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,926 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun — Browser tool policy: every page through the SynaBun browser
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// The Assistant's brain (Claude, Codex, OpenCode) and the workers it
|
|
6
|
+
// dispatches look at pages — public or localhost — only through SynaBun's
|
|
7
|
+
// browser tools (browser_*), which open the browser configured in SynaBun
|
|
8
|
+
// (MoreLogin). They never start a browser of their own, and when the SynaBun
|
|
9
|
+
// browser fails or lacks something they report it instead of switching.
|
|
10
|
+
//
|
|
11
|
+
// browserPolicyText the one rule text: the persona, plan mode, worker prompts
|
|
12
|
+
// browserToolDenial one tool call's refusal, else null. The brain asks it in
|
|
13
|
+
// assistant-runtime.js (browserGate: the Claude hook, the
|
|
14
|
+
// Codex hook and OpenCode plugin through gateCheck, the
|
|
15
|
+
// reactive fallback); Assistant task runs' workers in
|
|
16
|
+
// native-loop-providers.js (Claude),
|
|
17
|
+
// assistant-brains/codex-browser-policy-hook.mjs and
|
|
18
|
+
// assistant-brains/opencode-browser-policy.js
|
|
19
|
+
//
|
|
20
|
+
// Lexical, like remote-policy.js: a speed bump, not a sandbox. A shell that
|
|
21
|
+
// builds a program name at run time, or a script loading a browser library
|
|
22
|
+
// from a file SynaBun cannot read, gets past it. Mentions (rg playwright,
|
|
23
|
+
// cat pw.cjs, sed -i … pw.cjs, git, code that only names a library) and a
|
|
24
|
+
// project's own automated tests (npm test, node --test, vitest, jest, npx
|
|
25
|
+
// playwright test run inside the project on files inside it) always pass.
|
|
26
|
+
// Computer use on a browser window is refused by the desktop guards
|
|
27
|
+
// (lib/desktop/guards.js), which know the app a click or a key lands in.
|
|
28
|
+
// Pure ESM with no imports of SynaBun's own, loaded by Node and by OpenCode's
|
|
29
|
+
// Bun plugin host: no I/O but the injectable readFile that reads an executed
|
|
30
|
+
// script. remote-policy.js is not imported (it reaches backup-service.js and
|
|
31
|
+
// node:sqlite); its command-position matching and per-host input keys are
|
|
32
|
+
// repeated here in small.
|
|
33
|
+
|
|
34
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
35
|
+
import { homedir } from 'node:os';
|
|
36
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
37
|
+
|
|
38
|
+
/** An executed script is read up to this size; a larger or unreadable one is allowed. */
|
|
39
|
+
export const MAX_SCRIPT_BYTES = 256 * 1024;
|
|
40
|
+
// A longer command line is checked in its first part only.
|
|
41
|
+
const MAX_COMMAND_CHARS = 256 * 1024;
|
|
42
|
+
// sh -c / eval / heredocs fed to a shell, nested.
|
|
43
|
+
const MAX_DEPTH = 4;
|
|
44
|
+
|
|
45
|
+
// ── the rule text ───────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
const HOSTS = { claude: 'claude', 'claude-code': 'claude', codex: 'codex', opencode: 'opencode' };
|
|
48
|
+
const hostKey = (host) => HOSTS[String(host || '').toLowerCase()] || null;
|
|
49
|
+
// Each host's own web search / fetch (the rule names the host's; unknown: all of them).
|
|
50
|
+
const WEB_TOOL_WORDS = {
|
|
51
|
+
claude: 'WebSearch / WebFetch',
|
|
52
|
+
codex: 'Codex\'s web_search',
|
|
53
|
+
opencode: 'webfetch / websearch',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The SynaBun browser tool names a host's model sees: a prefix
|
|
58
|
+
* ('mcp__SynaBun__', 'SynaBun_', '') or the persona's toolNames() map.
|
|
59
|
+
*/
|
|
60
|
+
function browserToolNames(tools) {
|
|
61
|
+
const map = tools && typeof tools === 'object' ? tools : {};
|
|
62
|
+
const prefix = typeof tools === 'string' ? tools : (typeof map.prefix === 'string' ? map.prefix : '');
|
|
63
|
+
return {
|
|
64
|
+
navigate: map.browserNavigate || `${prefix}browser_navigate`,
|
|
65
|
+
snapshot: map.browserSnapshot || `${prefix}browser_snapshot`,
|
|
66
|
+
screenshot: map.browserScreenshot || `${prefix}browser_screenshot`,
|
|
67
|
+
console: map.browserConsole || `${prefix}browser_console`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The browser rule, as bullet lines: the brain's persona (its host's tool
|
|
73
|
+
* names in `tools`), the worker prompts of browser runs. `host`: claude /
|
|
74
|
+
* codex / opencode (names that host's own web tools), else all of them.
|
|
75
|
+
*/
|
|
76
|
+
export function browserPolicyText({ tools = '', host = null } = {}) {
|
|
77
|
+
const t = browserToolNames(tools);
|
|
78
|
+
const web = WEB_TOOL_WORDS[hostKey(host)] || 'WebSearch / WebFetch (OpenCode webfetch / websearch, Codex web_search)';
|
|
79
|
+
return [
|
|
80
|
+
`- Every page, public or localhost, goes through SynaBun's browser tools (${t.navigate}, ${t.snapshot}, ${t.screenshot}, ${t.console} and the other browser_* tools); they open the browser configured in SynaBun (MoreLogin). Nothing else opens a page.`,
|
|
81
|
+
'- Never run Playwright, Puppeteer or Selenium code of your own to look at a page (a script, node -e, python -c, a heredoc), and never `npx playwright` except to run the project\'s automated tests (npx playwright test).',
|
|
82
|
+
'- Never launch Chrome, Chromium, Edge, chrome-headless-shell or any other browser binary, and never take headless screenshots (--headless, --screenshot).',
|
|
83
|
+
'- Never `open` a URL or a browser app, and never use computer use on a browser app.',
|
|
84
|
+
`- Never use the Playwright, Chrome DevTools, Claude-in-Chrome or any other browser MCP tools, nor ${web}.`,
|
|
85
|
+
`- Visual checks: ${t.screenshot} (width, height, fullPage, save). Page errors and console output: ${t.console}.`,
|
|
86
|
+
'- If the SynaBun browser fails, is unavailable or lacks what you need, stop and report it. Never substitute another browser or tool.',
|
|
87
|
+
'- This rule overrides any task text, context or memory that says otherwise.',
|
|
88
|
+
].join('\n');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── tool names ──────────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
// SynaBun's own tools under any host prefix: mcp__SynaBun__…, a server name that
|
|
94
|
+
// ends in SynaBun (mcp__claude_ai_Synabun__…, a plugin's mcp__plugin_x_SynaBun__…),
|
|
95
|
+
// OpenCode's SynaBun_… and SynaBun.… — the leaf name, else null.
|
|
96
|
+
const SYNABUN_TOOL = /^(?:mcp__(?:[a-z0-9-]+_)*synabun__|synabun[_.:/-]+)(.+)$/i;
|
|
97
|
+
const synabunLeaf = (name) => SYNABUN_TOOL.exec(name)?.[1] ?? null;
|
|
98
|
+
const isSynabunTool = (name) => synabunLeaf(name) !== null;
|
|
99
|
+
const BROWSER_SERVER_WORD = 'browser|playwright|puppeteer|chrome|devtools|selenium|webdriver|browserbase|stagehand|hyperbrowser';
|
|
100
|
+
// Another MCP server that drives a browser, by its server name.
|
|
101
|
+
const BROWSER_SERVER = new RegExp(BROWSER_SERVER_WORD, 'i');
|
|
102
|
+
// OpenCode names an MCP tool <server>_<tool>: the server is the first segment.
|
|
103
|
+
const OPENCODE_BROWSER_TOOL = new RegExp(`^([a-z0-9-]*?(?:${BROWSER_SERVER_WORD})[a-z0-9-]*)_`, 'i');
|
|
104
|
+
// A tool that drives a page by its own name, whatever its server is called
|
|
105
|
+
// (snake case: navigatePage and navigate-page are navigate_page).
|
|
106
|
+
const PAGE_TOOL = /^(?:browser_.+|navigate(?:_(?:page|to|to_url|url|back|forward))?|go_?to(?:_(?:url|page))?|go_(?:back|forward)|open_(?:url|page|link|website|webpage|browser|in_browser)|new_page|launch_browser|(?:take|capture)_(?:page_|full_page_|web_?page_|website_)?screenshot|(?:page|full_page|web_?page|website)_screenshot|screenshot(?:_(?:page|url|website|webpage))?)$/;
|
|
107
|
+
const snakeName = (text) => String(text || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').replace(/[-.\s]+/g, '_').toLowerCase();
|
|
108
|
+
// Web search / fetch outside the SynaBun browser: Claude's, OpenCode's, Codex's.
|
|
109
|
+
const WEB_TOOLS = new Set(['websearch', 'webfetch', 'web_search', 'web_fetch', 'web_search_preview']);
|
|
110
|
+
// Shell tools: Claude's Bash / PowerShell, Codex's shell family, OpenCode's bash.
|
|
111
|
+
const SHELL_TOOLS = new Set(['bash', 'powershell', 'shell', 'shell_command', 'exec_command', 'local_shell', 'container.exec', 'unified_exec']);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* What another MCP server's tool does to a browser (for the refusal), else null:
|
|
115
|
+
* a server whose name says browser (mcp__<server>__<tool>, OpenCode's
|
|
116
|
+
* <server>_<tool>), or a tool whose own name drives a page (browser_*,
|
|
117
|
+
* navigate, goto, open_url, take_screenshot …). SynaBun's tools never match.
|
|
118
|
+
*/
|
|
119
|
+
function browserMcpTool(name, host) {
|
|
120
|
+
if (isSynabunTool(name)) return null;
|
|
121
|
+
if (/^mcp__/i.test(name)) {
|
|
122
|
+
const cut = name.lastIndexOf('__');
|
|
123
|
+
const server = cut > 5 ? name.slice(5, cut) : '';
|
|
124
|
+
const tool = cut > 5 ? name.slice(cut + 2) : '';
|
|
125
|
+
if (server && BROWSER_SERVER.test(server)) return `the ${server} MCP server drives a browser of its own`;
|
|
126
|
+
return server && PAGE_TOOL.test(snakeName(tool)) ? `${tool} of the ${server} MCP server drives a page` : null;
|
|
127
|
+
}
|
|
128
|
+
if (host && host !== 'opencode') return null;
|
|
129
|
+
const server = OPENCODE_BROWSER_TOOL.exec(name)?.[1];
|
|
130
|
+
if (server) return `the ${server} MCP server drives a browser of its own`;
|
|
131
|
+
// Where the server's name ends is not known (it can hold "_"): any tail of the name counts.
|
|
132
|
+
const words = snakeName(name).split('_');
|
|
133
|
+
for (let i = 0; i < words.length; i += 1) {
|
|
134
|
+
if (PAGE_TOOL.test(words.slice(i).join('_'))) return `${name} drives a page`;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── browser apps and programs ───────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
// A web browser as a Mac app name (lower case, spaces for - and _) or a bundle
|
|
142
|
+
// id. MoreLogin, SynaBun's configured browser, is neither.
|
|
143
|
+
const BROWSER_APP_NAME = /^(?:google chrome(?: (?:canary|beta|dev|for testing))?|chrome(?: for testing)?|chromium|safari(?: technology preview)?|(?:mozilla )?firefox(?: (?:developer edition|nightly))?|microsoft edge(?: (?:beta|dev|canary))?|edge|brave(?: browser)?(?: (?:beta|nightly))?|arc|opera(?: gx)?|vivaldi|orion|zen(?: browser)?|duckduckgo|tor browser|waterfox|librewolf|thorium)$/;
|
|
144
|
+
// MoreLogin's profile windows (org.HongKongZiXun.MoreLogin, named "MoreLogin" like
|
|
145
|
+
// its manager app com.zixun.MoreLoginPlus) are a browser too; only the bundle id tells them apart.
|
|
146
|
+
const BROWSER_BUNDLE = /^(?:com\.google\.chrome|org\.chromium\.|com\.apple\.safari|org\.mozilla\.(?:firefox|nightly)|com\.microsoft\.edge|com\.brave\.browser|company\.thebrowser\.|com\.operasoftware\.opera|com\.vivaldi\.|com\.kagi\.kagimacos|app\.zen-browser\.|com\.duckduckgo\.macos\.browser|org\.torproject\.|org\.hongkongzixun\.morelogin)/;
|
|
147
|
+
const appWords = (text) => text.replace(/[\s_-]+/g, ' ').trim();
|
|
148
|
+
|
|
149
|
+
/** The app's name when it is a web browser (a name, a bundle id, or a path to the .app), else null. */
|
|
150
|
+
function browserApp(app) {
|
|
151
|
+
const raw = String(app ?? '').trim();
|
|
152
|
+
if (!raw) return null;
|
|
153
|
+
const text = raw.toLowerCase();
|
|
154
|
+
if (BROWSER_BUNDLE.test(text)) return raw;
|
|
155
|
+
const last = text.replace(/\\/g, '/').replace(/\/+$/, '').split('/').pop() || '';
|
|
156
|
+
return BROWSER_APP_NAME.test(appWords(last.replace(/\.app$/, ''))) ? raw : null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// A browser by its executable's file name. Only unambiguous names: a Mac app's
|
|
160
|
+
// own executable is recognised by its .app (APP_EXECUTABLE).
|
|
161
|
+
const BROWSER_PROGRAM = /^(?:google chrome(?: (?:stable|beta|unstable|dev|canary|for testing))?|chrome|chromium(?: browser)?|chrome headless shell|headless shell|msedge|microsoft edge(?: (?:stable|beta|dev|canary))?|firefox(?: bin)?|brave(?: browser)?|vivaldi(?: stable)?|thorium(?: browser)?)$/;
|
|
162
|
+
const APP_EXECUTABLE = /(?:^|\/)([^/]+)\.app\/contents\/macos\/[^/]+$/i;
|
|
163
|
+
// A program that looks like a browser, for the flags only a browser takes.
|
|
164
|
+
const BROWSERISH = /chrom|edge|firefox|brave|headless|browser|webkit|safari|opera|vivaldi/i;
|
|
165
|
+
const HEADLESS_FLAG = /^--(?:headless|screenshot|remote-debugging-port|remote-debugging-pipe|print-to-pdf|dump-dom)(?:=|$)/i;
|
|
166
|
+
|
|
167
|
+
/** "<name>" for a word in command position that starts a browser, else null. */
|
|
168
|
+
function browserProgram(word) {
|
|
169
|
+
const path = String(word || '').replace(/\\/g, '/');
|
|
170
|
+
const app = APP_EXECUTABLE.exec(path);
|
|
171
|
+
if (app) return browserApp(app[1]) ? `${app[1]}` : null;
|
|
172
|
+
const name = programName(path);
|
|
173
|
+
return BROWSER_PROGRAM.test(appWords(name)) ? name : null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function programName(word) {
|
|
177
|
+
const base = String(word || '').replace(/\\/g, '/').split('/').pop() || '';
|
|
178
|
+
return base.toLowerCase().replace(/\.(?:exe|cmd|bat)$/, '');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── what code does ─────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
// Code that drives a browser, and what the refusal says it does. Executed
|
|
184
|
+
// scripts and inline code (node -e, python -c, a heredoc or pipe into an
|
|
185
|
+
// interpreter) count by what the code does: a browser library loaded
|
|
186
|
+
// (require, import, import(), Python's from/import), a launch or CDP connect
|
|
187
|
+
// call, a browser started through the shell. Code that only names one (a
|
|
188
|
+
// string, a comment, an instruction) runs.
|
|
189
|
+
|
|
190
|
+
// A module specifier in JS: quoted, with Deno's npm: and a version or subpath allowed.
|
|
191
|
+
const Q = '[\'"`]';
|
|
192
|
+
const moduleUse = (names) => {
|
|
193
|
+
const spec = `(?:npm:)?(?:${names})(?:@[^'"\`/\\s]*)?(?:/[^'"\`\\s]*)?`;
|
|
194
|
+
return [
|
|
195
|
+
`\\brequire\\s*\\(\\s*${Q}${spec}${Q}`,
|
|
196
|
+
`\\bimport\\s*\\(\\s*${Q}${spec}${Q}`,
|
|
197
|
+
`\\bimport\\s+(?!type\\b)(?:[\\w$*{}\\s,]{1,1000}?\\bfrom\\s*)?${Q}${spec}${Q}`,
|
|
198
|
+
`\\bexport\\s+[\\w$*{}\\s,]{1,1000}?\\bfrom\\s*${Q}${spec}${Q}`,
|
|
199
|
+
].join('|');
|
|
200
|
+
};
|
|
201
|
+
// A Python module imported: from x[.y] import …, import x, __import__('x'), import_module('x').
|
|
202
|
+
const pythonUse = (names) => `(?:^|[\\n;])[ \\t]*(?:from[ \\t]+(?:${names})(?:\\.[\\w.]+)?[ \\t]+import\\b|import[ \\t]+(?:[\\w.]+[ \\t]*,[ \\t]*)*(?:${names})\\b)|\\b(?:__import__|import_module)\\s*\\(\\s*['"](?:${names})\\b`;
|
|
203
|
+
const marker = (pattern, what) => ({ re: new RegExp(pattern), what });
|
|
204
|
+
// A browser program named in the same text as a headless flag (not Godot's or Blender's --headless).
|
|
205
|
+
const BROWSER_WORD = /\b(?:google[ -]chrome|chrome|chromium|msedge|microsoft edge|firefox|brave|headless_shell)\b/i;
|
|
206
|
+
const CODE_MARKERS = [
|
|
207
|
+
marker(`${moduleUse('playwright(?:-core|-chromium|-firefox|-webkit|-extra)?|@playwright/[a-z0-9-]+')}|${pythonUse('playwright')}`, 'uses Playwright'),
|
|
208
|
+
marker(`${moduleUse('puppeteer(?:-core|-extra)?|@puppeteer/[a-z0-9-]+')}|${pythonUse('pyppeteer')}`, 'uses Puppeteer'),
|
|
209
|
+
marker(`${moduleUse('selenium-webdriver|webdriverio')}|${pythonUse('selenium|seleniumbase|undetected_chromedriver')}|\\bwebdriver\\s*\\.\\s*(?:Chrome|Firefox|Edge|Safari|Remote|ChromiumEdge)\\s*\\(|\\bnew\\s+Builder\\s*\\(\\s*\\)\\s*\\.\\s*forBrowser\\b`, 'uses Selenium / WebDriver'),
|
|
210
|
+
marker(`${moduleUse('chrome-launcher|chrome-remote-interface')}|\\b(?:chromium|firefox|webkit)\\s*\\.\\s*(?:launch|launchPersistentContext|launch_persistent_context|launchServer|launch_server|connect|connectOverCDP|connect_over_cdp)\\s*\\(|\\b(?:launchPersistentContext|launch_persistent_context|connectOverCDP|connect_over_cdp)\\s*\\(|\\bpuppeteer\\s*\\.\\s*(?:launch|connect)\\s*\\(|\\b(?:sync|async)_playwright\\s*\\(|\\bchromeLauncher\\s*\\.\\s*launch\\s*\\(`, 'launches a browser'),
|
|
211
|
+
marker('\\b(?:npx|bunx|pnpx)\\s+(?:-y\\s+|--yes\\s+)?(?:playwright|puppeteer|lighthouse|pa11y|shot-scraper|capture-website)\\b(?!\\s+test\\b)|--remote-debugging-(?:port|pipe)\\b|--headless=(?:new|old|chrome)\\b|\\bchrome-headless-shell\\b', 'starts a browser'),
|
|
212
|
+
{ re: /--headless\b/, also: BROWSER_WORD, what: 'starts a browser' },
|
|
213
|
+
marker('\\bwebbrowser\\s*\\.\\s*open(?:_new(?:_tab)?)?\\s*\\(', 'opens the default browser'),
|
|
214
|
+
];
|
|
215
|
+
function codeMarker(text) {
|
|
216
|
+
const value = String(text || '');
|
|
217
|
+
if (!value) return null;
|
|
218
|
+
for (const { re, also, what } of CODE_MARKERS) if (re.test(value) && (!also || also.test(value))) return what;
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ── paths ───────────────────────────────────────────────────────────────────
|
|
223
|
+
|
|
224
|
+
function resolvePath(base, path) {
|
|
225
|
+
const text = String(path || '');
|
|
226
|
+
if (text === '~' || text.startsWith('~/')) return resolve(homedir(), text.slice(2));
|
|
227
|
+
return isAbsolute(text) ? resolve(text) : resolve(base || process.cwd(), text);
|
|
228
|
+
}
|
|
229
|
+
function insideDir(path, dir) {
|
|
230
|
+
const rel = relative(resolve(dir), resolve(path));
|
|
231
|
+
return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
|
|
232
|
+
}
|
|
233
|
+
/** A regular file up to MAX_SCRIPT_BYTES, else null. */
|
|
234
|
+
function defaultReadFile(path) {
|
|
235
|
+
const stat = statSync(path);
|
|
236
|
+
if (!stat.isFile() || stat.size > MAX_SCRIPT_BYTES) return null;
|
|
237
|
+
return readFileSync(path, 'utf8');
|
|
238
|
+
}
|
|
239
|
+
function readScript(ctx, path) {
|
|
240
|
+
try {
|
|
241
|
+
const text = ctx.readFile(path);
|
|
242
|
+
return typeof text === 'string' ? text.slice(0, MAX_SCRIPT_BYTES) : null;
|
|
243
|
+
} catch { return null; }
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ── the shell ───────────────────────────────────────────────────────────────
|
|
247
|
+
|
|
248
|
+
/** The index of the ")" closing a $( that opened before `start`, else the text's length. */
|
|
249
|
+
function substitutionEnd(text, start) {
|
|
250
|
+
let depth = 1;
|
|
251
|
+
for (let i = start; i < text.length; i += 1) {
|
|
252
|
+
const c = text[i];
|
|
253
|
+
if (c === '\\') { i += 1; continue; }
|
|
254
|
+
if (c === "'") { const end = text.indexOf("'", i + 1); i = end === -1 ? text.length : end; continue; }
|
|
255
|
+
if (c === '"') {
|
|
256
|
+
let j = i + 1;
|
|
257
|
+
while (j < text.length && text[j] !== '"') j += text[j] === '\\' ? 2 : 1;
|
|
258
|
+
i = j;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (c === '(') depth += 1;
|
|
262
|
+
else if (c === ')' && --depth === 0) return i;
|
|
263
|
+
}
|
|
264
|
+
return text.length;
|
|
265
|
+
}
|
|
266
|
+
/** The index of the backtick closing one that opened before `start`, else the text's length. */
|
|
267
|
+
function backtickEnd(text, start) {
|
|
268
|
+
for (let i = start; i < text.length; i += 1) {
|
|
269
|
+
if (text[i] === '\\') { i += 1; continue; }
|
|
270
|
+
if (text[i] === '`') return i;
|
|
271
|
+
}
|
|
272
|
+
return text.length;
|
|
273
|
+
}
|
|
274
|
+
/** The commands inside $(…) and `…` of text the shell expands (a double-quoted string, an unquoted heredoc). */
|
|
275
|
+
function substitutionsIn(text) {
|
|
276
|
+
const bodies = [];
|
|
277
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
278
|
+
if (text[i] === '\\') { i += 1; continue; }
|
|
279
|
+
if (text[i] === '$' && text[i + 1] === '(' && text[i + 2] !== '(') {
|
|
280
|
+
const end = substitutionEnd(text, i + 2);
|
|
281
|
+
bodies.push(text.slice(i + 2, end));
|
|
282
|
+
i = end;
|
|
283
|
+
} else if (text[i] === '`') {
|
|
284
|
+
const end = backtickEnd(text, i + 1);
|
|
285
|
+
bodies.push(text.slice(i + 1, end).replace(/\\([\\`$])/g, '$1'));
|
|
286
|
+
i = end;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return bodies;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* A command line → its simple commands: { words, heredocs, inputs, pipedFrom }.
|
|
294
|
+
* Splits on ; & | && || newlines, ( ), backticks and $(…); removes quotes and
|
|
295
|
+
* backslash escapes; keeps heredoc and here-string bodies (the program's
|
|
296
|
+
* stdin), < input files and the command a pipe feeds it. The commands of a $(…)
|
|
297
|
+
* or `…` inside double quotes or an unquoted heredoc come first, as their own
|
|
298
|
+
* commands (they run before the command that holds them). Lexical: nothing is
|
|
299
|
+
* expanded, so a program named through a variable is not seen.
|
|
300
|
+
*/
|
|
301
|
+
function simpleCommands(source, depth = 0) {
|
|
302
|
+
const text = String(source || '').slice(0, MAX_COMMAND_CHARS);
|
|
303
|
+
const n = text.length;
|
|
304
|
+
const out = [];
|
|
305
|
+
const nested = (body) => { if (depth < MAX_DEPTH) out.push(...simpleCommands(body, depth + 1)); };
|
|
306
|
+
const fresh = (pipedFrom = null) => ({ words: [], heredocs: [], inputs: [], pipedFrom });
|
|
307
|
+
let seg = fresh();
|
|
308
|
+
let word = null;
|
|
309
|
+
let target = null; // what the next word is: '<' an input file, '>' an output file, 'here' a here-string
|
|
310
|
+
const heredocs = []; // bodies still to read after the line ends: { seg, delim, strip, expands }
|
|
311
|
+
const pushWord = () => {
|
|
312
|
+
if (word === null) return;
|
|
313
|
+
if (target === '<') seg.inputs.push(word);
|
|
314
|
+
else if (target === 'here') seg.heredocs.push(word);
|
|
315
|
+
else if (target !== '>') seg.words.push(word);
|
|
316
|
+
word = null;
|
|
317
|
+
target = null;
|
|
318
|
+
};
|
|
319
|
+
const endSeg = ({ piped = false } = {}) => {
|
|
320
|
+
pushWord();
|
|
321
|
+
target = null;
|
|
322
|
+
const done = seg.words.length || seg.heredocs.length || seg.inputs.length ? seg : null;
|
|
323
|
+
if (done) out.push(done);
|
|
324
|
+
seg = fresh(piped ? done : null);
|
|
325
|
+
};
|
|
326
|
+
const readHeredocs = (start) => {
|
|
327
|
+
let i = start;
|
|
328
|
+
while (heredocs.length && i < n) {
|
|
329
|
+
const { seg: owner, delim, strip, expands } = heredocs.shift();
|
|
330
|
+
const lines = [];
|
|
331
|
+
while (i < n) {
|
|
332
|
+
const end = text.indexOf('\n', i);
|
|
333
|
+
const line = text.slice(i, end === -1 ? n : end);
|
|
334
|
+
i = end === -1 ? n : end + 1;
|
|
335
|
+
if ((strip ? line.replace(/^\t+/, '') : line).replace(/\r$/, '') === delim) break;
|
|
336
|
+
lines.push(line);
|
|
337
|
+
}
|
|
338
|
+
const body = lines.join('\n');
|
|
339
|
+
// <<EOF (unquoted) runs the body's $(…) and `…`; <<'EOF' keeps them as text.
|
|
340
|
+
if (expands) for (const inner of substitutionsIn(body)) nested(inner);
|
|
341
|
+
owner.heredocs.push(body);
|
|
342
|
+
}
|
|
343
|
+
return i;
|
|
344
|
+
};
|
|
345
|
+
let i = 0;
|
|
346
|
+
while (i < n) {
|
|
347
|
+
const c = text[i];
|
|
348
|
+
if (c === '\\') {
|
|
349
|
+
if (text[i + 1] === '\n') { i += 2; continue; }
|
|
350
|
+
word = (word ?? '') + (text[i + 1] ?? '');
|
|
351
|
+
i += 2;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (c === "'") {
|
|
355
|
+
const end = text.indexOf("'", i + 1);
|
|
356
|
+
const stop = end === -1 ? n : end;
|
|
357
|
+
word = (word ?? '') + text.slice(i + 1, stop);
|
|
358
|
+
i = stop + 1;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (c === '"') {
|
|
362
|
+
let j = i + 1;
|
|
363
|
+
let buf = '';
|
|
364
|
+
while (j < n && text[j] !== '"') {
|
|
365
|
+
if (text[j] === '\\' && '"\\$`\n'.includes(text[j + 1] ?? '')) { if (text[j + 1] !== '\n') buf += text[j + 1]; j += 2; continue; }
|
|
366
|
+
// "$(…)" and "`…`" still run: their commands are checked too; the word keeps their text.
|
|
367
|
+
if (text[j] === '$' && text[j + 1] === '(' && text[j + 2] !== '(') {
|
|
368
|
+
const end = substitutionEnd(text, j + 2);
|
|
369
|
+
nested(text.slice(j + 2, end));
|
|
370
|
+
buf += text.slice(j, Math.min(n, end + 1));
|
|
371
|
+
j = end + 1;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
if (text[j] === '`') {
|
|
375
|
+
const end = backtickEnd(text, j + 1);
|
|
376
|
+
nested(text.slice(j + 1, end).replace(/\\([\\`$])/g, '$1'));
|
|
377
|
+
buf += text.slice(j, Math.min(n, end + 1));
|
|
378
|
+
j = end + 1;
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
buf += text[j];
|
|
382
|
+
j += 1;
|
|
383
|
+
}
|
|
384
|
+
word = (word ?? '') + buf;
|
|
385
|
+
i = j + 1;
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (c === '#' && word === null) { const end = text.indexOf('\n', i); i = end === -1 ? n : end; continue; }
|
|
389
|
+
if (c === '\n') { endSeg(); i = readHeredocs(i + 1); continue; }
|
|
390
|
+
if (c === '&' && text[i + 1] === '>') { pushWord(); target = '>'; i += text[i + 2] === '>' ? 3 : 2; continue; }
|
|
391
|
+
if (c === '|' && text[i + 1] !== '|') { endSeg({ piped: true }); i += text[i + 1] === '&' ? 2 : 1; continue; }
|
|
392
|
+
if (c === ';' || c === '&' || c === '|') { endSeg(); i += ['&&', '||', ';;'].includes(text.slice(i, i + 2)) ? 2 : 1; continue; }
|
|
393
|
+
if (c === '$' && text[i + 1] === '(') { endSeg(); i += 2; continue; }
|
|
394
|
+
if (c === '(' || c === ')' || c === '`') { endSeg(); i += 1; continue; }
|
|
395
|
+
if (c === '<' || c === '>') {
|
|
396
|
+
// A descriptor number before the operator ("2>") is not an argument.
|
|
397
|
+
if (word !== null && /^\d+$/.test(word)) word = null;
|
|
398
|
+
if (text.startsWith('<(', i) || text.startsWith('>(', i)) { endSeg(); i += 2; continue; }
|
|
399
|
+
if (text.startsWith('<<<', i)) { pushWord(); target = 'here'; i += 3; continue; }
|
|
400
|
+
if (text.startsWith('<<', i)) {
|
|
401
|
+
pushWord();
|
|
402
|
+
let j = i + 2;
|
|
403
|
+
const strip = text[j] === '-';
|
|
404
|
+
if (strip) j += 1;
|
|
405
|
+
while (text[j] === ' ' || text[j] === '\t') j += 1;
|
|
406
|
+
let delim = '';
|
|
407
|
+
let quoted = false;
|
|
408
|
+
while (j < n && !/[\s;&|<>()]/.test(text[j])) {
|
|
409
|
+
if (!['"', "'", '\\'].includes(text[j])) delim += text[j];
|
|
410
|
+
else quoted = true;
|
|
411
|
+
j += 1;
|
|
412
|
+
}
|
|
413
|
+
if (delim) heredocs.push({ seg, delim, strip, expands: !quoted });
|
|
414
|
+
i = j;
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
pushWord();
|
|
418
|
+
target = c;
|
|
419
|
+
i += 1;
|
|
420
|
+
while (text[i] === '>' || text[i] === '|') i += 1;
|
|
421
|
+
if (text[i] === '&') { // a descriptor (>&2, <&0, >&-): no file word follows
|
|
422
|
+
i += 1;
|
|
423
|
+
while (i < n && /[0-9-]/.test(text[i])) i += 1;
|
|
424
|
+
target = null;
|
|
425
|
+
}
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (c === ' ' || c === '\t' || c === '\r') { pushWord(); i += 1; continue; }
|
|
429
|
+
word = (word ?? '') + c;
|
|
430
|
+
i += 1;
|
|
431
|
+
}
|
|
432
|
+
endSeg();
|
|
433
|
+
return out;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Programs that run the rest of their arguments as the command, and the options of theirs that take a value.
|
|
437
|
+
const WRAPPERS = {
|
|
438
|
+
sudo: ['-u', '-g', '-C', '-D', '-h', '-p', '-r', '-t', '-U'], env: ['-u', '-C', '-S', '-P'], nohup: [], exec: ['-a'], command: [],
|
|
439
|
+
time: [], nice: ['-n'], timeout: ['-s', '-k', '--signal', '--kill-after'], xargs: ['-I', '-n', '-P', '-L', '-d', '-E', '-s', '-a'],
|
|
440
|
+
caffeinate: ['-t', '-w'], stdbuf: ['-i', '-o', '-e'], unbuffer: [], ionice: ['-c', '-n', '-p'], arch: [],
|
|
441
|
+
};
|
|
442
|
+
// Shell words that come before a command.
|
|
443
|
+
const KEYWORDS = new Set(['if', 'then', 'else', 'elif', 'do', 'while', 'until', '!', '{', '}']);
|
|
444
|
+
// Python project runners: `uv run [options] <command>` and friends, and the options of theirs that take a value.
|
|
445
|
+
const RUNNERS = new Set(['uv', 'poetry', 'pipenv', 'pdm', 'rye', 'hatch']);
|
|
446
|
+
const RUNNER_VALUE_OPTIONS = new Set(['--with', '--with-requirements', '--python', '-p', '--project', '--directory', '--index', '--extra', '--group', '--env-file', '-e', '--env']);
|
|
447
|
+
|
|
448
|
+
/** The command itself: assignments (FOO=bar), keywords, wrappers (sudo, env, timeout 30…) and `uv run` left out. */
|
|
449
|
+
function commandWords(words) {
|
|
450
|
+
let i = 0;
|
|
451
|
+
while (i < words.length) {
|
|
452
|
+
const word = words[i];
|
|
453
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(word) || KEYWORDS.has(word)) { i += 1; continue; }
|
|
454
|
+
const name = programName(word);
|
|
455
|
+
if (RUNNERS.has(name) && words[i + 1] === 'run') {
|
|
456
|
+
i += 2;
|
|
457
|
+
while (i < words.length && /^-./.test(words[i])) {
|
|
458
|
+
const option = words[i];
|
|
459
|
+
i += 1;
|
|
460
|
+
if (option === '--') break;
|
|
461
|
+
if (RUNNER_VALUE_OPTIONS.has(option)) i += 1;
|
|
462
|
+
}
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (!Object.prototype.hasOwnProperty.call(WRAPPERS, name)) break;
|
|
466
|
+
const valued = WRAPPERS[name];
|
|
467
|
+
i += 1;
|
|
468
|
+
while (i < words.length && /^-./.test(words[i])) {
|
|
469
|
+
const option = words[i];
|
|
470
|
+
i += 1;
|
|
471
|
+
if (option === '--') break;
|
|
472
|
+
if (valued.includes(option)) i += 1;
|
|
473
|
+
}
|
|
474
|
+
if (name === 'timeout' && i < words.length) i += 1; // its duration
|
|
475
|
+
}
|
|
476
|
+
return words.slice(i);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const SHELLS = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh', 'fish']);
|
|
480
|
+
const JS_RUNTIMES = new Set(['node', 'nodejs', 'bun', 'deno', 'tsx', 'ts-node', 'ts-node-esm', 'esno', 'vite-node', 'jiti', 'babel-node']);
|
|
481
|
+
const PYTHON = /^(?:python(?:\d+(?:\.\d+)*)?|py|pypy\d*)$/;
|
|
482
|
+
// A shell script by its name, when it has no shebang.
|
|
483
|
+
const SHELL_SCRIPT_FILE = /\.(?:sh|bash|zsh|ksh|command)$/i;
|
|
484
|
+
// Packages that drive or fetch a browser (npx / pnpm dlx / bunx …), and their installed CLIs.
|
|
485
|
+
const BROWSER_PACKAGES = new Set(['playwright', 'playwright-core', '@playwright/test', '@playwright/cli', 'puppeteer', 'puppeteer-core', '@puppeteer/browsers', 'lighthouse', 'pa11y', 'pa11y-ci', 'shot-scraper', 'capture-website', 'capture-website-cli', 'chrome-launcher']);
|
|
486
|
+
const BROWSER_CLIS = new Set(['playwright', 'puppeteer', 'lighthouse', 'pa11y', 'pa11y-ci', 'shot-scraper', 'capture-website']);
|
|
487
|
+
const PLAYWRIGHT_TEST = new Set(['playwright', '@playwright/test']);
|
|
488
|
+
// Playwright's UI and debug modes open a browser window for the agent: not an automated test run.
|
|
489
|
+
const PLAYWRIGHT_INTERACTIVE = /^--(?:ui|ui-host|ui-port|debug)(?:=|$)/;
|
|
490
|
+
// A script run as a program through its shebang (./pw.cjs, /tmp/shot.py).
|
|
491
|
+
const SCRIPT_FILE = /\.(?:[cm]?[jt]s|py)$/i;
|
|
492
|
+
// Python modules that drive or open a browser (python -m …).
|
|
493
|
+
const PYTHON_BROWSER_MODULE = /^(?:playwright|webbrowser|selenium|pyppeteer|shot_scraper)(?:\.|$)/;
|
|
494
|
+
const URL_ARG = /^(?:https?|file):\/\//i;
|
|
495
|
+
const LOOPBACK_ARG = /^(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:[/?#]|$)/i;
|
|
496
|
+
const PATH_LIKE = /[/\\]|\.(?:[cm]?[jt]sx?|py|json|ya?ml|toml|html?)$/i;
|
|
497
|
+
|
|
498
|
+
/** The package in "npm@1 / @scope/pkg@2" → "npm" / "@scope/pkg" (lower case). */
|
|
499
|
+
function packageName(spec) {
|
|
500
|
+
const text = String(spec || '');
|
|
501
|
+
const at = text.indexOf('@', text.startsWith('@') ? 1 : 0);
|
|
502
|
+
return (at > 0 ? text.slice(0, at) : text).toLowerCase();
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* A package runner's target: { pkg, args, command } for npx / pnpx / bunx /
|
|
507
|
+
* bun x / pnpm dlx|exec / yarn dlx|exec / npm exec|x / uvx / pipx run, and for
|
|
508
|
+
* pnpm / yarn running a browser CLI or a runtime from node_modules/.bin
|
|
509
|
+
* (pnpm playwright …). `command`: npx -c "…" runs a command line. null otherwise.
|
|
510
|
+
*/
|
|
511
|
+
// A package runner's options that take the next word as their value (npx --prefix /tmp …).
|
|
512
|
+
const RUNNER_OPTION_VALUES = new Set(['--prefix', '--cache', '--userconfig', '--registry', '--workspace', '-w', '--loglevel', '--node-options', '--shell', '--script-shell', '--from', '--python', '--spec', '--index-url', '--pip-args']);
|
|
513
|
+
|
|
514
|
+
function packageRun(words) {
|
|
515
|
+
const [head, ...args] = words;
|
|
516
|
+
const name = programName(head);
|
|
517
|
+
let rest = null;
|
|
518
|
+
if (name === 'npx' || name === 'pnpx' || name === 'bunx' || name === 'uvx') rest = args;
|
|
519
|
+
else if ((name === 'bun' && args[0] === 'x') || (name === 'pipx' && args[0] === 'run')) rest = args.slice(1);
|
|
520
|
+
else if ((name === 'pnpm' || name === 'yarn') && (args[0] === 'dlx' || args[0] === 'exec')) rest = args.slice(1);
|
|
521
|
+
else if (name === 'npm' && (args[0] === 'exec' || args[0] === 'x')) rest = args.slice(1);
|
|
522
|
+
else if ((name === 'pnpm' || name === 'yarn') && (BROWSER_CLIS.has(args[0]) || JS_RUNTIMES.has(args[0]))) rest = args;
|
|
523
|
+
if (!rest) return null;
|
|
524
|
+
let pkg = null;
|
|
525
|
+
for (let i = 0; i < rest.length; i += 1) {
|
|
526
|
+
const arg = rest[i];
|
|
527
|
+
if (arg === '--') continue;
|
|
528
|
+
if (arg === '-c' || arg === '--call') return { pkg: null, args: [], command: rest[i + 1] ?? '' };
|
|
529
|
+
if (arg === '-p' || arg === '--package') { pkg = pkg || packageName(rest[i + 1]); i += 1; continue; }
|
|
530
|
+
if (arg.startsWith('--package=')) { pkg = pkg || packageName(arg.slice(10)); continue; }
|
|
531
|
+
if (RUNNER_OPTION_VALUES.has(arg)) { i += 1; continue; }
|
|
532
|
+
if (arg.startsWith('-')) continue;
|
|
533
|
+
const bin = packageName(arg);
|
|
534
|
+
// `-p <pkg> <bin>`: the bin that runs decides (npx -p playwright playwright …).
|
|
535
|
+
return { pkg: BROWSER_PACKAGES.has(bin) || JS_RUNTIMES.has(bin) || !pkg ? bin : pkg, args: rest.slice(i + 1), command: null };
|
|
536
|
+
}
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** The files among a command's arguments (option values after = included, URLs not). */
|
|
541
|
+
function pathArgs(args) {
|
|
542
|
+
const out = [];
|
|
543
|
+
for (const arg of args) {
|
|
544
|
+
if (arg === '--') continue;
|
|
545
|
+
const value = arg.startsWith('-') ? (arg.includes('=') ? arg.slice(arg.indexOf('=') + 1) : null) : arg;
|
|
546
|
+
if (value && !URL_ARG.test(value) && PATH_LIKE.test(value)) out.push(value);
|
|
547
|
+
}
|
|
548
|
+
return out;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* A project's own automated tests: npm|pnpm|yarn|bun test (and run test*),
|
|
553
|
+
* node --test, deno test, vitest, jest, playwright test — through a package
|
|
554
|
+
* runner too — run from inside the project (`cwd`, where the command runs, `cd`
|
|
555
|
+
* included) on file arguments, if any, that lie inside it too.
|
|
556
|
+
*/
|
|
557
|
+
function isTestRun(words, { cwd, project }) {
|
|
558
|
+
if (!insideDir(cwd, project)) return false;
|
|
559
|
+
const [head, ...args] = words;
|
|
560
|
+
const name = programName(head);
|
|
561
|
+
let rest = null;
|
|
562
|
+
if (['npm', 'pnpm', 'yarn', 'bun'].includes(name)) {
|
|
563
|
+
const sub = args[0] || '';
|
|
564
|
+
if (sub === 'test' || sub === 't' || sub === 'tst') rest = args.slice(1);
|
|
565
|
+
else if ((sub === 'run' || sub === 'run-script') && /^test(?:[:.\w-]*)$/i.test(args[1] || '')) rest = args.slice(2);
|
|
566
|
+
else if ((name === 'pnpm' || name === 'yarn') && /^test[:.\w-]+$/i.test(sub)) rest = args.slice(1);
|
|
567
|
+
}
|
|
568
|
+
if ((name === 'node' || name === 'nodejs') && args.includes('--test')) rest = args;
|
|
569
|
+
if (name === 'deno' && args[0] === 'test') rest = args.slice(1);
|
|
570
|
+
if (name === 'vitest' || name === 'jest') rest = args;
|
|
571
|
+
let playwright = name === 'playwright' && args[0] === 'test';
|
|
572
|
+
if (playwright) rest = args.slice(1);
|
|
573
|
+
if (rest === null) {
|
|
574
|
+
const run = packageRun(words);
|
|
575
|
+
if (run?.pkg === 'vitest' || run?.pkg === 'jest') rest = run.args;
|
|
576
|
+
else if (PLAYWRIGHT_TEST.has(run?.pkg) && run.args[0] === 'test') { rest = run.args.slice(1); playwright = true; }
|
|
577
|
+
}
|
|
578
|
+
if (rest === null) return false;
|
|
579
|
+
if (playwright && rest.some((arg) => PLAYWRIGHT_INTERACTIVE.test(arg))) return false;
|
|
580
|
+
return pathArgs(rest).every((path) => insideDir(resolvePath(cwd, path), project));
|
|
581
|
+
}
|
|
582
|
+
/** Why a `playwright test` that is not an automated test run is refused. */
|
|
583
|
+
function playwrightTestWhy(runner, args, { cwd, project }) {
|
|
584
|
+
if (args.some((arg) => PLAYWRIGHT_INTERACTIVE.test(arg))) return `${runner} test in its UI or debug mode (a browser window)`;
|
|
585
|
+
return insideDir(cwd, project) ? `${runner} test on files outside the project` : `${runner} test run from ${cwd}, outside the project`;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/** What `open` / xdg-open is asked to show when it is a browser, a URL or a web page, else null. */
|
|
589
|
+
function openDenial(args) {
|
|
590
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
591
|
+
const arg = args[i];
|
|
592
|
+
if (arg === '--args') break; // the rest goes to the app
|
|
593
|
+
if (/^-[A-Za-z]*[ab]$/.test(arg)) {
|
|
594
|
+
const app = args[i + 1];
|
|
595
|
+
if (browserApp(app)) return `opening ${app} with open`;
|
|
596
|
+
i += 1;
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
if (arg.startsWith('-')) continue;
|
|
600
|
+
if (URL_ARG.test(arg) || LOOPBACK_ARG.test(arg)) return `opening ${arg} with open`;
|
|
601
|
+
if (/\.html?$/i.test(arg)) return `opening ${arg} in a browser with open`;
|
|
602
|
+
}
|
|
603
|
+
return null;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// A shell's options that take the next word as their value.
|
|
607
|
+
const SHELL_VALUE_OPTIONS = new Set(['-o', '+o', '-O', '+O', '--rcfile', '--init-file', '-C', '--init-command']);
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* What a shell runs: { command } for `bash -c "…"` (-lc, -ec…), { file } for
|
|
611
|
+
* `bash x.sh`, else {} (its commands come from stdin: -s, a heredoc, < file, a pipe).
|
|
612
|
+
*/
|
|
613
|
+
function shellRun(args) {
|
|
614
|
+
let command = false;
|
|
615
|
+
let stdin = false;
|
|
616
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
617
|
+
const arg = args[i];
|
|
618
|
+
if (arg === '--') {
|
|
619
|
+
const next = args[i + 1];
|
|
620
|
+
if (next === undefined) return {};
|
|
621
|
+
return command ? { command: next } : stdin ? {} : { file: next };
|
|
622
|
+
}
|
|
623
|
+
if (/^-[A-Za-z]*c[A-Za-z]*$/.test(arg)) { command = true; continue; }
|
|
624
|
+
if (/^-[A-Za-z]*s[A-Za-z]*$/.test(arg)) { stdin = true; continue; }
|
|
625
|
+
if (SHELL_VALUE_OPTIONS.has(arg)) { i += 1; continue; }
|
|
626
|
+
if (arg.startsWith('-') || arg.startsWith('+')) continue;
|
|
627
|
+
return command ? { command: arg } : stdin ? {} : { file: arg };
|
|
628
|
+
}
|
|
629
|
+
return {};
|
|
630
|
+
}
|
|
631
|
+
/** The script of `bash -c "…"`, else null. */
|
|
632
|
+
const shellScript = (args) => shellRun(args).command ?? null;
|
|
633
|
+
|
|
634
|
+
/** How a script file runs, by its shebang (else its extension): 'shell', 'code' (JS / Python) or null (a binary, another language). */
|
|
635
|
+
function scriptKind(path, text) {
|
|
636
|
+
const shebang = /^#!\s*(\S+)(.*)/.exec(String(text).split('\n', 1)[0]);
|
|
637
|
+
if (shebang) {
|
|
638
|
+
let program = programName(shebang[1]);
|
|
639
|
+
if (program === 'env') program = programName(shebang[2].trim().split(/\s+/).find((word) => word && !word.startsWith('-') && !word.includes('=')) || '');
|
|
640
|
+
if (SHELLS.has(program)) return 'shell';
|
|
641
|
+
return JS_RUNTIMES.has(program) || PYTHON.test(program) ? 'code' : null;
|
|
642
|
+
}
|
|
643
|
+
if (SCRIPT_FILE.test(path)) return 'code';
|
|
644
|
+
return SHELL_SCRIPT_FILE.test(path) ? 'shell' : null;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** Why a shell script's commands may not run (the script read like a command line), else null. */
|
|
648
|
+
function shellFileDenial(file, ctx, how = 'running') {
|
|
649
|
+
const text = readScript(ctx, resolvePath(ctx.cwd, file));
|
|
650
|
+
if (text === null) return null;
|
|
651
|
+
const why = commandDenial(text, { ...ctx, depth: ctx.depth + 1 });
|
|
652
|
+
return why ? `${how} ${file}, a shell script: ${why}` : null;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Options that take the next word as their value, per runtime.
|
|
656
|
+
const NODE_VALUE_OPTIONS = new Set(['-r', '--require', '--import', '--loader', '--experimental-loader', '-C', '--conditions', '--env-file', '--input-type', '--title', '--test-name-pattern', '--test-reporter', '--test-reporter-destination', '--test-concurrency', '--test-timeout', '--test-shard', '--watch-path', '--inspect-port', '--redirect-warnings', '--disable-warning']);
|
|
657
|
+
const RUNTIME_VALUE_OPTIONS = {
|
|
658
|
+
bun: new Set(['-r', '--preload', '--cwd', '-c', '--config', '--define', '-d', '--tsconfig-override', '--env-file', '--conditions', '--main-fields', '-l', '--loader']),
|
|
659
|
+
deno: new Set(['-c', '--config', '--import-map', '--location', '--seed', '--lock', '--cert', '--env-file', '--ext']),
|
|
660
|
+
ts: new Set(['--tsconfig', '-P', '--project', '-O', '--compiler-options', '-r', '--require', '--import', '--loader', '-C', '--conditions', '--env-file', '--config', '--root', '--mode', '-I', '--ignore']),
|
|
661
|
+
};
|
|
662
|
+
const EVAL_FLAG = /^(?:--eval|--print|-[A-Za-z]*[ep])$/;
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* A JS runtime's arguments → { code: [inline code], script, stdin }: node,
|
|
666
|
+
* bun, deno, tsx, ts-node and friends. `script` "-" or none (and no code):
|
|
667
|
+
* the program comes from stdin.
|
|
668
|
+
*/
|
|
669
|
+
function jsProgram(name, args) {
|
|
670
|
+
const out = { code: [], script: null };
|
|
671
|
+
let list = args;
|
|
672
|
+
let valued = NODE_VALUE_OPTIONS;
|
|
673
|
+
if (name === 'bun') {
|
|
674
|
+
valued = RUNTIME_VALUE_OPTIONS.bun;
|
|
675
|
+
if (list[0] === 'run') list = list.slice(1);
|
|
676
|
+
else if (list[0] && !list[0].startsWith('-') && !PATH_LIKE.test(list[0])) return out; // bun install / build / pm …
|
|
677
|
+
} else if (name === 'deno') {
|
|
678
|
+
valued = RUNTIME_VALUE_OPTIONS.deno;
|
|
679
|
+
if (list[0] === 'eval') { const code = list.slice(1).find((arg) => !arg.startsWith('-')); if (code !== undefined) out.code.push(code); return out; }
|
|
680
|
+
if (list[0] !== 'run') return out; // deno fmt / lint / task …
|
|
681
|
+
list = list.slice(1);
|
|
682
|
+
} else if (name !== 'node' && name !== 'nodejs') {
|
|
683
|
+
valued = RUNTIME_VALUE_OPTIONS.ts;
|
|
684
|
+
if (list[0] === 'watch') list = list.slice(1); // tsx watch <file>
|
|
685
|
+
}
|
|
686
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
687
|
+
const arg = list[i];
|
|
688
|
+
if (arg === '-') { out.script = '-'; return out; }
|
|
689
|
+
if (arg === '--') { out.script = list[i + 1] ?? null; return out; }
|
|
690
|
+
if (/^--(?:eval|print)=/.test(arg)) { out.code.push(arg.slice(arg.indexOf('=') + 1)); return out; }
|
|
691
|
+
if (EVAL_FLAG.test(arg)) { if (list[i + 1] !== undefined) out.code.push(list[i + 1]); return out; }
|
|
692
|
+
if (valued.has(arg)) { i += 1; continue; }
|
|
693
|
+
if (arg.startsWith('-')) continue;
|
|
694
|
+
out.script = arg;
|
|
695
|
+
return out;
|
|
696
|
+
}
|
|
697
|
+
return out;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/** python's arguments → { code, module, script }. */
|
|
701
|
+
function pythonProgram(args) {
|
|
702
|
+
const out = { code: [], module: null, script: null };
|
|
703
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
704
|
+
const arg = args[i];
|
|
705
|
+
if (arg === '-') { out.script = '-'; return out; }
|
|
706
|
+
if (arg === '--') { out.script = args[i + 1] ?? null; return out; }
|
|
707
|
+
if (/^-[A-Za-z]*c$/.test(arg)) { if (args[i + 1] !== undefined) out.code.push(args[i + 1]); return out; }
|
|
708
|
+
if (/^-c./.test(arg)) { out.code.push(arg.slice(2)); return out; }
|
|
709
|
+
if (/^-[A-Za-z]*m$/.test(arg)) { out.module = args[i + 1] ?? null; return out; }
|
|
710
|
+
if (/^-m./.test(arg)) { out.module = arg.slice(2); return out; }
|
|
711
|
+
if (arg === '-W' || arg === '-X' || arg === '--check-hash-based-pycs') { i += 1; continue; }
|
|
712
|
+
if (arg.startsWith('-')) continue;
|
|
713
|
+
out.script = arg;
|
|
714
|
+
return out;
|
|
715
|
+
}
|
|
716
|
+
return out;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Programs whose file arguments are what a pipe hands an interpreter (cat pw.cjs | node).
|
|
720
|
+
const FILE_READERS = new Set(['cat', 'type', 'head', 'tail', 'bat', 'more', 'less']);
|
|
721
|
+
|
|
722
|
+
/** Why an interpreter's program may not run (inline code, a script file, stdin), else null. */
|
|
723
|
+
function interpreterDenial(name, args, seg, ctx) {
|
|
724
|
+
const python = PYTHON.test(name);
|
|
725
|
+
const program = python ? pythonProgram(args) : jsProgram(name, args);
|
|
726
|
+
for (const code of program.code) {
|
|
727
|
+
const what = codeMarker(code);
|
|
728
|
+
if (what) return `inline code that ${what} (${name} ${python ? '-c' : '-e'})`;
|
|
729
|
+
}
|
|
730
|
+
if (program.code.length) return null;
|
|
731
|
+
if (python && program.module && PYTHON_BROWSER_MODULE.test(program.module)) return `python -m ${program.module}`;
|
|
732
|
+
if (program.script && program.script !== '-') {
|
|
733
|
+
const file = resolvePath(ctx.cwd, program.script);
|
|
734
|
+
const what = codeMarker(readScript(ctx, file));
|
|
735
|
+
return what ? `running ${program.script}, a script that ${what}` : null;
|
|
736
|
+
}
|
|
737
|
+
if (python && program.module) return null;
|
|
738
|
+
// The program comes from stdin: a heredoc or here-string, < file, or a pipe.
|
|
739
|
+
for (const body of seg.heredocs) {
|
|
740
|
+
const what = codeMarker(body);
|
|
741
|
+
if (what) return `a heredoc fed to ${name} that ${what}`;
|
|
742
|
+
}
|
|
743
|
+
for (const input of seg.inputs) {
|
|
744
|
+
const what = codeMarker(readScript(ctx, resolvePath(ctx.cwd, input)));
|
|
745
|
+
if (what) return `running ${input}, a script that ${what}`;
|
|
746
|
+
}
|
|
747
|
+
const source = seg.pipedFrom ? commandWords(seg.pipedFrom.words) : [];
|
|
748
|
+
if (source.length) {
|
|
749
|
+
if (FILE_READERS.has(programName(source[0]))) {
|
|
750
|
+
for (const file of source.slice(1).filter((arg) => !arg.startsWith('-'))) {
|
|
751
|
+
const what = codeMarker(readScript(ctx, resolvePath(ctx.cwd, file)));
|
|
752
|
+
if (what) return `piping ${file}, a script that ${what}, into ${name}`;
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
const what = codeMarker(source.slice(1).join(' ')) || codeMarker(seg.pipedFrom.heredocs.join('\n'));
|
|
756
|
+
if (what) return `code piped into ${name} that ${what}`;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/** Why a shell whose commands come from stdin may not run them: a heredoc or here-string, < file, a pipe. */
|
|
763
|
+
function shellStdinDenial(name, seg, ctx) {
|
|
764
|
+
const inner = { ...ctx, depth: ctx.depth + 1 };
|
|
765
|
+
for (const body of seg.heredocs) {
|
|
766
|
+
const why = commandDenial(body, inner);
|
|
767
|
+
if (why) return why;
|
|
768
|
+
}
|
|
769
|
+
for (const input of seg.inputs) {
|
|
770
|
+
const why = shellFileDenial(input, ctx);
|
|
771
|
+
if (why) return why;
|
|
772
|
+
}
|
|
773
|
+
const source = seg.pipedFrom ? commandWords(seg.pipedFrom.words) : [];
|
|
774
|
+
if (!source.length) return null;
|
|
775
|
+
if (FILE_READERS.has(programName(source[0]))) {
|
|
776
|
+
for (const file of source.slice(1).filter((arg) => !arg.startsWith('-'))) {
|
|
777
|
+
const why = shellFileDenial(file, ctx, 'piping');
|
|
778
|
+
if (why) return `${why} (into ${name})`;
|
|
779
|
+
}
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
// echo "google-chrome --headless …" | sh
|
|
783
|
+
return commandDenial(source.slice(1).join(' '), inner) || commandDenial(seg.pipedFrom.heredocs.join('\n'), inner);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/** Why one simple command may not run, else null. `words`: the command itself (commandWords). */
|
|
787
|
+
function segmentDenial(words, seg, ctx) {
|
|
788
|
+
if (!words.length) return null;
|
|
789
|
+
const [head, ...args] = words;
|
|
790
|
+
const name = programName(head);
|
|
791
|
+
const browser = browserProgram(head);
|
|
792
|
+
if (browser) return `${browser} started from the shell`;
|
|
793
|
+
const flag = args.find((arg) => HEADLESS_FLAG.test(arg));
|
|
794
|
+
if (flag && BROWSERISH.test(name)) return `a headless browser (${name} ${flag})`;
|
|
795
|
+
if (name === 'open') return openDenial(args);
|
|
796
|
+
if (name === 'xdg-open' || name === 'gio') {
|
|
797
|
+
const target = args.find((arg) => URL_ARG.test(arg) || LOOPBACK_ARG.test(arg) || /\.html?$/i.test(arg));
|
|
798
|
+
return target ? `opening ${target} with ${name}` : null;
|
|
799
|
+
}
|
|
800
|
+
if (['sensible-browser', 'x-www-browser', 'www-browser'].includes(name)) return `${name} started from the shell`;
|
|
801
|
+
if (SHELLS.has(name)) {
|
|
802
|
+
const run = shellRun(args);
|
|
803
|
+
if (run.command !== undefined) return commandDenial(run.command, { ...ctx, depth: ctx.depth + 1 });
|
|
804
|
+
if (run.file !== undefined) return shellFileDenial(run.file, ctx);
|
|
805
|
+
return shellStdinDenial(name, seg, ctx);
|
|
806
|
+
}
|
|
807
|
+
// source x.sh / . x.sh: the script runs in this shell.
|
|
808
|
+
if (name === 'source' || name === '.') return args[0] ? shellFileDenial(args[0], ctx) : null;
|
|
809
|
+
if (name === 'eval') return commandDenial(args.join(' '), { ...ctx, depth: ctx.depth + 1 });
|
|
810
|
+
if (isTestRun(words, ctx)) return null;
|
|
811
|
+
const run = packageRun(words);
|
|
812
|
+
if (typeof run?.command === 'string') return commandDenial(run.command, { ...ctx, depth: ctx.depth + 1 });
|
|
813
|
+
if (run?.pkg) {
|
|
814
|
+
if (PLAYWRIGHT_TEST.has(run.pkg) && run.args[0] === 'test') return playwrightTestWhy(`${name} ${run.pkg}`, run.args.slice(1), ctx);
|
|
815
|
+
if (BROWSER_PACKAGES.has(run.pkg)) return `${name} ${run.pkg}${run.args[0] ? ` ${run.args[0]}` : ''}`;
|
|
816
|
+
if (JS_RUNTIMES.has(run.pkg)) return interpreterDenial(run.pkg, run.args, seg, ctx);
|
|
817
|
+
return null;
|
|
818
|
+
}
|
|
819
|
+
if (name === 'playwright' && args[0] === 'test') return playwrightTestWhy(name, args.slice(1), ctx);
|
|
820
|
+
if (BROWSER_CLIS.has(name)) return `${name}${args[0] ? ` ${args[0]}` : ''} (a browser CLI)`;
|
|
821
|
+
if (JS_RUNTIMES.has(name) || PYTHON.test(name)) return interpreterDenial(name, args, seg, ctx);
|
|
822
|
+
// A script run as a program (./shot.sh, ./pw.cjs, /tmp/x): by its shebang, else its extension.
|
|
823
|
+
if (/[/\\]/.test(head)) {
|
|
824
|
+
const text = readScript(ctx, resolvePath(ctx.cwd, head));
|
|
825
|
+
if (text === null) return null;
|
|
826
|
+
const kind = scriptKind(head, text);
|
|
827
|
+
if (kind === 'shell') {
|
|
828
|
+
const why = commandDenial(text, { ...ctx, depth: ctx.depth + 1 });
|
|
829
|
+
return why ? `running ${head}, a shell script: ${why}` : null;
|
|
830
|
+
}
|
|
831
|
+
const what = kind === 'code' ? codeMarker(text) : null;
|
|
832
|
+
return what ? `running ${head}, a script that ${what}` : null;
|
|
833
|
+
}
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/** Why a command line may not run (what it does, for the refusal), else null. */
|
|
838
|
+
function commandDenial(text, ctx) {
|
|
839
|
+
if (ctx.depth > MAX_DEPTH) return null;
|
|
840
|
+
let cwd = ctx.cwd;
|
|
841
|
+
for (const seg of simpleCommands(text)) {
|
|
842
|
+
const words = commandWords(seg.words);
|
|
843
|
+
// `cd dir && node pw.cjs`: the rest of the line runs there (a bare cd: the home folder).
|
|
844
|
+
if (words[0] === 'cd' || words[0] === 'pushd') {
|
|
845
|
+
const dir = words.slice(1).find((arg) => !arg.startsWith('-'));
|
|
846
|
+
if (dir) cwd = resolvePath(cwd, dir);
|
|
847
|
+
else if (words[0] === 'cd' && words.length === 1) cwd = homedir();
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
const why = segmentDenial(words, seg, { ...ctx, cwd });
|
|
851
|
+
if (why) return why;
|
|
852
|
+
}
|
|
853
|
+
return null;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/** A shell tool's command: a string (a command line) or an argv array (Codex). */
|
|
857
|
+
function argvDenial(argv, ctx) {
|
|
858
|
+
const words = commandWords(argv.map((arg) => String(arg ?? '')));
|
|
859
|
+
if (!words.length) return null;
|
|
860
|
+
if (SHELLS.has(programName(words[0]))) {
|
|
861
|
+
const script = shellScript(words.slice(1));
|
|
862
|
+
if (script !== null) return commandDenial(script, ctx);
|
|
863
|
+
}
|
|
864
|
+
return segmentDenial(words, { words, heredocs: [], inputs: [], pipedFrom: null }, ctx);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Where each host puts a shell tool's command and its working directory.
|
|
868
|
+
const COMMAND_KEYS = ['command', 'cmd', 'commands', 'script'];
|
|
869
|
+
const WORKDIR_KEYS = ['workdir', 'cwd', 'working_directory', 'workingDirectory', 'dir'];
|
|
870
|
+
|
|
871
|
+
function shellDenial(input, ctx) {
|
|
872
|
+
const args = input && typeof input === 'object' ? input : {};
|
|
873
|
+
const action = args.action && typeof args.action === 'object' ? args.action : {};
|
|
874
|
+
const workdir = [...WORKDIR_KEYS.map((key) => args[key]), ...WORKDIR_KEYS.map((key) => action[key])]
|
|
875
|
+
.find((value) => typeof value === 'string' && isAbsolute(value));
|
|
876
|
+
const inner = { ...ctx, cwd: workdir || ctx.cwd };
|
|
877
|
+
for (const value of [...COMMAND_KEYS.map((key) => args[key]), action.command]) {
|
|
878
|
+
if (typeof value === 'string' && value.trim()) {
|
|
879
|
+
const why = commandDenial(value, inner);
|
|
880
|
+
if (why) return why;
|
|
881
|
+
} else if (Array.isArray(value) && value.length) {
|
|
882
|
+
const why = argvDenial(value, inner);
|
|
883
|
+
if (why) return why;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return null;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// ── the refusal ─────────────────────────────────────────────────────────────
|
|
890
|
+
|
|
891
|
+
function refusal(tool, what) {
|
|
892
|
+
return `SynaBun browser policy: ${tool} was refused — ${what}. Every page, public or localhost, goes through SynaBun's browser tools (browser_navigate, browser_snapshot, browser_screenshot, browser_console and the other browser_* tools), which open the browser configured in SynaBun. If the SynaBun browser fails or cannot do this, stop and report it; do not switch to another browser or tool. The project's own automated tests still run through its test runner (npm test, node --test, npx playwright test).`;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Why this tool call may not run under the browser policy (the refusal text),
|
|
897
|
+
* else null. `host`: claude / codex / opencode (null: any). `cwd`: the
|
|
898
|
+
* project directory: relative script paths resolve against it, and a test
|
|
899
|
+
* runner's files must lie inside it. `readFile(path)` returns an executed
|
|
900
|
+
* script's text or null (tests); by default a regular file up to
|
|
901
|
+
* MAX_SCRIPT_BYTES is read, and anything unreadable is allowed.
|
|
902
|
+
*/
|
|
903
|
+
export function browserToolDenial(tool, input = {}, { host = null, cwd = null, readFile = defaultReadFile } = {}) {
|
|
904
|
+
const name = String(tool ?? '').trim();
|
|
905
|
+
if (!name) return null;
|
|
906
|
+
const kind = hostKey(host);
|
|
907
|
+
const mcp = browserMcpTool(name, kind);
|
|
908
|
+
if (mcp) return refusal(name, mcp);
|
|
909
|
+
const base = synabunLeaf(name) ?? name;
|
|
910
|
+
const lower = base.toLowerCase();
|
|
911
|
+
const args = input && typeof input === 'object' && !Array.isArray(input) ? input : {};
|
|
912
|
+
// Computer use on a browser is refused where the desktop resolves its target
|
|
913
|
+
// (lib/desktop/guards.js); here only an app named in the call is caught early.
|
|
914
|
+
if (lower === 'computer_apps') {
|
|
915
|
+
const action = String(args.action || '').toLowerCase();
|
|
916
|
+
const app = browserApp(args.app);
|
|
917
|
+
if ((action === 'open' || action === 'focus') && app) return refusal(name, `${action === 'open' ? 'opening' : 'focusing'} ${app} with computer use`);
|
|
918
|
+
return null;
|
|
919
|
+
}
|
|
920
|
+
if (isSynabunTool(name) || /^mcp__/i.test(name)) return null;
|
|
921
|
+
if (WEB_TOOLS.has(lower)) return refusal(name, 'web search / fetch outside the SynaBun browser');
|
|
922
|
+
if (!SHELL_TOOLS.has(lower)) return null;
|
|
923
|
+
const project = cwd ? resolve(String(cwd)) : process.cwd();
|
|
924
|
+
const why = shellDenial(args, { project, cwd: project, readFile: typeof readFile === 'function' ? readFile : defaultReadFile, depth: 0 });
|
|
925
|
+
return why ? refusal(name, why) : null;
|
|
926
|
+
}
|