synabun 2.1.0 → 2.2.1
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/CHANGELOG.md +139 -0
- package/README.md +1 -1
- package/docs/whatsapp.md +11 -11
- package/lib/client-config-repair.js +13 -9
- package/lib/external-tools.js +6 -5
- package/lib/update-snapshot.js +77 -3
- package/lib/virustotal.mjs +12 -1
- package/mcp-server/dist/index.js +1 -1
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +2 -1
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +2 -1
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.js +1 -1
- package/mcp-server/dist/services/tool-catalog.js.map +1 -1
- package/mcp-server/dist/services/tool-list.d.ts +1 -1
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.d.ts +2 -2
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.js +1 -1
- package/mcp-server/dist/services/tool-runtime.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +8 -8
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +10 -9
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +8 -8
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/skill-tools.js +11 -8
- package/mcp-server/dist/tools/skill-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/index.ts +1 -1
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +2 -1
- package/mcp-server/src/services/server-instructions.ts +2 -1
- package/mcp-server/src/services/tool-catalog.ts +1 -1
- package/mcp-server/src/services/tool-list.ts +1 -1
- package/mcp-server/src/services/tool-runtime.ts +2 -2
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/tools/agents.ts +10 -9
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +11 -8
- package/neural-interface/i18n/en.json +504 -39
- package/neural-interface/i18n/pt-BR.json +504 -39
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +1 -0
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/codex.js +6 -1
- package/neural-interface/lib/assistant-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +76 -9
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +211 -50
- package/neural-interface/lib/assistant-envelope.js +153 -1
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +16 -11
- package/neural-interface/lib/assistant-plan-permissions.js +15 -0
- package/neural-interface/lib/assistant-router.js +237 -35
- package/neural-interface/lib/assistant-runtime.js +158 -12
- package/neural-interface/lib/assistant-task-prompt.js +10 -8
- package/neural-interface/lib/assistant-tools.js +2 -2
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +6 -1
- package/neural-interface/lib/browser-guard-cdp.js +5 -4
- package/neural-interface/lib/browser-network-guard.js +274 -82
- package/neural-interface/lib/browser-tool-policy.js +12 -7
- package/neural-interface/lib/claude-agent-bridge.js +7 -0
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +160 -31
- package/neural-interface/lib/cli-resolver.js +9 -2
- package/neural-interface/lib/cli-update-planner.js +25 -15
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +25 -6
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +9 -2
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- package/neural-interface/lib/mcp-client-config.js +37 -6
- package/neural-interface/lib/mcp-external-servers.js +40 -7
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +147 -25
- package/neural-interface/lib/native-loop-providers.js +423 -23
- package/neural-interface/lib/native-loop-runtime.js +23 -2
- package/neural-interface/lib/opencode-native-boundary.js +165 -22
- package/neural-interface/lib/owner-authority.js +1 -1
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +80 -6
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +3 -0
- package/neural-interface/lib/rulesets/api.js +6 -5
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +89 -10
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +64 -1
- package/neural-interface/lib/skills/catalog.js +5 -1
- package/neural-interface/lib/skills/creation-brief.js +1 -1
- package/neural-interface/lib/skills/creation-sources.js +19 -1
- package/neural-interface/lib/skills/deploy.js +9 -4
- package/neural-interface/lib/skills/draft-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-trace.js +16 -0
- package/neural-interface/lib/skills/export.js +5 -2
- package/neural-interface/lib/skills/known-bridge-digests.json +58 -4
- package/neural-interface/lib/skills/ownership.js +1 -1
- package/neural-interface/lib/skills/roots.js +10 -3
- package/neural-interface/lib/skills/runtime-checks.js +6 -3
- package/neural-interface/lib/skills/service.js +15 -7
- package/neural-interface/lib/skills/telemetry.js +6 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +77 -1
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-resume.js +13 -4
- package/neural-interface/lib/worker-sandbox.js +46 -16
- package/neural-interface/package-lock.json +18 -2
- package/neural-interface/package.json +2 -1
- package/neural-interface/public/onboarding.html +1 -1
- package/neural-interface/public/shared/agent-runtime-options.js +89 -11
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- package/neural-interface/public/shared/api.js +4 -4
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +3 -4
- package/neural-interface/public/shared/assistant/asst-api.js +15 -3
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +56 -9
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-computer.js +26 -2
- package/neural-interface/public/shared/assistant/asst-control.js +48 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +6 -1
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +38 -5
- package/neural-interface/public/shared/assistant/asst-motion-gate.js +80 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +46 -9
- package/neural-interface/public/shared/assistant/asst-render.js +112 -18
- package/neural-interface/public/shared/assistant/asst-route.js +237 -57
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +55 -23
- package/neural-interface/public/shared/assistant/asst-scenes.js +279 -80
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +4 -4
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +51 -7
- package/neural-interface/public/shared/assistant/asst-slash.js +8 -2
- package/neural-interface/public/shared/assistant/asst-state.js +76 -9
- package/neural-interface/public/shared/assistant/asst-style-cache.js +44 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +58 -4
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +34 -7
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +26 -3
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +11 -10
- package/neural-interface/public/shared/cdx/cdx-render.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-requests.js +11 -1
- package/neural-interface/public/shared/cdx/cdx-styles.js +4 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +75 -5
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +7 -4
- package/neural-interface/public/shared/cli-status.js +9 -8
- package/neural-interface/public/shared/constants.js +3 -2
- package/neural-interface/public/shared/context-menu-model.js +1 -0
- package/neural-interface/public/shared/cp/cp-permissions.js +12 -0
- package/neural-interface/public/shared/cp/cp-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +1 -0
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +21 -4
- package/neural-interface/public/shared/loading-teardown.js +34 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +6 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +28 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +17 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +6 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +101 -68
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +46 -3
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +1 -1
- package/neural-interface/public/shared/settings/settings-skill-folders.js +2 -2
- package/neural-interface/public/shared/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-creation.js +6 -3
- package/neural-interface/public/shared/skills/ss-dialog.js +5 -2
- package/neural-interface/public/shared/skills/ss-lint.js +9 -1
- package/neural-interface/public/shared/skills/ss-profiles.js +44 -6
- package/neural-interface/public/shared/skills/ss-review-view.js +2 -2
- package/neural-interface/public/shared/skills/studio/sx-actions.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-dom.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +9 -6
- package/neural-interface/public/shared/skills/studio/sx-install.js +20 -3
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +144 -35
- package/neural-interface/public/shared/skills/studio/sx-library.js +6 -2
- package/neural-interface/public/shared/skills/studio/sx-main.js +11 -2
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-subject.js +7 -6
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +6 -5
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/storage-retry.js +47 -0
- package/neural-interface/public/shared/storage.js +25 -4
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styles.css +362 -35
- package/neural-interface/public/shared/synabun-mascot.js +27 -8
- package/neural-interface/public/shared/synabun-ticker.js +147 -12
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +2 -2
- package/neural-interface/public/shared/tool-list-view.js +2 -2
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +20 -12
- package/neural-interface/public/shared/ui-claude-panel.js +374 -134
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +8 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-loading.js +5 -4
- package/neural-interface/public/shared/ui-menubar.js +2 -2
- package/neural-interface/public/shared/ui-native-loop-router.js +4 -0
- package/neural-interface/public/shared/ui-navbar.js +45 -0
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +41 -10
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +22 -12
- package/neural-interface/public/shared/ui-settings.js +90 -65
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -3
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +3 -3
- package/neural-interface/public/shared/ui-terminal.js +146 -10
- package/neural-interface/public/shared/ui-tool-updates.js +3 -3
- package/neural-interface/public/shared/ui-tooltip.js +71 -46
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1 -1
- package/neural-interface/public/shared/ui-worker-end.js +1 -1
- package/neural-interface/public/shared/whatsapp/wa-view.js +2 -2
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/server.js +731 -466
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +5 -5
- package/neural-interface/templates/rulesets/manifest.json +1 -1
- package/npm-shrinkwrap.json +18 -2
- package/package.json +2 -1
- package/skills/skill-forge/SKILL.md +4 -4
- package/skills/synabun/SKILL.md +1 -1
- package/skills/synabun/modules/schedule.md +3 -3
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -108,14 +108,22 @@ export function createAssistantHosts({
|
|
|
108
108
|
return { host: hostId, sessionId, focused: true };
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Map(id → session) of the sessions still open on the server, or null when the list could not be
|
|
113
|
+
* read (a server that is starting answers before its Assistant routes exist): a host restoring its
|
|
114
|
+
* saved tabs from it keeps them then, instead of reading "none is open".
|
|
115
|
+
*/
|
|
116
|
+
async function readLive() {
|
|
117
|
+
let list;
|
|
118
|
+
try { list = await api.list(); } catch { return null; }
|
|
119
|
+
return new Map((Array.isArray(list) ? list : [])
|
|
120
|
+
.filter(s => s?.id && isAssistantSessionLive(s))
|
|
121
|
+
.map(s => [s.id, s]));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Map(id → session) of the sessions still open on the server (boot's saved-tab restore); a failing server reads as none. */
|
|
112
125
|
async function fetchLive() {
|
|
113
|
-
|
|
114
|
-
const list = await api.list();
|
|
115
|
-
return new Map((Array.isArray(list) ? list : [])
|
|
116
|
-
.filter(s => s?.id && isAssistantSessionLive(s))
|
|
117
|
-
.map(s => [s.id, s]));
|
|
118
|
-
} catch { return new Map(); }
|
|
126
|
+
return (await readLive()) || new Map();
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
/**
|
|
@@ -302,6 +310,7 @@ export function createAssistantHosts({
|
|
|
302
310
|
gone,
|
|
303
311
|
noteFocus,
|
|
304
312
|
fetchLive,
|
|
313
|
+
readLive,
|
|
305
314
|
isLive: isAssistantSessionLive,
|
|
306
315
|
lastUsed: () => lastOpen(),
|
|
307
316
|
hosts: () => [...adapters.keys()],
|
|
@@ -20,7 +20,12 @@ export function createLimitDock(transcript, { t, createWait = createLimitWait, c
|
|
|
20
20
|
host.replaceChildren();
|
|
21
21
|
active = key;
|
|
22
22
|
provider = next?.[1].provider;
|
|
23
|
-
wait = next ? createWait({
|
|
23
|
+
wait = next ? createWait({
|
|
24
|
+
t, ...next[1],
|
|
25
|
+
onRetry: next[1].onRetry ? () => entries.get(key)?.onRetry?.() : null,
|
|
26
|
+
onSwitchProvider: next[1].onSwitchProvider ? (anchor) => entries.get(key)?.onSwitchProvider?.(anchor) : null,
|
|
27
|
+
onClose: next[1].onClose ? () => entries.get(key)?.onClose?.() : null,
|
|
28
|
+
}) : null;
|
|
24
29
|
if (wait) host.appendChild(wait.el);
|
|
25
30
|
} else if (wait) wait.update({ resetsAt: next[1].resetsAt });
|
|
26
31
|
host.hidden = !wait;
|
|
@@ -6,10 +6,15 @@
|
|
|
6
6
|
// mascot dozes inside a gold ring that fills toward the reset, a live
|
|
7
7
|
// hh:mm:ss countdown and the local reset time beside it. At zero it wakes
|
|
8
8
|
// ("Usage limit restored") and offers Retry now. With no reset time known it
|
|
9
|
-
// waits with "Reset time unknown" and offers the retry at once.
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
9
|
+
// waits with "Reset time unknown" and offers the retry at once. While it
|
|
10
|
+
// blocks, a host that passes onSwitchProvider also offers "Continue with
|
|
11
|
+
// another provider" (the host owns the picker and what a pick does); a host
|
|
12
|
+
// that passes onClose always offers Close, which only dismisses the card —
|
|
13
|
+
// the limit itself is untouched — and Esc does the same while focus is
|
|
14
|
+
// inside. The clock is the shared ticker at 1 fps, only while it counts and
|
|
15
|
+
// only while the card is on the page; under prefers-reduced-motion the mascot
|
|
16
|
+
// is a still and nothing eases. Its sheet is its own (injectLimitWaitStyles),
|
|
17
|
+
// like the rack's.
|
|
13
18
|
|
|
14
19
|
import * as mascotLib from '../synabun-mascot.js';
|
|
15
20
|
import { isReducedMotion, subscribe } from '../synabun-ticker.js';
|
|
@@ -37,10 +42,12 @@ function localTime(ms, now) {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/**
|
|
40
|
-
* createLimitWait({ t, resetsAt, since, provider, onRetry, retryLabel, announce(text) })
|
|
45
|
+
* createLimitWait({ t, resetsAt, since, provider, onRetry, retryLabel, onSwitchProvider, onClose, announce(text) })
|
|
41
46
|
* → { el, get state(), update({ resetsAt, since }), retried(), stale(), destroy() }
|
|
42
47
|
* `resetsAt`: epoch ms / s or ISO, or null (unknown). `since`: when the wait began (the ring's start).
|
|
43
48
|
* `provider`: the name in the meta line ("Codex"). `onRetry()`: Retry now; null: no button.
|
|
49
|
+
* `onSwitchProvider(anchorEl)`: Continue with another provider, while blocking; null: no button.
|
|
50
|
+
* `onClose()`: Close (and Esc, while focus is inside); null: no button.
|
|
44
51
|
*/
|
|
45
52
|
export function createLimitWait(opts = {}) {
|
|
46
53
|
injectLimitWaitStyles();
|
|
@@ -84,6 +91,16 @@ export function createLimitWait(opts = {}) {
|
|
|
84
91
|
const actions = $('.asst-limit-wait-actions');
|
|
85
92
|
const live = $('.asst-limit-wait-live');
|
|
86
93
|
|
|
94
|
+
// Continue with another provider: only while actively blocking (waiting / unknown). Opens the
|
|
95
|
+
// host's own provider picker (never a native select); the host decides what happens on a pick.
|
|
96
|
+
let switchBtn = null;
|
|
97
|
+
if (typeof opts.onSwitchProvider === 'function') {
|
|
98
|
+
switchBtn = el('button', 'asst-btn asst-btn-secondary asst-limit-wait-switch', t('assistant.limitWait.switchProvider', 'Continue with another provider'));
|
|
99
|
+
switchBtn.type = 'button';
|
|
100
|
+
switchBtn.addEventListener('click', () => { if (!destroyed) opts.onSwitchProvider(switchBtn); });
|
|
101
|
+
actions.appendChild(switchBtn);
|
|
102
|
+
}
|
|
103
|
+
|
|
87
104
|
let retryBtn = null;
|
|
88
105
|
if (typeof opts.onRetry === 'function') {
|
|
89
106
|
retryBtn = el('button', 'asst-btn asst-btn-primary asst-limit-wait-retry');
|
|
@@ -96,6 +113,21 @@ export function createLimitWait(opts = {}) {
|
|
|
96
113
|
actions.appendChild(retryBtn);
|
|
97
114
|
}
|
|
98
115
|
|
|
116
|
+
// Dismisses the card only; the limit itself is untouched (the host decides how it resurfaces).
|
|
117
|
+
let closeBtn = null;
|
|
118
|
+
if (typeof opts.onClose === 'function') {
|
|
119
|
+
closeBtn = el('button', 'asst-btn asst-btn-secondary asst-limit-wait-close', t('common.close', 'Close'));
|
|
120
|
+
closeBtn.type = 'button';
|
|
121
|
+
closeBtn.addEventListener('click', () => { if (!destroyed) opts.onClose(); });
|
|
122
|
+
actions.appendChild(closeBtn);
|
|
123
|
+
// Not a dialog (role="group"): Esc closes it only while focus is inside.
|
|
124
|
+
card.addEventListener('keydown', (e) => {
|
|
125
|
+
if (e.key !== 'Escape' || destroyed) return;
|
|
126
|
+
e.stopPropagation();
|
|
127
|
+
opts.onClose();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
99
131
|
function setPose(next) {
|
|
100
132
|
if (pose === next || destroyed) return;
|
|
101
133
|
pose = next;
|
|
@@ -146,6 +178,7 @@ export function createLimitWait(opts = {}) {
|
|
|
146
178
|
: (opts.retryLabel || t('assistant.limitWait.retry', 'Retry now'));
|
|
147
179
|
retryBtn.textContent = label;
|
|
148
180
|
}
|
|
181
|
+
if (switchBtn) switchBtn.hidden = !(next === 'waiting' || next === 'unknown');
|
|
149
182
|
if (next === 'waiting') { setPose('sleep'); setRing(limitCountdown({ resetsAt, since }, now).progress || 0); }
|
|
150
183
|
else if (next === 'unknown') { setPose('wait'); setRing(0.18, true); }
|
|
151
184
|
else if (next === 'restored') { setPose(was === 'waiting' ? 'success' : 'idle'); setRing(1); }
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Assistant — loops run only on screen
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
// The transcript's decorative loops (a run card's cameo, its stage's scene and
|
|
5
|
+
// sweep; a live rack's sweep, ticks and scene; a route line's sweep and icon)
|
|
6
|
+
// run only while their holder is on screen. One IntersectionObserver per
|
|
7
|
+
// renderer marks a holder that is not (scrolled out of its transcript, its tab
|
|
8
|
+
// hidden, its window minimised to nothing) with `data-offscreen`; the
|
|
9
|
+
// stylesheet pauses every animation under it (asst-styles.js), and the loop
|
|
10
|
+
// picks up where it stopped when the holder is back. Every frame the page
|
|
11
|
+
// draws restyles each running animation on the main thread, composited or
|
|
12
|
+
// not, so a loop nobody sees is never free; the observer is the browser's own,
|
|
13
|
+
// so watching costs nothing while the transcript scrolls.
|
|
14
|
+
//
|
|
15
|
+
// createMotionGate({ IntersectionObserver }?) → { watch(el), unwatch(el), disconnect(), size() }
|
|
16
|
+
//
|
|
17
|
+
// No observer (an old engine, a test without one): nothing is marked, every
|
|
18
|
+
// loop runs as before. DOM-light on purpose: tests/assistant-motion-gate.test.mjs
|
|
19
|
+
// drives it with a stand-in observer.
|
|
20
|
+
|
|
21
|
+
export const OFFSCREEN_ATTR = 'data-offscreen';
|
|
22
|
+
const PRUNE_EVERY = 32; // watched holders between two sweeps for ones that left the document
|
|
23
|
+
|
|
24
|
+
export function createMotionGate({ IntersectionObserver: IO = globalThis.IntersectionObserver } = {}) {
|
|
25
|
+
const watched = new Set();
|
|
26
|
+
let io = null; // undefined: no observer here
|
|
27
|
+
|
|
28
|
+
function mark(el, off) {
|
|
29
|
+
try {
|
|
30
|
+
if (off) { if (!el.hasAttribute(OFFSCREEN_ATTR)) el.setAttribute(OFFSCREEN_ATTR, ''); }
|
|
31
|
+
else if (el.hasAttribute(OFFSCREEN_ATTR)) el.removeAttribute(OFFSCREEN_ATTR);
|
|
32
|
+
} catch { /* not an element */ }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function observer() {
|
|
36
|
+
if (io !== null) return io;
|
|
37
|
+
if (typeof IO !== 'function') { io = undefined; return io; }
|
|
38
|
+
try {
|
|
39
|
+
io = new IO((entries) => {
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
const el = entry.target;
|
|
42
|
+
if (!watched.has(el)) continue;
|
|
43
|
+
if (el.isConnected === false) { unwatch(el); continue; }
|
|
44
|
+
mark(el, !entry.isIntersecting);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
} catch { io = undefined; }
|
|
48
|
+
return io;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Holders removed while already off screen get no report: drop them now and then. */
|
|
52
|
+
function prune() {
|
|
53
|
+
for (const el of Array.from(watched)) if (el.isConnected === false) unwatch(el);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function watch(el) {
|
|
57
|
+
if (!el || watched.has(el)) return false;
|
|
58
|
+
const o = observer();
|
|
59
|
+
if (!o) return false;
|
|
60
|
+
watched.add(el);
|
|
61
|
+
try { o.observe(el); } catch { watched.delete(el); return false; }
|
|
62
|
+
if (watched.size % PRUNE_EVERY === 0) prune();
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function unwatch(el) {
|
|
67
|
+
if (!watched.delete(el)) return;
|
|
68
|
+
try { io?.unobserve(el); } catch { /* already gone */ }
|
|
69
|
+
mark(el, false);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function disconnect() {
|
|
73
|
+
try { io?.disconnect(); } catch { /* already gone */ }
|
|
74
|
+
for (const el of watched) mark(el, false);
|
|
75
|
+
watched.clear();
|
|
76
|
+
if (io) io = null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { watch, unwatch, disconnect, size: () => watched.size };
|
|
80
|
+
}
|
|
@@ -35,7 +35,6 @@ import { t } from '../i18n.js';
|
|
|
35
35
|
import '../account-i18n.js';
|
|
36
36
|
import { forgetGreeting, mountGreeting } from '../greeting/greeting-card.js';
|
|
37
37
|
import { notify, NOTIF_TYPE } from '../ui-notifications.js';
|
|
38
|
-
import { getProviderMeta } from '../provider-icons.js';
|
|
39
38
|
import { isGuest, hasPermission } from '../ui-sync.js';
|
|
40
39
|
import { getWhiteboardElementById } from '../ui-whiteboard.js';
|
|
41
40
|
import { focusNativeLoopRun } from '../ui-native-loop-router.js';
|
|
@@ -51,7 +50,7 @@ import { buildPromptText, createComposer } from './asst-composer.js';
|
|
|
51
50
|
import { buildDispatchSpec, parseSlashCommand, slashHelpMarkdown } from './asst-slash.js';
|
|
52
51
|
import { resolveStopTarget } from './asst-stop.js';
|
|
53
52
|
import { plural } from './asst-tool-kinds.js';
|
|
54
|
-
import { cachedProjects, createBrainPicker, testDensityLabel } from './asst-brain-picker.js';
|
|
53
|
+
import { cachedProjects, createBrainPicker, openModelMenu, testDensityLabel } from './asst-brain-picker.js';
|
|
55
54
|
import { createRovingToolbar } from './asst-roving.js';
|
|
56
55
|
import { openAccountsManager } from './asst-accounts.js';
|
|
57
56
|
import { createAgentsDock } from './asst-agents-dock.js';
|
|
@@ -62,8 +61,8 @@ import { createRouteModeControl, openModelsManager, openRoutesEditor, refreshMod
|
|
|
62
61
|
import { budgetChipText, budgetSpendText, budgetTone, closeBudgetEditor, createBudgetController, mountBudgetChip, openBudgetEditor } from './asst-budget.js';
|
|
63
62
|
import { computerRemoteView, createComputerPanel, createComputerToggle, normalizeComputerRemote, openFrameLightbox, closeFrameLightbox, requestDesktopStop } from './asst-computer.js';
|
|
64
63
|
import {
|
|
65
|
-
applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
|
|
66
|
-
brainModePatch, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerShortLabel, readStoredBrain, runFromPayload,
|
|
64
|
+
applyLimit, applyLimitPacket, applyUsagePacket, BRAIN_PROVIDERS, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
|
|
65
|
+
brainModePatch, isBrainProvider, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerMeta, providerShortLabel, readStoredBrain, runFromPayload,
|
|
67
66
|
serializeTabState, sessionStatus, tabStorageKey, userSessionTitle,
|
|
68
67
|
} from './asst-state.js';
|
|
69
68
|
import {
|
|
@@ -244,8 +243,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
244
243
|
if (host.toolbarSlot) host.toolbarSlot.appendChild(barEl);
|
|
245
244
|
|
|
246
245
|
// ── Helpers ──
|
|
247
|
-
|
|
248
|
-
const
|
|
246
|
+
// A worker-only provider provider-icons.js does not know yet keeps its own name (asst-state.js providerMeta).
|
|
247
|
+
const providerIcon = (p) => providerMeta(p).icon;
|
|
248
|
+
const providerColor = (p) => providerMeta(p).color;
|
|
249
249
|
const visible = () => { try { return host.isVisible ? !!host.isVisible() : true; } catch { return true; } };
|
|
250
250
|
|
|
251
251
|
// ── Just-in-time tips (../tour/tour-tips.js): once each, ever; never in a replay or while the tour runs ──
|
|
@@ -537,6 +537,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
537
537
|
onFollowup: (text) => { submit(clickPayload(text)); },
|
|
538
538
|
onFollowupOther: () => composer.focus(),
|
|
539
539
|
onLimitRetry: (text) => { submit(clickPayload(text)); },
|
|
540
|
+
onSwitchProvider: (anchor, meta) => continueOnAnotherProvider(anchor, meta),
|
|
540
541
|
limitInfo: () => st.limit,
|
|
541
542
|
brainProvider: () => st.brain.provider,
|
|
542
543
|
heroOrigin: () => { try { return host.takeHeroOrigin?.() || null; } catch { return null; } },
|
|
@@ -1117,7 +1118,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1117
1118
|
computerPanel.applyStatus(status);
|
|
1118
1119
|
applyFeatures();
|
|
1119
1120
|
})
|
|
1120
|
-
.catch(() => { st.features.computer = false; applyFeatures(); });
|
|
1121
|
+
.catch((err) => { st.features.computer = false; computerPanel.checkFailed?.(err); applyFeatures(); });
|
|
1121
1122
|
}
|
|
1122
1123
|
}
|
|
1123
1124
|
|
|
@@ -1480,6 +1481,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1480
1481
|
compact();
|
|
1481
1482
|
return true;
|
|
1482
1483
|
case 'new':
|
|
1484
|
+
if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
|
|
1483
1485
|
newSession(parsed.provider || null);
|
|
1484
1486
|
return true;
|
|
1485
1487
|
case 'resume':
|
|
@@ -1507,6 +1509,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1507
1509
|
if (parsed.error) { toast(tt('assistant.slash.needsText', 'Usage: /remember <text>')); return false; }
|
|
1508
1510
|
return queueOrSend({ ...payload, display: payload.text, text: tt('assistant.prompts.remember', 'Store this in SynaBun memory with the remember tool (pick a fitting category, project, tags and importance): {text}', { text: parsed.text }) });
|
|
1509
1511
|
case 'model': {
|
|
1512
|
+
if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
|
|
1510
1513
|
if (!parsed.model && !parsed.provider) { picker.openField('model'); return true; }
|
|
1511
1514
|
const next = { ...st.brain };
|
|
1512
1515
|
let requiresSwitch = false;
|
|
@@ -1555,10 +1558,15 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1555
1558
|
}
|
|
1556
1559
|
}
|
|
1557
1560
|
|
|
1561
|
+
/** /model or /new naming a provider that runs dispatched work only (none today: all four can be the brain). */
|
|
1562
|
+
function notBrainText(provider) {
|
|
1563
|
+
return tt('assistant.slash.notBrain', '{provider} runs dispatched work only, never the Assistant itself. Send it a task with /dispatch {id} <task>.', { provider: providerShortLabel(provider), id: provider });
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1558
1566
|
function dispatchErrorText(parsed) {
|
|
1559
1567
|
switch (parsed.error) {
|
|
1560
|
-
case 'missing_provider': return tt('assistant.slash.dispatchProvider', 'Usage: /dispatch <claude|codex|opencode> [flags] <task>');
|
|
1561
|
-
case 'invalid_provider': return tt('assistant.slash.dispatchInvalidProvider', 'Unknown provider "{provider}". Use claude, codex or
|
|
1568
|
+
case 'missing_provider': return tt('assistant.slash.dispatchProvider', 'Usage: /dispatch <claude|codex|opencode|antigravity> [flags] <task>');
|
|
1569
|
+
case 'invalid_provider': return tt('assistant.slash.dispatchInvalidProvider', 'Unknown provider "{provider}". Use claude, codex, opencode or antigravity.', { provider: parsed.provider });
|
|
1562
1570
|
case 'unknown_flag': return tt('assistant.slash.dispatchUnknownFlag', 'Unknown flag --{flag}', { flag: parsed.flag });
|
|
1563
1571
|
case 'missing_flag_value': return tt('assistant.slash.dispatchFlagValue', 'Flag --{flag} needs a value', { flag: parsed.flag });
|
|
1564
1572
|
case 'missing_task': return tt('assistant.slash.dispatchTask', 'Add the task text after the flags');
|
|
@@ -1607,6 +1615,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1607
1615
|
}
|
|
1608
1616
|
|
|
1609
1617
|
function newSession(provider) {
|
|
1618
|
+
// Only a brain provider names a new session's brain (Claude Code, Codex, OpenCode or Antigravity).
|
|
1619
|
+
if (provider && !isBrainProvider(provider)) provider = null;
|
|
1610
1620
|
const b = provider ? normalizeBrain({ ...st.brain, provider, model: '', effort: null, agent: null, accountId: null }) : st.brain;
|
|
1611
1621
|
// This one is still empty: it is the new session (the server keeps one draft, not a pile of them).
|
|
1612
1622
|
// /new <provider> switches its brain as the picker does; what only this page showed (/help) is cleared.
|
|
@@ -1663,6 +1673,33 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1663
1673
|
});
|
|
1664
1674
|
}
|
|
1665
1675
|
|
|
1676
|
+
// "Continue with another provider" on the Assistant's own limit-wait card: the same model menu
|
|
1677
|
+
// the toolbar's model field opens (never a native select), minus the limited provider, then the
|
|
1678
|
+
// existing switch (applyBrain → switch_brain) and, where the blocked prompt is known, Retry now's
|
|
1679
|
+
// own resend (submit) — in that order, so the server sees the switch before the retried prompt.
|
|
1680
|
+
function continueOnAnotherProvider(anchor, { excludeProvider = '', retryText = '' } = {}) {
|
|
1681
|
+
if (!anchor) return;
|
|
1682
|
+
const providers = BRAIN_PROVIDERS.filter((p) => p !== excludeProvider);
|
|
1683
|
+
if (!providers.length) return;
|
|
1684
|
+
openModelMenu(anchor, {
|
|
1685
|
+
brain: st.brain,
|
|
1686
|
+
t,
|
|
1687
|
+
providers,
|
|
1688
|
+
title: tt('assistant.limitWait.switchProvider', 'Continue with another provider'),
|
|
1689
|
+
warnSwitch: true,
|
|
1690
|
+
allowCustom: false, // a custom id here would resolve to the (still limited) current provider
|
|
1691
|
+
onToast: toast,
|
|
1692
|
+
onManageModels: () => openModels(),
|
|
1693
|
+
onSelect: async (target) => {
|
|
1694
|
+
if (!target?.provider) return;
|
|
1695
|
+
await picker.switchProvider(target.provider, target.model || '');
|
|
1696
|
+
if (destroyed) return;
|
|
1697
|
+
renderer.clearLimitWait();
|
|
1698
|
+
if (retryText) submit(clickPayload(retryText));
|
|
1699
|
+
},
|
|
1700
|
+
}).catch(() => {});
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1666
1703
|
// ── Runs ──
|
|
1667
1704
|
async function focusRun(runId) {
|
|
1668
1705
|
if (!runId) return;
|