synabun 2.0.10 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +2 -2
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +17 -8
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +1 -1
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +228 -0
- package/lib/virustotal.mjs +192 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +16 -10
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +20 -62
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -10
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +22 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +639 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/neural-interface.ts +79 -20
- package/mcp-server/src/services/server-instructions.ts +27 -63
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +22 -14
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/skill-tools.ts +589 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3463 -200
- package/neural-interface/i18n/pt-BR.json +3411 -151
- package/neural-interface/lib/assistant-api.js +127 -28
- 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-catalog.js +6 -7
- package/neural-interface/lib/assistant-dispatch.js +871 -156
- package/neural-interface/lib/assistant-envelope.js +3 -1
- package/neural-interface/lib/assistant-persona.js +80 -11
- package/neural-interface/lib/assistant-plan-permissions.js +10 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +13 -8
- package/neural-interface/lib/assistant-runtime.js +56 -18
- package/neural-interface/lib/assistant-task-prompt.js +78 -14
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/backup-service.js +620 -3
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +83 -0
- package/neural-interface/lib/browser-network-guard.js +284 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +186 -31
- package/neural-interface/lib/claude-agent-bridge.js +4 -2
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install.js +18 -138
- package/neural-interface/lib/cli-resolver.js +4 -1
- package/neural-interface/lib/cli-update-planner.js +32 -31
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-worker-app-server.js +172 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/exec-loop-command.js +4 -8
- 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 +0 -29
- package/neural-interface/lib/mcp-external-servers.js +323 -0
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/morelogin.js +30 -0
- package/neural-interface/lib/native-loop-providers.js +547 -47
- package/neural-interface/lib/native-loop-runtime.js +268 -41
- 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 +44 -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/peer-identity.js +763 -0
- package/neural-interface/lib/request-gate.js +17 -2
- package/neural-interface/lib/rulesets/api.js +1 -1
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +92 -27
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +17 -30
- 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 +294 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +267 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +564 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +214 -0
- package/neural-interface/lib/skills/eval-confinement.js +397 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +119 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +200 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +262 -0
- package/neural-interface/lib/skills/runtime-checks.js +355 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +522 -0
- package/neural-interface/lib/skills/telemetry.js +113 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/worker-confinement.js +1192 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +229 -0
- package/neural-interface/lib/worker-sandbox.js +299 -0
- package/neural-interface/package-lock.json +18 -12
- package/neural-interface/package.json +2 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +2 -2
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +35 -19
- 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 +33 -2
- 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 +49 -35
- package/neural-interface/public/shared/assistant/asst-control.js +157 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +106 -11
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +401 -77
- package/neural-interface/public/shared/assistant/asst-route.js +83 -12
- package/neural-interface/public/shared/assistant/asst-scenes.js +2 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
- package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
- package/neural-interface/public/shared/assistant/asst-state.js +11 -15
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +59 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +156 -16
- 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 +8 -7
- package/neural-interface/public/shared/cdx/cdx-panel.js +45 -149
- package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
- package/neural-interface/public/shared/cdx/cdx-render.js +47 -29
- package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +11 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +52 -39
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-view.js +4 -8
- package/neural-interface/public/shared/cli-status.js +2 -2
- package/neural-interface/public/shared/constants.js +2 -2
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +366 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-update-view.js +20 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/html-shell.js +9 -11
- 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 +47 -252
- 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-render.js +6 -21
- 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 +0 -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 +14 -47
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +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-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/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +219 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +141 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1525 -1779
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-automation-studio.js +91 -128
- package/neural-interface/public/shared/ui-claude-panel.js +77 -5
- 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-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-keybinds.js +26 -1
- package/neural-interface/public/shared/ui-menubar.js +8 -18
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +7 -1
- package/neural-interface/public/shared/ui-navbar.js +4 -24
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-schedules-studio.js +507 -423
- package/neural-interface/public/shared/ui-sessions.js +5 -3
- package/neural-interface/public/shared/ui-settings.js +594 -462
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +1 -1
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
- 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 +124 -180
- package/neural-interface/public/shared/ui-tool-updates.js +3 -1
- package/neural-interface/public/shared/ui-tooltip.js +10 -5
- package/neural-interface/public/shared/ui-trash.js +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 +311 -58
- package/neural-interface/public/shared/ui-worker-end.js +4 -0
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +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 +3934 -2454
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +18 -12
- package/package.json +16 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +4 -4
- 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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// composer attachments, Claude/Codex account management, and the sidepanel tab registry.
|
|
8
8
|
// Mounted from server.js with `app.use('/api/assistant', createAssistantApi(deps))`.
|
|
9
9
|
|
|
10
|
+
import { dispatchInput } from './assistant-tools.js';
|
|
10
11
|
import { Router } from 'express';
|
|
11
12
|
import { DispatchError } from './assistant-dispatch.js';
|
|
12
13
|
import { openServable } from './assistant-media.js';
|
|
@@ -42,7 +43,7 @@ const NO_CATALOG = Object.freeze({});
|
|
|
42
43
|
function sendError(res, error, fallbackStatus = 500) {
|
|
43
44
|
if (error instanceof DispatchError || (error && error.code && error.status)) {
|
|
44
45
|
const status = Number(error.status) || fallbackStatus;
|
|
45
|
-
const body = typeof error.toJSON === 'function' ? error.toJSON() : { code: error.code, message: error.message };
|
|
46
|
+
const body = typeof error.toJSON === 'function' ? error.toJSON() : { code: error.code, message: error.message, ...(error.problems ? { problems: error.problems } : {}) };
|
|
46
47
|
return res.status(status).json({ ok: false, error: body.message, ...body });
|
|
47
48
|
}
|
|
48
49
|
return res.status(fallbackStatus).json({ ok: false, error: error?.message || String(error), code: error?.code || 'INTERNAL' });
|
|
@@ -96,7 +97,7 @@ export function slimRunView(run) {
|
|
|
96
97
|
* @param {object} [deps.runtime] createAssistantRuntime() (sessions; optional until wired)
|
|
97
98
|
* @param {object} [deps.claudeAccounts] createClaudeAccounts()
|
|
98
99
|
* @param {object} [deps.codexAccounts] createCodexAccounts() (lib/codex-accounts.js)
|
|
99
|
-
* @param {Function} [deps.buildCatalog] async () => catalog object (models/accounts/projects/
|
|
100
|
+
* @param {Function} [deps.buildCatalog] async () => catalog object (models/accounts/projects/tools)
|
|
100
101
|
* @param {Function} [deps.createLoginTerminal] async ({ env, cwd, profile, accountId }) => { terminalSessionId, profile }
|
|
101
102
|
* @param {Function} [deps.claudeSignIn] async (accountId) => { sessionId, status, error } — Claude Code's own
|
|
102
103
|
* `auth login` in a SynaBun terminal under the account's config directory (lib/provider-panel-terminal-auth.js)
|
|
@@ -153,6 +154,11 @@ export function createAssistantApi({
|
|
|
153
154
|
port = 3344,
|
|
154
155
|
// The Admin sandbox setting (lib/agent-sandbox-setting.js): one global value for every agent SynaBun starts.
|
|
155
156
|
adminSandbox = null,
|
|
157
|
+
// Protect workers (lib/worker-guard-setting.js): what capability read-only / workspace means for every worker.
|
|
158
|
+
workerGuard = null,
|
|
159
|
+
// The page secret (lib/page-session.js): a request without an agent pin is the owner's page only when it carries
|
|
160
|
+
// this boot's cookie; a local process that merely sends no headers is nobody (never 'ui').
|
|
161
|
+
pageSession = null,
|
|
156
162
|
} = {}) {
|
|
157
163
|
if (!dispatcher) throw new Error('createAssistantApi requires a dispatcher');
|
|
158
164
|
const router = Router();
|
|
@@ -164,20 +170,31 @@ export function createAssistantApi({
|
|
|
164
170
|
next();
|
|
165
171
|
});
|
|
166
172
|
|
|
167
|
-
// Resolve who is calling: the UI (no pin),
|
|
168
|
-
//
|
|
173
|
+
// Resolve who is calling: the UI (the page secret cookie, no pin), a dispatched worker (run id pin →
|
|
174
|
+
// forbidden for orchestration), or nobody known. A brain is NOT decided here: a pin only records which
|
|
175
|
+
// session a request *claims* to be (for attribution), never that the request is that session's brain.
|
|
176
|
+
// Brain authority is the per-launch credential alone (brainCaller) — the final pre-restart review
|
|
177
|
+
// (run f283e53b) showed a forged `X-Synabun-Terminal: assistant-*`, and equally a real but non-secret
|
|
178
|
+
// session id (a worker's environment and its task text both carry one), would otherwise pass as the brain.
|
|
169
179
|
function callerContext(req) {
|
|
170
180
|
const pin = String(req.get('x-synabun-terminal') || req.get('x-synabun-assistant') || '').trim();
|
|
171
181
|
const bodySession = req.body?.assistantSessionId || req.body?.assistant_session_id || req.query?.assistantSessionId || null;
|
|
172
|
-
if (!pin)
|
|
182
|
+
if (!pin) {
|
|
183
|
+
// The page: this boot's page secret cookie (the browser sends it by itself). Without a page session wired
|
|
184
|
+
// (a test, an older host) every pinless request is the page, as before.
|
|
185
|
+
if (pageSession && typeof pageSession.verify === 'function' && !pageSession.verify(req)) return { kind: 'unknown', assistantSessionId: bodySession ? String(bodySession) : null, pin: '', pageless: true };
|
|
186
|
+
return { kind: 'ui', assistantSessionId: bodySession ? String(bodySession) : null };
|
|
187
|
+
}
|
|
173
188
|
if (dispatcher.get(pin)) return { kind: 'worker', forbidden: true, pin };
|
|
174
|
-
//
|
|
175
|
-
// OpenCode brain pins assistant-oc-<24
|
|
189
|
+
// The session a request claims, for attribution once a credential has proven it a brain: a Claude brain's
|
|
190
|
+
// pin resolves to its session; the OpenCode brain pins assistant-oc-<24> (never taken as an id) and names
|
|
191
|
+
// the session in the body. The claim grants nothing on its own.
|
|
176
192
|
const resolved = runtime?.resolveTerminal?.(pin) || null;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
193
|
+
const claimed = resolved
|
|
194
|
+
|| (/^assistant-oc-/.test(pin) ? (bodySession ? String(bodySession) : null)
|
|
195
|
+
: /^assistant-/.test(pin) ? pin
|
|
196
|
+
: (bodySession ? String(bodySession) : null));
|
|
197
|
+
return { kind: 'unknown', assistantSessionId: claimed, pin };
|
|
181
198
|
}
|
|
182
199
|
/**
|
|
183
200
|
* The plan mode of the brain making this call: 'read-only' (a remote session
|
|
@@ -212,20 +229,56 @@ export function createAssistantApi({
|
|
|
212
229
|
function orchestrationGuard(req, res, next) {
|
|
213
230
|
const caller = callerContext(req);
|
|
214
231
|
if (caller.forbidden) return res.status(403).json({ ok: false, code: 'AGENTS_NOT_PERMITTED', error: 'Dispatched workers cannot orchestrate other agents.' });
|
|
215
|
-
|
|
216
|
-
next();
|
|
232
|
+
// The user's own page (this boot's page secret cookie): the only caller that orchestrates without being a brain.
|
|
233
|
+
if (caller.kind === 'ui') { req.assistantCaller = caller; return next(); }
|
|
234
|
+
// The only other caller allowed is an Assistant brain, and only its per-launch credential proves it (brainCaller):
|
|
235
|
+
// never a pin, never a session id, which a worker's environment and its task text both carry. This is the forged-
|
|
236
|
+
// and known-pin bypass the final pre-restart review found (run f283e53b, assistant-api.js:189): an
|
|
237
|
+
// `X-Synabun-Terminal: assistant-*` header, or a real live session id, used to pass here as the brain.
|
|
238
|
+
const brain = brainCaller(req);
|
|
239
|
+
if (brain) { req.assistantCaller = brain; return next(); }
|
|
240
|
+
return res.status(403).json({ ok: false, code: 'UI_ONLY', error: 'Orchestration is the user\'s (from SynaBun\'s own page) and the Assistant\'s brain\'s: this request is neither (no page secret, no brain launch credential a live session knows).' });
|
|
217
241
|
}
|
|
218
242
|
/**
|
|
219
|
-
* The caller when it is an assistant brain, else null.
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
243
|
+
* The caller when it is an assistant brain, else null. The one proof is the per-launch credential
|
|
244
|
+
* (X-Synabun-Brain-Token, SYNABUN_BRAIN_TOKEN in the brain's own environment only, minted per brain launch and
|
|
245
|
+
* resolved by runtime.sessionForBrainCredential over the live brains): a pin or a session id names nobody here,
|
|
246
|
+
* because any local process can send a header and a session id is not secret (a worker carries its own, and ids
|
|
247
|
+
* appear in task text). The credential's session is authoritative, whatever pin or body the request carries. The
|
|
248
|
+
* UI, workers and other sessions never count.
|
|
223
249
|
*/
|
|
224
250
|
function brainCaller(req) {
|
|
251
|
+
if (req.assistantCaller?.credentialed) return req.assistantCaller;
|
|
252
|
+
if (String(req.get('x-synabun-role') || '').trim().toLowerCase() !== 'assistant') return null;
|
|
253
|
+
let session = null;
|
|
254
|
+
try { session = runtime?.sessionForBrainCredential?.(req.get('x-synabun-brain-token')) || null; } catch { session = null; }
|
|
255
|
+
if (!session) return null;
|
|
225
256
|
const caller = req.assistantCaller || callerContext(req);
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
257
|
+
return { ...caller, kind: 'assistant', assistantSessionId: String(session), credentialed: true };
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Who may READ a run (GET /runs/:id, /result, /transcript): the owner's page (ui), a credential-verified
|
|
261
|
+
* Assistant brain (its session's runs, as today), or the worker of that very run — a worker's pin is its own
|
|
262
|
+
* run id, so it reads only itself, never another run. Everyone else (a pinless local process with no page
|
|
263
|
+
* secret, a worker naming another run) is refused. Listing and deletion are owner-or-brain only (never a worker):
|
|
264
|
+
* the list is not "its own run", and a finished run is cleared by the owner or the brain that owns its session.
|
|
265
|
+
*/
|
|
266
|
+
function runReadAllowed(req, runId) {
|
|
267
|
+
const caller = callerContext(req);
|
|
268
|
+
if (caller.kind === 'ui') return true;
|
|
269
|
+
const brain = brainCaller(req);
|
|
270
|
+
if (brain) {
|
|
271
|
+
// A brain reads only its OWN session's runs (like DELETE): another session's run is not readable through the
|
|
272
|
+
// credential. A run with no session, or a sessionless brain, falls through as before (nothing to scope to).
|
|
273
|
+
const runSession = dispatcher.get(runId)?.assistantSessionId || null;
|
|
274
|
+
if (runSession && brain.assistantSessionId && String(runSession) !== String(brain.assistantSessionId)) return false;
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
if (caller.kind === 'worker' && caller.pin && String(caller.pin) === String(runId)) return true;
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
function refuseRunRead(res) {
|
|
281
|
+
return res.status(403).json({ ok: false, code: 'RUN_FORBIDDEN', error: 'This run is readable by the owner (from SynaBun\'s own page), its own worker and the Assistant brain of its session only.' });
|
|
229
282
|
}
|
|
230
283
|
/** A remote session whose workers only a person may answer (strict worker approvals below autonomous). */
|
|
231
284
|
function humanApprovalRequired(assistantSessionId) {
|
|
@@ -363,9 +416,8 @@ export function createAssistantApi({
|
|
|
363
416
|
try {
|
|
364
417
|
const body = req.body || {};
|
|
365
418
|
const spec = {
|
|
366
|
-
...body,
|
|
419
|
+
...dispatchInput(body),
|
|
367
420
|
accountId: body.accountId || body.account_id || body.codexAccountId || body.claudeAccountId || null,
|
|
368
|
-
mcpProfile: body.mcpProfile || body.mcp_profile,
|
|
369
421
|
permissionPolicy: body.permissionPolicy || body.permission_policy,
|
|
370
422
|
maxMinutes: body.maxMinutes ?? body.max_minutes,
|
|
371
423
|
budgetUsd: body.budgetUsd ?? body.budget_usd,
|
|
@@ -724,18 +776,25 @@ export function createAssistantApi({
|
|
|
724
776
|
});
|
|
725
777
|
|
|
726
778
|
router.get('/runs', (req, res) => {
|
|
779
|
+
// Listing is owner-or-brain only: a worker reads its own run by id, never the roster of every run.
|
|
780
|
+
const caller = callerContext(req);
|
|
781
|
+
const brain = brainCaller(req);
|
|
782
|
+
if (caller.kind !== 'ui' && !brain) return refuseRunRead(res);
|
|
727
783
|
try {
|
|
728
784
|
const active = req.query.active === '1' || req.query.activeOnly === '1';
|
|
785
|
+
// A brain sees only its OWN session's runs (its session id forced over whatever the query asks); the owner's
|
|
786
|
+
// page may list any session.
|
|
787
|
+
const scopedSession = (brain && caller.kind !== 'ui') ? (brain.assistantSessionId || null) : (req.query.assistantSessionId || null);
|
|
729
788
|
res.json({
|
|
730
789
|
ok: true,
|
|
731
790
|
runs: dispatcher.list({
|
|
732
791
|
activeOnly: active,
|
|
733
|
-
assistantSessionId:
|
|
792
|
+
assistantSessionId: scopedSession,
|
|
734
793
|
workflowId: req.query.workflowId || null,
|
|
735
794
|
status: req.query.status || null,
|
|
736
795
|
limit: clampInt(req.query.limit, 1, 500, 100),
|
|
737
796
|
}),
|
|
738
|
-
totals: dispatcher.totals({ assistantSessionId:
|
|
797
|
+
totals: dispatcher.totals({ assistantSessionId: scopedSession, workflowId: req.query.workflowId || null }),
|
|
739
798
|
});
|
|
740
799
|
} catch (error) { sendError(res, error); }
|
|
741
800
|
});
|
|
@@ -768,12 +827,19 @@ export function createAssistantApi({
|
|
|
768
827
|
if (!assistantSessionId && !workflowId && req.assistantCaller.kind !== 'ui') {
|
|
769
828
|
return res.status(400).json({ ok: false, code: 'SCOPE_REQUIRED', error: 'Pass assistant_session_id (your ASSISTANT_SESSION_ID) or workflow_id to stop runs.' });
|
|
770
829
|
}
|
|
771
|
-
const
|
|
830
|
+
const reason = body.reason || 'kill_all';
|
|
831
|
+
const result = await dispatcher.killAll({ assistantSessionId, workflowId, reason });
|
|
832
|
+
// Who stopped every run, when: the records only say `kill_all` (2026-10-24 had to be traced by elimination).
|
|
833
|
+
const caller = req.assistantCaller.kind === 'ui' ? 'the page' : `the brain of ${req.assistantCaller.assistantSessionId || 'an unknown session'}`;
|
|
834
|
+
const scope = [assistantSessionId ? `session ${assistantSessionId}` : null, workflowId ? `workflow ${workflowId}` : null].filter(Boolean).join(', ') || 'every session';
|
|
835
|
+
const stopped = Array.isArray(result?.stopped) ? result.stopped : [];
|
|
836
|
+
log('kill-all', `${new Date(now()).toISOString()} ${caller} stopped ${stopped.length} run(s) of ${scope} (${reason})${stopped.length ? `: ${stopped.join(', ')}` : ''}`);
|
|
772
837
|
res.json(result);
|
|
773
838
|
} catch (error) { sendError(res, error); }
|
|
774
839
|
});
|
|
775
840
|
|
|
776
841
|
router.get('/runs/:runId', (req, res) => {
|
|
842
|
+
if (!runReadAllowed(req, req.params.runId)) return refuseRunRead(res);
|
|
777
843
|
const run = dispatcher.get(req.params.runId);
|
|
778
844
|
if (!run) return res.status(404).json({ ok: false, code: 'RUN_NOT_FOUND', error: `Unknown run ${req.params.runId}` });
|
|
779
845
|
const brain = brainCaller(req);
|
|
@@ -781,6 +847,7 @@ export function createAssistantApi({
|
|
|
781
847
|
res.json({ ok: true, run: brain ? slimRunView(run) : run });
|
|
782
848
|
});
|
|
783
849
|
router.get('/runs/:runId/result', (req, res) => {
|
|
850
|
+
if (!runReadAllowed(req, req.params.runId)) return refuseRunRead(res);
|
|
784
851
|
try {
|
|
785
852
|
const out = dispatcher.transcript(req.params.runId, { format: 'result' });
|
|
786
853
|
if (out?.result) {
|
|
@@ -791,6 +858,7 @@ export function createAssistantApi({
|
|
|
791
858
|
} catch (error) { sendError(res, error); }
|
|
792
859
|
});
|
|
793
860
|
router.get('/runs/:runId/transcript', (req, res) => {
|
|
861
|
+
if (!runReadAllowed(req, req.params.runId)) return refuseRunRead(res);
|
|
794
862
|
try {
|
|
795
863
|
const format = req.query.format || 'tail';
|
|
796
864
|
const out = dispatcher.transcript(req.params.runId, {
|
|
@@ -811,6 +879,7 @@ export function createAssistantApi({
|
|
|
811
879
|
// path from the request; owner-only like everything here. sendFile answers
|
|
812
880
|
// Range requests, so a video seeks.
|
|
813
881
|
router.get('/runs/:runId/media/:n', async (req, res) => {
|
|
882
|
+
if (!runReadAllowed(req, req.params.runId)) return refuseRunRead(res);
|
|
814
883
|
const notFound = () => res.status(404).json({ ok: false, code: 'MEDIA_NOT_FOUND', error: `No media ${req.params.n} for run ${req.params.runId}` });
|
|
815
884
|
if (!/^\d{1,4}$/.test(String(req.params.n))) return notFound();
|
|
816
885
|
let file = null;
|
|
@@ -900,10 +969,23 @@ export function createAssistantApi({
|
|
|
900
969
|
router.post('/runs/:runId/stop', orchestrationGuard, async (req, res) => {
|
|
901
970
|
try { res.json(await dispatcher.stop(req.params.runId, req.body?.reason || (req.assistantCaller.kind === 'ui' ? 'user' : 'assistant'))); } catch (error) { sendError(res, error); }
|
|
902
971
|
});
|
|
903
|
-
// Finished runs are cleared from the agents tray by the
|
|
972
|
+
// Finished runs are cleared from the agents tray by the owner (the page) or the Assistant brain of the run's
|
|
973
|
+
// own session; never by a worker (even its own run). A brain's delete is scoped to its session's runs.
|
|
904
974
|
router.delete('/runs/:runId', async (req, res) => {
|
|
905
|
-
|
|
906
|
-
|
|
975
|
+
const caller = callerContext(req);
|
|
976
|
+
const brain = brainCaller(req);
|
|
977
|
+
if (caller.kind !== 'ui' && !brain) return res.status(403).json({ ok: false, code: 'UI_ONLY', error: 'Finished runs are removed by the owner (from SynaBun\'s own page) or the Assistant brain of the run\'s session.' });
|
|
978
|
+
if (brain && caller.kind !== 'ui') {
|
|
979
|
+
// A brain removes only the runs of its own session: another session's run is left untouched.
|
|
980
|
+
const runSession = dispatcher.get(req.params.runId)?.assistantSessionId || null;
|
|
981
|
+
if (runSession && brain.assistantSessionId && String(runSession) !== String(brain.assistantSessionId)) {
|
|
982
|
+
return res.status(403).json({ ok: false, code: 'RUN_NOT_IN_SESSION', error: `Run ${req.params.runId} belongs to another assistant session` });
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
const assistantSessionId = (brain && caller.kind !== 'ui')
|
|
986
|
+
? (brain.assistantSessionId || null)
|
|
987
|
+
: (req.query.assistantSessionId || req.body?.assistantSessionId || null);
|
|
988
|
+
try { res.json(await dispatcher.remove(req.params.runId, { assistantSessionId })); } catch (error) { sendError(res, error); }
|
|
907
989
|
});
|
|
908
990
|
router.post('/runs/clear-finished', async (req, res) => {
|
|
909
991
|
if (callerContext(req).kind !== 'ui') return res.status(403).json({ ok: false, code: 'UI_ONLY', error: 'Finished runs are removed from the assistant panel only.' });
|
|
@@ -1263,6 +1345,23 @@ export function createAssistantApi({
|
|
|
1263
1345
|
try { res.json({ ok: true, ...adminSandbox.set(value) }); } catch (error) { sendError(res, error); }
|
|
1264
1346
|
});
|
|
1265
1347
|
|
|
1348
|
+
// ── Protect workers (lib/worker-guard-setting.js) ──────────────────────────
|
|
1349
|
+
// What capability read-only / workspace means for every worker the dispatcher starts
|
|
1350
|
+
// (lib/worker-confinement.js): enforce (default), warn, off. The user's setting: an agent cannot change it.
|
|
1351
|
+
router.get('/worker-guard', (req, res) => {
|
|
1352
|
+
if (!workerGuard) return res.status(503).json({ ok: false, code: 'WORKER_GUARD_UNAVAILABLE', error: 'The Protect workers setting is not available on this server' });
|
|
1353
|
+
res.json({ ok: true, ...workerGuard.view() });
|
|
1354
|
+
});
|
|
1355
|
+
router.put('/worker-guard', requireJson, (req, res) => {
|
|
1356
|
+
if (!workerGuard) return res.status(503).json({ ok: false, code: 'WORKER_GUARD_UNAVAILABLE', error: 'The Protect workers setting is not available on this server' });
|
|
1357
|
+
if (callerContext(req).kind !== 'ui' || req.get('x-synabun-desktop-grant') || req.get('x-synabun-role')) {
|
|
1358
|
+
return res.status(403).json({ ok: false, code: 'UI_ONLY', error: 'Only the user can change Protect workers.' });
|
|
1359
|
+
}
|
|
1360
|
+
const value = req.body?.mode;
|
|
1361
|
+
if (typeof value !== 'string' || !workerGuard.view().modes.includes(value)) return res.status(400).json({ ok: false, code: 'INVALID_VALUE', error: `mode must be one of ${workerGuard.view().modes.join(', ')}.` });
|
|
1362
|
+
try { res.json({ ok: true, ...workerGuard.set(value) }); } catch (error) { sendError(res, error); }
|
|
1363
|
+
});
|
|
1364
|
+
|
|
1266
1365
|
// ── sidepanel tab registry (UI heartbeat) ──────────────────────────────────
|
|
1267
1366
|
function listTabs() {
|
|
1268
1367
|
const cutoff = now() - tabTtlMs;
|
|
@@ -123,10 +123,11 @@ export function createClaudeBrain({ session, sink, deps = {}, persona = '', hook
|
|
|
123
123
|
'X-Synabun-Role': 'assistant', 'X-Synabun-Terminal': session.id, 'X-Synabun-Memory-Session': session.id,
|
|
124
124
|
...(deps.desktopGrant ? { 'X-Synabun-Desktop-Grant': deps.desktopGrant } : {}),
|
|
125
125
|
...mcpHeaders,
|
|
126
|
-
//
|
|
126
|
+
// This brain launch's credential (assistant-runtime.js mintBrainCredential). The header names the variable and
|
|
127
127
|
// the CLI expands it from its own environment (below): the MCP config is on its command line, which every
|
|
128
128
|
// account of the computer can read, an environment only this user's processes. The in-process MCP server
|
|
129
|
-
// keeps the value for the request it arrived with, and sends it
|
|
129
|
+
// keeps the value for the request it arrived with, and sends it only to the routes that ask who the brain is
|
|
130
|
+
// (whatsapp_send_file, the Skills Service). Last, so nothing replaces it.
|
|
130
131
|
...(deps.brainCredential ? { 'X-Synabun-Brain-Token': '${SYNABUN_BRAIN_TOKEN}' } : {}),
|
|
131
132
|
},
|
|
132
133
|
// A remote (WhatsApp) session never pre-approves computer use: its PreToolUse hook refuses, asks or allows each call.
|
|
@@ -143,7 +144,7 @@ export function createClaudeBrain({ session, sink, deps = {}, persona = '', hook
|
|
|
143
144
|
...(typeof deps.claudeAccountEnv === 'function' ? deps.claudeAccountEnv(brain.accountId) : {}),
|
|
144
145
|
SYNABUN_ASSISTANT_SESSION: String(session.id),
|
|
145
146
|
...(deps.userContextThreads === true ? { SYNABUN_ASSISTANT_THREADS: '1' } : {}),
|
|
146
|
-
// The value of the X-Synabun-Brain-Token header above
|
|
147
|
+
// The value of the X-Synabun-Brain-Token header above.
|
|
147
148
|
...(deps.brainCredential ? { SYNABUN_BRAIN_TOKEN: deps.brainCredential } : {}),
|
|
148
149
|
},
|
|
149
150
|
maxBudgetUsd: Number(deps.maxBudgetUsd) > 0 ? Number(deps.maxBudgetUsd) : undefined,
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
// PreToolUse payload from stdin and asks lib/browser-tool-policy.js here, with
|
|
7
7
|
// no server round trip; a refusal becomes permissionDecision "deny" with the
|
|
8
8
|
// reason. Script paths resolve against the payload's cwd, else
|
|
9
|
-
// SYNABUN_BROWSER_POLICY_CWD (the run's project)
|
|
9
|
+
// SYNABUN_BROWSER_POLICY_CWD (the run's project); SYNABUN_BROWSER_POLICY_ROOTS
|
|
10
|
+
// (a JSON list, written as the run starts) names the registered code projects
|
|
11
|
+
// its test runners may also run in. An unreadable payload allows
|
|
10
12
|
// the call: the policy is a speed bump, not a sandbox. A policy module that
|
|
11
13
|
// cannot load fails closed (logged on stderr): shell commands, web search and
|
|
12
14
|
// every MCP tool but SynaBun's are denied with that reason.
|
|
@@ -25,6 +27,14 @@ function unloadedDenial(tool) {
|
|
|
25
27
|
return `SynaBun browser policy: ${tool} was refused — SynaBun's browser policy could not load (${loadError?.message || 'browserToolDenial is missing'}), so no command, web search or other server's tool can be checked for a browser launch. SynaBun's own tools still work. Stop and report this`;
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
/** The registered code projects from the env (a JSON list of paths); anything unreadable is none. */
|
|
31
|
+
function policyRoots() {
|
|
32
|
+
try {
|
|
33
|
+
const list = JSON.parse(process.env.SYNABUN_BROWSER_POLICY_ROOTS || '[]');
|
|
34
|
+
return Array.isArray(list) ? list.filter((path) => typeof path === 'string') : [];
|
|
35
|
+
} catch { return []; }
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
let raw = '';
|
|
29
39
|
try { for await (const chunk of process.stdin) raw += chunk; } catch {}
|
|
30
40
|
let payload = {};
|
|
@@ -35,7 +45,7 @@ try {
|
|
|
35
45
|
const input = payload.tool_input && typeof payload.tool_input === 'object' ? payload.tool_input : {};
|
|
36
46
|
const cwd = (typeof payload.cwd === 'string' && payload.cwd) || process.env.SYNABUN_BROWSER_POLICY_CWD || process.cwd();
|
|
37
47
|
if (typeof browserToolDenial !== 'function') process.stderr.write(`[SynaBun] browser policy could not load (${loadError?.message || 'browserToolDenial is missing'}); denying shell, web search and other servers' tools\n`);
|
|
38
|
-
const reason = !tool ? null : typeof browserToolDenial === 'function' ? browserToolDenial(tool, input, { host: 'codex', cwd }) : unloadedDenial(tool);
|
|
48
|
+
const reason = !tool ? null : typeof browserToolDenial === 'function' ? browserToolDenial(tool, input, { host: 'codex', cwd, roots: policyRoots() }) : unloadedDenial(tool);
|
|
39
49
|
// Codex prints "Command blocked by PreToolUse hook: <reason>. Command: <cmd>", so
|
|
40
50
|
// the reason goes without its own final period.
|
|
41
51
|
if (reason) process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: reason.replace(/[.\s]+$/, '') } }));
|
|
@@ -4,9 +4,19 @@
|
|
|
4
4
|
// tool may run; a refusal becomes permissionDecision "deny" with the reason.
|
|
5
5
|
// The call's whole tool_input travels (the remote denylist reads paths from
|
|
6
6
|
// it), marked inputComplete; one too big to send goes as its command/action
|
|
7
|
-
// only, marked incomplete.
|
|
8
|
-
// allows the call — except in a WhatsApp session
|
|
9
|
-
// where a call SynaBun could not check is
|
|
7
|
+
// only, marked incomplete. No env or no answer at all (the server unreachable
|
|
8
|
+
// or slow) allows the call — except in a WhatsApp session
|
|
9
|
+
// (SYNABUN_ROUTE_GATE_REMOTE=1), where a call SynaBun could not check is
|
|
10
|
+
// denied. An answer that is not a decision (the check itself refused, such as
|
|
11
|
+
// 403 PEER_REFUSED, an error status, a body without `allow`) denies the call in
|
|
12
|
+
// every session and says what SynaBun answered: a refusal never passes for an
|
|
13
|
+
// allow.
|
|
14
|
+
//
|
|
15
|
+
// The request carries the session's pin (X-Synabun-Assistant): this hook runs
|
|
16
|
+
// under the brain's Codex app-server, an AI agent's process tree, which
|
|
17
|
+
// SynaBun's owner gate (lib/owner-authority.js) refuses unless the call says
|
|
18
|
+
// it is an agent's own. The per-session token in the body is what the route
|
|
19
|
+
// itself checks.
|
|
10
20
|
|
|
11
21
|
const url = process.env.SYNABUN_ROUTE_GATE_URL;
|
|
12
22
|
const session = process.env.SYNABUN_ROUTE_GATE_SESSION;
|
|
@@ -14,6 +24,7 @@ const token = process.env.SYNABUN_ROUTE_GATE_TOKEN;
|
|
|
14
24
|
const remote = process.env.SYNABUN_ROUTE_GATE_REMOTE === '1';
|
|
15
25
|
const MAX_INPUT_BYTES = 256 * 1024;
|
|
16
26
|
const UNCHECKED = 'SynaBun could not check this call, so a WhatsApp session does not run it.';
|
|
27
|
+
const PIN_HEADER = 'x-synabun-assistant';
|
|
17
28
|
|
|
18
29
|
let raw = '';
|
|
19
30
|
try { for await (const chunk of process.stdin) raw += chunk; } catch {}
|
|
@@ -37,20 +48,32 @@ function callArguments(toolInput) {
|
|
|
37
48
|
function deny(reason) {
|
|
38
49
|
process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: String(reason).replace(/[.\s]+$/, '') } }));
|
|
39
50
|
}
|
|
51
|
+
/** The refusal of a call whose check got an answer that is not a decision: what SynaBun answered, in short. */
|
|
52
|
+
function notADecision(status, body) {
|
|
53
|
+
const code = body && typeof body === 'object' && typeof body.code === 'string' ? ` ${body.code.slice(0, 64)}` : '';
|
|
54
|
+
const said = body && typeof body === 'object' && typeof body.error === 'string' ? `: ${body.error.slice(0, 300)}` : '';
|
|
55
|
+
return `SynaBun could not check this call (its route gate answered ${status}${code}${said}), so it did not run.`;
|
|
56
|
+
}
|
|
40
57
|
|
|
41
58
|
if (url && session && token) {
|
|
59
|
+
let response = null;
|
|
42
60
|
try {
|
|
43
|
-
|
|
61
|
+
response = await fetch(url, {
|
|
44
62
|
method: 'POST',
|
|
45
|
-
|
|
63
|
+
// The session id as a header value: printable ASCII only (fetch refuses anything else before sending).
|
|
64
|
+
headers: { 'content-type': 'application/json', [PIN_HEADER]: String(session).replace(/[^\x21-\x7e]/g, '').slice(0, 200) },
|
|
46
65
|
body: JSON.stringify({ session, token, host: 'codex', tool: String(input.tool_name || input.toolName || input.tool || ''), agent: input.agent_id || null, ...callArguments(input.tool_input) }),
|
|
47
66
|
signal: AbortSignal.timeout(5000),
|
|
48
67
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else if (remote && !(decision && decision.allow === true)) deny(UNCHECKED);
|
|
52
|
-
} catch {
|
|
68
|
+
} catch { response = null; }
|
|
69
|
+
if (!response) {
|
|
53
70
|
if (remote) deny(UNCHECKED);
|
|
71
|
+
} else {
|
|
72
|
+
let decision = null;
|
|
73
|
+
try { decision = await response.json(); } catch { decision = null; }
|
|
74
|
+
if (response.ok && decision && decision.allow === true) { /* allowed: Codex runs the call */ }
|
|
75
|
+
else if (response.ok && decision && decision.allow === false) deny(decision.reason || 'SynaBun refused this call.');
|
|
76
|
+
else deny(notADecision(response.status, decision));
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
79
|
process.exit(0);
|
|
@@ -14,6 +14,8 @@ import { createCodexEnvelopeTranslator, codexControlResponse } from '../assistan
|
|
|
14
14
|
import { baseModelId, contextVariantOf } from '../assistant-catalog.js';
|
|
15
15
|
import { codexPlanPermission, codexReadOnlyPermission, planDenyMessage, readOnlyDenyMessage } from '../assistant-plan-permissions.js';
|
|
16
16
|
import { planModeInstructions } from '../assistant-persona.js';
|
|
17
|
+
import { shouldAutoAcceptCodexMcpToolApproval } from '../codex-mcp-approvals.js';
|
|
18
|
+
import { codexMcpToolApproval } from '../../public/shared/cdx/cdx-protocol.js';
|
|
17
19
|
|
|
18
20
|
const READY_TIMEOUT_MS = 90_000;
|
|
19
21
|
// Approvals the Codex sidepanel's Auto-accept answers on its own (cdx-requests.js).
|
|
@@ -83,7 +85,7 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
83
85
|
}
|
|
84
86
|
if (planned) {
|
|
85
87
|
const method = packet.request?.brain_native?.method || packet.request?.method || '';
|
|
86
|
-
const tool = packet.request?.brain_native?.params?.
|
|
88
|
+
const tool = codexMcpToolApproval(packet.request?.brain_native?.params)?.fullName || packet.request?.tool_name || 'request';
|
|
87
89
|
const response = planned === 'allow'
|
|
88
90
|
? { behavior: 'allow', ...(!remoteReadOnly && approvalMode === 'auto' ? { always: true } : {}) }
|
|
89
91
|
: { behavior: 'deny', decline: true, message: remoteReadOnly ? readOnlyDenyMessage(tool) : planDenyMessage(tool, { host: 'codex' }) };
|
|
@@ -91,7 +93,9 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
91
93
|
sink.send({ type: 'stderr', text: `${planMode ? 'Plan mode' : 'Read-only (WhatsApp)'}: ${planned === 'allow' ? 'allowed' : 'declined'} ${String(method).split('/').slice(1, -1).join('/') || 'request'} ${tool}${planned === 'allow' ? '' : remoteReadOnly ? ' (read-only)' : ' (no code changes)'}` });
|
|
92
94
|
return;
|
|
93
95
|
}
|
|
94
|
-
|
|
96
|
+
const method = packet.request?.brain_native?.method || packet.request?.method;
|
|
97
|
+
const autoMcp = method === 'mcpServer/elicitation/request' && shouldAutoAcceptCodexMcpToolApproval(packet.request?.brain_native?.params, { autoAccept: approvalMode === 'auto', role: 'assistant' });
|
|
98
|
+
if (packet.type === 'control_request' && !planMode && !remoteReadOnly && (autoMcp || (approvalMode === 'auto' && AUTO_ACCEPT_METHODS.has(method)))) {
|
|
95
99
|
// Auto-accept: approve at once (for the session when offered), as the Codex sidepanel does.
|
|
96
100
|
send({ type: 'server_request_response', ...codexControlResponse(packet, { behavior: 'allow', always: true }) });
|
|
97
101
|
sink.send({ type: 'stderr', text: `Auto-accepted: ${String(packet.request?.brain_native?.method || packet.request?.method).split('/').slice(1, -1).join('/')}` });
|
|
@@ -119,8 +123,8 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
119
123
|
});
|
|
120
124
|
const socket = createVirtualSocket({
|
|
121
125
|
name: `codex-brain-${session.id}`,
|
|
122
|
-
//
|
|
123
|
-
//
|
|
126
|
+
// The brain's launch credential rides on the socket object, never in a message: the skin handler gives it to
|
|
127
|
+
// this app-server's SynaBun MCP child through its environment (whatsapp_send_file, the Skills Service).
|
|
124
128
|
credential: deps.brainCredential || null,
|
|
125
129
|
onSend: (packet) => {
|
|
126
130
|
if (disposed || !packet || typeof packet !== 'object') return;
|
|
@@ -159,7 +163,7 @@ export function createCodexBrain({ session, sink, deps = {}, persona = '' } = {}
|
|
|
159
163
|
readyResolve = () => { clearTimeout(timer); resolve(true); };
|
|
160
164
|
});
|
|
161
165
|
send({
|
|
162
|
-
type: 'bootstrap', windowId, accountId: brain.accountId || 'default',
|
|
166
|
+
type: 'bootstrap', windowId, accountId: brain.accountId || 'default',
|
|
163
167
|
cwd: brain.cwd || deps.PACKAGE_ROOT || undefined, threadId: threadId || null, role: 'assistant',
|
|
164
168
|
// Unlocks the capability-gated `computer` MCP group for this brain only.
|
|
165
169
|
desktopGrant: deps.desktopGrant || null,
|