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
|
@@ -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,18 +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
|
-
|
|
39
|
-
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';
|
|
40
37
|
|
|
41
38
|
// Types answered by the switch in server.js.
|
|
42
39
|
export const OPENCODE_V2_WS_INLINE_TYPES = Object.freeze([
|
|
43
40
|
'init', 'identify',
|
|
44
41
|
'session:list', 'session:create', 'session:get', 'session:update', 'session:delete', 'session:messages',
|
|
45
|
-
'mcp:
|
|
42
|
+
'mcp:tools:get', 'mcp:tools:set',
|
|
46
43
|
'message:send', 'message:abort',
|
|
47
44
|
'question:list', 'question:reject',
|
|
48
45
|
]);
|
|
@@ -70,6 +67,10 @@ const SESSION_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
|
70
67
|
*/
|
|
71
68
|
export function canonicalizeOpencodeV2Message(msg) {
|
|
72
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
|
+
}
|
|
73
74
|
const raw = msg.sessionId;
|
|
74
75
|
if (raw === undefined || raw === null) {
|
|
75
76
|
msg.sessionId = undefined;
|
|
@@ -133,18 +134,11 @@ function modelOf(value) {
|
|
|
133
134
|
return providerID && modelID ? { providerID, modelID } : null;
|
|
134
135
|
}
|
|
135
136
|
|
|
136
|
-
// session
|
|
137
|
+
// OpenCode compacts a session on the model it runs on.
|
|
137
138
|
async function compactSession(msg, deps) {
|
|
138
|
-
const client = await deps.turn(sessionKeyOf(msg), msg.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
sessionID: sessionIdOf(msg), directory: directoryOf(msg), model: modelOf(msg.model),
|
|
142
|
-
});
|
|
143
|
-
} catch (err) {
|
|
144
|
-
// "Pick a model first" is an answer for the user, not a server error.
|
|
145
|
-
if (err?.status === 400) return failure(400, err.message);
|
|
146
|
-
throw err;
|
|
147
|
-
}
|
|
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 };
|
|
148
142
|
}
|
|
149
143
|
|
|
150
144
|
const PERMISSION_REPLIES = new Set(['once', 'always', 'reject']);
|
|
@@ -229,45 +223,18 @@ async function sessionStatus(msg, deps) {
|
|
|
229
223
|
return { status: r.status, data: { status: statusForSession(r.data, sessionIdOf(msg)) } };
|
|
230
224
|
}
|
|
231
225
|
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
return !(data?.type === 'event' && data.eventType === 'sync');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Body of `POST /mcp` for a server SynaBun describes as { command, args, env }
|
|
240
|
-
// or { url, headers }. OpenCode takes McpLocalConfig (`type: 'local'`, the
|
|
241
|
-
// command as one array, `environment`) or McpRemoteConfig; `type: 'stdio'` with
|
|
242
|
-
// 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.
|
|
243
230
|
export function buildOpencodeRuntimeMcpConfig(config = {}) {
|
|
244
|
-
|
|
245
|
-
if (typeof config.url === 'string' && config.url) {
|
|
246
|
-
return {
|
|
247
|
-
type: 'remote',
|
|
248
|
-
url: config.url,
|
|
249
|
-
...(config.headers && typeof config.headers === 'object' ? { headers: config.headers } : {}),
|
|
250
|
-
enabled: config.enabled !== false,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
// Every word goes through as it is: an argument may be empty or carry
|
|
254
|
-
// spaces on purpose, and what is registered must be what was typed.
|
|
255
|
-
const head = Array.isArray(config.command) ? config.command : [config.command];
|
|
256
|
-
const command = [...head, ...(Array.isArray(config.args) ? config.args : [])]
|
|
257
|
-
.filter((part) => typeof part === 'string');
|
|
258
|
-
const environment = config.environment || config.env;
|
|
259
|
-
return {
|
|
260
|
-
type: 'local',
|
|
261
|
-
command,
|
|
262
|
-
...(environment && typeof environment === 'object' ? { environment } : {}),
|
|
263
|
-
enabled: config.enabled !== false,
|
|
264
|
-
};
|
|
231
|
+
return opencodeMcpServerEntry(config);
|
|
265
232
|
}
|
|
266
233
|
|
|
267
234
|
// ── Session list (read straight from OpenCode's SQLite) ─────────────────────
|
|
268
|
-
// The
|
|
269
|
-
// lists every project, so server.js reads
|
|
270
|
-
// 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.
|
|
271
238
|
export const SESSION_LIST_MAX = 500;
|
|
272
239
|
|
|
273
240
|
/**
|
|
@@ -278,6 +245,7 @@ export const SESSION_LIST_MAX = 500;
|
|
|
278
245
|
* Un-archiving writes time_archived = 0, so "live" is NULL or 0.
|
|
279
246
|
*/
|
|
280
247
|
export function buildSessionListQuery(options = {}) {
|
|
248
|
+
const tables = OPENCODE_SESSION_TABLES;
|
|
281
249
|
const where = [];
|
|
282
250
|
const params = [];
|
|
283
251
|
where.push(options.archived === true
|
|
@@ -293,10 +261,10 @@ export function buildSessionListQuery(options = {}) {
|
|
|
293
261
|
const requested = Number(options.limit);
|
|
294
262
|
const limit = Number.isInteger(requested) && requested > 0 ? Math.min(requested, SESSION_LIST_MAX) : null;
|
|
295
263
|
const sql = `
|
|
296
|
-
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,
|
|
297
265
|
s.time_created, s.time_updated, s.time_archived,
|
|
298
|
-
|
|
299
|
-
FROM session s
|
|
266
|
+
${tables.messageCount} AS message_count
|
|
267
|
+
FROM ${tables.session} s
|
|
300
268
|
WHERE ${where.join(' AND ')}
|
|
301
269
|
ORDER BY s.time_updated DESC${limit ? '\n LIMIT ?' : ''}
|
|
302
270
|
`;
|
|
@@ -317,20 +285,19 @@ export function mapSessionListRow(row) {
|
|
|
317
285
|
time: { created: epochMs(row.time_created), updated: epochMs(row.time_updated) },
|
|
318
286
|
};
|
|
319
287
|
if (row.parent_id) out.parentID = row.parent_id;
|
|
320
|
-
if (row.share_url) out.share = { url: row.share_url };
|
|
321
288
|
const archived = epochMs(row.time_archived);
|
|
322
289
|
if (archived) out.time.archived = archived;
|
|
323
290
|
return out;
|
|
324
291
|
}
|
|
325
292
|
|
|
326
|
-
// ── Session lifecycle (revert, fork,
|
|
293
|
+
// ── Session lifecycle (revert, fork, children) ──────────────────────────────
|
|
327
294
|
|
|
328
295
|
const messageIdOf = (msg) => (typeof msg?.messageID === 'string' && msg.messageID.trim()
|
|
329
296
|
? msg.messageID.trim()
|
|
330
297
|
: (typeof msg?.messageId === 'string' ? msg.messageId.trim() : ''));
|
|
331
298
|
|
|
332
|
-
// Reverting
|
|
333
|
-
//
|
|
299
|
+
// Reverting under a running turn would pull the transcript out from under the
|
|
300
|
+
// model.
|
|
334
301
|
function refuseWhileRunning(msg, deps, what) {
|
|
335
302
|
return deps.isTurnActive?.(sessionIdOf(msg))
|
|
336
303
|
? failure(409, `Stop the running turn before you ${what}.`)
|
|
@@ -368,48 +335,6 @@ async function sessionChildren(msg, deps) {
|
|
|
368
335
|
return { status: r.status, data: Array.isArray(r.data) ? r.data : [] };
|
|
369
336
|
}
|
|
370
337
|
|
|
371
|
-
async function messageDelete(msg, deps) {
|
|
372
|
-
const busy = refuseWhileRunning(msg, deps, 'delete a message');
|
|
373
|
-
if (busy) return busy;
|
|
374
|
-
const messageID = messageIdOf(msg);
|
|
375
|
-
if (!messageID) return failure(400, 'messageID is required');
|
|
376
|
-
const r = await deps.bound(sessionKeyOf(msg)).extra.session.deleteMessage({
|
|
377
|
-
sessionID: sessionIdOf(msg), messageID, directory: directoryOf(msg),
|
|
378
|
-
});
|
|
379
|
-
return { status: r.status, data: r.data };
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// OpenCode's `share` setting: manual (default), auto, or disabled.
|
|
383
|
-
export function sharePolicyOf(config) {
|
|
384
|
-
const value = config?.share;
|
|
385
|
-
if (value === 'disabled' || value === 'auto' || value === 'manual') return value;
|
|
386
|
-
return 'manual';
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
async function readSharePolicy(msg, deps) {
|
|
390
|
-
const r = await deps.shared.extra.config.get({ directory: directoryOf(msg) });
|
|
391
|
-
return sharePolicyOf(r.data);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async function sessionSharePolicy(msg, deps) {
|
|
395
|
-
return { status: 200, data: { share: await readSharePolicy(msg, deps) } };
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Publishes the transcript at a public opencode URL. The panel confirms with
|
|
399
|
-
// the user every time; the server refuses when the config forbids sharing.
|
|
400
|
-
async function sessionShare(msg, deps) {
|
|
401
|
-
if (await readSharePolicy(msg, deps) === 'disabled') {
|
|
402
|
-
return failure(403, 'Sharing is disabled in the OpenCode config.');
|
|
403
|
-
}
|
|
404
|
-
const r = await deps.shared.extra.session.share({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
405
|
-
return { status: r.status, data: r.data };
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
async function sessionUnshare(msg, deps) {
|
|
409
|
-
const r = await deps.shared.extra.session.unshare({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
410
|
-
return { status: r.status, data: r.data };
|
|
411
|
-
}
|
|
412
|
-
|
|
413
338
|
// ── Composer: slash commands, shell, file search ────────────────────────────
|
|
414
339
|
|
|
415
340
|
/** What the slash menu needs of a Command; the template can be 16 KB and is not sent. */
|
|
@@ -438,10 +363,12 @@ function modelRef(value) {
|
|
|
438
363
|
|
|
439
364
|
// Run something that occupies the session like a prompt does: on the
|
|
440
365
|
// session's dedicated serve, inside the same turn bookkeeping as message:send.
|
|
441
|
-
async function withTurn(msg, deps, run) {
|
|
366
|
+
async function withTurn(msg, deps, run, { needsMcp = true } = {}) {
|
|
442
367
|
const scope = deps.turnScope(sessionIdOf(msg));
|
|
443
368
|
try {
|
|
444
|
-
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 });
|
|
445
372
|
const r = await run(client, scope.signal ? { signal: scope.signal } : undefined);
|
|
446
373
|
return { status: r.status, data: r.data };
|
|
447
374
|
} finally {
|
|
@@ -479,7 +406,7 @@ async function sessionShell(msg, deps) {
|
|
|
479
406
|
agent: typeof msg.agent === 'string' && msg.agent ? msg.agent : 'build',
|
|
480
407
|
model: modelOf(msg.model) || undefined,
|
|
481
408
|
directory: directoryOf(msg),
|
|
482
|
-
}, options));
|
|
409
|
+
}, options), { needsMcp: false });
|
|
483
410
|
}
|
|
484
411
|
|
|
485
412
|
export const FIND_FILES_LIMIT = 50;
|
|
@@ -647,55 +574,6 @@ async function vcsDiff(msg, deps) {
|
|
|
647
574
|
return { status: r.status, data: capFileDiffs(r.data) };
|
|
648
575
|
}
|
|
649
576
|
|
|
650
|
-
// ── Worktrees ───────────────────────────────────────────────────────────────
|
|
651
|
-
|
|
652
|
-
// worktree.create answers a Worktree { name, branch, directory }; worktree.list
|
|
653
|
-
// answers the directories only (confirmed on 1.18.34).
|
|
654
|
-
function worktreeRow(w) {
|
|
655
|
-
const directory = typeof w === 'string' ? w : (w && typeof w.directory === 'string' ? w.directory : '');
|
|
656
|
-
if (!directory) return null;
|
|
657
|
-
const leaf = directory.split(/[\\/]/).filter(Boolean).pop() || directory;
|
|
658
|
-
return {
|
|
659
|
-
name: typeof w === 'object' && w.name ? String(w.name) : leaf,
|
|
660
|
-
branch: typeof w === 'object' && typeof w.branch === 'string' ? w.branch : '',
|
|
661
|
-
directory,
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
async function worktreeList(msg, deps) {
|
|
666
|
-
if (!directoryOf(msg)) return failure(400, 'cwd is required');
|
|
667
|
-
const r = await deps.shared.extra.worktree.list({ directory: directoryOf(msg) });
|
|
668
|
-
return { status: r.status, data: (Array.isArray(r.data) ? r.data : []).map(worktreeRow).filter(Boolean) };
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
async function worktreeCreate(msg, deps) {
|
|
672
|
-
if (!directoryOf(msg)) return failure(400, 'cwd is required');
|
|
673
|
-
const name = typeof msg.name === 'string' ? msg.name.trim() : '';
|
|
674
|
-
if (name && !/^[A-Za-z0-9][\w.-]{0,63}$/.test(name)) {
|
|
675
|
-
return failure(400, 'A worktree name may use letters, digits, ".", "_" and "-".');
|
|
676
|
-
}
|
|
677
|
-
const r = await deps.shared.extra.worktree.create({
|
|
678
|
-
directory: directoryOf(msg),
|
|
679
|
-
worktreeCreateInput: name ? { name } : {},
|
|
680
|
-
});
|
|
681
|
-
const row = worktreeRow(r.data);
|
|
682
|
-
if (!row) return failure(502, 'OpenCode did not return the new worktree.');
|
|
683
|
-
return { status: r.status, data: row };
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// Removing deletes a directory, so only one OpenCode itself lists as a worktree
|
|
687
|
-
// of this project is accepted.
|
|
688
|
-
async function worktreeRemove(msg, deps) {
|
|
689
|
-
const cwd = directoryOf(msg);
|
|
690
|
-
const target = typeof msg.directory === 'string' ? msg.directory.trim() : '';
|
|
691
|
-
if (!cwd || !target) return failure(400, 'cwd and directory are required');
|
|
692
|
-
const listed = await deps.shared.extra.worktree.list({ directory: cwd });
|
|
693
|
-
const known = (Array.isArray(listed.data) ? listed.data : []).some((w) => worktreeRow(w)?.directory === target);
|
|
694
|
-
if (!known) return failure(404, 'That directory is not a worktree of this project.');
|
|
695
|
-
const r = await deps.shared.extra.worktree.remove({ directory: cwd, worktreeRemoveInput: { directory: target } });
|
|
696
|
-
return { status: r.status, data: true };
|
|
697
|
-
}
|
|
698
|
-
|
|
699
577
|
// ── Environment: MCP servers, LSP, formatters ───────────────────────────────
|
|
700
578
|
|
|
701
579
|
// SynaBun's own MCP entry is pinned by the runtime (profile, terminal identity,
|
|
@@ -740,19 +618,6 @@ async function mcpSwitch(msg, deps, connect) {
|
|
|
740
618
|
return { status: r.status, data: after ? mcpRows(after.data) : [] };
|
|
741
619
|
}
|
|
742
620
|
|
|
743
|
-
// OAuth for a remote MCP server: OpenCode opens the browser itself and waits
|
|
744
|
-
// for the callback, so the request can take minutes.
|
|
745
|
-
async function mcpAuthenticate(msg, deps) {
|
|
746
|
-
const name = mcpNameOf(msg);
|
|
747
|
-
if (!name) return failure(400, 'MCP server name is required');
|
|
748
|
-
if (isManagedMcpName(name)) return failure(403, `${name} is managed by SynaBun.`);
|
|
749
|
-
const path = `/mcp/${encodeURIComponent(name)}/auth/authenticate${deps.directoryQuery(msg.cwd)}`;
|
|
750
|
-
const r = await deps.proxy('POST', path, {}, 5 * 60 * 1000, deps.baseUrlFor(sessionKeyOf(msg)));
|
|
751
|
-
if (r.status >= 400 || typeof r.data === 'string') {
|
|
752
|
-
return failure(r.status >= 400 ? r.status : 502, proxyErrorText(r.data, 'Authentication did not complete'));
|
|
753
|
-
}
|
|
754
|
-
return { status: r.status, data: r.data };
|
|
755
|
-
}
|
|
756
621
|
|
|
757
622
|
const MCP_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
758
623
|
const stringMap = (value) => value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -860,10 +725,6 @@ const HANDLERS = {
|
|
|
860
725
|
'session:unrevert': { session: true, mutates: true, run: sessionUnrevert },
|
|
861
726
|
'session:fork': { session: true, mutates: true, run: sessionFork },
|
|
862
727
|
'session:children': { session: true, run: sessionChildren },
|
|
863
|
-
'session:share': { session: true, mutates: true, run: sessionShare },
|
|
864
|
-
'session:unshare': { session: true, mutates: true, run: sessionUnshare },
|
|
865
|
-
'session:share:policy': { run: sessionSharePolicy },
|
|
866
|
-
'message:delete': { session: true, mutates: true, run: messageDelete },
|
|
867
728
|
'command:list': { run: commandList },
|
|
868
729
|
'command:run': { session: true, mutates: true, run: commandRun },
|
|
869
730
|
'session:shell': { session: true, mutates: true, run: sessionShell },
|
|
@@ -876,13 +737,9 @@ const HANDLERS = {
|
|
|
876
737
|
'vcs:get': { run: vcsGet },
|
|
877
738
|
'vcs:status': { run: vcsStatus },
|
|
878
739
|
'vcs:diff': { run: vcsDiff },
|
|
879
|
-
'worktree:list': { run: worktreeList },
|
|
880
|
-
'worktree:create': { run: worktreeCreate },
|
|
881
|
-
'worktree:remove': { run: worktreeRemove },
|
|
882
740
|
'mcp:status': { run: mcpStatus },
|
|
883
741
|
'mcp:connect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, true) },
|
|
884
742
|
'mcp:disconnect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, false) },
|
|
885
|
-
'mcp:authenticate': { session: true, mutates: true, run: mcpAuthenticate },
|
|
886
743
|
'mcp:add': { session: true, mutates: true, run: mcpAdd },
|
|
887
744
|
'env:status': { run: envStatus },
|
|
888
745
|
};
|
|
@@ -898,29 +755,12 @@ export const OPENCODE_V2_WS_MODULE_TYPES = Object.freeze(Object.keys(HANDLERS));
|
|
|
898
755
|
// Behaviours of an existing type that an older server lacks. Listed next to
|
|
899
756
|
// the types so the panel can gate on them the same way; never a request type.
|
|
900
757
|
export const OPENCODE_V2_WS_FEATURES = Object.freeze([
|
|
758
|
+
'feature:tool-lists',
|
|
901
759
|
'feature:permission-reply-message', // permission:reply forwards a rejection reason
|
|
902
|
-
'feature:compact-summarize', // session:compact falls back to session.summarize
|
|
903
760
|
'feature:session-list-filters', // session:list takes search / archived / roots / limit, rows carry parentID
|
|
904
761
|
'feature:mcp-add-persist', // mcp:add with persist:true saves the server without starting it a second time
|
|
905
762
|
]);
|
|
906
763
|
|
|
907
|
-
// The version of the @opencode-ai/sdk this server talks to OpenCode through,
|
|
908
|
-
// for the panel's Versions rows ('' when its package.json cannot be read).
|
|
909
|
-
let _sdkVersion;
|
|
910
|
-
export function opencodeSdkVersion() {
|
|
911
|
-
if (_sdkVersion !== undefined) return _sdkVersion;
|
|
912
|
-
_sdkVersion = '';
|
|
913
|
-
try {
|
|
914
|
-
let dir = dirname(fileURLToPath(import.meta.resolve('@opencode-ai/sdk/v2')));
|
|
915
|
-
for (let i = 0; i < 6 && dir !== dirname(dir); i += 1, dir = dirname(dir)) {
|
|
916
|
-
let pkg = null;
|
|
917
|
-
try { pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); } catch { /* not the package root */ }
|
|
918
|
-
if (pkg?.name === '@opencode-ai/sdk') { _sdkVersion = String(pkg.version || ''); break; }
|
|
919
|
-
}
|
|
920
|
-
} catch { /* stays '' */ }
|
|
921
|
-
return _sdkVersion;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
764
|
// Everything this server answers, for the panel's feature gating.
|
|
925
765
|
export function opencodeV2WsCapabilities() {
|
|
926
766
|
return [...OPENCODE_V2_WS_INLINE_TYPES, ...OPENCODE_V2_WS_MODULE_TYPES, ...OPENCODE_V2_WS_FEATURES];
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the Assistant page sees of a dispatched OpenCode worker: its tool calls.
|
|
3
|
+
*
|
|
4
|
+
* Claude and Codex workers reach the page through the sync socket
|
|
5
|
+
* (sidepanel:provider-event); an OpenCode worker's events stay on its own
|
|
6
|
+
* isolated `opencode serve`, which only its V2 panel reads, so server.js keeps
|
|
7
|
+
* them off the socket. The Assistant's run stage and agents tray
|
|
8
|
+
* (public/shared/assistant/asst-scenes.js activityOf) only need to know which
|
|
9
|
+
* call the worker is on, so this relay forwards a copy of each tool call's
|
|
10
|
+
* start (its part turns `running`) and finish (`completed` or `error`), once
|
|
11
|
+
* each, in the real event shape: { provider: 'opencode', runId, eventType:
|
|
12
|
+
* 'message.part.updated', event: { sessionID, part: { type: 'tool', tool,
|
|
13
|
+
* callID, state: { status, input } } } }. Nothing else goes: no text,
|
|
14
|
+
* reasoning or file parts, no output, title, metadata or error text, and of
|
|
15
|
+
* the call's input only the short fields a step line names ("Editing
|
|
16
|
+
* router.js", "Running npm test", "Opening localhost:3344"), made safe
|
|
17
|
+
* (public/shared/assistant/asst-redact.js: credentials masked, a command's
|
|
18
|
+
* heredoc and inline file bodies omitted, an address without its query) and
|
|
19
|
+
* then clipped; a file tool's path only; never an edit's text, a written file
|
|
20
|
+
* or a typed value.
|
|
21
|
+
*
|
|
22
|
+
* Bounded: at most one event per run every `minIntervalMs`; a call seen inside
|
|
23
|
+
* the window waits for its end, the newest replacing the one before (so the
|
|
24
|
+
* page always learns the latest call), and a run's state goes with its end.
|
|
25
|
+
* Calls overlap (OpenCode runs tools in parallel): the end of a call older than
|
|
26
|
+
* one still running is no news to the page and is never sent, so it can never
|
|
27
|
+
* replace or follow the newer call's start, in the window or after it.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { redactSecrets, safeCommand, safeUrl } from '../public/shared/assistant/asst-redact.js';
|
|
31
|
+
|
|
32
|
+
export const OPENCODE_ACTIVITY_MIN_MS = 250;
|
|
33
|
+
const MAX_CALLS_PER_RUN = 256; // callIDs remembered per run (start / finish seen)
|
|
34
|
+
const MAX_RUNS = 64; // runs tracked at once (each forgotten at its end)
|
|
35
|
+
const FIELD_MAX = 300; // characters of an input field
|
|
36
|
+
const PLAN_ITEMS = 20; // todowrite items forwarded
|
|
37
|
+
const PLAN_ITEM_MAX = 120;
|
|
38
|
+
|
|
39
|
+
const str = (v) => (v == null ? '' : String(v));
|
|
40
|
+
const clip = (v, max = FIELD_MAX) => {
|
|
41
|
+
const s = str(v).replace(/\s+/g, ' ').trim();
|
|
42
|
+
return s.length > max ? `${s.slice(0, max - 1).trimEnd()}…` : s;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Input fields a step line reads (asst-tool-kinds.js sayCall), whatever the tool. */
|
|
46
|
+
const STEP_FIELDS = Object.freeze([
|
|
47
|
+
'command', 'cmd', // a shell command
|
|
48
|
+
'filePath', 'file_path', 'path', 'notebook_path', // a file, a folder
|
|
49
|
+
'pattern', 'query', 'q', 'include', 'glob', // a search
|
|
50
|
+
'url', 'href', // a page
|
|
51
|
+
'element', 'label', 'name', 'target', 'selector', 'ref', 'key', 'keys', // a browser control, a key, never what is typed into it
|
|
52
|
+
'subagent_type', 'agent', 'action', // a sub-agent, a desktop or memory action
|
|
53
|
+
]);
|
|
54
|
+
const STEP_NUMBERS = Object.freeze(['offset', 'limit']);
|
|
55
|
+
/** Fields that are a step only for some tools: a click's visible text, a sub-agent's one-line description. */
|
|
56
|
+
const TOOL_FIELDS = Object.freeze([
|
|
57
|
+
[/(^|_)browser_(click|hover)$/i, ['text']],
|
|
58
|
+
[/^task$/i, ['description']],
|
|
59
|
+
]);
|
|
60
|
+
/** File tools: their step is the file, so the path is all that goes (a read keeps its line range). */
|
|
61
|
+
const FILE_TOOLS = /^(?:read|edit|write|patch|multiedit|notebook_?(?:read|edit))$/i;
|
|
62
|
+
const PATH_FIELDS = Object.freeze(['filePath', 'file_path', 'path', 'notebook_path']);
|
|
63
|
+
const COMMAND_FIELDS = new Set(['command', 'cmd']);
|
|
64
|
+
const URL_FIELDS = new Set(['url', 'href']);
|
|
65
|
+
|
|
66
|
+
/** A field as its step line may say it: a command and an address made safe, anything else masked, then clipped. */
|
|
67
|
+
function safeField(key, value) {
|
|
68
|
+
const text = COMMAND_FIELDS.has(key) ? safeCommand(value) : URL_FIELDS.has(key) ? safeUrl(value) : redactSecrets(value);
|
|
69
|
+
return clip(text);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The part of a tool call's input its step line needs: a command with its credentials masked and its heredoc or
|
|
74
|
+
* inline file bodies left out, an address as scheme://host/path, a file tool's path only; every field masked
|
|
75
|
+
* (asst-redact.js) before it is clipped. Never an edit's text, a file's content or a typed value.
|
|
76
|
+
*/
|
|
77
|
+
export function stepInput(tool, input) {
|
|
78
|
+
const i = input && typeof input === 'object' && !Array.isArray(input) ? input : {};
|
|
79
|
+
const out = {};
|
|
80
|
+
const file = FILE_TOOLS.test(str(tool));
|
|
81
|
+
const fields = file ? [...PATH_FIELDS] : [...STEP_FIELDS];
|
|
82
|
+
if (!file) for (const [re, extra] of TOOL_FIELDS) if (re.test(str(tool))) fields.push(...extra);
|
|
83
|
+
for (const key of fields) {
|
|
84
|
+
const value = i[key];
|
|
85
|
+
if (typeof value === 'string' && value.trim()) out[key] = safeField(key, value);
|
|
86
|
+
else if (Array.isArray(value) && value.every((v) => typeof v === 'string')) {
|
|
87
|
+
const joined = safeField(key, value.join(' '));
|
|
88
|
+
if (joined) out[key] = joined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (file && !/^read$/i.test(str(tool))) return out;
|
|
92
|
+
for (const key of STEP_NUMBERS) if (Number.isFinite(i[key])) out[key] = i[key];
|
|
93
|
+
if (file) return out;
|
|
94
|
+
// A plan: its items' words and states (planState's current step), never more than a short list.
|
|
95
|
+
if (Array.isArray(i.todos)) {
|
|
96
|
+
out.todos = i.todos.filter((x) => x && typeof x === 'object').slice(0, PLAN_ITEMS)
|
|
97
|
+
.map((x) => ({ content: clip(redactSecrets(x.content ?? x.text), PLAN_ITEM_MAX), status: clip(x.status, 24) }));
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* One OpenCode provider event ({ provider, runId, eventType, event }, the
|
|
104
|
+
* adapter's onEvent payload) as a tool call's start or finish, or null for
|
|
105
|
+
* anything else (text, reasoning, files, a sub-agent's session, other events).
|
|
106
|
+
* → { callID, phase: 'start' | 'finish', payload } with `payload` the compact
|
|
107
|
+
* copy the page gets.
|
|
108
|
+
*/
|
|
109
|
+
export function openCodeToolCall(payload) {
|
|
110
|
+
if (!payload || payload.provider !== 'opencode' || payload.childSession) return null;
|
|
111
|
+
if (!/^message[.:]part[.:]updated$/i.test(str(payload.eventType))) return null;
|
|
112
|
+
const event = payload.event && typeof payload.event === 'object' ? payload.event : {};
|
|
113
|
+
const part = event.part && typeof event.part === 'object' ? event.part : null;
|
|
114
|
+
if (!part || part.type !== 'tool' || !str(part.tool).trim()) return null;
|
|
115
|
+
const status = str(part.state?.status);
|
|
116
|
+
const phase = status === 'running' ? 'start' : status === 'completed' || status === 'error' ? 'finish' : null;
|
|
117
|
+
if (!phase) return null; // pending: its input is still streaming
|
|
118
|
+
const tool = clip(part.tool, 160);
|
|
119
|
+
const callID = str(part.callID || part.id);
|
|
120
|
+
const sessionID = str(event.sessionID || part.sessionID) || undefined;
|
|
121
|
+
return {
|
|
122
|
+
callID,
|
|
123
|
+
phase,
|
|
124
|
+
payload: {
|
|
125
|
+
provider: 'opencode',
|
|
126
|
+
runId: payload.runId,
|
|
127
|
+
eventType: 'message.part.updated',
|
|
128
|
+
event: {
|
|
129
|
+
sessionID,
|
|
130
|
+
part: { id: str(part.id) || undefined, sessionID, messageID: str(part.messageID) || undefined, type: 'tool', callID, tool, state: { status, input: stepInput(tool, part.state?.input) } },
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const TERMINAL = new Set(['sidepanel:run-completed', 'sidepanel:run-failed', 'sidepanel:run-stopped']);
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* createOpenCodeActivityRelay({ send, minIntervalMs, now, setTimer, clearTimer })
|
|
140
|
+
* observe(message) takes every NativeLoopRuntime message (onEvent): it returns
|
|
141
|
+
* true for an OpenCode provider event, which it never passes on as it is
|
|
142
|
+
* (its tool calls go to send() as compact copies, at the bounded rate), and
|
|
143
|
+
* false for everything else, which the caller sends as before.
|
|
144
|
+
*/
|
|
145
|
+
export function createOpenCodeActivityRelay({
|
|
146
|
+
send,
|
|
147
|
+
minIntervalMs = OPENCODE_ACTIVITY_MIN_MS,
|
|
148
|
+
now = () => Date.now(),
|
|
149
|
+
setTimer = (fn, ms) => { const timer = setTimeout(fn, ms); timer.unref?.(); return timer; },
|
|
150
|
+
clearTimer = (timer) => clearTimeout(timer),
|
|
151
|
+
} = {}) {
|
|
152
|
+
const runs = new Map(); // runId → { calls: Map(callID → { phase, seq }), seq, last, pending, timer }
|
|
153
|
+
|
|
154
|
+
function forget(runId) {
|
|
155
|
+
const state = runs.get(runId);
|
|
156
|
+
if (!state) return;
|
|
157
|
+
if (state.timer) clearTimer(state.timer);
|
|
158
|
+
runs.delete(runId);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function stateOf(runId) {
|
|
162
|
+
let state = runs.get(runId);
|
|
163
|
+
if (!state) {
|
|
164
|
+
while (runs.size >= MAX_RUNS) forget(runs.keys().next().value);
|
|
165
|
+
state = { calls: new Map(), seq: 0, last: -Infinity, pending: null, timer: null };
|
|
166
|
+
runs.set(runId, state);
|
|
167
|
+
}
|
|
168
|
+
return state;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** A call that started after the one `seq` names is still running. */
|
|
172
|
+
function newerRunning(state, callID, seq) {
|
|
173
|
+
for (const [id, c] of state.calls) if (id !== callID && c.phase === 'start' && c.seq > seq) return true;
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function emit(state, message) {
|
|
178
|
+
state.last = now();
|
|
179
|
+
try { send(message); } catch { /* the socket is gone */ }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function flush(runId) {
|
|
183
|
+
const state = runs.get(runId);
|
|
184
|
+
if (!state) return;
|
|
185
|
+
state.timer = null;
|
|
186
|
+
const message = state.pending;
|
|
187
|
+
state.pending = null;
|
|
188
|
+
if (message) emit(state, message);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function observe(message) {
|
|
192
|
+
const type = str(message?.type);
|
|
193
|
+
if (TERMINAL.has(type)) {
|
|
194
|
+
const runId = message.run?.runId || message.runId;
|
|
195
|
+
if (runId) forget(runId);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (type !== 'sidepanel:provider-event' || message.event?.provider !== 'opencode') return false;
|
|
199
|
+
const call = openCodeToolCall(message.event);
|
|
200
|
+
const runId = str(message.run?.runId || message.event?.runId);
|
|
201
|
+
if (!call || !runId) return true;
|
|
202
|
+
const state = stateOf(runId);
|
|
203
|
+
// Once per call and phase (OpenCode updates a running part many times); a start after its finish is old news.
|
|
204
|
+
const seen = state.calls.get(call.callID);
|
|
205
|
+
if (call.callID && (seen?.phase === call.phase || seen?.phase === 'finish')) return true;
|
|
206
|
+
const seq = seen?.seq ?? ++state.seq; // the order calls started in (a call first seen at its end starts now)
|
|
207
|
+
if (call.callID) {
|
|
208
|
+
state.calls.delete(call.callID);
|
|
209
|
+
state.calls.set(call.callID, { phase: call.phase, seq });
|
|
210
|
+
while (state.calls.size > MAX_CALLS_PER_RUN) state.calls.delete(state.calls.keys().next().value);
|
|
211
|
+
}
|
|
212
|
+
// An older call's end, while a newer call runs: the page shows the newer one, and keeps it.
|
|
213
|
+
if (call.phase === 'finish' && newerRunning(state, call.callID, seq)) return true;
|
|
214
|
+
const out = { type: 'sidepanel:provider-event', run: message.run, event: call.payload };
|
|
215
|
+
const wait = state.last + minIntervalMs - now();
|
|
216
|
+
if (wait <= 0 && !state.timer) { emit(state, out); return true; }
|
|
217
|
+
state.pending = out; // the newest call the window held back
|
|
218
|
+
if (!state.timer) state.timer = setTimer(() => flush(runId), Math.max(0, wait));
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
observe,
|
|
224
|
+
/** Runs with state (tests and devtools). */
|
|
225
|
+
size: () => runs.size,
|
|
226
|
+
/** Drop every run's state and timer (shutdown). */
|
|
227
|
+
clear() { for (const runId of [...runs.keys()]) forget(runId); },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -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
|
+
}
|