aimeat 1.25.1 → 1.26.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/README.md +8 -1
- package/dist/locales/en.json +130 -0
- package/dist/locales/fi.json +130 -0
- package/dist/public/components/ImageDeliverable.js +2 -1
- package/dist/public/components/Modal.js +3 -2
- package/dist/public/components/NotificationBell.js +2 -1
- package/dist/public/components/PresenceDot.js +53 -0
- package/dist/public/css/components/markdown.css +67 -0
- package/dist/public/css/theme.css +30 -0
- package/dist/public/css/views/notebook.css +195 -0
- package/dist/public/css/views/profile.css +15 -0
- package/dist/public/js/api.js +5 -3
- package/dist/public/js/components/auth-image.js +3 -2
- package/dist/public/js/components/tag-cloud.js +1 -1
- package/dist/public/js/components/tag-editor.js +1 -1
- package/dist/public/js/hooks.js +1 -2
- package/dist/public/js/presence-store.js +97 -0
- package/dist/public/js/services/admin.js +6 -0
- package/dist/public/js/services/boards.js +1 -1
- package/dist/public/js/services/ecosystem.js +1 -1
- package/dist/public/js/services/foundry-prompts-base.js +2 -2
- package/dist/public/js/services/foundry-smoke.js +2 -1
- package/dist/public/js/services/foundry-validate.js +6 -8
- package/dist/public/js/services/foundry.js +4 -3
- package/dist/public/js/services/generator-prompts-base.js +2 -2
- package/dist/public/js/services/generator-smoke.js +2 -1
- package/dist/public/js/services/generator-validate.js +5 -7
- package/dist/public/js/services/generator.js +2 -1
- package/dist/public/js/services/memory.js +13 -0
- package/dist/public/js/services/messages.js +2 -1
- package/dist/public/js/services/notebook.js +124 -0
- package/dist/public/js/services/packages.js +3 -2
- package/dist/public/js/services/presence.js +35 -0
- package/dist/public/js/style-testbed.js +6 -5
- package/dist/public/lib/minidenticons.min.js +1 -0
- package/dist/public/lib/yaml.mjs +1 -0
- package/dist/public/spa.html +68 -8
- package/dist/public/types/aimeat-globals.d.ts +52 -0
- package/dist/public/types/vendored-libs.d.ts +56 -0
- package/dist/public/views/_template.js +3 -1
- package/dist/public/views/admin/agent-integration-tab.js +4 -3
- package/dist/public/views/admin/agents-tab.js +3 -2
- package/dist/public/views/admin/config-tab.js +4 -3
- package/dist/public/views/admin/economy-tab.js +4 -3
- package/dist/public/views/admin/federation-tab.js +138 -1
- package/dist/public/views/admin/maintenance-tab.js +1 -1
- package/dist/public/views/admin/overview-tab.js +4 -3
- package/dist/public/views/admin/portal-tab.js +90 -2
- package/dist/public/views/admin/push-tab.js +8 -6
- package/dist/public/views/admin/security-tab.js +7 -7
- package/dist/public/views/admin.js +2 -1
- package/dist/public/views/doc-solo.js +3 -1
- package/dist/public/views/guides.js +8 -4
- package/dist/public/views/hobbies.js +4 -2
- package/dist/public/views/marketplace.js +10 -9
- package/dist/public/views/openclaw.js +1 -1
- package/dist/public/views/portal-dev.js +5 -2
- package/dist/public/views/portal.js +3 -2
- package/dist/public/views/profile/agents/shared-board.js +4 -2
- package/dist/public/views/profile/agents/tab-messages.js +13 -11
- package/dist/public/views/profile/agents-messages-subtab.js +2 -1
- package/dist/public/views/profile/apps-tab.js +2 -1
- package/dist/public/views/profile/boards-tab.js +3 -2
- package/dist/public/views/profile/calibrator-batch.js +3 -2
- package/dist/public/views/profile/data-wallet-tab.js +2 -1
- package/dist/public/views/profile/extensions-tab.js +4 -3
- package/dist/public/views/profile/federation-tab.js +4 -0
- package/dist/public/views/profile/foundry-dashboard/use-autopilot.js +3 -2
- package/dist/public/views/profile/foundry-detail.js +1 -1
- package/dist/public/views/profile/generator-detail.js +1 -1
- package/dist/public/views/profile/inbox-tab.js +7 -3
- package/dist/public/views/profile/inline-panels.js +3 -1
- package/dist/public/views/profile/knowledge-tab.js +2 -1
- package/dist/public/views/profile/landing-page.js +88 -0
- package/dist/public/views/profile/memory-tab.js +6 -5
- package/dist/public/views/profile/notebook-tab.js +500 -0
- package/dist/public/views/profile/organisms/activity-panel.js +135 -0
- package/dist/public/views/profile/organisms/agents.js +141 -0
- package/dist/public/views/profile/organisms/document.js +274 -0
- package/dist/public/views/profile/organisms/helpers.js +61 -0
- package/dist/public/views/profile/organisms/home.js +315 -0
- package/dist/public/views/profile/organisms/members.js +220 -0
- package/dist/public/views/profile/organisms/panels.js +173 -0
- package/dist/public/views/profile/organisms/participants-panel.js +160 -0
- package/dist/public/views/profile/organisms/schema-form.js +127 -0
- package/dist/public/views/profile/organisms/sources-panel.js +164 -0
- package/dist/public/views/profile/organisms/widgets.js +58 -0
- package/dist/public/views/profile/organisms/workspace-comments.js +99 -0
- package/dist/public/views/profile/organisms/workspace-list.js +268 -0
- package/dist/public/views/profile/organisms/workspace.js +1272 -0
- package/dist/public/views/profile/organisms-tab.js +456 -3819
- package/dist/public/views/profile/shared.js +64 -2
- package/dist/public/views/profile/workflows-form.js +1 -1
- package/dist/public/views/profile.js +16 -14
- package/dist/public/views/public-knowledge-viewer.js +3 -2
- package/dist/public/views/public-workspace-viewer.js +2 -1
- package/dist/scripts/check-importmap.d.ts +2 -0
- package/dist/scripts/check-importmap.d.ts.map +1 -0
- package/dist/scripts/check-importmap.js +102 -0
- package/dist/scripts/check-importmap.js.map +1 -0
- package/dist/src/config.d.ts +10 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +5 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/generated/api-types.d.ts +852 -11
- package/dist/src/generated/api-types.d.ts.map +1 -1
- package/dist/src/generated/prisma-postgres/edge.js +18 -5
- package/dist/src/generated/prisma-postgres/index-browser.js +15 -2
- package/dist/src/generated/prisma-postgres/index.d.ts +422 -7
- package/dist/src/generated/prisma-postgres/index.js +18 -5
- package/dist/src/generated/prisma-postgres/package.json +1 -1
- package/dist/src/generated/prisma-postgres/schema.prisma +30 -12
- package/dist/src/generated/prisma-postgres/wasm.js +18 -5
- package/dist/src/routes/federation-peer.d.ts.map +1 -1
- package/dist/src/routes/federation-peer.js +327 -43
- package/dist/src/routes/federation-peer.js.map +1 -1
- package/dist/src/routes/federation-sync.d.ts +2 -0
- package/dist/src/routes/federation-sync.d.ts.map +1 -1
- package/dist/src/routes/federation-sync.js +20 -1
- package/dist/src/routes/federation-sync.js.map +1 -1
- package/dist/src/routes/librarian.d.ts +18 -0
- package/dist/src/routes/librarian.d.ts.map +1 -0
- package/dist/src/routes/librarian.js +88 -0
- package/dist/src/routes/librarian.js.map +1 -0
- package/dist/src/routes/portal.d.ts.map +1 -1
- package/dist/src/routes/portal.js +9 -1
- package/dist/src/routes/portal.js.map +1 -1
- package/dist/src/routes/presence.d.ts +23 -0
- package/dist/src/routes/presence.d.ts.map +1 -0
- package/dist/src/routes/presence.js +88 -0
- package/dist/src/routes/presence.js.map +1 -0
- package/dist/src/routes/site.d.ts +2 -0
- package/dist/src/routes/site.d.ts.map +1 -1
- package/dist/src/routes/site.js +27 -0
- package/dist/src/routes/site.js.map +1 -1
- package/dist/src/routes/sse.d.ts +2 -0
- package/dist/src/routes/sse.d.ts.map +1 -1
- package/dist/src/routes/sse.js +9 -0
- package/dist/src/routes/sse.js.map +1 -1
- package/dist/src/routes/wellknown.d.ts.map +1 -1
- package/dist/src/routes/wellknown.js +5 -0
- package/dist/src/routes/wellknown.js.map +1 -1
- package/dist/src/routes/work.d.ts.map +1 -1
- package/dist/src/routes/work.js +6 -0
- package/dist/src/routes/work.js.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
- package/dist/src/server-bootstrap/routes-loader.js +13 -0
- package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
- package/dist/src/server-bootstrap/service-init.d.ts.map +1 -1
- package/dist/src/server-bootstrap/service-init.js +34 -0
- package/dist/src/server-bootstrap/service-init.js.map +1 -1
- package/dist/src/services/config-schema.d.ts.map +1 -1
- package/dist/src/services/config-schema.js +2 -0
- package/dist/src/services/config-schema.js.map +1 -1
- package/dist/src/services/federation-availability.d.ts +28 -0
- package/dist/src/services/federation-availability.d.ts.map +1 -0
- package/dist/src/services/federation-availability.js +58 -0
- package/dist/src/services/federation-availability.js.map +1 -0
- package/dist/src/services/federation-book.d.ts +70 -0
- package/dist/src/services/federation-book.d.ts.map +1 -0
- package/dist/src/services/federation-book.js +198 -0
- package/dist/src/services/federation-book.js.map +1 -0
- package/dist/src/services/federation-tiers.d.ts +45 -0
- package/dist/src/services/federation-tiers.d.ts.map +1 -0
- package/dist/src/services/federation-tiers.js +58 -0
- package/dist/src/services/federation-tiers.js.map +1 -0
- package/dist/src/services/federation.d.ts +15 -0
- package/dist/src/services/federation.d.ts.map +1 -1
- package/dist/src/services/federation.js +12 -0
- package/dist/src/services/federation.js.map +1 -1
- package/dist/src/services/librarian.d.ts +62 -0
- package/dist/src/services/librarian.d.ts.map +1 -0
- package/dist/src/services/librarian.js +135 -0
- package/dist/src/services/librarian.js.map +1 -0
- package/dist/src/services/network-policy.d.ts +88 -0
- package/dist/src/services/network-policy.d.ts.map +1 -0
- package/dist/src/services/network-policy.js +154 -0
- package/dist/src/services/network-policy.js.map +1 -0
- package/dist/src/services/notebook-classify-prompt.d.ts +15 -0
- package/dist/src/services/notebook-classify-prompt.d.ts.map +1 -0
- package/dist/src/services/notebook-classify-prompt.js +39 -0
- package/dist/src/services/notebook-classify-prompt.js.map +1 -0
- package/dist/src/services/notebook-classify.d.ts +80 -0
- package/dist/src/services/notebook-classify.d.ts.map +1 -0
- package/dist/src/services/notebook-classify.js +150 -0
- package/dist/src/services/notebook-classify.js.map +1 -0
- package/dist/src/services/presence.d.ts +108 -0
- package/dist/src/services/presence.d.ts.map +1 -0
- package/dist/src/services/presence.js +304 -0
- package/dist/src/services/presence.js.map +1 -0
- package/dist/src/services/prompt-defaults.d.ts.map +1 -1
- package/dist/src/services/prompt-defaults.js +13 -0
- package/dist/src/services/prompt-defaults.js.map +1 -1
- package/dist/src/services/site.d.ts +20 -0
- package/dist/src/services/site.d.ts.map +1 -1
- package/dist/src/services/site.js +70 -0
- package/dist/src/services/site.js.map +1 -1
- package/dist/src/storage/interface.d.ts +18 -0
- package/dist/src/storage/interface.d.ts.map +1 -1
- package/dist/src/storage/interface.js.map +1 -1
- package/dist/src/storage/providers/mongodb/index.d.ts +5 -0
- package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
- package/dist/src/storage/providers/mongodb/index.js +65 -2
- package/dist/src/storage/providers/mongodb/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/index.d.ts +2 -0
- package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/index.js +15 -2
- package/dist/src/storage/providers/sqlite/index.js.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/memory.d.ts +2 -0
- package/dist/src/storage/providers/sqlite/repos/memory.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/repos/memory.js +55 -0
- package/dist/src/storage/providers/sqlite/repos/memory.js.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
- package/dist/src/storage/providers/sqlite/schema.js +46 -0
- package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
- package/dist/src/storage/repositories/memory.repository.d.ts +25 -0
- package/dist/src/storage/repositories/memory.repository.d.ts.map +1 -1
- package/dist/src/utils/node-descriptor.d.ts +34 -0
- package/dist/src/utils/node-descriptor.d.ts.map +1 -0
- package/dist/src/utils/node-descriptor.js +42 -0
- package/dist/src/utils/node-descriptor.js.map +1 -0
- package/dist/src/utils/version.d.ts +3 -0
- package/dist/src/utils/version.d.ts.map +1 -0
- package/dist/src/utils/version.js +40 -0
- package/dist/src/utils/version.js.map +1 -0
- package/dist/static/app-catalog.html +643 -4
- package/package.json +5 -2
- package/prisma/schema.postgres.prisma +37 -19
- package/prisma/schema.prisma +14 -0
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* v1.1.0 — 2026-06-02 — Component unification (#11): node-badge dot uses
|
|
8
8
|
* canonical <StatusDot status="online" /> instead of bespoke .dv-dot
|
|
9
9
|
* (which had a hardcoded #22c55e — now tokenized via the component).
|
|
10
|
+
* v1.1.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
10
11
|
*/
|
|
11
12
|
import { h } from 'preact';
|
|
12
13
|
import { useState, useEffect, useRef, useCallback } from 'preact/hooks';
|
|
@@ -23,7 +24,9 @@ const NODE_URL = window.location.origin;
|
|
|
23
24
|
/* ══════════════════════════════════════════════
|
|
24
25
|
i18n — use SPA i18n.js t() with 'dev.' prefix
|
|
25
26
|
══════════════════════════════════════════════ */
|
|
26
|
-
|
|
27
|
+
// `locale` is accepted for call-site symmetry but currently unused — t() resolves against
|
|
28
|
+
// the active global locale, not a per-call override.
|
|
29
|
+
function dt(key, _locale) {
|
|
27
30
|
return globalT('dev.' + key);
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -612,7 +615,7 @@ function CommunityApps({ locale, isLoggedIn, session }) {
|
|
|
612
615
|
style="background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:.25rem .4rem;color:var(--text);font-size:.8rem;width:120px" />
|
|
613
616
|
<a href="#" onClick=${e => {
|
|
614
617
|
e.preventDefault();
|
|
615
|
-
const code = document.getElementById(codeInputId)?.value?.trim();
|
|
618
|
+
const code = /** @type {HTMLInputElement} */ (document.getElementById(codeInputId))?.value?.trim();
|
|
616
619
|
if (!code) return;
|
|
617
620
|
window.open(NODE_URL + app.download_url + '?code=' + encodeURIComponent(code));
|
|
618
621
|
}} style="font-size:.85rem">\u2b07 ${dt('download', locale)}</a>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @version-history
|
|
6
6
|
* v1.1.0 — 2026-06-02 — Component unification (#11): live-feed header dot uses
|
|
7
7
|
* canonical <StatusDot status="live" /> instead of bespoke .live-dot.
|
|
8
|
+
* v1.1.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
8
9
|
*/
|
|
9
10
|
import { h } from 'preact';
|
|
10
11
|
import { useState, useEffect, useRef, useCallback } from 'preact/hooks';
|
|
@@ -1180,7 +1181,7 @@ function TheWorld({ navigate }) {
|
|
|
1180
1181
|
// Trigger login modal
|
|
1181
1182
|
const slot = document.getElementById('headerAuth');
|
|
1182
1183
|
const loginBtn = slot && slot.querySelector('#aimeat-login-btn');
|
|
1183
|
-
if (loginBtn) loginBtn.click();
|
|
1184
|
+
if (loginBtn) /** @type {HTMLElement} */ (loginBtn).click();
|
|
1184
1185
|
}, [navigate]);
|
|
1185
1186
|
|
|
1186
1187
|
return html`
|
|
@@ -1289,7 +1290,7 @@ export default function Portal({ navigate, locale }) {
|
|
|
1289
1290
|
// Trigger login via the header auth button
|
|
1290
1291
|
const loginBtn = document.querySelector('#headerAuth #aimeat-login-btn');
|
|
1291
1292
|
if (loginBtn) {
|
|
1292
|
-
loginBtn.click();
|
|
1293
|
+
/** @type {HTMLElement} */ (loginBtn).click();
|
|
1293
1294
|
// After login, the aimeat-auth-change event will fire and we re-check
|
|
1294
1295
|
const handler = () => {
|
|
1295
1296
|
const s = getCurrentSession();
|
|
@@ -33,10 +33,10 @@ const BUCKETS = [
|
|
|
33
33
|
|
|
34
34
|
export default function SharedBoard({ agents, onboardings, onAgentClick }) {
|
|
35
35
|
const [bucketFilter, setBucketFilter] = useState(null);
|
|
36
|
-
if (!agents || agents.length === 0) return null;
|
|
37
36
|
|
|
37
|
+
// Hooks must run unconditionally before any early return (Rules of Hooks).
|
|
38
38
|
const agentStates = useMemo(() => {
|
|
39
|
-
const rows = agents.map(agent => {
|
|
39
|
+
const rows = (agents || []).map(agent => {
|
|
40
40
|
const state = detectAgentState(agent, onboardings?.[agent.name]);
|
|
41
41
|
return { agent, state, bucket: BUCKET_OF[state] || 'quiet', onboarding: onboardings?.[agent.name] };
|
|
42
42
|
});
|
|
@@ -63,6 +63,8 @@ export default function SharedBoard({ agents, onboardings, onAgentClick }) {
|
|
|
63
63
|
return tagCounts;
|
|
64
64
|
}, [agentStates]);
|
|
65
65
|
|
|
66
|
+
if (!agents || agents.length === 0) return null;
|
|
67
|
+
|
|
66
68
|
return html`
|
|
67
69
|
<div class="pf-agd-board">
|
|
68
70
|
<div class="pf-agd-board-legend">
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* v1.2.0 -- 2026-05-24 -- Add command-reply visual pairing for slash commands
|
|
19
19
|
* v1.1.0 -- 2026-05-24 -- M7: visual distinction for command messages (slash prefix)
|
|
20
20
|
* v1.0.0 -- 2026-05-24 -- Initial creation for Agent Detail Tab-View
|
|
21
|
+
* v1.6.1 -- 2026-06-19 -- JSDoc type annotations for frontend type-checking
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
24
|
import { h } from 'preact';
|
|
@@ -47,6 +48,17 @@ function threadLabel(thread) {
|
|
|
47
48
|
function CommandPalette({ commands, onSend }) {
|
|
48
49
|
const [expanded, setExpanded] = useState(false);
|
|
49
50
|
|
|
51
|
+
// Hooks must run unconditionally before any early return (Rules of Hooks).
|
|
52
|
+
const categories = useMemo(() => {
|
|
53
|
+
const cats = {};
|
|
54
|
+
for (const cmd of (commands || [])) {
|
|
55
|
+
const cat = cmd.category || t('profile.agents.detail.messages.commands.defaultCategory');
|
|
56
|
+
if (!cats[cat]) cats[cat] = [];
|
|
57
|
+
cats[cat].push(cmd);
|
|
58
|
+
}
|
|
59
|
+
return cats;
|
|
60
|
+
}, [commands]);
|
|
61
|
+
|
|
50
62
|
if (!commands || commands.length === 0) {
|
|
51
63
|
// No registered commands → one quiet line, not an expandable empty box.
|
|
52
64
|
return html`
|
|
@@ -57,16 +69,6 @@ function CommandPalette({ commands, onSend }) {
|
|
|
57
69
|
`;
|
|
58
70
|
}
|
|
59
71
|
|
|
60
|
-
const categories = useMemo(() => {
|
|
61
|
-
const cats = {};
|
|
62
|
-
for (const cmd of commands) {
|
|
63
|
-
const cat = cmd.category || t('profile.agents.detail.messages.commands.defaultCategory');
|
|
64
|
-
if (!cats[cat]) cats[cat] = [];
|
|
65
|
-
cats[cat].push(cmd);
|
|
66
|
-
}
|
|
67
|
-
return cats;
|
|
68
|
-
}, [commands]);
|
|
69
|
-
|
|
70
72
|
return html`
|
|
71
73
|
<div class="pf-agd-commands">
|
|
72
74
|
<div class="pf-agd-commands-header" onClick=${() => setExpanded(!expanded)}>
|
|
@@ -332,7 +334,7 @@ export default function TabMessages({ agent, agentName, session, showToast }) {
|
|
|
332
334
|
${messages.length > 0 && html`
|
|
333
335
|
<div class="pf-agd-msg-history" ref=${historyRef}>
|
|
334
336
|
${(() => {
|
|
335
|
-
const sorted = [...messages].sort((a, b) => new Date(a.createdAt || 0) - new Date(b.createdAt || 0));
|
|
337
|
+
const sorted = [...messages].sort((a, b) => +new Date(a.createdAt || 0) - +new Date(b.createdAt || 0));
|
|
336
338
|
// An option-prompt is answerable only while it is the newest message
|
|
337
339
|
// in its thread (any later message locks it). Map each thread to its
|
|
338
340
|
// last message id, and each prompt_id to the owner's chosen text.
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* v1.2.0 -- 2026-05-22 -- Fix: use camelCase field names from API (createdAt, metadata.tokensUsed)
|
|
17
17
|
* v1.1.0 -- 2026-05-22 -- Show timestamp on messages, sort oldest-first (chat-style)
|
|
18
18
|
* v1.0.0 -- 2026-05-22 -- Initial creation for Agent Dashboard Phase 3
|
|
19
|
+
* v1.3.1 -- 2026-06-19 -- JSDoc type annotations for frontend type-checking
|
|
19
20
|
*/
|
|
20
21
|
import { h } from 'preact';
|
|
21
22
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
@@ -262,7 +263,7 @@ export default function AgentMessagesSubtab({ agentName, session, showToast }) {
|
|
|
262
263
|
const lastSeen = null; // TODO Phase 2+: derive from agent.last_seen
|
|
263
264
|
|
|
264
265
|
// Oldest-first (chat order).
|
|
265
|
-
const sorted = [...messages].sort((a, b) => new Date(a.createdAt || 0) - new Date(b.createdAt || 0));
|
|
266
|
+
const sorted = [...messages].sort((a, b) => +new Date(a.createdAt || 0) - +new Date(b.createdAt || 0));
|
|
266
267
|
// Latest message id per thread -> an option-prompt is answerable only while it
|
|
267
268
|
// is the newest message in its thread (any later message locks it).
|
|
268
269
|
const lastIdByThread = {};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @version-history
|
|
5
5
|
* v1.1.0 — 2026-03-19 — Add launch button to My Apps list
|
|
6
6
|
* v1.0.0 — 2026-03-17 — Refactor: replace inline styles with CSS utility classes (card-h3, text-caption, etc.)
|
|
7
|
+
* v1.1.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
7
8
|
*/
|
|
8
9
|
import { h } from 'preact';
|
|
9
10
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
@@ -42,7 +43,7 @@ export default function AppsTab({ session, showToast, onStats }) {
|
|
|
42
43
|
|
|
43
44
|
async function handleUpload(file, screenshot, accessCode) {
|
|
44
45
|
if (!file) { showToast(t('profile.apps.selectFile'), true); return; }
|
|
45
|
-
const readFile = (f) => new Promise(res => { const r = new FileReader(); r.onload = () => res(r.result.split(',')[1]); r.readAsDataURL(f); });
|
|
46
|
+
const readFile = (f) => new Promise(res => { const r = new FileReader(); r.onload = () => res(/** @type {string} */ (r.result).split(',')[1]); r.readAsDataURL(f); });
|
|
46
47
|
const contentBase64 = await readFile(file);
|
|
47
48
|
const opts = {};
|
|
48
49
|
if (accessCode) opts.accessCode = accessCode;
|
|
@@ -34,6 +34,9 @@ export default function BoardsTab({ session, showToast }) {
|
|
|
34
34
|
const [boardView, setBoardView] = useState(null);
|
|
35
35
|
const [brdSubTab, setBrdSubTab] = useState('mine');
|
|
36
36
|
const [showBrdForm, setShowBrdForm] = useState(false);
|
|
37
|
+
// Refs used by the board-detail view below — declared unconditionally (Rules of Hooks).
|
|
38
|
+
const postRef = useRef(null);
|
|
39
|
+
const memberInputRef = useRef(null);
|
|
37
40
|
|
|
38
41
|
useEffect(() => {
|
|
39
42
|
if (session) loadMyData();
|
|
@@ -176,8 +179,6 @@ export default function BoardsTab({ session, showToast }) {
|
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
if (boardView) {
|
|
179
|
-
const postRef = useRef(null);
|
|
180
|
-
const memberInputRef = useRef(null);
|
|
181
182
|
const bd = boardView.boardData;
|
|
182
183
|
const showMembers = bd && bd.visibility === 'shared' && isBoardOwner(bd);
|
|
183
184
|
return html`
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - renderStep4 — Step 4 UI (Synthesis — grouped proposals + A/B/C options)
|
|
15
15
|
* @version-history
|
|
16
16
|
* v1.0.0 — 2026-03-29 — Initial V2 implementation
|
|
17
|
+
* v1.0.1 — 2026-06-19 — lint fixes (misleading-char-class/unused-expression/empty-block)
|
|
17
18
|
*/
|
|
18
19
|
import { h } from 'preact';
|
|
19
20
|
import { useState, useEffect, useCallback } from 'preact/hooks';
|
|
@@ -40,7 +41,7 @@ import { getBatch, updateBatch, createVersion } from '/js/services/calibrator.js
|
|
|
40
41
|
|
|
41
42
|
// ── Helpers ──
|
|
42
43
|
|
|
43
|
-
async function callModel(projectId, prompt, modelId, { retries = 1, temperature, top_p, max_tokens } = {}) {
|
|
44
|
+
async function callModel(projectId, prompt, modelId, { retries = 1, temperature, top_p, max_tokens } = /** @type {{ retries?: number, temperature?: number, top_p?: number, max_tokens?: number }} */ ({})) {
|
|
44
45
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
45
46
|
const controller = new AbortController();
|
|
46
47
|
const timeoutId = setTimeout(() => controller.abort(), 1_800_000); // 30 min
|
|
@@ -436,7 +437,7 @@ export default function BatchCard({ batchSummary, index, projectId, project, cur
|
|
|
436
437
|
const { getVersion } = await import('/js/services/calibrator.js');
|
|
437
438
|
const ver = await getVersion(projectId, batchVersion);
|
|
438
439
|
if (ver?.prompt) batchPrompt = ver.prompt;
|
|
439
|
-
} catch {}
|
|
440
|
+
} catch { /* best effort — fall through to the no-prompt guard below */ }
|
|
440
441
|
}
|
|
441
442
|
if (!batchPrompt) { showToast?.('Could not load prompt for this batch\'s version', true); return; }
|
|
442
443
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @version-history
|
|
11
11
|
* v1.0.0 — 2026-03-10 — Initial data wallet tab implementation
|
|
12
12
|
* v1.1.0 — 2026-03-17 — Refactor: replace all inline styles with CSS classes
|
|
13
|
+
* v1.1.1 — 2026-06-19 — lint fixes (misleading-char-class/unused-expression/empty-block)
|
|
13
14
|
*/
|
|
14
15
|
import { h } from 'preact';
|
|
15
16
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
@@ -279,7 +280,7 @@ export default function DataWalletTab({ session, showToast }) {
|
|
|
279
280
|
<td><input type="checkbox" checked=${selectedConsents.has(cId)}
|
|
280
281
|
onChange=${(e) => {
|
|
281
282
|
const next = new Set(selectedConsents);
|
|
282
|
-
e.target.checked
|
|
283
|
+
if (e.target.checked) next.add(cId); else next.delete(cId);
|
|
283
284
|
setSelectedConsents(next);
|
|
284
285
|
}} /></td>
|
|
285
286
|
<td><span class="dw-code-accent">${escHtml(c.data_pattern || c.pattern || '-')}</span></td>
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* v1.4.0 — 2026-06-02 — Component unification (#11): all six extension/instance
|
|
24
24
|
* status dots use the canonical <StatusDot> instead of bespoke .ext-status-dot
|
|
25
25
|
* (which had hardcoded #4ade80/#9ca3af — now tokenized via the component).
|
|
26
|
+
* v1.4.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
26
27
|
*/
|
|
27
28
|
import { h } from 'preact';
|
|
28
29
|
import { useState, useEffect } from 'preact/hooks';
|
|
@@ -577,18 +578,18 @@ export default function ExtensionsTab({ session, showToast }) {
|
|
|
577
578
|
try {
|
|
578
579
|
let manifest = '';
|
|
579
580
|
if (manifestMode === 'upload') {
|
|
580
|
-
const fileInput = document.getElementById('ext-manifest-file');
|
|
581
|
+
const fileInput = /** @type {HTMLInputElement} */ (document.getElementById('ext-manifest-file'));
|
|
581
582
|
if (!fileInput?.files[0]) throw new Error('No manifest file selected');
|
|
582
583
|
manifest = await fileInput.files[0].text();
|
|
583
584
|
} else {
|
|
584
|
-
const textarea = document.getElementById('ext-manifest-text');
|
|
585
|
+
const textarea = /** @type {HTMLInputElement} */ (document.getElementById('ext-manifest-text'));
|
|
585
586
|
manifest = textarea?.value || '';
|
|
586
587
|
if (!manifest.trim()) throw new Error('Manifest is empty');
|
|
587
588
|
}
|
|
588
589
|
|
|
589
590
|
const libs = {};
|
|
590
591
|
if (libMode === 'upload') {
|
|
591
|
-
const libInput = document.getElementById('ext-lib-files');
|
|
592
|
+
const libInput = /** @type {HTMLInputElement} */ (document.getElementById('ext-lib-files'));
|
|
592
593
|
if (libInput?.files) {
|
|
593
594
|
for (const f of libInput.files) {
|
|
594
595
|
libs[f.name] = await f.text();
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* v1.1.0 — 2026-03-17 — Replace inline styles with CSS classes
|
|
7
7
|
* v1.2.0 — 2026-06-02 — Component unification (#11): peer online/offline dot
|
|
8
8
|
* uses canonical <StatusDot> (alive/dead) instead of bespoke .peer-dot.
|
|
9
|
+
* v1.3.0 — 2026-06-19 — Show peer tier (visiting/member/genesis) + availability
|
|
10
|
+
* (temporary/permanent) pills next to the status (visiting-node feature).
|
|
9
11
|
*/
|
|
10
12
|
import { h } from 'preact';
|
|
11
13
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
@@ -56,6 +58,8 @@ export default function FederationTab({ session, showToast }) {
|
|
|
56
58
|
<div class="card-subtitle">${escHtml(p.url || '')}</div>
|
|
57
59
|
</div>
|
|
58
60
|
<div class="peer-status">
|
|
61
|
+
<span class="badge ${(p.tier || 'member') === 'visiting' ? 'badge-info' : (p.tier || 'member') === 'genesis' ? 'badge-info' : 'badge-success'}">${t('profile.federation.tier_' + (p.tier || 'member')) || (p.tier || 'member')}</span>
|
|
62
|
+
${p.availability && p.availability !== 'unknown' ? html`<span class="badge ${p.availability === 'permanent' ? 'badge-success' : 'badge-info'}">${t('profile.federation.avail_' + p.availability) || p.availability}</span>` : null}
|
|
59
63
|
<${StatusDot} status=${alive ? 'alive' : 'dead'} />
|
|
60
64
|
<span class="fed-status-text ${alive ? 'online' : 'offline'}">${alive ? t('profile.federation.online') : t('profile.federation.offline')}</span>
|
|
61
65
|
</div>
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* @version-history
|
|
28
28
|
* v1.0.0 — 2026-03-22 — Extracted from foundry-tab.js ProjectDashboard
|
|
29
29
|
* v2.0.0 — 2026-03-26 — Wire multi-pass flow: runComponentPasses for extension/cortex/app
|
|
30
|
+
* v2.0.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
30
31
|
*/
|
|
31
32
|
import { t } from '/js/i18n.js';
|
|
32
33
|
import { apiPost, apiDelete } from '/js/api.js';
|
|
@@ -206,7 +207,7 @@ export function useAutopilot(core, autopilotState, projectId, orSettings, sessio
|
|
|
206
207
|
* @param {string} cid - Component ID
|
|
207
208
|
* @param {Object} project - Project object (with blueprint)
|
|
208
209
|
* @param {Object} interviewSpec - Interview spec
|
|
209
|
-
* @returns {{ success: boolean, content: string|null, updated: Object }} - Final result
|
|
210
|
+
* @returns {Promise<{ success: boolean, content: string|null, updated: Object }>} - Final result
|
|
210
211
|
*/
|
|
211
212
|
async function runComponentPasses(comp, cid, project, interviewSpec) {
|
|
212
213
|
const blueprint = project.blueprint;
|
|
@@ -734,7 +735,7 @@ export function useAutopilot(core, autopilotState, projectId, orSettings, sessio
|
|
|
734
735
|
await writeProjectLog(projectId, 'extension_probe_start', { meta: { component: comp.label, extensionName: updated.registeredAs, scenarios: probeScenarios.length, by: 'autopilot' } });
|
|
735
736
|
|
|
736
737
|
const probeResp = await probeExtension(projectId, updated.registeredAs, probeScenarios);
|
|
737
|
-
const probeResults = probeResp?.data?.results || [];
|
|
738
|
+
const probeResults = /** @type {any} */ (probeResp)?.data?.results || [];
|
|
738
739
|
|
|
739
740
|
// Save probe results + context bundle — downstream prompts will inject these
|
|
740
741
|
const contextBundle = createBundle(updated, probeResults);
|
|
@@ -131,7 +131,7 @@ export function getWorkflowStep(component, validationResult, result) {
|
|
|
131
131
|
|
|
132
132
|
/** Small circle-with-arrow SVG placed inline next to the current action target.
|
|
133
133
|
* @param {Object} props
|
|
134
|
-
* @param {'right'|'down'} [props.direction='right']
|
|
134
|
+
* @param {'right'|'down'} [props.direction='right'] - arrow direction
|
|
135
135
|
*/
|
|
136
136
|
function StepArrow({ direction = 'right' } = {}) {
|
|
137
137
|
const chevron = direction === 'down'
|
|
@@ -162,7 +162,7 @@ export function getWorkflowStep(component, validationResult, result) {
|
|
|
162
162
|
|
|
163
163
|
/** Small circle-with-arrow SVG placed inline next to the current action target.
|
|
164
164
|
* @param {Object} props
|
|
165
|
-
* @param {'right'|'down'} [props.direction='right']
|
|
165
|
+
* @param {'right'|'down'} [props.direction='right'] - arrow direction
|
|
166
166
|
*/
|
|
167
167
|
function StepArrow({ direction = 'right' } = {}) {
|
|
168
168
|
const chevron = direction === 'down'
|
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
* @structure InboxTab (default) · Composer (Toast UI) · MessageBubble · Avatar · helpers
|
|
12
12
|
* @usage Lazy-loaded profile tab; registered in profile.js TABS as id `messages`.
|
|
13
13
|
* @version-history
|
|
14
|
+
* v1.3.0 -- 2026-06-19 -- Show a presence dot next to peers (request rows, conversation list,
|
|
15
|
+
* thread header) via the shared <PresenceDot>.
|
|
14
16
|
* v1.2.0 -- 2026-06-16 -- Composer upgraded to the shared Toast UI editor (parity with the
|
|
15
17
|
* workspace document editor) + markdown-preview fallback.
|
|
16
18
|
* v1.1.0 -- 2026-06-16 -- Redesigned as a proper messenger (avatars, bubbles, ticks, dividers).
|
|
17
19
|
* v1.0.0 -- 2026-06-16 -- Initial creation for user-to-user messaging (layer 5).
|
|
20
|
+
* v1.3.1 -- 2026-06-19 -- JSDoc type annotations for frontend type-checking
|
|
18
21
|
*/
|
|
19
22
|
import { h } from 'preact';
|
|
20
23
|
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
@@ -24,6 +27,7 @@ import { t, getLocale } from '/js/i18n.js';
|
|
|
24
27
|
import { escHtml } from '/js/utils.js';
|
|
25
28
|
import { Markdown } from '/components/Markdown.js';
|
|
26
29
|
import { minidenticon } from '/lib/minidenticons.min.js';
|
|
30
|
+
import { PresenceDot } from '/components/PresenceDot.js';
|
|
27
31
|
import * as messages from '/js/services/messages.js';
|
|
28
32
|
|
|
29
33
|
/* Lazy-load the vendored Toast UI Editor (MIT, /lib/toastui/) — the same editor the workspace
|
|
@@ -313,7 +317,7 @@ export default function InboxTab({ showToast }) {
|
|
|
313
317
|
<div class="inbox-request-top">
|
|
314
318
|
<${Avatar} seed=${r.contactId} size=${36} />
|
|
315
319
|
<div class="inbox-request-id">
|
|
316
|
-
<div class="inbox-name">${escHtml(peerName(r.contactId))}
|
|
320
|
+
<div class="inbox-name">${escHtml(peerName(r.contactId))} <${PresenceDot} ghii=${r.contactId} /></div>
|
|
317
321
|
<div class="inbox-sub">${escHtml(r.contactId)}</div>
|
|
318
322
|
</div>
|
|
319
323
|
</div>
|
|
@@ -332,7 +336,7 @@ export default function InboxTab({ showToast }) {
|
|
|
332
336
|
<${Avatar} seed=${c.peerGhii} size=${40} />
|
|
333
337
|
<div class="inbox-conv-main">
|
|
334
338
|
<div class="inbox-conv-line1">
|
|
335
|
-
<span class="inbox-name">${escHtml(peerName(c.peerGhii))}
|
|
339
|
+
<span class="inbox-name">${escHtml(peerName(c.peerGhii))} <${PresenceDot} ghii=${c.peerGhii} /></span>
|
|
336
340
|
<span class="inbox-conv-time">${c.updatedAt ? timeShort(c.updatedAt) : ''}</span>
|
|
337
341
|
</div>
|
|
338
342
|
<div class="inbox-conv-line2">
|
|
@@ -350,7 +354,7 @@ export default function InboxTab({ showToast }) {
|
|
|
350
354
|
<div class="inbox-thread-head">
|
|
351
355
|
<${Avatar} seed=${activeConv.peerGhii} size=${36} />
|
|
352
356
|
<div class="inbox-thread-id">
|
|
353
|
-
<div class="inbox-name">${escHtml(peerName(activeConv.peerGhii))}
|
|
357
|
+
<div class="inbox-name">${escHtml(peerName(activeConv.peerGhii))} <${PresenceDot} ghii=${activeConv.peerGhii} label=${true} /></div>
|
|
354
358
|
<div class="inbox-sub">${escHtml(activeConv.peerGhii)}</div>
|
|
355
359
|
</div>
|
|
356
360
|
</div>
|
|
@@ -35,8 +35,8 @@ const PANELS = {
|
|
|
35
35
|
|
|
36
36
|
export function InlinePanel({ panelId, onClose, switchTab, session }) {
|
|
37
37
|
const cfg = PANELS[panelId];
|
|
38
|
-
if (!cfg) return null;
|
|
39
38
|
|
|
39
|
+
// Hooks must run unconditionally before any early return (Rules of Hooks).
|
|
40
40
|
const panelRef = useRef(null);
|
|
41
41
|
|
|
42
42
|
/* Smooth scroll into view after opening */
|
|
@@ -48,6 +48,8 @@ export function InlinePanel({ panelId, onClose, switchTab, session }) {
|
|
|
48
48
|
}
|
|
49
49
|
}, [panelId]);
|
|
50
50
|
|
|
51
|
+
if (!cfg) return null;
|
|
52
|
+
|
|
51
53
|
return html`
|
|
52
54
|
<div class="pf-inline-panel open" ref=${panelRef}>
|
|
53
55
|
<div class="pf-inline-panel-header">
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* pf-sharing-box, pf-sharing-heading, kpkg-detail-loading). Replace inline
|
|
19
19
|
* visibility pill with shared VisibilityPill component. Replace hardcoded English
|
|
20
20
|
* strings with i18n t() calls.
|
|
21
|
+
* v1.0.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
21
22
|
*/
|
|
22
23
|
import { h } from 'preact';
|
|
23
24
|
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
@@ -393,7 +394,7 @@ export default function KnowledgeTab({ session, showToast, onStats }) {
|
|
|
393
394
|
if (!el) {
|
|
394
395
|
const all = document.querySelectorAll('[data-entry-key]');
|
|
395
396
|
for (const candidate of all) {
|
|
396
|
-
if (candidate.dataset.entryKey.endsWith('/' + entryKey)) { el = candidate; break; }
|
|
397
|
+
if (/** @type {HTMLElement} */ (candidate).dataset.entryKey.endsWith('/' + entryKey)) { el = candidate; break; }
|
|
397
398
|
}
|
|
398
399
|
}
|
|
399
400
|
if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'center' }); el.classList.add('kpkg-entry-highlight'); setTimeout(() => el.classList.remove('kpkg-entry-highlight'), 1500); }
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* AppStrip — home/section sub-components
|
|
16
16
|
* - LandingPage — main orchestrator (default export)
|
|
17
17
|
* @version-history
|
|
18
|
+
* v3.3.0 — 2026-06-19 — Add the PresenceControl card to the home dashboard (own availability:
|
|
19
|
+
* auto/manual status + who-can-see visibility), previewing the shared <PresenceDot>.
|
|
18
20
|
* v3.2.0 — 2026-06-10 — Sidebar reorg: groups follow the information-refinement pipeline
|
|
19
21
|
* (Information / Automation / Activity / Build & Share / Account / Infrastructure) —
|
|
20
22
|
* Daily/Personal/Technical are gone. Pinned section under Home (pin-on-hover 📌, max 5,
|
|
@@ -65,7 +67,9 @@ import * as orgService from '/js/services/organisms.js';
|
|
|
65
67
|
import { listRecents } from '/js/recents.js';
|
|
66
68
|
import { getMemory, createMemory } from '/js/services/memory.js';
|
|
67
69
|
import { listInbox } from '/js/services/messages.js';
|
|
70
|
+
import { getMyPresence, setMyPresence } from '/js/services/presence.js';
|
|
68
71
|
import { Spinner } from './shared.js';
|
|
72
|
+
import { PresenceDot } from '/components/PresenceDot.js';
|
|
69
73
|
import { minidenticon } from '/lib/minidenticons.min.js';
|
|
70
74
|
|
|
71
75
|
/* ───── Small time helpers (reuse the organisms rel-time keys) ───── */
|
|
@@ -515,6 +519,88 @@ function AgentsCard({ owner }) {
|
|
|
515
519
|
`;
|
|
516
520
|
}
|
|
517
521
|
|
|
522
|
+
/* "Presence" — the owner's own availability control: status source (auto/manual),
|
|
523
|
+
* chosen status, and who-can-see visibility. One self-contained card; the dot it
|
|
524
|
+
* previews is the same <PresenceDot> rendered next to people everywhere else. */
|
|
525
|
+
function PresenceControl() {
|
|
526
|
+
const [cfg, setCfg] = useState(null);
|
|
527
|
+
const [status, setStatus] = useState('unknown');
|
|
528
|
+
const [saving, setSaving] = useState(false);
|
|
529
|
+
|
|
530
|
+
const load = useCallback(async () => {
|
|
531
|
+
try {
|
|
532
|
+
const r = await getMyPresence();
|
|
533
|
+
if (r?.data) { setCfg(r.data.config); setStatus(r.data.status || 'unknown'); }
|
|
534
|
+
} catch { /* control stays hidden until it loads */ }
|
|
535
|
+
}, []);
|
|
536
|
+
useEffect(() => { load(); }, [load]);
|
|
537
|
+
|
|
538
|
+
const save = async (partial) => {
|
|
539
|
+
if (!cfg) return;
|
|
540
|
+
const optimistic = { ...cfg, ...partial };
|
|
541
|
+
setCfg(optimistic);
|
|
542
|
+
setSaving(true);
|
|
543
|
+
try {
|
|
544
|
+
const r = await setMyPresence(partial);
|
|
545
|
+
if (r?.data) { setCfg(r.data.config); setStatus(r.data.status || 'unknown'); }
|
|
546
|
+
} catch { setCfg(cfg); /* revert */ }
|
|
547
|
+
setSaving(false);
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
if (!cfg) return null;
|
|
551
|
+
|
|
552
|
+
return html`
|
|
553
|
+
<div class="pf-presence-card">
|
|
554
|
+
<div class="pf-presence-head">
|
|
555
|
+
<div>
|
|
556
|
+
<div class="section-title">${t('presence.control.title')}</div>
|
|
557
|
+
<div class="section-desc">${t('presence.control.desc')}</div>
|
|
558
|
+
</div>
|
|
559
|
+
<${PresenceDot} status=${status} size="md" label=${true} />
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
<div class="pf-presence-row">
|
|
563
|
+
<label class="pf-presence-label">${t('presence.control.modeLabel')}</label>
|
|
564
|
+
<div class="pf-presence-modes">
|
|
565
|
+
<button class=${'pf-presence-pill' + (cfg.mode === 'auto' ? ' pf-presence-pill--on' : '')}
|
|
566
|
+
disabled=${saving} onClick=${() => save({ mode: 'auto' })}>${t('presence.control.modeAuto')}</button>
|
|
567
|
+
<button class=${'pf-presence-pill' + (cfg.mode === 'manual' ? ' pf-presence-pill--on' : '')}
|
|
568
|
+
disabled=${saving} onClick=${() => save({ mode: 'manual' })}>${t('presence.control.modeManual')}</button>
|
|
569
|
+
</div>
|
|
570
|
+
</div>
|
|
571
|
+
|
|
572
|
+
${cfg.mode === 'auto' ? html`
|
|
573
|
+
<div class="pf-presence-hint">${t('presence.control.modeAutoHint')}</div>
|
|
574
|
+
` : html`
|
|
575
|
+
<div class="pf-presence-row">
|
|
576
|
+
<label class="pf-presence-label" for="pf-presence-status">${t('presence.control.statusLabel')}</label>
|
|
577
|
+
<select id="pf-presence-status" class="pf-edit-select" value=${cfg.status} disabled=${saving}
|
|
578
|
+
onChange=${(e) => save({ status: e.target.value })}>
|
|
579
|
+
<option value="available">${t('presence.status.available')}</option>
|
|
580
|
+
<option value="busy">${t('presence.status.busy')}</option>
|
|
581
|
+
<option value="away">${t('presence.status.away')}</option>
|
|
582
|
+
<option value="invisible">${t('presence.status.invisible')}</option>
|
|
583
|
+
</select>
|
|
584
|
+
</div>
|
|
585
|
+
`}
|
|
586
|
+
|
|
587
|
+
<div class="pf-presence-row">
|
|
588
|
+
<label class="pf-presence-label" for="pf-presence-vis">${t('presence.control.visibilityLabel')}</label>
|
|
589
|
+
<select id="pf-presence-vis" class="pf-edit-select" value=${cfg.visibility} disabled=${saving}
|
|
590
|
+
onChange=${(e) => save({ visibility: e.target.value })}>
|
|
591
|
+
<option value="everyone">${t('presence.control.visEveryone')}</option>
|
|
592
|
+
<option value="contacts">${t('presence.control.visContacts')}</option>
|
|
593
|
+
<option value="nobody">${t('presence.control.visNobody')}</option>
|
|
594
|
+
</select>
|
|
595
|
+
</div>
|
|
596
|
+
<div class="pf-presence-hint">
|
|
597
|
+
${cfg.visibility === 'everyone' ? t('presence.control.visEveryoneHint')
|
|
598
|
+
: cfg.visibility === 'contacts' ? t('presence.control.visContactsHint') : ''}
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
`;
|
|
602
|
+
}
|
|
603
|
+
|
|
518
604
|
/* ───── Sub-components ───── */
|
|
519
605
|
|
|
520
606
|
function ProfileCard({ tier, stats, session, onEditProfile, switchTab }) {
|
|
@@ -771,6 +857,7 @@ const SIDEBAR_GROUPS = [
|
|
|
771
857
|
{ titleKey: 'profile.landing.menuInformation', items: [ // raw → curated → governed
|
|
772
858
|
{ id: 'organisms', icon: '\u{1F3E2}', labelKey: 'profile.tabs.organisms' },
|
|
773
859
|
{ id: 'memory', icon: '\u{1F9E0}', labelKey: 'profile.tabs.memory' },
|
|
860
|
+
{ id: 'notebook', icon: '\u{1F4D3}', labelKey: 'profile.tabs.notebook' },
|
|
774
861
|
{ id: 'knowledge', icon: '\u{1F4DA}', labelKey: 'knowledge.tabLabel' },
|
|
775
862
|
{ id: 'boards', icon: '\u{1F4CB}', labelKey: 'profile.tabs.boards' },
|
|
776
863
|
] },
|
|
@@ -1035,6 +1122,7 @@ export default function LandingPage({ tier, stats, session, navigate, showToast,
|
|
|
1035
1122
|
<${ProfileCard} tier=${tier} stats=${stats} session=${session}
|
|
1036
1123
|
onEditProfile=${() => setEditOpen(true)}
|
|
1037
1124
|
switchTab=${(id) => open(id, 'main')} />
|
|
1125
|
+
<${PresenceControl} />
|
|
1038
1126
|
${isNew ? html`<${HeroOnboarding} switchTab=${(id) => open(id, 'main')} />` : null}
|
|
1039
1127
|
${(isNew || isActive) ? html`<${KnowledgeCallout} switchTab=${() => open('knowledge', 'main')} />` : null}
|
|
1040
1128
|
${isNew ? html`<${GhostTiles} switchTab=${() => open('packages', 'main')} />` : null}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
* group-share brought into Memory; "Create a group →" when none exist). Plus bulk edit:
|
|
34
34
|
* per-row checkboxes + a bulk bar (change visibility incl. group / delete with confirm /
|
|
35
35
|
* clear). The detail-row select and edit-modal select remain as alternate paths.
|
|
36
|
+
* v2.2.1 — 2026-06-19 — JSDoc type annotations for frontend type-checking
|
|
36
37
|
*/
|
|
37
38
|
import { h } from 'preact';
|
|
38
39
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
@@ -279,7 +280,7 @@ export default function MemoryTab({ session, showToast, onStats }) {
|
|
|
279
280
|
function readFileAsBase64(file) {
|
|
280
281
|
return new Promise((resolve, reject) => {
|
|
281
282
|
const reader = new FileReader();
|
|
282
|
-
reader.onload = () => resolve(reader.result.split(',')[1]);
|
|
283
|
+
reader.onload = () => resolve(/** @type {string} */ (reader.result).split(',')[1]);
|
|
283
284
|
reader.onerror = reject;
|
|
284
285
|
reader.readAsDataURL(file);
|
|
285
286
|
});
|
|
@@ -287,13 +288,13 @@ export default function MemoryTab({ session, showToast, onStats }) {
|
|
|
287
288
|
|
|
288
289
|
async function handleDownloadFile(key) {
|
|
289
290
|
try {
|
|
290
|
-
const headers = {};
|
|
291
|
+
const headers = /** @type {Record<string,string>} */ ({});
|
|
291
292
|
if (window.AIMEAT?.auth?.hasSession) {
|
|
292
293
|
const session = window.AIMEAT.auth.getSession();
|
|
293
294
|
if (session?.jwt) headers['Authorization'] = 'Bearer ' + session.jwt;
|
|
294
295
|
}
|
|
295
296
|
const resp = await fetch(`${NODE_URL}/v1/memory/files/${encodeURIComponent(key)}`, { headers });
|
|
296
|
-
if (!resp.ok) throw new Error(resp.status);
|
|
297
|
+
if (!resp.ok) throw new Error(String(resp.status));
|
|
297
298
|
const blob = await resp.blob();
|
|
298
299
|
const url = URL.createObjectURL(blob);
|
|
299
300
|
const a = document.createElement('a');
|
|
@@ -433,9 +434,9 @@ export default function MemoryTab({ session, showToast, onStats }) {
|
|
|
433
434
|
const sorted = [...entries];
|
|
434
435
|
switch (sortBy) {
|
|
435
436
|
case 'updated':
|
|
436
|
-
return sorted.sort((a, b) => new Date(b.updated_at || 0) - new Date(a.updated_at || 0));
|
|
437
|
+
return sorted.sort((a, b) => +new Date(b.updated_at || 0) - +new Date(a.updated_at || 0));
|
|
437
438
|
case 'created':
|
|
438
|
-
return sorted.sort((a, b) => new Date(b.created_at || 0) - new Date(a.created_at || 0));
|
|
439
|
+
return sorted.sort((a, b) => +new Date(b.created_at || 0) - +new Date(a.created_at || 0));
|
|
439
440
|
case 'alpha':
|
|
440
441
|
return sorted.sort((a, b) => a.key.localeCompare(b.key));
|
|
441
442
|
default:
|