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
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
// deps (all supplied by handleOpencodeV2Ws):
|
|
10
10
|
// send(data) write one JSON message to this socket
|
|
11
11
|
// shared the shared-serve client (opencode-v2-client).
|
|
12
|
-
//
|
|
12
|
+
// Client calls added for the panel are under
|
|
13
13
|
// `client.extra.<group>.<method>`
|
|
14
14
|
// bound(sessionId) the serve currently hosting the session's
|
|
15
15
|
// turn, else the shared client; never spawns
|
|
16
|
-
// turn(sessionId,
|
|
16
|
+
// turn(sessionId, tools) the session's dedicated serve; may spawn it
|
|
17
17
|
// proxy(method, path, body, timeoutMs, baseUrl) raw HTTP to a serve
|
|
18
18
|
// baseUrlFor(sessionId) base URL of the serve hosting the session
|
|
19
19
|
// directoryQuery(cwd) `?directory=…` or ''
|
|
@@ -31,19 +31,15 @@
|
|
|
31
31
|
// a type only when that type is listed.
|
|
32
32
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
33
33
|
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import { compactOrSummarize, lastModelOf } from './opencode-v2-client.js';
|
|
38
|
-
import { sessionTablesFor } from './opencode-db-schema.js';
|
|
39
|
-
|
|
40
|
-
export { lastModelOf };
|
|
34
|
+
import { OPENCODE_SESSION_TABLES } from './opencode-db-schema.js';
|
|
35
|
+
import { opencodeMcpServerEntry } from './opencode-config.js';
|
|
36
|
+
import { storedToolList } from './tool-lists.js';
|
|
41
37
|
|
|
42
38
|
// Types answered by the switch in server.js.
|
|
43
39
|
export const OPENCODE_V2_WS_INLINE_TYPES = Object.freeze([
|
|
44
40
|
'init', 'identify',
|
|
45
41
|
'session:list', 'session:create', 'session:get', 'session:update', 'session:delete', 'session:messages',
|
|
46
|
-
'mcp:
|
|
42
|
+
'mcp:tools:get', 'mcp:tools:set',
|
|
47
43
|
'message:send', 'message:abort',
|
|
48
44
|
'question:list', 'question:reject',
|
|
49
45
|
]);
|
|
@@ -71,6 +67,10 @@ const SESSION_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
|
71
67
|
*/
|
|
72
68
|
export function canonicalizeOpencodeV2Message(msg) {
|
|
73
69
|
if (!msg || typeof msg !== 'object') return failure(400, 'malformed request');
|
|
70
|
+
if (msg.tools !== undefined && msg.tools !== null) {
|
|
71
|
+
try { msg.tools = storedToolList({ tools: msg.tools }); }
|
|
72
|
+
catch (error) { return failure(400, error.message, { code: error.code, problems: error.problems }); }
|
|
73
|
+
}
|
|
74
74
|
const raw = msg.sessionId;
|
|
75
75
|
if (raw === undefined || raw === null) {
|
|
76
76
|
msg.sessionId = undefined;
|
|
@@ -134,18 +134,11 @@ function modelOf(value) {
|
|
|
134
134
|
return providerID && modelID ? { providerID, modelID } : null;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
// session
|
|
137
|
+
// OpenCode compacts a session on the model it runs on.
|
|
138
138
|
async function compactSession(msg, deps) {
|
|
139
|
-
const client = await deps.turn(sessionKeyOf(msg), msg.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
sessionID: sessionIdOf(msg), directory: directoryOf(msg), model: modelOf(msg.model),
|
|
143
|
-
});
|
|
144
|
-
} catch (err) {
|
|
145
|
-
// "Pick a model first" is an answer for the user, not a server error.
|
|
146
|
-
if (err?.status === 400) return failure(400, err.message);
|
|
147
|
-
throw err;
|
|
148
|
-
}
|
|
139
|
+
const client = await deps.turn(sessionKeyOf(msg), msg.tools);
|
|
140
|
+
const r = await client.session.compact({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
141
|
+
return { status: r?.status, data: r?.data };
|
|
149
142
|
}
|
|
150
143
|
|
|
151
144
|
const PERMISSION_REPLIES = new Set(['once', 'always', 'reject']);
|
|
@@ -230,45 +223,18 @@ async function sessionStatus(msg, deps) {
|
|
|
230
223
|
return { status: r.status, data: { status: statusForSession(r.data, sessionIdOf(msg)) } };
|
|
231
224
|
}
|
|
232
225
|
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
|
|
237
|
-
return !(data?.type === 'event' && data.eventType === 'sync');
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Body of `POST /mcp` for a server SynaBun describes as { command, args, env }
|
|
241
|
-
// or { url, headers }. OpenCode takes McpLocalConfig (`type: 'local'`, the
|
|
242
|
-
// command as one array, `environment`) or McpRemoteConfig; `type: 'stdio'` with
|
|
243
|
-
// a string command is answered 400.
|
|
226
|
+
// An MCP server as OpenCode 2 takes it (`mcp.servers.<name>`, lib/opencode-config.js), from what SynaBun
|
|
227
|
+
// describes as { command, args, env } or { url, headers }: type local with the command as one array and its
|
|
228
|
+
// `environment`, or type remote. Every word goes through as it is: an argument may be empty or carry spaces on
|
|
229
|
+
// purpose, and what is registered must be what was typed.
|
|
244
230
|
export function buildOpencodeRuntimeMcpConfig(config = {}) {
|
|
245
|
-
|
|
246
|
-
if (typeof config.url === 'string' && config.url) {
|
|
247
|
-
return {
|
|
248
|
-
type: 'remote',
|
|
249
|
-
url: config.url,
|
|
250
|
-
...(config.headers && typeof config.headers === 'object' ? { headers: config.headers } : {}),
|
|
251
|
-
enabled: config.enabled !== false,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
// Every word goes through as it is: an argument may be empty or carry
|
|
255
|
-
// spaces on purpose, and what is registered must be what was typed.
|
|
256
|
-
const head = Array.isArray(config.command) ? config.command : [config.command];
|
|
257
|
-
const command = [...head, ...(Array.isArray(config.args) ? config.args : [])]
|
|
258
|
-
.filter((part) => typeof part === 'string');
|
|
259
|
-
const environment = config.environment || config.env;
|
|
260
|
-
return {
|
|
261
|
-
type: 'local',
|
|
262
|
-
command,
|
|
263
|
-
...(environment && typeof environment === 'object' ? { environment } : {}),
|
|
264
|
-
enabled: config.enabled !== false,
|
|
265
|
-
};
|
|
231
|
+
return opencodeMcpServerEntry(config);
|
|
266
232
|
}
|
|
267
233
|
|
|
268
234
|
// ── Session list (read straight from OpenCode's SQLite) ─────────────────────
|
|
269
|
-
// The
|
|
270
|
-
// lists every project, so server.js reads
|
|
271
|
-
// the row mapping live here so they can be tested against a real table.
|
|
235
|
+
// The client's session.list only answers for the serve's own project; the panel
|
|
236
|
+
// lists every project, so server.js reads OpenCode's `session_v2` table. The
|
|
237
|
+
// query and the row mapping live here so they can be tested against a real table.
|
|
272
238
|
export const SESSION_LIST_MAX = 500;
|
|
273
239
|
|
|
274
240
|
/**
|
|
@@ -278,10 +244,8 @@ export const SESSION_LIST_MAX = 500;
|
|
|
278
244
|
* search case-insensitive match on title, slug or directory
|
|
279
245
|
* Un-archiving writes time_archived = 0, so "live" is NULL or 0.
|
|
280
246
|
*/
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
export function buildSessionListQuery(options = {}, { flavor = 'v1' } = {}) {
|
|
284
|
-
const tables = sessionTablesFor(flavor);
|
|
247
|
+
export function buildSessionListQuery(options = {}) {
|
|
248
|
+
const tables = OPENCODE_SESSION_TABLES;
|
|
285
249
|
const where = [];
|
|
286
250
|
const params = [];
|
|
287
251
|
where.push(options.archived === true
|
|
@@ -297,7 +261,7 @@ export function buildSessionListQuery(options = {}, { flavor = 'v1' } = {}) {
|
|
|
297
261
|
const requested = Number(options.limit);
|
|
298
262
|
const limit = Number.isInteger(requested) && requested > 0 ? Math.min(requested, SESSION_LIST_MAX) : null;
|
|
299
263
|
const sql = `
|
|
300
|
-
SELECT s.id, s.title, s.directory, s.slug, s.project_id, s.parent_id,
|
|
264
|
+
SELECT s.id, s.title, s.directory, s.slug, s.project_id, s.parent_id,
|
|
301
265
|
s.time_created, s.time_updated, s.time_archived,
|
|
302
266
|
${tables.messageCount} AS message_count
|
|
303
267
|
FROM ${tables.session} s
|
|
@@ -321,20 +285,19 @@ export function mapSessionListRow(row) {
|
|
|
321
285
|
time: { created: epochMs(row.time_created), updated: epochMs(row.time_updated) },
|
|
322
286
|
};
|
|
323
287
|
if (row.parent_id) out.parentID = row.parent_id;
|
|
324
|
-
if (row.share_url) out.share = { url: row.share_url };
|
|
325
288
|
const archived = epochMs(row.time_archived);
|
|
326
289
|
if (archived) out.time.archived = archived;
|
|
327
290
|
return out;
|
|
328
291
|
}
|
|
329
292
|
|
|
330
|
-
// ── Session lifecycle (revert, fork,
|
|
293
|
+
// ── Session lifecycle (revert, fork, children) ──────────────────────────────
|
|
331
294
|
|
|
332
295
|
const messageIdOf = (msg) => (typeof msg?.messageID === 'string' && msg.messageID.trim()
|
|
333
296
|
? msg.messageID.trim()
|
|
334
297
|
: (typeof msg?.messageId === 'string' ? msg.messageId.trim() : ''));
|
|
335
298
|
|
|
336
|
-
// Reverting
|
|
337
|
-
//
|
|
299
|
+
// Reverting under a running turn would pull the transcript out from under the
|
|
300
|
+
// model.
|
|
338
301
|
function refuseWhileRunning(msg, deps, what) {
|
|
339
302
|
return deps.isTurnActive?.(sessionIdOf(msg))
|
|
340
303
|
? failure(409, `Stop the running turn before you ${what}.`)
|
|
@@ -372,48 +335,6 @@ async function sessionChildren(msg, deps) {
|
|
|
372
335
|
return { status: r.status, data: Array.isArray(r.data) ? r.data : [] };
|
|
373
336
|
}
|
|
374
337
|
|
|
375
|
-
async function messageDelete(msg, deps) {
|
|
376
|
-
const busy = refuseWhileRunning(msg, deps, 'delete a message');
|
|
377
|
-
if (busy) return busy;
|
|
378
|
-
const messageID = messageIdOf(msg);
|
|
379
|
-
if (!messageID) return failure(400, 'messageID is required');
|
|
380
|
-
const r = await deps.bound(sessionKeyOf(msg)).extra.session.deleteMessage({
|
|
381
|
-
sessionID: sessionIdOf(msg), messageID, directory: directoryOf(msg),
|
|
382
|
-
});
|
|
383
|
-
return { status: r.status, data: r.data };
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// OpenCode's `share` setting: manual (default), auto, or disabled.
|
|
387
|
-
export function sharePolicyOf(config) {
|
|
388
|
-
const value = config?.share;
|
|
389
|
-
if (value === 'disabled' || value === 'auto' || value === 'manual') return value;
|
|
390
|
-
return 'manual';
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async function readSharePolicy(msg, deps) {
|
|
394
|
-
const r = await deps.shared.extra.config.get({ directory: directoryOf(msg) });
|
|
395
|
-
return sharePolicyOf(r.data);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
async function sessionSharePolicy(msg, deps) {
|
|
399
|
-
return { status: 200, data: { share: await readSharePolicy(msg, deps) } };
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Publishes the transcript at a public opencode URL. The panel confirms with
|
|
403
|
-
// the user every time; the server refuses when the config forbids sharing.
|
|
404
|
-
async function sessionShare(msg, deps) {
|
|
405
|
-
if (await readSharePolicy(msg, deps) === 'disabled') {
|
|
406
|
-
return failure(403, 'Sharing is disabled in the OpenCode config.');
|
|
407
|
-
}
|
|
408
|
-
const r = await deps.shared.extra.session.share({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
409
|
-
return { status: r.status, data: r.data };
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
async function sessionUnshare(msg, deps) {
|
|
413
|
-
const r = await deps.shared.extra.session.unshare({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
414
|
-
return { status: r.status, data: r.data };
|
|
415
|
-
}
|
|
416
|
-
|
|
417
338
|
// ── Composer: slash commands, shell, file search ────────────────────────────
|
|
418
339
|
|
|
419
340
|
/** What the slash menu needs of a Command; the template can be 16 KB and is not sent. */
|
|
@@ -442,10 +363,12 @@ function modelRef(value) {
|
|
|
442
363
|
|
|
443
364
|
// Run something that occupies the session like a prompt does: on the
|
|
444
365
|
// session's dedicated serve, inside the same turn bookkeeping as message:send.
|
|
445
|
-
async function withTurn(msg, deps, run) {
|
|
366
|
+
async function withTurn(msg, deps, run, { needsMcp = true } = {}) {
|
|
446
367
|
const scope = deps.turnScope(sessionIdOf(msg));
|
|
447
368
|
try {
|
|
448
|
-
const client = await deps.turn(sessionKeyOf(msg), msg.
|
|
369
|
+
const client = await deps.turn(sessionKeyOf(msg), msg.tools);
|
|
370
|
+
if (needsMcp) await deps.waitForTools?.(client, sessionIdOf(msg), directoryOf(msg), scope.signal);
|
|
371
|
+
if (scope.signal?.aborted) throw Object.assign(new Error('OpenCode turn stopped before sending'), { name: 'AbortError', status: 499 });
|
|
449
372
|
const r = await run(client, scope.signal ? { signal: scope.signal } : undefined);
|
|
450
373
|
return { status: r.status, data: r.data };
|
|
451
374
|
} finally {
|
|
@@ -483,7 +406,7 @@ async function sessionShell(msg, deps) {
|
|
|
483
406
|
agent: typeof msg.agent === 'string' && msg.agent ? msg.agent : 'build',
|
|
484
407
|
model: modelOf(msg.model) || undefined,
|
|
485
408
|
directory: directoryOf(msg),
|
|
486
|
-
}, options));
|
|
409
|
+
}, options), { needsMcp: false });
|
|
487
410
|
}
|
|
488
411
|
|
|
489
412
|
export const FIND_FILES_LIMIT = 50;
|
|
@@ -651,55 +574,6 @@ async function vcsDiff(msg, deps) {
|
|
|
651
574
|
return { status: r.status, data: capFileDiffs(r.data) };
|
|
652
575
|
}
|
|
653
576
|
|
|
654
|
-
// ── Worktrees ───────────────────────────────────────────────────────────────
|
|
655
|
-
|
|
656
|
-
// worktree.create answers a Worktree { name, branch, directory }; worktree.list
|
|
657
|
-
// answers the directories only (confirmed on 1.18.34).
|
|
658
|
-
function worktreeRow(w) {
|
|
659
|
-
const directory = typeof w === 'string' ? w : (w && typeof w.directory === 'string' ? w.directory : '');
|
|
660
|
-
if (!directory) return null;
|
|
661
|
-
const leaf = directory.split(/[\\/]/).filter(Boolean).pop() || directory;
|
|
662
|
-
return {
|
|
663
|
-
name: typeof w === 'object' && w.name ? String(w.name) : leaf,
|
|
664
|
-
branch: typeof w === 'object' && typeof w.branch === 'string' ? w.branch : '',
|
|
665
|
-
directory,
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
async function worktreeList(msg, deps) {
|
|
670
|
-
if (!directoryOf(msg)) return failure(400, 'cwd is required');
|
|
671
|
-
const r = await deps.shared.extra.worktree.list({ directory: directoryOf(msg) });
|
|
672
|
-
return { status: r.status, data: (Array.isArray(r.data) ? r.data : []).map(worktreeRow).filter(Boolean) };
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
async function worktreeCreate(msg, deps) {
|
|
676
|
-
if (!directoryOf(msg)) return failure(400, 'cwd is required');
|
|
677
|
-
const name = typeof msg.name === 'string' ? msg.name.trim() : '';
|
|
678
|
-
if (name && !/^[A-Za-z0-9][\w.-]{0,63}$/.test(name)) {
|
|
679
|
-
return failure(400, 'A worktree name may use letters, digits, ".", "_" and "-".');
|
|
680
|
-
}
|
|
681
|
-
const r = await deps.shared.extra.worktree.create({
|
|
682
|
-
directory: directoryOf(msg),
|
|
683
|
-
worktreeCreateInput: name ? { name } : {},
|
|
684
|
-
});
|
|
685
|
-
const row = worktreeRow(r.data);
|
|
686
|
-
if (!row) return failure(502, 'OpenCode did not return the new worktree.');
|
|
687
|
-
return { status: r.status, data: row };
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// Removing deletes a directory, so only one OpenCode itself lists as a worktree
|
|
691
|
-
// of this project is accepted.
|
|
692
|
-
async function worktreeRemove(msg, deps) {
|
|
693
|
-
const cwd = directoryOf(msg);
|
|
694
|
-
const target = typeof msg.directory === 'string' ? msg.directory.trim() : '';
|
|
695
|
-
if (!cwd || !target) return failure(400, 'cwd and directory are required');
|
|
696
|
-
const listed = await deps.shared.extra.worktree.list({ directory: cwd });
|
|
697
|
-
const known = (Array.isArray(listed.data) ? listed.data : []).some((w) => worktreeRow(w)?.directory === target);
|
|
698
|
-
if (!known) return failure(404, 'That directory is not a worktree of this project.');
|
|
699
|
-
const r = await deps.shared.extra.worktree.remove({ directory: cwd, worktreeRemoveInput: { directory: target } });
|
|
700
|
-
return { status: r.status, data: true };
|
|
701
|
-
}
|
|
702
|
-
|
|
703
577
|
// ── Environment: MCP servers, LSP, formatters ───────────────────────────────
|
|
704
578
|
|
|
705
579
|
// SynaBun's own MCP entry is pinned by the runtime (profile, terminal identity,
|
|
@@ -744,19 +618,6 @@ async function mcpSwitch(msg, deps, connect) {
|
|
|
744
618
|
return { status: r.status, data: after ? mcpRows(after.data) : [] };
|
|
745
619
|
}
|
|
746
620
|
|
|
747
|
-
// OAuth for a remote MCP server: OpenCode opens the browser itself and waits
|
|
748
|
-
// for the callback, so the request can take minutes.
|
|
749
|
-
async function mcpAuthenticate(msg, deps) {
|
|
750
|
-
const name = mcpNameOf(msg);
|
|
751
|
-
if (!name) return failure(400, 'MCP server name is required');
|
|
752
|
-
if (isManagedMcpName(name)) return failure(403, `${name} is managed by SynaBun.`);
|
|
753
|
-
const path = `/mcp/${encodeURIComponent(name)}/auth/authenticate${deps.directoryQuery(msg.cwd)}`;
|
|
754
|
-
const r = await deps.proxy('POST', path, {}, 5 * 60 * 1000, deps.baseUrlFor(sessionKeyOf(msg)));
|
|
755
|
-
if (r.status >= 400 || typeof r.data === 'string') {
|
|
756
|
-
return failure(r.status >= 400 ? r.status : 502, proxyErrorText(r.data, 'Authentication did not complete'));
|
|
757
|
-
}
|
|
758
|
-
return { status: r.status, data: r.data };
|
|
759
|
-
}
|
|
760
621
|
|
|
761
622
|
const MCP_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
762
623
|
const stringMap = (value) => value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -864,10 +725,6 @@ const HANDLERS = {
|
|
|
864
725
|
'session:unrevert': { session: true, mutates: true, run: sessionUnrevert },
|
|
865
726
|
'session:fork': { session: true, mutates: true, run: sessionFork },
|
|
866
727
|
'session:children': { session: true, run: sessionChildren },
|
|
867
|
-
'session:share': { session: true, mutates: true, run: sessionShare },
|
|
868
|
-
'session:unshare': { session: true, mutates: true, run: sessionUnshare },
|
|
869
|
-
'session:share:policy': { run: sessionSharePolicy },
|
|
870
|
-
'message:delete': { session: true, mutates: true, run: messageDelete },
|
|
871
728
|
'command:list': { run: commandList },
|
|
872
729
|
'command:run': { session: true, mutates: true, run: commandRun },
|
|
873
730
|
'session:shell': { session: true, mutates: true, run: sessionShell },
|
|
@@ -880,13 +737,9 @@ const HANDLERS = {
|
|
|
880
737
|
'vcs:get': { run: vcsGet },
|
|
881
738
|
'vcs:status': { run: vcsStatus },
|
|
882
739
|
'vcs:diff': { run: vcsDiff },
|
|
883
|
-
'worktree:list': { run: worktreeList },
|
|
884
|
-
'worktree:create': { run: worktreeCreate },
|
|
885
|
-
'worktree:remove': { run: worktreeRemove },
|
|
886
740
|
'mcp:status': { run: mcpStatus },
|
|
887
741
|
'mcp:connect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, true) },
|
|
888
742
|
'mcp:disconnect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, false) },
|
|
889
|
-
'mcp:authenticate': { session: true, mutates: true, run: mcpAuthenticate },
|
|
890
743
|
'mcp:add': { session: true, mutates: true, run: mcpAdd },
|
|
891
744
|
'env:status': { run: envStatus },
|
|
892
745
|
};
|
|
@@ -902,42 +755,15 @@ export const OPENCODE_V2_WS_MODULE_TYPES = Object.freeze(Object.keys(HANDLERS));
|
|
|
902
755
|
// Behaviours of an existing type that an older server lacks. Listed next to
|
|
903
756
|
// the types so the panel can gate on them the same way; never a request type.
|
|
904
757
|
export const OPENCODE_V2_WS_FEATURES = Object.freeze([
|
|
758
|
+
'feature:tool-lists',
|
|
905
759
|
'feature:permission-reply-message', // permission:reply forwards a rejection reason
|
|
906
|
-
'feature:compact-summarize', // session:compact falls back to session.summarize
|
|
907
760
|
'feature:session-list-filters', // session:list takes search / archived / roots / limit, rows carry parentID
|
|
908
761
|
'feature:mcp-add-persist', // mcp:add with persist:true saves the server without starting it a second time
|
|
909
762
|
]);
|
|
910
763
|
|
|
911
|
-
// The version of the @opencode-ai/sdk this server talks to OpenCode through,
|
|
912
|
-
// for the panel's Versions rows ('' when its package.json cannot be read).
|
|
913
|
-
let _sdkVersion;
|
|
914
|
-
export function opencodeSdkVersion() {
|
|
915
|
-
if (_sdkVersion !== undefined) return _sdkVersion;
|
|
916
|
-
_sdkVersion = '';
|
|
917
|
-
try {
|
|
918
|
-
let dir = dirname(fileURLToPath(import.meta.resolve('@opencode-ai/sdk/v2')));
|
|
919
|
-
for (let i = 0; i < 6 && dir !== dirname(dir); i += 1, dir = dirname(dir)) {
|
|
920
|
-
let pkg = null;
|
|
921
|
-
try { pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); } catch { /* not the package root */ }
|
|
922
|
-
if (pkg?.name === '@opencode-ai/sdk') { _sdkVersion = String(pkg.version || ''); break; }
|
|
923
|
-
}
|
|
924
|
-
} catch { /* stays '' */ }
|
|
925
|
-
return _sdkVersion;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
764
|
// Everything this server answers, for the panel's feature gating.
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
// feature an older SynaBun server lacks.
|
|
932
|
-
export const OPENCODE2_UNSUPPORTED_TYPES = Object.freeze([
|
|
933
|
-
'session:share', 'session:unshare', 'session:share:policy', 'message:delete',
|
|
934
|
-
'worktree:create', 'worktree:remove', 'mcp:authenticate',
|
|
935
|
-
]);
|
|
936
|
-
|
|
937
|
-
/** `protocol`: the OpenCode major the shared serve speaks (2 leaves out OPENCODE2_UNSUPPORTED_TYPES). */
|
|
938
|
-
export function opencodeV2WsCapabilities({ protocol = null } = {}) {
|
|
939
|
-
const all = [...OPENCODE_V2_WS_INLINE_TYPES, ...OPENCODE_V2_WS_MODULE_TYPES, ...OPENCODE_V2_WS_FEATURES];
|
|
940
|
-
return protocol === 2 ? all.filter((type) => !OPENCODE2_UNSUPPORTED_TYPES.includes(type)) : all;
|
|
765
|
+
export function opencodeV2WsCapabilities() {
|
|
766
|
+
return [...OPENCODE_V2_WS_INLINE_TYPES, ...OPENCODE_V2_WS_MODULE_TYPES, ...OPENCODE_V2_WS_FEATURES];
|
|
941
767
|
}
|
|
942
768
|
|
|
943
769
|
export function ownsOpencodeV2Request(type) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Isolate the serve/config, not the provider's credential database. OpenCode 2
|
|
2
|
+
// keeps credentials and sessions together. Pin the original XDG stores so a
|
|
3
|
+
// restart cannot silently select another HOME/account or an empty database.
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { isAbsolute, join } from 'node:path';
|
|
7
|
+
|
|
8
|
+
export function openCodeWorkerData(configRoot, { resume = false, env = process.env, home = homedir() } = {}) {
|
|
9
|
+
const file = join(configRoot, 'worker-data.json');
|
|
10
|
+
const keys = ['XDG_DATA_HOME', 'XDG_STATE_HOME', 'XDG_CACHE_HOME'];
|
|
11
|
+
if (resume || existsSync(file)) {
|
|
12
|
+
let saved;
|
|
13
|
+
try { saved = JSON.parse(readFileSync(file, 'utf8')); } catch { throw new Error('OpenCode durable session data descriptor is gone'); }
|
|
14
|
+
if (!keys.every(key => typeof saved[key] === 'string' && isAbsolute(saved[key]))) throw new Error('OpenCode durable session data descriptor is invalid');
|
|
15
|
+
if (!existsSync(join(saved.XDG_DATA_HOME, 'opencode', 'opencode.db'))) throw new Error('OpenCode durable session database is gone');
|
|
16
|
+
return Object.fromEntries(keys.map(key => [key, saved[key]]));
|
|
17
|
+
}
|
|
18
|
+
const saved = {
|
|
19
|
+
XDG_DATA_HOME: env.XDG_DATA_HOME || join(home, '.local', 'share'),
|
|
20
|
+
XDG_STATE_HOME: env.XDG_STATE_HOME || join(home, '.local', 'state'),
|
|
21
|
+
XDG_CACHE_HOME: env.XDG_CACHE_HOME || join(home, '.cache'),
|
|
22
|
+
};
|
|
23
|
+
if (!keys.every(key => isAbsolute(saved[key]))) throw new Error('OpenCode XDG directories must be absolute');
|
|
24
|
+
mkdirSync(configRoot, { recursive: true });
|
|
25
|
+
writeFileSync(file, JSON.stringify(saved) + '\n', { mode: 0o600 });
|
|
26
|
+
return saved;
|
|
27
|
+
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
-
// OpenCode 2 client — the
|
|
2
|
+
// OpenCode 2 client — the one client SynaBun speaks to `opencode serve` with.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// (
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// (the OpenCode panel, the Assistant's OpenCode brain, workers, loops, the
|
|
12
|
-
// usage meter), runs unchanged on either major.
|
|
4
|
+
// lib/opencode-v2-client.js (`connect`, `createClientInstance`) builds it for
|
|
5
|
+
// every serve. It has the groups and methods SynaBun calls (`session.prompt`,
|
|
6
|
+
// `global.event`, `permission.reply`, …) with the `{ data, error, response }`
|
|
7
|
+
// results SynaBun's consumers read, in the shapes they were written for
|
|
8
|
+
// (OpenCode 1's: lib/opencode2-translate.js). So the wrapper, and everything
|
|
9
|
+
// above it (the OpenCode panel, the Assistant's OpenCode brain, workers, loops,
|
|
10
|
+
// the usage meter), reads one set of shapes.
|
|
13
11
|
//
|
|
14
|
-
// What OpenCode 2 needs
|
|
12
|
+
// What OpenCode 2's API needs:
|
|
15
13
|
// • HTTP Basic auth (user `opencode`, the launch's password) on every call;
|
|
16
|
-
// • the project folder as `location[directory]
|
|
14
|
+
// • the project folder as `location[directory]`;
|
|
17
15
|
// • a prompt carries no model, agent or system prompt: the session is switched
|
|
18
16
|
// to the model and agent first (only when they change), and a system prompt
|
|
19
17
|
// is the session's instruction entry `synabun-system`;
|
|
@@ -22,15 +20,18 @@
|
|
|
22
20
|
// `session.command` (a slash command only queues its prompt);
|
|
23
21
|
// • a permission or a question is answered under its session, which the
|
|
24
22
|
// event translator remembers (or the pending lists say).
|
|
25
|
-
// Things OpenCode 2 does not have answer
|
|
26
|
-
//
|
|
23
|
+
// Things OpenCode 2 does not have answer with an empty list (todos, LSP,
|
|
24
|
+
// formatters, symbols) or an error that says so (share).
|
|
27
25
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
26
|
|
|
29
27
|
import { basicAuthHeader } from './opencode-protocol.js';
|
|
28
|
+
import { opencodeMcpServerEntry } from './opencode-config.js';
|
|
30
29
|
import {
|
|
31
30
|
answersToForm,
|
|
32
31
|
createEventTranslator,
|
|
33
32
|
formToQuestionV1,
|
|
33
|
+
integrationEnvNames,
|
|
34
|
+
integrationsToAuthMethods,
|
|
34
35
|
messagesToV1,
|
|
35
36
|
modelRefToV2,
|
|
36
37
|
permissionToV1,
|
|
@@ -119,13 +120,15 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
119
120
|
|
|
120
121
|
/** `{ data }` with `data` mapped, errors passed through. */
|
|
121
122
|
const map = (result, fn) => (result.error ? result : { ...result, data: fn(result.data) });
|
|
123
|
+
/** The rows of an /api/integration answer (none when it failed: a provider list does not wait on it). */
|
|
124
|
+
const integrationRows = (result) => (result && !result.error && Array.isArray(result.data?.data) ? result.data.data : []);
|
|
122
125
|
const ok = (result, data) => (result.error ? result : { ...result, data });
|
|
123
126
|
|
|
124
127
|
// ── Sessions ──
|
|
125
128
|
|
|
126
129
|
const noteAll = (rows) => rows.map((info) => translator.noteSession(info));
|
|
127
130
|
|
|
128
|
-
async function listSessions({ directory, roots, search, limit, parentID } = {}) {
|
|
131
|
+
async function listSessions({ directory, roots, search, limit, parentID, archived } = {}) {
|
|
129
132
|
const max = Number(limit) > 0 ? Number(limit) : Infinity;
|
|
130
133
|
const out = [];
|
|
131
134
|
let cursor = null;
|
|
@@ -140,6 +143,8 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
140
143
|
limit: String(Math.min(PAGE_LIMIT, Number.isFinite(max) ? max - out.length : PAGE_LIMIT)),
|
|
141
144
|
order: 'desc',
|
|
142
145
|
...(parentID ? { parentID } : (roots === true || roots === 'true' ? { parentID: 'null' } : {})),
|
|
146
|
+
// Archived sessions only (OpenCode lists live ones by default).
|
|
147
|
+
...(archived === true ? { archived: 'true' } : {}),
|
|
143
148
|
};
|
|
144
149
|
last = await call('GET', '/api/session', { query });
|
|
145
150
|
if (last.error) return last;
|
|
@@ -452,26 +457,40 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
452
457
|
return out;
|
|
453
458
|
}
|
|
454
459
|
|
|
455
|
-
/**
|
|
460
|
+
/**
|
|
461
|
+
* The provider list SynaBun reads (`{ all, connected, defaults }`) from OpenCode 2's providers, enabled models,
|
|
462
|
+
* default model and integrations: every integration a provider can be connected through is in `all` (with the
|
|
463
|
+
* variables it reads its key from), the ones with models are `connected`.
|
|
464
|
+
*/
|
|
456
465
|
async function providerCatalog(directory) {
|
|
457
|
-
const [providers, models, fallback] = await Promise.all([
|
|
466
|
+
const [providers, models, fallback, integrations] = await Promise.all([
|
|
458
467
|
call('GET', '/api/provider', { query: located(directory) }),
|
|
459
468
|
call('GET', '/api/model', { query: located(directory) }),
|
|
460
469
|
call('GET', '/api/model/default', { query: located(directory) }),
|
|
470
|
+
call('GET', '/api/integration', { query: located(directory) }),
|
|
461
471
|
]);
|
|
462
472
|
if (providers.error) return { error: providers.error, response: providers.response };
|
|
463
473
|
if (models.error) return { error: models.error, response: models.response };
|
|
474
|
+
const envOf = new Map();
|
|
475
|
+
for (const integration of integrationRows(integrations)) {
|
|
476
|
+
envOf.set(str(integration.id), integrationEnvNames(integration));
|
|
477
|
+
}
|
|
464
478
|
const byProvider = new Map();
|
|
465
479
|
for (const provider of Array.isArray(providers.data?.data) ? providers.data.data : []) {
|
|
466
480
|
byProvider.set(provider.id, {
|
|
467
481
|
id: str(provider.id),
|
|
468
482
|
name: str(provider.name || provider.id),
|
|
469
483
|
source: provider.activation === 'enabled' ? 'config' : 'api',
|
|
470
|
-
env: [],
|
|
484
|
+
env: envOf.get(str(provider.integrationID || provider.id)) || [],
|
|
471
485
|
options: {},
|
|
472
486
|
models: {},
|
|
473
487
|
});
|
|
474
488
|
}
|
|
489
|
+
for (const integration of integrationRows(integrations)) {
|
|
490
|
+
const id = str(integration.id);
|
|
491
|
+
if (!id || byProvider.has(id)) continue;
|
|
492
|
+
byProvider.set(id, { id, name: str(integration.name || id), source: 'api', env: envOf.get(id) || [], options: {}, models: {} });
|
|
493
|
+
}
|
|
475
494
|
for (const model of Array.isArray(models.data?.data) ? models.data.data : []) {
|
|
476
495
|
if (!model?.id || !model.providerID || model.enabled === false) continue;
|
|
477
496
|
let provider = byProvider.get(model.providerID);
|
|
@@ -524,16 +543,24 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
524
543
|
},
|
|
525
544
|
get: ({ sessionID } = {}) => getSession(sessionID),
|
|
526
545
|
update: async ({ sessionID, title, permission, metadata, time } = {}) => {
|
|
527
|
-
// OpenCode 2's update takes a title, metadata and permissions: archiving is not in its API.
|
|
528
|
-
if (time && typeof time === 'object' && 'archived' in time) return notSupported('Archiving a session');
|
|
529
546
|
const body = {};
|
|
530
547
|
if (typeof title === 'string') body.title = title;
|
|
531
548
|
if (metadata && typeof metadata === 'object') body.metadata = metadata;
|
|
532
549
|
const rules = rulesToV2(permission);
|
|
533
550
|
if (rules) body.permissions = rules;
|
|
551
|
+
// Archiving: `archived: true | false` (OpenCode 1's `time.archived`, a time or 0 to bring a session back).
|
|
552
|
+
// 2.1.4 does it; 2.0.32 answers the same request 204 and keeps the session as it was, so the session is read
|
|
553
|
+
// back and an archive that did not happen is refused with a sentence, never a silent success.
|
|
554
|
+
const archive = time && typeof time === 'object' && 'archived' in time ? Boolean(Number(time.archived)) : null;
|
|
555
|
+
if (archive !== null) body.archived = archive;
|
|
534
556
|
const patched = await call('PATCH', `/api/session/${encodeURIComponent(sessionID)}`, { body });
|
|
535
557
|
if (patched.error) return patched;
|
|
536
|
-
|
|
558
|
+
const read = await getSession(sessionID);
|
|
559
|
+
if (archive !== null && !read.error && Boolean(read.data?.time?.archived) !== archive) {
|
|
560
|
+
const error = { _tag: 'NotSupportedError', message: `This OpenCode answered without ${archive ? 'archiving' : 'unarchiving'} the session: it needs a newer OpenCode 2 (run: opencode upgrade).` };
|
|
561
|
+
return { data: undefined, error, response: { status: 501, ok: false } };
|
|
562
|
+
}
|
|
563
|
+
return read;
|
|
537
564
|
},
|
|
538
565
|
delete: async ({ sessionID } = {}) => {
|
|
539
566
|
const removed = await call('DELETE', `/api/session/${encodeURIComponent(sessionID)}`);
|
|
@@ -573,8 +600,6 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
573
600
|
if (cleared.error) return cleared;
|
|
574
601
|
return getSession(sessionID);
|
|
575
602
|
},
|
|
576
|
-
share: async () => notSupported('Sharing a session'),
|
|
577
|
-
unshare: async () => notSupported('Sharing a session'),
|
|
578
603
|
summarize: async ({ sessionID } = {}) => ok(await call('POST', `/api/session/${encodeURIComponent(sessionID)}/compact`, { body: {} }), true),
|
|
579
604
|
init: async ({ sessionID } = {}) => ok(await call('POST', `/api/session/${encodeURIComponent(sessionID)}/command`, { body: { name: 'init', text: '' } }), true),
|
|
580
605
|
command: (p, o) => runCommand(p, o),
|
|
@@ -583,11 +608,9 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
583
608
|
if (failed) return failed;
|
|
584
609
|
return ok(await call('POST', `/api/session/${encodeURIComponent(sessionID)}/shell`, { body: { command: String(command || '') } }), { info: null, parts: [] });
|
|
585
610
|
},
|
|
586
|
-
deleteMessage: async () => notSupported('Deleting one message'),
|
|
587
611
|
};
|
|
588
612
|
|
|
589
613
|
const client = {
|
|
590
|
-
protocol: 2,
|
|
591
614
|
global: {
|
|
592
615
|
event: globalEvent,
|
|
593
616
|
health: async () => map(await call('GET', '/api/info'), (body) => ({ healthy: true, version: str(body?.version) })),
|
|
@@ -645,11 +668,8 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
645
668
|
connect: async ({ name, directory } = {}) => ok(await call('POST', `/api/experimental/mcp/${encodeURIComponent(name)}/connect`, { query: located(directory) }), true),
|
|
646
669
|
disconnect: async ({ name, directory } = {}) => ok(await call('POST', `/api/experimental/mcp/${encodeURIComponent(name)}/disconnect`, { query: located(directory) }), true),
|
|
647
670
|
add: async ({ name, config, directory } = {}) => {
|
|
648
|
-
|
|
649
|
-
const server =
|
|
650
|
-
? { type: 'remote', url: str(c.url), ...(c.headers ? { headers: obj(c.headers) } : {}), ...(c.enabled === false ? { disabled: true } : {}) }
|
|
651
|
-
: { type: 'local', command: Array.isArray(c.command) ? c.command.map(str) : [str(c.command), ...(Array.isArray(c.args) ? c.args.map(str) : [])].filter(Boolean), ...(c.environment || c.env ? { environment: obj(c.environment || c.env) } : {}), ...(c.enabled === false ? { disabled: true } : {}) };
|
|
652
|
-
if (Number(c.timeout) > 0) server.timeout = { startup: Number(c.timeout), catalog: Number(c.timeout), execution: Number(c.timeout) };
|
|
671
|
+
// OpenCode 2's MCP server entry, whatever SynaBun described (lib/opencode-config.js).
|
|
672
|
+
const server = opencodeMcpServerEntry(obj(config));
|
|
653
673
|
const added = await call('PUT', `/api/experimental/mcp/${encodeURIComponent(name)}`, { query: located(directory), body: { config: server } });
|
|
654
674
|
if (added.error) return added;
|
|
655
675
|
return client.mcp.status({ directory });
|
|
@@ -703,7 +723,29 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
703
723
|
if (catalog.error) return { data: undefined, error: catalog.error, response: catalog.response };
|
|
704
724
|
return { data: { all: catalog.all, default: catalog.defaults, connected: catalog.connected }, error: undefined, response: catalog.response };
|
|
705
725
|
},
|
|
706
|
-
|
|
726
|
+
// How each provider is connected (OpenCode 1's shape: { [id]: [{ type: 'api' | 'oauth', label, id }] }).
|
|
727
|
+
auth: async ({ directory } = {}) => map(await call('GET', '/api/integration', { query: located(directory) }), (body) => integrationsToAuthMethods(Array.isArray(body?.data) ? body.data : [])),
|
|
728
|
+
},
|
|
729
|
+
// OpenCode 2's integrations (how a provider is connected) and the credentials they stored. Secrets never come
|
|
730
|
+
// back from here: an integration's `connections` name a credential, never its value.
|
|
731
|
+
integration: {
|
|
732
|
+
list: async ({ directory } = {}) => map(await call('GET', '/api/integration', { query: located(directory) }), (body) => (Array.isArray(body?.data) ? body.data : [])),
|
|
733
|
+
connectKey: async ({ integrationID, key, label, answer, directory } = {}) => ok(await call('POST', `/api/integration/${encodeURIComponent(integrationID)}/connect/key`, {
|
|
734
|
+
query: located(directory),
|
|
735
|
+
body: { key: str(key), ...(label ? { label: str(label) } : {}), ...(answer && typeof answer === 'object' ? { answer } : {}) },
|
|
736
|
+
}), true),
|
|
737
|
+
connectOAuth: async ({ integrationID, methodID, answer, directory } = {}) => map(await call('POST', `/api/integration/${encodeURIComponent(integrationID)}/connect/oauth`, {
|
|
738
|
+
query: located(directory),
|
|
739
|
+
body: { methodID: str(methodID), ...(answer && typeof answer === 'object' ? { answer } : {}) },
|
|
740
|
+
}), (body) => obj(body?.data)),
|
|
741
|
+
oauthStatus: async ({ integrationID, attemptID, directory } = {}) => map(await call('GET', `/api/integration/${encodeURIComponent(integrationID)}/connect/oauth/${encodeURIComponent(attemptID)}`, { query: located(directory) }), (body) => obj(body?.data)),
|
|
742
|
+
oauthComplete: async ({ integrationID, attemptID, code, directory } = {}) => ok(await call('POST', `/api/integration/${encodeURIComponent(integrationID)}/connect/oauth/${encodeURIComponent(attemptID)}/complete`, {
|
|
743
|
+
query: located(directory),
|
|
744
|
+
body: { code: code == null ? null : str(code) },
|
|
745
|
+
}), true),
|
|
746
|
+
},
|
|
747
|
+
credential: {
|
|
748
|
+
remove: async ({ credentialID } = {}) => ok(await call('DELETE', `/api/credential/${encodeURIComponent(credentialID)}`), true),
|
|
707
749
|
},
|
|
708
750
|
find: {
|
|
709
751
|
files: async ({ query, directory, limit, type } = {}) => map(await call('GET', '/api/fs/find', { query: located(directory, { query: str(query), ...(type ? { type } : { type: 'file' }), ...(limit ? { limit: String(limit) } : {}) }) }), (body) => (Array.isArray(body?.data) ? body.data : []).map((entry) => str(entry?.path || entry?.name || entry))),
|
|
@@ -734,12 +776,6 @@ export function createOpencode2Client({ baseUrl, password, fetchImpl = globalThi
|
|
|
734
776
|
// default branch) its 'branch'. OpenCode 2 refuses a diff that names no mode.
|
|
735
777
|
diff: async ({ directory, mode } = {}) => map(await call('GET', '/api/vcs/diff', { query: located(directory, { mode: vcsModeToV2(mode) }) }), (body) => (Array.isArray(body?.data) ? body.data : []).map((row) => ({ file: str(row.file), patch: str(row.patch), additions: Number(row.additions) || 0, deletions: Number(row.deletions) || 0, status: row.status }))),
|
|
736
778
|
},
|
|
737
|
-
worktree: {
|
|
738
|
-
list: async ({ directory } = {}) => map(await call('GET', '/api/worktree', { query: located(directory) }), (body) => (Array.isArray(body?.data) ? body.data : []).map((row) => str(row?.directory || row))),
|
|
739
|
-
create: async () => notSupported('Creating a worktree from SynaBun'),
|
|
740
|
-
remove: async () => notSupported('Removing a worktree from SynaBun'),
|
|
741
|
-
reset: async () => notSupported('Resetting a worktree from SynaBun'),
|
|
742
|
-
},
|
|
743
779
|
lsp: { status: async () => ({ data: [], error: undefined, response: { status: 200, ok: true } }) },
|
|
744
780
|
formatter: { status: async () => ({ data: [], error: undefined, response: { status: 200, ok: true } }) },
|
|
745
781
|
path: {
|