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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { retainExternalRefs } from './mcp-external-servers.js';
|
|
2
|
+
import { storedToolList, toolListRecord, readStoredToolListRecord } from './tool-lists.js';
|
|
1
3
|
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
4
|
import { dirname, resolve } from 'node:path';
|
|
3
5
|
|
|
@@ -30,7 +32,9 @@ function cleanDescriptor(record) {
|
|
|
30
32
|
contextMode: record.contextMode || null,
|
|
31
33
|
modelContextWindow: record.modelContextWindow || null,
|
|
32
34
|
effort: record.effort || null,
|
|
33
|
-
|
|
35
|
+
tools: storedToolList(record),
|
|
36
|
+
externalMcpVersion: 2,
|
|
37
|
+
...(record.toolListError ? { toolListError: record.toolListError } : {}),
|
|
34
38
|
accountId: record.accountId || null,
|
|
35
39
|
currentIteration: record.currentIteration || 0,
|
|
36
40
|
totalIterations: record.totalIterations || 0,
|
|
@@ -53,9 +57,18 @@ function cleanDescriptor(record) {
|
|
|
53
57
|
// lastResult.status): an idle warm worker whose turn ended asking waits on the user.
|
|
54
58
|
outcome: record.outcome || null,
|
|
55
59
|
assistantSessionId: record.assistantSessionId || null,
|
|
60
|
+
// A dispatched worker a server restart cut off (status 'suspended') waits for its resume on the next start;
|
|
61
|
+
// `resumes` counts how often it was resumed (assistant-dispatch.js resumeRun).
|
|
62
|
+
suspendedAt: record.suspendedAt || null,
|
|
63
|
+
suspendReason: record.suspendReason || null,
|
|
64
|
+
resumes: Number(record.resumes) || 0,
|
|
65
|
+
resumedAt: record.resumedAt || null,
|
|
56
66
|
};
|
|
57
67
|
}
|
|
58
68
|
|
|
69
|
+
/** Run statuses that hold a run in the ledger as live: it runs, or waits for its resume after a restart. */
|
|
70
|
+
const LIVE_STATUSES = new Set(['starting', 'running', 'suspended']);
|
|
71
|
+
|
|
59
72
|
function readJson(path, fallback = null) {
|
|
60
73
|
try { return JSON.parse(readFileSync(path, 'utf8')); }
|
|
61
74
|
catch { return fallback; }
|
|
@@ -76,6 +89,7 @@ export class NativeLoopRuntime {
|
|
|
76
89
|
constructor({
|
|
77
90
|
stateDir,
|
|
78
91
|
ledgerPath,
|
|
92
|
+
toolListOptions = () => ({}),
|
|
79
93
|
providerFactories = {},
|
|
80
94
|
buildPrompt,
|
|
81
95
|
onEvent = () => {},
|
|
@@ -95,10 +109,14 @@ export class NativeLoopRuntime {
|
|
|
95
109
|
// A truthy `met` ends the run early with stoppedReason 'goal_met'; the
|
|
96
110
|
// iteration and time caps stay the fallback.
|
|
97
111
|
judgeGoal = null,
|
|
112
|
+
// How long a dispatched worker the restart cut off waits, from this start, for its dispatcher to resume it
|
|
113
|
+
// (or end it) before it ends as interrupted by itself.
|
|
114
|
+
resumeHoldMs = 60_000,
|
|
98
115
|
} = {}) {
|
|
99
116
|
if (!stateDir) throw new Error('NativeLoopRuntime requires stateDir');
|
|
100
117
|
if (typeof buildPrompt !== 'function') throw new Error('NativeLoopRuntime requires buildPrompt');
|
|
101
118
|
this.stateDir = stateDir;
|
|
119
|
+
this.toolListOptions = toolListOptions;
|
|
102
120
|
this.judgeGoal = typeof judgeGoal === 'function' ? judgeGoal : null;
|
|
103
121
|
this.ledgerPath = ledgerPath || resolve(dirname(stateDir), 'native-loop-runs.json');
|
|
104
122
|
this.providerFactories = { ...providerFactories };
|
|
@@ -113,6 +131,8 @@ export class NativeLoopRuntime {
|
|
|
113
131
|
this.providerStartupTimeoutMs = providerStartupTimeoutMs;
|
|
114
132
|
this.claimTtlMs = claimTtlMs;
|
|
115
133
|
this.ledgerFlushMs = Math.max(50, Number(ledgerFlushMs) || 200);
|
|
134
|
+
this.resumeHoldMs = Math.max(1000, Number(resumeHoldMs) || 60_000);
|
|
135
|
+
this._holdTimers = new Map();
|
|
116
136
|
this.records = new Map();
|
|
117
137
|
this._pendingPersist = false;
|
|
118
138
|
this._persistTimer = null;
|
|
@@ -184,8 +204,32 @@ export class NativeLoopRuntime {
|
|
|
184
204
|
if (!Array.isArray(rows)) return;
|
|
185
205
|
for (const row of rows) {
|
|
186
206
|
if (!row?.runId) continue;
|
|
187
|
-
|
|
188
|
-
|
|
207
|
+
let stored;
|
|
208
|
+
try { stored = readStoredToolListRecord(row, this.toolListOptions()); }
|
|
209
|
+
catch (error) {
|
|
210
|
+
// A historical run may name a custom preset the owner has since deleted. Refuse that
|
|
211
|
+
// run, preserve the original selection for diagnosis, and keep the rest of the server up.
|
|
212
|
+
stored = { ...row, tools: [], status: 'failed', stoppedReason: 'tools_invalid',
|
|
213
|
+
error: error.message, toolListError: { code: error.code, message: error.message,
|
|
214
|
+
original: row.tools ?? row.mcpProfile ?? null } };
|
|
215
|
+
delete stored.mcpProfile;
|
|
216
|
+
}
|
|
217
|
+
const record = { ...stored, adapter: null, timer: null, execution: null };
|
|
218
|
+
const cutOff = record.status === 'starting' || record.status === 'running' || record.status === 'suspended';
|
|
219
|
+
if (cutOff && record.runMode === 'task' && isNativeLoopProfile(record.provider)) {
|
|
220
|
+
// A dispatched Claude Code worker the restart cut off (suspended by the last shutdown, or left running by a
|
|
221
|
+
// crash): held for its dispatcher, which resumes it (assistant-dispatch.js resumeRun) or ends it. Its state file
|
|
222
|
+
// stays as it is. Nobody takes it within resumeHoldMs: it ends as interrupted, as every cut-off run did before.
|
|
223
|
+
record.status = 'suspended';
|
|
224
|
+
record.suspendedAt = record.suspendedAt || iso(this.now());
|
|
225
|
+
record.suspendReason = record.suspendReason || 'server_restart';
|
|
226
|
+
record.turnState = 'suspended';
|
|
227
|
+
record.stopping = false;
|
|
228
|
+
this.records.set(record.runId, record);
|
|
229
|
+
this._hold(record);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (cutOff) {
|
|
189
233
|
record.status = 'interrupted';
|
|
190
234
|
record.stoppedReason = 'server_restart';
|
|
191
235
|
record.completedAt = record.completedAt || iso(this.now());
|
|
@@ -208,9 +252,9 @@ export class NativeLoopRuntime {
|
|
|
208
252
|
|
|
209
253
|
_writeLedgerNow() {
|
|
210
254
|
const records = [...this.records.values()];
|
|
211
|
-
const active = records.filter((record) =>
|
|
255
|
+
const active = records.filter((record) => LIVE_STATUSES.has(record.status));
|
|
212
256
|
const terminal = records
|
|
213
|
-
.filter((record) => !
|
|
257
|
+
.filter((record) => !LIVE_STATUSES.has(record.status))
|
|
214
258
|
.sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
|
|
215
259
|
const retained = [...active, ...terminal.slice(0, Math.max(0, 500 - active.length))];
|
|
216
260
|
const retainedIds = new Set(retained.map((record) => record.runId));
|
|
@@ -221,7 +265,7 @@ export class NativeLoopRuntime {
|
|
|
221
265
|
}
|
|
222
266
|
}
|
|
223
267
|
const rows = retained
|
|
224
|
-
.map(cleanDescriptor)
|
|
268
|
+
.map(record => toolListRecord(cleanDescriptor(record)))
|
|
225
269
|
.sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
|
|
226
270
|
try { writeJsonAtomic(this.ledgerPath, rows); }
|
|
227
271
|
catch (error) { this.log(null, 'ledger:error', error.message); }
|
|
@@ -265,11 +309,12 @@ export class NativeLoopRuntime {
|
|
|
265
309
|
|
|
266
310
|
_readState(runId) {
|
|
267
311
|
const path = this._statePath(runId);
|
|
268
|
-
|
|
312
|
+
const state = existsSync(path) ? readJson(path, null) : null;
|
|
313
|
+
return state ? readStoredToolListRecord(state, this.toolListOptions()) : null;
|
|
269
314
|
}
|
|
270
315
|
|
|
271
316
|
_writeState(runId, state) {
|
|
272
|
-
writeJsonAtomic(this._statePath(runId), state);
|
|
317
|
+
writeJsonAtomic(this._statePath(runId), toolListRecord(state, this.toolListOptions()));
|
|
273
318
|
}
|
|
274
319
|
|
|
275
320
|
_writeTerminalState(record, patch) {
|
|
@@ -285,8 +330,9 @@ export class NativeLoopRuntime {
|
|
|
285
330
|
record.version = (Number(record.version) || 0) + 1;
|
|
286
331
|
record.updatedAt = iso(this.now());
|
|
287
332
|
// Force-flush on terminal transitions (a crash between throttled flushes
|
|
288
|
-
// would otherwise leave the run listed as running after a restart)
|
|
289
|
-
|
|
333
|
+
// would otherwise leave the run listed as running after a restart), and on
|
|
334
|
+
// a suspension (the next start resumes the run from this ledger).
|
|
335
|
+
const terminal = ['completed', 'failed', 'stopped', 'interrupted', 'suspended'].includes(record.status);
|
|
290
336
|
this._persistLedger({ force: terminal });
|
|
291
337
|
const descriptor = cleanDescriptor(record);
|
|
292
338
|
const message = { type, run: descriptor, ...extra };
|
|
@@ -333,7 +379,7 @@ export class NativeLoopRuntime {
|
|
|
333
379
|
mkdirSync(this.stateDir, { recursive: true });
|
|
334
380
|
const startedAt = state.startedAt || iso(this.now());
|
|
335
381
|
const nativeState = {
|
|
336
|
-
...state,
|
|
382
|
+
...toolListRecord(state, this.toolListOptions()),
|
|
337
383
|
runId,
|
|
338
384
|
terminalSessionId: runId,
|
|
339
385
|
active: true,
|
|
@@ -361,7 +407,7 @@ export class NativeLoopRuntime {
|
|
|
361
407
|
contextMode: state.contextMode || null,
|
|
362
408
|
modelContextWindow: state.modelContextWindow || null,
|
|
363
409
|
effort: state.effort || null,
|
|
364
|
-
|
|
410
|
+
tools: storedToolList(state, this.toolListOptions()),
|
|
365
411
|
accountId: state.codexAccountId || null,
|
|
366
412
|
currentIteration: Number(state.currentIteration) || 0,
|
|
367
413
|
totalIterations: Number(state.totalIterations) || 1,
|
|
@@ -400,6 +446,24 @@ export class NativeLoopRuntime {
|
|
|
400
446
|
record.timer.unref?.();
|
|
401
447
|
}
|
|
402
448
|
|
|
449
|
+
this._bootstrap(record, factory, nativeState, { source, profile: state.profile });
|
|
450
|
+
|
|
451
|
+
// For back-compat: callers that awaited launch() to know whether the run was
|
|
452
|
+
// accepted can observe the descriptor. The failure (if any) is delivered via
|
|
453
|
+
// sidepanel:run-failed and via record.bootstrap rejecting with the original
|
|
454
|
+
// startup error. The descriptor itself resolves immediately with the
|
|
455
|
+
// 'starting' state so the HTTP caller is never gated on provider boot.
|
|
456
|
+
return cleanDescriptor(record);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Start the provider of a run whose record is in place (launch, resume) and drive it. Sets record.bootstrap: it
|
|
461
|
+
* resolves once the provider started and rejects with the startup error. A provider that cannot start ends the
|
|
462
|
+
* run as failed, or (`failAs: 'interrupted'`, a resume) as interrupted with the reason resume_failed.
|
|
463
|
+
*/
|
|
464
|
+
_bootstrap(record, factory, nativeState, { source = record.source, profile = record.provider, failAs = 'failed' } = {}) {
|
|
465
|
+
const runId = record.runId;
|
|
466
|
+
const state = { profile };
|
|
403
467
|
const startupSignal = record.startupAbortController.signal;
|
|
404
468
|
const factoryPromise = Promise.resolve().then(() => factory({
|
|
405
469
|
...nativeState,
|
|
@@ -418,7 +482,8 @@ export class NativeLoopRuntime {
|
|
|
418
482
|
if (!adapter || candidateCleaned) return;
|
|
419
483
|
candidateCleaned = true;
|
|
420
484
|
try { await adapter.abort?.(reason); } catch {}
|
|
421
|
-
|
|
485
|
+
// Suspended for a server shutdown while it started (suspend): its process is ended now, as a started one's is.
|
|
486
|
+
try { await adapter.dispose?.({ preserveSession: true, ...(record.status === 'suspended' ? { terminate: true } : {}) }); } catch {}
|
|
422
487
|
};
|
|
423
488
|
const finishBootstrap = async () => {
|
|
424
489
|
clearTimeout(startupTimer);
|
|
@@ -497,11 +562,15 @@ export class NativeLoopRuntime {
|
|
|
497
562
|
if (candidate) await cleanupCandidate(candidate, error?.code || 'startup_failed');
|
|
498
563
|
else factoryPromise.then((adapter) => cleanupCandidate(adapter, error?.code || 'startup_failed')).catch(() => {});
|
|
499
564
|
}
|
|
500
|
-
|
|
501
|
-
record,
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
565
|
+
if (failAs === 'interrupted') {
|
|
566
|
+
await this._fail(record, error, 'resume_failed', { status: 'interrupted' });
|
|
567
|
+
} else {
|
|
568
|
+
await this._fail(
|
|
569
|
+
record,
|
|
570
|
+
error,
|
|
571
|
+
error?.code === 'NATIVE_LOOP_PROVIDER_START_TIMEOUT' ? 'provider_startup_timeout' : 'provider_error',
|
|
572
|
+
);
|
|
573
|
+
}
|
|
505
574
|
} finally {
|
|
506
575
|
await finishBootstrap();
|
|
507
576
|
// Re-throw so record.bootstrap rejects with the original startup error.
|
|
@@ -516,15 +585,146 @@ export class NativeLoopRuntime {
|
|
|
516
585
|
// timer holds the process until cleanup. Swallow the unhandled rejection
|
|
517
586
|
// here because callers that care must await record.bootstrap explicitly.
|
|
518
587
|
bootstrap.catch(() => {});
|
|
588
|
+
return bootstrap;
|
|
589
|
+
}
|
|
519
590
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
591
|
+
/**
|
|
592
|
+
* Continue a suspended run (a dispatched worker a server restart cut off; assistant-dispatch.js resumeRun) as the
|
|
593
|
+
* same record: its runId, tab, claim, title and startedAt stay, its version keeps growing. The state file is written
|
|
594
|
+
* again at iteration 0 of 1, so the drive runs the run's one task iteration again (the dispatcher's wrapper decides
|
|
595
|
+
* what that turn sends), and the provider factory gets what `state` carries to continue the provider session
|
|
596
|
+
* (resumeSessionId, costBaseUsd). Resolves with the descriptor once the provider started; a provider that cannot
|
|
597
|
+
* start ends the run as interrupted (resume_failed) and the promise rejects with why.
|
|
598
|
+
*/
|
|
599
|
+
async resume({ runId, state, buildPrompt = null, wrapAdapter = null } = {}) {
|
|
600
|
+
const record = this.records.get(runId);
|
|
601
|
+
if (!record) throw new Error(`Native loop ${runId} is not known`);
|
|
602
|
+
if (record.status !== 'suspended') throw new Error(`Native loop ${runId} is ${record.status}, not suspended`);
|
|
603
|
+
if (buildPrompt !== null && typeof buildPrompt !== 'function') throw new Error('Native loop buildPrompt override must be a function');
|
|
604
|
+
if (wrapAdapter !== null && typeof wrapAdapter !== 'function') throw new Error('Native loop wrapAdapter override must be a function');
|
|
605
|
+
if (!state?.profile || !isNativeLoopProfile(state.profile)) throw new Error(`Unsupported native loop profile: ${state?.profile || 'unknown'}`);
|
|
606
|
+
const factory = this.providerFactories[state.profile];
|
|
607
|
+
if (!factory) throw new Error(`Native provider unavailable: ${state.profile}`);
|
|
608
|
+
this._clearHold(record);
|
|
609
|
+
mkdirSync(this.stateDir, { recursive: true });
|
|
610
|
+
const totalIterations = Number(state.totalIterations) || 1;
|
|
611
|
+
const nativeState = {
|
|
612
|
+
...toolListRecord(state, this.toolListOptions()),
|
|
613
|
+
runId,
|
|
614
|
+
terminalSessionId: runId,
|
|
615
|
+
active: true,
|
|
616
|
+
pending: false,
|
|
617
|
+
driverType: 'native',
|
|
618
|
+
runtimeType: 'native',
|
|
619
|
+
surface: 'sidepanel',
|
|
620
|
+
startedAt: record.startedAt || state.startedAt || iso(this.now()),
|
|
621
|
+
currentIteration: 0,
|
|
622
|
+
totalIterations,
|
|
623
|
+
};
|
|
624
|
+
this._writeState(runId, nativeState);
|
|
625
|
+
Object.assign(record, {
|
|
626
|
+
status: 'starting',
|
|
627
|
+
stoppedReason: null,
|
|
628
|
+
completedAt: null,
|
|
629
|
+
error: null,
|
|
630
|
+
adapter: null,
|
|
631
|
+
timer: null,
|
|
632
|
+
execution: null,
|
|
633
|
+
stopping: false,
|
|
634
|
+
startupAbortController: new AbortController(),
|
|
635
|
+
turnState: 'starting',
|
|
636
|
+
currentIteration: 0,
|
|
637
|
+
totalIterations,
|
|
638
|
+
browserSessionId: state.browserSessionId || null,
|
|
639
|
+
browserTabId: state.browserTabId || null,
|
|
640
|
+
suspendedAt: null,
|
|
641
|
+
suspendReason: null,
|
|
642
|
+
resumes: (Number(record.resumes) || 0) + 1,
|
|
643
|
+
resumedAt: iso(this.now()),
|
|
644
|
+
buildPrompt,
|
|
645
|
+
wrapAdapter,
|
|
646
|
+
});
|
|
647
|
+
record.identityPromise = new Promise((resolveIdentity) => { record._resolveIdentity = resolveIdentity; });
|
|
648
|
+
record.startupCancelPromise = new Promise((resolveCancel) => { record._cancelStartup = resolveCancel; });
|
|
649
|
+
this._emit('sidepanel:run-updated', record, { reason: 'resuming' });
|
|
650
|
+
await this._bootstrap(record, factory, nativeState, { profile: state.profile, failAs: 'interrupted' });
|
|
525
651
|
return cleanDescriptor(record);
|
|
526
652
|
}
|
|
527
653
|
|
|
654
|
+
/** The hold of a run the restart cut off: it ends as interrupted when nobody resumes it in time. */
|
|
655
|
+
_hold(record) {
|
|
656
|
+
this._clearHold(record);
|
|
657
|
+
const timer = setTimeout(() => {
|
|
658
|
+
this._holdTimers.delete(record.runId);
|
|
659
|
+
this.endSuspended(record.runId, record.suspendReason || 'server_restart').catch(() => {});
|
|
660
|
+
}, this.resumeHoldMs);
|
|
661
|
+
timer.unref?.();
|
|
662
|
+
this._holdTimers.set(record.runId, timer);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
_clearHold(record) {
|
|
666
|
+
const timer = this._holdTimers.get(record?.runId);
|
|
667
|
+
if (timer) { clearTimeout(timer); this._holdTimers.delete(record.runId); }
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** Whether a run waits for its resume after a restart (suspended). */
|
|
671
|
+
isSuspended(runId) {
|
|
672
|
+
return this.records.get(runId)?.status === 'suspended';
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/**
|
|
676
|
+
* The dispatcher takes a suspended run over (it resumes it or ends it itself): its hold no longer ends it.
|
|
677
|
+
* Returns whether the run is suspended.
|
|
678
|
+
*/
|
|
679
|
+
keepSuspended(runId) {
|
|
680
|
+
const record = this.records.get(runId);
|
|
681
|
+
if (!record || record.status !== 'suspended') return false;
|
|
682
|
+
this._clearHold(record);
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* A suspended run that will not be resumed ends as interrupted (`reason`, by default why it was suspended), with an
|
|
688
|
+
* event, so a tab that waited for its resume shows how it ended. `error`: why it was not resumed.
|
|
689
|
+
*/
|
|
690
|
+
async endSuspended(runId, reason = null, { error = null } = {}) {
|
|
691
|
+
const record = this.records.get(runId);
|
|
692
|
+
if (!record || record.status !== 'suspended') return false;
|
|
693
|
+
this._clearHold(record);
|
|
694
|
+
record.status = 'interrupted';
|
|
695
|
+
record.stoppedReason = reason || record.suspendReason || 'server_restart';
|
|
696
|
+
record.completedAt = iso(this.now());
|
|
697
|
+
if (error) record.error = String(error);
|
|
698
|
+
this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: record.stoppedReason, ...(error ? { error: record.error } : {}) });
|
|
699
|
+
this._releaseRuntimeRefs(record);
|
|
700
|
+
this._emit('sidepanel:run-stopped', record);
|
|
701
|
+
try { await this.onFinish(cleanDescriptor(record)); } catch {}
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Suspend a running dispatched worker for a server shutdown (shutdown's `keep`): its CLI is ended (the adapter's
|
|
707
|
+
* dispose with terminate), its state file stays active, and the record waits as suspended for the next start to
|
|
708
|
+
* resume it. No run-stopped event and no end: a run-updated with the reason 'suspended'.
|
|
709
|
+
*/
|
|
710
|
+
async suspend(runId, reason = 'server_shutdown') {
|
|
711
|
+
const record = this.records.get(runId);
|
|
712
|
+
if (!record || !['starting', 'running'].includes(record.status) || record.stopping) return false;
|
|
713
|
+
record.stopping = true;
|
|
714
|
+
clearTimeout(record.timer);
|
|
715
|
+
record.status = 'suspended';
|
|
716
|
+
record.suspendedAt = iso(this.now());
|
|
717
|
+
record.suspendReason = reason;
|
|
718
|
+
if (record._resolveIdentity) { record._resolveIdentity(null); record._resolveIdentity = null; }
|
|
719
|
+
try { record.startupAbortController?.abort(reason); } catch {}
|
|
720
|
+
if (record._cancelStartup) { record._cancelStartup(reason); record._cancelStartup = null; }
|
|
721
|
+
try { await record.adapter?.dispose?.({ preserveSession: true, terminate: true }); } catch {}
|
|
722
|
+
this._releaseRuntimeRefs(record, { turnState: 'suspended' });
|
|
723
|
+
record.stopping = false;
|
|
724
|
+
this._emit('sidepanel:run-updated', record, { reason: 'suspended' });
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
727
|
+
|
|
528
728
|
async _drive(record) {
|
|
529
729
|
let failures = 0;
|
|
530
730
|
while (this.isAlive(record.runId)) {
|
|
@@ -618,7 +818,7 @@ export class NativeLoopRuntime {
|
|
|
618
818
|
}
|
|
619
819
|
}
|
|
620
820
|
|
|
621
|
-
_releaseRuntimeRefs(record) {
|
|
821
|
+
_releaseRuntimeRefs(record, { turnState = 'terminal' } = {}) {
|
|
622
822
|
if (!record) return;
|
|
623
823
|
record.adapter = null;
|
|
624
824
|
record.timer = null;
|
|
@@ -630,7 +830,8 @@ export class NativeLoopRuntime {
|
|
|
630
830
|
record.startupAbortController = null;
|
|
631
831
|
record.buildPrompt = null;
|
|
632
832
|
record.wrapAdapter = null;
|
|
633
|
-
if (
|
|
833
|
+
if (turnState === 'suspended') record.turnState = 'suspended';
|
|
834
|
+
else if (record.turnState && record.turnState !== 'terminal') record.turnState = 'terminal';
|
|
634
835
|
}
|
|
635
836
|
|
|
636
837
|
async _complete(record, reason = 'completed') {
|
|
@@ -646,10 +847,11 @@ export class NativeLoopRuntime {
|
|
|
646
847
|
try { await this.onFinish(cleanDescriptor(record)); } catch {}
|
|
647
848
|
}
|
|
648
849
|
|
|
649
|
-
|
|
650
|
-
|
|
850
|
+
/** `status`: 'failed', or 'interrupted' for a resume that could not start (reason resume_failed). */
|
|
851
|
+
async _fail(record, error, reason = 'provider_error', { status = 'failed' } = {}) {
|
|
852
|
+
if (!record || ['completed', 'failed', 'stopped', 'interrupted', 'suspended'].includes(record.status)) return;
|
|
651
853
|
clearTimeout(record.timer);
|
|
652
|
-
record.status = 'failed';
|
|
854
|
+
record.status = status === 'interrupted' ? 'interrupted' : 'failed';
|
|
653
855
|
record.error = error?.message || String(error);
|
|
654
856
|
record.stoppedReason = reason;
|
|
655
857
|
record.completedAt = iso(this.now());
|
|
@@ -660,12 +862,27 @@ export class NativeLoopRuntime {
|
|
|
660
862
|
try { await record.adapter?.abort?.(reason); } catch {}
|
|
661
863
|
try { await record.adapter?.dispose?.({ preserveSession: true }); } catch {}
|
|
662
864
|
this._releaseRuntimeRefs(record);
|
|
663
|
-
this._emit('sidepanel:run-failed', record);
|
|
865
|
+
this._emit(record.status === 'interrupted' ? 'sidepanel:run-stopped' : 'sidepanel:run-failed', record);
|
|
664
866
|
try { await this.onFinish(cleanDescriptor(record)); } catch {}
|
|
665
867
|
}
|
|
666
868
|
|
|
667
|
-
|
|
869
|
+
/**
|
|
870
|
+
* `terminate` (a server shutdown): the provider's process is ended at once (the Claude adapter's dispose), never
|
|
871
|
+
* left to finish its tool call after the server is gone. A suspended run (waiting for its resume) ends as stopped.
|
|
872
|
+
*/
|
|
873
|
+
async stop(runId, reason = 'user', { terminate = false } = {}) {
|
|
668
874
|
const record = this.records.get(runId);
|
|
875
|
+
if (record?.status === 'suspended' && !record.stopping) {
|
|
876
|
+
this._clearHold(record);
|
|
877
|
+
record.status = 'stopped';
|
|
878
|
+
record.stoppedReason = reason;
|
|
879
|
+
record.completedAt = iso(this.now());
|
|
880
|
+
this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: reason });
|
|
881
|
+
this._releaseRuntimeRefs(record);
|
|
882
|
+
this._emit('sidepanel:run-stopped', record);
|
|
883
|
+
try { await this.onFinish(cleanDescriptor(record)); } catch {}
|
|
884
|
+
return true;
|
|
885
|
+
}
|
|
669
886
|
if (!record || !['starting', 'running'].includes(record.status) || record.stopping) return false;
|
|
670
887
|
record.stopping = true;
|
|
671
888
|
clearTimeout(record.timer);
|
|
@@ -677,7 +894,7 @@ export class NativeLoopRuntime {
|
|
|
677
894
|
if (record._cancelStartup) { record._cancelStartup(reason); record._cancelStartup = null; }
|
|
678
895
|
this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: reason });
|
|
679
896
|
try { await record.adapter?.abort?.(reason); } catch {}
|
|
680
|
-
try { await record.adapter?.dispose?.({ preserveSession: true }); } catch {}
|
|
897
|
+
try { await record.adapter?.dispose?.({ preserveSession: true, ...(terminate ? { terminate: true } : {}) }); } catch {}
|
|
681
898
|
this._releaseRuntimeRefs(record);
|
|
682
899
|
this._emit('sidepanel:run-stopped', record);
|
|
683
900
|
try { await this.onFinish(cleanDescriptor(record)); } catch {}
|
|
@@ -735,19 +952,21 @@ export class NativeLoopRuntime {
|
|
|
735
952
|
return released;
|
|
736
953
|
}
|
|
737
954
|
|
|
738
|
-
|
|
955
|
+
setTools(runId, tools) {
|
|
739
956
|
const record = this.records.get(runId);
|
|
740
|
-
|
|
741
|
-
if (!
|
|
742
|
-
|
|
743
|
-
record.
|
|
957
|
+
if (!record) return null;
|
|
958
|
+
if (!Array.isArray(tools)) throw Object.assign(new Error('tools must be an array'), { code: 'TOOLS_INVALID', status: 400 });
|
|
959
|
+
const normalized = storedToolList({ tools: retainExternalRefs(tools, record.tools) });
|
|
960
|
+
if (JSON.stringify(record.tools) === JSON.stringify(normalized)) return cleanDescriptor(record);
|
|
961
|
+
record.tools = normalized;
|
|
962
|
+
delete record.mcpProfile;
|
|
744
963
|
try {
|
|
745
964
|
const state = this._readState(record.runId);
|
|
746
|
-
if (state) this._writeState(record.runId, { ...state,
|
|
965
|
+
if (state) this._writeState(record.runId, { ...state, tools: normalized });
|
|
747
966
|
} catch (error) {
|
|
748
967
|
this.log(record.runId, 'native:state-write-error', error?.message || String(error));
|
|
749
968
|
}
|
|
750
|
-
return this._emit('sidepanel:run-updated', record, { reason: 'mcp-
|
|
969
|
+
return this._emit('sidepanel:run-updated', record, { reason: 'mcp-tools' });
|
|
751
970
|
}
|
|
752
971
|
|
|
753
972
|
get(runId) {
|
|
@@ -757,15 +976,23 @@ export class NativeLoopRuntime {
|
|
|
757
976
|
|
|
758
977
|
list({ activeOnly = false } = {}) {
|
|
759
978
|
return [...this.records.values()]
|
|
760
|
-
.filter((record) => !activeOnly ||
|
|
979
|
+
.filter((record) => !activeOnly || LIVE_STATUSES.has(record.status))
|
|
761
980
|
.map(cleanDescriptor)
|
|
762
981
|
.sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
|
|
763
982
|
}
|
|
764
983
|
|
|
765
|
-
|
|
984
|
+
/**
|
|
985
|
+
* The server is going down. `keep`: the runs its dispatcher suspends to resume on the next start
|
|
986
|
+
* (assistant-dispatch.js suspendForShutdown); every other running run is stopped. Either way each provider process
|
|
987
|
+
* is ended now (terminate), so nothing outlives the server. A run still waiting for its resume stays suspended.
|
|
988
|
+
*/
|
|
989
|
+
async shutdown(reason = 'server_shutdown', { keep = [] } = {}) {
|
|
990
|
+
const kept = new Set((Array.isArray(keep) ? keep : []).map(String));
|
|
766
991
|
await Promise.allSettled([...this.records.values()]
|
|
767
992
|
.filter((record) => ['starting', 'running'].includes(record.status))
|
|
768
|
-
.map((record) => this.stop(record.runId, reason)));
|
|
993
|
+
.map((record) => (kept.has(record.runId) ? this.suspend(record.runId, reason) : this.stop(record.runId, reason, { terminate: true }))));
|
|
994
|
+
for (const timer of this._holdTimers.values()) clearTimeout(timer);
|
|
995
|
+
this._holdTimers.clear();
|
|
769
996
|
this._persistLedger({ force: true });
|
|
770
997
|
}
|
|
771
998
|
}
|