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
|
@@ -65,12 +65,15 @@ export function resumeSandboxPlan(current, previous, channelPort) {
|
|
|
65
65
|
*/
|
|
66
66
|
export function resumeRefusal(entry, { now = Date.now(), workLeftMs = Infinity, atShutdown = false, isDirectory = () => true, accountUnusable = () => '' } = {}) {
|
|
67
67
|
if (!entry) return 'the run is not known';
|
|
68
|
-
if (!['claude-code', 'codex', 'opencode'].includes(entry.provider)) return 'this provider cannot continue after a restart';
|
|
68
|
+
if (!['claude-code', 'codex', 'opencode', 'antigravity'].includes(entry.provider)) return 'this provider cannot continue after a restart';
|
|
69
69
|
if (entry.confinement?.kind === 'skill-eval') return 'a skill evaluation run is a measurement and starts over instead';
|
|
70
70
|
if (entry.confinement) return 'a skill drafting run is not resumed';
|
|
71
71
|
if (entry.removedAt) return 'the run was removed';
|
|
72
|
-
if (!(entry.provider === 'codex' ? entry.providerThreadId : entry.providerSessionId)) return `its ${entry.provider === 'codex' ? 'Codex thread' : entry.provider === 'opencode' ? 'OpenCode session' : 'Claude session'} had not started yet`;
|
|
72
|
+
if (!(entry.provider === 'codex' ? entry.providerThreadId : entry.providerSessionId)) return `its ${entry.provider === 'codex' ? 'Codex thread' : entry.provider === 'opencode' ? 'OpenCode session' : entry.provider === 'antigravity' ? 'Antigravity session' : 'Claude session'} had not started yet`;
|
|
73
73
|
if (entry.provider === 'opencode' && !entry.resumeInfo?.persistentOpenCode) return 'its OpenCode session has no durable run data';
|
|
74
|
+
// Antigravity keeps the conversation in the run's own home (lib/antigravity/home.js): a run started before homes
|
|
75
|
+
// existed has its session in the user's own ~/.gemini, which a resume does not use.
|
|
76
|
+
if (entry.provider === 'antigravity' && !entry.resumeInfo?.antigravityHome) return 'its Antigravity session has no SynaBun home to resume from';
|
|
74
77
|
const resumes = Number(entry.resumes) || 0;
|
|
75
78
|
if (resumes >= MAX_RESUMES) return `it was resumed ${resumes} times already`;
|
|
76
79
|
if (!(workLeftMs > 0)) return entry.maxMinutes ? `its ${entry.maxMinutes} minutes of work time are used up` : 'its work time is used up';
|
|
@@ -79,7 +82,8 @@ export function resumeRefusal(entry, { now = Date.now(), workLeftMs = Infinity,
|
|
|
79
82
|
if (since && now - since > RESUME_WINDOW_MS) return `the server was back ${Math.round((now - since) / 60_000)} minutes later (more than ${Math.round(RESUME_WINDOW_MS / 60_000)})`;
|
|
80
83
|
if (!entry.cwd || !isDirectory(entry.cwd)) return `its working directory is gone (${entry.cwd || 'none'})`;
|
|
81
84
|
let unusable = '';
|
|
82
|
-
|
|
85
|
+
// OpenCode and Antigravity sign in inside their own CLI: SynaBun keeps no account of theirs.
|
|
86
|
+
try { unusable = entry.provider === 'opencode' || entry.provider === 'antigravity' ? '' : String(accountUnusable((entry.provider === 'codex' ? entry.codexAccountId : entry.claudeAccountId) || 'default', entry.provider, entry) || ''); } catch (error) { unusable = error?.message || 'it could not be read'; }
|
|
83
87
|
if (unusable) return `its ${entry.provider === 'codex' ? 'Codex' : 'Claude'} account (${entry.codexAccountId || entry.claudeAccountId || 'default'}) cannot be used: ${unusable}`;
|
|
84
88
|
return null;
|
|
85
89
|
}
|
|
@@ -184,7 +188,12 @@ export function processCommandLine(pid, { platform = process.platform, run = exe
|
|
|
184
188
|
*/
|
|
185
189
|
export function isRunCliCommand(command, runId) {
|
|
186
190
|
const text = String(command || '');
|
|
187
|
-
return !!runId && text.includes(String(runId)) && (
|
|
191
|
+
return !!runId && text.includes(String(runId)) && (
|
|
192
|
+
(text.includes('--input-format') && text.includes('stream-json'))
|
|
193
|
+
|| (text.includes('app-server') && text.includes('synabun_worker_run='))
|
|
194
|
+
// Antigravity: `agy acp --gemini-dir <data home>/runtime/antigravity/homes/run-<run id>-…` (lib/antigravity/home.js).
|
|
195
|
+
|| (/\sacp(?:\s|$)/.test(text) && text.includes('--gemini-dir') && /[\\/]antigravity[\\/]homes[\\/]run-/.test(text))
|
|
196
|
+
);
|
|
188
197
|
}
|
|
189
198
|
|
|
190
199
|
/** Windows: end a process and every process it started (taskkill /T /F, as the server's own shutdown does). */
|
|
@@ -19,13 +19,32 @@
|
|
|
19
19
|
// interface IPs and its hostname — while a different port and the public internet stay open. The earlier
|
|
20
20
|
// `localhost:<port>` literal did NOT cover [::ffff:127.0.0.1] (a verified full bypass of the whole layer on the
|
|
21
21
|
// dual-stack listener): Seatbelt's `localhost` resolves to 127.0.0.1 + ::1 only. The host literal must be `*`
|
|
22
|
-
// or `localhost` (a numeric IP literal
|
|
22
|
+
// or `localhost` (a numeric IP literal, with or without a CIDR suffix, is rejected by the parser: "host must be
|
|
23
|
+
// * or localhost in network address"); `*` is the only form that is address-proof.
|
|
23
24
|
// Seatbelt has no port-range syntax (`*:4120-4400` is rejected), so a reserved range is emitted one port a line.
|
|
24
25
|
// • `(deny file-read* file-write* (subpath "<canonical>"))` blocks reads AND writes under a path; a later
|
|
25
26
|
// `(allow file-read* file-write* (subpath "<canonical>"))` wins (Seatbelt is last-match-wins within a filter),
|
|
26
27
|
// so SynaBun's whole data home can be denied and the run's own scratch / cwd / config folder allowed back after
|
|
27
28
|
// it. Seatbelt matches the RESOLVED path, so every literal must be canonicalised (/tmp is a symlink to
|
|
28
29
|
// /private/tmp; an un-resolved literal never matches, and an allow-back must resolve the same way as its deny).
|
|
30
|
+
// • macOS 27 (27.2 / 26B123, confirmed with scratch sandbox-exec probes outside the repo, 2026-11-01): a
|
|
31
|
+
// `(deny network-outbound (remote ip …))` rule placed textually AFTER an `(allow network-outbound (remote ip
|
|
32
|
+
// …))` rule silently defeats that allow — even when the deny's port is completely unrelated to the allow's
|
|
33
|
+
// (e.g. a later `deny *:4096` broke an earlier `allow localhost:9` for a different, unrelated port 9). This
|
|
34
|
+
// held on every literal form tried (`localhost` and `*` alike), so it is not about the host literal at all —
|
|
35
|
+
// it is purely textual position. A deny is never undone by what comes after it, and a later allow for one port
|
|
36
|
+
// never reopens a different, already-denied port — only "deny AFTER allow, different port" misbehaves. A
|
|
37
|
+
// same-port pair (a broad `*:<port>` allow immediately followed by a narrower `localhost:<port>` deny, the
|
|
38
|
+
// INTERNET_PORTS local-redeny below) still narrows correctly on 27.2: last-match-wins for an overlapping
|
|
39
|
+
// filter is unaffected, confirmed by direct probe. The fix is purely about ORDER, so buildWorkerSandboxProfile
|
|
40
|
+
// emits every plain port/range deny FIRST, then the strict profile's own allow-then-narrow pair for
|
|
41
|
+
// INTERNET_PORTS, then the worker-channel allow(s) dead last among network-outbound rules — nothing (deny)
|
|
42
|
+
// ever follows them, on macOS 26 or 27. This does not widen anything: the channel allow keeps the narrow
|
|
43
|
+
// `localhost:<port>` literal (still local-only on both macOS versions), and the reorder also fixes a second,
|
|
44
|
+
// previously-undetected collateral regression — the strict profile's own INTERNET_PORTS allow-back (meant to
|
|
45
|
+
// keep DNS/SSH/HTTP/HTTPS reachable on real remote hosts) was equally defeated by the later control-port and
|
|
46
|
+
// reserved-range denies that used to sit between it and nothing; a guarded worker in the strict fallback had
|
|
47
|
+
// silently lost the public internet too.
|
|
29
48
|
// • The sandbox is inherited by detached / nohup grandchildren, so a worker cannot escape it by backgrounding.
|
|
30
49
|
// • A same-user `KERN_PROCARGS2` read (ps -E / a tiny C program) CANNOT be blocked by Seatbelt (it is a same-uid
|
|
31
50
|
// kernel allowance, not a sandbox-governed operation). So a worker inside the sandbox can still read another
|
|
@@ -166,6 +185,10 @@ function metadataAncestors(allowPaths, denyPaths) {
|
|
|
166
185
|
* spelling (the IPv4-mapped one included); Seatbelt's `localhost` misses [::ffff:…],
|
|
167
186
|
* and mixing `ip6` rules with `localhost` ones silently re-opens IPv4 loopback (verified
|
|
168
187
|
* on macOS 26), so this is written as deny-all-then-allow, never as a loopback deny.
|
|
188
|
+
* On macOS 27 a later deny for an unrelated port defeats an earlier allow (see the
|
|
189
|
+
* module header), so every network-outbound ALLOW rule this emits — the strict
|
|
190
|
+
* profile's INTERNET_PORTS allow-back and the channel allow(s) — is placed after
|
|
191
|
+
* every plain port/range deny, with the channel allow(s) last of all.
|
|
169
192
|
* @param {string} [o.note] a short comment line (the run id), for readability in a log.
|
|
170
193
|
* @returns {string} the profile text (ends with a newline).
|
|
171
194
|
*/
|
|
@@ -177,34 +200,41 @@ export function buildWorkerSandboxProfile({ denyPorts = [], denyLocalPorts = [],
|
|
|
177
200
|
? { from: Math.max(1, Number(denyPortRange.from)), to: Math.min(65535, Number(denyPortRange.to)) } : null;
|
|
178
201
|
const denies = [...new Set((denyPaths || []).filter((p) => typeof p === 'string' && p).map(canonicalPath))];
|
|
179
202
|
const allows = [...new Set((allowPaths || []).filter((p) => typeof p === 'string' && p).map(canonicalPath))];
|
|
203
|
+
const channelPorts = strictLocal ? cleanPorts(strictLocal.allowPorts) : [];
|
|
180
204
|
const lines = ['(version 1)'];
|
|
181
205
|
if (note) lines.push(`; ${String(note).replace(/[\r\n]+/g, ' ').slice(0, 200)}`);
|
|
182
206
|
lines.push('(allow default)');
|
|
183
207
|
if (strictLocal) {
|
|
184
208
|
// Detection failed: nothing local is known to be safe, so nothing local is reachable but the worker channel.
|
|
185
|
-
// Deny every outbound IP connection, allow the internet's ports back on every host, take them away again on this
|
|
186
|
-
// computer's own addresses, and allow the channel last (last match wins).
|
|
187
209
|
lines.push('; strict: the relay detection failed for this run, so no local port is reachable but the worker channel');
|
|
188
210
|
lines.push(`(deny network-outbound (remote ip ${sexpr('*:*')}))`);
|
|
189
|
-
for (const port of INTERNET_PORTS) lines.push(`(allow network-outbound (remote ip ${sexpr(`*:${port}`)}))`);
|
|
190
|
-
for (const port of INTERNET_PORTS) if (port !== 53) localOnly.add(port); // a local DNS resolver stays reachable
|
|
191
|
-
for (const port of cleanPorts(strictLocal.allowPorts)) {
|
|
192
|
-
localOnly.delete(port);
|
|
193
|
-
lines.push(`(allow network-outbound (remote ip ${sexpr(`localhost:${port}`)}))`);
|
|
194
|
-
}
|
|
195
211
|
}
|
|
196
|
-
// The control ports
|
|
197
|
-
//
|
|
198
|
-
//
|
|
212
|
+
// The control ports and the reserved relay range FIRST, before any allow rule below: on macOS 27 a later deny
|
|
213
|
+
// here would defeat an earlier allow for an unrelated port (module header). A plain deny is never undone by
|
|
214
|
+
// what follows it, so their own position relative to each other never matters.
|
|
199
215
|
const seen = new Set();
|
|
200
216
|
for (const port of ports) { seen.add(port); lines.push(`(deny network-outbound (remote ip ${sexpr(`*:${port}`)}))`); }
|
|
201
|
-
//
|
|
217
|
+
// The reserved relay range in full: every isolated OpenCode serve, whether it started before or after this profile.
|
|
218
|
+
if (range) for (let p = range.from; p <= range.to; p++) { if (!seen.has(p)) { seen.add(p); lines.push(`(deny network-outbound (remote ip ${sexpr(`*:${p}`)}))`); } }
|
|
219
|
+
if (strictLocal) {
|
|
220
|
+
// Allow the internet's ports back on every host, then narrow them to this computer's own addresses right
|
|
221
|
+
// after (same port: last-match-wins narrows it locally, unaffected by the macOS 27 ordering issue above,
|
|
222
|
+
// which is about an unrelated port's deny, not a same-port narrowing pair).
|
|
223
|
+
for (const port of INTERNET_PORTS) if (port !== 53) localOnly.add(port); // a local DNS resolver stays reachable
|
|
224
|
+
for (const port of channelPorts) localOnly.delete(port);
|
|
225
|
+
for (const port of INTERNET_PORTS) lines.push(`(allow network-outbound (remote ip ${sexpr(`*:${port}`)}))`);
|
|
226
|
+
}
|
|
227
|
+
// Local-only denies (an internet port a relay holds here, local SSH): this computer's own addresses, never the
|
|
228
|
+
// internet. In strict mode these sit right after the INTERNET_PORTS allow-back above (the same-port narrowing
|
|
229
|
+
// pair); otherwise there is no preceding allow to narrow and the position carries no ordering requirement.
|
|
202
230
|
for (const port of [...new Set([...localOnly, ...ALWAYS_LOCAL_DENY_PORTS])].sort((x, y) => x - y)) {
|
|
203
|
-
if (
|
|
231
|
+
if (channelPorts.includes(port)) continue;
|
|
204
232
|
lines.push(`(deny network-outbound (remote ip ${sexpr(`localhost:${port}`)}))`);
|
|
205
233
|
}
|
|
206
|
-
// The
|
|
207
|
-
|
|
234
|
+
// The worker channel, allowed dead last among every network-outbound rule above: on macOS 27 any later deny —
|
|
235
|
+
// even for a wholly unrelated port — would silently defeat this allow (module header). Kept local-only
|
|
236
|
+
// (`localhost:<port>`, not `*:<port>`): still unreachable from a remote host on this exact port, on macOS 26 and 27.
|
|
237
|
+
for (const port of channelPorts) lines.push(`(allow network-outbound (remote ip ${sexpr(`localhost:${port}`)}))`);
|
|
208
238
|
// SynaBun's whole data home (its auth secrets, other runs' task text, the memory DB) and other runtimes' creds:
|
|
209
239
|
// a worker neither reads nor writes them.
|
|
210
240
|
for (const path of denies) lines.push(`(deny file-read* file-write* (subpath ${sexpr(path)}))`);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neural-memory-interface",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "neural-memory-interface",
|
|
9
|
-
"version": "2.1
|
|
9
|
+
"version": "2.2.1",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"dependencies": {
|
|
13
|
+
"@agentclientprotocol/sdk": "2.2.0",
|
|
13
14
|
"@anthropic-ai/claude-agent-sdk": "0.3.288",
|
|
14
15
|
"@huggingface/transformers": "^3.0.0",
|
|
15
16
|
"@openai/codex-sdk": "^0.160.0",
|
|
@@ -57,6 +58,21 @@
|
|
|
57
58
|
"node": ">=22.19.0"
|
|
58
59
|
}
|
|
59
60
|
},
|
|
61
|
+
"node_modules/@agentclientprotocol/sdk": {
|
|
62
|
+
"version": "2.2.0",
|
|
63
|
+
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-2.2.0.tgz",
|
|
64
|
+
"integrity": "sha512-o1+eDQVb05yzPY+5v54awHyONU1oeLsbLVavkwrMQaZDuJDh/38pQiXJS4ix4d6QA3Y4bU0lHFRjwg99KKKSaQ==",
|
|
65
|
+
"license": "Apache-2.0",
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@modelcontextprotocol/server": "^2.4.0",
|
|
68
|
+
"zod": "^3.25.76 || ^4.0.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"@modelcontextprotocol/server": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
60
76
|
"node_modules/@antfu/install-pkg": {
|
|
61
77
|
"version": "2.1.0",
|
|
62
78
|
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-2.1.0.tgz",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neural-memory-interface",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Private local SynaBun interface for memory visualization and multi-agent workflows",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"postinstall": "node scripts/rebuild-pty.js && node scripts/build-vendor.mjs"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"@agentclientprotocol/sdk": "2.2.0",
|
|
24
25
|
"@anthropic-ai/claude-agent-sdk": "0.3.288",
|
|
25
26
|
"@huggingface/transformers": "^3.0.0",
|
|
26
27
|
"@openai/codex-sdk": "^0.160.0",
|
|
@@ -1489,7 +1489,7 @@ const wizardState = {
|
|
|
1489
1489
|
// `id` is also the host name of the rules API (/api/setup/rules/:host).
|
|
1490
1490
|
const TOOLS = [
|
|
1491
1491
|
{ id: 'claude', name: 'Claude Code', api: '/api/claude-code/mcp', configPath: '~/.claude.json' },
|
|
1492
|
-
{ id: '
|
|
1492
|
+
{ id: 'antigravity', name: 'Antigravity CLI', api: '/api/setup/antigravity/mcp', configPath: '~/.gemini/config/mcp_config.json' },
|
|
1493
1493
|
{ id: 'codex', name: 'Codex CLI', api: '/api/setup/codex/mcp', configPath: '~/.codex/config.toml' },
|
|
1494
1494
|
{ id: 'opencode', name: 'OpenCode', api: '/api/opencode/mcp', configPath: '~/.config/opencode/opencode.json' },
|
|
1495
1495
|
];
|
|
@@ -6,16 +6,36 @@ import { fetchOpencodeProviders, opencodeProviders } from './opencode-providers.
|
|
|
6
6
|
export const CLI_PROFILES = [
|
|
7
7
|
{ id: 'claude-code', label: 'Claude Code', desc: 'Anthropic' },
|
|
8
8
|
{ id: 'codex', label: 'Codex CLI', desc: 'OpenAI' },
|
|
9
|
-
{ id: '
|
|
9
|
+
{ id: 'antigravity', label: 'Antigravity CLI', desc: 'Google' },
|
|
10
10
|
{ id: 'opencode', label: 'OpenCode CLI', desc: 'Multi-provider' },
|
|
11
11
|
];
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
// Google Antigravity replaced the Gemini CLI (provider id `gemini` → `antigravity`). What was saved before
|
|
14
|
+
// (a launch profile, a resume tab, a template's CLI or icon) can still say `gemini`: it reads as Antigravity.
|
|
15
|
+
// The server moves its own files the same way (lib/antigravity/migrate-gemini.js).
|
|
16
|
+
export function migrateProviderId(id) { return id === 'gemini' ? 'antigravity' : id; }
|
|
17
|
+
|
|
18
|
+
// The Gemini CLI's own model ids (gemini-1.x, gemini-2.x) are not Antigravity's: one saved for it reads as
|
|
19
|
+
// none, so Antigravity's default runs (the same rule as isGeminiCliModel in lib/antigravity/migrate-gemini.js).
|
|
20
|
+
const GEMINI_CLI_MODEL_RE = /^gemini-[12](?:[.-]|$)/i;
|
|
21
|
+
export function migrateProviderModel(profileId, model) {
|
|
22
|
+
return migrateProviderId(profileId) === 'antigravity' && typeof model === 'string' && GEMINI_CLI_MODEL_RE.test(model.trim()) ? null : model;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Saved launch records (loop templates, schedules, groups, timers) with a Gemini CLI profile or icon read as Antigravity's. */
|
|
26
|
+
export function migrateLaunchRecords(list) {
|
|
27
|
+
if (!Array.isArray(list)) return list;
|
|
28
|
+
return list.map((record) => {
|
|
29
|
+
if (!record || typeof record !== 'object' || (record.profile !== 'gemini' && record.icon !== 'gemini')) return record;
|
|
30
|
+
const next = { ...record };
|
|
31
|
+
if (next.icon === 'gemini') next.icon = migrateProviderId(next.icon);
|
|
32
|
+
if (next.profile === 'gemini') {
|
|
33
|
+
next.profile = migrateProviderId(next.profile);
|
|
34
|
+
if (migrateProviderModel(next.profile, next.model) !== next.model) next.model = null;
|
|
35
|
+
}
|
|
36
|
+
return next;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
19
39
|
|
|
20
40
|
// Claude Code models are discovered live from the installed CLI via
|
|
21
41
|
// /api/claude/models (see lib/claude-model-catalog.js) — the CLI is the only
|
|
@@ -59,6 +79,15 @@ export const EFFORT_LEVELS_BY_PROFILE = {
|
|
|
59
79
|
{ id: 'max', label: 'Max', desc: 'Maximum' },
|
|
60
80
|
{ id: 'ultra', label: 'Ultra', desc: 'Maximum, with delegation', tier: 'top' },
|
|
61
81
|
],
|
|
82
|
+
// The levels `agy --effort` takes; `off` passes none, so Antigravity uses its own default.
|
|
83
|
+
antigravity: [
|
|
84
|
+
{ id: 'off', label: 'Default', desc: 'Model default' },
|
|
85
|
+
{ id: 'low', label: 'Low', desc: 'Light' },
|
|
86
|
+
{ id: 'medium', label: 'Med', desc: 'Balanced' },
|
|
87
|
+
{ id: 'high', label: 'High', desc: 'Deep' },
|
|
88
|
+
{ id: 'xhigh', label: 'XHigh', desc: 'Very deep' },
|
|
89
|
+
{ id: 'max', label: 'Max', desc: 'Maximum', tier: 'top' },
|
|
90
|
+
],
|
|
62
91
|
};
|
|
63
92
|
|
|
64
93
|
// One effort vocabulary, lowest first (the server keeps the same table in
|
|
@@ -145,14 +174,16 @@ let _opencodeModelsCache = null;
|
|
|
145
174
|
let _opencodeModelsLoading = null;
|
|
146
175
|
let _claudeModelsCache = null;
|
|
147
176
|
let _claudeModelsLoading = null;
|
|
177
|
+
let _antigravityModelsCache = null;
|
|
178
|
+
let _antigravityModelsLoading = null;
|
|
148
179
|
let _toolCatalog = null;
|
|
149
180
|
const _toolCatalogLoads = new Map();
|
|
150
181
|
const _toolCatalogByCwd = new Map();
|
|
151
182
|
const _toolCatalogAt = new Map();
|
|
152
183
|
let _toolCatalogEpoch = 0;
|
|
153
184
|
|
|
154
|
-
// The verified Claude and
|
|
155
|
-
// pickers paint from them at once (a list read back is due, so the first load still asks the server).
|
|
185
|
+
// The verified Claude, Codex and Antigravity lists are also kept in sessionStorage (this tab only): after a reload
|
|
186
|
+
// the pickers paint from them at once (a list read back is due, so the first load still asks the server).
|
|
156
187
|
const LIST_STORE_PREFIX = 'synabun:runtime-models:v1:';
|
|
157
188
|
function keepList(key, list) {
|
|
158
189
|
try { if (typeof sessionStorage !== 'undefined') sessionStorage.setItem(LIST_STORE_PREFIX + key, JSON.stringify(list)); } catch { /* full or unavailable */ }
|
|
@@ -169,6 +200,8 @@ function keptList(key) {
|
|
|
169
200
|
if (claude && !_claudeModelsCache) _claudeModelsCache = claude;
|
|
170
201
|
const codex = keptList('codex:default');
|
|
171
202
|
if (codex && !_codexModelsCache.has('default')) _codexModelsCache.set('default', codex);
|
|
203
|
+
const antigravity = keptList('antigravity');
|
|
204
|
+
if (antigravity && !_antigravityModelsCache) _antigravityModelsCache = antigravity;
|
|
172
205
|
})();
|
|
173
206
|
|
|
174
207
|
function localJsonArray(key) {
|
|
@@ -538,16 +571,59 @@ export async function fetchClaudeModels(force = false) {
|
|
|
538
571
|
return _claudeModelsLoading;
|
|
539
572
|
}
|
|
540
573
|
|
|
574
|
+
// GET /api/antigravity/models answers { models: [{ id, label, description?, default? }], source: 'live' | 'unavailable' }.
|
|
575
|
+
function antigravityModelOption(model) {
|
|
576
|
+
const id = String(model?.id || '').trim();
|
|
577
|
+
if (!id) return null;
|
|
578
|
+
return {
|
|
579
|
+
id,
|
|
580
|
+
provider: 'antigravity',
|
|
581
|
+
cliReady: true,
|
|
582
|
+
label: String(model.label || id),
|
|
583
|
+
desc: String(model.description || ''),
|
|
584
|
+
...(model.default === true ? { tier: 'default', isDefault: true } : {}),
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Antigravity's models come only from the installed `agy`: there is no list of SynaBun's own to fall back on,
|
|
589
|
+
// so until it answers the pickers are empty and a launch runs Antigravity's default. A list it gave once is
|
|
590
|
+
// kept through a failed or unavailable answer.
|
|
591
|
+
export async function fetchAntigravityModels(force = false) {
|
|
592
|
+
if (!force && _antigravityModelsCache?.length && modelListIsFresh('antigravity')) return _antigravityModelsCache;
|
|
593
|
+
if (_antigravityModelsLoading) return _antigravityModelsLoading;
|
|
594
|
+
_antigravityModelsLoading = (async () => {
|
|
595
|
+
try {
|
|
596
|
+
const resp = await fetch('/api/antigravity/models');
|
|
597
|
+
const data = await resp.json().catch(() => ({}));
|
|
598
|
+
const models = resp.ok && data?.source !== 'unavailable' && Array.isArray(data?.models)
|
|
599
|
+
? data.models.map(antigravityModelOption).filter(Boolean)
|
|
600
|
+
: [];
|
|
601
|
+
if (models.length) {
|
|
602
|
+
_antigravityModelsCache = models;
|
|
603
|
+
_modelListAt.set('antigravity', Date.now());
|
|
604
|
+
keepList('antigravity', models);
|
|
605
|
+
}
|
|
606
|
+
return _antigravityModelsCache || [];
|
|
607
|
+
} catch {
|
|
608
|
+
return _antigravityModelsCache || [];
|
|
609
|
+
} finally {
|
|
610
|
+
_antigravityModelsLoading = null;
|
|
611
|
+
}
|
|
612
|
+
})();
|
|
613
|
+
return _antigravityModelsLoading;
|
|
614
|
+
}
|
|
615
|
+
|
|
541
616
|
// Profiles whose model list is fetched at runtime rather than baked in. Callers use
|
|
542
617
|
// this to decide whether to kick off an async load and re-render when it lands.
|
|
543
618
|
export function isDynamicModelProfile(profileId) {
|
|
544
|
-
return profileId === 'opencode' || profileId === 'codex' || profileId === 'claude-code';
|
|
619
|
+
return profileId === 'opencode' || profileId === 'codex' || profileId === 'claude-code' || profileId === 'antigravity';
|
|
545
620
|
}
|
|
546
621
|
|
|
547
622
|
export async function ensureModelsForProfile(profileId, force = false, accountId = 'default') {
|
|
548
623
|
if (profileId === 'codex') return fetchCodexModels(force, accountId);
|
|
549
624
|
if (profileId === 'opencode') return fetchOpencodeModels(force);
|
|
550
625
|
if (profileId === 'claude-code') return fetchClaudeModels(force);
|
|
626
|
+
if (profileId === 'antigravity') return fetchAntigravityModels(force);
|
|
551
627
|
return getModelsForProfile(profileId, accountId);
|
|
552
628
|
}
|
|
553
629
|
|
|
@@ -565,7 +641,8 @@ export function getModelsForProfile(profileId, accountId = 'default') {
|
|
|
565
641
|
if (profileId === 'codex') return _codexModelsCache.get(String(accountId || 'default')) || [];
|
|
566
642
|
if (profileId === 'opencode') return _opencodeModelsCache || keptOpencodeModels() || [];
|
|
567
643
|
if (profileId === 'claude-code') return _claudeModelsCache || [];
|
|
568
|
-
|
|
644
|
+
if (profileId === 'antigravity') return _antigravityModelsCache || [];
|
|
645
|
+
return [];
|
|
569
646
|
}
|
|
570
647
|
|
|
571
648
|
// Live Claude and Codex options are spawn-ready ids. Only legacy Claude options
|
|
@@ -678,6 +755,7 @@ export function clearRuntimeOptionCaches() {
|
|
|
678
755
|
_opencodeModelsCache = null;
|
|
679
756
|
opencodeProviders.invalidate('');
|
|
680
757
|
_claudeModelsCache = null;
|
|
758
|
+
_antigravityModelsCache = null;
|
|
681
759
|
_modelListAt.clear();
|
|
682
760
|
invalidateToolCatalog(); _toolCatalog = null; _toolCatalogByCwd.clear(); _toolCatalogAt.clear();
|
|
683
761
|
_claudeAccountsCache = null;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun — Antigravity panel: a tab's Bypass (no DOM)
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Bypass is a tab's choice, like the Claude Code panel's: off by default, turned on only by the owner in the
|
|
6
|
+
// permissions picker (after one confirm each time), saved with the tab, and stated to the bridge with every session
|
|
7
|
+
// the tab opens (`bypass` on session:new / load / resume) and at once for a running one (session:bypass). The bridge
|
|
8
|
+
// answers each permission request of that session "allow once" itself, except what SynaBun's hard rails refuse
|
|
9
|
+
// (lib/antigravity/bypass.js: the browser policy and the protected folders). A server without the `bypass`
|
|
10
|
+
// capability cannot run it: the pick waits there, shown as unavailable, and the tab asks as before.
|
|
11
|
+
|
|
12
|
+
export const PERMISSION_DEFAULT = 'default';
|
|
13
|
+
export const PERMISSION_BYPASS = 'bypass';
|
|
14
|
+
|
|
15
|
+
/** The permissions picker of a tab: its entries, the state the control is styled by and its tooltip. */
|
|
16
|
+
export function bypassControl({ bypass = false, supported = true } = {}, T = (key) => key) {
|
|
17
|
+
const on = bypass === true;
|
|
18
|
+
const entries = [
|
|
19
|
+
{ value: PERMISSION_DEFAULT, label: T('permDefault'), title: T('permDefaultHint'), selected: !on },
|
|
20
|
+
{ value: PERMISSION_BYPASS, label: T('permBypass'), title: supported ? T('permBypassHint') : T('permBypassRestart'), selected: on, disabled: !supported && !on },
|
|
21
|
+
];
|
|
22
|
+
if (on && !supported) return { entries, state: 'bypass', waiting: true, title: T('permBypassWaiting') };
|
|
23
|
+
if (on) return { entries, state: 'bypass', waiting: false, title: T('permBypassOnTitle') };
|
|
24
|
+
return { entries, state: '', waiting: false, title: supported ? T('permDefaultHint') : T('permBypassRestart') };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** What a pick in the picker does: { confirm: true } to ask first, { set: boolean } to apply, or null for no change. */
|
|
28
|
+
export function pickPermission(value, { bypass = false, supported = true } = {}) {
|
|
29
|
+
const want = value === PERMISSION_BYPASS;
|
|
30
|
+
if (want === (bypass === true)) return null;
|
|
31
|
+
if (want && !supported) return null;
|
|
32
|
+
return want ? { confirm: true } : { set: false };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A saved tab's Bypass: only a literal true counts (anything else in storage is off). */
|
|
36
|
+
export function restoredBypass(value) {
|
|
37
|
+
return value === true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A permission:auto event as one transcript row: { severity, text }. */
|
|
41
|
+
export function autoAnswerRow(message, T = (key) => key) {
|
|
42
|
+
const tool = String(message?.toolCall?.title || message?.toolCall?.kind || T('permTool')).slice(0, 160);
|
|
43
|
+
if (message?.decision === 'refused') {
|
|
44
|
+
return { severity: 'error', text: T('permAutoRefused', { tool, reason: String(message.reason || '').slice(0, 400) }) };
|
|
45
|
+
}
|
|
46
|
+
return { severity: 'info', text: T('permAutoAllowed', { tool }) };
|
|
47
|
+
}
|