synabun 2.0.9 → 2.1.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 +115 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +68 -4
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +2 -2
- 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/launcher.mjs +9 -3
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +17 -8
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +1 -1
- 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 +43 -5
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +228 -0
- package/lib/virustotal.mjs +192 -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/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/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/neural-interface.d.ts +16 -10
- 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 +20 -62
- 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/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 +10 -10
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +22 -13
- 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/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +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 +639 -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/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/neural-interface.ts +79 -20
- package/mcp-server/src/services/server-instructions.ts +27 -63
- 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/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +22 -14
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/skill-tools.ts +589 -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 +3680 -206
- package/neural-interface/i18n/pt-BR.json +3628 -157
- package/neural-interface/lib/account-usage.js +5 -3
- package/neural-interface/lib/app-controls-api.js +161 -0
- package/neural-interface/lib/assistant-api.js +148 -35
- 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 +122 -44
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +59 -0
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +97 -0
- package/neural-interface/lib/assistant-catalog.js +23 -9
- package/neural-interface/lib/assistant-dispatch.js +874 -156
- package/neural-interface/lib/assistant-envelope.js +22 -2
- package/neural-interface/lib/assistant-persona.js +80 -11
- package/neural-interface/lib/assistant-plan-permissions.js +10 -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 +13 -8
- package/neural-interface/lib/assistant-runtime.js +183 -26
- package/neural-interface/lib/assistant-task-prompt.js +78 -14
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/backup-service.js +620 -3
- 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 +83 -0
- package/neural-interface/lib/browser-network-guard.js +284 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +186 -31
- package/neural-interface/lib/claude-agent-bridge.js +4 -2
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +64 -14
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install.js +18 -138
- package/neural-interface/lib/cli-resolver.js +4 -1
- package/neural-interface/lib/cli-update-planner.js +32 -31
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-settings-schema.js +109 -47
- package/neural-interface/lib/codex-worker-app-server.js +172 -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 +164 -67
- package/neural-interface/lib/exec-loop-command.js +4 -1
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/launch-cache.js +293 -0
- package/neural-interface/lib/login-start.js +524 -0
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +0 -29
- package/neural-interface/lib/mcp-external-servers.js +323 -0
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/morelogin.js +30 -0
- package/neural-interface/lib/native-loop-providers.js +565 -50
- package/neural-interface/lib/native-loop-runtime.js +287 -41
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +58 -0
- package/neural-interface/lib/opencode-history.js +49 -204
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +44 -0
- package/neural-interface/lib/opencode-protocol.js +310 -0
- package/neural-interface/lib/opencode-provider-view.js +81 -0
- package/neural-interface/lib/opencode-runtime-config.js +32 -15
- package/neural-interface/lib/opencode-serve-records.js +624 -0
- package/neural-interface/lib/opencode-v2-client.js +53 -131
- package/neural-interface/lib/opencode-v2-ws-requests.js +35 -195
- package/neural-interface/lib/opencode-worker-activity.js +229 -0
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +796 -0
- package/neural-interface/lib/opencode2-proxy.js +76 -0
- package/neural-interface/lib/opencode2-translate.js +1057 -0
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/peer-identity.js +763 -0
- package/neural-interface/lib/process-identity.js +361 -0
- package/neural-interface/lib/request-gate.js +17 -2
- package/neural-interface/lib/rulesets/api.js +1 -1
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +92 -27
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +18 -10
- package/neural-interface/lib/session-title-generator.js +58 -18
- 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 +294 -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 +267 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +564 -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 +214 -0
- package/neural-interface/lib/skills/eval-confinement.js +397 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +119 -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 +200 -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 +387 -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 +262 -0
- package/neural-interface/lib/skills/runtime-checks.js +355 -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 +522 -0
- package/neural-interface/lib/skills/telemetry.js +113 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/style-guide/api.js +4 -3
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/untrusted-file-headers.js +27 -0
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/worker-confinement.js +1192 -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-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +229 -0
- package/neural-interface/lib/worker-sandbox.js +299 -0
- package/neural-interface/package-lock.json +1354 -50
- package/neural-interface/package.json +6 -2
- package/neural-interface/public/index.html +5 -3
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +2 -2
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +76 -16
- 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 +205 -19
- package/neural-interface/public/shared/assistant/asst-api.js +11 -3
- 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 +241 -112
- package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
- package/neural-interface/public/shared/assistant/asst-control.js +157 -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 +49 -2
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -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 +84 -12
- package/neural-interface/public/shared/assistant/asst-panel.js +303 -44
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +93 -58
- package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
- package/neural-interface/public/shared/assistant/asst-render.js +770 -100
- package/neural-interface/public/shared/assistant/asst-route.js +83 -12
- package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
- package/neural-interface/public/shared/assistant/asst-scenes.js +530 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
- package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
- package/neural-interface/public/shared/assistant/asst-state.js +25 -15
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +102 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +165 -13
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +550 -0
- 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 +8 -7
- package/neural-interface/public/shared/cdx/cdx-panel.js +58 -150
- package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
- package/neural-interface/public/shared/cdx/cdx-render.js +62 -32
- package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
- 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 +201 -74
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-view.js +4 -8
- package/neural-interface/public/shared/cli-status.js +2 -2
- package/neural-interface/public/shared/constants.js +2 -2
- 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 +366 -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-markdown.js +4 -57
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/data-cache.js +223 -0
- package/neural-interface/public/shared/desktop-bridge.js +11 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
- package/neural-interface/public/shared/desktop-titlebar.js +214 -28
- package/neural-interface/public/shared/desktop-update-view.js +35 -5
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/file-links.js +73 -8
- package/neural-interface/public/shared/html-shell.js +78 -86
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/launch-prefetch.js +59 -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-caps.js +3 -2
- 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 +9 -2
- 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-modelpicker.js +54 -17
- 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 +140 -254
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +97 -203
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +20 -13
- 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 +53 -82
- 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 +48 -40
- 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 +205 -62
- package/neural-interface/public/shared/opencode-providers.js +39 -0
- package/neural-interface/public/shared/page-session.js +96 -0
- 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 +452 -0
- package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
- package/neural-interface/public/shared/settings/settings-app.js +243 -0
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +90 -0
- package/neural-interface/public/shared/settings/settings-ia.js +23 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- 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/sidepanel-session-status.js +49 -0
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +219 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +130 -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 +141 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +475 -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 +236 -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 +229 -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-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 +279 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +681 -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 +248 -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 +425 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +2065 -2150
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- 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/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-assistant.js +27 -5
- package/neural-interface/public/shared/ui-automation-studio.js +155 -152
- package/neural-interface/public/shared/ui-bookmarks.js +2 -1
- package/neural-interface/public/shared/ui-claude-panel.js +153 -13
- package/neural-interface/public/shared/ui-codex-panel.js +1 -0
- 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 +21 -9
- package/neural-interface/public/shared/ui-file-links.js +1 -0
- package/neural-interface/public/shared/ui-image-gallery.js +56 -52
- package/neural-interface/public/shared/ui-invite.js +18 -2
- package/neural-interface/public/shared/ui-keybinds.js +26 -1
- package/neural-interface/public/shared/ui-link.js +9 -9
- package/neural-interface/public/shared/ui-menubar.js +229 -40
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +9 -1
- package/neural-interface/public/shared/ui-navbar.js +4 -24
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-schedules-studio.js +2267 -953
- package/neural-interface/public/shared/ui-sessions.js +20 -7
- package/neural-interface/public/shared/ui-settings.js +679 -496
- package/neural-interface/public/shared/ui-sidebar.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +56 -5
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
- package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
- package/neural-interface/public/shared/ui-skills.js +42 -2781
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +22 -5
- package/neural-interface/public/shared/ui-terminal.js +159 -199
- package/neural-interface/public/shared/ui-tool-updates.js +3 -1
- package/neural-interface/public/shared/ui-tooltip.js +10 -5
- package/neural-interface/public/shared/ui-trash.js +14 -5
- 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 -61
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -499
- package/neural-interface/public/shared/ui-update.js +121 -16
- package/neural-interface/public/shared/ui-whiteboard.js +313 -59
- package/neural-interface/public/shared/ui-worker-end.js +4 -0
- 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 +1 -1
- 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-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- 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 +36 -2
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +72 -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/highlight/LICENSE +29 -0
- package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
- package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
- package/neural-interface/public/vendor/highlight/manifest.json +5 -0
- package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
- package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
- package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
- package/neural-interface/public/vendor/marked/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
- package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
- package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -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 +116 -3
- package/neural-interface/server.js +4834 -2541
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +18 -12
- package/package.json +16 -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 +5 -5
- 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
|
@@ -4,9 +4,19 @@
|
|
|
4
4
|
// tool may run; a refusal becomes permissionDecision "deny" with the reason.
|
|
5
5
|
// The call's whole tool_input travels (the remote denylist reads paths from
|
|
6
6
|
// it), marked inputComplete; one too big to send goes as its command/action
|
|
7
|
-
// only, marked incomplete.
|
|
8
|
-
// allows the call — except in a WhatsApp session
|
|
9
|
-
// where a call SynaBun could not check is
|
|
7
|
+
// only, marked incomplete. No env or no answer at all (the server unreachable
|
|
8
|
+
// or slow) allows the call — except in a WhatsApp session
|
|
9
|
+
// (SYNABUN_ROUTE_GATE_REMOTE=1), where a call SynaBun could not check is
|
|
10
|
+
// denied. An answer that is not a decision (the check itself refused, such as
|
|
11
|
+
// 403 PEER_REFUSED, an error status, a body without `allow`) denies the call in
|
|
12
|
+
// every session and says what SynaBun answered: a refusal never passes for an
|
|
13
|
+
// allow.
|
|
14
|
+
//
|
|
15
|
+
// The request carries the session's pin (X-Synabun-Assistant): this hook runs
|
|
16
|
+
// under the brain's Codex app-server, an AI agent's process tree, which
|
|
17
|
+
// SynaBun's owner gate (lib/owner-authority.js) refuses unless the call says
|
|
18
|
+
// it is an agent's own. The per-session token in the body is what the route
|
|
19
|
+
// itself checks.
|
|
10
20
|
|
|
11
21
|
const url = process.env.SYNABUN_ROUTE_GATE_URL;
|
|
12
22
|
const session = process.env.SYNABUN_ROUTE_GATE_SESSION;
|
|
@@ -14,6 +24,7 @@ const token = process.env.SYNABUN_ROUTE_GATE_TOKEN;
|
|
|
14
24
|
const remote = process.env.SYNABUN_ROUTE_GATE_REMOTE === '1';
|
|
15
25
|
const MAX_INPUT_BYTES = 256 * 1024;
|
|
16
26
|
const UNCHECKED = 'SynaBun could not check this call, so a WhatsApp session does not run it.';
|
|
27
|
+
const PIN_HEADER = 'x-synabun-assistant';
|
|
17
28
|
|
|
18
29
|
let raw = '';
|
|
19
30
|
try { for await (const chunk of process.stdin) raw += chunk; } catch {}
|
|
@@ -37,20 +48,32 @@ function callArguments(toolInput) {
|
|
|
37
48
|
function deny(reason) {
|
|
38
49
|
process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: String(reason).replace(/[.\s]+$/, '') } }));
|
|
39
50
|
}
|
|
51
|
+
/** The refusal of a call whose check got an answer that is not a decision: what SynaBun answered, in short. */
|
|
52
|
+
function notADecision(status, body) {
|
|
53
|
+
const code = body && typeof body === 'object' && typeof body.code === 'string' ? ` ${body.code.slice(0, 64)}` : '';
|
|
54
|
+
const said = body && typeof body === 'object' && typeof body.error === 'string' ? `: ${body.error.slice(0, 300)}` : '';
|
|
55
|
+
return `SynaBun could not check this call (its route gate answered ${status}${code}${said}), so it did not run.`;
|
|
56
|
+
}
|
|
40
57
|
|
|
41
58
|
if (url && session && token) {
|
|
59
|
+
let response = null;
|
|
42
60
|
try {
|
|
43
|
-
|
|
61
|
+
response = await fetch(url, {
|
|
44
62
|
method: 'POST',
|
|
45
|
-
|
|
63
|
+
// The session id as a header value: printable ASCII only (fetch refuses anything else before sending).
|
|
64
|
+
headers: { 'content-type': 'application/json', [PIN_HEADER]: String(session).replace(/[^\x21-\x7e]/g, '').slice(0, 200) },
|
|
46
65
|
body: JSON.stringify({ session, token, host: 'codex', tool: String(input.tool_name || input.toolName || input.tool || ''), agent: input.agent_id || null, ...callArguments(input.tool_input) }),
|
|
47
66
|
signal: AbortSignal.timeout(5000),
|
|
48
67
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else if (remote && !(decision && decision.allow === true)) deny(UNCHECKED);
|
|
52
|
-
} catch {
|
|
68
|
+
} catch { response = null; }
|
|
69
|
+
if (!response) {
|
|
53
70
|
if (remote) deny(UNCHECKED);
|
|
71
|
+
} else {
|
|
72
|
+
let decision = null;
|
|
73
|
+
try { decision = await response.json(); } catch { decision = null; }
|
|
74
|
+
if (response.ok && decision && decision.allow === true) { /* allowed: Codex runs the call */ }
|
|
75
|
+
else if (response.ok && decision && decision.allow === false) deny(decision.reason || 'SynaBun refused this call.');
|
|
76
|
+
else deny(notADecision(response.status, decision));
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
79
|
process.exit(0);
|
|
@@ -14,6 +14,8 @@ import { createCodexEnvelopeTranslator, codexControlResponse } from '../assistan
|
|
|
14
14
|
import { baseModelId, contextVariantOf } from '../assistant-catalog.js';
|
|
15
15
|
import { codexPlanPermission, codexReadOnlyPermission, planDenyMessage, readOnlyDenyMessage } from '../assistant-plan-permissions.js';
|
|
16
16
|
import { planModeInstructions } from '../assistant-persona.js';
|
|
17
|
+
import { shouldAutoAcceptCodexMcpToolApproval } from '../codex-mcp-approvals.js';
|
|
18
|
+
import { codexMcpToolApproval } from '../../public/shared/cdx/cdx-protocol.js';
|
|
17
19
|
|
|
18
20
|
const READY_TIMEOUT_MS = 90_000;
|
|
19
21
|
// Approvals the Codex sidepanel's Auto-accept answers on its own (cdx-requests.js).
|
|
@@ -83,7 +85,7 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
83
85
|
}
|
|
84
86
|
if (planned) {
|
|
85
87
|
const method = packet.request?.brain_native?.method || packet.request?.method || '';
|
|
86
|
-
const tool = packet.request?.brain_native?.params?.
|
|
88
|
+
const tool = codexMcpToolApproval(packet.request?.brain_native?.params)?.fullName || packet.request?.tool_name || 'request';
|
|
87
89
|
const response = planned === 'allow'
|
|
88
90
|
? { behavior: 'allow', ...(!remoteReadOnly && approvalMode === 'auto' ? { always: true } : {}) }
|
|
89
91
|
: { behavior: 'deny', decline: true, message: remoteReadOnly ? readOnlyDenyMessage(tool) : planDenyMessage(tool, { host: 'codex' }) };
|
|
@@ -91,7 +93,9 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
91
93
|
sink.send({ type: 'stderr', text: `${planMode ? 'Plan mode' : 'Read-only (WhatsApp)'}: ${planned === 'allow' ? 'allowed' : 'declined'} ${String(method).split('/').slice(1, -1).join('/') || 'request'} ${tool}${planned === 'allow' ? '' : remoteReadOnly ? ' (read-only)' : ' (no code changes)'}` });
|
|
92
94
|
return;
|
|
93
95
|
}
|
|
94
|
-
|
|
96
|
+
const method = packet.request?.brain_native?.method || packet.request?.method;
|
|
97
|
+
const autoMcp = method === 'mcpServer/elicitation/request' && shouldAutoAcceptCodexMcpToolApproval(packet.request?.brain_native?.params, { autoAccept: approvalMode === 'auto', role: 'assistant' });
|
|
98
|
+
if (packet.type === 'control_request' && !planMode && !remoteReadOnly && (autoMcp || (approvalMode === 'auto' && AUTO_ACCEPT_METHODS.has(method)))) {
|
|
95
99
|
// Auto-accept: approve at once (for the session when offered), as the Codex sidepanel does.
|
|
96
100
|
send({ type: 'server_request_response', ...codexControlResponse(packet, { behavior: 'allow', always: true }) });
|
|
97
101
|
sink.send({ type: 'stderr', text: `Auto-accepted: ${String(packet.request?.brain_native?.method || packet.request?.method).split('/').slice(1, -1).join('/')}` });
|
|
@@ -119,8 +123,8 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
119
123
|
});
|
|
120
124
|
const socket = createVirtualSocket({
|
|
121
125
|
name: `codex-brain-${session.id}`,
|
|
122
|
-
//
|
|
123
|
-
//
|
|
126
|
+
// The brain's launch credential rides on the socket object, never in a message: the skin handler gives it to
|
|
127
|
+
// this app-server's SynaBun MCP child through its environment (whatsapp_send_file, the Skills Service).
|
|
124
128
|
credential: deps.brainCredential || null,
|
|
125
129
|
onSend: (packet) => {
|
|
126
130
|
if (disposed || !packet || typeof packet !== 'object') return;
|
|
@@ -159,7 +163,7 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
159
163
|
readyResolve = () => { clearTimeout(timer); resolve(true); };
|
|
160
164
|
});
|
|
161
165
|
send({
|
|
162
|
-
type: 'bootstrap', windowId, accountId: brain.accountId || 'default',
|
|
166
|
+
type: 'bootstrap', windowId, accountId: brain.accountId || 'default',
|
|
163
167
|
cwd: brain.cwd || deps.PACKAGE_ROOT || undefined, threadId: threadId || null, role: 'assistant',
|
|
164
168
|
// Unlocks the capability-gated `computer` MCP group for this brain only.
|
|
165
169
|
desktopGrant: deps.desktopGrant || null,
|
|
@@ -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,8 +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)), '
|
|
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;
|
|
39
42
|
|
|
40
43
|
/**
|
|
41
44
|
* SynaBun's plan agent. OpenCode adds its own read-only reminder ("commands may
|
|
@@ -46,65 +49,111 @@ export const OPENCODE_ROUTE_GATE_PLUGIN = pathToFileURL(resolve(dirname(fileURLT
|
|
|
46
49
|
*/
|
|
47
50
|
export const OPENCODE_PLAN_AGENT = 'synabun-plan';
|
|
48
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
|
+
|
|
49
60
|
/** The brain's SynaBun MCP tool-call timeout (ms): as long as the Codex brain's tool_timeout_sec (server.js). */
|
|
50
61
|
export const OPENCODE_BRAIN_MCP_TIMEOUT_MS = 180_000;
|
|
51
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
|
+
|
|
52
85
|
/**
|
|
53
86
|
* `routeGate` ({ url, session, token }) installs the route-gate plugin in this
|
|
54
|
-
* 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.
|
|
55
89
|
*/
|
|
56
90
|
export function patchOpenCodeAssistantConfig(xdgRoot, { persona = '', role = 'assistant', model = null, desktopGrant = null, routeGate = null, brainCredential = null } = {}) {
|
|
57
|
-
const configPath = resolve(xdgRoot, 'opencode'
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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 };
|
|
63
98
|
// Computer use: an unforgeable per-brain grant unlocks the `computer` group.
|
|
64
99
|
if (desktopGrant) env.SYNABUN_DESKTOP_GRANT = desktopGrant;
|
|
65
100
|
else delete env.SYNABUN_DESKTOP_GRANT;
|
|
66
|
-
//
|
|
101
|
+
// The brain's launch credential (whatsapp_send_file, the Skills Service), for this serve's SynaBun MCP child only.
|
|
67
102
|
// This file names the variable; the value is in the serve's own environment (ensureIsolatedServe), so
|
|
68
103
|
// neither this file (it is in every backup of data/) nor OPENCODE_CONFIG_CONTENT ever holds it.
|
|
69
104
|
if (brainCredential) env.SYNABUN_BRAIN_TOKEN = '{env:SYNABUN_BRAIN_TOKEN}';
|
|
70
105
|
else delete env.SYNABUN_BRAIN_TOKEN;
|
|
71
|
-
config.mcp.SynaBun[envKey] = env;
|
|
72
106
|
// OpenCode gives an MCP tool call 60 s unless the server says otherwise; agent_route may wait on the
|
|
73
107
|
// user's route card and whatsapp_send_file on an upload (130 s): the Codex brain's 180 s here too.
|
|
74
|
-
|
|
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 } });
|
|
75
113
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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,
|
|
79
123
|
mode: 'primary',
|
|
80
124
|
description: 'SynaBun central assistant',
|
|
81
|
-
|
|
125
|
+
...(persona ? { system: persona } : {}),
|
|
82
126
|
...(model ? { model } : {}),
|
|
83
|
-
|
|
127
|
+
permissions: withOurRules(assistant, withoutExecute),
|
|
128
|
+
});
|
|
84
129
|
// SynaBun's plan agent (desktop plan turns): no code changes, anything else as the approval mode says.
|
|
85
|
-
|
|
86
|
-
|
|
130
|
+
const synabunPlan = agentOf(config, OPENCODE_PLAN_AGENT);
|
|
131
|
+
setAgent(config, OPENCODE_PLAN_AGENT, {
|
|
132
|
+
...synabunPlan,
|
|
87
133
|
mode: 'primary',
|
|
88
134
|
hidden: true,
|
|
89
135
|
description: 'SynaBun plan mode: explore, run commands and use every tool; no code changes',
|
|
90
|
-
|
|
136
|
+
...(persona ? { system: persona } : {}),
|
|
91
137
|
...(model ? { model } : {}),
|
|
92
|
-
|
|
93
|
-
};
|
|
138
|
+
permissions: withOurRules(synabunPlan, [...withoutExecute, rule('edit', 'deny'), rule('shell', 'ask'), rule('question', 'allow'), rule('subagent', 'deny', 'general')]),
|
|
139
|
+
});
|
|
94
140
|
// OpenCode's own plan agent (a WhatsApp session's read-only brain) refuses only
|
|
95
141
|
// edits and runs any command without asking: here every command asks, so the
|
|
96
142
|
// read-only classifier decides on the whole line.
|
|
97
|
-
|
|
98
|
-
|
|
143
|
+
const plan = agentOf(config, 'plan');
|
|
144
|
+
setAgent(config, 'plan', { ...plan, permissions: withOurRules(plan, [rule('shell', 'ask')]) });
|
|
145
|
+
withoutPlugin(config, OPENCODE_ROUTE_GATE_PLUGIN);
|
|
99
146
|
// `remote`: a WhatsApp session's serve — the plugin refuses a call it could not check (fail closed).
|
|
100
|
-
if (routeGate?.url && routeGate?.session && routeGate?.token)
|
|
101
|
-
|
|
102
|
-
|
|
147
|
+
if (routeGate?.url && routeGate?.session && routeGate?.token) {
|
|
148
|
+
withPlugin(config, OPENCODE_ROUTE_GATE_PLUGIN, { url: routeGate.url, session: routeGate.session, token: routeGate.token, ...(routeGate.remote === true ? { remote: true } : {}) });
|
|
149
|
+
}
|
|
150
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
103
151
|
// It carries this brain's grants (the desktop grant): readable by this user only.
|
|
104
152
|
try { chmodSync(configPath, 0o600); } catch { /* a filesystem without modes */ }
|
|
105
153
|
return true;
|
|
106
154
|
}
|
|
107
155
|
|
|
156
|
+
|
|
108
157
|
/** The assistant's OpenCode approval mode: 'auto' (auto-accept) or 'default'. */
|
|
109
158
|
export function opencodeApprovalMode(mode) {
|
|
110
159
|
return mode === 'auto' || mode === 'acceptEdits' || mode === 'bypassPermissions' ? 'auto' : 'default';
|
|
@@ -157,8 +206,13 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
157
206
|
let keepAliveTimer = null;
|
|
158
207
|
let costUsd = 0;
|
|
159
208
|
let startPromise = null;
|
|
160
|
-
|
|
161
|
-
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
|
+
};
|
|
162
216
|
// Plan mode runs SynaBun's plan agent (OPENCODE_PLAN_AGENT; OpenCode's own
|
|
163
217
|
// `plan` agent, the persona riding as `system`, when the config patch failed).
|
|
164
218
|
let approvalMode = opencodeApprovalMode(brain.permissionMode);
|
|
@@ -207,17 +261,29 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
207
261
|
}
|
|
208
262
|
|
|
209
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 } }); }
|
|
210
265
|
async function reportMcpStatus() {
|
|
211
|
-
try { const status = await client?.mcp?.status?.({ directory: cwd });
|
|
266
|
+
try { const status = await client?.mcp?.status?.({ directory: cwd }); sendMcpStatus(status?.data || status || []); } catch {}
|
|
212
267
|
}
|
|
213
268
|
|
|
214
269
|
async function start() {
|
|
215
270
|
if (disposed) throw new Error('OpenCode brain disposed');
|
|
216
271
|
if (startPromise) return startPromise;
|
|
217
272
|
startPromise = (async () => {
|
|
218
|
-
const xdgRoot = deps.setupOpencodeSidepanelConfig(termId, brain.
|
|
219
|
-
|
|
220
|
-
|
|
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 } });
|
|
221
287
|
if (!entry?.client) throw new Error('OpenCode isolated serve failed to start');
|
|
222
288
|
client = entry.client;
|
|
223
289
|
await client.waitUntilConnected?.(20_000);
|
|
@@ -241,7 +307,9 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
241
307
|
kind: 'opencode',
|
|
242
308
|
start,
|
|
243
309
|
async sendUserTurn({ text, images = [], model = null, effort = null, permissionMode: mode = null, planMode: plan = null } = {}) {
|
|
310
|
+
const stop = stops;
|
|
244
311
|
await start();
|
|
312
|
+
if (disposed || stops !== stop) return false;
|
|
245
313
|
applyModes(mode, plan);
|
|
246
314
|
turnActive = true;
|
|
247
315
|
// The runtime passes the effective model/effort on every turn (the record
|
|
@@ -250,7 +318,6 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
250
318
|
const request = {
|
|
251
319
|
sessionID: sessionId, parts, model: normalizeOpenCodeModel(model || brain.model), directory: cwd,
|
|
252
320
|
};
|
|
253
|
-
if (request.model) lastTurnModel = request.model;
|
|
254
321
|
if (effort) request.variant = String(effort);
|
|
255
322
|
turnPlanned = planMode && !remoteReadOnly;
|
|
256
323
|
if (turnPlanned && personaInstalled) {
|
|
@@ -265,14 +332,25 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
265
332
|
else if (personaInstalled) request.agent = brain.agent || 'assistant';
|
|
266
333
|
else { request.agent = brain.agent || 'build'; if (persona) request.system = persona; }
|
|
267
334
|
if (entry) entry.lastUsed = Date.now();
|
|
268
|
-
// SynaBun
|
|
269
|
-
|
|
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; }
|
|
270
348
|
const response = await client.session.promptAsync(request);
|
|
271
349
|
const status = Number(response?.status);
|
|
272
350
|
if (Number.isFinite(status) && status >= 400) { turnActive = false; throw new Error(`OpenCode prompt failed (${status})`); }
|
|
273
351
|
return true;
|
|
274
352
|
},
|
|
275
|
-
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' }); },
|
|
276
354
|
async setPermissionMode(mode, { planMode: plan = null } = {}) { applyModes(mode, plan); sink.send({ type: 'mode_changed', mode: approvalMode, planMode }); },
|
|
277
355
|
respondControl(requestId, response) {
|
|
278
356
|
const pending = pendingControls.get(String(requestId));
|
|
@@ -284,12 +362,11 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
284
362
|
: client.permission.reply({ requestID: body.requestID, reply: body.reply, directory: cwd });
|
|
285
363
|
Promise.resolve(call).catch((error) => sink.send({ type: 'error', message: `OpenCode reply failed: ${error?.message || error}` }));
|
|
286
364
|
},
|
|
287
|
-
// OpenCode
|
|
288
|
-
// compactOrSummarize then summarises on the model of the last turn.
|
|
365
|
+
// OpenCode compacts the session on the model it runs on.
|
|
289
366
|
async compact() {
|
|
290
367
|
await start();
|
|
291
368
|
turnPlanned = false;
|
|
292
|
-
await
|
|
369
|
+
await client.session.compact({ sessionID: sessionId, directory: cwd });
|
|
293
370
|
},
|
|
294
371
|
async mcpStatus() { await reportMcpStatus(); },
|
|
295
372
|
async reconcileUsage(meter) {
|
|
@@ -325,6 +402,7 @@ export function createOpenCodeBrain({ session, sink, deps = {}, persona = '' } =
|
|
|
325
402
|
async dispose() {
|
|
326
403
|
if (disposed) return;
|
|
327
404
|
disposed = true;
|
|
405
|
+
waitingAbort?.abort();
|
|
328
406
|
if (keepAliveTimer) clearInterval(keepAliveTimer);
|
|
329
407
|
if (unsubscribe) { try { unsubscribe(); } catch {} }
|
|
330
408
|
try { deps.stopIsolatedServe(termId); } catch {}
|
|
@@ -0,0 +1,59 @@
|
|
|
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.
|
|
21
|
+
|
|
22
|
+
// An absolute file URL: the policy loads from SynaBun's lib/ wherever OpenCode imports this file from.
|
|
23
|
+
const POLICY_URL = new URL('../../browser-tool-policy.js', import.meta.url).href;
|
|
24
|
+
const V1_NAMES = { shell: 'bash', subagent: 'task' };
|
|
25
|
+
|
|
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.
|
|
28
|
+
const OWN_TOOLS = new Set([
|
|
29
|
+
'read', 'list', 'glob', 'grep', 'edit', 'write', 'patch', 'todo', 'task', 'skill', 'lsp', 'question',
|
|
30
|
+
'invalid', 'plan_exit', 'plan_enter',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
export default {
|
|
34
|
+
id: 'synabun.browser-policy',
|
|
35
|
+
async setup(context) {
|
|
36
|
+
const options = context?.options || {};
|
|
37
|
+
let policy = null;
|
|
38
|
+
let loadError = null;
|
|
39
|
+
try { policy = await import(POLICY_URL); } catch (error) { loadError = error; }
|
|
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') : [];
|
|
42
|
+
if (typeof policy?.browserToolDenial !== 'function') {
|
|
43
|
+
const why = loadError?.message || 'browserToolDenial is missing';
|
|
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`);
|
|
45
|
+
await context.tool.hook('execute.before', async (call) => {
|
|
46
|
+
const raw = String(call?.tool || '');
|
|
47
|
+
const tool = V1_NAMES[raw] || raw;
|
|
48
|
+
if (/^synabun_/i.test(tool) || OWN_TOOLS.has(tool.toLowerCase())) return;
|
|
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.`);
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
await context.tool.hook('execute.before', async (call) => {
|
|
54
|
+
const raw = String(call?.tool || '');
|
|
55
|
+
const reason = policy.browserToolDenial(V1_NAMES[raw] || raw, call?.input || {}, { host: 'opencode', cwd, roots });
|
|
56
|
+
if (reason) throw new Error(reason);
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
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.
|
|
35
|
+
|
|
36
|
+
const MAX_INPUT_BYTES = 256 * 1024;
|
|
37
|
+
const UNCHECKED = 'SynaBun could not check this call, so a WhatsApp session does not run it.';
|
|
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
|
+
}
|
|
52
|
+
|
|
53
|
+
/** { input, inputComplete }: the whole arguments when small enough to send, else their command/action. */
|
|
54
|
+
function callArguments(args) {
|
|
55
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) return { input: {}, inputComplete: false };
|
|
56
|
+
let size = Infinity;
|
|
57
|
+
try { size = JSON.stringify(args).length; } catch {}
|
|
58
|
+
if (size <= MAX_INPUT_BYTES) return { input: args, inputComplete: true };
|
|
59
|
+
const subset = {};
|
|
60
|
+
for (const key of ['command', 'action']) {
|
|
61
|
+
if (typeof args[key] === 'string' && args[key].length <= 64 * 1024) subset[key] = args[key];
|
|
62
|
+
}
|
|
63
|
+
return { input: subset, inputComplete: false };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default {
|
|
67
|
+
id: 'synabun.route-gate',
|
|
68
|
+
async setup(context) {
|
|
69
|
+
const { url, session, token, remote = false } = context?.options || {};
|
|
70
|
+
if (!url || !session || !token) return;
|
|
71
|
+
const post = (body) => fetch(url, {
|
|
72
|
+
method: 'POST',
|
|
73
|
+
headers: { 'content-type': 'application/json', [PIN_HEADER]: pinOf(session) },
|
|
74
|
+
body: JSON.stringify({ session, token, host: 'opencode', ...body }),
|
|
75
|
+
signal: AbortSignal.timeout(5000),
|
|
76
|
+
});
|
|
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(() => {});
|
|
81
|
+
await context.tool.hook('execute.before', async (call) => {
|
|
82
|
+
const name = String(call?.tool || '');
|
|
83
|
+
let response;
|
|
84
|
+
try {
|
|
85
|
+
response = await post({ tool: V1_NAMES[name] || name, providerSessionId: call?.sessionID || null, ...callArguments(call?.input) });
|
|
86
|
+
} catch {
|
|
87
|
+
if (remote === true) throw new Error(UNCHECKED);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
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));
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
};
|