aimeat 1.30.2 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/locales/en.json +246 -1
- package/dist/locales/fi.json +246 -1
- package/dist/public/components/InboxLink.js +29 -0
- package/dist/public/components/offer-card-view.js +87 -0
- package/dist/public/css/views/companies.css +65 -0
- package/dist/public/css/views/inbox.css +153 -1
- package/dist/public/css/views/members.css +33 -0
- package/dist/public/css/views/my-company.css +315 -0
- package/dist/public/css/views/profile.css +22 -0
- package/dist/public/js/services/messages.js +21 -3
- package/dist/public/js/services/notebook.js +16 -6
- package/dist/public/llms-template.txt +7 -0
- package/dist/public/spa.html +14 -0
- package/dist/public/views/companies.js +190 -0
- package/dist/public/views/members.js +42 -0
- package/dist/public/views/my-company.js +664 -0
- package/dist/public/views/portfolio-themes.js +77 -0
- package/dist/public/views/profile/agents-tab.js +4 -1
- package/dist/public/views/profile/discover-tab.js +118 -0
- package/dist/public/views/profile/inbox-tab.js +663 -16
- package/dist/public/views/profile/landing-page.js +2 -1
- package/dist/public/views/profile/notebook-card.js +11 -3
- package/dist/public/views/profile/offers-tab.js +5 -24
- package/dist/public/views/profile/organisms/home.js +5 -3
- package/dist/public/views/profile/organisms/mindmap.js +14 -3
- package/dist/public/views/profile/organisms/workspace.js +5 -2
- package/dist/public/views/profile/organisms-tab.js +12 -4
- package/dist/public/views/profile.js +2 -0
- package/dist/src/cli/connect/mcp/tools/core.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/core.js +34 -0
- package/dist/src/cli/connect/mcp/tools/core.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/dm-messages.d.ts +1 -0
- package/dist/src/cli/connect/mcp/tools/dm-messages.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/dm-messages.js +23 -0
- package/dist/src/cli/connect/mcp/tools/dm-messages.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/organisms.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/organisms.js +31 -0
- package/dist/src/cli/connect/mcp/tools/organisms.js.map +1 -1
- package/dist/src/cli/connect/mcp/tools/workspaces.d.ts.map +1 -1
- package/dist/src/cli/connect/mcp/tools/workspaces.js +4 -0
- package/dist/src/cli/connect/mcp/tools/workspaces.js.map +1 -1
- package/dist/src/generated/api-types.d.ts +249 -0
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/generated/prisma-postgres/edge.js +6 -3
- package/dist/src/generated/prisma-postgres/index-browser.js +3 -0
- package/dist/src/generated/prisma-postgres/index.d.ts +112 -1
- package/dist/src/generated/prisma-postgres/index.js +6 -3
- package/dist/src/generated/prisma-postgres/package.json +1 -1
- package/dist/src/generated/prisma-postgres/schema.prisma +4 -0
- package/dist/src/generated/prisma-postgres/wasm.js +6 -3
- package/dist/src/mcp/annotations.d.ts.map +1 -1
- package/dist/src/mcp/annotations.js +2 -0
- package/dist/src/mcp/annotations.js.map +1 -1
- package/dist/src/mcp/catalog/definitions.d.ts.map +1 -1
- package/dist/src/mcp/catalog/definitions.js +33 -1
- package/dist/src/mcp/catalog/definitions.js.map +1 -1
- package/dist/src/mcp/catalog/scopes.d.ts.map +1 -1
- package/dist/src/mcp/catalog/scopes.js +1 -0
- package/dist/src/mcp/catalog/scopes.js.map +1 -1
- package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
- package/dist/src/mcp/catalog/surfaces.js +7 -4
- package/dist/src/mcp/catalog/surfaces.js.map +1 -1
- package/dist/src/mcp/core.d.ts.map +1 -1
- package/dist/src/mcp/core.js +49 -0
- package/dist/src/mcp/core.js.map +1 -1
- package/dist/src/mcp/dm-messages.d.ts +2 -0
- package/dist/src/mcp/dm-messages.d.ts.map +1 -1
- package/dist/src/mcp/dm-messages.js +45 -1
- package/dist/src/mcp/dm-messages.js.map +1 -1
- package/dist/src/models/message-schemas.d.ts +140 -2
- package/dist/src/models/message-schemas.d.ts.map +1 -1
- package/dist/src/models/message-schemas.js +60 -3
- package/dist/src/models/message-schemas.js.map +1 -1
- package/dist/src/routes/bootstrap.d.ts.map +1 -1
- package/dist/src/routes/bootstrap.js +3 -0
- package/dist/src/routes/bootstrap.js.map +1 -1
- package/dist/src/routes/discover.d.ts +22 -0
- package/dist/src/routes/discover.d.ts.map +1 -0
- package/dist/src/routes/discover.js +123 -0
- package/dist/src/routes/discover.js.map +1 -0
- package/dist/src/routes/federation-sync.d.ts.map +1 -1
- package/dist/src/routes/federation-sync.js +69 -2
- package/dist/src/routes/federation-sync.js.map +1 -1
- package/dist/src/routes/messages.d.ts.map +1 -1
- package/dist/src/routes/messages.js +102 -3
- package/dist/src/routes/messages.js.map +1 -1
- package/dist/src/routes/organisms.d.ts +3 -0
- package/dist/src/routes/organisms.d.ts.map +1 -1
- package/dist/src/routes/organisms.js +11 -32
- package/dist/src/routes/organisms.js.map +1 -1
- package/dist/src/routes/portal.d.ts.map +1 -1
- package/dist/src/routes/portal.js +3 -0
- package/dist/src/routes/portal.js.map +1 -1
- package/dist/src/routes/portfolio.d.ts.map +1 -1
- package/dist/src/routes/portfolio.js +30 -0
- package/dist/src/routes/portfolio.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +2 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/services/connect-tunnel.d.ts +3 -0
- package/dist/src/services/connect-tunnel.d.ts.map +1 -1
- package/dist/src/services/connect-tunnel.js +6 -0
- package/dist/src/services/connect-tunnel.js.map +1 -1
- package/dist/src/services/discovery/__tests__/discovery.test.d.ts +2 -0
- package/dist/src/services/discovery/__tests__/discovery.test.d.ts.map +1 -0
- package/dist/src/services/discovery/__tests__/discovery.test.js +178 -0
- package/dist/src/services/discovery/__tests__/discovery.test.js.map +1 -0
- package/dist/src/services/discovery/classify.d.ts +36 -0
- package/dist/src/services/discovery/classify.d.ts.map +1 -0
- package/dist/src/services/discovery/classify.js +61 -0
- package/dist/src/services/discovery/classify.js.map +1 -0
- package/dist/src/services/discovery/facets.d.ts +21 -0
- package/dist/src/services/discovery/facets.d.ts.map +1 -0
- package/dist/src/services/discovery/facets.js +0 -0
- package/dist/src/services/discovery/facets.js.map +1 -0
- package/dist/src/services/discovery/index.d.ts +22 -0
- package/dist/src/services/discovery/index.d.ts.map +1 -0
- package/dist/src/services/discovery/index.js +22 -0
- package/dist/src/services/discovery/index.js.map +1 -0
- package/dist/src/services/discovery/normalize.d.ts +25 -0
- package/dist/src/services/discovery/normalize.d.ts.map +1 -0
- package/dist/src/services/discovery/normalize.js +108 -0
- package/dist/src/services/discovery/normalize.js.map +1 -0
- package/dist/src/services/discovery/registry.d.ts +30 -0
- package/dist/src/services/discovery/registry.d.ts.map +1 -0
- package/dist/src/services/discovery/registry.js +31 -0
- package/dist/src/services/discovery/registry.js.map +1 -0
- package/dist/src/services/discovery/run.d.ts +23 -0
- package/dist/src/services/discovery/run.d.ts.map +1 -0
- package/dist/src/services/discovery/run.js +20 -0
- package/dist/src/services/discovery/run.js.map +1 -0
- package/dist/src/services/discovery/setup.d.ts +16 -0
- package/dist/src/services/discovery/setup.d.ts.map +1 -0
- package/dist/src/services/discovery/setup.js +12 -0
- package/dist/src/services/discovery/setup.js.map +1 -0
- package/dist/src/services/discovery/sources/memory-source.d.ts +24 -0
- package/dist/src/services/discovery/sources/memory-source.d.ts.map +1 -0
- package/dist/src/services/discovery/sources/memory-source.js +183 -0
- package/dist/src/services/discovery/sources/memory-source.js.map +1 -0
- package/dist/src/services/discovery/sources/table-sources.d.ts +27 -0
- package/dist/src/services/discovery/sources/table-sources.d.ts.map +1 -0
- package/dist/src/services/discovery/sources/table-sources.js +128 -0
- package/dist/src/services/discovery/sources/table-sources.js.map +1 -0
- package/dist/src/services/discovery/types.d.ts +117 -0
- package/dist/src/services/discovery/types.d.ts.map +1 -0
- package/dist/src/services/discovery/types.js +19 -0
- package/dist/src/services/discovery/types.js.map +1 -0
- package/dist/src/services/handbooks/agent.d.ts +1 -1
- package/dist/src/services/handbooks/agent.d.ts.map +1 -1
- package/dist/src/services/handbooks/agent.js +9 -3
- package/dist/src/services/handbooks/agent.js.map +1 -1
- package/dist/src/services/message-broadcast.d.ts +49 -0
- package/dist/src/services/message-broadcast.d.ts.map +1 -0
- package/dist/src/services/message-broadcast.js +116 -0
- package/dist/src/services/message-broadcast.js.map +1 -0
- package/dist/src/services/message-delivery.d.ts.map +1 -1
- package/dist/src/services/message-delivery.js +3 -0
- package/dist/src/services/message-delivery.js.map +1 -1
- package/dist/src/services/message-send.d.ts +9 -1
- package/dist/src/services/message-send.d.ts.map +1 -1
- package/dist/src/services/message-send.js +11 -5
- package/dist/src/services/message-send.js.map +1 -1
- package/dist/src/services/presence.d.ts +8 -0
- package/dist/src/services/presence.d.ts.map +1 -1
- package/dist/src/services/presence.js +38 -0
- package/dist/src/services/presence.js.map +1 -1
- package/dist/src/services/workspace-enrichment.d.ts +15 -5
- package/dist/src/services/workspace-enrichment.d.ts.map +1 -1
- package/dist/src/services/workspace-enrichment.js +52 -14
- package/dist/src/services/workspace-enrichment.js.map +1 -1
- package/dist/src/storage/interface.d.ts +49 -0
- package/dist/src/storage/interface.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.d.ts +1 -0
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.js +16 -0
- package/dist/src/storage/providers/mongodb/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/index.d.ts +1 -0
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +3 -0
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/direct-message.d.ts +3 -0
- package/dist/src/storage/providers/sqlite/repos/direct-message.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/direct-message.js +15 -2
- package/dist/src/storage/providers/sqlite/repos/direct-message.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +10 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/direct-message.repository.d.ts +3 -0
- package/dist/src/storage/repositories/direct-message.repository.d.ts.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.postgres.prisma +4 -0
- package/prisma/schema.prisma +4 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file portfolio-themes.js
|
|
3
|
+
* @description Ready-made company portfolio themes — generate a complete, self-contained public
|
|
4
|
+
* portfolio HTML page client-side from the company's data, so an admin can publish a portfolio
|
|
5
|
+
* WITHOUT the AI round-trip (the AI-prompt path stays for full custom designs). Each theme is a
|
|
6
|
+
* pure function `render(data) → htmlString`; the page is fully inline (no external deps) and
|
|
7
|
+
* responsive. User-supplied text is HTML-escaped (the result is served as a standalone public file).
|
|
8
|
+
* @structure esc() · buildPortfolioData() · THEMES = [{ id, name, render }]
|
|
9
|
+
* @usage imported by views/my-company.js (PortfolioPanel theme picker).
|
|
10
|
+
* @version-history
|
|
11
|
+
* v0.1.0 — 2026-06-23 — initial: minimal, midnight, corporate themes
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Escape for safe interpolation into the generated HTML document. */
|
|
15
|
+
export function esc(s) {
|
|
16
|
+
return String(s ?? '')
|
|
17
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
18
|
+
.replace(/"/g, '"').replace(/'/g, ''');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Build the theme input from the selected company + offerings + the builder's include choices. */
|
|
22
|
+
export function buildPortfolioData(org, offerings, choices) {
|
|
23
|
+
const origin = (typeof window !== 'undefined' && window.location.origin) || '';
|
|
24
|
+
return {
|
|
25
|
+
name: org.name || '',
|
|
26
|
+
businessId: choices.includeInfo ? (org.businessId || '') : '',
|
|
27
|
+
description: choices.includeInfo ? (org.description || '') : '',
|
|
28
|
+
logo: (choices.useLogo && org.logo) ? (origin + org.logo) : '',
|
|
29
|
+
offerings: choices.includeOfferings
|
|
30
|
+
? (offerings || []).map(o => ({ title: o.offer?.title || '', price: o.offer?.price?.morsels || 0, agent: o.agentName || '', ask: o.offer?.ask || '' }))
|
|
31
|
+
: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const priceLabel = (p) => p > 0 ? `${p} morsels` : 'Contact for pricing';
|
|
36
|
+
|
|
37
|
+
const doc = (title, css, body) =>
|
|
38
|
+
`<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<meta name="viewport" content="width=device-width,initial-scale=1">\n<title>${esc(title)}</title>\n<style>${css}</style>\n</head>\n<body>\n${body}\n</body>\n</html>\n`;
|
|
39
|
+
|
|
40
|
+
// ── Theme: Minimal (light, clean, editorial) ─────────────────────────────────────────────────────
|
|
41
|
+
function minimal(d) {
|
|
42
|
+
const css = `*{box-sizing:border-box}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:#1a1a1a;background:#fff;line-height:1.65}.wrap{max-width:760px;margin:0 auto;padding:72px 24px}header{display:flex;align-items:center;gap:20px}.logo{width:72px;height:72px;border-radius:14px;object-fit:cover;border:1px solid #eee}h1{font-size:2.3rem;margin:0;letter-spacing:-.02em}.yt{color:#777;font-size:.9rem;margin-top:6px}.about{font-size:1.15rem;color:#333;margin:28px 0 56px;max-width:60ch}h2{font-size:1.25rem;border-bottom:2px solid #E8564A;display:inline-block;padding-bottom:4px;margin:0 0 18px}.svc{border:1px solid #ececec;border-radius:14px;padding:18px 22px;margin:14px 0;transition:border-color .15s}.svc h3{margin:0 0 6px;font-size:1.05rem}.svc p{margin:0;color:#666;font-size:.95rem}.price{color:#E8564A;font-weight:700;white-space:nowrap}.row{display:flex;justify-content:space-between;align-items:baseline;gap:12px}footer{margin-top:72px;color:#999;font-size:.85rem;border-top:1px solid #eee;padding-top:20px}a{color:#E8564A}`;
|
|
43
|
+
const logo = d.logo ? `<img class="logo" src="${esc(d.logo)}" alt="${esc(d.name)} logo">` : '';
|
|
44
|
+
const yt = d.businessId ? `<div class="yt">Business ID ${esc(d.businessId)}</div>` : '';
|
|
45
|
+
const about = d.description ? `<p class="about">${esc(d.description)}</p>` : '';
|
|
46
|
+
const services = d.offerings.length ? `<section><h2>Services</h2>${d.offerings.map(o => `<div class="svc"><div class="row"><h3>${esc(o.title)}</h3><span class="price">${esc(priceLabel(o.price))}</span></div>${o.ask ? `<p>${esc(o.ask)}</p>` : ''}</div>`).join('')}</section>` : '';
|
|
47
|
+
const body = `<div class="wrap"><header>${logo}<div><h1>${esc(d.name)}</h1>${yt}</div></header>${about}${services}<footer>Powered by AIMEAT</footer></div>`;
|
|
48
|
+
return doc(d.name, css, body);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ── Theme: Midnight (dark, bold, accent gradient) ────────────────────────────────────────────────
|
|
52
|
+
function midnight(d) {
|
|
53
|
+
const css = `*{box-sizing:border-box}body{margin:0;font-family:"Segoe UI",system-ui,-apple-system,Roboto,sans-serif;color:#e8e8ea;background:#0d0d12;line-height:1.6}.hero{padding:88px 24px 56px;text-align:center;background:radial-gradient(120% 120% at 50% 0%,#1c1530 0%,#0d0d12 60%)}.logo{width:88px;height:88px;border-radius:18px;object-fit:cover;border:1px solid #2a2a3a;margin-bottom:20px}h1{font-size:2.8rem;margin:0;background:linear-gradient(90deg,#fff,#b59cff);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:-.02em}.yt{color:#8a8aa0;font-size:.9rem;margin-top:10px}.about{max-width:62ch;margin:22px auto 0;color:#c4c4d4;font-size:1.12rem}.wrap{max-width:880px;margin:0 auto;padding:8px 24px 80px}h2{font-size:1.4rem;margin:48px 0 20px;color:#fff}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:16px}.svc{background:#15151f;border:1px solid #26263a;border-radius:16px;padding:20px}.svc h3{margin:0 0 8px;color:#fff;font-size:1.05rem}.svc p{margin:0 0 12px;color:#9a9ab0;font-size:.92rem}.price{display:inline-block;background:#2a1f44;color:#c4a8ff;font-weight:700;border-radius:999px;padding:4px 12px;font-size:.85rem}footer{text-align:center;color:#6a6a80;font-size:.85rem;padding:32px 0}`;
|
|
54
|
+
const logo = d.logo ? `<img class="logo" src="${esc(d.logo)}" alt="${esc(d.name)} logo">` : '';
|
|
55
|
+
const yt = d.businessId ? `<div class="yt">Business ID ${esc(d.businessId)}</div>` : '';
|
|
56
|
+
const about = d.description ? `<p class="about">${esc(d.description)}</p>` : '';
|
|
57
|
+
const services = d.offerings.length ? `<div class="wrap"><h2>Services</h2><div class="grid">${d.offerings.map(o => `<div class="svc"><h3>${esc(o.title)}</h3>${o.ask ? `<p>${esc(o.ask)}</p>` : ''}<span class="price">${esc(priceLabel(o.price))}</span></div>`).join('')}</div></div>` : '';
|
|
58
|
+
const body = `<div class="hero">${logo}<h1>${esc(d.name)}</h1>${yt}${about}</div>${services}<footer>Powered by AIMEAT</footer>`;
|
|
59
|
+
return doc(d.name, css, body);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ── Theme: Corporate (professional, header bar, two-tone) ─────────────────────────────────────────
|
|
63
|
+
function corporate(d) {
|
|
64
|
+
const css = `*{box-sizing:border-box}body{margin:0;font-family:Georgia,"Times New Roman",serif;color:#222;background:#f7f6f3;line-height:1.65}.bar{background:#14213d;color:#fff;padding:22px 24px}.bar .inner{max-width:920px;margin:0 auto;display:flex;align-items:center;gap:16px}.logo{width:56px;height:56px;border-radius:8px;object-fit:cover;background:#fff}.bar h1{font-size:1.6rem;margin:0;font-family:Georgia,serif}.bar .yt{color:#aeb6c8;font-size:.82rem;margin-top:2px}.wrap{max-width:920px;margin:0 auto;padding:48px 24px 72px}.about{font-size:1.15rem;color:#333;border-left:4px solid #fca311;padding-left:18px;margin:0 0 48px;max-width:62ch}h2{font-size:1.3rem;color:#14213d;margin:0 0 20px;font-family:Georgia,serif}table{width:100%;border-collapse:collapse;background:#fff;border:1px solid #e3e0d8}td,th{text-align:left;padding:14px 18px;border-bottom:1px solid #eee;font-family:-apple-system,Segoe UI,sans-serif}th{background:#14213d;color:#fff;font-weight:600}.price{color:#14213d;font-weight:700;white-space:nowrap;font-family:-apple-system,Segoe UI,sans-serif}.ask{color:#777;font-size:.9rem;font-family:-apple-system,Segoe UI,sans-serif}footer{max-width:920px;margin:0 auto;padding:24px;color:#999;font-size:.85rem;font-family:-apple-system,Segoe UI,sans-serif}`;
|
|
65
|
+
const logo = d.logo ? `<img class="logo" src="${esc(d.logo)}" alt="${esc(d.name)} logo">` : '';
|
|
66
|
+
const yt = d.businessId ? `<div class="yt">Business ID ${esc(d.businessId)}</div>` : '';
|
|
67
|
+
const about = d.description ? `<p class="about">${esc(d.description)}</p>` : '';
|
|
68
|
+
const services = d.offerings.length ? `<section><h2>Services & Pricing</h2><table><thead><tr><th>Service</th><th>Price</th></tr></thead><tbody>${d.offerings.map(o => `<tr><td><strong>${esc(o.title)}</strong>${o.ask ? `<div class="ask">${esc(o.ask)}</div>` : ''}</td><td class="price">${esc(priceLabel(o.price))}</td></tr>`).join('')}</tbody></table></section>` : '';
|
|
69
|
+
const body = `<div class="bar"><div class="inner">${logo}<div><h1>${esc(d.name)}</h1>${yt}</div></div></div><div class="wrap">${about}${services}</div><footer>Powered by AIMEAT</footer>`;
|
|
70
|
+
return doc(d.name, css, body);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const THEMES = [
|
|
74
|
+
{ id: 'minimal', name: 'Minimal', render: minimal },
|
|
75
|
+
{ id: 'midnight', name: 'Midnight', render: midnight },
|
|
76
|
+
{ id: 'corporate', name: 'Corporate', render: corporate },
|
|
77
|
+
];
|
|
@@ -63,6 +63,7 @@ const html = htm.bind(h);
|
|
|
63
63
|
import { t } from '/js/i18n.js';
|
|
64
64
|
import { escHtml, timeAgo } from '/js/utils.js';
|
|
65
65
|
import { CopyButton } from '/components/CopyButton.js';
|
|
66
|
+
import { InboxLink } from '/components/InboxLink.js';
|
|
66
67
|
import { Spinner } from './shared.js';
|
|
67
68
|
import { apiGet, apiPost, apiPatch } from '/js/api.js';
|
|
68
69
|
import { listAgents, updateAgentScopes, deleteAgent, getAgentGroups, saveAgentGroups } from '/js/services/agents.js';
|
|
@@ -1401,7 +1402,9 @@ function ScopesModal({ agent, session, onSave, onCancel }) {
|
|
|
1401
1402
|
|
|
1402
1403
|
return html`
|
|
1403
1404
|
<${Modal} open=${true} onClose=${onCancel} className="scope-modal" title=${`${t('profile.agents.scopeUi.scopeProfile')}: ${agent.display_name || agent.name}`}>
|
|
1404
|
-
<div class="scope-agent-info">${escHtml(agent.gaii || '')}
|
|
1405
|
+
<div class="scope-agent-info">${escHtml(agent.gaii || '')}
|
|
1406
|
+
${agent.gaii ? html`<${InboxLink} to=${agent.gaii} title=${t('inbox.messageThis')} className="scope-agent-msg">✉️</${InboxLink}>` : null}
|
|
1407
|
+
</div>
|
|
1405
1408
|
|
|
1406
1409
|
${isReadOnly ? html`
|
|
1407
1410
|
<p class="text-caption mb-1">${t('profile.agents.scopeUi.readOnlyView')}</p>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file discover-tab.js
|
|
3
|
+
* @description Profile tab for the master directory — a faceted browse over GET /v1/discover. One
|
|
4
|
+
* surface to find anything on the node across every domain (capabilities, workflows, knowledge,
|
|
5
|
+
* decisions, research, material, companies + offerings, documents, apps, memory). Scope toggle
|
|
6
|
+
* (own / public / shared), free-text query, clickable type facets, and a ranked result list.
|
|
7
|
+
* Reads only via cortex-free session.fetch; re-fetches on aimeat-live-update.
|
|
8
|
+
* @structure DiscoverTab() — scope + query + type-facet state → /v1/discover → result list
|
|
9
|
+
* @usage registered in profile.js TABS as id 'discover'
|
|
10
|
+
* @version-history
|
|
11
|
+
* v0.1.0 — 2026-06-23 — Phase 4: human-facing master-directory browse (design doc 2026-06-23).
|
|
12
|
+
*/
|
|
13
|
+
import { h } from 'preact';
|
|
14
|
+
import { useState, useEffect, useCallback } from 'preact/hooks';
|
|
15
|
+
import htm from 'htm';
|
|
16
|
+
const html = htm.bind(h);
|
|
17
|
+
import { t } from '/js/i18n.js';
|
|
18
|
+
import { escHtml } from '/js/utils.js';
|
|
19
|
+
import { Spinner } from './shared.js';
|
|
20
|
+
import { getSession } from '/js/services/auth.js';
|
|
21
|
+
|
|
22
|
+
const SCOPES = ['own', 'public', 'shared'];
|
|
23
|
+
const TYPE_ICONS = {
|
|
24
|
+
capability: '\u{1F9E9}', workflow: '\u{2699}\u{FE0F}', knowledge: '\u{1F4DA}', decision: '\u{2696}\u{FE0F}',
|
|
25
|
+
research: '\u{1F52C}', material: '\u{1F4E6}', company: '\u{1F3E2}', offering: '\u{1F3F7}\u{FE0F}',
|
|
26
|
+
document: '\u{1F4C4}', organism: '\u{1F9EC}', app: '\u{1F4F1}', memory: '\u{1F9E0}',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default function DiscoverTab() {
|
|
30
|
+
const [scope, setScope] = useState('own');
|
|
31
|
+
const [query, setQuery] = useState('');
|
|
32
|
+
const [typeFilter, setTypeFilter] = useState('');
|
|
33
|
+
const [data, setData] = useState({ entries: [], total: 0, facets: { types: [], tags: [] } });
|
|
34
|
+
const [loading, setLoading] = useState(true);
|
|
35
|
+
|
|
36
|
+
const load = useCallback(async () => {
|
|
37
|
+
const session = getSession();
|
|
38
|
+
if (!session) return;
|
|
39
|
+
setLoading(true);
|
|
40
|
+
const params = new URLSearchParams({ scope, per_page: '50' });
|
|
41
|
+
if (query.trim()) params.set('q', query.trim());
|
|
42
|
+
if (typeFilter) params.set('type', typeFilter);
|
|
43
|
+
try {
|
|
44
|
+
const res = await session.fetch(`/v1/discover?${params.toString()}`);
|
|
45
|
+
setData(res.data || { entries: [], total: 0, facets: { types: [], tags: [] } });
|
|
46
|
+
} catch {
|
|
47
|
+
setData({ entries: [], total: 0, facets: { types: [], tags: [] } });
|
|
48
|
+
}
|
|
49
|
+
setLoading(false);
|
|
50
|
+
}, [scope, query, typeFilter]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => { load(); }, [load]);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const handler = () => load();
|
|
55
|
+
window.addEventListener('aimeat-live-update', handler);
|
|
56
|
+
return () => window.removeEventListener('aimeat-live-update', handler);
|
|
57
|
+
}, [load]);
|
|
58
|
+
|
|
59
|
+
const facetTypes = data.facets?.types || [];
|
|
60
|
+
|
|
61
|
+
return html`
|
|
62
|
+
<div class="pf-section">
|
|
63
|
+
<div class="section-title">${t('discover.title')}</div>
|
|
64
|
+
<div class="section-desc">${t('discover.desc')}</div>
|
|
65
|
+
|
|
66
|
+
<div class="dsc-controls">
|
|
67
|
+
<div class="dsc-scope">
|
|
68
|
+
${SCOPES.map(s => html`
|
|
69
|
+
<button
|
|
70
|
+
class=${'btn-ghost dsc-scope-btn' + (scope === s ? ' dsc-scope-active' : '')}
|
|
71
|
+
onClick=${() => setScope(s)}
|
|
72
|
+
>${t('discover.scope.' + s)}</button>
|
|
73
|
+
`)}
|
|
74
|
+
</div>
|
|
75
|
+
<input
|
|
76
|
+
type="text"
|
|
77
|
+
class="dsc-search"
|
|
78
|
+
placeholder="${t('discover.searchPlaceholder')}"
|
|
79
|
+
value=${query}
|
|
80
|
+
onInput=${e => setQuery(e.target.value)}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<!-- Type facets (map mode) -->
|
|
85
|
+
<div class="dsc-facets">
|
|
86
|
+
<button
|
|
87
|
+
class=${'dsc-facet' + (typeFilter === '' ? ' dsc-facet-active' : '')}
|
|
88
|
+
onClick=${() => setTypeFilter('')}
|
|
89
|
+
>${t('discover.allTypes')} (${data.total})</button>
|
|
90
|
+
${facetTypes.map(f => html`
|
|
91
|
+
<button
|
|
92
|
+
class=${'dsc-facet' + (typeFilter === f.value ? ' dsc-facet-active' : '')}
|
|
93
|
+
onClick=${() => setTypeFilter(typeFilter === f.value ? '' : f.value)}
|
|
94
|
+
>${TYPE_ICONS[f.value] || ''} ${t('discover.type.' + f.value) || f.value} (${f.count})</button>
|
|
95
|
+
`)}
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
${loading ? html`<${Spinner} />` : html`
|
|
99
|
+
${!data.entries.length
|
|
100
|
+
? html`<div class="pf-empty">${t('discover.empty')}</div>`
|
|
101
|
+
: data.entries.map(e => html`
|
|
102
|
+
<a class="dsc-item" href=${e.href || '#'} target="_blank" rel="noopener">
|
|
103
|
+
<div class="dsc-item-head">
|
|
104
|
+
<span class="dsc-type-badge">${TYPE_ICONS[e.type] || ''} ${t('discover.type.' + e.type) || e.type}</span>
|
|
105
|
+
<strong class="dsc-item-title">${escHtml(e.title || e.id)}</strong>
|
|
106
|
+
${e.segment ? html`<span class="dsc-segment">${escHtml(e.segment)}</span>` : ''}
|
|
107
|
+
</div>
|
|
108
|
+
${e.description ? html`<div class="dsc-item-desc">${escHtml(e.description)}</div>` : ''}
|
|
109
|
+
<div class="dsc-item-meta">
|
|
110
|
+
${(e.tags || []).slice(0, 6).map(tag => html`<span class="dsc-tag">${escHtml(tag)}</span>`)}
|
|
111
|
+
<span class="dsc-owner">${escHtml(e.owner || '')}</span>
|
|
112
|
+
</div>
|
|
113
|
+
</a>
|
|
114
|
+
`)}
|
|
115
|
+
`}
|
|
116
|
+
</div>
|
|
117
|
+
`;
|
|
118
|
+
}
|