polish: favicon, markdown rendering, steward inline login form, co-steward support
This commit is contained in:
parent
0bfdb2285e
commit
0755a83283
1 changed files with 50 additions and 7 deletions
|
|
@ -3028,6 +3028,8 @@ a{color:#c9b87e}a:hover{text-decoration:underline}
|
|||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>${esc(name)} — Agentify.Help</title>
|
||||
<meta name="description" content="${metaDesc}">
|
||||
<link rel="icon" href="${AH_FAVICON}">
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked@9/marked.min.js"></script>
|
||||
<style>
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
body{background:#07102a;color:#d4cfbb;font-family:"IBM Plex Sans","Inter",system-ui,sans-serif;min-height:100vh}
|
||||
|
|
@ -3046,7 +3048,18 @@ h1{font-size:1.6rem;color:#f0e8d0;margin-bottom:4px}
|
|||
.chat-box{width:100%;min-height:80px;background:#060e1c;border:1px solid #1a2e44;border-radius:6px;padding:12px;color:#d4cfbb;font-family:inherit;font-size:.88rem;resize:vertical}
|
||||
.btn{padding:9px 22px;background:#c9b87e;color:#07102a;border:none;border-radius:6px;font-weight:700;font-size:.88rem;cursor:pointer;margin-top:8px}
|
||||
.btn:hover{background:#d4c48e}
|
||||
.response{background:#060e1c;border:1px solid #1a2e44;border-radius:6px;padding:14px;margin-top:12px;font-size:.88rem;line-height:1.65;white-space:pre-wrap;display:none}
|
||||
.response{background:#060e1c;border:1px solid #1a2e44;border-radius:6px;padding:14px;margin-top:12px;font-size:.88rem;line-height:1.65;display:none}
|
||||
.response p{margin-bottom:.75em}.response p:last-child{margin-bottom:0}
|
||||
.response h1,.response h2,.response h3{color:#f0e8d0;margin:1em 0 .4em;font-size:1rem}
|
||||
.response h2{font-size:.95rem}.response h3{font-size:.9rem}
|
||||
.response ul,.response ol{padding-left:1.4em;margin-bottom:.75em}
|
||||
.response li{margin-bottom:.25em}
|
||||
.response strong{color:#f0e8d0}.response em{color:#c9b87e}
|
||||
.response code{background:#1a2e4a;padding:1px 5px;border-radius:3px;font-family:monospace;font-size:.83em;color:#86efac}
|
||||
.response pre{background:#1a2e4a;padding:10px 12px;border-radius:5px;overflow-x:auto;margin-bottom:.75em}
|
||||
.response pre code{background:none;padding:0;color:#86efac}
|
||||
.response blockquote{border-left:3px solid #c9b87e44;padding-left:12px;color:#8899bb;margin:.5em 0}
|
||||
.response hr{border:none;border-top:1px solid #1a2e44;margin:.75em 0}
|
||||
.scope-list{list-style:none;display:flex;flex-wrap:wrap;gap:4px}
|
||||
.scope-list li{background:#1a2e4a;color:#c9b87e;padding:2px 10px;border-radius:3px;font-family:monospace;font-size:.72rem}
|
||||
.refusal-list li{color:#f87171}
|
||||
|
|
@ -3184,9 +3197,12 @@ h1{font-size:1.6rem;color:#f0e8d0;margin-bottom:4px}
|
|||
|
||||
<div class="card" style="border-color:#1a2e4a44;margin-top:32px">
|
||||
<div class="card-title" style="color:#6b7f99">Steward access</div>
|
||||
<p style="font-size:.82rem;color:#6b7f99;margin-bottom:12px">Are you the steward for this expert? Access your corpus portal to review, expand, or update the corpus — or check the status of this agent.</p>
|
||||
${stewardDashToken ? `<a href="/stewardship/${esc(slug)}?token=${esc(stewardDashToken)}" style="display:inline-block;padding:7px 16px;background:#1a2e4a;color:#c9b87e;border:1px solid #c9b87e44;border-radius:6px;font-size:.82rem;font-weight:600;text-decoration:none">Open my corpus portal →</a>` : ""}
|
||||
<a href="/my-agents" style="display:inline-block;padding:7px 16px;background:#0d1f3c;color:#8899bb;border:1px solid #1a2e4a;border-radius:6px;font-size:.82rem;font-weight:600;text-decoration:none;margin-left:8px">Find my agents by email →</a>
|
||||
<p style="font-size:.82rem;color:#6b7f99;margin-bottom:14px">Are you the steward or a collaborator for this agent? Enter your email to receive a secure link to your corpus portal.</p>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
||||
<input type="email" id="steward-email" placeholder="your@email.com" style="flex:1;min-width:200px;background:#060e1c;border:1px solid #1a2e44;border-radius:5px;padding:8px 10px;color:#d4cfbb;font-family:inherit;font-size:.82rem;box-sizing:border-box">
|
||||
<button onclick="requestPortfolioAccess()" style="padding:8px 16px;background:#1a2e4a;color:#c9b87e;border:1px solid #c9b87e44;border-radius:5px;font-size:.82rem;font-weight:600;cursor:pointer;font-family:inherit;white-space:nowrap">Send my link →</button>
|
||||
</div>
|
||||
<div id="steward-access-result" style="margin-top:8px;font-size:.8rem;color:#6b7f99"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -3205,13 +3221,39 @@ async function ask() {
|
|||
});
|
||||
const d = await r.json();
|
||||
if (d.error === 'rate_limit') { resp.textContent = 'Rate limit reached — please try again in ' + (d.retry_after || 'a little while') + '.'; return; }
|
||||
resp.textContent = d.answer || d.response || d.error || JSON.stringify(d, null, 2);
|
||||
const text = d.answer || d.response || d.error || JSON.stringify(d, null, 2);
|
||||
resp.innerHTML = (typeof marked !== 'undefined') ? marked.parse(text) : text.replace(/&/g,'&').replace(/</g,'<').replace(/\n/g,'<br>');
|
||||
} catch(e) {
|
||||
resp.textContent = 'Error: ' + e.message;
|
||||
}
|
||||
}
|
||||
document.getElementById('q')?.addEventListener('keydown', e => { if (e.key === 'Enter' && e.metaKey) ask(); });
|
||||
|
||||
async function requestPortfolioAccess() {
|
||||
const emailEl = document.getElementById('steward-email');
|
||||
const result = document.getElementById('steward-access-result');
|
||||
const email = emailEl.value.trim();
|
||||
if (!email || !email.includes('@')) { result.textContent = 'Please enter a valid email address.'; result.style.color = '#f87171'; return; }
|
||||
result.textContent = 'Sending…'; result.style.color = '#6b7f99';
|
||||
try {
|
||||
const r = await fetch('/api/agentify-help/portfolio-access', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email })
|
||||
});
|
||||
const d = await r.json();
|
||||
if (d.ok && d.sent !== false) {
|
||||
result.textContent = '✓ Check your inbox — your steward link is on the way.';
|
||||
result.style.color = '#22c55e';
|
||||
} else {
|
||||
result.textContent = d.message || 'No steward account found for that email.';
|
||||
result.style.color = '#f87171';
|
||||
}
|
||||
} catch(e) {
|
||||
result.textContent = 'Error sending link. Please try again.';
|
||||
result.style.color = '#f87171';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSuggest() {
|
||||
const body = document.getElementById('suggest-body');
|
||||
const btn = document.getElementById('suggest-toggle-btn');
|
||||
|
|
@ -3279,7 +3321,8 @@ async function submitSuggestion() {
|
|||
try {
|
||||
const { rows } = await pool.query(
|
||||
`SELECT subject_slug, subject_name, status, dashboard_token FROM agentify_subject_registry
|
||||
WHERE LOWER(steward_email) = LOWER($1) AND status != 'verify_email'
|
||||
WHERE (LOWER(steward_email) = LOWER($1) OR LOWER($1) = ANY(COALESCE(co_steward_emails, '{}')))
|
||||
AND status != 'verify_email'
|
||||
ORDER BY created_at DESC`, [email]
|
||||
);
|
||||
if (rows.length === 0) {
|
||||
|
|
@ -3288,7 +3331,7 @@ async function submitSuggestion() {
|
|||
const token = makePortfolioToken(email);
|
||||
const portfolioUrl = `https://agentify.help/my-agents?token=${token}`;
|
||||
const expertList = rows.map((r: any) => {
|
||||
const dashLink = r.dashboard_token ? `<a href="https://agentify.help/stewardship/${r.subject_slug}?token=${r.dashboard_token}" style="color:#c9b87e;font-weight:600">Open corpus portal →</a>` : "";
|
||||
const dashLink = r.dashboard_token ? `<a href="https://agentify.help/steward/${r.subject_slug}?token=${r.dashboard_token}" style="color:#c9b87e;font-weight:600">Open corpus portal →</a>` : "";
|
||||
return `<li style="margin-bottom:14px"><strong>${r.subject_name}</strong> <span style="color:#888;font-size:.82rem">(${r.status})</span><br><a href="https://agentify.help/agents/${r.subject_slug}" style="color:#4499ff;font-size:.82rem">View public page</a>${dashLink ? " · " + dashLink : ""}</li>`;
|
||||
}).join("");
|
||||
await resend.emails.send({
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue