aimeat 1.31.0 → 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 +196 -2
- package/dist/locales/fi.json +196 -2
- package/dist/public/components/InboxLink.js +29 -0
- package/dist/public/css/views/companies.css +65 -0
- package/dist/public/css/views/inbox.css +100 -1
- package/dist/public/css/views/members.css +33 -0
- package/dist/public/css/views/my-company.css +52 -0
- package/dist/public/css/views/profile.css +22 -0
- package/dist/public/js/services/messages.js +16 -0
- package/dist/public/js/services/notebook.js +16 -6
- package/dist/public/llms-template.txt +7 -0
- package/dist/public/spa.html +8 -0
- package/dist/public/views/companies.js +190 -0
- package/dist/public/views/members.js +42 -0
- package/dist/public/views/my-company.js +440 -47
- 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 +506 -12
- 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/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 +211 -0
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/generated/prisma-postgres/edge.js +5 -3
- package/dist/src/generated/prisma-postgres/index-browser.js +2 -0
- package/dist/src/generated/prisma-postgres/index.d.ts +89 -1
- package/dist/src/generated/prisma-postgres/index.js +5 -3
- package/dist/src/generated/prisma-postgres/package.json +1 -1
- package/dist/src/generated/prisma-postgres/schema.prisma +3 -0
- package/dist/src/generated/prisma-postgres/wasm.js +5 -3
- package/dist/src/mcp/annotations.d.ts.map +1 -1
- package/dist/src/mcp/annotations.js +1 -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 +18 -0
- package/dist/src/mcp/catalog/definitions.js.map +1 -1
- package/dist/src/mcp/catalog/surfaces.d.ts.map +1 -1
- package/dist/src/mcp/catalog/surfaces.js +6 -3
- 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/models/message-schemas.d.ts +56 -0
- package/dist/src/models/message-schemas.d.ts.map +1 -1
- package/dist/src/models/message-schemas.js +13 -0
- 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 +67 -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 +86 -1
- 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 +2 -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 +2 -0
- package/dist/src/services/message-delivery.js.map +1 -1
- package/dist/src/services/message-send.d.ts +6 -0
- package/dist/src/services/message-send.d.ts.map +1 -1
- package/dist/src/services/message-send.js +7 -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 +5 -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 +13 -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 +13 -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 +5 -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 +3 -0
- package/prisma/schema.prisma +3 -0
|
@@ -163,7 +163,9 @@
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/* ── Right pane ── */
|
|
166
|
-
|
|
166
|
+
/* min-height:0 lets this grid item respect the fixed .inbox-body height instead of growing to fit a tall
|
|
167
|
+
thread (grid/flex items default to min-height:auto = content size). */
|
|
168
|
+
.inbox-panel { display: flex; flex-direction: column; min-width: 0; min-height: 0; height: 100%; }
|
|
167
169
|
.inbox-panel--empty { align-items: center; justify-content: center; }
|
|
168
170
|
|
|
169
171
|
.inbox-empty { text-align: center; color: var(--text-dim); display: flex; flex-direction: column; align-items: center; gap: 8px; }
|
|
@@ -182,6 +184,7 @@
|
|
|
182
184
|
/* Message scroll area. */
|
|
183
185
|
.inbox-msgs {
|
|
184
186
|
flex: 1;
|
|
187
|
+
min-height: 0; /* required so the flex child scrolls instead of growing past the composer */
|
|
185
188
|
overflow-y: auto;
|
|
186
189
|
padding: 16px;
|
|
187
190
|
display: flex;
|
|
@@ -476,3 +479,99 @@
|
|
|
476
479
|
/* Read-only summary once the question has been answered. */
|
|
477
480
|
.inbox-iform--done { gap: 8px; }
|
|
478
481
|
.inbox-iform-answered { font-size: 13px; color: var(--text-dim); }
|
|
482
|
+
|
|
483
|
+
/* ── Broadcast / send-to-many compose ── */
|
|
484
|
+
.inbox-bc-mode { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
485
|
+
.inbox-bc-modeopt {
|
|
486
|
+
display: flex; align-items: center; gap: 6px;
|
|
487
|
+
padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
|
|
488
|
+
background: var(--card-bg); cursor: pointer; font-size: 13px;
|
|
489
|
+
}
|
|
490
|
+
.inbox-bc-modeopt input { accent-color: var(--accent); }
|
|
491
|
+
.inbox-bc-modeopt--on { border-color: var(--accent); background: var(--accent-subtle); }
|
|
492
|
+
.inbox-bc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
493
|
+
.inbox-bc-chip {
|
|
494
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
495
|
+
padding: 3px 6px 3px 10px; border: 1px solid var(--accent-border); border-radius: var(--radius-full);
|
|
496
|
+
background: var(--accent-subtle); font-size: 12px; max-width: 100%;
|
|
497
|
+
}
|
|
498
|
+
.inbox-bc-chip-x {
|
|
499
|
+
border: none; background: transparent; color: var(--text-dim); cursor: pointer;
|
|
500
|
+
font-size: 12px; line-height: 1; padding: 2px 4px; border-radius: var(--radius-full);
|
|
501
|
+
}
|
|
502
|
+
.inbox-bc-chip-x:hover { color: var(--danger); background: var(--card-bg); }
|
|
503
|
+
.inbox-bc-add { display: flex; gap: 8px; }
|
|
504
|
+
.inbox-bc-add .inbox-input { flex: 1; }
|
|
505
|
+
/* Operator audience select (all node / all federation users). */
|
|
506
|
+
.inbox-bc-audience--on { border-color: var(--accent); background: var(--accent-subtle); }
|
|
507
|
+
|
|
508
|
+
/* Announcement note shown in place of the reply composer (read-only thread). */
|
|
509
|
+
.inbox-announce-note {
|
|
510
|
+
border-top: 1px solid var(--border-subtle);
|
|
511
|
+
padding: 12px 16px; color: var(--text-dim); font-size: 13px; text-align: center;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/* ── Poll builder (compose a poll broadcast) ── */
|
|
515
|
+
.inbox-poll-builder { display: flex; flex-direction: column; gap: 12px; }
|
|
516
|
+
.inbox-poll-q {
|
|
517
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
518
|
+
border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px; background: var(--card-bg);
|
|
519
|
+
}
|
|
520
|
+
.inbox-poll-q-head { display: flex; align-items: center; gap: 8px; }
|
|
521
|
+
.inbox-poll-q-head .inbox-input { flex: 1; }
|
|
522
|
+
.inbox-poll-q-n { font-weight: 600; color: var(--text-dim); }
|
|
523
|
+
.inbox-poll-opts { display: flex; flex-direction: column; gap: 6px; padding-left: 12px; }
|
|
524
|
+
.inbox-poll-opt { display: flex; align-items: center; gap: 6px; }
|
|
525
|
+
.inbox-poll-opt .inbox-input { flex: 1; }
|
|
526
|
+
.inbox-poll-flags { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--text-dim); }
|
|
527
|
+
.inbox-poll-flags label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
|
|
528
|
+
.inbox-poll-flags input { accent-color: var(--accent); }
|
|
529
|
+
|
|
530
|
+
/* ── Broadcast / poll results ── */
|
|
531
|
+
.inbox-results-summary { font-size: 13px; color: var(--text-dim); padding-bottom: 8px; border-bottom: 1px solid var(--border-subtle); }
|
|
532
|
+
.inbox-results-q { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; }
|
|
533
|
+
.inbox-results-prompt { font-weight: 600; font-size: 14px; }
|
|
534
|
+
.inbox-results-bar { display: flex; flex-direction: column; gap: 3px; }
|
|
535
|
+
.inbox-results-bar-label { display: flex; justify-content: space-between; font-size: 13px; }
|
|
536
|
+
.inbox-results-bar-track { height: 8px; border-radius: var(--radius-full); background: var(--card-bg-alt); overflow: hidden; }
|
|
537
|
+
.inbox-results-bar-fill { height: 100%; width: var(--w, 0%); background: var(--accent); border-radius: var(--radius-full); transition: width 0.3s; }
|
|
538
|
+
.inbox-results-others { font-size: 12px; color: var(--text-dim); }
|
|
539
|
+
.inbox-results-reclist { display: flex; flex-direction: column; gap: 4px; padding-top: 8px; }
|
|
540
|
+
.inbox-results-rec { display: flex; justify-content: space-between; font-size: 13px; color: var(--text-dim); }
|
|
541
|
+
|
|
542
|
+
/* ── Agent capabilities in chat: command chips + fill-in form (Phase A) ── */
|
|
543
|
+
.inbox-cmdbar {
|
|
544
|
+
display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
|
|
545
|
+
padding: 8px 12px; border-top: 1px solid var(--border-subtle);
|
|
546
|
+
}
|
|
547
|
+
.inbox-cmdbar-label { font-size: 12px; color: var(--text-dim); margin-right: 2px; }
|
|
548
|
+
.inbox-cmd-chip {
|
|
549
|
+
border: 1px solid var(--accent-border); background: var(--accent-subtle); color: var(--text);
|
|
550
|
+
font-size: 12px; padding: 4px 10px; border-radius: var(--radius-full); cursor: pointer;
|
|
551
|
+
}
|
|
552
|
+
.inbox-cmd-chip:hover { border-color: var(--accent); }
|
|
553
|
+
.inbox-cmdfill {
|
|
554
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
555
|
+
padding: 10px 12px; border-top: 1px solid var(--border-subtle); background: var(--card-bg-alt);
|
|
556
|
+
}
|
|
557
|
+
.inbox-cmdfill-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 13px; }
|
|
558
|
+
.inbox-cmdfill-desc { font-size: 12px; color: var(--text-dim); }
|
|
559
|
+
.inbox-cmdfill-field { display: flex; flex-direction: column; gap: 3px; }
|
|
560
|
+
.inbox-cmdfill-pname { font-size: 12px; color: var(--text-dim); }
|
|
561
|
+
.inbox-cmdfill-go { align-self: flex-start; }
|
|
562
|
+
|
|
563
|
+
/* ── Agent schedule panel (Phase B — own agents only) ── */
|
|
564
|
+
.inbox-sched-btn { margin-left: auto; }
|
|
565
|
+
.inbox-sched-btn--on { background: var(--accent-subtle); border-color: var(--accent); }
|
|
566
|
+
.inbox-sched {
|
|
567
|
+
display: flex; flex-direction: column; gap: 10px;
|
|
568
|
+
padding: 10px 12px; border-top: 1px solid var(--border-subtle); background: var(--card-bg-alt);
|
|
569
|
+
}
|
|
570
|
+
.inbox-sched-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 13px; }
|
|
571
|
+
.inbox-sched-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
|
|
572
|
+
.inbox-sched-item { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
|
|
573
|
+
.inbox-sched-name { color: var(--text); }
|
|
574
|
+
.inbox-sched-cron { color: var(--text-dim); font-family: var(--font-mono, monospace); font-size: 12px; }
|
|
575
|
+
.inbox-sched-new { display: flex; flex-direction: column; gap: 6px; }
|
|
576
|
+
.inbox-sched-new .btn-primary { align-self: flex-start; }
|
|
577
|
+
.inbox-sched-desc { min-height: 38px; resize: vertical; }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file members.css
|
|
3
|
+
* @description Node members showcase grid (published-portfolio owners). Card grid with avatar + name +
|
|
4
|
+
* bio, linking to each member's portfolio.
|
|
5
|
+
* @version-history
|
|
6
|
+
* v1.0.0 — 2026-06-23 — Initial.
|
|
7
|
+
*/
|
|
8
|
+
.mbr { max-width: 1100px; margin: 0 auto; padding: 24px 16px; }
|
|
9
|
+
.mbr-title { font-size: 1.6rem; margin: 0 0 6px; }
|
|
10
|
+
.mbr-desc { color: var(--text-dim); margin: 0 0 24px; }
|
|
11
|
+
.mbr-empty { color: var(--text-dim); text-align: center; padding: 40px; }
|
|
12
|
+
.mbr-grid {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
15
|
+
gap: 16px;
|
|
16
|
+
}
|
|
17
|
+
.mbr-card {
|
|
18
|
+
display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
|
|
19
|
+
padding: 20px 14px; border: 1px solid var(--card-border, var(--border)); border-radius: var(--radius-md, 12px);
|
|
20
|
+
background: var(--card-bg); text-decoration: none; color: inherit;
|
|
21
|
+
transition: border-color 0.12s, transform 0.12s;
|
|
22
|
+
}
|
|
23
|
+
.mbr-card:hover { border-color: var(--accent); transform: translateY(-2px); }
|
|
24
|
+
.mbr-avatar {
|
|
25
|
+
width: 64px; height: 64px; border-radius: var(--radius-full, 50%);
|
|
26
|
+
display: flex; align-items: center; justify-content: center;
|
|
27
|
+
font-size: 32px; background: var(--accent-subtle); border: 1px solid var(--accent-border);
|
|
28
|
+
}
|
|
29
|
+
.mbr-name { font-weight: 600; }
|
|
30
|
+
.mbr-bio {
|
|
31
|
+
font-size: 13px; color: var(--text-dim);
|
|
32
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
33
|
+
}
|
|
@@ -217,11 +217,62 @@
|
|
|
217
217
|
border-radius: var(--radius-sm); padding: 0.5rem 0.7rem;
|
|
218
218
|
}
|
|
219
219
|
.mc-listed { color: var(--success); font-size: 0.8rem; font-weight: 600; }
|
|
220
|
+
.mc-pick-agents { display: flex; flex-direction: column; gap: 0.75rem; }
|
|
221
|
+
.mc-pick-agent { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.6rem; background: var(--bg-elevated); }
|
|
222
|
+
.mc-pick-agent-name { font-weight: 600; color: var(--text); font-size: 0.85rem; margin-bottom: 0.35rem; }
|
|
223
|
+
.mc-pick-none { color: var(--text-muted); }
|
|
224
|
+
|
|
225
|
+
.mc-manage { border: 1px dashed var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.6rem; margin: 0.4rem 0 0.6rem; }
|
|
226
|
+
.mc-manage-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
|
|
227
|
+
.mc-config { display: flex; flex-direction: column; gap: 0.2rem; color: var(--text-dim); font-size: 0.85rem; }
|
|
228
|
+
.mc-config b { color: var(--text); }
|
|
229
|
+
.mc-manage-row { align-items: center; gap: 0.4rem; }
|
|
230
|
+
.mc-price-input { width: 5rem; }
|
|
231
|
+
.mc-saved { color: var(--success); }
|
|
232
|
+
.mc-warn { color: var(--text-muted); }
|
|
233
|
+
.mc-remove { color: var(--danger); }
|
|
220
234
|
|
|
221
235
|
.mc-cat-item { list-style: none; margin-bottom: 0.6rem; }
|
|
222
236
|
.of-card-head--static { cursor: default; }
|
|
223
237
|
.mc-not-callable { color: var(--text-muted); font-size: 0.75rem; margin: 0.2rem 0; }
|
|
224
238
|
|
|
239
|
+
.mc-subtabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--border); margin: 0.5rem 0 1rem; flex-wrap: wrap; }
|
|
240
|
+
.mc-subtab {
|
|
241
|
+
background: transparent; border: none; border-bottom: 2px solid transparent;
|
|
242
|
+
padding: 0.4rem 0.7rem; cursor: pointer; color: var(--text-dim); font-size: 0.9rem; font-weight: 600;
|
|
243
|
+
}
|
|
244
|
+
.mc-subtab:hover { color: var(--text); }
|
|
245
|
+
.mc-subtab.active { color: var(--accent-bright); border-bottom-color: var(--accent); }
|
|
246
|
+
.mc-role-chip { margin-left: auto; align-self: center; font-size: 0.72rem; font-weight: 600; color: var(--text-dim); background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-full); padding: 0.1rem 0.55rem; }
|
|
247
|
+
|
|
248
|
+
.mc-cust-list, .mc-member-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
|
|
249
|
+
.mc-cust { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.6rem 0.75rem; }
|
|
250
|
+
.mc-cust-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
|
|
251
|
+
.mc-cust-name { color: var(--text); font-weight: 600; }
|
|
252
|
+
.mc-cust-spend { color: var(--accent-bright); font-weight: 600; }
|
|
253
|
+
.mc-cust-meta { color: var(--text-muted); font-size: 0.78rem; margin: 0.2rem 0 0.4rem; }
|
|
254
|
+
|
|
255
|
+
.mc-member { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.7rem; }
|
|
256
|
+
.mc-member-name { color: var(--text); font-weight: 600; }
|
|
257
|
+
|
|
258
|
+
.mc-head-id { display: flex; align-items: center; gap: 0.75rem; }
|
|
259
|
+
.mc-head-logo { width: 44px; height: 44px; border-radius: var(--radius-sm); object-fit: cover; border: 1px solid var(--border); background: var(--bg-elevated); }
|
|
260
|
+
.mc-logo-row { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.3rem; }
|
|
261
|
+
.mc-logo-preview { width: 56px; height: 56px; border-radius: var(--radius-sm); object-fit: cover; border: 1px solid var(--border); background: var(--bg-elevated); }
|
|
262
|
+
.mc-logo-empty { width: 56px; height: 56px; border-radius: var(--radius-sm); border: 1px dashed var(--border); display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 0.7rem; text-align: center; }
|
|
263
|
+
.mc-upload-btn { position: relative; overflow: hidden; cursor: pointer; }
|
|
264
|
+
.mc-file-hidden { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
|
|
265
|
+
.mc-checkbox-row { display: flex; align-items: center; gap: 0.5rem; color: var(--text); font-size: 0.9rem; cursor: pointer; }
|
|
266
|
+
|
|
267
|
+
.mc-portfolio { display: flex; flex-direction: column; gap: 0.6rem; }
|
|
268
|
+
.mc-pf-live { background: var(--success-bg); border: 1px solid var(--success); border-radius: var(--radius-sm); padding: 0.6rem 0.75rem; display: flex; flex-direction: column; gap: 0.4rem; }
|
|
269
|
+
.mc-pf-prompt { font-family: var(--font-mono, monospace); font-size: 0.8rem; white-space: pre; }
|
|
270
|
+
.mc-pf-html { font-family: var(--font-mono, monospace); font-size: 0.8rem; }
|
|
271
|
+
.mc-theme-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.3rem 0 0.6rem; }
|
|
272
|
+
.mc-theme-btn { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.4rem 0.9rem; cursor: pointer; color: var(--text-dim); font-weight: 600; font-size: 0.85rem; transition: border-color 0.15s, color 0.15s; }
|
|
273
|
+
.mc-theme-btn:hover { color: var(--text); }
|
|
274
|
+
.mc-theme-btn.active { border-color: var(--accent); color: var(--accent-bright); background: var(--accent-faint); }
|
|
275
|
+
|
|
225
276
|
.mc-header-row { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; }
|
|
226
277
|
|
|
227
278
|
.mc-orders-received { border-top: 1px solid var(--border); margin-top: 1.25rem; padding-top: 1rem; }
|
|
@@ -234,6 +285,7 @@
|
|
|
234
285
|
.mc-order-title { color: var(--text); font-weight: 600; }
|
|
235
286
|
.mc-order-meta { display: flex; flex-wrap: wrap; gap: 0.6rem; color: var(--text-muted); font-size: 0.78rem; margin-top: 0.2rem; }
|
|
236
287
|
.mc-order-input { color: var(--text-dim); font-size: 0.85rem; margin-top: 0.3rem; }
|
|
288
|
+
.mc-order-receipt { color: var(--accent-bright); font-size: 0.82rem; margin-top: 0.3rem; }
|
|
237
289
|
|
|
238
290
|
.mc-status { font-size: 0.72rem; font-weight: 600; padding: 0.1rem 0.55rem; border-radius: var(--radius-full); white-space: nowrap; }
|
|
239
291
|
.mc-status--queued { background: var(--bg-card); color: var(--text-dim); border: 1px solid var(--border); }
|
|
@@ -482,6 +482,7 @@
|
|
|
482
482
|
.pf .scope-modal {max-width:560px}
|
|
483
483
|
.pf .scope-modal h3 {margin-bottom:.25rem}
|
|
484
484
|
.pf .scope-modal .scope-agent-info {color:var(--text-dim,#6B7280);font-size:.8rem;margin-bottom:1.25rem;font-family:monospace}
|
|
485
|
+
.pf .scope-agent-msg {margin-left:.5rem;text-decoration:none;font-family:initial}
|
|
485
486
|
.pf .scope-templates {display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1.25rem}
|
|
486
487
|
.pf .scope-tpl-btn {flex:1;min-width:100px;padding:.6rem .75rem;background:var(--bg-card,#FFFFFF);border:1px solid var(--border,#E5E7EB);border-radius:8px;cursor:pointer;color:var(--text-dim,#6B7280);font-size:.8rem;font-weight:600;transition:all .2s;text-align:center}
|
|
487
488
|
.pf .scope-tpl-btn:hover {color:var(--text,#1A1A2E);border-color:var(--accent,#E8564A)}
|
|
@@ -3027,3 +3028,24 @@
|
|
|
3027
3028
|
.pf-presence-pill--on { background: var(--accent); border-color: var(--accent); color: #fff; }
|
|
3028
3029
|
.pf-presence-pill:disabled { opacity: .6; cursor: default; }
|
|
3029
3030
|
.pf-presence-hint { font-size: .78rem; color: var(--text-dim); margin: .15rem 0 .35rem; }
|
|
3031
|
+
|
|
3032
|
+
/* ── Discover tab (master directory) ───────────────────────────────────── */
|
|
3033
|
+
.dsc-controls { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; margin: 1rem 0 .75rem; }
|
|
3034
|
+
.dsc-scope { display: inline-flex; gap: .25rem; background: var(--bg-dim); border: 1px solid var(--border); border-radius: var(--radius-full); padding: .2rem; }
|
|
3035
|
+
.dsc-scope-btn { border-radius: var(--radius-full); padding: .3rem .85rem; font-size: .85rem; }
|
|
3036
|
+
.dsc-scope-active { background: var(--accent); color: #fff; }
|
|
3037
|
+
.dsc-search { flex: 1; min-width: 200px; padding: .5rem .75rem; background: var(--control-bg); border: 1px solid var(--control-border); border-radius: var(--radius); color: inherit; }
|
|
3038
|
+
.dsc-facets { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: 1rem; }
|
|
3039
|
+
.dsc-facet { padding: .3rem .7rem; font-size: .82rem; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-full); cursor: pointer; color: inherit; }
|
|
3040
|
+
.dsc-facet:hover { border-color: var(--accent-border); }
|
|
3041
|
+
.dsc-facet-active { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent); }
|
|
3042
|
+
.dsc-item { display: block; padding: .75rem .9rem; margin-bottom: .6rem; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); text-decoration: none; color: inherit; transition: border-color .12s; }
|
|
3043
|
+
.dsc-item:hover { border-color: var(--accent-border); box-shadow: var(--shadow-sm); }
|
|
3044
|
+
.dsc-item-head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
|
|
3045
|
+
.dsc-type-badge { font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; color: var(--accent); background: var(--accent-subtle); border: 1px solid var(--accent-border); border-radius: var(--radius-full); padding: .1rem .5rem; }
|
|
3046
|
+
.dsc-item-title { font-size: .98rem; }
|
|
3047
|
+
.dsc-segment { font-size: .75rem; color: var(--text-dim); background: var(--bg-dim); border-radius: var(--radius-full); padding: .1rem .5rem; }
|
|
3048
|
+
.dsc-item-desc { margin-top: .35rem; font-size: .87rem; color: var(--text-dim); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
|
|
3049
|
+
.dsc-item-meta { margin-top: .5rem; display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
|
|
3050
|
+
.dsc-tag { font-size: .72rem; color: var(--muted); background: var(--bg-dim); border-radius: var(--radius-full); padding: .08rem .45rem; }
|
|
3051
|
+
.dsc-owner { margin-left: auto; font-size: .72rem; color: var(--muted); font-family: var(--mono); }
|
|
@@ -26,6 +26,22 @@ export async function send({ to, body, attachments, replyTo, subject, conversati
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/** Send one message to MANY recipients. `to` is an array of identities and/or `groupId` is a Share Group
|
|
30
|
+
* whose members are the audience. `mode` 'announcement' = read-only; 'broadcast' = repliable. `interactive`
|
|
31
|
+
* makes it a poll. Returns { broadcast_id, recipients, sent, failed }. */
|
|
32
|
+
export async function sendBroadcast({ to, groupId, audience, mode, body, attachments, interactive } = /** @type {{ to?: any, groupId?: any, audience?: any, mode?: any, body?: any, attachments?: any, interactive?: any }} */ ({})) {
|
|
33
|
+
return api('/v1/messages/broadcast', {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
body: JSON.stringify({ to, group_id: groupId, audience, mode, body, attachments, interactive }),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Aggregated results for a broadcast (recipients, delivered/read/answered counts, poll answers). */
|
|
40
|
+
export async function getBroadcastResults(broadcastId) {
|
|
41
|
+
const r = await apiGet(`/v1/messages/broadcast/${enc(broadcastId)}`);
|
|
42
|
+
return r?.data || null;
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
export async function listInbox(unreadOnly = false) {
|
|
30
46
|
const r = await apiGet(`/v1/messages/inbox${unreadOnly ? '?unread=true' : ''}`);
|
|
31
47
|
return r?.data || { messages: [], total: 0, unread: 0 };
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @structure
|
|
10
10
|
* - classifyNote(text) — POST /v1/librarian/classify
|
|
11
11
|
* - distributeNote(text) — POST /v1/librarian/distribute (split into placed chunks)
|
|
12
|
-
* - materializeDocument(plan) — resolve/create org → ws → document space →
|
|
12
|
+
* - materializeDocument(plan) — resolve/create org → ws → document space → draft→publish doc → drop source
|
|
13
13
|
* - distributeChunks(chunks, sourceKey, onProgress) — materialize each chunk to its home
|
|
14
14
|
* - getNotebookSettings/saveNotebookSettings — the per-owner trust toggles (notebook.settings)
|
|
15
15
|
* @version-history
|
|
@@ -18,10 +18,13 @@
|
|
|
18
18
|
* v1.2.0 — 2026-06-21 — (reverted) materializeRecord/patchRecord removed — the Tracked Response flow
|
|
19
19
|
* now writes records through the proper workspace draft→publish path (services/organisms.js), not a
|
|
20
20
|
* raw memory write, so records land in the right namespace/owner and show up with activity.
|
|
21
|
+
* v1.3.0 — 2026-06-23 — materializeDocument now writes via writeDraft + publishDraft (was a raw
|
|
22
|
+
* `.latest` memory write) so notebook documents get version history and appear in the workspace
|
|
23
|
+
* activity log/heatmap — the document-path counterpart to the v1.2.0 record fix.
|
|
21
24
|
*/
|
|
22
25
|
import { api, apiPost } from '/js/api.js';
|
|
23
26
|
import { createMemory, getMemory, deleteMemory } from '/js/services/memory.js';
|
|
24
|
-
import { createOrganism, saveManifest, listWorkspaces, saveWorkspaceRegistry, wsRoot } from '/js/services/organisms.js';
|
|
27
|
+
import { createOrganism, saveManifest, listWorkspaces, saveWorkspaceRegistry, wsRoot, writeDraft, publishDraft } from '/js/services/organisms.js';
|
|
25
28
|
|
|
26
29
|
const DOC_SPACE = 'pages';
|
|
27
30
|
|
|
@@ -162,11 +165,18 @@ export async function materializeDocument(plan) {
|
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
// 4. Write the document.
|
|
168
|
+
// 4. Write the document through the proper workspace draft→publish path (NOT a raw `.latest` write).
|
|
169
|
+
// A raw write to `…{space}.{docId}.latest` lands the content but produces no version history and
|
|
170
|
+
// no activity event (the feed is derived from `.draft`/`.version.N` keys), so notebook documents
|
|
171
|
+
// used to be invisible in the workspace activity log / heatmap. Going through writeDraft +
|
|
172
|
+
// publishDraft mints `.version.1` + `.latest` and shows up like every other published object —
|
|
173
|
+
// matching the Tracked-Response record path migrated in v1.2.0.
|
|
166
174
|
const docId = rid('doc-');
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
if (
|
|
175
|
+
const docValue = { id: docId, title: plan.title, markdown: plan.markdown };
|
|
176
|
+
const draftResp = await writeDraft(organismId, workspaceId, space, docId, docValue);
|
|
177
|
+
if (draftResp?.ok === false) throw new Error(draftResp.error?.message || 'Could not write document');
|
|
178
|
+
const pubResp = await publishDraft(organismId, workspaceId, space, docId);
|
|
179
|
+
if (pubResp?.ok === false) throw new Error(pubResp.error?.message || 'Could not publish document');
|
|
170
180
|
|
|
171
181
|
// 5. Drop the source inbox note (it has been filed).
|
|
172
182
|
if (plan.sourceKey) await deleteMemory(plan.sourceKey).catch(() => {});
|
|
@@ -285,6 +285,7 @@ entry: index.html
|
|
|
285
285
|
|
|
286
286
|
### Other options (not app building)
|
|
287
287
|
|
|
288
|
+
- **Discover everything from one place:** `GET /v1/discover` — the master directory. One faceted query across all domains (capabilities, workflows, knowledge, decisions, companies+offerings, apps, documents, memory). `?mode=map` (or `/v1/discover/facets`) returns counts by type/tag so you can see what exists before pulling content; `scope=own|public|shared`. MCP: `aimeat_discover`.
|
|
288
289
|
- Browse this node: `GET /v1/catalogue`, `GET /v1/apps`, `GET /v1/stats`
|
|
289
290
|
- Connect as AI agent: see "Connecting: Device Authorization" section below
|
|
290
291
|
- Anonymous quick test: `POST /v1/auth/anonymous`
|
|
@@ -1668,6 +1669,12 @@ Discover actions, agents, and boards available on this node.
|
|
|
1668
1669
|
|
|
1669
1670
|
#### Endpoints
|
|
1670
1671
|
|
|
1672
|
+
GET {{BASE_URL}}/v1/discover — Master directory: unified cross-domain discovery (start here)
|
|
1673
|
+
Query: ?mode=find&scope=own|public|shared&q=text&type=capability,knowledge&tags=finance&segment=research&page=1&per_page=20
|
|
1674
|
+
→ 200: { "ok": true, "data": { "entries": [{ "type": "capability", "segment": "manual", "id": "...", "title": "...", "description": "...", "tags": [...], "visibility": "public", "owner": "alice@node", "updatedAt": "...", "href": "/v1/..." }], "total": 42, "scope": "own", "facets": { "types": [...], "segments": [...], "tags": [...] } } }
|
|
1675
|
+
GET {{BASE_URL}}/v1/discover/facets — Map mode: counts by type/segment/tag only (cheap "what exists?" probe), same filters + scope
|
|
1676
|
+
→ 200: { "ok": true, "data": { "scope": "public", "total": 42, "types": [{ "value": "knowledge", "count": 18 }], "segments": [...], "tags": [...] } }
|
|
1677
|
+
|
|
1671
1678
|
GET {{BASE_URL}}/v1/catalogue — Full catalogue listing
|
|
1672
1679
|
Query: ?search=translate&category=language&page=1&per_page=20&include_federated=true
|
|
1673
1680
|
→ 200: { "ok": true, "data": { "actions": [{ "id": "...", "display_name": "...", "description": "...", "provider_gaii": "...", "category": "...", "pricing": { "base_morsels": 5 }, "tags": [...] }], "total": 42 } }
|
package/dist/public/spa.html
CHANGED
|
@@ -86,11 +86,13 @@
|
|
|
86
86
|
<link rel="stylesheet" href="/css/views/aimeat-os.css">
|
|
87
87
|
<link rel="stylesheet" href="/css/views/openclaw.css">
|
|
88
88
|
<link rel="stylesheet" href="/css/views/portfolio.css">
|
|
89
|
+
<link rel="stylesheet" href="/css/views/members.css">
|
|
89
90
|
<link rel="stylesheet" href="/css/views/inbox.css">
|
|
90
91
|
<link rel="stylesheet" href="/css/components/tags.css">
|
|
91
92
|
<link rel="stylesheet" href="/css/components/image-deliverable.css">
|
|
92
93
|
<link rel="stylesheet" href="/css/views/help.css">
|
|
93
94
|
<link rel="stylesheet" href="/css/views/my-company.css">
|
|
95
|
+
<link rel="stylesheet" href="/css/views/companies.css">
|
|
94
96
|
<link rel="stylesheet" href="/css/views/capabilities.css">
|
|
95
97
|
<link rel="stylesheet" href="/css/views/agents-detail.css">
|
|
96
98
|
<link rel="stylesheet" href="/css/views/scheduler.css">
|
|
@@ -188,6 +190,7 @@
|
|
|
188
190
|
"/components/Modal.js": "/components/Modal.js",
|
|
189
191
|
"/components/useViewCSS.js": "/components/useViewCSS.js",
|
|
190
192
|
"/components/Markdown.js": "/components/Markdown.js",
|
|
193
|
+
"/components/InboxLink.js": "/components/InboxLink.js",
|
|
191
194
|
"/components/JsonView.js": "/components/JsonView.js",
|
|
192
195
|
"/components/ImageDeliverable.js": "/components/ImageDeliverable.js",
|
|
193
196
|
"/components/offer-card-view.js": "/components/offer-card-view.js",
|
|
@@ -226,6 +229,7 @@
|
|
|
226
229
|
"/js/services/admin-agent-integration.js": "/js/services/admin-agent-integration.js",
|
|
227
230
|
"/js/services/schedules.js": "/js/services/schedules.js",
|
|
228
231
|
"/js/services/workflows.js": "/js/services/workflows.js",
|
|
232
|
+
"/views/portfolio-themes.js": "/views/portfolio-themes.js",
|
|
229
233
|
"/views/profile/shared.js": "/views/profile/shared.js",
|
|
230
234
|
"/views/profile/generator-settings.js": "/views/profile/generator-settings.js",
|
|
231
235
|
"/views/profile/organisms/helpers.js": "/views/profile/organisms/helpers.js",
|
|
@@ -341,6 +345,7 @@
|
|
|
341
345
|
'/v1/business': () => import('/views/business.js' + B),
|
|
342
346
|
'/v1/profile': () => import('/views/profile.js' + B),
|
|
343
347
|
'/v1/my-company': () => import('/views/my-company.js' + B),
|
|
348
|
+
'/v1/companies': () => import('/views/companies.js' + B),
|
|
344
349
|
'/v1/app-grant': () => import('/views/app-grant.js' + B),
|
|
345
350
|
'/v1/guides': () => import('/views/guides.js' + B),
|
|
346
351
|
'/v1/hobbies': () => import('/views/hobbies.js' + B),
|
|
@@ -349,6 +354,7 @@
|
|
|
349
354
|
'/v1/openclaw': () => import('/views/openclaw.js' + B),
|
|
350
355
|
'/v1/classic': () => import('/views/portal-classic.js' + B),
|
|
351
356
|
'/v1/portfolio': () => import('/views/portfolio.js' + B),
|
|
357
|
+
'/v1/members': () => import('/views/members.js' + B),
|
|
352
358
|
'/v1/admin': () => import('/views/admin.js' + B),
|
|
353
359
|
'/v1/help': () => import('/views/help.js' + B),
|
|
354
360
|
'/v1/publicknowledgeviewer': () => import('/views/public-knowledge-viewer.js' + B),
|
|
@@ -511,6 +517,8 @@
|
|
|
511
517
|
{ id: 'try', path: '/v1/portal', key: 'nav.try' },
|
|
512
518
|
{ id: 'howItWorks', path: '/v1/how-it-works', key: 'nav.howItWorks', fallback: 'How it works' },
|
|
513
519
|
{ id: 'business', path: '/v1/business', key: 'nav.business', fallback: 'For your business' },
|
|
520
|
+
{ id: 'companies', path: '/v1/companies', key: 'nav.companies', fallback: 'Companies' },
|
|
521
|
+
{ id: 'members', path: '/v1/members', key: 'nav.members', fallback: 'Members' },
|
|
514
522
|
{ id: 'devView', path: '/v1/portal?view=dev', key: 'nav.devView', matchActive: false },
|
|
515
523
|
{ id: 'help', path: '/v1/help', key: 'nav.help' },
|
|
516
524
|
];
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file companies.js
|
|
3
|
+
* @description Public company directory + public company page (the Enterprise discovery surface).
|
|
4
|
+
* Anyone (even anonymous) can browse every company on the node (GET /v1/orgs/directory), open one
|
|
5
|
+
* to see its public profile (name, Y-tunnus, description) and catalogue (GET
|
|
6
|
+
* /v1/orgs/:owner/:slug/offerings — the SAME offer cards as profile>offers), and order an offering
|
|
7
|
+
* (POST .../use — ordering requires login). Backend stays protocol-only; the EE module provides the
|
|
8
|
+
* org APIs (a Community node returns ENTERPRISE_REQUIRED).
|
|
9
|
+
* @structure CompaniesView · directory list · PublicOfferingCard (order box, reuses OfferCardView)
|
|
10
|
+
* @usage routed at /v1/companies; deep-link a company via ?c=owner/slug.
|
|
11
|
+
* @version-history
|
|
12
|
+
* v0.1.0 — 2026-06-23 — initial: directory + public company page + order
|
|
13
|
+
*/
|
|
14
|
+
import { h } from 'preact';
|
|
15
|
+
import { useState, useEffect } from 'preact/hooks';
|
|
16
|
+
import htm from 'htm';
|
|
17
|
+
import { t } from '/js/i18n.js';
|
|
18
|
+
import { apiGet, apiPost } from '/js/api.js';
|
|
19
|
+
import { DeliverableBody } from '/components/ImageDeliverable.js';
|
|
20
|
+
import { OfferCardView } from '/components/offer-card-view.js';
|
|
21
|
+
|
|
22
|
+
const html = htm.bind(h);
|
|
23
|
+
|
|
24
|
+
const isLoggedIn = () => !!(typeof window !== 'undefined' && window.AIMEAT?.auth?.getSession?.());
|
|
25
|
+
|
|
26
|
+
/** One orderable offering on the public company page (same card as profile>offers + an order box). */
|
|
27
|
+
function PublicOfferingCard({ o, owner, slug }) {
|
|
28
|
+
const offer = o.offer;
|
|
29
|
+
const [input, setInput] = useState('');
|
|
30
|
+
const [busy, setBusy] = useState(false);
|
|
31
|
+
const [result, setResult] = useState(null);
|
|
32
|
+
const [err, setErr] = useState('');
|
|
33
|
+
const loggedIn = isLoggedIn();
|
|
34
|
+
|
|
35
|
+
async function order() {
|
|
36
|
+
setBusy(true); setErr(''); setResult(null);
|
|
37
|
+
try {
|
|
38
|
+
const res = await apiPost(`/v1/orgs/${encodeURIComponent(owner)}/${encodeURIComponent(slug)}/use`,
|
|
39
|
+
{ agentName: o.agentName, offerId: o.offerId, input: input.trim() || undefined });
|
|
40
|
+
setResult(res.data); setInput('');
|
|
41
|
+
} catch (e) { setErr(e.message || 'Order failed'); }
|
|
42
|
+
finally { setBusy(false); }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const actions = html`
|
|
46
|
+
<div class="cm-not-callable">${o.callable ? t('companies.callable') : t('companies.viaInbox')}</div>
|
|
47
|
+
${loggedIn
|
|
48
|
+
? html`
|
|
49
|
+
<textarea class="input-field input-sm of-input" rows="2" value=${input}
|
|
50
|
+
placeholder=${t('companies.usePlaceholder')} onInput=${(e) => setInput(e.target.value)}></textarea>
|
|
51
|
+
<div class="flex-row-wrap">
|
|
52
|
+
<button class="btn-primary btn-sm" disabled=${busy} onClick=${order}>
|
|
53
|
+
${t('companies.order')}${offer.price?.morsels ? ` · ${offer.price.morsels} ${t('companies.morsels')}` : ''}
|
|
54
|
+
</button>
|
|
55
|
+
</div>`
|
|
56
|
+
: html`<a class="btn-outline btn-sm" href="/v1/profile">${t('companies.loginToOrder')}</a>`}
|
|
57
|
+
${err && html`<p class="cm-error">${err}</p>`}
|
|
58
|
+
${result && html`
|
|
59
|
+
<div class="cm-result">
|
|
60
|
+
${result.kind === 'result'
|
|
61
|
+
? html`<div class="cm-result-msg">${t('companies.orderResult')}</div><${DeliverableBody} value=${result.result} alt=${offer.title} format=${offer.deliverable?.format} />`
|
|
62
|
+
: html`<div class="cm-result-msg">${t('companies.orderTask').replace('{agent}', o.agentName)}</div>`}
|
|
63
|
+
${result.receipt?.charged > 0 && html`<div class="cm-receipt">${t('companies.charged').replace('{n}', result.receipt.charged)}</div>`}
|
|
64
|
+
</div>`}
|
|
65
|
+
`;
|
|
66
|
+
return html`<li class="cm-cat-item"><${OfferCardView} entry=${{ agent: o.agentName, online: o.online }} offer=${offer} actions=${actions} /></li>`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** One purchase receipt in the buyer's "My orders" panel. */
|
|
70
|
+
function ReceiptRow({ o }) {
|
|
71
|
+
const statusKey = o.kind === 'result' ? 'stInstant' : ({ queued: 'stQueued', active: 'stActive', done: 'stDone', failed: 'stFailed' }[o.status] || 'stQueued');
|
|
72
|
+
return html`
|
|
73
|
+
<li class="cm-receipt-row">
|
|
74
|
+
<div class="cm-receipt-top">
|
|
75
|
+
<span class="cm-receipt-title">${o.offerTitle}</span>
|
|
76
|
+
<span class="cm-receipt-amt">${o.charged > 0 ? `${o.charged} ${t('companies.morsels')}` : t('companies.free')}</span>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="cm-receipt-meta">
|
|
79
|
+
<span>${t('companies.fromCompany')}: ${o.orgSlug}</span>
|
|
80
|
+
<span>🤖 ${o.agentName}</span>
|
|
81
|
+
<span>${t('companies.' + statusKey)}</span>
|
|
82
|
+
<span class="cm-mini">${new Date(o.createdAt).toLocaleString()}</span>
|
|
83
|
+
</div>
|
|
84
|
+
${o.trackingCode && html`<div class="cm-mini cm-receipt-code">🧾 ${o.trackingCode}</div>`}
|
|
85
|
+
</li>`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default function CompaniesView() {
|
|
89
|
+
const [companies, setCompanies] = useState(null);
|
|
90
|
+
const [selected, setSelected] = useState(null); // { owner, slug }
|
|
91
|
+
const [profile, setProfile] = useState(null); // { org, offerings }
|
|
92
|
+
const [myOrders, setMyOrders] = useState(null);
|
|
93
|
+
const [showOrders, setShowOrders] = useState(false);
|
|
94
|
+
const [err, setErr] = useState('');
|
|
95
|
+
const loggedIn = isLoggedIn();
|
|
96
|
+
|
|
97
|
+
async function loadMyOrders() {
|
|
98
|
+
try { const r = await apiGet('/v1/orders'); setMyOrders(r.data?.orders ?? []); }
|
|
99
|
+
catch { setMyOrders([]); }
|
|
100
|
+
}
|
|
101
|
+
function toggleOrders() { const n = !showOrders; setShowOrders(n); if (n) loadMyOrders(); }
|
|
102
|
+
|
|
103
|
+
async function loadDirectory() {
|
|
104
|
+
try { const r = await apiGet('/v1/orgs/directory'); setCompanies(r.data?.companies ?? []); }
|
|
105
|
+
catch (e) {
|
|
106
|
+
if (e.code === 'ENTERPRISE_REQUIRED') setCompanies('enterprise');
|
|
107
|
+
else { setErr(e.message || 'Failed to load'); setCompanies([]); }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
useEffect(() => { loadDirectory(); }, []);
|
|
111
|
+
|
|
112
|
+
async function openCompany(owner, slug) {
|
|
113
|
+
setSelected({ owner, slug }); setProfile(null); setErr('');
|
|
114
|
+
try { history.replaceState(null, '', `/v1/companies?c=${encodeURIComponent(owner)}/${encodeURIComponent(slug)}`); } catch { /* ignore */ }
|
|
115
|
+
try {
|
|
116
|
+
const r = await apiGet(`/v1/orgs/${encodeURIComponent(owner)}/${encodeURIComponent(slug)}/offerings`);
|
|
117
|
+
setProfile(r.data ?? null);
|
|
118
|
+
} catch (e) { setErr(e.message || ''); }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Deep-link: once the directory is loaded, open ?c=owner/slug if present.
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (Array.isArray(companies) && !selected) {
|
|
124
|
+
const c = new URLSearchParams(location.search).get('c');
|
|
125
|
+
if (c && c.includes('/')) { const [o, s] = c.split('/'); openCompany(o, s); }
|
|
126
|
+
}
|
|
127
|
+
}, [companies]);
|
|
128
|
+
|
|
129
|
+
if (companies === null) return html`<div class="cm-container"><div class="cm-center"><div class="spinner"></div></div></div>`;
|
|
130
|
+
if (companies === 'enterprise') return html`<div class="cm-container"><div class="cm-card"><h1 class="cm-title">${t('companies.title')}</h1><p class="cm-desc">${t('companies.enterpriseRequired')}</p></div></div>`;
|
|
131
|
+
|
|
132
|
+
return html`
|
|
133
|
+
<div class="cm-container">
|
|
134
|
+
<header class="cm-header">
|
|
135
|
+
<div class="cm-header-row">
|
|
136
|
+
<h1 class="cm-title">${t('companies.title')}</h1>
|
|
137
|
+
${loggedIn && html`<button class="btn-outline btn-sm" onClick=${toggleOrders}>${showOrders ? t('companies.done') : t('companies.myOrders')}</button>`}
|
|
138
|
+
</div>
|
|
139
|
+
<p class="cm-desc">${t('companies.desc')}</p>
|
|
140
|
+
</header>
|
|
141
|
+
${err && html`<p class="cm-error">${err}</p>`}
|
|
142
|
+
|
|
143
|
+
${showOrders && html`
|
|
144
|
+
<div class="cm-col cm-orders-panel">
|
|
145
|
+
<h2 class="cm-col-title">${t('companies.myOrders')}</h2>
|
|
146
|
+
${myOrders === null ? html`<div class="cm-center"><div class="spinner"></div></div>`
|
|
147
|
+
: (myOrders.length === 0 ? html`<p class="cm-empty">${t('companies.noMyOrders')}</p>`
|
|
148
|
+
: html`<ul class="cm-receipt-list">${myOrders.map(o => html`<${ReceiptRow} key=${o.id} o=${o} />`)}</ul>`)}
|
|
149
|
+
</div>`}
|
|
150
|
+
<div class="cm-grid">
|
|
151
|
+
<aside class="cm-col">
|
|
152
|
+
<h2 class="cm-col-title">${t('companies.directory')} (${companies.length})</h2>
|
|
153
|
+
${companies.length === 0 && html`<p class="cm-empty">${t('companies.none')}</p>`}
|
|
154
|
+
<ul class="cm-dir-list">
|
|
155
|
+
${companies.map(c => html`<li key=${c.goii}>
|
|
156
|
+
<button class="cm-dir-item ${selected?.slug === c.slug && selected?.owner === c.creatorOwner ? 'active' : ''}" onClick=${() => openCompany(c.creatorOwner, c.slug)}>
|
|
157
|
+
${c.logo && html`<img class="cm-dir-logo" src=${c.logo} alt=${c.name} />`}
|
|
158
|
+
<div class="cm-dir-text">
|
|
159
|
+
<span class="cm-dir-name">${c.name}</span>
|
|
160
|
+
<span class="cm-dir-meta">${c.businessId ? html`<span class="cm-tag">Y ${c.businessId}</span>` : ''}${c.offerings} ${t('companies.offeringsShort')}</span>
|
|
161
|
+
</div>
|
|
162
|
+
</button></li>`)}
|
|
163
|
+
</ul>
|
|
164
|
+
</aside>
|
|
165
|
+
<section class="cm-col">
|
|
166
|
+
${!selected && html`<p class="cm-empty">${t('companies.selectHint')}</p>`}
|
|
167
|
+
${selected && !profile && html`<div class="cm-center"><div class="spinner"></div></div>`}
|
|
168
|
+
${profile && html`
|
|
169
|
+
<div class="cm-profile-head">
|
|
170
|
+
<div class="cm-profile-id">
|
|
171
|
+
${profile.org?.logo && html`<img class="cm-profile-logo" src=${profile.org.logo} alt=${profile.org?.name} />`}
|
|
172
|
+
<div>
|
|
173
|
+
<h2 class="cm-col-title">${profile.org?.name}</h2>
|
|
174
|
+
${profile.org?.businessId && html`<span class="cm-mini">${t('companies.businessId')}: ${profile.org.businessId}</span>`}
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
${profile.org?.description && html`<p class="cm-profile-desc">${profile.org.description}</p>`}
|
|
178
|
+
${profile.org?.portfolio?.enabled && profile.org.portfolio.publicUrl && html`
|
|
179
|
+
<a class="btn-outline btn-sm cm-pf-link" href=${profile.org.portfolio.publicUrl} target="_blank">${t('companies.viewPortfolio')}</a>`}
|
|
180
|
+
</div>
|
|
181
|
+
<h3 class="cm-form-title">${t('companies.catalogue')}</h3>
|
|
182
|
+
${(profile.offerings ?? []).length === 0 && html`<p class="cm-empty">${t('companies.noOfferings')}</p>`}
|
|
183
|
+
<ul class="cm-cat-list">
|
|
184
|
+
${(profile.offerings ?? []).map(o => html`<${PublicOfferingCard} key=${o.agentName + '/' + o.offerId} o=${o} owner=${selected.owner} slug=${selected.slug} />`)}
|
|
185
|
+
</ul>
|
|
186
|
+
`}
|
|
187
|
+
</section>
|
|
188
|
+
</div>
|
|
189
|
+
</div>`;
|
|
190
|
+
}
|