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,20 +1,23 @@
|
|
|
1
|
+
import { OPENCODE_BRAIN_TOOLS } from '../assistant-tools.js';
|
|
1
2
|
// ═══════════════════════════════════════════
|
|
2
3
|
// SynaBun — Assistant brain: OpenCode (isolated serve + SDK client)
|
|
3
4
|
// ═══════════════════════════════════════════
|
|
4
5
|
//
|
|
5
6
|
// One isolated `opencode serve` per assistant session (same helpers the
|
|
6
7
|
// OpenCode sidepanel uses). The persona is installed as a custom primary agent
|
|
7
|
-
// (`
|
|
8
|
-
// its system prompt; SSE events are translated to the unified envelope.
|
|
8
|
+
// (`agents.assistant.system`) in the per-serve opencode.json so the model sees
|
|
9
|
+
// it as its system prompt; SSE events are translated to the unified envelope.
|
|
9
10
|
|
|
10
|
-
import { chmodSync,
|
|
11
|
+
import { chmodSync, writeFileSync } from 'node:fs';
|
|
11
12
|
import { dirname, resolve } from 'node:path';
|
|
12
13
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
14
|
import { normalizeOpenCodeModel } from '../native-loop-providers.js';
|
|
14
|
-
import {
|
|
15
|
+
import { agentOf, mcpServersOf, opencodeConfigFilePath, readOpencodeConfigDocument, setAgent, setMcpServer, withPlugin, withoutPlugin } from '../opencode-config.js';
|
|
15
16
|
import { createOpenCodeEnvelopeTranslator, opencodeControlResponse } from '../assistant-envelope.js';
|
|
16
17
|
import { opencodePlanPermission, opencodeReadOnlyPermission, planDenyMessage, readOnlyDenyMessage } from '../assistant-plan-permissions.js';
|
|
17
18
|
import { planModeInstructions } from '../assistant-persona.js';
|
|
19
|
+
import { waitForSynabunTools, synabunConfigured, synabunToolsTimeoutText, OPENCODE_MCP_READY_TIMEOUT_MS, OPENCODE_MCP_SETTLE_MS, OPENCODE_MCP_LIST_GRACE_MS } from '../opencode-mcp-ready.js';
|
|
20
|
+
export { synabunMcpState } from '../opencode-mcp-ready.js';
|
|
18
21
|
|
|
19
22
|
/** The MCP terminal pin of an assistant session's OpenCode brain. */
|
|
20
23
|
export function opencodeTermIdFor(sessionId) {
|
|
@@ -34,14 +37,8 @@ export function opencodeImageParts(images = []) {
|
|
|
34
37
|
return parts;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
/** The route-gate plugin (
|
|
38
|
-
export const OPENCODE_ROUTE_GATE_PLUGIN = pathToFileURL(resolve(dirname(fileURLToPath(import.meta.url)), '
|
|
39
|
-
/**
|
|
40
|
-
* The same gate for OpenCode 2 (opencode2-route-gate/: OpenCode 2 loads a plugin
|
|
41
|
-
* folder from the config's `plugins` list). Both entries are written: OpenCode 1
|
|
42
|
-
* ignores `plugins`, OpenCode 2 skips the 1.x file (a warning in its log).
|
|
43
|
-
*/
|
|
44
|
-
export const OPENCODE2_ROUTE_GATE_PLUGIN = pathToFileURL(resolve(dirname(fileURLToPath(import.meta.url)), 'opencode2-route-gate')).href;
|
|
40
|
+
/** The route-gate plugin (opencode2-route-gate/, a plugin folder OpenCode loads from `plugins`) as a file URL. */
|
|
41
|
+
export const OPENCODE_ROUTE_GATE_PLUGIN = pathToFileURL(resolve(dirname(fileURLToPath(import.meta.url)), 'opencode2-route-gate')).href;
|
|
45
42
|
|
|
46
43
|
/**
|
|
47
44
|
* SynaBun's plan agent. OpenCode adds its own read-only reminder ("commands may
|
|
@@ -52,71 +49,111 @@ export const OPENCODE2_ROUTE_GATE_PLUGIN = pathToFileURL(resolve(dirname(fileURL
|
|
|
52
49
|
*/
|
|
53
50
|
export const OPENCODE_PLAN_AGENT = 'synabun-plan';
|
|
54
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Tools this brain's agents must never call. Code Mode's `execute` runs arbitrary code (a `fetch`
|
|
54
|
+
* included) that no argument check can read, so the route gate refuses it before routing - and this
|
|
55
|
+
* brain's SynaBun tools are direct (codemode: false), so the only thing `execute` can do here is earn
|
|
56
|
+
* that refusal. Denied at the agent, the model is not offered it at all.
|
|
57
|
+
*/
|
|
58
|
+
export const OPENCODE_BRAIN_DENIED_TOOLS = Object.freeze(['execute']);
|
|
59
|
+
|
|
55
60
|
/** The brain's SynaBun MCP tool-call timeout (ms): as long as the Codex brain's tool_timeout_sec (server.js). */
|
|
56
61
|
export const OPENCODE_BRAIN_MCP_TIMEOUT_MS = 180_000;
|
|
57
62
|
|
|
63
|
+
// Compatibility exports for the brain's existing consumers and tests.
|
|
64
|
+
export const OPENCODE_BRAIN_MCP_READY_TIMEOUT_MS = OPENCODE_MCP_READY_TIMEOUT_MS;
|
|
65
|
+
export const OPENCODE_BRAIN_MCP_SETTLE_MS = OPENCODE_MCP_SETTLE_MS;
|
|
66
|
+
export const OPENCODE_BRAIN_MCP_LIST_GRACE_MS = OPENCODE_MCP_LIST_GRACE_MS;
|
|
67
|
+
export const assistantSynabunConfigured = synabunConfigured;
|
|
68
|
+
export { OPENCODE_BRAIN_TOOLS } from '../assistant-tools.js';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Why the brain's serve would start with SynaBun behind Code Mode (`execute` only, which the route gate
|
|
72
|
+
* refuses before routing, so agent_route would be unreachable), read back from the written config; null
|
|
73
|
+
* when it is fine. No config file at all: the serve has no SynaBun server, the gate turns itself off.
|
|
74
|
+
*/
|
|
75
|
+
export function assistantConfigProblem(xdgRoot) {
|
|
76
|
+
let doc;
|
|
77
|
+
try { doc = readOpencodeConfigDocument(opencodeConfigFilePath(resolve(xdgRoot, 'opencode'))); } catch (err) { return `its OpenCode configuration could not be read (${err?.message || err})`; }
|
|
78
|
+
if (!doc.exists) return null;
|
|
79
|
+
if (doc.error) return 'its OpenCode configuration could not be read';
|
|
80
|
+
const synabun = mcpServersOf(doc.config).SynaBun;
|
|
81
|
+
if (synabun && synabun.codemode !== false) return 'SynaBun\'s tools could not be set up for direct use (OpenCode Code Mode stayed on)';
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
58
85
|
/**
|
|
59
86
|
* `routeGate` ({ url, session, token }) installs the route-gate plugin in this
|
|
60
|
-
* isolated serve's
|
|
87
|
+
* isolated serve's opencode.json only (assistant brains; never the shared
|
|
88
|
+
* sidepanel setup). Everything is written in OpenCode 2's schema.
|
|
61
89
|
*/
|
|
62
90
|
export function patchOpenCodeAssistantConfig(xdgRoot, { persona = '', role = 'assistant', model = null, desktopGrant = null, routeGate = null, brainCredential = null } = {}) {
|
|
63
|
-
const configPath = resolve(xdgRoot, 'opencode'
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
const configPath = opencodeConfigFilePath(resolve(xdgRoot, 'opencode'));
|
|
92
|
+
const doc = readOpencodeConfigDocument(configPath);
|
|
93
|
+
if (!doc.exists || doc.error) return false;
|
|
94
|
+
const config = doc.config;
|
|
95
|
+
const synabun = mcpServersOf(config).SynaBun;
|
|
96
|
+
if (synabun) {
|
|
97
|
+
const env = { ...(synabun.environment || {}), SYNABUN_ROLE: role };
|
|
69
98
|
// Computer use: an unforgeable per-brain grant unlocks the `computer` group.
|
|
70
99
|
if (desktopGrant) env.SYNABUN_DESKTOP_GRANT = desktopGrant;
|
|
71
100
|
else delete env.SYNABUN_DESKTOP_GRANT;
|
|
72
|
-
//
|
|
101
|
+
// The brain's launch credential (whatsapp_send_file, the Skills Service), for this serve's SynaBun MCP child only.
|
|
73
102
|
// This file names the variable; the value is in the serve's own environment (ensureIsolatedServe), so
|
|
74
103
|
// neither this file (it is in every backup of data/) nor OPENCODE_CONFIG_CONTENT ever holds it.
|
|
75
104
|
if (brainCredential) env.SYNABUN_BRAIN_TOKEN = '{env:SYNABUN_BRAIN_TOKEN}';
|
|
76
105
|
else delete env.SYNABUN_BRAIN_TOKEN;
|
|
77
|
-
config.mcp.SynaBun[envKey] = env;
|
|
78
106
|
// OpenCode gives an MCP tool call 60 s unless the server says otherwise; agent_route may wait on the
|
|
79
107
|
// user's route card and whatsapp_send_file on an upload (130 s): the Codex brain's 180 s here too.
|
|
80
|
-
|
|
108
|
+
// OpenCode 2.1's MCP default is Code Mode: only `execute` reaches these tools. The route gate must
|
|
109
|
+
// refuse arbitrary execute code until routed, so wrapping agent_route (and exempt memory tools) deadlocks
|
|
110
|
+
// the brain. Expose this brain's SynaBun tools directly instead. The serve's OPENCODE_CONFIG_CONTENT
|
|
111
|
+
// overlay carries this entry past project config too; other servers, workers and sidepanels keep their mode.
|
|
112
|
+
setMcpServer(config, 'SynaBun', { ...synabun, codemode: false, environment: env, timeout: { ...(synabun.timeout || {}), execution: OPENCODE_BRAIN_MCP_TIMEOUT_MS } });
|
|
81
113
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
const rule = (action, effect, resource = '*') => ({ action, resource, effect });
|
|
115
|
+
// An agent's rules with ours last, in place of any it had for the same tools (as OpenCode 1's
|
|
116
|
+
// `permission.<tool>` replaced the user's value): every command asks whatever was allowed before, and the
|
|
117
|
+
// list stays as it is when the config is patched again.
|
|
118
|
+
const withOurRules = (agent, ours) => [...(agent.permissions || []).filter((own) => !ours.some((r) => r.action === own?.action)), ...ours];
|
|
119
|
+
const withoutExecute = OPENCODE_BRAIN_DENIED_TOOLS.map((name) => rule(name, 'deny'));
|
|
120
|
+
const assistant = agentOf(config, 'assistant');
|
|
121
|
+
setAgent(config, 'assistant', {
|
|
122
|
+
...assistant,
|
|
85
123
|
mode: 'primary',
|
|
86
124
|
description: 'SynaBun central assistant',
|
|
87
|
-
|
|
125
|
+
...(persona ? { system: persona } : {}),
|
|
88
126
|
...(model ? { model } : {}),
|
|
89
|
-
|
|
127
|
+
permissions: withOurRules(assistant, withoutExecute),
|
|
128
|
+
});
|
|
90
129
|
// SynaBun's plan agent (desktop plan turns): no code changes, anything else as the approval mode says.
|
|
91
|
-
|
|
92
|
-
|
|
130
|
+
const synabunPlan = agentOf(config, OPENCODE_PLAN_AGENT);
|
|
131
|
+
setAgent(config, OPENCODE_PLAN_AGENT, {
|
|
132
|
+
...synabunPlan,
|
|
93
133
|
mode: 'primary',
|
|
94
134
|
hidden: true,
|
|
95
135
|
description: 'SynaBun plan mode: explore, run commands and use every tool; no code changes',
|
|
96
|
-
|
|
136
|
+
...(persona ? { system: persona } : {}),
|
|
97
137
|
...(model ? { model } : {}),
|
|
98
|
-
|
|
99
|
-
};
|
|
138
|
+
permissions: withOurRules(synabunPlan, [...withoutExecute, rule('edit', 'deny'), rule('shell', 'ask'), rule('question', 'allow'), rule('subagent', 'deny', 'general')]),
|
|
139
|
+
});
|
|
100
140
|
// OpenCode's own plan agent (a WhatsApp session's read-only brain) refuses only
|
|
101
141
|
// edits and runs any command without asking: here every command asks, so the
|
|
102
142
|
// read-only classifier decides on the whole line.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
143
|
+
const plan = agentOf(config, 'plan');
|
|
144
|
+
setAgent(config, 'plan', { ...plan, permissions: withOurRules(plan, [rule('shell', 'ask')]) });
|
|
145
|
+
withoutPlugin(config, OPENCODE_ROUTE_GATE_PLUGIN);
|
|
106
146
|
// `remote`: a WhatsApp session's serve — the plugin refuses a call it could not check (fail closed).
|
|
107
147
|
if (routeGate?.url && routeGate?.session && routeGate?.token) {
|
|
108
|
-
|
|
109
|
-
plugins.push([OPENCODE_ROUTE_GATE_PLUGIN, options]);
|
|
110
|
-
plugins2.push({ package: OPENCODE2_ROUTE_GATE_PLUGIN, options });
|
|
148
|
+
withPlugin(config, OPENCODE_ROUTE_GATE_PLUGIN, { url: routeGate.url, session: routeGate.session, token: routeGate.token, ...(routeGate.remote === true ? { remote: true } : {}) });
|
|
111
149
|
}
|
|
112
|
-
|
|
113
|
-
if (plugins2.length) config.plugins = plugins2; else delete config.plugins;
|
|
114
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
150
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
115
151
|
// It carries this brain's grants (the desktop grant): readable by this user only.
|
|
116
152
|
try { chmodSync(configPath, 0o600); } catch { /* a filesystem without modes */ }
|
|
117
153
|
return true;
|
|
118
154
|
}
|
|
119
155
|
|
|
156
|
+
|
|
120
157
|
/** The assistant's OpenCode approval mode: 'auto' (auto-accept) or 'default'. */
|
|
121
158
|
export function opencodeApprovalMode(mode) {
|
|
122
159
|
return mode === 'auto' || mode === 'acceptEdits' || mode === 'bypassPermissions' ? 'auto' : 'default';
|
|
@@ -169,8 +206,13 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
169
206
|
let keepAliveTimer = null;
|
|
170
207
|
let costUsd = 0;
|
|
171
208
|
let startPromise = null;
|
|
172
|
-
|
|
173
|
-
let
|
|
209
|
+
let synabunExpected = false;
|
|
210
|
+
let stops = 0;
|
|
211
|
+
let waitingAbort = null;
|
|
212
|
+
const mcpWait = {
|
|
213
|
+
readyTimeoutMs: deps.mcpReadyTimeoutMs, settleMs: deps.mcpSettleMs,
|
|
214
|
+
listGraceMs: deps.mcpListGraceMs, pollMs: deps.mcpPollMs,
|
|
215
|
+
};
|
|
174
216
|
// Plan mode runs SynaBun's plan agent (OPENCODE_PLAN_AGENT; OpenCode's own
|
|
175
217
|
// `plan` agent, the persona riding as `system`, when the config patch failed).
|
|
176
218
|
let approvalMode = opencodeApprovalMode(brain.permissionMode);
|
|
@@ -219,17 +261,29 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
219
261
|
}
|
|
220
262
|
|
|
221
263
|
/** The serve's MCP servers as an `mcp_status` event (the runtime reads whether SynaBun, and so agent_route, is reachable). */
|
|
264
|
+
function sendMcpStatus(servers) { sink.send({ type: 'event', event: { type: 'system', subtype: 'mcp_status', servers } }); }
|
|
222
265
|
async function reportMcpStatus() {
|
|
223
|
-
try { const status = await client?.mcp?.status?.({ directory: cwd });
|
|
266
|
+
try { const status = await client?.mcp?.status?.({ directory: cwd }); sendMcpStatus(status?.data || status || []); } catch {}
|
|
224
267
|
}
|
|
225
268
|
|
|
226
269
|
async function start() {
|
|
227
270
|
if (disposed) throw new Error('OpenCode brain disposed');
|
|
228
271
|
if (startPromise) return startPromise;
|
|
229
272
|
startPromise = (async () => {
|
|
230
|
-
const xdgRoot = deps.setupOpencodeSidepanelConfig(termId, brain.
|
|
231
|
-
|
|
232
|
-
|
|
273
|
+
const xdgRoot = deps.setupOpencodeSidepanelConfig(termId, brain.tools ?? OPENCODE_BRAIN_TOOLS, { cwd: brain.cwd, scopeExternal: false });
|
|
274
|
+
// A brain whose config could not be patched would start with Code Mode on: SynaBun's tools only behind
|
|
275
|
+
// `execute`, which the route gate refuses before routing, so agent_route is unreachable. Refuse to start.
|
|
276
|
+
let patchError = null;
|
|
277
|
+
try { personaInstalled = patchOpenCodeAssistantConfig(xdgRoot, { persona, model: null, desktopGrant: deps.desktopGrant || null, routeGate: deps.routeGate || null, brainCredential: deps.brainCredential || null }); } catch (err) { personaInstalled = false; patchError = err; }
|
|
278
|
+
const unready = assistantConfigProblem(xdgRoot);
|
|
279
|
+
if (unready) {
|
|
280
|
+
throw new Error(`OpenCode Assistant could not start: ${unready}${patchError?.message ? ` (${patchError.message})` : ''}. Check Settings → OpenCode, or switch the Assistant to another provider.`);
|
|
281
|
+
}
|
|
282
|
+
// Its turns go out once SynaBun's tools are on the model's list (waitForSynabunTools).
|
|
283
|
+
synabunExpected = assistantSynabunConfigured(xdgRoot);
|
|
284
|
+
// An inherited OPENCODE_CONFIG_DIR would replace this isolated configuration (route-gate plugin,
|
|
285
|
+
// the assistant and plan agents): the brain's serve never reads it.
|
|
286
|
+
entry = await deps.ensureIsolatedServe(termId, { xdgRoot, keepAlive: true, tools: brain.tools ?? OPENCODE_BRAIN_TOOLS, brainCredential: deps.brainCredential || null, extraEnv: { OPENCODE_CONFIG_DIR: null } });
|
|
233
287
|
if (!entry?.client) throw new Error('OpenCode isolated serve failed to start');
|
|
234
288
|
client = entry.client;
|
|
235
289
|
await client.waitUntilConnected?.(20_000);
|
|
@@ -253,7 +307,9 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
253
307
|
kind: 'opencode',
|
|
254
308
|
start,
|
|
255
309
|
async sendUserTurn({ text, images = [], model = null, effort = null, permissionMode: mode = null, planMode: plan = null } = {}) {
|
|
310
|
+
const stop = stops;
|
|
256
311
|
await start();
|
|
312
|
+
if (disposed || stops !== stop) return false;
|
|
257
313
|
applyModes(mode, plan);
|
|
258
314
|
turnActive = true;
|
|
259
315
|
// The runtime passes the effective model/effort on every turn (the record
|
|
@@ -262,7 +318,6 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
262
318
|
const request = {
|
|
263
319
|
sessionID: sessionId, parts, model: normalizeOpenCodeModel(model || brain.model), directory: cwd,
|
|
264
320
|
};
|
|
265
|
-
if (request.model) lastTurnModel = request.model;
|
|
266
321
|
if (effort) request.variant = String(effort);
|
|
267
322
|
turnPlanned = planMode && !remoteReadOnly;
|
|
268
323
|
if (turnPlanned && personaInstalled) {
|
|
@@ -277,14 +332,25 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
277
332
|
else if (personaInstalled) request.agent = brain.agent || 'assistant';
|
|
278
333
|
else { request.agent = brain.agent || 'build'; if (persona) request.system = persona; }
|
|
279
334
|
if (entry) entry.lastUsed = Date.now();
|
|
280
|
-
// SynaBun
|
|
281
|
-
|
|
335
|
+
// SynaBun's tools on the model's list first (a fresh serve may still be connecting them); the route gate
|
|
336
|
+
// follows what was seen. Stopped meanwhile (its `aborted` is out) or disposed: the turn never goes out.
|
|
337
|
+
const controller = new AbortController();
|
|
338
|
+
waitingAbort = controller;
|
|
339
|
+
let ready;
|
|
340
|
+
try {
|
|
341
|
+
ready = await waitForSynabunTools(client, { ...mcpWait, directory: cwd, expected: synabunExpected,
|
|
342
|
+
signal: controller.signal, stopped: () => disposed || stops !== stop,
|
|
343
|
+
onStatus: sendMcpStatus,
|
|
344
|
+
onTimeout: (ms) => sink.send({ type: 'event', event: { type: 'system', subtype: 'status', text: synabunToolsTimeoutText(ms, 'brain') } }),
|
|
345
|
+
});
|
|
346
|
+
} finally { if (waitingAbort === controller) waitingAbort = null; }
|
|
347
|
+
if (!ready || disposed || stops !== stop) { turnActive = false; return false; }
|
|
282
348
|
const response = await client.session.promptAsync(request);
|
|
283
349
|
const status = Number(response?.status);
|
|
284
350
|
if (Number.isFinite(status) && status >= 400) { turnActive = false; throw new Error(`OpenCode prompt failed (${status})`); }
|
|
285
351
|
return true;
|
|
286
352
|
},
|
|
287
|
-
async abort() { if (client && sessionId) await client.session.abort({ sessionID: sessionId, directory: cwd }).catch(() => {}); emit({ type: 'aborted' }); },
|
|
353
|
+
async abort() { stops += 1; waitingAbort?.abort(); if (client && sessionId) await client.session.abort({ sessionID: sessionId, directory: cwd }).catch(() => {}); emit({ type: 'aborted' }); },
|
|
288
354
|
async setPermissionMode(mode, { planMode: plan = null } = {}) { applyModes(mode, plan); sink.send({ type: 'mode_changed', mode: approvalMode, planMode }); },
|
|
289
355
|
respondControl(requestId, response) {
|
|
290
356
|
const pending = pendingControls.get(String(requestId));
|
|
@@ -296,12 +362,11 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
296
362
|
: client.permission.reply({ requestID: body.requestID, reply: body.reply, directory: cwd });
|
|
297
363
|
Promise.resolve(call).catch((error) => sink.send({ type: 'error', message: `OpenCode reply failed: ${error?.message || error}` }));
|
|
298
364
|
},
|
|
299
|
-
// OpenCode
|
|
300
|
-
// compactOrSummarize then summarises on the model of the last turn.
|
|
365
|
+
// OpenCode compacts the session on the model it runs on.
|
|
301
366
|
async compact() {
|
|
302
367
|
await start();
|
|
303
368
|
turnPlanned = false;
|
|
304
|
-
await
|
|
369
|
+
await client.session.compact({ sessionID: sessionId, directory: cwd });
|
|
305
370
|
},
|
|
306
371
|
async mcpStatus() { await reportMcpStatus(); },
|
|
307
372
|
async reconcileUsage(meter) {
|
|
@@ -337,6 +402,7 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
337
402
|
async dispose() {
|
|
338
403
|
if (disposed) return;
|
|
339
404
|
disposed = true;
|
|
405
|
+
waitingAbort?.abort();
|
|
340
406
|
if (keepAliveTimer) clearInterval(keepAliveTimer);
|
|
341
407
|
if (unsubscribe) { try { unsubscribe(); } catch {} }
|
|
342
408
|
try { deps.stopIsolatedServe(termId); } catch {}
|
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
// SynaBun —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
1
|
+
// SynaBun — OpenCode plugin: the browser policy of an Assistant task run.
|
|
2
|
+
// Loaded only by the isolated `opencode serve` of a worker the Assistant
|
|
3
|
+
// dispatched (its opencode.json's `plugins` entry, { package: <this folder as a
|
|
4
|
+
// file URL>, options }, added by withOpenCodeBrowserPolicy from server.js
|
|
5
|
+
// setupOpencodeLoopConfig); loops, schedules and the OpenCode sidepanel never
|
|
6
|
+
// load it. OpenCode 2's plugin API: the default export is `{ id, setup(context) }`,
|
|
7
|
+
// registering `context.tool.hook('execute.before', …)`, which sees `{ tool, sessionID, input }`;
|
|
8
|
+
// a refusal is thrown as a plain Error, which OpenCode records as that tool's
|
|
9
|
+
// error, and the loop continues. Before every tool call it asks
|
|
10
|
+
// lib/browser-tool-policy.js here, with no server round trip. OpenCode calls the
|
|
11
|
+
// shell tool `shell` and the sub-agent tool `subagent`: the policy is asked with
|
|
12
|
+
// the names the rest of SynaBun knows (`bash`, `task`). Script paths resolve
|
|
13
|
+
// against the run's cwd (the plugin options), else the serve's directory; the
|
|
14
|
+
// options' `roots` name the registered code projects its test runners may also
|
|
15
|
+
// run in (the serve is sandboxed and cannot read SynaBun's data home: server.js
|
|
16
|
+
// lists them as the run starts). A
|
|
17
|
+
// policy module that cannot load fails closed: the failure is logged once, and
|
|
18
|
+
// the shell, webfetch, websearch and every tool that is not OpenCode's own or
|
|
19
|
+
// SynaBun's (another MCP server's, another plugin's) are refused with that
|
|
20
|
+
// reason until the run ends.
|
|
8
21
|
|
|
9
22
|
// An absolute file URL: the policy loads from SynaBun's lib/ wherever OpenCode imports this file from.
|
|
10
23
|
const POLICY_URL = new URL('../../browser-tool-policy.js', import.meta.url).href;
|
|
11
24
|
const V1_NAMES = { shell: 'bash', subagent: 'task' };
|
|
12
25
|
|
|
13
|
-
// OpenCode's own tools that run no command
|
|
26
|
+
// OpenCode's own tools that run no command, fetch no page and open no browser (by the names above). The shell,
|
|
27
|
+
// webfetch, websearch and OpenCode's browser are not here; any other name belongs to an MCP server or a plugin.
|
|
14
28
|
const OWN_TOOLS = new Set([
|
|
15
|
-
'read', 'list', 'glob', 'grep', 'edit', 'write', 'patch', '
|
|
16
|
-
'
|
|
29
|
+
'read', 'list', 'glob', 'grep', 'edit', 'write', 'patch', 'todo', 'task', 'skill', 'lsp', 'question',
|
|
30
|
+
'invalid', 'plan_exit', 'plan_enter',
|
|
17
31
|
]);
|
|
18
32
|
|
|
19
33
|
export default {
|
|
@@ -24,20 +38,21 @@ export default {
|
|
|
24
38
|
let loadError = null;
|
|
25
39
|
try { policy = await import(POLICY_URL); } catch (error) { loadError = error; }
|
|
26
40
|
const cwd = (typeof options.cwd === 'string' && options.cwd) || context?.location?.directory || process.cwd();
|
|
41
|
+
const roots = Array.isArray(options.roots) ? options.roots.filter((path) => typeof path === 'string') : [];
|
|
27
42
|
if (typeof policy?.browserToolDenial !== 'function') {
|
|
28
43
|
const why = loadError?.message || 'browserToolDenial is missing';
|
|
29
|
-
console.error(`[SynaBun] browser policy could not load from ${POLICY_URL} (${why}); refusing
|
|
44
|
+
console.error(`[SynaBun] browser policy could not load from ${POLICY_URL} (${why}); refusing the shell, webfetch, websearch and other servers' tools for this run`);
|
|
30
45
|
await context.tool.hook('execute.before', async (call) => {
|
|
31
46
|
const raw = String(call?.tool || '');
|
|
32
47
|
const tool = V1_NAMES[raw] || raw;
|
|
33
48
|
if (/^synabun_/i.test(tool) || OWN_TOOLS.has(tool.toLowerCase())) return;
|
|
34
|
-
throw new Error(`SynaBun browser policy: ${
|
|
49
|
+
throw new Error(`SynaBun browser policy: ${raw} was refused — SynaBun's browser policy could not load (${why}), so no command, web tool or other server's tool can be checked for a browser launch. SynaBun's own tools (SynaBun_*) and file tools still work. Stop and report this.`);
|
|
35
50
|
});
|
|
36
51
|
return;
|
|
37
52
|
}
|
|
38
53
|
await context.tool.hook('execute.before', async (call) => {
|
|
39
54
|
const raw = String(call?.tool || '');
|
|
40
|
-
const reason = policy.browserToolDenial(V1_NAMES[raw] || raw, call?.input || {}, { host: 'opencode', cwd });
|
|
55
|
+
const reason = policy.browserToolDenial(V1_NAMES[raw] || raw, call?.input || {}, { host: 'opencode', cwd, roots });
|
|
41
56
|
if (reason) throw new Error(reason);
|
|
42
57
|
});
|
|
43
58
|
},
|
|
@@ -1,18 +1,54 @@
|
|
|
1
|
-
// SynaBun — the Assistant's route gate
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// `
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
1
|
+
// SynaBun — OpenCode plugin for the Assistant's route gate.
|
|
2
|
+
// Loaded only by the assistant brain's isolated `opencode serve` (its
|
|
3
|
+
// opencode.json's `plugins` entry, { package: <this folder as a file URL>,
|
|
4
|
+
// options }, written by patchOpenCodeAssistantConfig); the OpenCode sidepanel
|
|
5
|
+
// never loads it. OpenCode 2's plugin API: the default export is
|
|
6
|
+
// `{ id, setup(context) }`; the hook it registers with
|
|
7
|
+
// `context.tool.hook('execute.before', …)` sees `{ tool, sessionID, input }`
|
|
8
|
+
// and refuses a call by throwing (OpenCode records
|
|
9
|
+
// the message as that tool's error and the loop continues; only
|
|
10
|
+
// permission/question rejections stop a turn). Before every tool call it asks
|
|
11
|
+
// the Neural Interface whether the call may run (the route gate, and plan
|
|
12
|
+
// mode's read-only policy on every session of this serve). When the gate
|
|
13
|
+
// allows, the user's own OpenCode permission rules apply exactly as before.
|
|
14
|
+
// OpenCode calls two tools by other names than the rest of SynaBun knows
|
|
15
|
+
// (`shell` for bash, `subagent` for task): the gate is asked with those names.
|
|
16
|
+
// The call's whole arguments travel (the remote denylist reads paths from
|
|
17
|
+
// them), marked inputComplete; arguments too big to send go as their
|
|
18
|
+
// command/action only. No answer at all (the server unreachable or slow)
|
|
19
|
+
// allows the call — except with `remote` (a WhatsApp session's serve), where a
|
|
20
|
+
// call SynaBun could not check is refused. An answer that is not a decision
|
|
21
|
+
// (the check itself refused, such as 403 PEER_REFUSED, an error status, a body
|
|
22
|
+
// without `allow`) refuses the call in every session and says what SynaBun
|
|
23
|
+
// answered: a refusal never passes for an allow.
|
|
24
|
+
//
|
|
25
|
+
// Every request carries the session's pin (X-Synabun-Assistant): this plugin
|
|
26
|
+
// runs inside the brain's `opencode serve`, an AI agent's process tree, which
|
|
27
|
+
// SynaBun's owner gate (lib/owner-authority.js) refuses unless the call says
|
|
28
|
+
// it is an agent's own. The per-session `token` in the body is what the route
|
|
29
|
+
// itself checks.
|
|
30
|
+
//
|
|
31
|
+
// On load it says hello: until the Neural Interface hears it, it enforces the
|
|
32
|
+
// gate reactively (interrupting a turn after an unrouted tool started), so a
|
|
33
|
+
// plugin that never loads still leaves the brain gated. A WhatsApp session
|
|
34
|
+
// runs no turn at all until the hello arrives.
|
|
12
35
|
|
|
13
36
|
const MAX_INPUT_BYTES = 256 * 1024;
|
|
14
37
|
const UNCHECKED = 'SynaBun could not check this call, so a WhatsApp session does not run it.';
|
|
15
38
|
const V1_NAMES = { shell: 'bash', subagent: 'task' };
|
|
39
|
+
const PIN_HEADER = 'x-synabun-assistant';
|
|
40
|
+
|
|
41
|
+
/** The session id as a header value (printable ASCII only: fetch refuses anything else before sending). */
|
|
42
|
+
function pinOf(session) {
|
|
43
|
+
return String(session).replace(/[^\x21-\x7e]/g, '').slice(0, 200);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The refusal of a call whose check got an answer that is not a decision: what SynaBun answered, in short. */
|
|
47
|
+
function notADecision(status, body) {
|
|
48
|
+
const code = body && typeof body === 'object' && typeof body.code === 'string' ? ` ${body.code.slice(0, 64)}` : '';
|
|
49
|
+
const said = body && typeof body === 'object' && typeof body.error === 'string' ? `: ${body.error.slice(0, 300)}` : '';
|
|
50
|
+
return `SynaBun could not check this call (its route gate answered ${status}${code}${said}), so it did not run.`;
|
|
51
|
+
}
|
|
16
52
|
|
|
17
53
|
/** { input, inputComplete }: the whole arguments when small enough to send, else their command/action. */
|
|
18
54
|
function callArguments(args) {
|
|
@@ -34,24 +70,28 @@ export default {
|
|
|
34
70
|
if (!url || !session || !token) return;
|
|
35
71
|
const post = (body) => fetch(url, {
|
|
36
72
|
method: 'POST',
|
|
37
|
-
headers: { 'content-type': 'application/json' },
|
|
73
|
+
headers: { 'content-type': 'application/json', [PIN_HEADER]: pinOf(session) },
|
|
38
74
|
body: JSON.stringify({ session, token, host: 'opencode', ...body }),
|
|
39
75
|
signal: AbortSignal.timeout(5000),
|
|
40
76
|
});
|
|
41
|
-
// Never blocks loading; a lost hello only keeps the reactive fallback on.
|
|
42
|
-
post({ hello: true }).
|
|
77
|
+
// Never blocks loading; a lost hello only keeps the reactive fallback on (a refused one is said in the serve's log).
|
|
78
|
+
post({ hello: true }).then((response) => {
|
|
79
|
+
if (!response.ok) console.error(`[SynaBun] the route gate refused this serve's hello (${response.status}); every tool call will be refused until it answers`);
|
|
80
|
+
}).catch(() => {});
|
|
43
81
|
await context.tool.hook('execute.before', async (call) => {
|
|
44
82
|
const name = String(call?.tool || '');
|
|
45
|
-
let
|
|
83
|
+
let response;
|
|
46
84
|
try {
|
|
47
|
-
|
|
48
|
-
decision = await response.json();
|
|
85
|
+
response = await post({ tool: V1_NAMES[name] || name, providerSessionId: call?.sessionID || null, ...callArguments(call?.input) });
|
|
49
86
|
} catch {
|
|
50
87
|
if (remote === true) throw new Error(UNCHECKED);
|
|
51
88
|
return;
|
|
52
89
|
}
|
|
53
|
-
|
|
54
|
-
|
|
90
|
+
let decision = null;
|
|
91
|
+
try { decision = await response.json(); } catch { decision = null; }
|
|
92
|
+
if (response.ok && decision && decision.allow === true) return;
|
|
93
|
+
if (response.ok && decision && decision.allow === false) throw new Error(String(decision.reason || 'SynaBun route gate: call agent_route first.'));
|
|
94
|
+
throw new Error(notADecision(response.status, decision));
|
|
55
95
|
});
|
|
56
96
|
},
|
|
57
97
|
};
|
|
@@ -27,7 +27,7 @@ import { dirname } from 'node:path';
|
|
|
27
27
|
import { BUDGET_DEFAULT_USD, BUDGET_WARN_RATIO, roundUsd } from './assistant-budget.js';
|
|
28
28
|
import {
|
|
29
29
|
BUDGET_PROVIDERS, MIN_SPEND_USD, billingOf, bucketEligibility, budgetView, coverageOf, coversWork, divideLeft,
|
|
30
|
-
dryProviders, fallbackWeights, jevWeights, listPriceOf, priceLabel, providerSpendOf, rowOf, totalSpentOf,
|
|
30
|
+
dryProviders, fallbackWeights, isUnpricedProvider, jevWeights, listPriceOf, priceLabel, providerSpendOf, rowOf, totalSpentOf,
|
|
31
31
|
} from './assistant-budget-split.js';
|
|
32
32
|
|
|
33
33
|
export const SPLIT_REASONS = Object.freeze(['first_route', 'share_used_up', 'brain_turn', 'budget_changed', 'run_ended']);
|
|
@@ -156,13 +156,16 @@ export function createBudgetPlanner({
|
|
|
156
156
|
function jevInput(id, { value, used, cov, eligible, brainInfo, cat, needs, task, reason, tasks }) {
|
|
157
157
|
const rows = safe(() => accounts(), null);
|
|
158
158
|
const prefs = safe(() => routing()?.preferences, {}) || {};
|
|
159
|
-
const savedRoutes = Object.entries(prefs).filter(([, pref]) => pref?.provider).map(([taskClass, pref]) => {
|
|
159
|
+
const savedRoutes = Object.entries(prefs).filter(([, pref]) => pref?.provider && !isUnpricedProvider(pref.provider)).map(([taskClass, pref]) => {
|
|
160
160
|
const info = modelInfo(cat, pref.provider, pref.model || null, accountFor(pref.provider, rows, brainInfo));
|
|
161
161
|
return { taskClass, provider: pref.provider, model: pref.model || null, effort: pref.effort || null, price: info.price, billing: info.billing };
|
|
162
162
|
});
|
|
163
163
|
const recent = safe(() => recentSpend(id), null) || {};
|
|
164
164
|
const providers = {};
|
|
165
165
|
for (const provider of BUDGET_PROVIDERS) {
|
|
166
|
+
// A provider no budget can hold (it reports no prices) is never asked about and never described: Jev's state
|
|
167
|
+
// stays the one its questions were tuned on (budget-judgments.ts).
|
|
168
|
+
if (isUnpricedProvider(provider)) continue;
|
|
166
169
|
const own = providerSpendOf(used, provider);
|
|
167
170
|
const account = accountFor(provider, rows, brainInfo);
|
|
168
171
|
const routed = savedRoutes.filter((r) => r.provider === provider);
|
|
@@ -308,7 +311,8 @@ export function createBudgetPlanner({
|
|
|
308
311
|
if (!id || !limited()) return true;
|
|
309
312
|
let cov = coverage(id);
|
|
310
313
|
if (coversWork(cov, { provider, forBrain, free })) return true;
|
|
311
|
-
|
|
314
|
+
// No split gives an unpriced provider money: never a re-split (or a Jev request) for one.
|
|
315
|
+
if (cov.leftUsd < MIN_SPEND_USD || free || isUnpricedProvider(provider)) return false;
|
|
312
316
|
const key = `${id}:${provider}:${forBrain ? 'brain' : 'runs'}`;
|
|
313
317
|
const tried = needTries.get(key);
|
|
314
318
|
const value = readSetting();
|