synabun 2.0.10 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +13 -13
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +30 -17
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +7 -6
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +302 -0
- package/lib/virustotal.mjs +203 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +18 -11
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +22 -63
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +14 -14
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +29 -19
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +642 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +81 -21
- package/mcp-server/src/services/server-instructions.ts +29 -64
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +29 -20
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +592 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3953 -228
- package/neural-interface/i18n/pt-BR.json +3901 -179
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +128 -28
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- package/neural-interface/lib/assistant-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +81 -15
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +1073 -200
- package/neural-interface/lib/assistant-envelope.js +156 -2
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +93 -19
- package/neural-interface/lib/assistant-plan-permissions.js +25 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +245 -38
- package/neural-interface/lib/assistant-runtime.js +214 -30
- package/neural-interface/lib/assistant-task-prompt.js +87 -21
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +626 -4
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +84 -0
- package/neural-interface/lib/browser-network-guard.js +476 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +198 -38
- package/neural-interface/lib/claude-agent-bridge.js +11 -2
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +163 -154
- package/neural-interface/lib/cli-resolver.js +13 -3
- package/neural-interface/lib/cli-update-planner.js +52 -41
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +191 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +13 -10
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +35 -33
- package/neural-interface/lib/mcp-external-servers.js +332 -0
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +177 -25
- package/neural-interface/lib/native-loop-providers.js +965 -66
- package/neural-interface/lib/native-loop-runtime.js +290 -42
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +53 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +793 -0
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +20 -2
- package/neural-interface/lib/rulesets/api.js +7 -6
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +180 -36
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +81 -31
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +298 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +285 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +569 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +216 -0
- package/neural-interface/lib/skills/eval-confinement.js +399 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +135 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +203 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +269 -0
- package/neural-interface/lib/skills/runtime-checks.js +358 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +530 -0
- package/neural-interface/lib/skills/telemetry.js +119 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +1268 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +238 -0
- package/neural-interface/lib/worker-sandbox.js +329 -0
- package/neural-interface/package-lock.json +34 -12
- package/neural-interface/package.json +3 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +3 -3
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +125 -31
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- package/neural-interface/public/shared/api.js +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +205 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +445 -82
- package/neural-interface/public/shared/assistant/asst-route.js +304 -53
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
- package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
- package/neural-interface/public/shared/assistant/asst-state.js +87 -24
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
- package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
- package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +11 -12
- package/neural-interface/public/shared/cli-status.js +11 -10
- package/neural-interface/public/shared/constants.js +5 -4
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +367 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/cp/cp-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +21 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +30 -15
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- package/neural-interface/public/shared/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +222 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +149 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1822 -1756
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +111 -140
- package/neural-interface/public/shared/ui-claude-panel.js +376 -82
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- package/neural-interface/public/shared/ui-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +33 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +10 -20
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
- package/neural-interface/public/shared/ui-navbar.js +49 -24
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +27 -15
- package/neural-interface/public/shared/ui-settings.js +683 -526
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +270 -190
- package/neural-interface/public/shared/ui-tool-updates.js +6 -4
- package/neural-interface/public/shared/ui-tooltip.js +81 -51
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +312 -59
- package/neural-interface/public/shared/ui-worker-end.js +5 -1
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +2 -2
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +4553 -2855
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +34 -12
- package/package.json +17 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +6 -6
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ═══════════════════════════════════════════
|
|
2
2
|
// SynaBun — CLI Update Planner
|
|
3
3
|
//
|
|
4
|
-
// Works out HOW each external CLI (Claude Code, Codex, OpenCode,
|
|
4
|
+
// Works out HOW each external CLI (Claude Code, Codex, OpenCode, Antigravity) was
|
|
5
5
|
// installed, and therefore which command actually updates it and which
|
|
6
6
|
// "latest version" it should be compared against.
|
|
7
7
|
//
|
|
@@ -16,12 +16,17 @@
|
|
|
16
16
|
// PATH, so the update silently does nothing and the badge never clears.
|
|
17
17
|
// ═══════════════════════════════════════════
|
|
18
18
|
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* npm package name per tool key. OpenCode has none: npm's opencode-ai is
|
|
21
|
+
* OpenCode 1, which SynaBun does not drive, and OpenCode 2 is installed by its
|
|
22
|
+
* own script, Homebrew or WinGet (lib/opencode-protocol.js). Neither has the
|
|
23
|
+
* Antigravity CLI (`agy`): Google ships it as a binary, through its own
|
|
24
|
+
* installer script or the Homebrew cask antigravity-cli, and it updates itself
|
|
25
|
+
* (`agy update`).
|
|
26
|
+
*/
|
|
20
27
|
export const NPM_PKGS = {
|
|
21
28
|
'claude-code': '@anthropic-ai/claude-code',
|
|
22
29
|
'codex': '@openai/codex',
|
|
23
|
-
'gemini': '@google/gemini-cli',
|
|
24
|
-
'opencode': 'opencode-ai',
|
|
25
30
|
};
|
|
26
31
|
|
|
27
32
|
/**
|
|
@@ -32,21 +37,23 @@ export const NPM_PKGS = {
|
|
|
32
37
|
export const BREW_FALLBACK_TOKENS = {
|
|
33
38
|
'claude-code': 'claude-code',
|
|
34
39
|
'codex': 'codex',
|
|
35
|
-
'
|
|
36
|
-
'opencode
|
|
40
|
+
'antigravity': 'antigravity-cli',
|
|
41
|
+
// OpenCode 2's own tap (its `opencode` formula there is still OpenCode 1).
|
|
42
|
+
'opencode': 'anomalyco/tap/opencode-v2',
|
|
37
43
|
};
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* Whether each tool ships as a Homebrew cask or a formula. This is a property
|
|
41
|
-
* of the package, not of the machine — claude-code
|
|
42
|
-
* casks,
|
|
47
|
+
* of the package, not of the machine — claude-code, codex and antigravity-cli
|
|
48
|
+
* exist ONLY as casks, opencode ONLY as a formula. Needed when a tool is not
|
|
43
49
|
* installed and there is no path to classify: guessing the wrong flavour
|
|
44
|
-
* produces a command that simply errors ("
|
|
50
|
+
* produces a command that simply errors ("No available formula with the name
|
|
51
|
+
* 'antigravity-cli'").
|
|
45
52
|
*/
|
|
46
53
|
export const BREW_KINDS = {
|
|
47
54
|
'claude-code': 'cask',
|
|
48
55
|
'codex': 'cask',
|
|
49
|
-
'
|
|
56
|
+
'antigravity': 'cask',
|
|
50
57
|
'opencode': 'formula',
|
|
51
58
|
};
|
|
52
59
|
|
|
@@ -55,23 +62,22 @@ const SELF_UPDATERS = {
|
|
|
55
62
|
'claude-code': 'claude update',
|
|
56
63
|
'codex': 'codex update',
|
|
57
64
|
'opencode': 'opencode upgrade',
|
|
58
|
-
|
|
65
|
+
'antigravity': 'agy update',
|
|
59
66
|
};
|
|
60
67
|
|
|
61
68
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* the channels we
|
|
69
|
+
* The `upgrade --method` of OpenCode 2 for a detected source (its own installer
|
|
70
|
+
* script, a JavaScript package manager, WinGet). Mapping our detected source
|
|
71
|
+
* onto it lets OpenCode do its own install-aware work for the channels we
|
|
72
|
+
* cannot drive directly.
|
|
65
73
|
*/
|
|
66
74
|
const OPENCODE_METHODS = {
|
|
67
75
|
'standalone': 'curl',
|
|
68
76
|
'npm': 'npm',
|
|
69
77
|
'pnpm': 'pnpm',
|
|
70
78
|
'bun': 'bun',
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'choco': 'choco',
|
|
74
|
-
'scoop': 'scoop',
|
|
79
|
+
'yarn': 'yarn',
|
|
80
|
+
'winget': 'winget',
|
|
75
81
|
};
|
|
76
82
|
|
|
77
83
|
/** Sources that mean "a package manager other than the tool itself owns this". */
|
|
@@ -196,7 +202,7 @@ const TOOL_COMMANDS = {
|
|
|
196
202
|
'claude-code': 'claude',
|
|
197
203
|
'codex': 'codex',
|
|
198
204
|
'opencode': 'opencode',
|
|
199
|
-
'
|
|
205
|
+
'antigravity': 'agy',
|
|
200
206
|
};
|
|
201
207
|
|
|
202
208
|
/**
|
|
@@ -248,6 +254,15 @@ function planUpdateCommand(toolKey, installSource, { brewToken = null, platform
|
|
|
248
254
|
: `brew upgrade ${token}`;
|
|
249
255
|
}
|
|
250
256
|
|
|
257
|
+
// OpenCode 2 updates itself through the channel it came from (brew is handled above).
|
|
258
|
+
if (toolKey === 'opencode') {
|
|
259
|
+
// Its installer script is bash: a copy in %USERPROFILE%\.opencode\bin on Windows is no OpenCode 2 install.
|
|
260
|
+
if (installSource === 'standalone' && platform === 'win32') return null;
|
|
261
|
+
if (OPENCODE_METHODS[installSource]) return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
|
|
262
|
+
if (['volta', 'scoop', 'choco'].includes(installSource)) return null; // not an OpenCode 2 channel: the caller shows a hint
|
|
263
|
+
return selfUpdate;
|
|
264
|
+
}
|
|
265
|
+
|
|
251
266
|
if (!npmPkg) return selfUpdate;
|
|
252
267
|
|
|
253
268
|
switch (installSource) {
|
|
@@ -255,24 +270,15 @@ function planUpdateCommand(toolKey, installSource, { brewToken = null, platform
|
|
|
255
270
|
case 'yarn': return `yarn global add ${npmPkg}@latest`;
|
|
256
271
|
case 'volta': return `volta install ${npmPkg}@latest`;
|
|
257
272
|
case 'bun':
|
|
273
|
+
return `bun add -g ${npmPkg}@latest`;
|
|
258
274
|
case 'pnpm':
|
|
259
|
-
|
|
260
|
-
if (toolKey === 'opencode') return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
|
|
261
|
-
return installSource === 'bun'
|
|
262
|
-
? `bun add -g ${npmPkg}@latest`
|
|
263
|
-
: `pnpm add -g ${npmPkg}@latest`;
|
|
275
|
+
return `pnpm add -g ${npmPkg}@latest`;
|
|
264
276
|
case 'scoop':
|
|
265
277
|
case 'choco':
|
|
266
|
-
if (toolKey === 'opencode') return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
|
|
267
|
-
return null; // no safe automated path — caller shows a hint
|
|
268
278
|
case 'winget':
|
|
269
|
-
return null;
|
|
279
|
+
return null; // no safe automated path — caller shows a hint
|
|
270
280
|
case 'standalone':
|
|
271
281
|
// The tool's own installer put it here, so its own updater is right.
|
|
272
|
-
// OpenCode's `curl` method runs its bash install script, which Windows
|
|
273
|
-
// does not have: a copy in %USERPROFILE%\.opencode\bin there came from
|
|
274
|
-
// the release archive (lib/cli-install.js) and has no updater to call.
|
|
275
|
-
if (toolKey === 'opencode') return platform === 'win32' ? null : 'opencode upgrade --method curl';
|
|
276
282
|
return selfUpdate;
|
|
277
283
|
case 'native':
|
|
278
284
|
return selfUpdate;
|
|
@@ -373,10 +379,13 @@ export function installSourceLabel(source) {
|
|
|
373
379
|
/**
|
|
374
380
|
* The install command each vendor documents first for an operating system
|
|
375
381
|
* (checked 2026-10-17): Anthropic's native installer (code.claude.com/docs/en/setup),
|
|
376
|
-
* OpenAI's standalone installer (learn.chatgpt.com/docs/codex/cli), OpenCode's
|
|
377
|
-
* install script (opencode.ai/
|
|
378
|
-
*
|
|
379
|
-
*
|
|
382
|
+
* OpenAI's standalone installer (learn.chatgpt.com/docs/codex/cli), OpenCode 2's
|
|
383
|
+
* install script (https://opencode.ai/v2/install, the one `opencode upgrade`
|
|
384
|
+
* runs; on Windows, where the script does not run, WinGet), and (checked
|
|
385
|
+
* 2026-10-30) Google's Antigravity CLI installer
|
|
386
|
+
* (antigravity.google/docs/getting-started). These are the same official
|
|
387
|
+
* sources the Install button runs (lib/cli-install.js), which on a Mac with
|
|
388
|
+
* Homebrew installs the Antigravity CLI's cask instead.
|
|
380
389
|
*/
|
|
381
390
|
export function vendorInstallCommand(toolKey, platform = process.platform) {
|
|
382
391
|
const windows = platform === 'win32';
|
|
@@ -388,7 +397,11 @@ export function vendorInstallCommand(toolKey, platform = process.platform) {
|
|
|
388
397
|
? 'powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"'
|
|
389
398
|
: 'curl -fsSL https://chatgpt.com/codex/install.sh | sh';
|
|
390
399
|
case 'opencode':
|
|
391
|
-
return windows ?
|
|
400
|
+
return windows ? 'winget install --id Anomaly.OpenCode --exact' : 'curl -fsSL https://opencode.ai/v2/install | bash';
|
|
401
|
+
case 'antigravity':
|
|
402
|
+
// Google's installer: it checks the binary against the SHA-512 of Google's release manifest and puts agy in
|
|
403
|
+
// ~/.local/bin (%LOCALAPPDATA%\agy\bin on Windows). A Homebrew machine is told the cask (buildInstallCommand).
|
|
404
|
+
return windows ? 'irm https://antigravity.google/cli/install.ps1 | iex' : 'curl -fsSL https://antigravity.google/cli/install.sh | bash';
|
|
392
405
|
default:
|
|
393
406
|
return NPM_PKGS[toolKey] ? `npm install -g ${NPM_PKGS[toolKey]}` : '';
|
|
394
407
|
}
|
|
@@ -420,7 +433,9 @@ export function buildInstallCommand(toolKey, installSource = 'unknown', { platfo
|
|
|
420
433
|
? `brew install --cask ${token}`
|
|
421
434
|
: `brew install ${token}`;
|
|
422
435
|
}
|
|
423
|
-
|
|
436
|
+
// OpenCode 2 and the Antigravity CLI have no npm package: their vendor's installer whatever JavaScript package
|
|
437
|
+
// manager the machine uses.
|
|
438
|
+
if (!npmPkg) return vendorInstallCommand(toolKey, platform || process.platform);
|
|
424
439
|
switch (installSource) {
|
|
425
440
|
case 'bun': return `bun add -g ${npmPkg}`;
|
|
426
441
|
case 'pnpm': return `pnpm add -g ${npmPkg}`;
|
|
@@ -438,10 +453,6 @@ function platformInstallCommand(toolKey, installSource, platform) {
|
|
|
438
453
|
if (windows && installSource === 'winget') return 'winget install Anthropic.ClaudeCode';
|
|
439
454
|
return vendor;
|
|
440
455
|
}
|
|
441
|
-
if (toolKey === 'opencode' && windows) {
|
|
442
|
-
if (installSource === 'scoop') return 'scoop install opencode';
|
|
443
|
-
if (installSource === 'choco') return 'choco install opencode';
|
|
444
|
-
}
|
|
445
456
|
// A JavaScript package manager this machine already uses: keep to it.
|
|
446
457
|
if (['npm', 'bun', 'pnpm', 'yarn', 'volta'].includes(installSource)) return null;
|
|
447
458
|
return vendor || null;
|
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
//
|
|
29
29
|
// An ended process is not forgotten: it is asked to end (SIGTERM), killed when
|
|
30
30
|
// it is still there a moment later (SIGKILL), and kept until it has exited.
|
|
31
|
+
//
|
|
32
|
+
// Each cloudflared it starts is on record from its spawn until it has exited
|
|
33
|
+
// (`records`: lib/opencode-serve-records.js, kind 'quick', in
|
|
34
|
+
// DATA_HOME/runtime/tunnels), with a token of its start in its environment. A
|
|
35
|
+
// server that ends without its exit handlers (a native crash) leaves its
|
|
36
|
+
// cloudflared running on macOS and Linux (Windows ends a child with its parent),
|
|
37
|
+
// the old address still pointing at the port the next server listens on: the
|
|
38
|
+
// next server ends it by that record (server.js sweepLeftoverTunnels), and only
|
|
39
|
+
// while the OS still reports that very process.
|
|
31
40
|
|
|
32
41
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
33
42
|
|
|
@@ -69,6 +78,22 @@ export function tunnelArguments(port, source) {
|
|
|
69
78
|
return ['tunnel', ...(source === 'system' ? [] : ['--no-autoupdate']), '--url', `http://localhost:${port}`];
|
|
70
79
|
}
|
|
71
80
|
|
|
81
|
+
/** The kind of the tunnel's records (lib/opencode-serve-records.js createServeRecords `kinds`). */
|
|
82
|
+
export const TUNNEL_KINDS = Object.freeze(['quick']);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Are `args` (a command line's arguments, as the platform reads them: lib/opencode-serve-records.js commandArgs) a
|
|
86
|
+
* quick tunnel to this server's `port` (`… tunnel … --url http://localhost:<port>`, as tunnelArguments makes them)?
|
|
87
|
+
* What a tunnel record must name.
|
|
88
|
+
*/
|
|
89
|
+
export function tunnelsToPort(args, port) {
|
|
90
|
+
const p = Number(port);
|
|
91
|
+
if (!Array.isArray(args) || !Number.isInteger(p) || p <= 0 || p > 65535) return false;
|
|
92
|
+
if (!args.includes('tunnel')) return false;
|
|
93
|
+
const url = `http://localhost:${p}`;
|
|
94
|
+
return args.some((arg, i) => arg === `--url=${url}` || (arg === '--url' && args[i + 1] === url));
|
|
95
|
+
}
|
|
96
|
+
|
|
72
97
|
/** What cloudflared said last that reads like a reason: its last error line, without the timestamp. */
|
|
73
98
|
function lastReason(output) {
|
|
74
99
|
const lines = output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
@@ -85,8 +110,10 @@ function lastReason(output) {
|
|
|
85
110
|
* @param {number} [o.urlTimeoutMs] how long a started cloudflared may take to print its address
|
|
86
111
|
* @param {number} [o.killAfterMs] how long an ended cloudflared has to exit before it is killed
|
|
87
112
|
* @param {(line: string) => void} [o.log]
|
|
113
|
+
* @param {{ newToken: () => string, tokenEnv: string, record: (entry: object) => Promise<object|null>, remove: (entry: object) => boolean }} [o.records]
|
|
114
|
+
* where each cloudflared it starts is kept on record until it has exited (lib/opencode-serve-records.js, kind 'quick')
|
|
88
115
|
*/
|
|
89
|
-
export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn = nodeSpawn, urlTimeoutMs = 90_000, killAfterMs = 1000, log = () => {} }) {
|
|
116
|
+
export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn = nodeSpawn, urlTimeoutMs = 90_000, killAfterMs = 1000, log = () => {}, records = null }) {
|
|
90
117
|
let phase = 'idle'; // idle | preparing | starting | running | failed
|
|
91
118
|
let child = null;
|
|
92
119
|
let url = null;
|
|
@@ -117,7 +144,19 @@ export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn =
|
|
|
117
144
|
log(` Tunnel: ${code === 'ended' ? 'stopped' : 'not started'} (${code}): ${message}`);
|
|
118
145
|
}
|
|
119
146
|
|
|
147
|
+
// On record from its spawn until it has exited: what the next server ends when this one crashed (see above).
|
|
148
|
+
function keepOnRecord(proc, token) {
|
|
149
|
+
const pid = Number(proc?.pid) || null;
|
|
150
|
+
if (!pid) return;
|
|
151
|
+
const kept = Promise.resolve().then(() => records.record({ kind: TUNNEL_KINDS[0], port: Number(port), pid, token })).catch(() => null);
|
|
152
|
+
proc.once('exit', () => { kept.then((entry) => { if (entry) records.remove(entry); }).catch(() => {}); });
|
|
153
|
+
}
|
|
154
|
+
|
|
120
155
|
function launch(found, mine) {
|
|
156
|
+
// The token of this start, in its environment: made before the check below, so nothing runs between them.
|
|
157
|
+
let token = null;
|
|
158
|
+
try { token = records?.tokenEnv ? records.newToken() : null; } catch { token = null; }
|
|
159
|
+
const options = { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, ...(token ? { env: { ...process.env, [records.tokenEnv]: token } } : {}) };
|
|
121
160
|
// Checked once more as it is about to run (the manager's confirm: the very file its check read, still where
|
|
122
161
|
// nobody else can change it), and started at once by the real path that was checked: nothing runs in between.
|
|
123
162
|
let path = found.path;
|
|
@@ -128,10 +167,11 @@ export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn =
|
|
|
128
167
|
}
|
|
129
168
|
let proc;
|
|
130
169
|
try {
|
|
131
|
-
proc = spawn(path, tunnelArguments(port, found.source),
|
|
170
|
+
proc = spawn(path, tunnelArguments(port, found.source), options);
|
|
132
171
|
} catch (failure) {
|
|
133
172
|
return fail('launch', `cloudflared could not be started (${failure?.code || failure?.message || failure}).`);
|
|
134
173
|
}
|
|
174
|
+
if (token) keepOnRecord(proc, token);
|
|
135
175
|
child = proc;
|
|
136
176
|
copy = { source: found.source, version: found.version };
|
|
137
177
|
phase = 'starting';
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { codexMcpToolApproval } from '../public/shared/cdx/cdx-protocol.js';
|
|
2
|
+
|
|
1
3
|
const CODEX_MCP_APPROVAL_MODES = new Set(['auto', 'prompt', 'writes', 'approve']);
|
|
2
4
|
|
|
5
|
+
/** Auto is this session's choice; Claude's allow list is not a Codex approval prerequisite. */
|
|
6
|
+
export function shouldAutoAcceptCodexMcpToolApproval(params, { autoAccept = false, role = null } = {}) {
|
|
7
|
+
const approval = codexMcpToolApproval(params);
|
|
8
|
+
if (!approval) return false;
|
|
9
|
+
// agent_route owns the model-choice card. Calling it must not require an
|
|
10
|
+
// additional permission card, even when ordinary tools are set to Ask.
|
|
11
|
+
return autoAccept || (role === 'assistant' && approval.fullName === 'mcp__SynaBun__agent_route');
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
export function codexConfigKeyPathSegment(value) {
|
|
4
15
|
const text = String(value || '').trim();
|
|
5
16
|
if (!text) throw new Error('Codex config key path segments cannot be empty');
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ── A Codex rollout, read once for the preview and the history fallback ──
|
|
2
|
+
// The early preview (server.js sendEarlyCodexRolloutPreview) used to readFileSync the
|
|
3
|
+
// whole rollout JSONL before Codex's app-server started, for every thread a tab
|
|
4
|
+
// bootstrapped, and the history fallback read it again right after. This reads it as
|
|
5
|
+
// a stream (the event loop and the app-server's start are not held up) and keeps the
|
|
6
|
+
// parsed items of the last few files by path, size and time, so the fallback that
|
|
7
|
+
// follows reuses them while the file is unchanged.
|
|
8
|
+
|
|
9
|
+
import { createReadStream, statSync } from 'node:fs';
|
|
10
|
+
import { jsonlLines } from './jsonl-lines.js';
|
|
11
|
+
|
|
12
|
+
export function createRolloutReader({
|
|
13
|
+
open = (path) => createReadStream(path, { encoding: 'utf-8' }),
|
|
14
|
+
stat = statSync,
|
|
15
|
+
maxEntries = 4,
|
|
16
|
+
} = {}) {
|
|
17
|
+
const kept = new Map(); // path → { size, mtimeMs, items }
|
|
18
|
+
const running = new Map(); // `${path}|${size}|${mtimeMs}` → promise of items
|
|
19
|
+
const stats = { reads: 0, reused: 0 };
|
|
20
|
+
|
|
21
|
+
/** The items `parse(lines)` makes of the file at `path` (an async iterable of its lines). */
|
|
22
|
+
async function items(path, parse) {
|
|
23
|
+
if (!path) return [];
|
|
24
|
+
let st;
|
|
25
|
+
try { st = stat(path); } catch { return []; }
|
|
26
|
+
const hit = kept.get(path);
|
|
27
|
+
if (hit && hit.size === st.size && hit.mtimeMs === st.mtimeMs) {
|
|
28
|
+
stats.reused++;
|
|
29
|
+
kept.delete(path); kept.set(path, hit);
|
|
30
|
+
return hit.items;
|
|
31
|
+
}
|
|
32
|
+
const key = `${path}|${st.size}|${st.mtimeMs}`;
|
|
33
|
+
if (running.has(key)) { stats.reused++; return running.get(key); }
|
|
34
|
+
const job = (async () => {
|
|
35
|
+
stats.reads++;
|
|
36
|
+
const stream = open(path);
|
|
37
|
+
try {
|
|
38
|
+
const out = await parse(jsonlLines(stream));
|
|
39
|
+
kept.delete(path);
|
|
40
|
+
kept.set(path, { size: st.size, mtimeMs: st.mtimeMs, items: out });
|
|
41
|
+
while (kept.size > maxEntries) kept.delete(kept.keys().next().value);
|
|
42
|
+
return out;
|
|
43
|
+
} finally {
|
|
44
|
+
stream.destroy?.();
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
running.set(key, job);
|
|
48
|
+
try { return await job; } finally { running.delete(key); }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { items, forget: (path) => kept.delete(path), get stats() { return { ...stats }; }, get size() { return kept.size; } };
|
|
52
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// One app-server per dispatched worker. The SDK-shaped surface keeps the native
|
|
2
|
+
// worker's event/usage contract while thread/resume reopens its durable thread.
|
|
3
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
4
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
5
|
+
|
|
6
|
+
const toml = (v) => Array.isArray(v) ? `[${v.map(toml).join(',')}]`
|
|
7
|
+
: v && typeof v === 'object' ? `{${Object.entries(v).filter(([, x]) => x != null).map(([k, x]) => `${JSON.stringify(k)}=${toml(x)}`).join(',')}}`
|
|
8
|
+
: JSON.stringify(v);
|
|
9
|
+
|
|
10
|
+
// Match the SDK's leaf overrides: pins/switches address only their intended
|
|
11
|
+
// fields and leave native command/url/env definitions in the native config.
|
|
12
|
+
// Codex splits override paths literally on dots (it does not parse TOML keys).
|
|
13
|
+
// Top-level keys may already be override paths; nested keys are literal segments.
|
|
14
|
+
export function codexWorkerConfigOverrides(config) {
|
|
15
|
+
const overrides = [];
|
|
16
|
+
const visit = (value, path) => {
|
|
17
|
+
if (value == null) return;
|
|
18
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
19
|
+
for (const [key, child] of Object.entries(value)) {
|
|
20
|
+
if (path && /[.=\x00-\x1f\x7f]/.test(key)) throw new Error('Codex override paths cannot address this config key');
|
|
21
|
+
visit(child, path ? `${path}.${key}` : key);
|
|
22
|
+
}
|
|
23
|
+
} else overrides.push(`${path}=${toml(value)}`);
|
|
24
|
+
};
|
|
25
|
+
visit(config, '');
|
|
26
|
+
return overrides;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class CodexWorkerAppServer {
|
|
30
|
+
constructor({ codexPathOverride, env, config = {}, configArgs = [], apiKey, signal, onProcess = () => {}, onRequest = null, permissionPolicy = 'auto' }) {
|
|
31
|
+
this.onRequest = onRequest;
|
|
32
|
+
this.approvalPolicy = permissionPolicy === 'ask' ? 'untrusted' : 'never';
|
|
33
|
+
this.requestAbort = new AbortController();
|
|
34
|
+
this.incoming = new Map();
|
|
35
|
+
this.requestAbort.signal.addEventListener('abort', () => { for (const pending of this.incoming.values()) pending.abort(); this.incoming.clear(); }, { once: true });
|
|
36
|
+
this.pending = new Map();
|
|
37
|
+
this.seq = 0;
|
|
38
|
+
this.listener = null;
|
|
39
|
+
this.failure = null;
|
|
40
|
+
const args = [...configArgs];
|
|
41
|
+
for (const override of codexWorkerConfigOverrides(config)) args.push('-c', override);
|
|
42
|
+
// Run identity in the command line permits conservative orphan identification.
|
|
43
|
+
args.push('-c', `synabun_worker_run=${JSON.stringify(env.SYNABUN_TERMINAL_SESSION || '')}`, 'app-server');
|
|
44
|
+
this.proc = spawn(codexPathOverride, args, { env, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
45
|
+
this.exited = new Promise((r) => this.proc.once('close', r));
|
|
46
|
+
onProcess({ pid: this.proc.pid, startedAt: new Date().toISOString() });
|
|
47
|
+
let buffer = '';
|
|
48
|
+
const decoder = new StringDecoder('utf8');
|
|
49
|
+
this.proc.stdout.on('data', (chunk) => {
|
|
50
|
+
buffer += decoder.write(chunk);
|
|
51
|
+
let end;
|
|
52
|
+
while ((end = buffer.indexOf('\n')) >= 0) {
|
|
53
|
+
const line = buffer.slice(0, end); buffer = buffer.slice(end + 1);
|
|
54
|
+
let msg; try { msg = JSON.parse(line); } catch { continue; }
|
|
55
|
+
if (msg.id != null && !msg.method) {
|
|
56
|
+
const p = this.pending.get(msg.id); if (!p) continue;
|
|
57
|
+
this.pending.delete(msg.id); clearTimeout(p.timer);
|
|
58
|
+
msg.error ? p.reject(new Error(msg.error.message || 'Codex RPC failed')) : p.resolve(msg.result);
|
|
59
|
+
} else if (msg.id != null) {
|
|
60
|
+
const controller = new AbortController();
|
|
61
|
+
this.incoming.set(msg.id, controller);
|
|
62
|
+
Promise.resolve().then(() => {
|
|
63
|
+
if (!this.onRequest) throw new Error('Worker has no interactive request handler');
|
|
64
|
+
return this.onRequest(msg, controller.signal);
|
|
65
|
+
}).then((reply) => {
|
|
66
|
+
if (!this.failure && !controller.signal.aborted) this.write({ id: msg.id, ...reply });
|
|
67
|
+
}, (error) => {
|
|
68
|
+
if (!this.failure && !controller.signal.aborted) this.write({ id: msg.id, error: { code: -32000, message: error.message } });
|
|
69
|
+
}).finally(() => this.incoming.delete(msg.id));
|
|
70
|
+
} else {
|
|
71
|
+
if (msg.method === 'serverRequest/resolved') this.incoming.get(msg.params?.requestId)?.abort();
|
|
72
|
+
if (msg.method === 'turn/completed') { for (const pending of this.incoming.values()) pending.abort(); this.incoming.clear(); }
|
|
73
|
+
this.listener?.(msg);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// Drain stderr without exposing credentials/config to the worker transcript.
|
|
78
|
+
this.proc.stderr.resume();
|
|
79
|
+
this.proc.on('error', (error) => this.fail(error));
|
|
80
|
+
this.proc.stdin.on('error', (error) => this.fail(error));
|
|
81
|
+
this.proc.on('close', (code, signal) => this.fail(new Error(`Codex app-server exited (${signal || code})`)));
|
|
82
|
+
this.ready = (async () => {
|
|
83
|
+
await this.rpc('initialize', { clientInfo: { name: 'synabun-worker', version: '1.0.0' }, capabilities: { experimentalApi: true } });
|
|
84
|
+
this.write({ method: 'initialized', params: {} });
|
|
85
|
+
if (apiKey) await this.rpc('account/login/start', { type: 'apiKey', apiKey });
|
|
86
|
+
})();
|
|
87
|
+
this.ready.catch(() => {});
|
|
88
|
+
this.startupSignal = signal;
|
|
89
|
+
this.cancelStartup = () => { this.dispose().catch(() => {}); };
|
|
90
|
+
signal?.addEventListener('abort', this.cancelStartup, { once: true });
|
|
91
|
+
if (signal?.aborted) this.cancelStartup();
|
|
92
|
+
}
|
|
93
|
+
write(value) { if (!this.proc.stdin.destroyed) this.proc.stdin.write(JSON.stringify(value) + '\n'); }
|
|
94
|
+
fail(error) {
|
|
95
|
+
this.failure = error;
|
|
96
|
+
this.requestAbort.abort();
|
|
97
|
+
for (const p of this.pending.values()) { clearTimeout(p.timer); p.reject(error); }
|
|
98
|
+
this.pending.clear();
|
|
99
|
+
this.listener?.({ method: 'synabun/exit', error });
|
|
100
|
+
}
|
|
101
|
+
rpc(method, params) {
|
|
102
|
+
if (this.failure) return Promise.reject(this.failure);
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const id = ++this.seq;
|
|
105
|
+
const timer = setTimeout(() => { this.pending.delete(id); reject(new Error(`Codex ${method} timed out`)); }, 30_000);
|
|
106
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
107
|
+
this.write({ id, method, params });
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
startThread(options) { return this.thread(null, options); }
|
|
111
|
+
resumeThread(id, options) { return this.thread(id, options); }
|
|
112
|
+
thread(id, options) {
|
|
113
|
+
const owner = this;
|
|
114
|
+
const sandboxPolicy = options.sandboxMode === 'read-only' ? { type: 'readOnly', networkAccess: !!options.networkAccessEnabled }
|
|
115
|
+
: options.sandboxMode === 'workspace-write' ? { type: 'workspaceWrite', writableRoots: [options.workingDirectory, ...(options.additionalDirectories || [])], networkAccess: !!options.networkAccessEnabled }
|
|
116
|
+
: { type: 'dangerFullAccess' };
|
|
117
|
+
const ready = this.ready.then(async () => {
|
|
118
|
+
const reply = await this.rpc(id ? 'thread/resume' : 'thread/start', {
|
|
119
|
+
...(id ? { threadId: id } : {}), cwd: options.workingDirectory,
|
|
120
|
+
model: options.model || null, approvalPolicy: owner.approvalPolicy, sandbox: options.sandboxMode,
|
|
121
|
+
config: { web_search: options.webSearchMode || 'disabled', sandbox_workspace_write: { network_access: !!options.networkAccessEnabled, writable_roots: options.additionalDirectories || [] } },
|
|
122
|
+
});
|
|
123
|
+
const actual = reply?.thread?.id;
|
|
124
|
+
if (!actual || (id && actual !== id)) throw new Error('Codex did not resume the requested thread');
|
|
125
|
+
id = actual;
|
|
126
|
+
});
|
|
127
|
+
ready.catch(() => {});
|
|
128
|
+
return {
|
|
129
|
+
get id() { return id; }, ready: () => ready,
|
|
130
|
+
async runStreamed(prompt, { signal, outputSchema } = {}) {
|
|
131
|
+
await ready;
|
|
132
|
+
const queue = []; const text = new Map(); let wake; let done = false; let failure; let turnId;
|
|
133
|
+
const push = (event) => { queue.push(event); wake?.(); };
|
|
134
|
+
const abort = () => {
|
|
135
|
+
failure = Object.assign(new Error('Codex turn aborted'), { name: 'AbortError' }); done = true; wake?.();
|
|
136
|
+
if (turnId) owner.rpc('turn/interrupt', { threadId: id, turnId }).catch(() => {});
|
|
137
|
+
};
|
|
138
|
+
owner.listener = (msg) => {
|
|
139
|
+
const p = msg.params || {};
|
|
140
|
+
if (p.threadId && p.threadId !== id) return;
|
|
141
|
+
if (msg.method === 'synabun/exit') { failure = msg.error; done = true; wake?.(); }
|
|
142
|
+
if (msg.method === 'item/agentMessage/delta') {
|
|
143
|
+
const value = (text.get(p.itemId) || '') + (p.delta || '');
|
|
144
|
+
text.set(p.itemId, value);
|
|
145
|
+
push({ type: 'item.updated', item: { id: p.itemId, type: 'agent_message', text: value } });
|
|
146
|
+
}
|
|
147
|
+
if (msg.method === 'item/started' || msg.method === 'item/completed') {
|
|
148
|
+
const item = p.item || {};
|
|
149
|
+
const types = { agentMessage: 'agent_message', commandExecution: 'command_execution', fileChange: 'file_change', mcpToolCall: 'mcp_tool_call', webSearch: 'web_search', reasoning: 'reasoning' };
|
|
150
|
+
push({ type: msg.method === 'item/started' ? 'item.started' : 'item.completed', item: { ...item, type: types[item.type] || item.type, aggregated_output: item.aggregatedOutput, exit_code: item.exitCode } });
|
|
151
|
+
}
|
|
152
|
+
if (msg.method === 'turn/completed') {
|
|
153
|
+
if (p.turn?.status === 'failed') push({ type: 'turn.failed', error: p.turn.error || { message: 'Codex turn failed' } });
|
|
154
|
+
else if (p.turn?.status === 'interrupted') failure = Object.assign(new Error('Codex turn interrupted'), { name: 'AbortError' });
|
|
155
|
+
else push({ type: 'turn.completed' }); // rollout meter is authoritative across resumes
|
|
156
|
+
done = true; wake?.();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
160
|
+
try {
|
|
161
|
+
if (signal?.aborted) throw Object.assign(new Error('Codex turn aborted'), { name: 'AbortError' });
|
|
162
|
+
const reply = await owner.rpc('turn/start', { threadId: id, input: [{ type: 'text', text: String(prompt), text_elements: [] }], approvalPolicy: owner.approvalPolicy, sandboxPolicy, effort: options.modelReasoningEffort || null, ...(outputSchema ? { outputSchema } : {}) });
|
|
163
|
+
turnId = reply?.turn?.id;
|
|
164
|
+
if (signal?.aborted) abort();
|
|
165
|
+
} catch (error) { owner.listener = null; signal?.removeEventListener('abort', abort); throw error; }
|
|
166
|
+
return { events: (async function* () {
|
|
167
|
+
try {
|
|
168
|
+
yield { type: 'thread.started', thread_id: id };
|
|
169
|
+
while (!done || queue.length) {
|
|
170
|
+
if (queue.length) yield queue.shift();
|
|
171
|
+
else await new Promise((r) => { wake = r; });
|
|
172
|
+
}
|
|
173
|
+
if (failure) throw failure;
|
|
174
|
+
} finally { owner.listener = null; signal?.removeEventListener('abort', abort); }
|
|
175
|
+
})() };
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async dispose() {
|
|
180
|
+
this.requestAbort.abort();
|
|
181
|
+
this.startupSignal?.removeEventListener('abort', this.cancelStartup);
|
|
182
|
+
if (this.proc.exitCode !== null || this.proc.signalCode) return;
|
|
183
|
+
if (process.platform === 'win32') {
|
|
184
|
+
try { execFileSync('taskkill', ['/pid', String(this.proc.pid), '/T', '/F'], { timeout: 5000, stdio: 'ignore', windowsHide: true }); } catch {}
|
|
185
|
+
} else this.proc.kill('SIGTERM');
|
|
186
|
+
let timer;
|
|
187
|
+
await Promise.race([this.exited, new Promise((r) => { timer = setTimeout(r, 1500); })]);
|
|
188
|
+
clearTimeout(timer);
|
|
189
|
+
if (this.proc.exitCode === null && !this.proc.signalCode) this.proc.kill('SIGKILL');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// sequence; it does not remove it.
|
|
20
20
|
|
|
21
21
|
import {
|
|
22
|
-
openSync, closeSync, fstatSync, lstatSync, readSync, writeSync, ftruncateSync, fsyncSync,
|
|
22
|
+
openSync, closeSync, fstatSync, fchmodSync, lstatSync, readSync, writeSync, ftruncateSync, fsyncSync,
|
|
23
23
|
mkdirSync, readdirSync, rmSync, unlinkSync, renameSync, realpathSync, createReadStream, constants,
|
|
24
24
|
} from 'node:fs';
|
|
25
25
|
import { randomBytes } from 'node:crypto';
|
|
@@ -142,6 +142,17 @@ export function writeConfinedFile(base, path, data, { exclusive = false, mode =
|
|
|
142
142
|
if (!st.isFile()) throw new PathConfineError(400, 'Not a regular file.');
|
|
143
143
|
if (!created) ftruncateSync(fd, 0);
|
|
144
144
|
writeAll(fd, data);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
// A file this call created and could not fill (the disk filled, the data could not be had) is not left
|
|
147
|
+
// half written: it is removed while it is still the file that was opened.
|
|
148
|
+
if (created) {
|
|
149
|
+
try {
|
|
150
|
+
const mine = fstatSync(fd);
|
|
151
|
+
const now = lstatSync(real);
|
|
152
|
+
if (now.dev === mine.dev && now.ino === mine.ino) unlinkSync(real);
|
|
153
|
+
} catch { /* gone already, or no longer ours */ }
|
|
154
|
+
}
|
|
155
|
+
throw err;
|
|
145
156
|
} finally { try { closeSync(fd); } catch {} }
|
|
146
157
|
return real;
|
|
147
158
|
}
|
|
@@ -173,14 +184,29 @@ export function removeConfinedEntry(base, path) {
|
|
|
173
184
|
return true;
|
|
174
185
|
}
|
|
175
186
|
|
|
187
|
+
/**
|
|
188
|
+
* What is at `path` itself, a link not followed: 'absent', 'file', 'dir', 'link' or 'other' (a FIFO, a
|
|
189
|
+
* socket, a device). Nothing is opened.
|
|
190
|
+
*/
|
|
191
|
+
export function entryKind(path) {
|
|
192
|
+
let st;
|
|
193
|
+
try { st = lstatSync(String(path)); } catch { return 'absent'; }
|
|
194
|
+
if (st.isSymbolicLink()) return 'link';
|
|
195
|
+
if (st.isFile()) return 'file';
|
|
196
|
+
if (st.isDirectory()) return 'dir';
|
|
197
|
+
return 'other';
|
|
198
|
+
}
|
|
199
|
+
|
|
176
200
|
/**
|
|
177
201
|
* Replace `path` with `data` through a temporary file in the same folder:
|
|
178
202
|
* created exclusively under an unpredictable name, never through a link, then
|
|
179
203
|
* renamed over `path` (a rename replaces a link, it does not follow it).
|
|
180
204
|
* `expect` is the file's state when it was read ({ dev, ino, mtimeMs, size }):
|
|
181
|
-
* a file that changed since is not overwritten (409).
|
|
205
|
+
* a file that changed since is not overwritten (409). `exactMode`: the new
|
|
206
|
+
* file gets `mode` as it is, not narrowed by the process umask (a file that
|
|
207
|
+
* replaces another keeps the permissions that one had).
|
|
182
208
|
*/
|
|
183
|
-
export function replaceFileAtomic(path, data, { mode = 0o600, expect = null } = {}) {
|
|
209
|
+
export function replaceFileAtomic(path, data, { mode = 0o600, expect = null, exactMode = false } = {}) {
|
|
184
210
|
const dir = realPathOf(dirname(String(path)));
|
|
185
211
|
const target = join(dir, basename(String(path)));
|
|
186
212
|
const tmp = join(dir, `.${basename(target)}.${randomBytes(12).toString('hex')}.tmp`);
|
|
@@ -190,6 +216,7 @@ export function replaceFileAtomic(path, data, { mode = 0o600, expect = null } =
|
|
|
190
216
|
try {
|
|
191
217
|
const st = verifyOpened(fd, tmp);
|
|
192
218
|
if (!st.isFile()) throw moved();
|
|
219
|
+
if (exactMode) fchmodSync(fd, mode & 0o7777);
|
|
193
220
|
writeAll(fd, data);
|
|
194
221
|
try { fsyncSync(fd); } catch {}
|
|
195
222
|
} finally { try { closeSync(fd); } catch {} }
|