synabun 2.0.10 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +13 -13
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +30 -17
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +7 -6
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +302 -0
- package/lib/virustotal.mjs +203 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.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/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.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-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- 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 +18 -11
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +22 -63
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- 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/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +14 -14
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +29 -19
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- 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/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +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 +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +642 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +81 -21
- package/mcp-server/src/services/server-instructions.ts +29 -64
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +29 -20
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +592 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3953 -228
- package/neural-interface/i18n/pt-BR.json +3901 -179
- 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 +128 -28
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- 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 +81 -15
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +1073 -200
- package/neural-interface/lib/assistant-envelope.js +156 -2
- 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 +93 -19
- package/neural-interface/lib/assistant-plan-permissions.js +25 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +245 -38
- package/neural-interface/lib/assistant-runtime.js +214 -30
- package/neural-interface/lib/assistant-task-prompt.js +87 -21
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +626 -4
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +84 -0
- package/neural-interface/lib/browser-network-guard.js +476 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +198 -38
- package/neural-interface/lib/claude-agent-bridge.js +11 -2
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +163 -154
- package/neural-interface/lib/cli-resolver.js +13 -3
- package/neural-interface/lib/cli-update-planner.js +52 -41
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +191 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +13 -10
- 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/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +35 -33
- package/neural-interface/lib/mcp-external-servers.js +332 -0
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +177 -25
- package/neural-interface/lib/native-loop-providers.js +965 -66
- package/neural-interface/lib/native-loop-runtime.js +290 -42
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +53 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +793 -0
- 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 +20 -2
- package/neural-interface/lib/rulesets/api.js +7 -6
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +180 -36
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +81 -31
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +298 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +285 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +569 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +216 -0
- package/neural-interface/lib/skills/eval-confinement.js +399 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +135 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +203 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +269 -0
- package/neural-interface/lib/skills/runtime-checks.js +358 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +530 -0
- package/neural-interface/lib/skills/telemetry.js +119 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/bridge.js +6 -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 +1268 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +238 -0
- package/neural-interface/lib/worker-sandbox.js +329 -0
- package/neural-interface/package-lock.json +34 -12
- package/neural-interface/package.json +3 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +3 -3
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +125 -31
- 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 +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +205 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +445 -82
- package/neural-interface/public/shared/assistant/asst-route.js +304 -53
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
- package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
- package/neural-interface/public/shared/assistant/asst-state.js +87 -24
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
- package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
- package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +11 -12
- package/neural-interface/public/shared/cli-status.js +11 -10
- package/neural-interface/public/shared/constants.js +5 -4
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +367 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- 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/crash-notice-view.js +168 -0
- 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 +21 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- 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 +30 -15
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- 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-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +222 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +149 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- 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-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1822 -1756
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -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 +111 -140
- package/neural-interface/public/shared/ui-claude-panel.js +376 -82
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- 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-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +33 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +10 -20
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
- package/neural-interface/public/shared/ui-navbar.js +49 -24
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +27 -15
- package/neural-interface/public/shared/ui-settings.js +683 -526
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +270 -190
- package/neural-interface/public/shared/ui-tool-updates.js +6 -4
- package/neural-interface/public/shared/ui-tooltip.js +81 -51
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +312 -59
- package/neural-interface/public/shared/ui-worker-end.js +5 -1
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +2 -2
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +4553 -2855
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +34 -12
- package/package.json +17 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +6 -6
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { OPENCODE_BRAIN_TOOLS } from './assistant-tools.js';
|
|
2
|
+
import { storedToolList, toolListRecord } from './tool-lists.js';
|
|
1
3
|
// ═══════════════════════════════════════════
|
|
2
4
|
// SynaBun — Assistant runtime (sessions, brains, unified WebSocket, mailbox)
|
|
3
5
|
// ═══════════════════════════════════════════
|
|
@@ -14,6 +16,10 @@ import { dirname, resolve } from 'node:path';
|
|
|
14
16
|
import { createClaudeBrain } from './assistant-brains/claude.js';
|
|
15
17
|
import { createCodexBrain } from './assistant-brains/codex.js';
|
|
16
18
|
import { createOpenCodeBrain } from './assistant-brains/opencode.js';
|
|
19
|
+
import { createAntigravityBrain } from './assistant-brains/antigravity.js';
|
|
20
|
+
import { acpPolicyInput, acpReadOnlyKind, acpToolName } from './antigravity/tool-call.js';
|
|
21
|
+
import { antigravityUsageTokens } from './assistant-usage.js';
|
|
22
|
+
import { UNPRICED_PROVIDER_REASON } from './assistant-budget-split.js';
|
|
17
23
|
import { buildAssistantPersona, formatMailbox, reconcileRouteItems } from './assistant-persona.js';
|
|
18
24
|
import { normalizeTestDensity, testDensityStamp } from './assistant-test-density.js';
|
|
19
25
|
import { codexUsageCostUsd, floorCents } from './assistant-budget.js';
|
|
@@ -31,13 +37,18 @@ import { codexRouteGateBootstrap } from './assistant-route-gate-codex.js';
|
|
|
31
37
|
import { proposedPlanText } from './assistant-envelope.js';
|
|
32
38
|
import { clampBrainModes, clampRouteMode, defaultRemotePolicyRegistry, effectiveLevel, isComputerTool, readRegisteredProjects, remoteBrainLimited, remoteComputerDenial, remoteComputerUse, remoteToolDenial, runExceedsPolicy } from './remote-policy.js';
|
|
33
39
|
import { browserToolDenial } from './browser-tool-policy.js';
|
|
40
|
+
import { browserPolicyRoots } from './browser-policy-roots.js';
|
|
41
|
+
import { stripFollowups } from '../public/shared/assistant/asst-followups.js';
|
|
42
|
+
import { readJsonStrict } from './rulesets/fs-safe.js';
|
|
34
43
|
|
|
35
|
-
export const BRAIN_PROVIDERS = new Set(['claude-code', 'codex', 'opencode']);
|
|
44
|
+
export const BRAIN_PROVIDERS = new Set(['claude-code', 'codex', 'opencode', 'antigravity']);
|
|
36
45
|
// Every tab is called SynaBun; the session title (the history list) comes from
|
|
37
46
|
// the first prompt. Legacy "Assistant N" titles still count as unnamed.
|
|
38
47
|
export const DEFAULT_SESSION_TITLE = 'SynaBun';
|
|
39
48
|
export function isDefaultSessionTitle(title) { return !title || /^(?:SynaBun|Assistant(?: \d+)?)$/.test(String(title).trim()); }
|
|
40
|
-
|
|
49
|
+
// suspended / resumed: a Claude Code worker a server restart cut off, and its resume on the next start
|
|
50
|
+
// (lib/assistant-dispatch.js); a run that could not be resumed arrives as interrupted, with why.
|
|
51
|
+
const MAILBOX_REASONS = new Set(['turn_completed', 'needs_input', 'permission_request', 'failed', 'interrupted', 'stalled', 'budget_warning', 'budget_exceeded', 'budget_unpriced', 'queue_started', 'user_intervened', 'stopped', 'suspended', 'resumed']);
|
|
41
52
|
// A stopped run reaches the brain when the user stopped it or it ran out of money.
|
|
42
53
|
const MAILBOX_STOP_REASONS = new Set(['user', 'budget_cap', 'session_budget_cap', 'budget_unpriced', 'budget_share']);
|
|
43
54
|
/** The `[SynaBun Budget]` line: a change of the session budget reaches the brain as one line before its next turn. */
|
|
@@ -129,25 +140,37 @@ function readJson(path, fallback) { try { return JSON.parse(readFileSync(path, '
|
|
|
129
140
|
function writeJsonAtomic(path, value) {
|
|
130
141
|
mkdirSync(dirname(path), { recursive: true });
|
|
131
142
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
try {
|
|
144
|
+
writeFileSync(tmp, JSON.stringify(value, null, 2) + '\n', 'utf8');
|
|
145
|
+
renameSync(tmp, path);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
try { rmSync(tmp, { force: true }); } catch { /* held too: the next write replaces it */ }
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
134
150
|
}
|
|
151
|
+
// What Windows answers, now and then, to a rename over a file another process holds open for a
|
|
152
|
+
// moment (an antivirus or indexer scanning it, a backup, the desktop app's pre-update snapshot).
|
|
153
|
+
const HELD_FILE_CODES = new Set(['EPERM', 'EACCES', 'EBUSY']);
|
|
154
|
+
// A write of the sessions index refused that way is tried again after these waits.
|
|
155
|
+
const INDEX_RETRY_MS = [200, 500, 1000, 2000, 5000, 10_000];
|
|
135
156
|
function clip(value, max = 200) { const text = String(value ?? '').replace(/\s+/g, ' ').trim(); return text.length > max ? `${text.slice(0, max - 1)}…` : text; }
|
|
136
157
|
|
|
137
158
|
/**
|
|
138
159
|
* A brain effort checked against its model (effort-levels.js). "off" (or a
|
|
139
160
|
* model with no levels) stays "off" for Claude and Codex, which reset to the
|
|
140
|
-
* model's default on it; OpenCode has no such variant
|
|
161
|
+
* model's default on it; OpenCode has no such variant and Antigravity's thinking
|
|
162
|
+
* level no "off" (its session keeps the model's own level), so they get null.
|
|
141
163
|
*/
|
|
142
164
|
export function checkBrainEffort(provider, model, effort, catalog) {
|
|
143
165
|
if (!effort) return null;
|
|
166
|
+
if (provider === 'antigravity' && /^(?:off|default|auto|none)$/i.test(String(effort))) return null;
|
|
144
167
|
if (!catalog) return String(effort);
|
|
145
168
|
const next = normalizeEffort({ provider, model, effort, catalog }).effort;
|
|
146
|
-
return next || (provider === 'opencode' ? null : 'off');
|
|
169
|
+
return next || (provider === 'opencode' || provider === 'antigravity' ? null : 'off');
|
|
147
170
|
}
|
|
148
171
|
|
|
149
172
|
/** `catalog` (a catalog value) checks the effort against the brain's model (effort-levels.js). */
|
|
150
|
-
export function normalizeBrain(input = {}, defaults = {}, { catalog = null } = {}) {
|
|
173
|
+
export function normalizeBrain(input = {}, defaults = {}, { catalog = null, customPresets = null } = {}) {
|
|
151
174
|
// Plan mode is a flag beside the approval mode ('plan' as a mode is the legacy form).
|
|
152
175
|
const legacyPlan = input?.permissionMode === 'plan';
|
|
153
176
|
const provider = BRAIN_PROVIDERS.has(input?.provider) ? input.provider : (BRAIN_PROVIDERS.has(defaults.provider) ? defaults.provider : 'claude-code');
|
|
@@ -158,9 +181,10 @@ export function normalizeBrain(input = {}, defaults = {}, { catalog = null } = {
|
|
|
158
181
|
model,
|
|
159
182
|
effort: checkBrainEffort(provider, model, effort, catalog),
|
|
160
183
|
agent: input?.agent ? String(input.agent) : null,
|
|
161
|
-
|
|
184
|
+
// OpenCode and Antigravity sign in inside their own CLI: SynaBun keeps no account of theirs.
|
|
185
|
+
accountId: provider === 'antigravity' ? null : input?.accountId ? String(input.accountId) : (provider === 'opencode' ? null : 'default'),
|
|
162
186
|
cwd: input?.cwd ? String(input.cwd) : (input?.project ? String(input.project) : (defaults.cwd || null)),
|
|
163
|
-
|
|
187
|
+
tools: provider === 'opencode' ? (storedToolList(input, { customPresets }) ?? storedToolList(defaults, { customPresets }) ?? [...OPENCODE_BRAIN_TOOLS]) : ['all'],
|
|
164
188
|
permissionMode: input?.permissionMode && !legacyPlan ? String(input.permissionMode) : 'default',
|
|
165
189
|
planMode: typeof input?.planMode === 'boolean' ? input.planMode : (legacyPlan || defaults?.planMode === true),
|
|
166
190
|
};
|
|
@@ -188,6 +212,7 @@ export function mergeHooks(a, b) {
|
|
|
188
212
|
}
|
|
189
213
|
|
|
190
214
|
export function createAssistantRuntime({
|
|
215
|
+
toolListOptions = () => ({}),
|
|
191
216
|
dispatcher = null,
|
|
192
217
|
claudeAccounts = null,
|
|
193
218
|
// lib/codex-accounts.js: a Codex brain whose account cannot run is refused before it starts.
|
|
@@ -199,6 +224,10 @@ export function createAssistantRuntime({
|
|
|
199
224
|
ensureIsolatedServe = null,
|
|
200
225
|
stopIsolatedServe = null,
|
|
201
226
|
setupOpencodeSidepanelConfig = null,
|
|
227
|
+
// Antigravity brains (assistant-brains/antigravity.js): the CLI's launch spec, the environment its process gets,
|
|
228
|
+
// the brain's home (lib/antigravity/home.js), SynaBun's own MCP entry there, and the policy registry and loopback
|
|
229
|
+
// address its hook asks (lib/antigravity/policy.js).
|
|
230
|
+
antigravity = null,
|
|
202
231
|
broadcastSync = () => {},
|
|
203
232
|
dataDir,
|
|
204
233
|
memory = null,
|
|
@@ -250,6 +279,7 @@ export function createAssistantRuntime({
|
|
|
250
279
|
adminSandbox = null,
|
|
251
280
|
} = {}) {
|
|
252
281
|
if (!dataDir) throw new Error('createAssistantRuntime requires dataDir');
|
|
282
|
+
const normalizeSessionBrain = (input, defaults, options) => normalizeBrain(input, defaults, { ...options, ...toolListOptions() });
|
|
253
283
|
const settings = {
|
|
254
284
|
idleDisposeMs: Math.max(60_000, Number(config.idleDisposeMinutes || 120) * 60_000),
|
|
255
285
|
// A draft (a session the panel opened, before its first prompt) with no socket attached goes after this.
|
|
@@ -314,12 +344,45 @@ export function createAssistantRuntime({
|
|
|
314
344
|
|| !!row.remote || !!row.channel || Number(row.costUsd) > 0;
|
|
315
345
|
return holds ? 'unstarted' : 'empty';
|
|
316
346
|
}
|
|
347
|
+
// Whether the index file may be written: it was read, or there was none. A file that could not be
|
|
348
|
+
// read (Windows: held by an antivirus or a backup) is never replaced by what this process holds;
|
|
349
|
+
// reading it is tried again (INDEX_RETRY_MS), and sessions made meanwhile join what it held.
|
|
350
|
+
let indexReady = false;
|
|
351
|
+
let indexReadTries = 0;
|
|
352
|
+
let indexBlockedLogged = false;
|
|
353
|
+
function readIndexRows() {
|
|
354
|
+
try {
|
|
355
|
+
const rows = readJsonStrict(indexPath);
|
|
356
|
+
if (Array.isArray(rows)) return rows;
|
|
357
|
+
const error = new Error(`${indexPath} does not hold a list`);
|
|
358
|
+
error.code = 'INVALID_JSON';
|
|
359
|
+
throw error;
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (error?.code === 'ENOENT') return [];
|
|
362
|
+
if (error?.code !== 'INVALID_JSON') throw error;
|
|
363
|
+
// A corrupt file is moved aside, never deleted, and the index starts again from what is live.
|
|
364
|
+
const aside = `${indexPath}.corrupt-${Date.now()}`;
|
|
365
|
+
renameSync(indexPath, aside);
|
|
366
|
+
log('assistant:index-corrupt', `${error.message}; moved to ${aside}`);
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
}
|
|
317
370
|
function loadIndex() {
|
|
318
|
-
|
|
319
|
-
|
|
371
|
+
let rows;
|
|
372
|
+
try { rows = readIndexRows(); } catch (error) {
|
|
373
|
+
log('assistant:index-unreadable', `${error?.code || ''} ${error?.message || String(error)}`.trim());
|
|
374
|
+
if (indexReadTries < INDEX_RETRY_MS.length) {
|
|
375
|
+
setTimeout(loadIndex, INDEX_RETRY_MS[indexReadTries++]).unref?.();
|
|
376
|
+
} else log('assistant:index-unreadable', `${indexPath} is left as it is; sessions of this run stay in memory only, until a restart reads it`);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
indexReady = true;
|
|
380
|
+
const late = sessions.size > 0; // sessions made while the file could not be read
|
|
320
381
|
let dropped = 0;
|
|
321
382
|
for (const row of rows) {
|
|
322
|
-
if (!row?.id) continue;
|
|
383
|
+
if (!row?.id || sessions.has(row.id)) continue;
|
|
384
|
+
try { row.brain = normalizeSessionBrain(row.brain); }
|
|
385
|
+
catch (error) { row.brain = { ...row.brain, tools: [], toolListError: { code: error.code, message: error.message, original: row.brain?.tools ?? row.brain?.mcpProfile } }; delete row.brain.mcpProfile; }
|
|
323
386
|
if (settleLegacyRow(row) === 'empty') { dropped += 1; continue; }
|
|
324
387
|
sessions.set(row.id, makeLive({ ...row, status: row.status === 'ended' ? 'ended' : 'idle', windowIds: [] }));
|
|
325
388
|
// A remote session nobody registered again since the restart reads as read-only.
|
|
@@ -329,16 +392,34 @@ export function createAssistantRuntime({
|
|
|
329
392
|
}
|
|
330
393
|
}
|
|
331
394
|
// The index is written again without them (and with the started marks).
|
|
332
|
-
if (dropped)
|
|
395
|
+
if (dropped) log('assistant:index', `${dropped} session record(s) without a conversation dropped`);
|
|
396
|
+
if (dropped || late) persist();
|
|
333
397
|
}
|
|
334
398
|
let persistTimer = null;
|
|
399
|
+
let persistRetries = 0; // index writes Windows refused in a row (INDEX_RETRY_MS)
|
|
335
400
|
function persist({ force = false } = {}) {
|
|
336
401
|
const write = () => {
|
|
402
|
+
if (!indexReady) {
|
|
403
|
+
if (!indexBlockedLogged) { indexBlockedLogged = true; log('assistant:index', 'not written: the sessions index has not been read'); }
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
337
406
|
// A draft is never written: it exists on disk only once its first prompt was sent (startChat).
|
|
338
407
|
const rows = [...sessions.values()].filter((live) => !live.draft).map((live) => publicRecord(live.record, { withLive: false, persisted: true }))
|
|
339
408
|
.sort((a, b) => String(b.updatedAt || '').localeCompare(String(a.updatedAt || '')))
|
|
340
409
|
.slice(0, settings.retention);
|
|
341
|
-
try {
|
|
410
|
+
try {
|
|
411
|
+
writeJsonAtomic(indexPath, rows);
|
|
412
|
+
persistRetries = 0;
|
|
413
|
+
} catch (error) {
|
|
414
|
+
log('assistant:index-error', error?.message || String(error));
|
|
415
|
+
// The records changed (a rename already answered as saved, among them) and the file did not: on
|
|
416
|
+
// Windows it is written again shortly, with whatever the records hold by then, instead of waiting
|
|
417
|
+
// for the next change (a restart before it would bring the old records back).
|
|
418
|
+
if (process.platform === 'win32' && HELD_FILE_CODES.has(error?.code) && persistRetries < INDEX_RETRY_MS.length && !persistTimer) {
|
|
419
|
+
persistTimer = setTimeout(() => { persistTimer = null; write(); }, INDEX_RETRY_MS[persistRetries++]);
|
|
420
|
+
persistTimer.unref?.();
|
|
421
|
+
} else persistRetries = 0;
|
|
422
|
+
}
|
|
342
423
|
};
|
|
343
424
|
if (force) { if (persistTimer) { clearTimeout(persistTimer); persistTimer = null; } write(); return; }
|
|
344
425
|
if (persistTimer) return;
|
|
@@ -379,7 +460,7 @@ export function createAssistantRuntime({
|
|
|
379
460
|
// Claude brains: the turns sent, keyed by their final text, for the in-process recall hook.
|
|
380
461
|
turnMeta: new Map(),
|
|
381
462
|
desktopGrant: null,
|
|
382
|
-
//
|
|
463
|
+
// This brain launch's credential (mintBrainCredential): this launch only, never persisted.
|
|
383
464
|
brainCredential: null,
|
|
384
465
|
// Route gate (assistant-route-gate.js): one per session while routing is wired.
|
|
385
466
|
// gatePluginAt: when the OpenCode serve loaded the gate plugin (until then, reactive).
|
|
@@ -903,17 +984,19 @@ export function createAssistantRuntime({
|
|
|
903
984
|
if (!disabled && !defaultIsHidden(value, provider) && !providerAllHidden(value, provider)) return { brain, fallback: null };
|
|
904
985
|
const note = (reason, row, to) => ({ reason, from: reason === 'model' ? model : provider, fromProvider: provider, to: row.id, provider: to, label: row.label || row.id });
|
|
905
986
|
const same = enabledStandIn(value, provider, model);
|
|
906
|
-
if (same) return { brain:
|
|
987
|
+
if (same) return { brain: normalizeSessionBrain({ ...brain, model: same.id }, {}, { catalog: value }), fallback: disabled ? note('model', same, provider) : null };
|
|
907
988
|
// Every model of this provider is disabled (or an OpenCode model is, whose default is OpenCode's own).
|
|
908
989
|
if (!fallback) throw disabled ? modelDisabledError(model) : everyModelDisabledError(provider);
|
|
909
990
|
const other = [settings.defaultBrain.provider, 'claude-code'].find((p) => BRAIN_PROVIDERS.has(p) && p !== provider);
|
|
910
991
|
const row = other ? enabledStandIn(value, other) : null;
|
|
911
992
|
if (!row) throw disabled ? modelDisabledError(model) : everyModelDisabledError(provider);
|
|
912
|
-
const next =
|
|
993
|
+
const next = normalizeSessionBrain({ provider: other, model: row.id, cwd: brain.cwd, tools: brain.tools, permissionMode: 'default' }, {}, { catalog: value });
|
|
913
994
|
return { brain: next, fallback: note(disabled ? 'model' : 'provider', row, other) };
|
|
914
995
|
}
|
|
915
996
|
function publicRecord(record, { withLive = true, live = null, persisted = false } = {}) {
|
|
916
997
|
const out = { ...record };
|
|
998
|
+
// Run 4 removes the old brain picker projection; persisted records use only tools.
|
|
999
|
+
if (!persisted) out.brain = toolListRecord(record.brain, toolListOptions());
|
|
917
1000
|
if (!persisted) delete out.usageState;
|
|
918
1001
|
// The user-context state (frozen digest, delivery ledgers) is the server's own.
|
|
919
1002
|
if (!persisted) delete out.userContext;
|
|
@@ -1012,7 +1095,8 @@ export function createAssistantRuntime({
|
|
|
1012
1095
|
// A run the dispatcher dropped has ended: its tokens stay, under a short name.
|
|
1013
1096
|
if (!run) return { ...agent, title: `Run ${String(agent.runId || agent.key).slice(0, 8)}`, state: 'done' };
|
|
1014
1097
|
const state = run.state || 'idle';
|
|
1015
|
-
|
|
1098
|
+
// A run a server restart cut off: suspended (its turn waits for the server) reads as running, resuming as queued.
|
|
1099
|
+
const displayState = state === 'completed' ? 'done' : state === 'starting' || state === 'awaiting_route' || state === 'resuming' ? 'queued' : state === 'awaiting_permission' || state === 'suspended' ? 'running' : state === 'interrupted' ? 'stopped' : state;
|
|
1016
1100
|
return { ...agent, title: run.title || agent.runId, state: ['queued', 'running', 'idle', 'done', 'failed', 'stopped'].includes(displayState) ? displayState : 'idle' };
|
|
1017
1101
|
});
|
|
1018
1102
|
if (live?.running && currentTask(sessionId) === view.task.id && !view.task.agents.some((agent) => agent.key === 'brain')) {
|
|
@@ -1287,7 +1371,8 @@ export function createAssistantRuntime({
|
|
|
1287
1371
|
if (event.subtype === 'error_max_budget_usd' && live.brainProvider === 'claude-code') live.brainCapHit = true;
|
|
1288
1372
|
if (live.planTurn) live.planText = planTurnText(event);
|
|
1289
1373
|
// The reply the user's next message answers (context for the learning loop; a subagent's result is not it).
|
|
1290
|
-
|
|
1374
|
+
// The follow-ups block is the panel's buttons, not words of the reply.
|
|
1375
|
+
if (typeof event.result === 'string' && event.result.trim() && !event.parent_tool_use_id) live.lastReply = clip(stripFollowups(event.result), 600);
|
|
1291
1376
|
touch(live);
|
|
1292
1377
|
}
|
|
1293
1378
|
if (TRANSCRIPT_EVENT_TYPES.has(event.type) && !(event.type === 'system' && event.subtype !== 'init')) appendTranscript(id, { at: iso(now()), packet });
|
|
@@ -1813,6 +1898,8 @@ export function createAssistantRuntime({
|
|
|
1813
1898
|
function brainCostBasis(live) {
|
|
1814
1899
|
const brain = live.record.brain || {};
|
|
1815
1900
|
if (brain.provider === 'claude-code') return 'reported';
|
|
1901
|
+
// Antigravity reports tokens, not prices: its spend has no dollar figure.
|
|
1902
|
+
if (brain.provider === 'antigravity') return null;
|
|
1816
1903
|
const info = brainCapabilities(live.record) || {};
|
|
1817
1904
|
if (brain.provider === 'codex') {
|
|
1818
1905
|
if (!pricing?.codexPrice) return null;
|
|
@@ -1854,6 +1941,10 @@ export function createAssistantRuntime({
|
|
|
1854
1941
|
const money = sessionMoney(live.record.id);
|
|
1855
1942
|
if (!money || money.unlimited) return null;
|
|
1856
1943
|
// Fail closed: a brain whose spend has no price could spend past the budget.
|
|
1944
|
+
// Antigravity has no price at all (whatever the pricing tables): a dollar budget cannot hold its turns.
|
|
1945
|
+
if (live.record.brain?.provider === 'antigravity') {
|
|
1946
|
+
return { code: 'BRAIN_UNPRICED', message: `${UNPRICED_PROVIDER_REASON}, so the session budget cannot hold an Antigravity brain's spend. Switch the budget to No limit in ⋯ → Budget…, or pick another provider for the brain.` };
|
|
1947
|
+
}
|
|
1857
1948
|
if (pricing && brainCostBasis(live) === null) {
|
|
1858
1949
|
const model = live.record.brain?.model || brainCapabilities(live.record)?.id || 'its default model';
|
|
1859
1950
|
return { code: 'BRAIN_UNPRICED', message: `No price is known for the ${live.record.brain?.provider || ''} brain model ${model}, so the session budget cannot hold its spend. Pick a priced or free model for the brain, or switch the budget to No limit.` };
|
|
@@ -1937,7 +2028,7 @@ export function createAssistantRuntime({
|
|
|
1937
2028
|
brain,
|
|
1938
2029
|
project: live.record.project || 'global',
|
|
1939
2030
|
toolPrefix: brain.provider === 'claude-code' ? 'mcp__SynaBun__' : 'SynaBun_',
|
|
1940
|
-
catalog: { models: catalogValue.models || {}, accounts: catalogValue.accounts || {}, projects: catalogValue.projects || [],
|
|
2031
|
+
catalog: { models: catalogValue.models || {}, accounts: catalogValue.accounts || {}, projects: catalogValue.projects || [], tools: catalogValue.tools },
|
|
1941
2032
|
limits: dispatcher?.refreshLimits?.() || dispatcher?.limits || {},
|
|
1942
2033
|
defaults: settings.defaultBrain,
|
|
1943
2034
|
extra: settings.personaExtra,
|
|
@@ -2003,9 +2094,12 @@ export function createAssistantRuntime({
|
|
|
2003
2094
|
live.computerGrantLive = false;
|
|
2004
2095
|
} catch (error) { log('assistant:desktop-grant-error', error?.message || String(error)); }
|
|
2005
2096
|
}
|
|
2006
|
-
//
|
|
2007
|
-
//
|
|
2008
|
-
|
|
2097
|
+
// One credential per brain launch (BRAIN_CREDENTIAL_RE), for that brain's SynaBun MCP server alone: how SynaBun
|
|
2098
|
+
// knows a call comes from this session's own brain, never from a process that only sent X-Synabun-Role or
|
|
2099
|
+
// X-Synabun-Terminal. Skill creation (lib/skills/creation-api.js) and the Skills Service's assistant author
|
|
2100
|
+
// (lib/skills/api-v2.js principalOf) take it; whatsapp_send_file takes it and then only the active WhatsApp
|
|
2101
|
+
// conversation's session (lib/whatsapp/service.js sendFile).
|
|
2102
|
+
live.brainCredential = mintBrainCredential();
|
|
2009
2103
|
const cliCap = brain.provider === 'claude-code' ? brainCliCap(live) : null;
|
|
2010
2104
|
const deps = {
|
|
2011
2105
|
ClaudeSession, sdkVersion, PACKAGE_ROOT, handleCodexSkinWebSocket, ensureIsolatedServe, stopIsolatedServe, setupOpencodeSidepanelConfig,
|
|
@@ -2038,6 +2132,8 @@ export function createAssistantRuntime({
|
|
|
2038
2132
|
remoteReadOnly: !!remote && remoteBrainLimited(brain.provider),
|
|
2039
2133
|
// The engine keeps this conversation's thread record: pre-compact.mjs asks for no conversation memory.
|
|
2040
2134
|
userContextThreads: brain.provider === 'claude-code' && userSuffix.nudges === true,
|
|
2135
|
+
// Antigravity (assistant-brains/antigravity.js): where it runs, and what its policy hook asks of this session.
|
|
2136
|
+
...(brain.provider === 'antigravity' ? antigravityBrainDeps(live) : {}),
|
|
2041
2137
|
};
|
|
2042
2138
|
const gate = ensureGate(live);
|
|
2043
2139
|
// A remote session's hook / plugin refuses a call it could not check (fail closed).
|
|
@@ -2047,7 +2143,7 @@ export function createAssistantRuntime({
|
|
|
2047
2143
|
? () => codexGateBootstrap({ url: gateUrl, session: live.record.id, token: live.gateToken, codexBin: typeof codexBin === 'function' ? codexBin() : codexBin, ...(remote ? { remote: true } : {}) })
|
|
2048
2144
|
: async () => null;
|
|
2049
2145
|
}
|
|
2050
|
-
const factories = brainFactories || { 'claude-code': createClaudeBrain, codex: createCodexBrain, opencode: createOpenCodeBrain };
|
|
2146
|
+
const factories = brainFactories || { 'claude-code': createClaudeBrain, codex: createCodexBrain, opencode: createOpenCodeBrain, antigravity: createAntigravityBrain };
|
|
2051
2147
|
const factory = factories[brain.provider];
|
|
2052
2148
|
if (!factory) throw new Error(`Unsupported brain provider ${brain.provider}`);
|
|
2053
2149
|
const memoryHooks = brain.provider === 'claude-code' && memory?.claudeHooks ? memory.claudeHooks({
|
|
@@ -2698,6 +2794,7 @@ export function createAssistantRuntime({
|
|
|
2698
2794
|
if (message.type === 'assistant:permission-request') {
|
|
2699
2795
|
sendToSockets(live, { type: 'event', event: { type: 'synabun.dispatch_control_request', runId: message.runId, request_id: message.request?.requestId, provider: dispatcher?.get?.(message.runId)?.provider || null, request: message.request } });
|
|
2700
2796
|
} else if (message.type === 'assistant:permission-resolved') {
|
|
2797
|
+
live.mailbox = live.mailbox.filter((item) => !(item.run?.runId === message.runId && item.request?.requestId === message.requestId));
|
|
2701
2798
|
sendToSockets(live, { type: 'event', event: { type: 'synabun.dispatch_control_resolved', runId: message.runId, request_id: message.requestId, resolvedBy: message.resolvedBy, behavior: message.behavior } });
|
|
2702
2799
|
}
|
|
2703
2800
|
}
|
|
@@ -2778,8 +2875,9 @@ export function createAssistantRuntime({
|
|
|
2778
2875
|
return { ...brain, accountId: row.id };
|
|
2779
2876
|
}
|
|
2780
2877
|
async function createSession({ brain = {}, label = null, cwd = null, windowId = null, fallback = false, channel = null, draft = false } = {}, internal = {}) {
|
|
2878
|
+
if (brain?.mcpProfile !== undefined) throw Object.assign(new Error('Use tools: [group ids].'), { code: 'MCP_PROFILE_REMOVED', status: 400 });
|
|
2781
2879
|
const id = `assistant-${randomUUID()}`;
|
|
2782
|
-
const requested =
|
|
2880
|
+
const requested = normalizeSessionBrain({ ...brain, cwd: brain?.cwd || cwd || settings.defaultBrain.cwd || PACKAGE_ROOT }, settings.defaultBrain, { catalog: catalog?.peek?.() || null });
|
|
2783
2881
|
const enabled = await enabledBrain(requested, { fallback: fallback === true, named: !!brain?.model });
|
|
2784
2882
|
const normalized = await resolveAutoAccount(enabled.brain);
|
|
2785
2883
|
const record = {
|
|
@@ -2856,14 +2954,17 @@ export function createAssistantRuntime({
|
|
|
2856
2954
|
// default, never from the old provider's model id.
|
|
2857
2955
|
const switching = BRAIN_PROVIDERS.has(patch.brain.provider) && patch.brain.provider !== live.record.brain.provider;
|
|
2858
2956
|
const base = switching && !patch.brain.model ? { ...live.record.brain, model: null } : live.record.brain;
|
|
2859
|
-
|
|
2957
|
+
// Public picker updates use arrays; stored records still convert on read.
|
|
2958
|
+
const input = { ...base, ...patch.brain, model: patch.brain.model || base.model };
|
|
2959
|
+
if (patch.brain.mcpProfile !== undefined) throw Object.assign(new Error('Use tools: [group ids].'), { code: 'MCP_PROFILE_REMOVED', status: 400 });
|
|
2960
|
+
let next = normalizeSessionBrain(input, base, { catalog: catalog?.peek?.() || null });
|
|
2860
2961
|
next = await resolveAutoAccount(next);
|
|
2861
2962
|
const modelChanged = next.model !== live.record.brain.model || next.provider !== live.record.brain.provider;
|
|
2862
2963
|
if (modelChanged) next = (await enabledBrain(next)).brain;
|
|
2863
2964
|
// A remote session keeps what was asked for and runs what its level allows.
|
|
2864
2965
|
if ('permissionMode' in patch.brain || 'planMode' in patch.brain) next = clampModeWrite(live, next);
|
|
2865
2966
|
else next = clampedBrain(live, next);
|
|
2866
|
-
const providerChanged = patch.restartBrain === true || next.provider !== live.record.brain.provider || next.accountId !== live.record.brain.accountId || next.cwd !== live.record.brain.cwd || next.
|
|
2967
|
+
const providerChanged = patch.restartBrain === true || next.provider !== live.record.brain.provider || next.accountId !== live.record.brain.accountId || next.cwd !== live.record.brain.cwd || JSON.stringify(next.tools) !== JSON.stringify(live.record.brain.tools);
|
|
2867
2968
|
// A usage limit is the account's: another provider or account starts without the notice.
|
|
2868
2969
|
if (next.provider !== live.record.brain.provider || next.accountId !== live.record.brain.accountId) setLimit(live, null);
|
|
2869
2970
|
live.record.brain = next;
|
|
@@ -3373,7 +3474,7 @@ export function createAssistantRuntime({
|
|
|
3373
3474
|
for (const card of clarifier?.pendingCards?.(live.record.id) || []) { try { ws.send(JSON.stringify(card)); } catch {} }
|
|
3374
3475
|
return;
|
|
3375
3476
|
case 'switch_brain':
|
|
3376
|
-
await updateSession(live.record.id, { brain: { provider: msg.brain || msg.provider, model: msg.model, effort: msg.effort, accountId: msg.accountId,
|
|
3477
|
+
await updateSession(live.record.id, { brain: { provider: msg.brain || msg.provider, model: msg.model, effort: msg.effort, accountId: msg.accountId, tools: msg.tools, cwd: msg.cwd, agent: msg.agent, permissionMode: msg.permissionMode, planMode: typeof msg.planMode === 'boolean' ? msg.planMode : undefined } });
|
|
3377
3478
|
return;
|
|
3378
3479
|
case 'list_sessions': {
|
|
3379
3480
|
const rows = listSessions();
|
|
@@ -3672,6 +3773,69 @@ export function createAssistantRuntime({
|
|
|
3672
3773
|
const decision = decide(live, tool);
|
|
3673
3774
|
return decision.allow ? { allow: true } : { allow: false, reason: decision.reason, refusals: decision.refusals, stopped: !!decision.abort };
|
|
3674
3775
|
}
|
|
3776
|
+
/**
|
|
3777
|
+
* An Antigravity brain's tool call (its policy hook, lib/antigravity/policy.js), checked in this process the way
|
|
3778
|
+
* gateCheck checks the OpenCode plugin's and the Codex hook's: plan mode, a remote session's read-only rules,
|
|
3779
|
+
* the browser policy (every session, plan mode and subagents included), then the route gate. → { decision:
|
|
3780
|
+
* 'deny', reason } or null (no objection: the brain's approval mode decides). `call`: lib/antigravity/tool-call.js
|
|
3781
|
+
* acpCall. Antigravity's own bookkeeping steps (task boundaries, notes to the user) are never routed.
|
|
3782
|
+
*/
|
|
3783
|
+
function antigravityGateCheck(live, call) {
|
|
3784
|
+
const name = acpToolName(call);
|
|
3785
|
+
const input = acpPolicyInput(call);
|
|
3786
|
+
const planned = planGate(live, 'antigravity', name, input);
|
|
3787
|
+
if (planned) return { decision: 'deny', reason: planned.reason };
|
|
3788
|
+
// A remote (WhatsApp) session's Antigravity brain is read-only for good, at every level.
|
|
3789
|
+
if (live.brainRemoteReadOnly && readOnlyToolDecision(name, input, { host: 'antigravity' }) === 'deny') {
|
|
3790
|
+
log('assistant:remote-policy', `${live.record.id}: refused ${name} (read-only)`);
|
|
3791
|
+
return { decision: 'deny', reason: `${readOnlyDenyMessage(name)} Tell the user to do this in SynaBun on their computer if they need it.` };
|
|
3792
|
+
}
|
|
3793
|
+
if (call.mcp) {
|
|
3794
|
+
const remoteDenied = remoteGate(live, name, input, { argsComplete: true, host: 'antigravity' });
|
|
3795
|
+
if (remoteDenied) return { decision: 'deny', reason: remoteDenied.reason };
|
|
3796
|
+
}
|
|
3797
|
+
const browserDenied = browserGate(live, name, input, { host: 'antigravity' });
|
|
3798
|
+
if (browserDenied) return { decision: 'deny', reason: browserDenied.reason };
|
|
3799
|
+
if (!live.gate || call.kind === 'think') return null;
|
|
3800
|
+
const decision = decide(live, name);
|
|
3801
|
+
return decision.allow ? null : { decision: 'deny', reason: decision.reason };
|
|
3802
|
+
}
|
|
3803
|
+
/** What an Antigravity brain needs from this session (assistant-brains/antigravity.js deps). */
|
|
3804
|
+
function antigravityBrainDeps(live) {
|
|
3805
|
+
const ag = antigravity || {};
|
|
3806
|
+
const saved = live.record.usageState?.antigravity;
|
|
3807
|
+
return {
|
|
3808
|
+
antigravityLaunch: typeof ag.launch === 'function' ? ag.launch : () => null,
|
|
3809
|
+
childEnv: typeof ag.childEnv === 'function' ? ag.childEnv : undefined,
|
|
3810
|
+
antigravityHome: typeof ag.home === 'function' ? (sessionId) => ag.home(sessionId) : null,
|
|
3811
|
+
synabunMcpEntry: typeof ag.synabunMcpEntry === 'function' ? ag.synabunMcpEntry : null,
|
|
3812
|
+
policy: ag.policy || null,
|
|
3813
|
+
policyUrl: typeof ag.policyUrl === 'function' ? ag.policyUrl() : (ag.policyUrl || null),
|
|
3814
|
+
connect: ag.connect || undefined,
|
|
3815
|
+
userGemini: ag.userGemini || undefined,
|
|
3816
|
+
policyCheck: (call) => antigravityGateCheck(live, call),
|
|
3817
|
+
// ACP counts tokens per session: what the session the record names had counted (a resume books only what follows).
|
|
3818
|
+
sessionUsageBase: saved && saved.sessionId && saved.sessionId === live.record.providerSessionId ? saved.usage || null : null,
|
|
3819
|
+
onAntigravitySession: (sessionId) => { if (sessionId && live.record.providerSessionId !== sessionId) { live.record.providerSessionId = sessionId; touch(live); } },
|
|
3820
|
+
onAntigravitySessionUsage: (sessionId, total) => { live.record.usageState ||= {}; live.record.usageState.antigravity = { sessionId, usage: total }; },
|
|
3821
|
+
onAntigravityUsage: (info) => settleAntigravityBrain(live, info),
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
/** One Antigravity brain turn's tokens into the ledger: unpriced (tokens, not prices), exact when its total agrees. */
|
|
3825
|
+
function settleAntigravityBrain(live, { usage: turnUsage = null, model = null } = {}) {
|
|
3826
|
+
if (!usage || !turnUsage) return;
|
|
3827
|
+
metered('antigravity-settle', () => {
|
|
3828
|
+
const { tokens, mismatch } = antigravityUsageTokens(turnUsage);
|
|
3829
|
+
if (totalTokens(tokens) === 0) return;
|
|
3830
|
+
const taskId = currentTask(live.record.id) || ensureTaskId(live.record.id);
|
|
3831
|
+
usage.settle({
|
|
3832
|
+
sessionId: live.record.id, taskId, scope: 'brain', runId: null, turn: live.record.turns, provider: 'antigravity',
|
|
3833
|
+
model: model || live.record.brain?.model || null, part: 'main', tokens, costUsd: null, costBasis: 'unpriced',
|
|
3834
|
+
fidelity: mismatch ? 'partial' : 'exact', reason: mismatch ? 'antigravity-total-mismatch' : null, source: 'antigravity-acp-usage',
|
|
3835
|
+
});
|
|
3836
|
+
});
|
|
3837
|
+
persist({ force: true });
|
|
3838
|
+
}
|
|
3675
3839
|
/**
|
|
3676
3840
|
* A remote session's hard refusal for one tool call (every level), else null.
|
|
3677
3841
|
* `argsComplete: false`: the host did not pass the call's arguments. An
|
|
@@ -3682,6 +3846,9 @@ export function createAssistantRuntime({
|
|
|
3682
3846
|
let reason = null;
|
|
3683
3847
|
if (host === 'opencode' && REMOTE_OPENCODE_WEB_TOOLS.has(String(tool || '').toLowerCase())) {
|
|
3684
3848
|
reason = `${tool}: a WhatsApp conversation on OpenCode is read-only and does not reach the web on its own; use SynaBun's browser tools, or switch the WhatsApp brain to Claude.`;
|
|
3849
|
+
} else if (host === 'opencode' && String(tool || '').toLowerCase() === 'execute') {
|
|
3850
|
+
// Code Mode's `execute` runs arbitrary code (fetch included) that no argument check can read: never remote.
|
|
3851
|
+
reason = `${tool}: a WhatsApp conversation on OpenCode does not run Code Mode; call SynaBun's tools directly, or switch the WhatsApp brain to Claude.`;
|
|
3685
3852
|
} else if (isComputerTool(tool)) {
|
|
3686
3853
|
// `computer`: what computerAccess said for this call (the Claude hook passes it). Any other
|
|
3687
3854
|
// caller (the Codex hook, the OpenCode plugin) asks here: those brains never get past "off".
|
|
@@ -3696,16 +3863,30 @@ export function createAssistantRuntime({
|
|
|
3696
3863
|
log('assistant:remote-policy', `${live.record.id}: refused ${tool} (${reason})`);
|
|
3697
3864
|
return { allow: false, remote: true, reason: `${reason} Tell the user to do this in SynaBun on their computer if they need it.` };
|
|
3698
3865
|
}
|
|
3866
|
+
// The registered code projects a brain's test runners may run in besides its session's project
|
|
3867
|
+
// (lib/browser-policy-roots.js): read again at most every 10 s, so a project registered while a
|
|
3868
|
+
// session lives counts from its next calls on.
|
|
3869
|
+
const BROWSER_ROOTS_TTL_MS = 10_000;
|
|
3870
|
+
let browserRoots = { at: -Infinity, roots: [] };
|
|
3871
|
+
function browserTestRoots() {
|
|
3872
|
+
const at = now();
|
|
3873
|
+
if (at - browserRoots.at < BROWSER_ROOTS_TTL_MS && at >= browserRoots.at) return browserRoots.roots;
|
|
3874
|
+
let roots = [];
|
|
3875
|
+
try { roots = browserPolicyRoots(registeredProjectPaths()); } catch { roots = []; }
|
|
3876
|
+
browserRoots = { at, roots };
|
|
3877
|
+
return roots;
|
|
3878
|
+
}
|
|
3699
3879
|
/**
|
|
3700
3880
|
* The browser policy (lib/browser-tool-policy.js) for one brain tool call:
|
|
3701
3881
|
* { allow:false, browser:true, reason } or null. Every provider and session,
|
|
3702
3882
|
* plan mode and subagents included; scripts resolve against the session's
|
|
3703
|
-
* project cwd
|
|
3883
|
+
* project cwd, and test runners run there or in a registered code project
|
|
3884
|
+
* (browserTestRoots). `argsComplete: false` (the host sent only the command /
|
|
3704
3885
|
* action of an oversized call): checked on what arrived.
|
|
3705
3886
|
*/
|
|
3706
3887
|
function browserGate(live, tool, input = {}, { host = null, argsComplete = true } = {}) {
|
|
3707
3888
|
const kind = host || (live.brainProvider === 'claude-code' ? 'claude' : live.brainProvider);
|
|
3708
|
-
const reason = browserToolDenial(tool, input && typeof input === 'object' ? input : {}, { host: kind, cwd: live.record.brain?.cwd || PACKAGE_ROOT });
|
|
3889
|
+
const reason = browserToolDenial(tool, input && typeof input === 'object' ? input : {}, { host: kind, cwd: live.record.brain?.cwd || PACKAGE_ROOT, roots: browserTestRoots() });
|
|
3709
3890
|
if (!reason) return null;
|
|
3710
3891
|
log('assistant:browser-policy', `${live.record.id}: refused ${tool}${argsComplete ? '' : ' (partial arguments)'}`);
|
|
3711
3892
|
return { allow: false, browser: true, reason };
|
|
@@ -3875,6 +4056,9 @@ export function createAssistantRuntime({
|
|
|
3875
4056
|
return {
|
|
3876
4057
|
handleWebSocket, listSessions, getSession, createSession, updateSession, closeSession, destroySession, removeSession,
|
|
3877
4058
|
resolveTerminal, accountInUse, ownsIsolatedServe, noteDispatch, subscribe, shutdown,
|
|
4059
|
+
// The sessions index written now, synchronously: the server's exit handler runs it on every way out,
|
|
4060
|
+
// since an exit through process.exit() never reaches shutdown()'s own write.
|
|
4061
|
+
flushIndex: () => persist({ force: true }),
|
|
3878
4062
|
observeBroadcast: onPermissionBroadcast,
|
|
3879
4063
|
testDensityFor, routerSession, routerSend, routerEvent, routerMailbox, routerContinue, routerSinks, routerRouted, routerRouteFailed, routerComputerApproved, gateCheck, isPlanning, isPlanReadOnly,
|
|
3880
4064
|
clarifySession, clarifyEvent, clarifyGate, clarifySinks,
|