@songsid/agend 2.2.0-beta.1 → 2.2.0-beta.10
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 +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-cli-instructions.md +16 -9
- package/dist/agent-cli.js +15 -7
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +21 -9
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.d.ts +47 -0
- package/dist/agent-whats-new.js +147 -0
- package/dist/agent-whats-new.js.map +1 -0
- package/dist/auth-api.d.ts +2 -2
- package/dist/auth-api.js +4 -2
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +3 -0
- package/dist/backend/antigravity.js +9 -0
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-carry.d.ts +22 -0
- package/dist/backend/claude-carry.js +170 -0
- package/dist/backend/claude-carry.js.map +1 -0
- package/dist/backend/claude-code.d.ts +65 -2
- package/dist/backend/claude-code.js +226 -33
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +33 -0
- package/dist/backend/codex-metadata.js +122 -18
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex.d.ts +3 -0
- package/dist/backend/codex.js +17 -1
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +40 -3
- package/dist/backend/credential-profile.js +113 -5
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +1 -1
- package/dist/backend/effort-metadata.js +3 -2
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.d.ts +4 -0
- package/dist/backend/grok.js +14 -0
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.d.ts +5 -0
- package/dist/backend/kiro-engine-ledger.js +20 -0
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-identity.d.ts +6 -0
- package/dist/backend/kiro-identity.js +19 -5
- package/dist/backend/kiro-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +39 -3
- package/dist/backend/kiro.js +143 -19
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +33 -0
- package/dist/backend/launch-effort.js +123 -0
- package/dist/backend/launch-effort.js.map +1 -0
- package/dist/backend/muse.d.ts +84 -0
- package/dist/backend/muse.js +449 -53
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/types.d.ts +33 -4
- package/dist/backend/types.js +2 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-command.d.ts +91 -0
- package/dist/backend-command.js +122 -0
- package/dist/backend-command.js.map +1 -0
- package/dist/background-work-ended.d.ts +18 -0
- package/dist/background-work-ended.js +30 -0
- package/dist/background-work-ended.js.map +1 -0
- package/dist/cache-service.d.ts +2 -0
- package/dist/cache-service.js +2 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +24 -1
- package/dist/channel/adapters/discord.js +87 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +24 -2
- package/dist/channel/adapters/telegram.js +118 -20
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +9 -1
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +11 -0
- package/dist/channel/mcp-tools.js +24 -13
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-edit-errors.d.ts +5 -0
- package/dist/channel/message-edit-errors.js +24 -0
- package/dist/channel/message-edit-errors.js.map +1 -0
- package/dist/channel/telegram-markdown.d.ts +6 -0
- package/dist/channel/telegram-markdown.js +104 -0
- package/dist/channel/telegram-markdown.js.map +1 -0
- package/dist/channel/tool-router.js +9 -3
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +39 -3
- package/dist/cli.js +133 -28
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +2 -2
- package/dist/command-table.js +6 -3
- package/dist/command-table.js.map +1 -1
- package/dist/config-validator.js +59 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/cross-instance-envelope.d.ts +15 -2
- package/dist/cross-instance-envelope.js +29 -5
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/daemon.d.ts +156 -1
- package/dist/daemon.js +764 -89
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +62 -7
- package/dist/delivery-outbox.js +309 -22
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +18 -1
- package/dist/delivery-reconciliation.js +67 -2
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/fleet-context.d.ts +10 -1
- package/dist/fleet-manager.d.ts +345 -10
- package/dist/fleet-manager.js +1868 -174
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/backend-providers/SKILL.md +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +92 -21
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +27 -3
- package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +8 -8
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +5 -5
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +4 -4
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +13 -13
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +3 -2
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +6 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +9 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +8 -2
- package/dist/general-knowledge/skills/scheduling/SKILL.md +5 -3
- package/dist/general-knowledge/skills/session-management/SKILL.md +6 -5
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +2 -2
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +8 -3
- package/dist/general-knowledge/steering/core-rules.md +8 -7
- package/dist/host-memory.d.ts +10 -0
- package/dist/host-memory.js +33 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/human-delivery-receipts.d.ts +83 -0
- package/dist/human-delivery-receipts.js +194 -0
- package/dist/human-delivery-receipts.js.map +1 -0
- package/dist/instance-avatar.d.ts +36 -0
- package/dist/instance-avatar.js +57 -0
- package/dist/instance-avatar.js.map +1 -0
- package/dist/instance-config-impact.js +6 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +29 -6
- package/dist/instance-lifecycle.js +79 -28
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +3 -1
- package/dist/instructions.js +11 -8
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-log-gate.d.ts +42 -0
- package/dist/kiro-log-gate.js +39 -0
- package/dist/kiro-log-gate.js.map +1 -0
- package/dist/locale.js +200 -44
- package/dist/locale.js.map +1 -1
- package/dist/log-service.d.ts +99 -0
- package/dist/log-service.js +243 -0
- package/dist/log-service.js.map +1 -0
- package/dist/log-steps.d.ts +169 -0
- package/dist/log-steps.js +858 -0
- package/dist/log-steps.js.map +1 -0
- package/dist/login-controller.d.ts +20 -3
- package/dist/login-controller.js +71 -19
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.d.ts +5 -2
- package/dist/login-flows.js +5 -4
- package/dist/login-flows.js.map +1 -1
- package/dist/memory-pressure.d.ts +13 -1
- package/dist/memory-pressure.js +50 -10
- package/dist/memory-pressure.js.map +1 -1
- package/dist/needs-you-hub.js +2 -0
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +6 -0
- package/dist/needs-you-live.js +23 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.js.map +1 -1
- package/dist/outbound-handlers.d.ts +100 -0
- package/dist/outbound-handlers.js +263 -96
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +26 -15
- package/dist/outbound-schemas.js +24 -7
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-link-progress.d.ts +1 -1
- package/dist/public-link-progress.js +8 -2
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.d.ts +101 -0
- package/dist/public-preview.js +236 -0
- package/dist/public-preview.js.map +1 -0
- package/dist/public-web-gateway.js +11 -4
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +24 -1
- package/dist/public-web-link.js +63 -9
- package/dist/public-web-link.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +3 -0
- package/dist/reply-buttons-controller.js +3 -2
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/restart-guard.d.ts +6 -3
- package/dist/restart-guard.js +6 -3
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +33 -0
- package/dist/restart-progress.js +30 -0
- package/dist/restart-progress.js.map +1 -1
- package/dist/service-activation.d.ts +15 -7
- package/dist/service-activation.js +46 -29
- package/dist/service-activation.js.map +1 -1
- package/dist/service-installer.d.ts +31 -0
- package/dist/service-installer.js +41 -2
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +85 -25
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +72 -1
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +28 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.js +7 -0
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +1 -1
- package/dist/spawn-gate.js +5 -1
- package/dist/spawn-gate.js.map +1 -1
- package/dist/spawn-hold-reply.d.ts +12 -0
- package/dist/spawn-hold-reply.js +39 -0
- package/dist/spawn-hold-reply.js.map +1 -0
- package/dist/status-emojis.d.ts +10 -3
- package/dist/status-emojis.js +11 -2
- package/dist/status-emojis.js.map +1 -1
- package/dist/systemd-peer-bus.d.ts +95 -0
- package/dist/systemd-peer-bus.js +430 -0
- package/dist/systemd-peer-bus.js.map +1 -0
- package/dist/systemd-runtime.d.ts +27 -1
- package/dist/systemd-runtime.js +69 -7
- package/dist/systemd-runtime.js.map +1 -1
- package/dist/tips.js +4 -4
- package/dist/tips.js.map +1 -1
- package/dist/tool-progress.js +3 -2
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-commands.d.ts +42 -2
- package/dist/topic-commands.js +92 -7
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.d.ts +3 -3
- package/dist/transcript-delta-reader.js +8 -8
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.d.ts +80 -3
- package/dist/transcript-jsonl.js +147 -10
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.d.ts +19 -0
- package/dist/transcript-monitor.js +87 -15
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +78 -0
- package/dist/transcript-sources.js +375 -64
- package/dist/transcript-sources.js.map +1 -1
- package/dist/transcript-turns.d.ts +15 -2
- package/dist/transcript-turns.js +15 -2
- package/dist/transcript-turns.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -15
- package/dist/tunnel/cloudflared.js +36 -1
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +5 -1
- package/dist/tunnel/purpose-lane.js +14 -7
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +5 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/turn-resume.d.ts +2 -0
- package/dist/turn-resume.js +1 -1
- package/dist/turn-resume.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/ui/chat-commands.js +1 -0
- package/dist/ui/chat-emojis.js +33 -0
- package/dist/ui/chat-mentions.js +63 -0
- package/dist/ui/chat-render.js +42 -2
- package/dist/ui/chat-store.js +2 -2
- package/dist/ui/chat-strings.js +38 -20
- package/dist/ui/chat-thread.js +69 -12
- package/dist/ui/chat-time.js +80 -0
- package/dist/ui/panel-chat.js +39 -10
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +199 -57
- package/dist/ui/panel-log.js +428 -0
- package/dist/ui/panel-needs.js +6 -2
- package/dist/ui/panel-settings.js +137 -32
- package/dist/ui/preview-panel.js +55 -15
- package/dist/ui/preview-status.js +28 -0
- package/dist/ui/preview.js +44 -3
- package/dist/ui/settings-dialogs.js +7 -2
- package/dist/ui/settings-model.js +2 -1
- package/dist/ui/settings-strings.js +46 -4
- package/dist/ui/settings-token.js +1 -1
- package/dist/ui/shared/app-i18n.js +43 -17
- package/dist/ui/shared/app-prefs.js +250 -0
- package/dist/ui/shared/app-route.js +7 -2
- package/dist/ui/shared/app-shell.js +165 -8
- package/dist/ui/shared/app-store.js +5 -1
- package/dist/ui/shared/app-stream.js +23 -5
- package/dist/ui/shared/app.css +155 -22
- package/dist/ui/shared/app.js +11 -1
- package/dist/ui/shared/fonts/README.md +1 -1
- package/dist/ui/shared/header-tools.js +55 -5
- package/dist/ui/shared/instance-nav.js +241 -45
- package/dist/ui/shared/instance-switch.js +4 -4
- package/dist/ui/shared/panel-view.js +6 -0
- package/dist/ui/shared/signin.js +7 -7
- package/dist/ui/shared/theme.js +39 -7
- package/dist/ui/shared/tokens.css +1 -1
- package/dist/ui/shared/ui-icons.js +1 -0
- package/dist/ui/shared/usage-dialog.js +23 -5
- package/dist/ui/shared/view-strings.js +32 -4
- package/dist/ui/signin.html +1 -1
- package/dist/unrecognised-prompt.d.ts +23 -0
- package/dist/unrecognised-prompt.js +74 -0
- package/dist/unrecognised-prompt.js.map +1 -0
- package/dist/update-install.d.ts +28 -2
- package/dist/update-install.js +22 -4
- package/dist/update-install.js.map +1 -1
- package/dist/update-marker.d.ts +51 -0
- package/dist/update-marker.js +61 -0
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.d.ts +100 -0
- package/dist/update-preflight.js +264 -0
- package/dist/update-preflight.js.map +1 -0
- package/dist/updater-caller.d.ts +31 -0
- package/dist/updater-caller.js +109 -0
- package/dist/updater-caller.js.map +1 -0
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +1 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/providers.d.ts +34 -5
- package/dist/usage/providers.js +160 -27
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.d.ts +6 -2
- package/dist/usage/statusline-usage.js +10 -4
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.d.ts +1 -1
- package/dist/view-api.js +38 -8
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.d.ts +11 -0
- package/dist/wake-coordinator.js +38 -4
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-api.d.ts +49 -2
- package/dist/web-api.js +421 -31
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +2 -2
- package/dist/web-auth.js +9 -4
- package/dist/web-auth.js.map +1 -1
- package/dist/web-commands.d.ts +27 -4
- package/dist/web-commands.js +19 -4
- package/dist/web-commands.js.map +1 -1
- package/dist/web-host-guard.d.ts +3 -11
- package/dist/web-host-guard.js +3 -12
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-images.d.ts +47 -0
- package/dist/web-images.js +169 -0
- package/dist/web-images.js.map +1 -0
- package/dist/web-mentions.d.ts +44 -0
- package/dist/web-mentions.js +75 -0
- package/dist/web-mentions.js.map +1 -0
- package/dist/web-prefs.d.ts +63 -0
- package/dist/web-prefs.js +265 -0
- package/dist/web-prefs.js.map +1 -0
- package/dist/web-preview.d.ts +14 -1
- package/dist/web-preview.js +35 -13
- package/dist/web-preview.js.map +1 -1
- package/dist/web-reply-files.d.ts +45 -0
- package/dist/web-reply-files.js +223 -0
- package/dist/web-reply-files.js.map +1 -0
- package/dist/web-schedules.d.ts +12 -0
- package/dist/web-schedules.js +34 -0
- package/dist/web-schedules.js.map +1 -0
- package/dist/web-server-drain.d.ts +10 -0
- package/dist/web-server-drain.js +50 -0
- package/dist/web-server-drain.js.map +1 -0
- package/dist/web-session.d.ts +36 -1
- package/dist/web-session.js +53 -6
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +23 -0
- package/dist/web-settings-patch.js +77 -0
- package/dist/web-settings-patch.js.map +1 -0
- package/dist/web-shell-routes.d.ts +5 -1
- package/dist/web-shell-routes.js +10 -1
- package/dist/web-shell-routes.js.map +1 -1
- package/dist/web-upload.d.ts +17 -4
- package/dist/web-upload.js +64 -13
- package/dist/web-upload.js.map +1 -1
- package/dist/workflow-templates/default.md +1 -1
- package/package.json +1 -1
- package/templates/launchd.plist.ejs +3 -1
- package/templates/systemd.service.ejs +2 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// #1770: the time a chat line shows, read in the fleet's zone (the one chat-logs, fleet.log and the #1586 DMs use) —
|
|
2
|
+
// "17:38" today, "Yesterday 17:38", "10/11 17:38" earlier this year, "2025/10/11 17:38" before. The hour and minute keep
|
|
3
|
+
// the browser's own format (12- or 24-hour), as they always had. No imports: the thread, the preview panel and the
|
|
4
|
+
// tests read it as it is.
|
|
5
|
+
|
|
6
|
+
const cache = new Map();
|
|
7
|
+
/** One formatter per (kind, zone, locale): a thread may label 500 lines on every render. */
|
|
8
|
+
function fmt(kind, tz, locale) {
|
|
9
|
+
const key = `${kind}|${tz || ""}|${locale || ""}`;
|
|
10
|
+
let f = cache.get(key);
|
|
11
|
+
if (!f) {
|
|
12
|
+
const o = kind === "hm" ? { hour: "2-digit", minute: "2-digit" }
|
|
13
|
+
: kind === "ymd" ? { year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hourCycle: "h23" }
|
|
14
|
+
: { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
|
|
15
|
+
f = new Intl.DateTimeFormat(kind === "ymd" ? "en-US" : (locale || []), { ...o, timeZone: tz || undefined });
|
|
16
|
+
cache.set(key, f);
|
|
17
|
+
}
|
|
18
|
+
return f;
|
|
19
|
+
}
|
|
20
|
+
/** `tz` when this browser knows it, else undefined (the browser's own zone): a label must still be drawn. */
|
|
21
|
+
function known(tz) {
|
|
22
|
+
if (!tz) return undefined;
|
|
23
|
+
try { fmt("ymd", tz); return tz; } catch { return undefined; }
|
|
24
|
+
}
|
|
25
|
+
/** The fleet's zone, as the page was served it (<body data-fleet-tz>); undefined when absent or unknown here. */
|
|
26
|
+
export function fleetTz() { return known(globalThis.document?.body?.dataset?.fleetTz); }
|
|
27
|
+
|
|
28
|
+
const toMs = (ts) => (typeof ts === "number" ? ts : Date.parse(String(ts || "")));
|
|
29
|
+
function wall(ms, tz) {
|
|
30
|
+
const p = {};
|
|
31
|
+
for (const x of fmt("ymd", tz).formatToParts(ms)) p[x.type] = Number(x.value);
|
|
32
|
+
return p;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The label for `ts` (ISO string or epoch ms), "" when it cannot be read. opts: tz (default the fleet's), now (epoch ms),
|
|
37
|
+
* yesterday(hm) → the word for "yesterday" around hm (default: hm alone), locale (tests).
|
|
38
|
+
*/
|
|
39
|
+
export function chatTime(ts, opts = {}) {
|
|
40
|
+
const ms = toMs(ts);
|
|
41
|
+
if (!Number.isFinite(ms)) return "";
|
|
42
|
+
const tz = "tz" in opts ? known(opts.tz) : fleetTz();
|
|
43
|
+
const hm = fmt("hm", tz, opts.locale).format(ms);
|
|
44
|
+
const d = wall(ms, tz), today = wall(opts.now ?? Date.now(), tz);
|
|
45
|
+
if (d.year === today.year && d.month === today.month && d.day === today.day) return hm;
|
|
46
|
+
const y = new Date(Date.UTC(today.year, today.month - 1, today.day - 1));
|
|
47
|
+
if (d.year === y.getUTCFullYear() && d.month === y.getUTCMonth() + 1 && d.day === y.getUTCDate()) return opts.yesterday ? opts.yesterday(hm) : hm;
|
|
48
|
+
return d.year === today.year ? `${d.month}/${d.day} ${hm}` : `${d.year}/${d.month}/${d.day} ${hm}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** The full date, time and zone of `ts`, for a tooltip; "" when it cannot be read. */
|
|
52
|
+
export function chatTimeFull(ts, opts = {}) {
|
|
53
|
+
const ms = toMs(ts);
|
|
54
|
+
if (!Number.isFinite(ms)) return "";
|
|
55
|
+
return fmt("full", "tz" in opts ? known(opts.tz) : fleetTz(), opts.locale).format(ms);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Milliseconds until the fleet's next midnight (when "today" labels change), at most an hour (a DST day self-corrects). */
|
|
59
|
+
export function msToNextDay(now = Date.now(), tz = fleetTz()) {
|
|
60
|
+
const w = wall(now, known(tz));
|
|
61
|
+
const into = ((w.hour * 60 + w.minute) * 60 + w.second) * 1000 + (now % 1000);
|
|
62
|
+
return Math.max(1000, Math.min(3_600_000, 86_400_000 - into + 1000));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Call `fn` when the fleet's day may have changed — at its next midnight, then again for each one after (an hour at
|
|
67
|
+
* most between looks, so a DST day or a late timer corrects itself). Each subscriber holds its own timer, and no
|
|
68
|
+
* module-wide state: the unsubscribe it returns leaves nothing armed.
|
|
69
|
+
*/
|
|
70
|
+
export function onDayChange(fn) {
|
|
71
|
+
let timer = null, live = true;
|
|
72
|
+
const arm = () => {
|
|
73
|
+
timer = setTimeout(() => {
|
|
74
|
+
timer = null;
|
|
75
|
+
try { fn(); } finally { if (live) arm(); }
|
|
76
|
+
}, msToNextDay());
|
|
77
|
+
};
|
|
78
|
+
arm();
|
|
79
|
+
return () => { live = false; if (timer !== null) { clearTimeout(timer); timer = null; } };
|
|
80
|
+
}
|
package/dist/ui/panel-chat.js
CHANGED
|
@@ -10,6 +10,7 @@ import { html, useEffect, useLayoutEffect, useRef, useState } from "/assets/app-
|
|
|
10
10
|
import { t } from "/assets/app-i18n.js";
|
|
11
11
|
import { appStore, useStore } from "/assets/app-store.js";
|
|
12
12
|
import { useLease } from "/assets/app-ctx.js";
|
|
13
|
+
import { namesOf, namesStore } from "/assets/instance-nav.js";
|
|
13
14
|
import { PanelHeader, onPanelKey, setTitle, statusClass, statusLabel, openDrawer, requestNewInstance } from "/assets/app-shell.js";
|
|
14
15
|
import { detailsPath } from "/assets/app-route.js";
|
|
15
16
|
import { InstanceSwitch } from "/assets/instance-switch.js";
|
|
@@ -21,11 +22,15 @@ import { Empty, Skeleton } from "/assets/ui-states.js";
|
|
|
21
22
|
import { Icon } from "/assets/ui-icons.js";
|
|
22
23
|
import { toast } from "/assets/ui-toast.js";
|
|
23
24
|
import { confirmDialog } from "/assets/ui-confirm.js";
|
|
25
|
+
import { savePref } from "/assets/app-prefs.js";
|
|
24
26
|
import "./chat-strings.js";
|
|
25
27
|
import { confirmedWrite } from "./settings-confirm.js";
|
|
26
28
|
import { createChatStore } from "./chat-store.js";
|
|
27
29
|
import { createThread, msgKey } from "./chat-thread.js";
|
|
28
|
-
import {
|
|
30
|
+
import { createEmojiIndex } from "./chat-emojis.js";
|
|
31
|
+
import { pollPublicPreview } from "./preview-status.js";
|
|
32
|
+
import { createMentionIndex } from "./chat-mentions.js";
|
|
33
|
+
import { PreviewPanel, claimPanel, openPanel, panelClaims, panelStore, panelVersion, shownKey } from "./preview-panel.js";
|
|
29
34
|
import { needsArgument, paletteFor, parseCommandLine } from "./chat-commands.js";
|
|
30
35
|
import { installTour, refreshTourSpot } from "./chat-tour.js";
|
|
31
36
|
import { FirstRunCard } from "./first-run.js";
|
|
@@ -40,6 +45,9 @@ export let store = null;
|
|
|
40
45
|
// ── Announcements: one polite, visually hidden line for the coarse events only (a reply arrived, the agent started,
|
|
41
46
|
// finished, or waits on you). Messages themselves are not read out as they arrive; the list is a log to browse.
|
|
42
47
|
let announceTimer = null;
|
|
48
|
+
/** #1630: which Discord server emoji this page may draw (created with the store, in boot). */
|
|
49
|
+
let emojiIndex = null;
|
|
50
|
+
let mentionIndex = null; // #1682: the names of the mentions shown
|
|
43
51
|
function announce(text) {
|
|
44
52
|
let el = document.getElementById("announcer");
|
|
45
53
|
if (!el) { el = document.createElement("div"); el.id = "announcer"; el.className = "sr-only"; el.setAttribute("role", "status"); el.setAttribute("aria-live", "polite"); el.setAttribute("aria-atomic", "true"); document.body.appendChild(el); }
|
|
@@ -51,11 +59,14 @@ function announce(text) {
|
|
|
51
59
|
|
|
52
60
|
/**
|
|
53
61
|
* This device's preview opt-in: asks once (the app's dialog) and says what it means; turning it off stops every
|
|
54
|
-
* running preview. Resolves to the choice in force.
|
|
62
|
+
* running preview. Resolves to the choice in force. commit(apply): runs `apply` (the change itself) — the panel's Allow
|
|
63
|
+
* wraps it to know which change of the choice is its own (#1704).
|
|
55
64
|
*/
|
|
56
|
-
export async function setPreviewOptIn(on) {
|
|
65
|
+
export async function setPreviewOptIn(on, commit = (apply) => apply()) {
|
|
57
66
|
if (on && !P().optedIn() && !(await confirmDialog({ message: t("chat.pvConfirm"), confirmLabel: t("chat.pvAllowButton") }))) on = false;
|
|
58
|
-
P().setOptIn(on);
|
|
67
|
+
commit(() => P().setOptIn(on));
|
|
68
|
+
// #1665: kept on the host for every device (only a signed-in page writes it; never the public link).
|
|
69
|
+
savePref("preview.optIn", P().optedIn());
|
|
59
70
|
return P().optedIn();
|
|
60
71
|
}
|
|
61
72
|
|
|
@@ -65,11 +76,15 @@ export function boot({ stream, boot: bootData, deps = {} }) {
|
|
|
65
76
|
store = createChatStore({
|
|
66
77
|
fetch: (...a) => fetch(...a), toast, announce, t, setTimeout: (fn, ms) => setTimeout(fn, ms), confirm: confirmDialog, ...deps,
|
|
67
78
|
});
|
|
79
|
+
emojiIndex = createEmojiIndex((url) => (deps.fetch || fetch)(url, { credentials: "same-origin" }));
|
|
80
|
+
mentionIndex = createMentionIndex((url) => (deps.fetch || fetch)(url, { credentials: "same-origin" }));
|
|
68
81
|
store.attach(stream);
|
|
69
82
|
// #1306: what the server said about previews for this load. The page-wide message and storage listeners this adds
|
|
70
83
|
// belong to the app, once (they are never per mount).
|
|
71
84
|
// #1554: its words in the page's language (chat.pv*); a key the dictionary does not have keeps preview.js's English.
|
|
72
85
|
if (P() && bootData) P().init(bootData, { text: (key, ...v) => { const k = `chat.${key}`, s = t(k, ...v); return s === k ? null : s; } });
|
|
86
|
+
// #1723: the public link's preview was still starting when this page loaded: ask until it is up (or failed).
|
|
87
|
+
if (P() && bootData) pollPublicPreview(P());
|
|
73
88
|
// #1568: the banner's "I understand" lasts until the next sign-in — preview.js is told which sign-in this page is
|
|
74
89
|
// (the session handle, from the one /auth/session read); none (no session, or no AgendAuth): this tab only.
|
|
75
90
|
if (P() && typeof P().setBannerScope === "function") {
|
|
@@ -119,6 +134,9 @@ function useChatTick(name, kinds) {
|
|
|
119
134
|
|
|
120
135
|
// ── The panel ──
|
|
121
136
|
|
|
137
|
+
/** #1722: the chat's title — the name that leads, the other on hover. */
|
|
138
|
+
const headerName = ({ primary, secondary }) => (secondary ? html`<span title=${secondary}>${primary}</span>` : primary);
|
|
139
|
+
|
|
122
140
|
export function ChatPanel({ route, navKey }) {
|
|
123
141
|
const lease = useLease(navKey);
|
|
124
142
|
const app = useStore(appStore);
|
|
@@ -154,6 +172,7 @@ function NotFound({ name }) {
|
|
|
154
172
|
}
|
|
155
173
|
|
|
156
174
|
function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
175
|
+
const names = useStore(namesStore); // #1722: which name leads (the title)
|
|
157
176
|
const [dialog, setDialog] = useState(null); // "delete" | null
|
|
158
177
|
const [wrap, setWrap] = useState(codeWrap);
|
|
159
178
|
const view = useRef(null), split = useRef(null), thread = useRef(null);
|
|
@@ -189,6 +208,7 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
189
208
|
try { const res = await fetch(`/ui/${verb}/${encodeURIComponent(name)}`, { method: "POST", headers: { "Content-Type": "application/json" } }); r = await res.json(); }
|
|
190
209
|
catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
|
|
191
210
|
if (r && r.error) toast(r.error, false);
|
|
211
|
+
else if (r && r.held) toast(r.message);
|
|
192
212
|
else toast(t(verb === "start" ? "chat.started" : verb === "stop" ? "chat.stoppedInst" : "chat.restarted", name));
|
|
193
213
|
};
|
|
194
214
|
const items = [
|
|
@@ -206,14 +226,14 @@ function ChatView({ name, inst, lease, navKey, exec, awaiting }) {
|
|
|
206
226
|
${inst.model ? html`<button type="button" class="hd-chip" title=${t("chat.chipModel", inst.model)} aria-label=${t("chat.chipModel", inst.model)} onClick=${() => pick("model")}>${inst.model}</button>` : null}
|
|
207
227
|
${inst.effort ? html`<button type="button" class="hd-chip" title=${t("chat.chipEffort", inst.effort)} aria-label=${t("chat.chipEffort", inst.effort)} onClick=${() => pick("effort")}>${inst.effort}</button>` : null}`;
|
|
208
228
|
return html`<div class=${`panel p-chat${wrap ? " wrap-code" : ""}`} ref=${view}>
|
|
209
|
-
<${PanelHeader} title=${name} sub=${sub} nav=${html`<${InstanceSwitch} name=${name} current="chat" />`}><${HeaderTools} navKey=${navKey} /><${Menu} items=${items} label=${t("app.more")} /></${PanelHeader}>
|
|
229
|
+
<${PanelHeader} title=${headerName(namesOf(inst || { name }, names.primary))} sub=${sub} nav=${html`<${InstanceSwitch} name=${name} current="chat" />`}><${HeaderTools} navKey=${navKey} /><${Menu} items=${items} label=${t("app.more")} /></${PanelHeader}>
|
|
210
230
|
<div class="chat-split" ref=${split}>
|
|
211
231
|
<div class="chat-main">
|
|
212
232
|
<${Thread} name=${name} th=${thread} />
|
|
213
233
|
<${Dock} name=${name} inst=${inst} lease=${lease} exec=${exec} awaiting=${awaiting} />
|
|
214
234
|
</div>
|
|
215
235
|
<${PreviewPanel} name=${name} split=${split} msgs=${() => store.state.msgs[name] || []} subscribe=${(fn) => store.subscribe(fn)}
|
|
216
|
-
keyOf=${msgKey} reveal=${(k) => thread.current && thread.current.reveal(k)} download=${downloadHtml} allow=${() => setPreviewOptIn(true)} />
|
|
236
|
+
keyOf=${msgKey} reveal=${(k) => thread.current && thread.current.reveal(k)} download=${downloadHtml} allow=${(commit) => setPreviewOptIn(true, commit)} />
|
|
217
237
|
</div>
|
|
218
238
|
<${LightboxHost} />
|
|
219
239
|
<div class="drop-overlay" aria-hidden="true"><div class="drop-card"><${Icon} name="attach" size=${32} /><span>${t("chat.dropHere")}</span></div></div>
|
|
@@ -232,14 +252,22 @@ function Thread({ name, th }) {
|
|
|
232
252
|
setPreviewOptIn, copyText, download: downloadHtml, toggleWrap,
|
|
233
253
|
clickReplyButton: (id, index) => store.clickReplyButton(name, id, index), // #1266
|
|
234
254
|
replyButtonBusy: (id) => store.state.rbBusy.has(id),
|
|
235
|
-
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o) }, // #1481
|
|
255
|
+
panel: { shown: shownKey, open: (spec, o) => openPanel(spec, o), version: panelVersion, claim: claimPanel, claims: panelClaims }, // #1481, #1704
|
|
236
256
|
openImage: openLightbox, // an image, full size, in the page
|
|
257
|
+
emojis: (id) => !!emojiIndex && emojiIndex.known(id), // #1630: the fleet's server emoji
|
|
258
|
+
mentions: (kind, id) => (mentionIndex ? mentionIndex.name(kind, id) : null), // #1682: mention names
|
|
237
259
|
});
|
|
238
260
|
th.current = thread;
|
|
261
|
+
// #1630: the server-emoji list is read once a message shows a tag; when it arrives, those messages are drawn again.
|
|
262
|
+
// #1682: the same for mention names — asked for the ids the messages carry; when names arrive, drawn again.
|
|
263
|
+
const wantEmojis = (msgs) => { if (emojiIndex && emojiIndex.wants(msgs)) emojiIndex.ensure(); if (mentionIndex) mentionIndex.ensure(msgs); };
|
|
264
|
+
const offEmojis = emojiIndex ? emojiIndex.subscribe(() => thread.render(store.state.msgs[name] || [])) : () => {};
|
|
265
|
+
const offMentions = mentionIndex ? mentionIndex.subscribe(() => thread.render(store.state.msgs[name] || [])) : () => {};
|
|
239
266
|
thread.render(store.state.msgs[name] || [], { restore: store.state.scrollMemo[name] ?? null });
|
|
267
|
+
wantEmojis(store.state.msgs[name]);
|
|
240
268
|
const off = store.subscribe((instance, kind) => {
|
|
241
269
|
if (instance !== name) return;
|
|
242
|
-
if (kind === "msgs") thread.render(store.state.msgs[name] || []);
|
|
270
|
+
if (kind === "msgs") { thread.render(store.state.msgs[name] || []); wantEmojis(store.state.msgs[name]); }
|
|
243
271
|
else if (kind === "sent") thread.jumpLatest();
|
|
244
272
|
});
|
|
245
273
|
const offPv = P() ? P().onChange(() => thread.refreshCards()) : () => {};
|
|
@@ -249,7 +277,7 @@ function Thread({ name, th }) {
|
|
|
249
277
|
sc.addEventListener("scroll", onScroll, { passive: true });
|
|
250
278
|
ls.addEventListener("click", thread.onClick);
|
|
251
279
|
return () => {
|
|
252
|
-
off(); offPv(); offPanel();
|
|
280
|
+
off(); offPv(); offPanel(); offEmojis(); offMentions();
|
|
253
281
|
sc.removeEventListener("scroll", onScroll);
|
|
254
282
|
ls.removeEventListener("click", thread.onClick);
|
|
255
283
|
thread.dispose(); // the whole thread goes: every preview in it stops first
|
|
@@ -292,6 +320,7 @@ function CommandCard({ name, lease }) {
|
|
|
292
320
|
aria-label=${t("chat.cmdDismiss")} onClick=${() => store.dismissCommand(name)}><${Icon} name="close" size=${14} /></button>`}</div>
|
|
293
321
|
${c.error ? html`<p class="cmd-text">${c.error}</p>` : null}
|
|
294
322
|
${c.text ? html`<pre class="cmd-text">${c.text}</pre>` : null}
|
|
323
|
+
${c.choices && c.choices.prompt ? html`<pre class="cmd-text">${c.choices.prompt}</pre>` : null}
|
|
295
324
|
${c.choices ? html`<div class="cmd-choices" role="group" aria-label=${t("chat.cmdChoose")}>${c.choices.options.map((o) => html`<button key=${o.id} type="button"
|
|
296
325
|
class=${`btn btn-sm${o.id === c.choices.current ? " current" : ""}`} aria-current=${o.id === c.choices.current ? "true" : undefined} onClick=${() => run(o.id)}>${o.label}</button>`)}</div>` : null}
|
|
297
326
|
</div>`;
|
|
@@ -466,7 +495,7 @@ function DeleteDialog({ name, onClose }) {
|
|
|
466
495
|
<button type="button" class="btn btn-danger" disabled=${typed !== want || busy} onClick=${go}>${t("chat.deleteGo")}</button>`}>
|
|
467
496
|
<p>${t("chat.deleteHelp", name)}</p>
|
|
468
497
|
<label class="field"><span class="sr-only">${t("chat.deleteHelp", name)}</span>
|
|
469
|
-
<input type="text" value=${typed} autocomplete="off" spellcheck
|
|
498
|
+
<input type="text" value=${typed} autocomplete="off" spellcheck=${false} placeholder=${want} onInput=${(e) => setTyped(e.target.value)}
|
|
470
499
|
onKeyDown=${(e) => { if (e.key === "Enter") go(); }} /></label>
|
|
471
500
|
</${Dialog}>`;
|
|
472
501
|
}
|
package/dist/ui/panel-details.js
CHANGED
|
@@ -73,11 +73,13 @@ function DetailsView({ name, inst, navKey, exec, awaiting }) {
|
|
|
73
73
|
try { const res = await fetch(`/ui/${verb}/${encodeURIComponent(name)}`, { method: "POST", headers: { "Content-Type": "application/json" } }); r = await res.json(); }
|
|
74
74
|
catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
|
|
75
75
|
if (r && r.error) toast(r.error, false);
|
|
76
|
+
else if (r && r.held) toast(r.message);
|
|
76
77
|
else toast(t(verb === "start" ? "chat.started" : verb === "stop" ? "chat.stoppedInst" : "chat.restarted", name));
|
|
77
78
|
});
|
|
78
79
|
const pauseWake = (verb) => act(verb, async () => {
|
|
79
80
|
const res = await api(`/api/settings/instances/${encodeURIComponent(name)}/${verb}`, { method: "POST" }).catch(() => ({ ok: false, body: {} }));
|
|
80
81
|
if (!res.ok) toast((res.body && res.body.error) || t("chat.dActionFailed"), false);
|
|
82
|
+
else if (res.body && res.body.held) toast(res.body.message);
|
|
81
83
|
else toast(t(verb === "pause" ? "chat.dPaused" : "chat.dWoken", name));
|
|
82
84
|
});
|
|
83
85
|
// A ClassicBot room (classicBot.yaml) keeps Classic's split: its own Settings dialog, and only the actions Settings'
|