synabun 1.3.0 → 2.0.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 +205 -662
- package/LICENSE-COMMERCIAL.md +33 -0
- package/NOTICE +17 -0
- package/README.md +175 -853
- package/THIRD-PARTY-LICENSES.md +136 -0
- package/benchmarks/browser-live-results.json +79 -0
- package/benchmarks/browser-v2-results.json +258 -0
- package/benchmarks/fixtures/browser/README.md +57 -0
- package/benchmarks/fixtures/browser/page-state.json +132 -0
- package/benchmarks/fixtures/browser/social.json +92 -0
- package/benchmarks/fixtures/browser/target.json +319 -0
- package/benchmarks/fixtures/desktop/README.md +58 -0
- package/benchmarks/fixtures/desktop/abstention.json +59 -0
- package/benchmarks/fixtures/desktop/adversarial.json +22 -0
- package/benchmarks/fixtures/desktop/forbidden.json +93 -0
- package/benchmarks/fixtures/desktop/generate.mjs +1023 -0
- package/benchmarks/fixtures/desktop/target.json +136 -0
- package/bin/synabun.js +30 -0
- package/docs/whatsapp.md +325 -0
- package/hooks/claude-code/post-plan.mjs +613 -391
- package/hooks/claude-code/post-remember.mjs +246 -122
- package/hooks/claude-code/pre-compact.mjs +171 -110
- package/hooks/claude-code/pre-task.mjs +133 -0
- package/hooks/claude-code/pre-websearch.mjs +15 -4
- package/hooks/claude-code/prompt-origin.mjs +94 -0
- package/hooks/claude-code/prompt-submit.mjs +1244 -861
- package/hooks/claude-code/session-start.mjs +114 -156
- package/hooks/claude-code/shared.mjs +1228 -368
- package/hooks/claude-code/state.mjs +167 -0
- package/hooks/claude-code/stop.mjs +515 -140
- package/hooks/claude-code/subagent-start.mjs +154 -0
- package/hooks/claude-code/subagent-stop.mjs +102 -0
- package/hooks/claude-code/task-gate.mjs +150 -0
- package/launcher.mjs +40 -0
- package/lib/claude-hooks.js +137 -0
- package/lib/claude-usage-audit.js +141 -0
- package/lib/client-config-repair.js +145 -0
- package/lib/data-home-migration.js +502 -0
- package/lib/desktop-pwa.js +206 -0
- package/lib/external-tools.js +221 -0
- package/lib/first-launch-protection.js +245 -0
- package/lib/packaged-runtime.js +110 -0
- package/lib/paths.d.ts +21 -0
- package/lib/paths.js +103 -0
- package/lib/start-launcher.js +1309 -0
- package/mcp-server/dist/config.d.ts +22 -0
- package/mcp-server/dist/config.d.ts.map +1 -0
- package/mcp-server/dist/config.js +109 -0
- package/mcp-server/dist/config.js.map +1 -0
- package/mcp-server/dist/http.d.ts +30 -0
- package/mcp-server/dist/http.d.ts.map +1 -0
- package/mcp-server/dist/http.js +276 -0
- package/mcp-server/dist/http.js.map +1 -0
- package/mcp-server/dist/index.d.ts +48 -0
- package/mcp-server/dist/index.d.ts.map +1 -0
- package/mcp-server/dist/index.js +538 -0
- package/mcp-server/dist/index.js.map +1 -0
- package/mcp-server/dist/preload-http.d.ts +3 -0
- package/mcp-server/dist/preload-http.d.ts.map +1 -0
- package/mcp-server/dist/preload-http.js +28 -0
- package/mcp-server/dist/preload-http.js.map +1 -0
- package/mcp-server/dist/preload.d.ts +3 -0
- package/mcp-server/dist/preload.d.ts.map +1 -0
- package/mcp-server/dist/preload.js +32 -0
- package/mcp-server/dist/preload.js.map +1 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts +19 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts.map +1 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js +403 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js.map +1 -0
- package/mcp-server/dist/scripts/setup-embeddings.d.ts +3 -0
- package/mcp-server/dist/scripts/setup-embeddings.d.ts.map +1 -0
- package/mcp-server/dist/scripts/setup-embeddings.js +15 -0
- package/mcp-server/dist/scripts/setup-embeddings.js.map +1 -0
- package/mcp-server/dist/services/assistant-judgments.d.ts +79 -0
- package/mcp-server/dist/services/assistant-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/assistant-judgments.js +128 -0
- package/mcp-server/dist/services/assistant-judgments.js.map +1 -0
- package/mcp-server/dist/services/browser-assist-gate.d.ts +314 -0
- package/mcp-server/dist/services/browser-assist-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-assist-gate.js +344 -0
- package/mcp-server/dist/services/browser-assist-gate.js.map +1 -0
- package/mcp-server/dist/services/browser-assist.d.ts +104 -0
- package/mcp-server/dist/services/browser-assist.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-assist.js +282 -0
- package/mcp-server/dist/services/browser-assist.js.map +1 -0
- package/mcp-server/dist/services/browser-bench.d.ts +772 -0
- package/mcp-server/dist/services/browser-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-bench.js +424 -0
- package/mcp-server/dist/services/browser-bench.js.map +1 -0
- package/mcp-server/dist/services/browser-judgments.d.ts +196 -0
- package/mcp-server/dist/services/browser-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-judgments.js +363 -0
- package/mcp-server/dist/services/browser-judgments.js.map +1 -0
- package/mcp-server/dist/services/browser-risk.d.ts +166 -0
- package/mcp-server/dist/services/browser-risk.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-risk.js +458 -0
- package/mcp-server/dist/services/browser-risk.js.map +1 -0
- package/mcp-server/dist/services/categories.d.ts +61 -0
- package/mcp-server/dist/services/categories.d.ts.map +1 -0
- package/mcp-server/dist/services/categories.js +377 -0
- package/mcp-server/dist/services/categories.js.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts +49 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.js +346 -0
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -0
- package/mcp-server/dist/services/desktop-assist-gate.d.ts +198 -0
- package/mcp-server/dist/services/desktop-assist-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-assist-gate.js +202 -0
- package/mcp-server/dist/services/desktop-assist-gate.js.map +1 -0
- package/mcp-server/dist/services/desktop-assist.d.ts +104 -0
- package/mcp-server/dist/services/desktop-assist.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-assist.js +266 -0
- package/mcp-server/dist/services/desktop-assist.js.map +1 -0
- package/mcp-server/dist/services/desktop-bench.d.ts +553 -0
- package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-bench.js +311 -0
- package/mcp-server/dist/services/desktop-bench.js.map +1 -0
- package/mcp-server/dist/services/desktop-client.d.ts +23 -0
- package/mcp-server/dist/services/desktop-client.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-client.js +79 -0
- package/mcp-server/dist/services/desktop-client.js.map +1 -0
- package/mcp-server/dist/services/desktop-judgments.d.ts +125 -0
- package/mcp-server/dist/services/desktop-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-judgments.js +177 -0
- package/mcp-server/dist/services/desktop-judgments.js.map +1 -0
- package/mcp-server/dist/services/desktop-risk.d.ts +283 -0
- package/mcp-server/dist/services/desktop-risk.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-risk.js +605 -0
- package/mcp-server/dist/services/desktop-risk.js.map +1 -0
- package/mcp-server/dist/services/discord.d.ts +112 -0
- package/mcp-server/dist/services/discord.d.ts.map +1 -0
- package/mcp-server/dist/services/discord.js +477 -0
- package/mcp-server/dist/services/discord.js.map +1 -0
- package/mcp-server/dist/services/edit-stale.d.ts +81 -0
- package/mcp-server/dist/services/edit-stale.d.ts.map +1 -0
- package/mcp-server/dist/services/edit-stale.js +358 -0
- package/mcp-server/dist/services/edit-stale.js.map +1 -0
- package/mcp-server/dist/services/embedding-service.d.ts +16 -0
- package/mcp-server/dist/services/embedding-service.d.ts.map +1 -0
- package/mcp-server/dist/services/embedding-service.js +126 -0
- package/mcp-server/dist/services/embedding-service.js.map +1 -0
- package/mcp-server/dist/services/embedding-worker.d.ts +2 -0
- package/mcp-server/dist/services/embedding-worker.d.ts.map +1 -0
- package/mcp-server/dist/services/embedding-worker.js +52 -0
- package/mcp-server/dist/services/embedding-worker.js.map +1 -0
- package/mcp-server/dist/services/fb-regions.d.ts +71 -0
- package/mcp-server/dist/services/fb-regions.d.ts.map +1 -0
- package/mcp-server/dist/services/fb-regions.js +211 -0
- package/mcp-server/dist/services/fb-regions.js.map +1 -0
- package/mcp-server/dist/services/file-checksums.d.ts +22 -0
- package/mcp-server/dist/services/file-checksums.d.ts.map +1 -0
- package/mcp-server/dist/services/file-checksums.js +55 -0
- package/mcp-server/dist/services/file-checksums.js.map +1 -0
- package/mcp-server/dist/services/file-excerpt.d.ts +24 -0
- package/mcp-server/dist/services/file-excerpt.d.ts.map +1 -0
- package/mcp-server/dist/services/file-excerpt.js +65 -0
- package/mcp-server/dist/services/file-excerpt.js.map +1 -0
- package/mcp-server/dist/services/identity.d.ts +124 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -0
- package/mcp-server/dist/services/identity.js +241 -0
- package/mcp-server/dist/services/identity.js.map +1 -0
- package/mcp-server/dist/services/local-embeddings.d.ts +2 -0
- package/mcp-server/dist/services/local-embeddings.d.ts.map +1 -0
- package/mcp-server/dist/services/local-embeddings.js +3 -0
- package/mcp-server/dist/services/local-embeddings.js.map +1 -0
- package/mcp-server/dist/services/memory-client.d.ts +4 -0
- package/mcp-server/dist/services/memory-client.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-client.js +27 -0
- package/mcp-server/dist/services/memory-client.js.map +1 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +135 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-judge-backfill.js +510 -0
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -0
- package/mcp-server/dist/services/memory-judgments.d.ts +362 -0
- package/mcp-server/dist/services/memory-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-judgments.js +674 -0
- package/mcp-server/dist/services/memory-judgments.js.map +1 -0
- package/mcp-server/dist/services/memory-maintenance.d.ts +108 -0
- package/mcp-server/dist/services/memory-maintenance.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-maintenance.js +403 -0
- package/mcp-server/dist/services/memory-maintenance.js.map +1 -0
- package/mcp-server/dist/services/memory-retrieval.d.ts +66 -0
- package/mcp-server/dist/services/memory-retrieval.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-retrieval.js +412 -0
- package/mcp-server/dist/services/memory-retrieval.js.map +1 -0
- package/mcp-server/dist/services/memory-schema.d.ts +16 -0
- package/mcp-server/dist/services/memory-schema.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-schema.js +282 -0
- package/mcp-server/dist/services/memory-schema.js.map +1 -0
- package/mcp-server/dist/services/memory-sessions.d.ts +24 -0
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-sessions.js +110 -0
- package/mcp-server/dist/services/memory-sessions.js.map +1 -0
- package/mcp-server/dist/services/memory-triage.d.ts +60 -0
- package/mcp-server/dist/services/memory-triage.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-triage.js +189 -0
- package/mcp-server/dist/services/memory-triage.js.map +1 -0
- package/mcp-server/dist/services/memory-verification.d.ts +24 -0
- package/mcp-server/dist/services/memory-verification.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-verification.js +92 -0
- package/mcp-server/dist/services/memory-verification.js.map +1 -0
- package/mcp-server/dist/services/memory-writer.d.ts +26 -0
- package/mcp-server/dist/services/memory-writer.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-writer.js +126 -0
- package/mcp-server/dist/services/memory-writer.js.map +1 -0
- package/mcp-server/dist/services/neural-interface.d.ts +439 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -0
- package/mcp-server/dist/services/neural-interface.js +1135 -0
- package/mcp-server/dist/services/neural-interface.js.map +1 -0
- package/mcp-server/dist/services/profiles.d.ts +120 -0
- package/mcp-server/dist/services/profiles.d.ts.map +1 -0
- package/mcp-server/dist/services/profiles.js +387 -0
- package/mcp-server/dist/services/profiles.js.map +1 -0
- package/mcp-server/dist/services/secret-gate.d.ts +29 -0
- package/mcp-server/dist/services/secret-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/secret-gate.js +43 -0
- package/mcp-server/dist/services/secret-gate.js.map +1 -0
- package/mcp-server/dist/services/server-instructions.d.ts +10 -0
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -0
- package/mcp-server/dist/services/server-instructions.js +101 -0
- package/mcp-server/dist/services/server-instructions.js.map +1 -0
- package/mcp-server/dist/services/sqlite.d.ts +235 -0
- package/mcp-server/dist/services/sqlite.d.ts.map +1 -0
- package/mcp-server/dist/services/sqlite.js +1185 -0
- package/mcp-server/dist/services/sqlite.js.map +1 -0
- package/mcp-server/dist/services/typesafe-bench.d.ts +99 -0
- package/mcp-server/dist/services/typesafe-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe-bench.js +218 -0
- package/mcp-server/dist/services/typesafe-bench.js.map +1 -0
- package/mcp-server/dist/services/typesafe-config.d.ts +342 -0
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe-config.js +746 -0
- package/mcp-server/dist/services/typesafe-config.js.map +1 -0
- package/mcp-server/dist/services/typesafe.d.ts +213 -0
- package/mcp-server/dist/services/typesafe.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe.js +330 -0
- package/mcp-server/dist/services/typesafe.js.map +1 -0
- package/mcp-server/dist/services/vector-cache.d.ts +68 -0
- package/mcp-server/dist/services/vector-cache.d.ts.map +1 -0
- package/mcp-server/dist/services/vector-cache.js +271 -0
- package/mcp-server/dist/services/vector-cache.js.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +305 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.js +666 -0
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -0
- package/mcp-server/dist/tools/agents.d.ts +212 -0
- package/mcp-server/dist/tools/agents.d.ts.map +1 -0
- package/mcp-server/dist/tools/agents.js +407 -0
- package/mcp-server/dist/tools/agents.js.map +1 -0
- package/mcp-server/dist/tools/bluesky.d.ts +39 -0
- package/mcp-server/dist/tools/bluesky.d.ts.map +1 -0
- package/mcp-server/dist/tools/bluesky.js +1144 -0
- package/mcp-server/dist/tools/bluesky.js.map +1 -0
- package/mcp-server/dist/tools/browser-advanced.d.ts +58 -0
- package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-advanced.js +106 -0
- package/mcp-server/dist/tools/browser-advanced.js.map +1 -0
- package/mcp-server/dist/tools/browser-batch.d.ts +99 -0
- package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-batch.js +187 -0
- package/mcp-server/dist/tools/browser-batch.js.map +1 -0
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts +21 -0
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-cheatsheet.js +144 -0
- package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -0
- package/mcp-server/dist/tools/browser-interact.d.ts +239 -0
- package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-interact.js +300 -0
- package/mcp-server/dist/tools/browser-interact.js.map +1 -0
- package/mcp-server/dist/tools/browser-navigate.d.ts +90 -0
- package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-navigate.js +142 -0
- package/mcp-server/dist/tools/browser-navigate.js.map +1 -0
- package/mcp-server/dist/tools/browser-observe.d.ts +561 -0
- package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-observe.js +2009 -0
- package/mcp-server/dist/tools/browser-observe.js.map +1 -0
- package/mcp-server/dist/tools/browser.d.ts +34 -0
- package/mcp-server/dist/tools/browser.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser.js +112 -0
- package/mcp-server/dist/tools/browser.js.map +1 -0
- package/mcp-server/dist/tools/card-tools.d.ts +82 -0
- package/mcp-server/dist/tools/card-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/card-tools.js +137 -0
- package/mcp-server/dist/tools/card-tools.js.map +1 -0
- package/mcp-server/dist/tools/card.d.ts +8 -0
- package/mcp-server/dist/tools/card.d.ts.map +1 -0
- package/mcp-server/dist/tools/card.js +16 -0
- package/mcp-server/dist/tools/card.js.map +1 -0
- package/mcp-server/dist/tools/category.d.ts +32 -0
- package/mcp-server/dist/tools/category.d.ts.map +1 -0
- package/mcp-server/dist/tools/category.js +290 -0
- package/mcp-server/dist/tools/category.js.map +1 -0
- package/mcp-server/dist/tools/choice.d.ts +160 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -0
- package/mcp-server/dist/tools/choice.js +80 -0
- package/mcp-server/dist/tools/choice.js.map +1 -0
- package/mcp-server/dist/tools/computer.d.ts +71 -0
- package/mcp-server/dist/tools/computer.d.ts.map +1 -0
- package/mcp-server/dist/tools/computer.js +174 -0
- package/mcp-server/dist/tools/computer.js.map +1 -0
- package/mcp-server/dist/tools/discord-channel.d.ts +44 -0
- package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-channel.js +236 -0
- package/mcp-server/dist/tools/discord-channel.js.map +1 -0
- package/mcp-server/dist/tools/discord-guild.d.ts +20 -0
- package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-guild.js +138 -0
- package/mcp-server/dist/tools/discord-guild.js.map +1 -0
- package/mcp-server/dist/tools/discord-member.d.ts +26 -0
- package/mcp-server/dist/tools/discord-member.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-member.js +122 -0
- package/mcp-server/dist/tools/discord-member.js.map +1 -0
- package/mcp-server/dist/tools/discord-message.d.ts +36 -0
- package/mcp-server/dist/tools/discord-message.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-message.js +184 -0
- package/mcp-server/dist/tools/discord-message.js.map +1 -0
- package/mcp-server/dist/tools/discord-onboarding.d.ts +32 -0
- package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-onboarding.js +179 -0
- package/mcp-server/dist/tools/discord-onboarding.js.map +1 -0
- package/mcp-server/dist/tools/discord-role.d.ts +34 -0
- package/mcp-server/dist/tools/discord-role.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-role.js +178 -0
- package/mcp-server/dist/tools/discord-role.js.map +1 -0
- package/mcp-server/dist/tools/discord-thread.d.ts +28 -0
- package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-thread.js +88 -0
- package/mcp-server/dist/tools/discord-thread.js.map +1 -0
- package/mcp-server/dist/tools/discord-webhook.d.ts +32 -0
- package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-webhook.js +154 -0
- package/mcp-server/dist/tools/discord-webhook.js.map +1 -0
- package/mcp-server/dist/tools/discord.d.ts +7 -0
- package/mcp-server/dist/tools/discord.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord.js +25 -0
- package/mcp-server/dist/tools/discord.js.map +1 -0
- package/mcp-server/dist/tools/fb-groups.d.ts +98 -0
- package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/fb-groups.js +369 -0
- package/mcp-server/dist/tools/fb-groups.js.map +1 -0
- package/mcp-server/dist/tools/forget.d.ts +14 -0
- package/mcp-server/dist/tools/forget.d.ts.map +1 -0
- package/mcp-server/dist/tools/forget.js +26 -0
- package/mcp-server/dist/tools/forget.js.map +1 -0
- package/mcp-server/dist/tools/git-tools.d.ts +24 -0
- package/mcp-server/dist/tools/git-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/git-tools.js +107 -0
- package/mcp-server/dist/tools/git-tools.js.map +1 -0
- package/mcp-server/dist/tools/git.d.ts +7 -0
- package/mcp-server/dist/tools/git.d.ts.map +1 -0
- package/mcp-server/dist/tools/git.js +11 -0
- package/mcp-server/dist/tools/git.js.map +1 -0
- package/mcp-server/dist/tools/gsc/experience.d.ts +135 -0
- package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/experience.js +351 -0
- package/mcp-server/dist/tools/gsc/experience.js.map +1 -0
- package/mcp-server/dist/tools/gsc/helpers.d.ts +78 -0
- package/mcp-server/dist/tools/gsc/helpers.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/helpers.js +258 -0
- package/mcp-server/dist/tools/gsc/helpers.js.map +1 -0
- package/mcp-server/dist/tools/gsc/indexing.d.ts +121 -0
- package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/indexing.js +357 -0
- package/mcp-server/dist/tools/gsc/indexing.js.map +1 -0
- package/mcp-server/dist/tools/gsc/inspect.d.ts +78 -0
- package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/inspect.js +321 -0
- package/mcp-server/dist/tools/gsc/inspect.js.map +1 -0
- package/mcp-server/dist/tools/gsc/navigate.d.ts +44 -0
- package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/navigate.js +197 -0
- package/mcp-server/dist/tools/gsc/navigate.js.map +1 -0
- package/mcp-server/dist/tools/gsc/performance.d.ts +84 -0
- package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/performance.js +274 -0
- package/mcp-server/dist/tools/gsc/performance.js.map +1 -0
- package/mcp-server/dist/tools/gsc/settings.d.ts +153 -0
- package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/settings.js +425 -0
- package/mcp-server/dist/tools/gsc/settings.js.map +1 -0
- package/mcp-server/dist/tools/gsc.d.ts +7 -0
- package/mcp-server/dist/tools/gsc.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc.js +51 -0
- package/mcp-server/dist/tools/gsc.js.map +1 -0
- package/mcp-server/dist/tools/image-tools.d.ts +24 -0
- package/mcp-server/dist/tools/image-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/image-tools.js +80 -0
- package/mcp-server/dist/tools/image-tools.js.map +1 -0
- package/mcp-server/dist/tools/image.d.ts +10 -0
- package/mcp-server/dist/tools/image.d.ts.map +1 -0
- package/mcp-server/dist/tools/image.js +14 -0
- package/mcp-server/dist/tools/image.js.map +1 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +97 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.js +228 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -0
- package/mcp-server/dist/tools/leonardo.d.ts +13 -0
- package/mcp-server/dist/tools/leonardo.d.ts.map +1 -0
- package/mcp-server/dist/tools/leonardo.js +21 -0
- package/mcp-server/dist/tools/leonardo.js.map +1 -0
- package/mcp-server/dist/tools/loop.d.ts +30 -0
- package/mcp-server/dist/tools/loop.d.ts.map +1 -0
- package/mcp-server/dist/tools/loop.js +401 -0
- package/mcp-server/dist/tools/loop.js.map +1 -0
- package/mcp-server/dist/tools/memories.d.ts +56 -0
- package/mcp-server/dist/tools/memories.d.ts.map +1 -0
- package/mcp-server/dist/tools/memories.js +171 -0
- package/mcp-server/dist/tools/memories.js.map +1 -0
- package/mcp-server/dist/tools/morelogin.d.ts +24 -0
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -0
- package/mcp-server/dist/tools/morelogin.js +79 -0
- package/mcp-server/dist/tools/morelogin.js.map +1 -0
- package/mcp-server/dist/tools/profile.d.ts +17 -0
- package/mcp-server/dist/tools/profile.d.ts.map +1 -0
- package/mcp-server/dist/tools/profile.js +114 -0
- package/mcp-server/dist/tools/profile.js.map +1 -0
- package/mcp-server/dist/tools/recall.d.ts +71 -0
- package/mcp-server/dist/tools/recall.d.ts.map +1 -0
- package/mcp-server/dist/tools/recall.js +147 -0
- package/mcp-server/dist/tools/recall.js.map +1 -0
- package/mcp-server/dist/tools/reflect.d.ts +56 -0
- package/mcp-server/dist/tools/reflect.d.ts.map +1 -0
- package/mcp-server/dist/tools/reflect.js +157 -0
- package/mcp-server/dist/tools/reflect.js.map +1 -0
- package/mcp-server/dist/tools/remember.d.ts +62 -0
- package/mcp-server/dist/tools/remember.d.ts.map +1 -0
- package/mcp-server/dist/tools/remember.js +201 -0
- package/mcp-server/dist/tools/remember.js.map +1 -0
- package/mcp-server/dist/tools/response.d.ts +23 -0
- package/mcp-server/dist/tools/response.d.ts.map +1 -0
- package/mcp-server/dist/tools/response.js +24 -0
- package/mcp-server/dist/tools/response.js.map +1 -0
- package/mcp-server/dist/tools/restore.d.ts +14 -0
- package/mcp-server/dist/tools/restore.d.ts.map +1 -0
- package/mcp-server/dist/tools/restore.js +23 -0
- package/mcp-server/dist/tools/restore.js.map +1 -0
- package/mcp-server/dist/tools/style-guide-tools.d.ts +51 -0
- package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/style-guide-tools.js +231 -0
- package/mcp-server/dist/tools/style-guide-tools.js.map +1 -0
- package/mcp-server/dist/tools/style-guide.d.ts +8 -0
- package/mcp-server/dist/tools/style-guide.d.ts.map +1 -0
- package/mcp-server/dist/tools/style-guide.js +12 -0
- package/mcp-server/dist/tools/style-guide.js.map +1 -0
- package/mcp-server/dist/tools/sync.d.ts +20 -0
- package/mcp-server/dist/tools/sync.d.ts.map +1 -0
- package/mcp-server/dist/tools/sync.js +156 -0
- package/mcp-server/dist/tools/sync.js.map +1 -0
- package/mcp-server/dist/tools/tictactoe-tools.d.ts +18 -0
- package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/tictactoe-tools.js +78 -0
- package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -0
- package/mcp-server/dist/tools/tictactoe.d.ts +7 -0
- package/mcp-server/dist/tools/tictactoe.d.ts.map +1 -0
- package/mcp-server/dist/tools/tictactoe.js +11 -0
- package/mcp-server/dist/tools/tictactoe.js.map +1 -0
- package/mcp-server/dist/tools/utils.d.ts +19 -0
- package/mcp-server/dist/tools/utils.d.ts.map +1 -0
- package/mcp-server/dist/tools/utils.js +54 -0
- package/mcp-server/dist/tools/utils.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts +88 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.js +337 -0
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +326 -0
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard-tools.js +222 -0
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard.d.ts +8 -0
- package/mcp-server/dist/tools/whiteboard.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard.js +16 -0
- package/mcp-server/dist/tools/whiteboard.js.map +1 -0
- package/mcp-server/dist/tools/youtube/analytics.d.ts +46 -0
- package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/analytics.js +83 -0
- package/mcp-server/dist/tools/youtube/analytics.js.map +1 -0
- package/mcp-server/dist/tools/youtube/dedup.d.ts +35 -0
- package/mcp-server/dist/tools/youtube/dedup.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/dedup.js +56 -0
- package/mcp-server/dist/tools/youtube/dedup.js.map +1 -0
- package/mcp-server/dist/tools/youtube/download.d.ts +31 -0
- package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/download.js +30 -0
- package/mcp-server/dist/tools/youtube/download.js.map +1 -0
- package/mcp-server/dist/tools/youtube/helpers.d.ts +66 -0
- package/mcp-server/dist/tools/youtube/helpers.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/helpers.js +143 -0
- package/mcp-server/dist/tools/youtube/helpers.js.map +1 -0
- package/mcp-server/dist/tools/youtube/media.d.ts +43 -0
- package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/media.js +97 -0
- package/mcp-server/dist/tools/youtube/media.js.map +1 -0
- package/mcp-server/dist/tools/youtube/metadata.d.ts +33 -0
- package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/metadata.js +106 -0
- package/mcp-server/dist/tools/youtube/metadata.js.map +1 -0
- package/mcp-server/dist/tools/youtube/navigate.d.ts +30 -0
- package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/navigate.js +71 -0
- package/mcp-server/dist/tools/youtube/navigate.js.map +1 -0
- package/mcp-server/dist/tools/youtube/playlist.d.ts +29 -0
- package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/playlist.js +128 -0
- package/mcp-server/dist/tools/youtube/playlist.js.map +1 -0
- package/mcp-server/dist/tools/youtube/schedule.d.ts +31 -0
- package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/schedule.js +147 -0
- package/mcp-server/dist/tools/youtube/schedule.js.map +1 -0
- package/mcp-server/dist/tools/youtube/source.d.ts +36 -0
- package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/source.js +85 -0
- package/mcp-server/dist/tools/youtube/source.js.map +1 -0
- package/mcp-server/dist/tools/youtube/upload.d.ts +53 -0
- package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/upload.js +255 -0
- package/mcp-server/dist/tools/youtube/upload.js.map +1 -0
- package/mcp-server/dist/tools/youtube.d.ts +12 -0
- package/mcp-server/dist/tools/youtube.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube.js +38 -0
- package/mcp-server/dist/tools/youtube.js.map +1 -0
- package/mcp-server/dist/tui.d.ts +3 -0
- package/mcp-server/dist/tui.d.ts.map +1 -0
- package/mcp-server/dist/tui.js +806 -0
- package/mcp-server/dist/tui.js.map +1 -0
- package/mcp-server/dist/types.d.ts +77 -0
- package/mcp-server/dist/types.d.ts.map +1 -0
- package/mcp-server/dist/types.js +2 -0
- package/mcp-server/dist/types.js.map +1 -0
- package/mcp-server/package-lock.json +4798 -0
- package/mcp-server/package.json +55 -38
- package/mcp-server/run.mjs +12 -2
- package/mcp-server/src/config.ts +48 -3
- package/mcp-server/src/http.ts +296 -93
- package/mcp-server/src/index.ts +546 -203
- package/mcp-server/src/preload-http.ts +19 -18
- package/mcp-server/src/preload.ts +19 -18
- package/mcp-server/src/scripts/setup-embeddings.ts +9 -0
- package/mcp-server/src/services/assistant-judgments.ts +157 -0
- package/mcp-server/src/services/browser-assist-gate.ts +383 -0
- package/mcp-server/src/services/browser-assist.ts +267 -0
- package/mcp-server/src/services/browser-bench.ts +477 -0
- package/mcp-server/src/services/browser-judgments.ts +414 -0
- package/mcp-server/src/services/browser-risk.ts +484 -0
- package/mcp-server/src/services/categories.ts +36 -19
- package/mcp-server/src/services/codex-config-heal.ts +403 -0
- package/mcp-server/src/services/desktop-assist-gate.ts +251 -0
- package/mcp-server/src/services/desktop-assist.ts +308 -0
- package/mcp-server/src/services/desktop-bench.ts +372 -0
- package/mcp-server/src/services/desktop-client.ts +76 -0
- package/mcp-server/src/services/desktop-judgments.ts +218 -0
- package/mcp-server/src/services/desktop-risk.ts +743 -0
- package/mcp-server/src/services/edit-stale.ts +299 -0
- package/mcp-server/src/services/embedding-service.ts +108 -0
- package/mcp-server/src/services/embedding-worker.ts +46 -0
- package/mcp-server/src/services/fb-regions.ts +221 -0
- package/mcp-server/src/services/file-checksums.ts +26 -9
- package/mcp-server/src/services/file-excerpt.ts +59 -0
- package/mcp-server/src/services/identity.ts +291 -0
- package/mcp-server/src/services/local-embeddings.ts +2 -77
- package/mcp-server/src/services/memory-client.ts +23 -0
- package/mcp-server/src/services/memory-judge-backfill.ts +462 -0
- package/mcp-server/src/services/memory-judgments.ts +901 -0
- package/mcp-server/src/services/memory-maintenance.ts +360 -0
- package/mcp-server/src/services/memory-retrieval.ts +349 -0
- package/mcp-server/src/services/memory-schema.ts +280 -0
- package/mcp-server/src/services/memory-sessions.ts +87 -0
- package/mcp-server/src/services/memory-triage.ts +182 -0
- package/mcp-server/src/services/memory-verification.ts +68 -0
- package/mcp-server/src/services/memory-writer.ts +125 -0
- package/mcp-server/src/services/neural-interface.ts +1217 -73
- package/mcp-server/src/services/profiles.ts +428 -0
- package/mcp-server/src/services/secret-gate.ts +52 -0
- package/mcp-server/src/services/server-instructions.ts +122 -0
- package/mcp-server/src/services/sqlite.ts +1456 -823
- package/mcp-server/src/services/typesafe-bench.ts +247 -0
- package/mcp-server/src/services/typesafe-config.ts +790 -0
- package/mcp-server/src/services/typesafe.ts +390 -0
- package/mcp-server/src/services/vector-cache.ts +255 -0
- package/mcp-server/src/services/whiteboard-geometry.ts +711 -0
- package/mcp-server/src/tools/agents.ts +539 -0
- package/mcp-server/src/tools/bluesky.ts +1186 -0
- package/mcp-server/src/tools/browser-advanced.ts +15 -6
- package/mcp-server/src/tools/browser-batch.ts +178 -0
- package/mcp-server/src/tools/browser-cheatsheet.ts +155 -0
- package/mcp-server/src/tools/browser-interact.ts +362 -255
- package/mcp-server/src/tools/browser-navigate.ts +164 -77
- package/mcp-server/src/tools/browser-observe.ts +2222 -1330
- package/mcp-server/src/tools/browser.ts +181 -107
- package/mcp-server/src/tools/card.ts +7 -5
- package/mcp-server/src/tools/choice.ts +103 -0
- package/mcp-server/src/tools/computer.ts +190 -0
- package/mcp-server/src/tools/discord.ts +10 -23
- package/mcp-server/src/tools/fb-groups.ts +387 -0
- package/mcp-server/src/tools/forget.ts +1 -1
- package/mcp-server/src/tools/git.ts +3 -1
- package/mcp-server/src/tools/gsc/experience.ts +440 -0
- package/mcp-server/src/tools/gsc/helpers.ts +288 -0
- package/mcp-server/src/tools/gsc/indexing.ts +495 -0
- package/mcp-server/src/tools/gsc/inspect.ts +391 -0
- package/mcp-server/src/tools/gsc/navigate.ts +236 -0
- package/mcp-server/src/tools/gsc/performance.ts +352 -0
- package/mcp-server/src/tools/gsc/settings.ts +564 -0
- package/mcp-server/src/tools/gsc.ts +95 -0
- package/mcp-server/src/tools/image.ts +3 -1
- package/mcp-server/src/tools/leonardo-browser-tools.ts +47 -37
- package/mcp-server/src/tools/leonardo.ts +7 -5
- package/mcp-server/src/tools/loop.ts +118 -25
- package/mcp-server/src/tools/memories.ts +65 -5
- package/mcp-server/src/tools/morelogin.ts +81 -0
- package/mcp-server/src/tools/profile.ts +122 -0
- package/mcp-server/src/tools/recall.ts +105 -261
- package/mcp-server/src/tools/reflect.ts +171 -145
- package/mcp-server/src/tools/remember.ts +223 -115
- package/mcp-server/src/tools/style-guide-tools.ts +250 -0
- package/mcp-server/src/tools/style-guide.ts +16 -0
- package/mcp-server/src/tools/sync.ts +66 -9
- package/mcp-server/src/tools/tictactoe.ts +3 -1
- package/mcp-server/src/tools/utils.ts +22 -0
- package/mcp-server/src/tools/whiteboard-format.ts +394 -0
- package/mcp-server/src/tools/whiteboard-tools.ts +191 -183
- package/mcp-server/src/tools/whiteboard.ts +7 -5
- package/mcp-server/src/tools/youtube/analytics.ts +106 -0
- package/mcp-server/src/tools/youtube/dedup.ts +57 -0
- package/mcp-server/src/tools/youtube/download.ts +41 -0
- package/mcp-server/src/tools/youtube/helpers.ts +183 -0
- package/mcp-server/src/tools/youtube/media.ts +109 -0
- package/mcp-server/src/tools/youtube/metadata.ts +112 -0
- package/mcp-server/src/tools/youtube/navigate.ts +81 -0
- package/mcp-server/src/tools/youtube/playlist.ts +134 -0
- package/mcp-server/src/tools/youtube/schedule.ts +158 -0
- package/mcp-server/src/tools/youtube/source.ts +101 -0
- package/mcp-server/src/tools/youtube/upload.ts +296 -0
- package/mcp-server/src/tools/youtube.ts +47 -0
- package/mcp-server/src/tui.ts +8 -9
- package/neural-interface/games/TicTacToe/1.svg +1 -0
- package/neural-interface/games/TicTacToe/2.svg +1 -0
- package/neural-interface/games/TicTacToe/3.svg +1 -0
- package/neural-interface/games/TicTacToe/4.svg +1 -0
- package/neural-interface/games/TicTacToe/5.svg +1 -0
- package/neural-interface/games/TicTacToe/6.svg +1 -0
- package/neural-interface/games/TicTacToe/7.svg +1 -0
- package/neural-interface/games/TicTacToe/8.svg +1 -0
- package/neural-interface/games/TicTacToe/9.svg +1 -0
- package/neural-interface/games/TicTacToe/Board.svg +1 -0
- package/neural-interface/games/TicTacToe/Circle.svg +1 -0
- package/neural-interface/games/TicTacToe/Cross.svg +1 -0
- package/neural-interface/i18n/en.json +7022 -0
- package/neural-interface/i18n/pt-BR.json +7026 -0
- package/neural-interface/lib/assistant-api.js +1005 -0
- package/neural-interface/lib/assistant-attachments.js +121 -0
- package/neural-interface/lib/assistant-brains/claude.js +207 -0
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +43 -0
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +56 -0
- package/neural-interface/lib/assistant-brains/codex.js +213 -0
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +47 -0
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +62 -0
- package/neural-interface/lib/assistant-brains/opencode.js +320 -0
- package/neural-interface/lib/assistant-budget.js +318 -0
- package/neural-interface/lib/assistant-catalog.js +731 -0
- package/neural-interface/lib/assistant-clarify.js +664 -0
- package/neural-interface/lib/assistant-config.js +232 -0
- package/neural-interface/lib/assistant-dispatch.js +2744 -0
- package/neural-interface/lib/assistant-envelope.js +582 -0
- package/neural-interface/lib/assistant-evidence.js +236 -0
- package/neural-interface/lib/assistant-hidden-models.js +272 -0
- package/neural-interface/lib/assistant-jev.js +117 -0
- package/neural-interface/lib/assistant-judgments.js +111 -0
- package/neural-interface/lib/assistant-media.js +335 -0
- package/neural-interface/lib/assistant-memory.js +398 -0
- package/neural-interface/lib/assistant-persona.js +444 -0
- package/neural-interface/lib/assistant-plan-permissions.js +448 -0
- package/neural-interface/lib/assistant-playbooks/design.md +87 -0
- package/neural-interface/lib/assistant-playbooks.js +72 -0
- package/neural-interface/lib/assistant-pricing.js +159 -0
- package/neural-interface/lib/assistant-route-gate-codex.js +163 -0
- package/neural-interface/lib/assistant-route-gate.js +212 -0
- package/neural-interface/lib/assistant-router.js +1324 -0
- package/neural-interface/lib/assistant-runtime.js +3337 -0
- package/neural-interface/lib/assistant-task-prompt.js +472 -0
- package/neural-interface/lib/assistant-usage.js +1688 -0
- package/neural-interface/lib/augmented-path.js +70 -0
- package/neural-interface/lib/automation-storage-migration.js +54 -0
- package/neural-interface/lib/backup-service.js +851 -0
- package/neural-interface/lib/backup-zip-reader.js +262 -0
- package/neural-interface/lib/browser-assist-api.js +41 -0
- package/neural-interface/lib/browser-console.js +176 -0
- package/neural-interface/lib/browser-execution.js +241 -0
- package/neural-interface/lib/browser-extraction.js +191 -0
- package/neural-interface/lib/browser-language.js +83 -0
- package/neural-interface/lib/browser-screenshot.js +399 -0
- package/neural-interface/lib/browser-semantic-context.js +639 -0
- package/neural-interface/lib/browser-snapshots.js +192 -0
- package/neural-interface/lib/browser-tab-recovery.js +119 -0
- package/neural-interface/lib/browser-targets.js +70 -0
- package/neural-interface/lib/browser-tool-policy.js +926 -0
- package/neural-interface/lib/claude-accounts.js +230 -0
- package/neural-interface/lib/claude-agent-bridge.js +3203 -0
- package/neural-interface/lib/claude-bypass-policy.js +99 -0
- package/neural-interface/lib/claude-executable.js +241 -0
- package/neural-interface/lib/claude-history.js +429 -0
- package/neural-interface/lib/claude-model-catalog.js +444 -0
- package/neural-interface/lib/claude-panel-requests.js +165 -0
- package/neural-interface/lib/claude-panel-session.js +272 -0
- package/neural-interface/lib/claude-permission-rules.js +153 -0
- package/neural-interface/lib/claude-session-cleanup.js +71 -0
- package/neural-interface/lib/claude-session-list.js +82 -0
- package/neural-interface/lib/claude-session-ops.js +140 -0
- package/neural-interface/lib/claude-settings-view.js +51 -0
- package/neural-interface/lib/claude-skin-connect.js +79 -0
- package/neural-interface/lib/claude-stall-policy.js +7 -0
- package/neural-interface/lib/claude-temporary.js +435 -0
- package/neural-interface/lib/cli-update-planner.js +312 -0
- package/neural-interface/lib/codex-capabilities.d.ts +41 -0
- package/neural-interface/lib/codex-capabilities.js +148 -0
- package/neural-interface/lib/codex-collaboration-mode.js +17 -0
- package/neural-interface/lib/codex-compat-rpc.js +241 -0
- package/neural-interface/lib/codex-mcp-approvals.js +56 -0
- package/neural-interface/lib/codex-mcp-apps.js +47 -0
- package/neural-interface/lib/codex-model-context.js +202 -0
- package/neural-interface/lib/codex-plan-store.js +71 -0
- package/neural-interface/lib/codex-request-journal.js +242 -0
- package/neural-interface/lib/codex-runtime-path.js +213 -0
- package/neural-interface/lib/codex-session-catalog.js +231 -0
- package/neural-interface/lib/codex-session-settings.js +46 -0
- package/neural-interface/lib/codex-sidepanel-permissions.js +110 -0
- package/neural-interface/lib/codex-thread-history.js +165 -0
- package/neural-interface/lib/codex-user-verification.js +34 -0
- package/neural-interface/lib/codex-writer-lifecycle.js +152 -0
- package/neural-interface/lib/confined-fs.js +256 -0
- package/neural-interface/lib/db.js +922 -0
- package/neural-interface/lib/design-md.js +9 -0
- package/neural-interface/lib/desktop/api.js +92 -0
- package/neural-interface/lib/desktop/audit.js +62 -0
- package/neural-interface/lib/desktop/build.js +423 -0
- package/neural-interface/lib/desktop/config.js +606 -0
- package/neural-interface/lib/desktop/coords.js +76 -0
- package/neural-interface/lib/desktop/fake-helper.js +1192 -0
- package/neural-interface/lib/desktop/frames.js +77 -0
- package/neural-interface/lib/desktop/grants.js +84 -0
- package/neural-interface/lib/desktop/guards.js +170 -0
- package/neural-interface/lib/desktop/helper/SynabunDesktop.swift +3056 -0
- package/neural-interface/lib/desktop/lease.js +51 -0
- package/neural-interface/lib/desktop/manager.js +545 -0
- package/neural-interface/lib/desktop/press-contexts.js +103 -0
- package/neural-interface/lib/desktop/protocol.js +495 -0
- package/neural-interface/lib/desktop/service.js +1202 -0
- package/neural-interface/lib/effort-levels.js +148 -0
- package/neural-interface/lib/event-loop-monitor.js +67 -0
- package/neural-interface/lib/exec-loop-command.js +209 -0
- package/neural-interface/lib/folder-picker.ps1 +77 -0
- package/neural-interface/lib/http-guards.js +287 -0
- package/neural-interface/lib/jsonl-lines.js +94 -0
- package/neural-interface/lib/loop-logger.js +127 -0
- package/neural-interface/lib/mcp-client-config.js +133 -0
- package/neural-interface/lib/mcp-installer.js +487 -0
- package/neural-interface/lib/mcp-profile-refresh-coordinator.js +78 -0
- package/neural-interface/lib/mcp-profile-servers.js +120 -0
- package/neural-interface/lib/memo-cache.js +84 -0
- package/neural-interface/lib/memory-api.js +758 -0
- package/neural-interface/lib/memory-map-api.js +1150 -0
- package/neural-interface/lib/memory-map-layout.js +872 -0
- package/neural-interface/lib/memory-map-worker.js +165 -0
- package/neural-interface/lib/memory-session-capture.js +81 -0
- package/neural-interface/lib/memory-timers.js +62 -0
- package/neural-interface/lib/morelogin.js +301 -0
- package/neural-interface/lib/native-binary-runtime.js +382 -0
- package/neural-interface/lib/native-loop-goal.js +33 -0
- package/neural-interface/lib/native-loop-providers.js +1002 -0
- package/neural-interface/lib/native-loop-runtime.js +747 -0
- package/neural-interface/lib/offline-page.js +54 -0
- package/neural-interface/lib/opencode-hidden-models.js +113 -0
- package/neural-interface/lib/opencode-history.js +253 -0
- package/neural-interface/lib/opencode-runtime-config.js +58 -0
- package/neural-interface/lib/opencode-v2-client.js +486 -0
- package/neural-interface/lib/opencode-v2-ws-requests.js +955 -0
- package/neural-interface/lib/path-confine.js +213 -0
- package/neural-interface/lib/plugin-installer.js +264 -0
- package/neural-interface/lib/project-storage.js +766 -0
- package/neural-interface/lib/pty-host/core.js +603 -0
- package/neural-interface/lib/pty-host/flow.js +43 -0
- package/neural-interface/lib/pty-host/host.js +47 -0
- package/neural-interface/lib/pty-host/manager.js +360 -0
- package/neural-interface/lib/pty-host/protocol.js +81 -0
- package/neural-interface/lib/pty-host/snapshot.js +133 -0
- package/neural-interface/lib/remote-policy.js +582 -0
- package/neural-interface/lib/rulesets/api.js +175 -0
- package/neural-interface/lib/rulesets/fs-safe.js +245 -0
- package/neural-interface/lib/rulesets/installer.js +1453 -0
- package/neural-interface/lib/rulesets/json-edit.js +186 -0
- package/neural-interface/lib/rulesets/lock.js +170 -0
- package/neural-interface/lib/rulesets/managed-text.js +314 -0
- package/neural-interface/lib/rulesets/normalise.js +24 -0
- package/neural-interface/lib/rulesets/render.js +84 -0
- package/neural-interface/lib/schedule-launch-intent.js +40 -0
- package/neural-interface/lib/session-cache-builder.js +524 -0
- package/neural-interface/lib/session-chunker.js +344 -0
- package/neural-interface/lib/session-indexer.js +327 -0
- package/neural-interface/lib/session-title-generator.js +232 -0
- package/neural-interface/lib/skill-prompt-bridge.js +11 -0
- package/neural-interface/lib/style-guide/api.js +375 -0
- package/neural-interface/lib/style-guide/color.js +352 -0
- package/neural-interface/lib/style-guide/export-css.js +99 -0
- package/neural-interface/lib/style-guide/export-dtcg.js +209 -0
- package/neural-interface/lib/style-guide/export-tailwind.js +102 -0
- package/neural-interface/lib/style-guide/fonts.json +227 -0
- package/neural-interface/lib/style-guide/import.js +1268 -0
- package/neural-interface/lib/style-guide/pointers.js +103 -0
- package/neural-interface/lib/style-guide/presets.js +232 -0
- package/neural-interface/lib/style-guide/render-design-md.js +319 -0
- package/neural-interface/lib/style-guide/schema.js +848 -0
- package/neural-interface/lib/style-guide/security.js +43 -0
- package/neural-interface/lib/style-guide/store.js +491 -0
- package/neural-interface/lib/style-guide/summary.js +106 -0
- package/neural-interface/lib/style-guide/tokens.js +170 -0
- package/neural-interface/lib/synabun-update-plan.js +324 -0
- package/neural-interface/lib/synabun-version.js +179 -0
- package/neural-interface/lib/system-restore.js +99 -0
- package/neural-interface/lib/terminal-env.js +86 -0
- package/neural-interface/lib/ui-blob-store.js +106 -0
- package/neural-interface/lib/vector-cache.js +2 -0
- package/neural-interface/lib/virtual-socket.js +60 -0
- package/neural-interface/lib/whatsapp/api.js +146 -0
- package/neural-interface/lib/whatsapp/auth-store.js +389 -0
- package/neural-interface/lib/whatsapp/baileys-adapter.js +457 -0
- package/neural-interface/lib/whatsapp/brain.js +128 -0
- package/neural-interface/lib/whatsapp/bridge.js +1499 -0
- package/neural-interface/lib/whatsapp/cards.js +519 -0
- package/neural-interface/lib/whatsapp/commands.js +92 -0
- package/neural-interface/lib/whatsapp/config.js +291 -0
- package/neural-interface/lib/whatsapp/connector/entry.mjs +25 -0
- package/neural-interface/lib/whatsapp/connector/manifest.json +6 -0
- package/neural-interface/lib/whatsapp/connector/npm-shrinkwrap.json +717 -0
- package/neural-interface/lib/whatsapp/connector/package.json +8 -0
- package/neural-interface/lib/whatsapp/fake-baileys.js +444 -0
- package/neural-interface/lib/whatsapp/format.js +552 -0
- package/neural-interface/lib/whatsapp/host-core.js +1225 -0
- package/neural-interface/lib/whatsapp/host.js +119 -0
- package/neural-interface/lib/whatsapp/identity.js +288 -0
- package/neural-interface/lib/whatsapp/inbound.js +149 -0
- package/neural-interface/lib/whatsapp/installer.js +562 -0
- package/neural-interface/lib/whatsapp/manager.js +638 -0
- package/neural-interface/lib/whatsapp/paths.js +81 -0
- package/neural-interface/lib/whatsapp/protocol.js +327 -0
- package/neural-interface/lib/whatsapp/qr-svg.js +57 -0
- package/neural-interface/lib/whatsapp/redact.js +130 -0
- package/neural-interface/lib/whatsapp/service.js +1305 -0
- package/neural-interface/lib/whatsapp/vendor/qrcodegen.js +848 -0
- package/neural-interface/package-lock.json +4431 -0
- package/neural-interface/package.json +58 -27
- package/neural-interface/public/apple-touch-icon.png +0 -0
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude.svg +1 -0
- package/neural-interface/public/favicon-16x16.png +0 -0
- package/neural-interface/public/favicon-32x32.png +0 -0
- package/neural-interface/public/icon-192.png +0 -0
- package/neural-interface/public/icon-512.png +0 -0
- package/neural-interface/public/index.html +32 -182
- package/neural-interface/public/index2d.html +2 -2
- package/neural-interface/public/install-app.html +31 -0
- package/neural-interface/public/logo-synabun.png +0 -0
- package/neural-interface/public/logoHD.png +0 -0
- package/neural-interface/public/manifest.json +2 -0
- package/neural-interface/public/mcp.svg +4 -0
- package/neural-interface/public/offline.html +670 -299
- package/neural-interface/public/onboarding.html +804 -161
- package/neural-interface/public/opencode-logo-dark-square.svg +1 -0
- package/neural-interface/public/shared/agent-runtime-options.js +596 -0
- package/neural-interface/public/shared/api.js +339 -28
- package/neural-interface/public/shared/assistant/asst-accounts.js +318 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +296 -0
- package/neural-interface/public/shared/assistant/asst-api.js +270 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +744 -0
- package/neural-interface/public/shared/assistant/asst-budget.js +333 -0
- package/neural-interface/public/shared/assistant/asst-composer.js +656 -0
- package/neural-interface/public/shared/assistant/asst-computer.js +803 -0
- package/neural-interface/public/shared/assistant/asst-control.js +1018 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +262 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +313 -0
- package/neural-interface/public/shared/assistant/asst-menu.js +375 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +1845 -0
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +586 -0
- package/neural-interface/public/shared/assistant/asst-render.js +3305 -0
- package/neural-interface/public/shared/assistant/asst-route.js +1653 -0
- package/neural-interface/public/shared/assistant/asst-roving.js +75 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +117 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +488 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +675 -0
- package/neural-interface/public/shared/assistant/asst-slash.js +258 -0
- package/neural-interface/public/shared/assistant/asst-state.js +727 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +1686 -0
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +1017 -0
- package/neural-interface/public/shared/assistant/asst-usage.js +444 -0
- package/neural-interface/public/shared/assistant/asst-ws.js +175 -0
- package/neural-interface/public/shared/automation-context.js +75 -0
- package/neural-interface/public/shared/blob-store.js +99 -0
- package/neural-interface/public/shared/cdx/cdx-capabilities.js +118 -0
- package/neural-interface/public/shared/cdx/cdx-cards.js +37 -0
- package/neural-interface/public/shared/cdx/cdx-commands.js +171 -0
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +402 -0
- package/neural-interface/public/shared/cdx/cdx-context-model.js +220 -0
- package/neural-interface/public/shared/cdx/cdx-features.js +408 -0
- package/neural-interface/public/shared/cdx/cdx-icons.js +89 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-host.js +414 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.html +6 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.js +56 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app.js +178 -0
- package/neural-interface/public/shared/cdx/cdx-model-catalog.js +120 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +261 -0
- package/neural-interface/public/shared/cdx/cdx-output.js +382 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +1372 -0
- package/neural-interface/public/shared/cdx/cdx-plan.js +266 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +682 -0
- package/neural-interface/public/shared/cdx/cdx-render.js +3381 -0
- package/neural-interface/public/shared/cdx/cdx-requests.js +1136 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +3251 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +7992 -0
- package/neural-interface/public/shared/cdx/cdx-ws.js +363 -0
- package/neural-interface/public/shared/cli-status.js +169 -0
- package/neural-interface/public/shared/command-runner-model.js +30 -0
- package/neural-interface/public/shared/constants.js +22 -5
- package/neural-interface/public/shared/cp/cp-agents.js +186 -0
- package/neural-interface/public/shared/cp/cp-bash.js +252 -0
- package/neural-interface/public/shared/cp/cp-compose.js +159 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +309 -0
- package/neural-interface/public/shared/cp/cp-context-model.js +157 -0
- package/neural-interface/public/shared/cp/cp-context-window.js +80 -0
- package/neural-interface/public/shared/cp/cp-ctx.js +11 -0
- package/neural-interface/public/shared/cp/cp-diff.js +255 -0
- package/neural-interface/public/shared/cp/cp-event-rows.js +637 -0
- package/neural-interface/public/shared/cp/cp-events.js +846 -0
- package/neural-interface/public/shared/cp/cp-markdown.js +104 -0
- package/neural-interface/public/shared/cp/cp-permission-model.js +905 -0
- package/neural-interface/public/shared/cp/cp-permissions.js +626 -0
- package/neural-interface/public/shared/cp/cp-rehydrate.js +113 -0
- package/neural-interface/public/shared/cp/cp-restore.js +224 -0
- package/neural-interface/public/shared/cp/cp-session-model.js +338 -0
- package/neural-interface/public/shared/cp/cp-session-settings.js +254 -0
- package/neural-interface/public/shared/cp/cp-sessions.js +227 -0
- package/neural-interface/public/shared/cp/cp-statusline.js +153 -0
- package/neural-interface/public/shared/cp/cp-styles.js +349 -0
- package/neural-interface/public/shared/cp/cp-tasks-model.js +282 -0
- package/neural-interface/public/shared/cp/cp-tasks.js +107 -0
- package/neural-interface/public/shared/cp/cp-temporary-view.js +56 -0
- package/neural-interface/public/shared/cp/cp-temporary.js +231 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +326 -0
- package/neural-interface/public/shared/cp/cp-tool-results.js +618 -0
- package/neural-interface/public/shared/cp/cp-usage-model.js +124 -0
- package/neural-interface/public/shared/graph-activity.js +68 -0
- package/neural-interface/public/shared/html-shell.js +116 -17
- package/neural-interface/public/shared/i18n.js +132 -34
- package/neural-interface/public/shared/node-positions-store.js +44 -0
- package/neural-interface/public/shared/ocp-hidden-models.js +116 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +355 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-autoaccept-button.js +35 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-automation-ownership.js +72 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +280 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +67 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +179 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes.js +164 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +725 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +75 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +1204 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm-logic.js +117 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm.js +59 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-gauge.js +252 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +478 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +179 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +233 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-icons.js +30 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +1065 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-mention-hints.js +182 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +655 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +2636 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +601 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-profile-inheritance.js +78 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +649 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +35 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +357 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render-logic.js +189 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1869 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-select.js +42 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +117 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +1714 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +468 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-widgets.js +63 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +366 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-settings-link.js +19 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +343 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +746 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +347 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +338 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +3543 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-subagents-logic.js +482 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-tools-logic.js +351 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-tools.js +168 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-variantpicker.js +315 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +545 -0
- package/neural-interface/public/shared/provider-icons.js +30 -0
- package/neural-interface/public/shared/pwa-install-page.js +34 -0
- package/neural-interface/public/shared/pwa-install.css +12 -0
- package/neural-interface/public/shared/pwa-install.js +28 -0
- package/neural-interface/public/shared/session-title.js +100 -0
- package/neural-interface/public/shared/settings/settings-ia.js +389 -0
- package/neural-interface/public/shared/settings/settings-kit.js +234 -0
- package/neural-interface/public/shared/settings/settings-rules.js +160 -0
- package/neural-interface/public/shared/settings/settings-search.js +463 -0
- package/neural-interface/public/shared/settings/settings-shell.js +570 -0
- package/neural-interface/public/shared/start-bridge.js +583 -0
- package/neural-interface/public/shared/state.js +5 -0
- package/neural-interface/public/shared/storage.js +50 -7
- package/neural-interface/public/shared/styleguide/sg-agents.js +42 -0
- package/neural-interface/public/shared/styleguide/sg-brand.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-color-client.js +388 -0
- package/neural-interface/public/shared/styleguide/sg-colors.js +151 -0
- package/neural-interface/public/shared/styleguide/sg-components.js +35 -0
- package/neural-interface/public/shared/styleguide/sg-history.js +41 -0
- package/neural-interface/public/shared/styleguide/sg-icons-logo.js +38 -0
- package/neural-interface/public/shared/styleguide/sg-imagery.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-import-export.js +48 -0
- package/neural-interface/public/shared/styleguide/sg-kit.js +284 -0
- package/neural-interface/public/shared/styleguide/sg-labels.js +318 -0
- package/neural-interface/public/shared/styleguide/sg-layout.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-motion.js +5 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +237 -0
- package/neural-interface/public/shared/styleguide/sg-preview.js +138 -0
- package/neural-interface/public/shared/styleguide/sg-rules.js +9 -0
- package/neural-interface/public/shared/styleguide/sg-shape.js +24 -0
- package/neural-interface/public/shared/styleguide/sg-state.js +132 -0
- package/neural-interface/public/shared/styleguide/sg-typography.js +125 -0
- package/neural-interface/public/shared/styles.css +8614 -1477
- package/neural-interface/public/shared/synabun-mascot.js +1625 -0
- package/neural-interface/public/shared/synabun-ticker.js +376 -0
- package/neural-interface/public/shared/term-ready.js +307 -0
- package/neural-interface/public/shared/term-renderer.js +343 -0
- package/neural-interface/public/shared/ui-assistant-panel.js +10 -0
- package/neural-interface/public/shared/ui-assistant.js +77 -0
- package/neural-interface/public/shared/ui-automation-studio.js +5105 -3573
- package/neural-interface/public/shared/ui-claude-panel.js +11685 -6333
- package/neural-interface/public/shared/ui-codex-panel.js +12 -0
- package/neural-interface/public/shared/ui-command-runner.js +251 -468
- package/neural-interface/public/shared/ui-cost-widget.js +55 -34
- package/neural-interface/public/shared/ui-detail.js +77 -14
- package/neural-interface/public/shared/ui-explorer.js +360 -181
- package/neural-interface/public/shared/ui-file-explorer.js +485 -107
- package/neural-interface/public/shared/ui-help.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +45 -21
- package/neural-interface/public/shared/ui-judgments.js +1346 -0
- package/neural-interface/public/shared/ui-keybinds.js +3 -2
- package/neural-interface/public/shared/ui-link.js +105 -51
- package/neural-interface/public/shared/ui-loading.js +222 -11
- package/neural-interface/public/shared/ui-memory-maintenance.js +111 -0
- package/neural-interface/public/shared/ui-menubar.js +100 -31
- package/neural-interface/public/shared/ui-native-loop-router-state.js +94 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +493 -0
- package/neural-interface/public/shared/ui-native-window-id.js +7 -0
- package/neural-interface/public/shared/ui-navbar.js +357 -222
- package/neural-interface/public/shared/ui-notifications.js +58 -12
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +17 -0
- package/neural-interface/public/shared/ui-panels.js +15 -7
- package/neural-interface/public/shared/ui-resume.js +823 -653
- package/neural-interface/public/shared/ui-schedule-queue.js +172 -0
- package/neural-interface/public/shared/ui-schedules-studio.js +1882 -0
- package/neural-interface/public/shared/ui-scroll-follow.js +194 -0
- package/neural-interface/public/shared/ui-sessions.js +789 -34
- package/neural-interface/public/shared/ui-settings.js +5774 -2194
- package/neural-interface/public/shared/ui-sidepanel-layout.js +109 -0
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +19 -0
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +40 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +221 -0
- package/neural-interface/public/shared/ui-sidepanel-state.js +131 -0
- package/neural-interface/public/shared/ui-sidepanel-tray.js +547 -0
- package/neural-interface/public/shared/ui-sidepanel-windows.js +387 -0
- package/neural-interface/public/shared/ui-skills.js +18 -32
- package/neural-interface/public/shared/ui-styleguide.js +35 -0
- package/neural-interface/public/shared/ui-sync.js +87 -0
- package/neural-interface/public/shared/ui-terminal.js +7863 -6385
- package/neural-interface/public/shared/ui-tool-updates.js +292 -0
- package/neural-interface/public/shared/ui-tooltip.js +156 -15
- package/neural-interface/public/shared/ui-tutorial-draw.js +119 -683
- package/neural-interface/public/shared/ui-tutorial-layout.js +135 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +59 -2209
- package/neural-interface/public/shared/ui-tutorial.css +102 -0
- package/neural-interface/public/shared/ui-tutorial.js +557 -1076
- package/neural-interface/public/shared/ui-update.js +420 -68
- package/neural-interface/public/shared/ui-whatsapp.js +941 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1076 -233
- package/neural-interface/public/shared/ui-workspaces.js +2 -1
- package/neural-interface/public/shared/utils.js +58 -0
- package/neural-interface/public/shared/vterm-buffer.js +15 -5
- package/neural-interface/public/shared/whatsapp/wa-phone.js +65 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +411 -0
- package/neural-interface/public/sidepanel-session.html +18 -0
- package/neural-interface/public/sw.js +10 -2
- package/neural-interface/public/synabun.png +0 -0
- package/neural-interface/public/variant/2d/graph.js +1707 -1635
- package/neural-interface/public/variant/2d/lasso.js +2 -1
- package/neural-interface/public/variant/2d/layout.js +595 -594
- package/neural-interface/public/variant/2d/main.js +557 -521
- package/neural-interface/public/variant/2d/settings-gfx.js +18 -24
- package/neural-interface/public/variant/3d/main.js +517 -500
- package/neural-interface/public/variant/3d/map-controls.js +144 -0
- package/neural-interface/public/variant/3d/map-data.js +251 -0
- package/neural-interface/public/variant/3d/map-labels.js +241 -0
- package/neural-interface/public/variant/3d/map-pick.js +90 -0
- package/neural-interface/public/variant/3d/map-renderer.js +521 -0
- package/neural-interface/public/variant/3d/map-shaders.js +158 -0
- package/neural-interface/public/variant/3d/map-view.js +618 -0
- package/neural-interface/public/vendor/three/manifest.json +3 -0
- package/neural-interface/public/vendor/three/three-0.169.0.min.js +3844 -0
- package/neural-interface/public/vendor/xterm/manifest.json +3 -0
- package/neural-interface/public/vendor/xterm/xterm-6.0.0.css +285 -0
- package/neural-interface/public/vendor/xterm/xterm-6.0.0.min.js +192 -0
- package/neural-interface/scripts/build-vendor.mjs +64 -0
- package/neural-interface/scripts/codex-protocol-fixture.mjs +83 -0
- package/neural-interface/scripts/rebuild-pty.js +39 -22
- package/neural-interface/scripts/vendor-three-entry.js +24 -0
- package/neural-interface/scripts/vendor-xterm-entry.js +8 -0
- package/neural-interface/server.js +33983 -15000
- package/neural-interface/skins/default/skin.css +90 -0
- package/neural-interface/skins/default/skin.json +8 -0
- package/neural-interface/templates/rulesets/README.md +9 -0
- package/neural-interface/templates/rulesets/claude.md +3 -0
- package/neural-interface/templates/rulesets/codex.md +2 -0
- package/neural-interface/templates/rulesets/coexistence.md +6 -0
- package/neural-interface/templates/rulesets/core.md +26 -0
- package/neural-interface/templates/rulesets/cursor.md +2 -0
- package/neural-interface/templates/rulesets/gemini.md +2 -0
- package/neural-interface/templates/rulesets/legacy-hashes.json +227 -0
- package/neural-interface/templates/rulesets/manifest.json +12 -0
- package/neural-interface/templates/rulesets/opencode.md +2 -0
- package/package.json +131 -53
- package/postinstall.js +55 -26
- package/preuninstall.js +187 -0
- package/scripts/restore-data-home-from-backup.mjs +239 -0
- package/setup.js +872 -260
- package/skills/leonardo/SKILL.md +19 -10
- package/skills/leonardo/modules/image-prompter.md +18 -12
- package/skills/leonardo/modules/video-prompter.md +19 -13
- package/skills/synabun/SKILL.md +209 -185
- package/skills/synabun/icon.png +0 -0
- package/skills/synabun/modules/audit.md +380 -374
- package/skills/synabun/modules/changelog.md +15 -6
- package/skills/synabun/modules/idea.md +148 -144
- package/skills/synabun/modules/memorize.md +13 -4
- package/skills/synabun/modules/schedule.md +198 -0
- package/skills/synabun/synabunicon.png +0 -0
- package/updater.cmd +31 -0
- package/updater.mjs +382 -0
- package/updater.sh +29 -0
- package/hooks/claude-code/test-user-learning.mjs +0 -531
- package/neural-interface/public/claude-chat.css +0 -878
- package/neural-interface/public/claude-chat.html +0 -92
- package/neural-interface/public/claude-chat.js +0 -1168
- package/neural-interface/public/index-legacy.html +0 -14677
- package/neural-interface/public/index2d-legacy.html +0 -8193
- package/neural-interface/public/shared/html-term-renderer.js +0 -1022
- package/neural-interface/public/variant/3d/background.js +0 -884
- package/neural-interface/public/variant/3d/camera.js +0 -661
- package/neural-interface/public/variant/3d/gfx.js +0 -116
- package/neural-interface/public/variant/3d/graph.js +0 -2399
- package/neural-interface/public/variant/3d/settings-gfx.js +0 -228
- package/neural-interface/templates/CLAUDE-template.md +0 -211
|
@@ -0,0 +1,955 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// OpenCode V2 — sidepanel WebSocket requests as pure functions
|
|
3
|
+
//
|
|
4
|
+
// server.js owns the socket, the isolated serves and the native-run guards; a
|
|
5
|
+
// request body lives here as `(msg, deps) => reply` so node:test can drive it
|
|
6
|
+
// with a fake client. `handleOpencodeV2Request` returns false for a type it
|
|
7
|
+
// does not own, and the caller falls through to its own switch.
|
|
8
|
+
//
|
|
9
|
+
// deps (all supplied by handleOpencodeV2Ws):
|
|
10
|
+
// send(data) write one JSON message to this socket
|
|
11
|
+
// shared the shared-serve client (opencode-v2-client).
|
|
12
|
+
// SDK calls added for the panel are under
|
|
13
|
+
// `client.extra.<group>.<method>`
|
|
14
|
+
// bound(sessionId) the serve currently hosting the session's
|
|
15
|
+
// turn, else the shared client; never spawns
|
|
16
|
+
// turn(sessionId, mcpProfile) the session's dedicated serve; may spawn it
|
|
17
|
+
// proxy(method, path, body, timeoutMs, baseUrl) raw HTTP to a serve
|
|
18
|
+
// baseUrlFor(sessionId) base URL of the serve hosting the session
|
|
19
|
+
// directoryQuery(cwd) `?directory=…` or ''
|
|
20
|
+
// isTurnActive(sessionId) true while a turn is running or starting
|
|
21
|
+
// turnScope(sessionId) the bookkeeping message:send does around a
|
|
22
|
+
// turn: aborts the previous prompt of this
|
|
23
|
+
// socket, marks the session active. Returns
|
|
24
|
+
// { signal, end() }; end() must always run
|
|
25
|
+
// persistMcp(name, config) write one MCP server into the OpenCode
|
|
26
|
+
// config file; starts nothing. Throws on failure
|
|
27
|
+
//
|
|
28
|
+
// The panel must work against a server that predates a request type, so the
|
|
29
|
+
// server says what it understands: `capabilities` in init:result and one
|
|
30
|
+
// `capabilities` message after identify. The panel shows a feature that needs
|
|
31
|
+
// a type only when that type is listed.
|
|
32
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
import { readFileSync } from 'node:fs';
|
|
35
|
+
import { dirname, join } from 'node:path';
|
|
36
|
+
import { fileURLToPath } from 'node:url';
|
|
37
|
+
import { compactOrSummarize, lastModelOf } from './opencode-v2-client.js';
|
|
38
|
+
|
|
39
|
+
export { lastModelOf };
|
|
40
|
+
|
|
41
|
+
// Types answered by the switch in server.js.
|
|
42
|
+
export const OPENCODE_V2_WS_INLINE_TYPES = Object.freeze([
|
|
43
|
+
'init', 'identify',
|
|
44
|
+
'session:list', 'session:create', 'session:get', 'session:update', 'session:delete', 'session:messages',
|
|
45
|
+
'mcp:profile:get', 'mcp:profile:set',
|
|
46
|
+
'message:send', 'message:abort',
|
|
47
|
+
'question:list', 'question:reject',
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
const failure = (status, error, extra = {}) => ({ ok: false, status, error, ...extra });
|
|
51
|
+
|
|
52
|
+
const sessionIdOf = (msg) => (typeof msg?.sessionId === 'string' ? msg.sessionId.trim() : '');
|
|
53
|
+
// The id every per-session resolver gets: the canonical one, or nothing.
|
|
54
|
+
const sessionKeyOf = (msg) => sessionIdOf(msg) || undefined;
|
|
55
|
+
const directoryOf = (msg) => (typeof msg?.cwd === 'string' && msg.cwd.trim() ? msg.cwd.trim() : undefined);
|
|
56
|
+
|
|
57
|
+
// ── One session id per request ──────────────────────────────────────────────
|
|
58
|
+
// The native-run and history guards in server.js look a session up by id, and
|
|
59
|
+
// so does every SDK call. They must look up the same string: an id that is
|
|
60
|
+
// trimmed for the SDK but not for the guard (" ses_x ") walks past the guard.
|
|
61
|
+
// So the id is made canonical once, in place, before anything reads it, and an
|
|
62
|
+
// id that is not a plain token is refused outright.
|
|
63
|
+
const SESSION_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Canonicalise `msg.sessionId` in place. Returns null when the message may go
|
|
67
|
+
* on, or the failure to answer with. An absent or empty id becomes `undefined`.
|
|
68
|
+
* A `body` (session:create / session:update) loses any session id of its own:
|
|
69
|
+
* the one that was checked is the only one a call may use.
|
|
70
|
+
*/
|
|
71
|
+
export function canonicalizeOpencodeV2Message(msg) {
|
|
72
|
+
if (!msg || typeof msg !== 'object') return failure(400, 'malformed request');
|
|
73
|
+
const raw = msg.sessionId;
|
|
74
|
+
if (raw === undefined || raw === null) {
|
|
75
|
+
msg.sessionId = undefined;
|
|
76
|
+
} else if (typeof raw !== 'string') {
|
|
77
|
+
return failure(400, 'sessionId must be a string');
|
|
78
|
+
} else {
|
|
79
|
+
const trimmed = raw.trim();
|
|
80
|
+
if (!trimmed) msg.sessionId = undefined;
|
|
81
|
+
else if (!SESSION_ID_RE.test(trimmed)) return failure(400, 'sessionId is not a valid session id');
|
|
82
|
+
else msg.sessionId = trimmed;
|
|
83
|
+
}
|
|
84
|
+
if (msg.body && typeof msg.body === 'object' && !Array.isArray(msg.body)) {
|
|
85
|
+
delete msg.body.sessionID;
|
|
86
|
+
delete msg.body.sessionId;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Everything that must hold before a request is answered, in one place so it
|
|
93
|
+
* can be tested: a canonical session id, no write while history is being
|
|
94
|
+
* cleared, and the native-automation ownership rules. Returns null to let the
|
|
95
|
+
* request through, or `{ status, error }`.
|
|
96
|
+
* ctx: { historyClearing, historyWriteTypes, nativeMutationTypes,
|
|
97
|
+
* protectedRunFor(sessionId), ownsRun(run) }
|
|
98
|
+
*/
|
|
99
|
+
export function guardOpencodeV2Request(msg, ctx = {}) {
|
|
100
|
+
const malformed = canonicalizeOpencodeV2Message(msg);
|
|
101
|
+
if (malformed) return { status: malformed.status, error: malformed.error };
|
|
102
|
+
const type = msg.type;
|
|
103
|
+
if (ctx.historyClearing && ctx.historyWriteTypes?.has(type)) {
|
|
104
|
+
return { status: 409, error: 'OpenCode history is being cleared' };
|
|
105
|
+
}
|
|
106
|
+
const protectedRun = msg.sessionId ? ctx.protectedRunFor?.(msg.sessionId) : null;
|
|
107
|
+
if (protectedRun && !ctx.ownsRun?.(protectedRun)) {
|
|
108
|
+
return { status: 409, error: 'Native automation session is owned by another window' };
|
|
109
|
+
}
|
|
110
|
+
if (protectedRun && ctx.nativeMutationTypes?.has(type)) {
|
|
111
|
+
return { status: 409, error: 'Stop the native automation before modifying its session' };
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// v2.session.context answers `{ data: [...] }` since 1.18; older serves sent the
|
|
117
|
+
// bare array.
|
|
118
|
+
export function contextRows(data) {
|
|
119
|
+
if (Array.isArray(data)) return data;
|
|
120
|
+
if (Array.isArray(data?.data)) return data.data;
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// session.status answers a map of the sessions that are NOT idle on that serve.
|
|
125
|
+
export function statusForSession(map, sessionId) {
|
|
126
|
+
const entry = map && typeof map === 'object' ? map[sessionId] : null;
|
|
127
|
+
return entry && typeof entry.type === 'string' ? entry : { type: 'idle' };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function modelOf(value) {
|
|
131
|
+
const providerID = typeof value?.providerID === 'string' ? value.providerID.trim() : '';
|
|
132
|
+
const modelID = typeof value?.modelID === 'string' ? value.modelID.trim() : '';
|
|
133
|
+
return providerID && modelID ? { providerID, modelID } : null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// session.compact with the session.summarize fallback (see compactOrSummarize).
|
|
137
|
+
async function compactSession(msg, deps) {
|
|
138
|
+
const client = await deps.turn(sessionKeyOf(msg), msg.mcpProfile);
|
|
139
|
+
try {
|
|
140
|
+
return await compactOrSummarize(client, {
|
|
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
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const PERMISSION_REPLIES = new Set(['once', 'always', 'reject']);
|
|
151
|
+
|
|
152
|
+
async function permissionReply(msg, deps) {
|
|
153
|
+
const requestID = String(msg.permissionId || msg.requestId || '').trim();
|
|
154
|
+
const reply = String(msg.response || '');
|
|
155
|
+
if (!requestID) return failure(400, 'permission id is required');
|
|
156
|
+
if (!PERMISSION_REPLIES.has(reply)) return failure(400, `unknown permission reply: ${reply || '(empty)'}`);
|
|
157
|
+
// The rejection reason is shown to the model; only a rejection carries one.
|
|
158
|
+
const message = reply === 'reject' && typeof msg.message === 'string' && msg.message.trim()
|
|
159
|
+
? msg.message.trim().slice(0, 2000)
|
|
160
|
+
: undefined;
|
|
161
|
+
const client = deps.bound(sessionKeyOf(msg));
|
|
162
|
+
const directory = directoryOf(msg);
|
|
163
|
+
try {
|
|
164
|
+
const r = await client.permission.reply({ requestID, reply, message, directory });
|
|
165
|
+
return { status: r.status, data: r.data };
|
|
166
|
+
} catch (err) {
|
|
167
|
+
// A request raised under the serve's default scope does not match a reply
|
|
168
|
+
// sent with ?directory=. One retry without it; nothing else is a real route
|
|
169
|
+
// (the old /respond and bare-id fallbacks answered with the web UI's HTML).
|
|
170
|
+
if (err?.status !== 404 || !directory) throw err;
|
|
171
|
+
const r = await client.permission.reply({ requestID, reply, message });
|
|
172
|
+
return { status: r.status, data: r.data };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function questionReply(msg, deps) {
|
|
177
|
+
const requestID = String(msg.requestId || msg.requestID || '').trim();
|
|
178
|
+
if (!requestID) return failure(400, 'question request id is required');
|
|
179
|
+
const body = { answers: Array.isArray(msg.answers) ? msg.answers : [] };
|
|
180
|
+
const path = `/question/${encodeURIComponent(requestID)}/reply${deps.directoryQuery(msg.cwd)}`;
|
|
181
|
+
const r = await deps.proxy('POST', path, body, 10000, deps.baseUrlFor(sessionKeyOf(msg)));
|
|
182
|
+
// Any unknown route on `opencode serve` answers 200 with the web UI; a reply
|
|
183
|
+
// that comes back as a document did not reach the question API.
|
|
184
|
+
if (typeof r.data === 'string' && /^\s*<(?:!doctype|html)/i.test(r.data)) {
|
|
185
|
+
return failure(502, 'OpenCode did not accept the question reply');
|
|
186
|
+
}
|
|
187
|
+
return { status: r.status, data: r.data };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function permissionList(msg, deps) {
|
|
191
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.permission.list({ directory: directoryOf(msg) });
|
|
192
|
+
return { status: r.status, data: Array.isArray(r.data) ? r.data : [] };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Rules OpenCode saved from "Always allow" (v2.permission.saved). They are
|
|
196
|
+
// stored per project, so the shared serve answers.
|
|
197
|
+
async function permissionSavedList(msg, deps) {
|
|
198
|
+
const projectID = typeof msg.projectID === 'string' && msg.projectID.trim() ? msg.projectID.trim() : '';
|
|
199
|
+
const query = projectID ? `?projectID=${encodeURIComponent(projectID)}` : '';
|
|
200
|
+
const r = await deps.proxy('GET', `/api/permission/saved${query}`, null, 10000, deps.baseUrlFor(null));
|
|
201
|
+
if (r.status >= 400) return failure(r.status, proxyErrorText(r.data, 'Could not list saved approvals'));
|
|
202
|
+
const rows = Array.isArray(r.data?.data) ? r.data.data : (Array.isArray(r.data) ? r.data : []);
|
|
203
|
+
return { status: r.status, data: rows };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function permissionSavedRemove(msg, deps) {
|
|
207
|
+
const id = String(msg.savedId || '').trim();
|
|
208
|
+
if (!id) return failure(400, 'saved approval id is required');
|
|
209
|
+
const r = await deps.proxy('DELETE', `/api/permission/saved/${encodeURIComponent(id)}`, null, 10000, deps.baseUrlFor(null));
|
|
210
|
+
if (r.status >= 400) return failure(r.status, proxyErrorText(r.data, 'Could not remove the saved approval'));
|
|
211
|
+
return { status: r.status, data: true };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// A raw proxy answer is the parsed body: `{ name, data: { message } }`,
|
|
215
|
+
// `{ _tag, message }` or text.
|
|
216
|
+
function proxyErrorText(body, fallback) {
|
|
217
|
+
if (typeof body === 'string') return /^\s*</.test(body) ? fallback : (body.trim().slice(0, 500) || fallback);
|
|
218
|
+
return body?.message || body?.data?.message || body?.error || fallback;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The model's todo list for the session (the todowrite tool keeps it).
|
|
222
|
+
async function sessionTodo(msg, deps) {
|
|
223
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.session.todo({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
224
|
+
return { status: r.status, data: Array.isArray(r.data) ? r.data : [] };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function sessionStatus(msg, deps) {
|
|
228
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.session.status({ directory: directoryOf(msg) });
|
|
229
|
+
return { status: r.status, data: { status: statusForSession(r.data, sessionIdOf(msg)) } };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// What the relay forwards to panels. OpenCode 1.18 mirrors every bus event as
|
|
233
|
+
// a `sync` envelope ({ type: 'sync', syncEvent }); the panel acts on the bus
|
|
234
|
+
// event itself, so the mirror is dropped. Everything else passes.
|
|
235
|
+
export function shouldRelayOpencodeV2Message(data) {
|
|
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.
|
|
243
|
+
export function buildOpencodeRuntimeMcpConfig(config = {}) {
|
|
244
|
+
if (config.type === 'local' || config.type === 'remote') return { ...config };
|
|
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
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ── Session list (read straight from OpenCode's SQLite) ─────────────────────
|
|
268
|
+
// The SDK's session.list only answers for the serve's own project; the panel
|
|
269
|
+
// lists every project, so server.js reads the `session` table. The query and
|
|
270
|
+
// the row mapping live here so they can be tested against a real table.
|
|
271
|
+
export const SESSION_LIST_MAX = 500;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* options: { search, archived, roots, limit }
|
|
275
|
+
* archived false (default) → live sessions; true → archived ones only
|
|
276
|
+
* roots true → no sub-agent sessions (parent_id IS NULL)
|
|
277
|
+
* search case-insensitive match on title, slug or directory
|
|
278
|
+
* Un-archiving writes time_archived = 0, so "live" is NULL or 0.
|
|
279
|
+
*/
|
|
280
|
+
export function buildSessionListQuery(options = {}) {
|
|
281
|
+
const where = [];
|
|
282
|
+
const params = [];
|
|
283
|
+
where.push(options.archived === true
|
|
284
|
+
? '(s.time_archived IS NOT NULL AND s.time_archived != 0)'
|
|
285
|
+
: '(s.time_archived IS NULL OR s.time_archived = 0)');
|
|
286
|
+
if (options.roots === true) where.push('s.parent_id IS NULL');
|
|
287
|
+
const search = typeof options.search === 'string' ? options.search.trim().slice(0, 200) : '';
|
|
288
|
+
if (search) {
|
|
289
|
+
const like = `%${search.replace(/[\\%_]/g, (ch) => `\\${ch}`)}%`;
|
|
290
|
+
where.push("(s.title LIKE ? ESCAPE '\\' OR s.slug LIKE ? ESCAPE '\\' OR s.directory LIKE ? ESCAPE '\\')");
|
|
291
|
+
params.push(like, like, like);
|
|
292
|
+
}
|
|
293
|
+
const requested = Number(options.limit);
|
|
294
|
+
const limit = Number.isInteger(requested) && requested > 0 ? Math.min(requested, SESSION_LIST_MAX) : null;
|
|
295
|
+
const sql = `
|
|
296
|
+
SELECT s.id, s.title, s.directory, s.slug, s.project_id, s.parent_id, s.share_url,
|
|
297
|
+
s.time_created, s.time_updated, s.time_archived,
|
|
298
|
+
(SELECT COUNT(*) FROM message m WHERE m.session_id = s.id) AS message_count
|
|
299
|
+
FROM session s
|
|
300
|
+
WHERE ${where.join(' AND ')}
|
|
301
|
+
ORDER BY s.time_updated DESC${limit ? '\n LIMIT ?' : ''}
|
|
302
|
+
`;
|
|
303
|
+
if (limit) params.push(limit);
|
|
304
|
+
return { sql, params };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const epochMs = (value) => (value ? Math.floor(new Date(value).getTime()) || 0 : 0);
|
|
308
|
+
|
|
309
|
+
export function mapSessionListRow(row) {
|
|
310
|
+
const out = {
|
|
311
|
+
id: row.id,
|
|
312
|
+
title: row.title || '',
|
|
313
|
+
slug: row.slug || '',
|
|
314
|
+
directory: row.directory || '',
|
|
315
|
+
projectID: row.project_id || '',
|
|
316
|
+
messageCount: row.message_count || 0,
|
|
317
|
+
time: { created: epochMs(row.time_created), updated: epochMs(row.time_updated) },
|
|
318
|
+
};
|
|
319
|
+
if (row.parent_id) out.parentID = row.parent_id;
|
|
320
|
+
if (row.share_url) out.share = { url: row.share_url };
|
|
321
|
+
const archived = epochMs(row.time_archived);
|
|
322
|
+
if (archived) out.time.archived = archived;
|
|
323
|
+
return out;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ── Session lifecycle (revert, fork, share, children, delete message) ───────
|
|
327
|
+
|
|
328
|
+
const messageIdOf = (msg) => (typeof msg?.messageID === 'string' && msg.messageID.trim()
|
|
329
|
+
? msg.messageID.trim()
|
|
330
|
+
: (typeof msg?.messageId === 'string' ? msg.messageId.trim() : ''));
|
|
331
|
+
|
|
332
|
+
// Reverting or deleting under a running turn would pull the transcript out
|
|
333
|
+
// from under the model.
|
|
334
|
+
function refuseWhileRunning(msg, deps, what) {
|
|
335
|
+
return deps.isTurnActive?.(sessionIdOf(msg))
|
|
336
|
+
? failure(409, `Stop the running turn before you ${what}.`)
|
|
337
|
+
: null;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async function sessionRevert(msg, deps) {
|
|
341
|
+
const busy = refuseWhileRunning(msg, deps, 'revert');
|
|
342
|
+
if (busy) return busy;
|
|
343
|
+
const messageID = messageIdOf(msg);
|
|
344
|
+
if (!messageID) return failure(400, 'messageID is required');
|
|
345
|
+
const partID = typeof msg.partID === 'string' && msg.partID.trim() ? msg.partID.trim() : undefined;
|
|
346
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.session.revert({
|
|
347
|
+
sessionID: sessionIdOf(msg), messageID, partID, directory: directoryOf(msg),
|
|
348
|
+
});
|
|
349
|
+
return { status: r.status, data: r.data };
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async function sessionUnrevert(msg, deps) {
|
|
353
|
+
const busy = refuseWhileRunning(msg, deps, 'restore');
|
|
354
|
+
if (busy) return busy;
|
|
355
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.session.unrevert({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
356
|
+
return { status: r.status, data: r.data };
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function sessionFork(msg, deps) {
|
|
360
|
+
const r = await deps.shared.extra.session.fork({
|
|
361
|
+
sessionID: sessionIdOf(msg), messageID: messageIdOf(msg) || undefined, directory: directoryOf(msg),
|
|
362
|
+
});
|
|
363
|
+
return { status: r.status, data: r.data };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async function sessionChildren(msg, deps) {
|
|
367
|
+
const r = await deps.shared.extra.session.children({ sessionID: sessionIdOf(msg), directory: directoryOf(msg) });
|
|
368
|
+
return { status: r.status, data: Array.isArray(r.data) ? r.data : [] };
|
|
369
|
+
}
|
|
370
|
+
|
|
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
|
+
// ── Composer: slash commands, shell, file search ────────────────────────────
|
|
414
|
+
|
|
415
|
+
/** What the slash menu needs of a Command; the template can be 16 KB and is not sent. */
|
|
416
|
+
export function commandRow(cmd) {
|
|
417
|
+
if (!cmd || typeof cmd.name !== 'string' || !cmd.name) return null;
|
|
418
|
+
const out = { name: cmd.name, description: typeof cmd.description === 'string' ? cmd.description : '' };
|
|
419
|
+
out.source = ['command', 'mcp', 'skill'].includes(cmd.source) ? cmd.source : 'command';
|
|
420
|
+
if (typeof cmd.agent === 'string' && cmd.agent) out.agent = cmd.agent;
|
|
421
|
+
if (cmd.subtask === true) out.subtask = true;
|
|
422
|
+
if (Array.isArray(cmd.hints) && cmd.hints.length) out.hints = cmd.hints.filter((h) => typeof h === 'string').slice(0, 8);
|
|
423
|
+
return out;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Commands depend on the project (.opencode/command, project skills), so the
|
|
427
|
+
// list is asked for the session's directory.
|
|
428
|
+
async function commandList(msg, deps) {
|
|
429
|
+
const r = await deps.shared.extra.command.list({ directory: directoryOf(msg) });
|
|
430
|
+
return { status: r.status, data: (Array.isArray(r.data) ? r.data : []).map(commandRow).filter(Boolean) };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// A model string for session.command / session.shell: `provider/model`.
|
|
434
|
+
function modelRef(value) {
|
|
435
|
+
const model = modelOf(value);
|
|
436
|
+
return model ? `${model.providerID}/${model.modelID}` : undefined;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Run something that occupies the session like a prompt does: on the
|
|
440
|
+
// session's dedicated serve, inside the same turn bookkeeping as message:send.
|
|
441
|
+
async function withTurn(msg, deps, run) {
|
|
442
|
+
const scope = deps.turnScope(sessionIdOf(msg));
|
|
443
|
+
try {
|
|
444
|
+
const client = await deps.turn(sessionKeyOf(msg), msg.mcpProfile);
|
|
445
|
+
const r = await run(client, scope.signal ? { signal: scope.signal } : undefined);
|
|
446
|
+
return { status: r.status, data: r.data };
|
|
447
|
+
} finally {
|
|
448
|
+
scope.end();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// session.command: run a slash command (a command file, a skill, an MCP prompt).
|
|
453
|
+
async function commandRun(msg, deps) {
|
|
454
|
+
const command = typeof msg.command === 'string' ? msg.command.trim().replace(/^\//, '') : '';
|
|
455
|
+
if (!command) return failure(400, 'command is required');
|
|
456
|
+
const parts = Array.isArray(msg.parts) && msg.parts.length ? msg.parts : undefined;
|
|
457
|
+
return withTurn(msg, deps, (client, options) => client.extra.session.command({
|
|
458
|
+
sessionID: sessionIdOf(msg),
|
|
459
|
+
command,
|
|
460
|
+
arguments: typeof msg.arguments === 'string' ? msg.arguments : '',
|
|
461
|
+
agent: typeof msg.agent === 'string' && msg.agent ? msg.agent : undefined,
|
|
462
|
+
model: modelRef(msg.model),
|
|
463
|
+
variant: typeof msg.variant === 'string' && msg.variant ? msg.variant : undefined,
|
|
464
|
+
parts,
|
|
465
|
+
directory: directoryOf(msg),
|
|
466
|
+
}, options));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// session.shell: run one shell command in the session, with no model call.
|
|
470
|
+
// The panel sends this only from its shell mode, which nothing but the user
|
|
471
|
+
// typing "!" into an empty composer can enter.
|
|
472
|
+
async function sessionShell(msg, deps) {
|
|
473
|
+
const command = typeof msg.command === 'string' ? msg.command.trim() : '';
|
|
474
|
+
if (!command) return failure(400, 'command is required');
|
|
475
|
+
if (command.length > 20000) return failure(400, 'command is too long');
|
|
476
|
+
return withTurn(msg, deps, (client, options) => client.extra.session.shell({
|
|
477
|
+
sessionID: sessionIdOf(msg),
|
|
478
|
+
command,
|
|
479
|
+
agent: typeof msg.agent === 'string' && msg.agent ? msg.agent : 'build',
|
|
480
|
+
model: modelOf(msg.model) || undefined,
|
|
481
|
+
directory: directoryOf(msg),
|
|
482
|
+
}, options));
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export const FIND_FILES_LIMIT = 50;
|
|
486
|
+
|
|
487
|
+
// find.files: fuzzy file (and directory) search for @ mentions.
|
|
488
|
+
async function findFiles(msg, deps) {
|
|
489
|
+
const query = typeof msg.query === 'string' ? msg.query.trim().slice(0, 200) : '';
|
|
490
|
+
const r = await deps.shared.extra.find.files({
|
|
491
|
+
query,
|
|
492
|
+
dirs: msg.dirs === false ? 'false' : 'true',
|
|
493
|
+
limit: FIND_FILES_LIMIT,
|
|
494
|
+
directory: directoryOf(msg),
|
|
495
|
+
});
|
|
496
|
+
const rows = (Array.isArray(r.data) ? r.data : []).filter((p) => typeof p === 'string' && p);
|
|
497
|
+
return { status: r.status, data: rows.slice(0, FIND_FILES_LIMIT) };
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// A file:// URI as a filesystem path; anything else is not a project file.
|
|
501
|
+
function pathOfFileUri(uri) {
|
|
502
|
+
if (typeof uri !== 'string' || !uri.startsWith('file://')) return '';
|
|
503
|
+
try { return decodeURIComponent(new URL(uri).pathname); } catch { return ''; }
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** A workspace symbol as the @ picker takes it: `{ name, kind, path, range }`. */
|
|
507
|
+
export function symbolRow(symbol) {
|
|
508
|
+
const name = typeof symbol?.name === 'string' ? symbol.name.trim() : '';
|
|
509
|
+
const path = pathOfFileUri(symbol?.location?.uri);
|
|
510
|
+
if (!name || !path) return null;
|
|
511
|
+
const point = (p) => ({ line: Number(p?.line) || 0, character: Number(p?.character) || 0 });
|
|
512
|
+
const range = symbol.location.range || {};
|
|
513
|
+
return {
|
|
514
|
+
name: name.slice(0, 200),
|
|
515
|
+
kind: Number(symbol.kind) || 0,
|
|
516
|
+
path,
|
|
517
|
+
range: { start: point(range.start), end: point(range.end) },
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// find.symbols: workspace symbols from the language servers of the serve that
|
|
522
|
+
// runs this session (they start when the session reads a file of that language).
|
|
523
|
+
async function findSymbols(msg, deps) {
|
|
524
|
+
const query = typeof msg.query === 'string' ? msg.query.trim().slice(0, 200) : '';
|
|
525
|
+
if (!query) return { status: 200, data: [] };
|
|
526
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.find.symbols({ query, directory: directoryOf(msg) });
|
|
527
|
+
const rows = (Array.isArray(r.data) ? r.data : []).map(symbolRow).filter(Boolean);
|
|
528
|
+
return { status: r.status, data: rows.slice(0, FIND_FILES_LIMIT) };
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export const RESOURCE_LIST_LIMIT = 200;
|
|
532
|
+
|
|
533
|
+
/** experimental.resource.list answers `{ [key]: McpResource }`; the picker takes rows. */
|
|
534
|
+
export function resourceRows(map) {
|
|
535
|
+
if (!map || typeof map !== 'object' || Array.isArray(map)) return [];
|
|
536
|
+
return Object.values(map)
|
|
537
|
+
.filter((r) => r && typeof r.uri === 'string' && r.uri && typeof r.client === 'string' && r.client)
|
|
538
|
+
.map((r) => ({
|
|
539
|
+
name: String(r.name || r.uri).slice(0, 200),
|
|
540
|
+
uri: r.uri,
|
|
541
|
+
client: r.client,
|
|
542
|
+
description: typeof r.description === 'string' ? r.description.slice(0, 300) : '',
|
|
543
|
+
mimeType: typeof r.mimeType === 'string' ? r.mimeType : '',
|
|
544
|
+
}))
|
|
545
|
+
.sort((a, b) => a.client.localeCompare(b.client) || a.name.localeCompare(b.name))
|
|
546
|
+
.slice(0, RESOURCE_LIST_LIMIT);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Resources of the MCP servers connected to the serve hosting this session.
|
|
550
|
+
async function resourceList(msg, deps) {
|
|
551
|
+
const r = await deps.proxy('GET', `/experimental/resource${deps.directoryQuery(msg.cwd)}`, null, 10000, deps.baseUrlFor(sessionKeyOf(msg)));
|
|
552
|
+
if (r.status >= 400) return failure(r.status, proxyErrorText(r.data, 'Could not list MCP resources'));
|
|
553
|
+
return { status: r.status, data: resourceRows(r.data) };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/** v2.reference.list answers `{ location, data: ReferenceInfo[] }`; hidden ones are left out. */
|
|
557
|
+
export function referenceRows(body) {
|
|
558
|
+
const list = Array.isArray(body?.data) ? body.data : (Array.isArray(body) ? body : []);
|
|
559
|
+
return list
|
|
560
|
+
.filter((r) => r && typeof r.name === 'string' && r.name && r.hidden !== true)
|
|
561
|
+
.map((r) => ({
|
|
562
|
+
name: r.name,
|
|
563
|
+
path: typeof r.path === 'string' ? r.path : '',
|
|
564
|
+
description: typeof r.description === 'string' ? r.description : '',
|
|
565
|
+
}));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// References live under /api and take the directory as a location.
|
|
569
|
+
function referencePath(directory) {
|
|
570
|
+
return directory
|
|
571
|
+
? `/api/reference?directory=${encodeURIComponent(directory)}&location%5Bdirectory%5D=${encodeURIComponent(directory)}`
|
|
572
|
+
: '/api/reference';
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async function referenceList(msg, deps) {
|
|
576
|
+
const r = await deps.proxy('GET', referencePath(directoryOf(msg)), null, 10000, deps.baseUrlFor(sessionKeyOf(msg)));
|
|
577
|
+
if (r.status >= 400 || typeof r.data === 'string') return { status: 200, data: [] };
|
|
578
|
+
return { status: r.status, data: referenceRows(r.data) };
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** What the agent toggle needs of an Agent; the prompt and permission ruleset stay behind. */
|
|
582
|
+
export function agentRow(agent) {
|
|
583
|
+
if (!agent || typeof agent.name !== 'string' || !agent.name) return null;
|
|
584
|
+
return {
|
|
585
|
+
name: agent.name,
|
|
586
|
+
mode: typeof agent.mode === 'string' ? agent.mode : '',
|
|
587
|
+
description: typeof agent.description === 'string' ? agent.description : '',
|
|
588
|
+
hidden: agent.hidden === true,
|
|
589
|
+
color: typeof agent.color === 'string' ? agent.color : '',
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Agents depend on the project (.opencode/agent), so they are asked per directory.
|
|
594
|
+
async function agentList(msg, deps) {
|
|
595
|
+
const r = await deps.shared.extra.app.agents({ directory: directoryOf(msg) });
|
|
596
|
+
return { status: r.status, data: (Array.isArray(r.data) ? r.data : []).map(agentRow).filter(Boolean) };
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// ── Changes and VCS ─────────────────────────────────────────────────────────
|
|
600
|
+
|
|
601
|
+
export const FILE_DIFF_MAX_FILES = 300;
|
|
602
|
+
export const FILE_DIFF_MAX_PATCH_CHARS = 200_000;
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* File diffs as the panel takes them: `{ file, patch, additions, deletions,
|
|
606
|
+
* status }`. `file` and `patch` are optional in the SDK (SnapshotFileDiff);
|
|
607
|
+
* a huge patch is cut and marked so one generated file cannot flood the socket.
|
|
608
|
+
*/
|
|
609
|
+
export function capFileDiffs(list) {
|
|
610
|
+
const rows = (Array.isArray(list) ? list : []).filter((row) => row && typeof row === 'object');
|
|
611
|
+
return rows.slice(0, FILE_DIFF_MAX_FILES).map((row) => {
|
|
612
|
+
const patch = typeof row.patch === 'string' ? row.patch : '';
|
|
613
|
+
const out = {
|
|
614
|
+
file: typeof row.file === 'string' ? row.file : '',
|
|
615
|
+
patch: patch.length > FILE_DIFF_MAX_PATCH_CHARS ? patch.slice(0, FILE_DIFF_MAX_PATCH_CHARS) : patch,
|
|
616
|
+
additions: Number(row.additions) || 0,
|
|
617
|
+
deletions: Number(row.deletions) || 0,
|
|
618
|
+
};
|
|
619
|
+
if (typeof row.status === 'string') out.status = row.status;
|
|
620
|
+
if (patch.length > FILE_DIFF_MAX_PATCH_CHARS) out.patchTruncated = true;
|
|
621
|
+
return out;
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// What the session changed (snapshot based), optionally only one message's turn.
|
|
626
|
+
async function sessionDiff(msg, deps) {
|
|
627
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.session.diff({
|
|
628
|
+
sessionID: sessionIdOf(msg), messageID: messageIdOf(msg) || undefined, directory: directoryOf(msg),
|
|
629
|
+
});
|
|
630
|
+
return { status: r.status, data: capFileDiffs(r.data) };
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async function vcsGet(msg, deps) {
|
|
634
|
+
const r = await deps.shared.extra.vcs.get({ directory: directoryOf(msg) });
|
|
635
|
+
return { status: r.status, data: { branch: r.data?.branch || '', defaultBranch: r.data?.default_branch || '' } };
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
async function vcsStatus(msg, deps) {
|
|
639
|
+
const r = await deps.shared.extra.vcs.status({ directory: directoryOf(msg) });
|
|
640
|
+
return { status: r.status, data: capFileDiffs(r.data).map(({ patch, ...row }) => row) };
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// mode 'git': the working tree against HEAD. 'branch': against the default branch.
|
|
644
|
+
async function vcsDiff(msg, deps) {
|
|
645
|
+
const mode = msg.mode === 'branch' ? 'branch' : 'git';
|
|
646
|
+
const r = await deps.shared.extra.vcs.diff({ mode, directory: directoryOf(msg) });
|
|
647
|
+
return { status: r.status, data: capFileDiffs(r.data) };
|
|
648
|
+
}
|
|
649
|
+
|
|
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
|
+
// ── Environment: MCP servers, LSP, formatters ───────────────────────────────
|
|
700
|
+
|
|
701
|
+
// SynaBun's own MCP entry is pinned by the runtime (profile, terminal identity,
|
|
702
|
+
// browser ownership): the panel shows it but may not switch it.
|
|
703
|
+
export const MANAGED_MCP_NAMES = Object.freeze(['SynaBun']);
|
|
704
|
+
const isManagedMcpName = (name) => MANAGED_MCP_NAMES.some((managed) => managed.toLowerCase() === String(name).trim().toLowerCase());
|
|
705
|
+
|
|
706
|
+
const MCP_STATUSES = new Set(['connected', 'disabled', 'failed', 'needs_auth', 'needs_client_registration']);
|
|
707
|
+
|
|
708
|
+
/** mcp.status answers `{ [name]: McpStatus }`; the panel takes sorted rows. */
|
|
709
|
+
export function mcpRows(statusMap) {
|
|
710
|
+
const map = statusMap && typeof statusMap === 'object' && !Array.isArray(statusMap) ? statusMap : {};
|
|
711
|
+
return Object.entries(map)
|
|
712
|
+
.map(([name, value]) => {
|
|
713
|
+
const row = {
|
|
714
|
+
name,
|
|
715
|
+
status: MCP_STATUSES.has(value?.status) ? value.status : 'failed',
|
|
716
|
+
managed: MANAGED_MCP_NAMES.includes(name),
|
|
717
|
+
};
|
|
718
|
+
if (typeof value?.error === 'string' && value.error) row.error = value.error.slice(0, 500);
|
|
719
|
+
return row;
|
|
720
|
+
})
|
|
721
|
+
.sort((a, b) => Number(b.managed) - Number(a.managed) || a.name.localeCompare(b.name));
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const mcpNameOf = (msg) => (typeof msg?.name === 'string' ? msg.name.trim() : '');
|
|
725
|
+
|
|
726
|
+
// The MCP servers of the serve that runs this session's turns.
|
|
727
|
+
async function mcpStatus(msg, deps) {
|
|
728
|
+
const r = await deps.bound(sessionKeyOf(msg)).mcp.status({ directory: directoryOf(msg) });
|
|
729
|
+
return { status: r.status, data: mcpRows(r.data) };
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
async function mcpSwitch(msg, deps, connect) {
|
|
733
|
+
const name = mcpNameOf(msg);
|
|
734
|
+
if (!name) return failure(400, 'MCP server name is required');
|
|
735
|
+
if (isManagedMcpName(name)) return failure(403, `${name} is managed by SynaBun and cannot be switched from the panel.`);
|
|
736
|
+
const client = deps.bound(sessionKeyOf(msg));
|
|
737
|
+
const params = { name, directory: directoryOf(msg) };
|
|
738
|
+
const r = connect ? await client.mcp.connect(params) : await client.mcp.disconnect(params);
|
|
739
|
+
const after = await client.mcp.status({ directory: directoryOf(msg) }).catch(() => null);
|
|
740
|
+
return { status: r.status, data: after ? mcpRows(after.data) : [] };
|
|
741
|
+
}
|
|
742
|
+
|
|
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
|
+
|
|
757
|
+
const MCP_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
758
|
+
const stringMap = (value) => value && typeof value === 'object' && !Array.isArray(value)
|
|
759
|
+
&& Object.values(value).every((v) => typeof v === 'string');
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* A server the user typed into the panel, as OpenCode's `POST /mcp` takes it.
|
|
763
|
+
* `{ command, args?, env? }` → McpLocalConfig, `{ url, headers? }` → McpRemoteConfig.
|
|
764
|
+
* Resolves `{ ok: true, config }` or `{ ok: false, error }`.
|
|
765
|
+
*
|
|
766
|
+
* This validates; it does not rewrite. The executable has to be there, and the
|
|
767
|
+
* command and its arguments have to be text. Past that every word is passed on
|
|
768
|
+
* exactly as it came: an empty argument stays an argument, leading and
|
|
769
|
+
* trailing spaces stay. The config that is registered is also the one that is
|
|
770
|
+
* saved (mcpAdd), so a later serve starts the server with the same argv.
|
|
771
|
+
*/
|
|
772
|
+
export function runtimeMcpConfigFor(input) {
|
|
773
|
+
if (!input || typeof input !== 'object') return { ok: false, error: 'A command or a URL is required.' };
|
|
774
|
+
const env = input.environment ?? input.env;
|
|
775
|
+
if (env != null && !stringMap(env)) return { ok: false, error: 'Environment variables must be text.' };
|
|
776
|
+
if (input.headers != null && !stringMap(input.headers)) return { ok: false, error: 'Headers must be text.' };
|
|
777
|
+
if (typeof input.url === 'string' && input.url.trim()) {
|
|
778
|
+
let url;
|
|
779
|
+
try { url = new URL(input.url.trim()); } catch { return { ok: false, error: 'That is not a valid URL.' }; }
|
|
780
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') return { ok: false, error: 'An MCP server URL must be http or https.' };
|
|
781
|
+
return { ok: true, config: buildOpencodeRuntimeMcpConfig({ url: url.toString(), headers: input.headers || undefined }) };
|
|
782
|
+
}
|
|
783
|
+
if (input.args != null && !Array.isArray(input.args)) return { ok: false, error: 'Arguments must be a list.' };
|
|
784
|
+
const command = [...(Array.isArray(input.command) ? input.command : [input.command]), ...(input.args || [])];
|
|
785
|
+
if (command[0] === undefined || command[0] === null) return { ok: false, error: 'A command or a URL is required.' };
|
|
786
|
+
if (!command.every((part) => typeof part === 'string')) return { ok: false, error: 'The command and its arguments must be text.' };
|
|
787
|
+
if (!command[0].trim()) return { ok: false, error: 'A command or a URL is required.' };
|
|
788
|
+
return { ok: true, config: buildOpencodeRuntimeMcpConfig({ command, env: env || undefined }) };
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// mcp.add: register one more MCP server on the serve that runs this session.
|
|
792
|
+
// It lasts as long as that serve. With `persist: true` the same config is then
|
|
793
|
+
// written to the OpenCode config (deps.persistMcp), so later serves start with
|
|
794
|
+
// it. That write starts nothing: the server runs once, where it was registered.
|
|
795
|
+
// (The Settings route, POST /api/opencode/mcp, also registers on the shared
|
|
796
|
+
// serve; a panel that saved through it started a command-based server twice.)
|
|
797
|
+
// A server that did not start is never saved: a typo must not end up in the config.
|
|
798
|
+
async function mcpAdd(msg, deps) {
|
|
799
|
+
const name = mcpNameOf(msg);
|
|
800
|
+
if (!name) return failure(400, 'MCP server name is required');
|
|
801
|
+
if (isManagedMcpName(name)) return failure(403, `${name} is managed by SynaBun and cannot be changed from the panel.`);
|
|
802
|
+
if (!MCP_NAME_RE.test(name)) return failure(400, 'A server name may use letters, digits, ".", "_" and "-".');
|
|
803
|
+
const built = runtimeMcpConfigFor(msg.config);
|
|
804
|
+
if (!built.ok) return failure(400, built.error);
|
|
805
|
+
const r = await deps.bound(sessionKeyOf(msg)).extra.mcp.add({ name, config: built.config, directory: directoryOf(msg) });
|
|
806
|
+
const rows = mcpRows(r.data);
|
|
807
|
+
const reply = { status: r.status, data: rows };
|
|
808
|
+
if (msg.persist !== true) return reply;
|
|
809
|
+
const row = rows.find((entry) => entry.name === name);
|
|
810
|
+
if (r.status >= 400 || !row || row.status === 'failed') return { ...reply, saved: false };
|
|
811
|
+
if (typeof deps.persistMcp !== 'function') return { ...reply, saved: false, saveError: 'This server cannot save MCP servers.' };
|
|
812
|
+
try {
|
|
813
|
+
await deps.persistMcp(name, built.config);
|
|
814
|
+
return { ...reply, saved: true };
|
|
815
|
+
} catch (err) {
|
|
816
|
+
return { ...reply, saved: false, saveError: err?.message || String(err) };
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
const listOr = (value) => (Array.isArray(value) ? value : []);
|
|
821
|
+
|
|
822
|
+
// Language servers and formatters of the session's serve. Each read is
|
|
823
|
+
// independent: one that fails is reported as an empty list.
|
|
824
|
+
async function envStatus(msg, deps) {
|
|
825
|
+
const client = deps.bound(sessionKeyOf(msg));
|
|
826
|
+
const directory = directoryOf(msg);
|
|
827
|
+
const [lsp, formatter, reference] = await Promise.all([
|
|
828
|
+
client.extra.lsp.status({ directory }).catch(() => null),
|
|
829
|
+
client.extra.formatter.status({ directory }).catch(() => null),
|
|
830
|
+
deps.proxy('GET', referencePath(directory), null, 10000, deps.baseUrlFor(sessionKeyOf(msg))).catch(() => null),
|
|
831
|
+
]);
|
|
832
|
+
return {
|
|
833
|
+
status: 200,
|
|
834
|
+
data: {
|
|
835
|
+
references: reference?.status === 200 ? referenceRows(reference.data) : [],
|
|
836
|
+
lsp: listOr(lsp?.data).map((s) => ({ id: String(s?.id || ''), name: String(s?.name || s?.id || ''), root: String(s?.root || ''), status: String(s?.status || '') })),
|
|
837
|
+
formatter: listOr(formatter?.data).map((f) => ({ name: String(f?.name || ''), extensions: listOr(f?.extensions).filter((e) => typeof e === 'string'), enabled: f?.enabled !== false })),
|
|
838
|
+
},
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// type → { run, session? }. `session: true` rejects a request without sessionId.
|
|
843
|
+
const HANDLERS = {
|
|
844
|
+
'session:context': {
|
|
845
|
+
session: true,
|
|
846
|
+
run: async (msg, deps) => {
|
|
847
|
+
const r = await deps.shared.session.context({ sessionID: sessionIdOf(msg) });
|
|
848
|
+
return { status: r.status, data: contextRows(r.data) };
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
'session:compact': { session: true, run: compactSession },
|
|
852
|
+
'session:status': { session: true, run: sessionStatus },
|
|
853
|
+
'session:todo': { session: true, run: sessionTodo },
|
|
854
|
+
'permission:reply': { run: permissionReply },
|
|
855
|
+
'permission:list': { run: permissionList },
|
|
856
|
+
'permission:saved:list': { run: permissionSavedList },
|
|
857
|
+
'permission:saved:remove': { run: permissionSavedRemove },
|
|
858
|
+
'question:reply': { run: questionReply },
|
|
859
|
+
'session:revert': { session: true, mutates: true, run: sessionRevert },
|
|
860
|
+
'session:unrevert': { session: true, mutates: true, run: sessionUnrevert },
|
|
861
|
+
'session:fork': { session: true, mutates: true, run: sessionFork },
|
|
862
|
+
'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
|
+
'command:list': { run: commandList },
|
|
868
|
+
'command:run': { session: true, mutates: true, run: commandRun },
|
|
869
|
+
'session:shell': { session: true, mutates: true, run: sessionShell },
|
|
870
|
+
'find:files': { run: findFiles },
|
|
871
|
+
'find:symbols': { run: findSymbols },
|
|
872
|
+
'resource:list': { run: resourceList },
|
|
873
|
+
'reference:list': { run: referenceList },
|
|
874
|
+
'agent:list': { run: agentList },
|
|
875
|
+
'session:diff': { session: true, run: sessionDiff },
|
|
876
|
+
'vcs:get': { run: vcsGet },
|
|
877
|
+
'vcs:status': { run: vcsStatus },
|
|
878
|
+
'vcs:diff': { run: vcsDiff },
|
|
879
|
+
'worktree:list': { run: worktreeList },
|
|
880
|
+
'worktree:create': { run: worktreeCreate },
|
|
881
|
+
'worktree:remove': { run: worktreeRemove },
|
|
882
|
+
'mcp:status': { run: mcpStatus },
|
|
883
|
+
'mcp:connect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, true) },
|
|
884
|
+
'mcp:disconnect': { session: true, mutates: true, run: (msg, deps) => mcpSwitch(msg, deps, false) },
|
|
885
|
+
'mcp:authenticate': { session: true, mutates: true, run: mcpAuthenticate },
|
|
886
|
+
'mcp:add': { session: true, mutates: true, run: mcpAdd },
|
|
887
|
+
'env:status': { run: envStatus },
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
// Types added here that change a session. server.js adds them to its
|
|
891
|
+
// native-run and history-clear guard sets, which key on the type name.
|
|
892
|
+
export const OPENCODE_V2_WS_MUTATION_TYPES = Object.freeze(
|
|
893
|
+
Object.keys(HANDLERS).filter((type) => HANDLERS[type].mutates),
|
|
894
|
+
);
|
|
895
|
+
|
|
896
|
+
export const OPENCODE_V2_WS_MODULE_TYPES = Object.freeze(Object.keys(HANDLERS));
|
|
897
|
+
|
|
898
|
+
// Behaviours of an existing type that an older server lacks. Listed next to
|
|
899
|
+
// the types so the panel can gate on them the same way; never a request type.
|
|
900
|
+
export const OPENCODE_V2_WS_FEATURES = Object.freeze([
|
|
901
|
+
'feature:permission-reply-message', // permission:reply forwards a rejection reason
|
|
902
|
+
'feature:compact-summarize', // session:compact falls back to session.summarize
|
|
903
|
+
'feature:session-list-filters', // session:list takes search / archived / roots / limit, rows carry parentID
|
|
904
|
+
'feature:mcp-add-persist', // mcp:add with persist:true saves the server without starting it a second time
|
|
905
|
+
]);
|
|
906
|
+
|
|
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
|
+
// Everything this server answers, for the panel's feature gating.
|
|
925
|
+
export function opencodeV2WsCapabilities() {
|
|
926
|
+
return [...OPENCODE_V2_WS_INLINE_TYPES, ...OPENCODE_V2_WS_MODULE_TYPES, ...OPENCODE_V2_WS_FEATURES];
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
export function ownsOpencodeV2Request(type) {
|
|
930
|
+
return Object.prototype.hasOwnProperty.call(HANDLERS, type);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/** Answer `msg` when its type lives here. Resolves true when it was handled. */
|
|
934
|
+
export async function handleOpencodeV2Request(msg, deps) {
|
|
935
|
+
const type = msg?.type;
|
|
936
|
+
if (!ownsOpencodeV2Request(type)) return false;
|
|
937
|
+
const handler = HANDLERS[type];
|
|
938
|
+
const reply = (body) => deps.send({ type: `${type}:result`, id: msg.id, ...body });
|
|
939
|
+
// server.js has done this already; a caller that has not gets the same id rules.
|
|
940
|
+
const malformed = canonicalizeOpencodeV2Message(msg);
|
|
941
|
+
if (malformed) {
|
|
942
|
+
reply(malformed);
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
945
|
+
if (handler.session && !sessionIdOf(msg)) {
|
|
946
|
+
reply(failure(400, 'sessionId is required'));
|
|
947
|
+
return true;
|
|
948
|
+
}
|
|
949
|
+
try {
|
|
950
|
+
reply(await handler.run(msg, deps));
|
|
951
|
+
} catch (err) {
|
|
952
|
+
reply(failure(err?.status || 500, err?.message || String(err), err?.tag ? { tag: err.tag } : {}));
|
|
953
|
+
}
|
|
954
|
+
return true;
|
|
955
|
+
}
|