synabun 2.0.9 → 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 +115 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +68 -4
- 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/launcher.mjs +9 -3
- 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 +43 -5
- 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 +3680 -206
- package/neural-interface/i18n/pt-BR.json +3628 -157
- package/neural-interface/lib/account-usage.js +5 -3
- package/neural-interface/lib/app-controls-api.js +161 -0
- package/neural-interface/lib/assistant-api.js +148 -35
- 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 +122 -44
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +59 -0
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +97 -0
- package/neural-interface/lib/assistant-catalog.js +23 -9
- package/neural-interface/lib/assistant-dispatch.js +874 -156
- package/neural-interface/lib/assistant-envelope.js +22 -2
- 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 +183 -26
- 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-model-catalog.js +64 -14
- 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-settings-schema.js +109 -47
- 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 +164 -67
- package/neural-interface/lib/exec-loop-command.js +4 -1
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/launch-cache.js +293 -0
- package/neural-interface/lib/login-start.js +524 -0
- 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 +565 -50
- package/neural-interface/lib/native-loop-runtime.js +287 -41
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +58 -0
- package/neural-interface/lib/opencode-history.js +49 -204
- 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 +310 -0
- package/neural-interface/lib/opencode-provider-view.js +81 -0
- package/neural-interface/lib/opencode-runtime-config.js +32 -15
- package/neural-interface/lib/opencode-serve-records.js +624 -0
- package/neural-interface/lib/opencode-v2-client.js +53 -131
- package/neural-interface/lib/opencode-v2-ws-requests.js +35 -195
- package/neural-interface/lib/opencode-worker-activity.js +229 -0
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +796 -0
- package/neural-interface/lib/opencode2-proxy.js +76 -0
- package/neural-interface/lib/opencode2-translate.js +1057 -0
- 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/process-identity.js +361 -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 +18 -10
- package/neural-interface/lib/session-title-generator.js +58 -18
- 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/style-guide/api.js +4 -3
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/untrusted-file-headers.js +27 -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 +1354 -50
- package/neural-interface/package.json +6 -2
- package/neural-interface/public/index.html +5 -3
- 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 +76 -16
- 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 +205 -19
- package/neural-interface/public/shared/assistant/asst-api.js +11 -3
- 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 +241 -112
- package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
- 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-hosts.js +49 -2
- 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 +84 -12
- package/neural-interface/public/shared/assistant/asst-panel.js +303 -44
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +93 -58
- package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
- package/neural-interface/public/shared/assistant/asst-render.js +770 -100
- package/neural-interface/public/shared/assistant/asst-route.js +83 -12
- package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
- package/neural-interface/public/shared/assistant/asst-scenes.js +530 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
- 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 +25 -15
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +102 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +165 -13
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +550 -0
- 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 +58 -150
- package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
- package/neural-interface/public/shared/cdx/cdx-render.js +62 -32
- 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 +15 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +201 -74
- 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/cp/cp-markdown.js +4 -57
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/data-cache.js +223 -0
- package/neural-interface/public/shared/desktop-bridge.js +11 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
- package/neural-interface/public/shared/desktop-titlebar.js +214 -28
- package/neural-interface/public/shared/desktop-update-view.js +35 -5
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/file-links.js +73 -8
- package/neural-interface/public/shared/html-shell.js +78 -86
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/launch-prefetch.js +59 -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-caps.js +3 -2
- 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 +9 -2
- 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-modelpicker.js +54 -17
- 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 +140 -254
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +97 -203
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +20 -13
- 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 +53 -82
- 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 +48 -40
- 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 +205 -62
- package/neural-interface/public/shared/opencode-providers.js +39 -0
- 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 +452 -0
- package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
- package/neural-interface/public/shared/settings/settings-app.js +243 -0
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +90 -0
- package/neural-interface/public/shared/settings/settings-ia.js +23 -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/sidepanel-session-status.js +49 -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 +2065 -2150
- 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-assistant.js +27 -5
- package/neural-interface/public/shared/ui-automation-studio.js +155 -152
- package/neural-interface/public/shared/ui-bookmarks.js +2 -1
- package/neural-interface/public/shared/ui-claude-panel.js +153 -13
- package/neural-interface/public/shared/ui-codex-panel.js +1 -0
- 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 +21 -9
- package/neural-interface/public/shared/ui-file-links.js +1 -0
- package/neural-interface/public/shared/ui-image-gallery.js +56 -52
- package/neural-interface/public/shared/ui-invite.js +18 -2
- package/neural-interface/public/shared/ui-keybinds.js +26 -1
- package/neural-interface/public/shared/ui-link.js +9 -9
- package/neural-interface/public/shared/ui-menubar.js +229 -40
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +9 -1
- package/neural-interface/public/shared/ui-navbar.js +4 -24
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-schedules-studio.js +2267 -953
- package/neural-interface/public/shared/ui-sessions.js +20 -7
- package/neural-interface/public/shared/ui-settings.js +679 -496
- package/neural-interface/public/shared/ui-sidebar.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +56 -5
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
- package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
- package/neural-interface/public/shared/ui-skills.js +42 -2781
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +22 -5
- package/neural-interface/public/shared/ui-terminal.js +159 -199
- 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 +14 -5
- 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 -61
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -499
- package/neural-interface/public/shared/ui-update.js +121 -16
- package/neural-interface/public/shared/ui-whiteboard.js +313 -59
- 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 +36 -2
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +72 -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/highlight/LICENSE +29 -0
- package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
- package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
- package/neural-interface/public/vendor/highlight/manifest.json +5 -0
- package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
- package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
- package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
- package/neural-interface/public/vendor/marked/manifest.json +4 -0
- package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
- package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
- package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
- package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
- package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -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 +116 -3
- package/neural-interface/server.js +4834 -2541
- 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 +5 -5
- 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
|
@@ -16,12 +16,12 @@ export function readOpenCodeSessionLink(event = {}) {
|
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function
|
|
19
|
+
export function bindOpenCodeChildSessionTools({
|
|
20
20
|
eventType,
|
|
21
21
|
event,
|
|
22
22
|
sourceRuntime,
|
|
23
23
|
sessionToRuntime,
|
|
24
|
-
|
|
24
|
+
sessionTools,
|
|
25
25
|
runtimes,
|
|
26
26
|
}) {
|
|
27
27
|
if (!CHILD_LINK_EVENT_TYPES.has(eventType)) return { bound: false, reason: 'event-type' };
|
|
@@ -41,10 +41,10 @@ export function bindOpenCodeChildSessionProfile({
|
|
|
41
41
|
runtimes?.get(previousRuntimeId)?.sessions?.delete(childSessionId);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const
|
|
44
|
+
const tools = sourceRuntime.tools || sessionTools?.get(parentSessionId) || null;
|
|
45
45
|
sessionToRuntime.set(childSessionId, sourceRuntimeId);
|
|
46
|
-
if (
|
|
47
|
-
else
|
|
46
|
+
if (tools) sessionTools.set(childSessionId, tools);
|
|
47
|
+
else sessionTools.delete(childSessionId);
|
|
48
48
|
sourceRuntime.sessions?.add(childSessionId);
|
|
49
49
|
|
|
50
50
|
return {
|
|
@@ -52,27 +52,27 @@ export function bindOpenCodeChildSessionProfile({
|
|
|
52
52
|
childSessionId,
|
|
53
53
|
parentSessionId,
|
|
54
54
|
runtimeId: sourceRuntimeId,
|
|
55
|
-
|
|
55
|
+
tools,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* The MCP
|
|
60
|
+
* The MCP tools a sub-agent panel starts with: its parent's. The primary
|
|
61
61
|
* panel's store speaks for the parent only while it is bound to that parent
|
|
62
|
-
* (`parentSessionId`): after a switch its
|
|
63
|
-
* then the parent's saved choice (`
|
|
62
|
+
* (`parentSessionId`): after a switch its tools is another session's, and
|
|
63
|
+
* then the parent's saved choice (`savedTools(parentSessionId)`) or what the
|
|
64
64
|
* child session itself carries is used. Without `parentSessionId` the parent
|
|
65
65
|
* store is trusted as before.
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
67
|
+
export function inheritChildPanelTools(childStore, parentStore, childInfo = null, { parentSessionId, savedTools } = {}) {
|
|
68
68
|
const parentState = parentStore?.getState?.() || null;
|
|
69
69
|
const parentIsBound = !parentSessionId || parentState?.sessionId === parentSessionId;
|
|
70
|
-
const
|
|
70
|
+
const parentTools = parentIsBound ? (parentState?.tools || null) : null;
|
|
71
71
|
let saved = null;
|
|
72
|
-
if (!
|
|
73
|
-
try { saved =
|
|
72
|
+
if (!parentTools && parentSessionId && typeof savedTools === 'function') {
|
|
73
|
+
try { saved = savedTools(parentSessionId) || null; } catch { saved = null; }
|
|
74
74
|
}
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
return
|
|
75
|
+
const tools = parentTools || saved || childInfo?.tools || null;
|
|
76
|
+
if (tools) childStore?.setTools?.(tools);
|
|
77
|
+
return tools;
|
|
78
78
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// listeners (used by the panel manager to spawn child panels).
|
|
7
7
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
8
|
|
|
9
|
+
import { createOutcomeNotifications } from './ocp-v2-outcome-notifications.js';
|
|
9
10
|
import { getDefaultStore } from './ocp-v2-state.js';
|
|
10
11
|
import { notify as uiNotify, NOTIF_TYPE } from '../ui-notifications.js';
|
|
11
12
|
import { nativeLoopWindowId } from '../ui-native-window-id.js';
|
|
@@ -13,30 +14,20 @@ import { registerAutomationSession } from './ocp-v2-automation-ownership.js';
|
|
|
13
14
|
import { applyEvent, resolveEventTargets } from './ocp-v2-events.js';
|
|
14
15
|
import { createCapabilities, gatedRequest } from './ocp-v2-caps.js';
|
|
15
16
|
import { shouldAutoAccept, autoAcceptRequest, autoAcceptInherited } from './ocp-v2-approvals.js';
|
|
16
|
-
import { verifyDescendant, knownDescendant, createReconnectNotifier, requestOwner } from './ocp-v2-rehydrate.js';
|
|
17
|
+
import { verifyDescendant, descendantState, knownDescendant, createReconnectNotifier, requestOwner } from './ocp-v2-rehydrate.js';
|
|
18
|
+
import { createAskTracker, createTurnClock, readOpenAsks, unreadAsksNotice, TURN_LIMIT_MS } from './ocp-v2-send-logic.js';
|
|
17
19
|
|
|
18
20
|
// Request types the connected server answers. Empty against a server that
|
|
19
21
|
// predates the list; cleared on every disconnect and refilled on reconnect.
|
|
20
22
|
export const capabilities = createCapabilities();
|
|
21
23
|
export const supports = (...types) => capabilities.hasAll(...types);
|
|
22
|
-
// The @opencode-ai/sdk version the server answered `init` with ('' from a
|
|
23
|
-
// server that does not say).
|
|
24
|
-
let _sdkVersion = '';
|
|
25
|
-
export const sdkVersion = () => _sdkVersion;
|
|
26
24
|
|
|
27
25
|
const _notifiedPermissionIds = new Set();
|
|
28
|
-
|
|
29
|
-
// duplicates until the next time `running` flips back to true (new turn).
|
|
30
|
-
// ERROR locks out future DONE; DONE allows a later ERROR through.
|
|
31
|
-
const _outcomeKey = new WeakMap(); // store → NOTIF_TYPE.DONE | NOTIF_TYPE.ERROR
|
|
32
|
-
const _outcomeSubscribed = new WeakSet(); // stores already wired for reset
|
|
26
|
+
const _outcomes = createOutcomeNotifications();
|
|
33
27
|
|
|
34
28
|
function _fireOutcomeNotify(store, type) {
|
|
35
|
-
const last = _outcomeKey.get(store);
|
|
36
|
-
if (last === type) return;
|
|
37
|
-
if (last === NOTIF_TYPE.ERROR && type === NOTIF_TYPE.DONE) return;
|
|
38
|
-
_outcomeKey.set(store, type);
|
|
39
29
|
const s = store.getState();
|
|
30
|
+
if (!_outcomes.take(s, type === NOTIF_TYPE.ERROR ? 'error' : 'done')) return;
|
|
40
31
|
const baseLabel = s.sessionInfo?.title || s.sessionInfo?.info?.title || 'OpenCode';
|
|
41
32
|
const label = s.parentSessionId ? `↳ ${baseLabel}` : baseLabel;
|
|
42
33
|
try {
|
|
@@ -44,18 +35,6 @@ function _fireOutcomeNotify(store, type) {
|
|
|
44
35
|
} catch (err) { console.warn('[ocp-v2-ws] outcome notify failed', err); }
|
|
45
36
|
}
|
|
46
37
|
|
|
47
|
-
function _ensureOutcomeReset(store) {
|
|
48
|
-
if (_outcomeSubscribed.has(store)) return;
|
|
49
|
-
_outcomeSubscribed.add(store);
|
|
50
|
-
try {
|
|
51
|
-
store.subscribe((event, state) => {
|
|
52
|
-
if (event?.type === 'running:set' && state.running) {
|
|
53
|
-
_outcomeKey.delete(store);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
} catch (err) { console.warn('[ocp-v2-ws] outcome subscribe failed', err); }
|
|
57
|
-
}
|
|
58
|
-
|
|
59
38
|
let _ws = null;
|
|
60
39
|
let _connecting = null;
|
|
61
40
|
let _reqSeq = 0;
|
|
@@ -99,6 +78,7 @@ export async function connect() {
|
|
|
99
78
|
catch (err) { console.warn('[ocp-v2-ws] identify failed', err); }
|
|
100
79
|
_connecting = null;
|
|
101
80
|
_reconnects.opened();
|
|
81
|
+
asksOpened();
|
|
102
82
|
resolve(ws);
|
|
103
83
|
});
|
|
104
84
|
|
|
@@ -114,7 +94,11 @@ export async function connect() {
|
|
|
114
94
|
_connecting = null;
|
|
115
95
|
capabilities.clear();
|
|
116
96
|
_reconnects.closed();
|
|
117
|
-
for (const [, p] of _pending) p.reject(new Error('websocket closed'));
|
|
97
|
+
for (const [, p] of _pending) { p.timeout.cancel(); p.reject(new Error('websocket closed')); }
|
|
98
|
+
// What waits on the user is not known again until the server's lists are read after the reconnect
|
|
99
|
+
// (rebuildAsks): until then no turn's clock counts. A socket that never opened lost nothing.
|
|
100
|
+
if (opened) _asks.hold();
|
|
101
|
+
asksClosed();
|
|
118
102
|
_pending.clear();
|
|
119
103
|
broadcastServerStatus({ status: 'reconnecting' });
|
|
120
104
|
setTimeout(() => { connect().catch(() => {}); }, 1500);
|
|
@@ -139,6 +123,21 @@ function broadcastServerStatus(payload) {
|
|
|
139
123
|
for (const store of _allStores) store.setServerStatus(payload);
|
|
140
124
|
}
|
|
141
125
|
|
|
126
|
+
// Why OpenCode cannot be used, as the server says it (an OpenCode version
|
|
127
|
+
// SynaBun does not drive, a port held by an OpenCode server it did not start,
|
|
128
|
+
// a web page where the API should be): one line in each panel's error list,
|
|
129
|
+
// never a second copy of the same sentence while the panel keeps retrying.
|
|
130
|
+
function broadcastServerProblem(text) {
|
|
131
|
+
const message = typeof text === 'string' ? text.trim().slice(0, 600) : '';
|
|
132
|
+
if (!message) return;
|
|
133
|
+
const stores = _allStores.size ? [..._allStores] : [getDefaultStore()];
|
|
134
|
+
for (const store of stores) {
|
|
135
|
+
const errors = store.getState?.().errors || [];
|
|
136
|
+
if (errors.some((err) => err?.message === message)) continue;
|
|
137
|
+
store.pushError?.({ message, kind: 'server' });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
142
141
|
export function disconnect() {
|
|
143
142
|
if (_ws) {
|
|
144
143
|
try { _ws.close(); } catch {}
|
|
@@ -152,7 +151,6 @@ export function disconnect() {
|
|
|
152
151
|
export function subscribeSession(sessionId, store) {
|
|
153
152
|
if (!store) return () => {};
|
|
154
153
|
_allStores.add(store);
|
|
155
|
-
_ensureOutcomeReset(store);
|
|
156
154
|
if (!sessionId) {
|
|
157
155
|
// Not yet bound — caller should call again once a session exists.
|
|
158
156
|
return () => { _allStores.delete(store); };
|
|
@@ -160,6 +158,7 @@ export function subscribeSession(sessionId, store) {
|
|
|
160
158
|
let set = _storesBySession.get(sessionId);
|
|
161
159
|
if (!set) { set = new Set(); _storesBySession.set(sessionId, set); }
|
|
162
160
|
set.add(store);
|
|
161
|
+
readAsksOf(sessionId);
|
|
163
162
|
return () => {
|
|
164
163
|
const s = _storesBySession.get(sessionId);
|
|
165
164
|
if (s) {
|
|
@@ -195,6 +194,7 @@ function handleMessage(msg) {
|
|
|
195
194
|
// Broadcast to every registered store; also poke the default singleton
|
|
196
195
|
// so legacy callers (no panel registered yet) still see status.
|
|
197
196
|
broadcastServerStatus(payload);
|
|
197
|
+
if (msg.status === 'error' && msg.error) broadcastServerProblem(msg.error);
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -206,6 +206,7 @@ function handleMessage(msg) {
|
|
|
206
206
|
if (msg.type === 'capabilities') {
|
|
207
207
|
capabilities.set(msg.capabilities);
|
|
208
208
|
_reconnects.capabilities();
|
|
209
|
+
asksReady();
|
|
209
210
|
return;
|
|
210
211
|
}
|
|
211
212
|
|
|
@@ -216,6 +217,7 @@ function handleMessage(msg) {
|
|
|
216
217
|
if (msg.nativeRunId && msg.nativeRootSessionId) {
|
|
217
218
|
registerAutomationSession(msg.nativeRootSessionId, msg.nativeRunId);
|
|
218
219
|
}
|
|
220
|
+
_asks.note(msg.eventType, msg.event || {});
|
|
219
221
|
handleEvent(msg.eventType, msg.event || {});
|
|
220
222
|
fanout(msg.eventType, msg.event || {});
|
|
221
223
|
return;
|
|
@@ -224,10 +226,11 @@ function handleMessage(msg) {
|
|
|
224
226
|
if (msg.id != null && _pending.has(msg.id)) {
|
|
225
227
|
const p = _pending.get(msg.id);
|
|
226
228
|
_pending.delete(msg.id);
|
|
227
|
-
|
|
229
|
+
p.timeout.cancel();
|
|
228
230
|
if (msg.type === 'init:result') {
|
|
229
231
|
capabilities.set(msg.capabilities);
|
|
230
|
-
if (
|
|
232
|
+
if (msg.ready === false && msg.problem) broadcastServerProblem(msg.problem);
|
|
233
|
+
asksReady();
|
|
231
234
|
}
|
|
232
235
|
p.resolve(msg);
|
|
233
236
|
return;
|
|
@@ -265,6 +268,18 @@ function handleEvent(eventType, ev) {
|
|
|
265
268
|
// Lets a sub-agent's permission or question reach the panel of its parent
|
|
266
269
|
// when no child panel is open for it.
|
|
267
270
|
const _parentOf = new Map();
|
|
271
|
+
|
|
272
|
+
// Requests that wait on the user, by session (a sub-agent's count for its parent): a turn's send does not
|
|
273
|
+
// count the time they wait (createTurnClock). A permission left open for more than 30 minutes used to end
|
|
274
|
+
// the turn's send with "request timeout: message:send" while the turn went on in OpenCode. Across a lost
|
|
275
|
+
// socket they are held from the close and read again from the server after the reconnect (rebuildAsks); a
|
|
276
|
+
// session a panel is bound to after the page loaded has its own read once (readAsksOf).
|
|
277
|
+
const _asks = createAskTracker({ parentOf: _parentOf });
|
|
278
|
+
/** True while `sessionId`, or a sub-agent below it, waits on a permission or a question. */
|
|
279
|
+
export const sessionWaitsOnUser = (sessionId) => _asks.waits(sessionId);
|
|
280
|
+
/** `listener()` whenever what waits on the user may have changed; returns an unsubscribe. */
|
|
281
|
+
export const onAsksChanged = (listener) => _asks.subscribe(listener);
|
|
282
|
+
|
|
268
283
|
function rememberParent(ev) {
|
|
269
284
|
const info = ev?.info || ev?.session || ev || {};
|
|
270
285
|
const childId = info.id || ev?.sessionID || ev?.sessionId;
|
|
@@ -316,15 +331,19 @@ const _rootSessions = new Set();
|
|
|
316
331
|
* from the session itself. Anything that cannot be established is false.
|
|
317
332
|
*/
|
|
318
333
|
export function isDescendantSession(sessionId, ancestorId) {
|
|
319
|
-
return verifyDescendant(sessionId, ancestorId, {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
334
|
+
return verifyDescendant(sessionId, ancestorId, { parentOf: _parentOf, roots: _rootSessions, fetchParent: fetchSessionParent });
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// The same question with "could not be read" kept apart from "no" (true, false or null): what the open
|
|
338
|
+
// requests read from the server need, so that a sub-agent whose place is unknown keeps its parent waiting.
|
|
339
|
+
function sessionAncestry(sessionId, ancestorId) {
|
|
340
|
+
return descendantState(sessionId, ancestorId, { parentOf: _parentOf, roots: _rootSessions, fetchParent: fetchSessionParent });
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function fetchSessionParent(id) {
|
|
344
|
+
const res = await api.sessionGet(id);
|
|
345
|
+
if (!res || res.error || (typeof res.status === 'number' && res.status >= 400) || !res.data?.id) return null;
|
|
346
|
+
return String(res.data.parentID || res.data.parentId || '');
|
|
328
347
|
}
|
|
329
348
|
|
|
330
349
|
/**
|
|
@@ -336,11 +355,135 @@ export function isKnownDescendantSession(sessionId, ancestorId) {
|
|
|
336
355
|
return knownDescendant(sessionId, ancestorId, _parentOf);
|
|
337
356
|
}
|
|
338
357
|
|
|
358
|
+
// ── What waits on the user, read from the server ───────────────────────────
|
|
359
|
+
// The stream says what is asked and answered while the socket is up. What was asked before (the page loaded,
|
|
360
|
+
// a panel was bound to another session, the socket was down) is read from the server (permission:list and
|
|
361
|
+
// question:list), one session at a time: its clocks wait until then. After a
|
|
362
|
+
// reconnect every bound session is read again (rebuildAsks). A list that cannot be read is read again a few
|
|
363
|
+
// times; then the session's clocks count again and its panel says so (noteUnreadAsks).
|
|
364
|
+
|
|
365
|
+
// A sub-agent runs on its parent's serve, in its folder: a bound parent's lists hold its requests too.
|
|
366
|
+
function underSession(sessionId, isAncestor) {
|
|
367
|
+
let cursor = parentSessionOf(sessionId);
|
|
368
|
+
for (let depth = 0; cursor && depth < 12; depth++) {
|
|
369
|
+
if (isAncestor(cursor)) return true;
|
|
370
|
+
cursor = parentSessionOf(cursor);
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// The sessions whose lists were read (or are out) since the socket opened.
|
|
376
|
+
const _asksRead = new Set();
|
|
377
|
+
// Bound sessions waiting for the socket to say what it serves before their lists are read.
|
|
378
|
+
const _asksUnread = new Set();
|
|
379
|
+
let _asksReady = false;
|
|
380
|
+
let _asksReadyTimer = null;
|
|
381
|
+
let _asksFlushTimer = null;
|
|
382
|
+
const asksKnown = (sessionId) => _asksRead.has(sessionId) || underSession(sessionId, (id) => _asksRead.has(id));
|
|
383
|
+
|
|
384
|
+
function askSession(sessionId, kinds) {
|
|
385
|
+
const s = [...(_storesBySession.get(sessionId) || [])][0]?.getState?.() || {};
|
|
386
|
+
return { sessionId, cwd: s.cwd || s.sessionInfo?.directory || undefined, ...(kinds ? { kinds } : {}) };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// `want`: null for every bound session (not one under another), else the sessions (and lists) to read.
|
|
390
|
+
// The first read of sessions bound at a page load (or later) looks up no sub-agent's place: the panel manager
|
|
391
|
+
// reads the session tree right then, for the pills, and the read again a second later finds the links it
|
|
392
|
+
// learned (a list holding a request whose place is not known yet is unresolved meanwhile: its session waits).
|
|
393
|
+
// After a reconnect the tree is known; only a sub-agent spawned during the outage is looked up.
|
|
394
|
+
function readAsks(want, { attempt = 1, partial = false } = {}) {
|
|
395
|
+
const bound = new Set(_storesBySession.keys());
|
|
396
|
+
const sessions = want
|
|
397
|
+
? want.filter(({ sessionId }) => bound.has(sessionId)).map(({ sessionId, kinds }) => askSession(sessionId, kinds))
|
|
398
|
+
: [...bound].filter((sessionId) => !underSession(sessionId, (id) => bound.has(id))).map((sessionId) => askSession(sessionId));
|
|
399
|
+
for (const { sessionId } of sessions) _asksRead.add(sessionId);
|
|
400
|
+
return readOpenAsks(api, sessions, {
|
|
401
|
+
ancestry: sessionAncestry,
|
|
402
|
+
known: (owner, root) => knownDescendant(owner, root, _parentOf),
|
|
403
|
+
...(partial && attempt === 1 ? { maxLookups: 0 } : {}),
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// The tracker gave up on some lists: the panels of those sessions say that their clock counts again.
|
|
408
|
+
function noteUnreadAsks(result) {
|
|
409
|
+
if (!result) return;
|
|
410
|
+
const lost = result.unread
|
|
411
|
+
? [..._storesBySession.keys()].map((sessionId) => ({ sessionId, kinds: undefined }))
|
|
412
|
+
: result.gaveUp || [];
|
|
413
|
+
for (const { sessionId, kinds } of lost) {
|
|
414
|
+
const message = unreadAsksNotice(kinds);
|
|
415
|
+
for (const store of _storesBySession.get(sessionId) || []) {
|
|
416
|
+
if ((store.getState?.().errors || []).some((err) => err?.message === message)) continue;
|
|
417
|
+
store.pushError?.({ message, notice: true });
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function rebuildAsks() {
|
|
423
|
+
return _asks.rebuild(readAsks).then(noteUnreadAsks);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// A session a panel was bound to: unless its lists (or a bound parent's) were read since the socket opened,
|
|
427
|
+
// its clocks wait from now and its lists are read once the socket can serve them.
|
|
428
|
+
function readAsksOf(sessionId) {
|
|
429
|
+
if (!sessionId || asksKnown(sessionId) || _asksUnread.has(sessionId)) return;
|
|
430
|
+
_asksUnread.add(sessionId);
|
|
431
|
+
_asks.expect([sessionId]);
|
|
432
|
+
flushAsksSoon();
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function flushAsksSoon() {
|
|
436
|
+
if (_asksFlushTimer || !_asksReady || !_asksUnread.size) return;
|
|
437
|
+
_asksFlushTimer = setTimeout(() => {
|
|
438
|
+
_asksFlushTimer = null;
|
|
439
|
+
if (!_asksReady) return;
|
|
440
|
+
// Those no panel is bound to any more are let go by the tracker (not in its answer); those whose lists
|
|
441
|
+
// were read meanwhile (their own, or a bound parent's) wait for nothing more.
|
|
442
|
+
// A sub-agent read in the same go as its parent is read with it.
|
|
443
|
+
const batch = [..._asksUnread];
|
|
444
|
+
const known = batch.filter((sessionId) => _storesBySession.has(sessionId)
|
|
445
|
+
&& (asksKnown(sessionId) || underSession(sessionId, (id) => id !== sessionId && batch.includes(id) && _storesBySession.has(id))));
|
|
446
|
+
const sessions = batch.filter((sessionId) => !known.includes(sessionId));
|
|
447
|
+
_asksUnread.clear();
|
|
448
|
+
if (known.length) _asks.release(known);
|
|
449
|
+
if (!sessions.length) return;
|
|
450
|
+
_asks.rebuild(readAsks, { sessions }).then(noteUnreadAsks)
|
|
451
|
+
.catch((err) => console.warn('[ocp-v2-ws] reading the open questions failed', err));
|
|
452
|
+
}, 0);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// The lists can be asked for once the socket said what it serves (capabilities, init:result), or, from a
|
|
456
|
+
// server that does not say, a moment after it opened.
|
|
457
|
+
function asksOpened() {
|
|
458
|
+
clearTimeout(_asksReadyTimer);
|
|
459
|
+
_asksReadyTimer = setTimeout(asksReady, 1500);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function asksReady() {
|
|
463
|
+
clearTimeout(_asksReadyTimer);
|
|
464
|
+
_asksReadyTimer = null;
|
|
465
|
+
if (!isConnected()) return;
|
|
466
|
+
_asksReady = true;
|
|
467
|
+
flushAsksSoon();
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// (A session still to be read stays so: a socket that never opened read nothing, and after a reconnect
|
|
471
|
+
// rebuildAsks reads every bound session anyway.)
|
|
472
|
+
function asksClosed() {
|
|
473
|
+
clearTimeout(_asksReadyTimer);
|
|
474
|
+
clearTimeout(_asksFlushTimer);
|
|
475
|
+
_asksReadyTimer = null;
|
|
476
|
+
_asksFlushTimer = null;
|
|
477
|
+
_asksReady = false;
|
|
478
|
+
_asksRead.clear();
|
|
479
|
+
}
|
|
480
|
+
|
|
339
481
|
// The socket came back after an outage: whatever was sent meanwhile reached no
|
|
340
482
|
// panel. Listeners re-read their session (the primary panel does it through its
|
|
341
483
|
// auto-heal; the panel manager does it for the sub-agent panel).
|
|
342
484
|
const _reconnectListeners = new Set();
|
|
343
485
|
const _reconnects = createReconnectNotifier(() => {
|
|
486
|
+
rebuildAsks().catch((err) => console.warn('[ocp-v2-ws] reading the open questions again failed', err));
|
|
344
487
|
for (const fn of _reconnectListeners) {
|
|
345
488
|
try { fn(); } catch (e) { console.warn('[ocp-v2-ws] reconnect listener error', e); }
|
|
346
489
|
}
|
|
@@ -462,14 +605,23 @@ function fanout(eventType, ev) {
|
|
|
462
605
|
|
|
463
606
|
// ── Request/response (id-correlated, 30s default timeout) ──
|
|
464
607
|
|
|
465
|
-
|
|
608
|
+
// `turnOf`: the session whose turn the request waits for (a prompt, a command). Its clock stops while that
|
|
609
|
+
// session waits on the user, so only working time counts toward `timeoutMs` (createTurnClock).
|
|
610
|
+
function request(payload, timeoutMs = 30000, { turnOf = '' } = {}) {
|
|
466
611
|
return new Promise(async (resolve, reject) => {
|
|
467
612
|
try { await connect(); } catch (e) { return reject(e); }
|
|
468
613
|
const id = ++_reqSeq;
|
|
469
|
-
const
|
|
614
|
+
const expire = () => {
|
|
470
615
|
_pending.delete(id);
|
|
471
616
|
reject(new Error(`request timeout: ${payload.type}`));
|
|
472
|
-
}
|
|
617
|
+
};
|
|
618
|
+
let timeout;
|
|
619
|
+
if (turnOf) {
|
|
620
|
+
timeout = createTurnClock({ ms: timeoutMs, paused: () => sessionWaitsOnUser(turnOf), subscribe: onAsksChanged, onExpire: expire });
|
|
621
|
+
} else {
|
|
622
|
+
const timer = setTimeout(expire, timeoutMs);
|
|
623
|
+
timeout = { cancel: () => clearTimeout(timer) };
|
|
624
|
+
}
|
|
473
625
|
_pending.set(id, { resolve, reject, timeout });
|
|
474
626
|
_ws.send(JSON.stringify({ ...payload, id }));
|
|
475
627
|
});
|
|
@@ -487,17 +639,17 @@ export const api = {
|
|
|
487
639
|
sessionMessages:(sessionId) => request({ type: 'session:messages', sessionId }),
|
|
488
640
|
sessionContext: ({ sessionId, cwd } = {}) => request({ type: 'session:context', sessionId, cwd }),
|
|
489
641
|
// `human` / `greetingId`: lib/greeting/ (a server that does not know them ignores them).
|
|
490
|
-
send: ({ sessionId, parts, model, agent, mode, variant, cwd,
|
|
491
|
-
request({ type: 'message:send', sessionId, parts, model, agent, mode, variant, cwd,
|
|
642
|
+
send: ({ sessionId, parts, model, agent, mode, variant, cwd, tools, noAbortPrev, human, greetingId }) =>
|
|
643
|
+
request({ type: 'message:send', sessionId, parts, model, agent, mode, variant, cwd, tools, noAbortPrev: !!noAbortPrev, ...(human ? { human: true } : {}), ...(greetingId ? { greetingId } : {}) }, TURN_LIMIT_MS, { turnOf: sessionId }),
|
|
492
644
|
abort: (sessionId) => request({ type: 'message:abort', sessionId }),
|
|
493
|
-
compact: ({ sessionId, cwd,
|
|
645
|
+
compact: ({ sessionId, cwd, tools } = {}) => request({ type: 'session:compact', sessionId, cwd, tools }, 5 * 60 * 1000),
|
|
494
646
|
permissionReply: ({ sessionId, permissionId, response, cwd, message }) =>
|
|
495
647
|
request({ type: 'permission:reply', sessionId, permissionId, response, cwd, message }),
|
|
496
648
|
questionList: ({ cwd, sessionId } = {}) => request({ type: 'question:list', cwd, sessionId }),
|
|
497
649
|
questionReply: ({ requestId, answers, cwd, sessionId }) => request({ type: 'question:reply', requestId, answers, cwd, sessionId }),
|
|
498
650
|
questionReject: ({ requestId, sessionId }) => request({ type: 'question:reject', requestId, sessionId }),
|
|
499
|
-
|
|
500
|
-
|
|
651
|
+
toolsGet: (sessionId) => gated({ type: 'mcp:tools:get', sessionId }),
|
|
652
|
+
toolsSet: (sessionId, tools) => gated({ type: 'mcp:tools:set', sessionId, tools }, 45_000),
|
|
501
653
|
|
|
502
654
|
// ── Newer request types: sent only when the server lists them (see
|
|
503
655
|
// ocp-v2-caps.js); otherwise they resolve { ok:false, unsupported:true }.
|
|
@@ -508,16 +660,12 @@ export const api = {
|
|
|
508
660
|
sessionUnrevert: ({ sessionId, cwd } = {}) => gated({ type: 'session:unrevert', sessionId, cwd }),
|
|
509
661
|
sessionFork: ({ sessionId, messageID, cwd } = {}) => gated({ type: 'session:fork', sessionId, messageID, cwd }),
|
|
510
662
|
sessionChildren: ({ sessionId, cwd } = {}) => gated({ type: 'session:children', sessionId, cwd }),
|
|
511
|
-
sessionShare: ({ sessionId, cwd } = {}) => gated({ type: 'session:share', sessionId, cwd }),
|
|
512
|
-
sessionUnshare: ({ sessionId, cwd } = {}) => gated({ type: 'session:unshare', sessionId, cwd }),
|
|
513
|
-
sessionSharePolicy: ({ cwd } = {}) => gated({ type: 'session:share:policy', cwd }),
|
|
514
|
-
messageDelete: ({ sessionId, messageID, cwd } = {}) => gated({ type: 'message:delete', sessionId, messageID, cwd }),
|
|
515
663
|
commandList: ({ cwd } = {}) => gated({ type: 'command:list', cwd }),
|
|
516
664
|
// A command is a turn: it can run as long as a prompt does.
|
|
517
|
-
commandRun: ({ sessionId, command, arguments: args, agent, model, variant, parts, cwd,
|
|
518
|
-
gated({ type: 'command:run', sessionId, command, arguments: args, agent, model, variant, parts, cwd,
|
|
519
|
-
sessionShell: ({ sessionId, command, agent, model, cwd,
|
|
520
|
-
gated({ type: 'session:shell', sessionId, command, agent, model, cwd,
|
|
665
|
+
commandRun: ({ sessionId, command, arguments: args, agent, model, variant, parts, cwd, tools } = {}) =>
|
|
666
|
+
gated({ type: 'command:run', sessionId, command, arguments: args, agent, model, variant, parts, cwd, tools }, TURN_LIMIT_MS, { turnOf: sessionId }),
|
|
667
|
+
sessionShell: ({ sessionId, command, agent, model, cwd, tools } = {}) =>
|
|
668
|
+
gated({ type: 'session:shell', sessionId, command, agent, model, cwd, tools }, 10 * 60 * 1000),
|
|
521
669
|
findFiles: ({ query, cwd, dirs } = {}) => gated({ type: 'find:files', query, cwd, dirs }, 10000),
|
|
522
670
|
findSymbols: ({ sessionId, query, cwd } = {}) => gated({ type: 'find:symbols', sessionId, query, cwd }, 10000),
|
|
523
671
|
resourceList: ({ sessionId, cwd } = {}) => gated({ type: 'resource:list', sessionId, cwd }, 15000),
|
|
@@ -527,20 +675,15 @@ export const api = {
|
|
|
527
675
|
vcsGet: ({ cwd } = {}) => gated({ type: 'vcs:get', cwd }),
|
|
528
676
|
vcsStatus: ({ cwd } = {}) => gated({ type: 'vcs:status', cwd }),
|
|
529
677
|
vcsDiff: ({ cwd, mode } = {}) => gated({ type: 'vcs:diff', cwd, mode }, 60_000),
|
|
530
|
-
worktreeList: ({ cwd } = {}) => gated({ type: 'worktree:list', cwd }),
|
|
531
|
-
worktreeCreate: ({ cwd, name } = {}) => gated({ type: 'worktree:create', cwd, name }, 60_000),
|
|
532
|
-
worktreeRemove: ({ cwd, directory } = {}) => gated({ type: 'worktree:remove', cwd, directory }, 60_000),
|
|
533
678
|
mcpStatus: ({ sessionId, cwd } = {}) => gated({ type: 'mcp:status', sessionId, cwd }),
|
|
534
679
|
mcpConnect: ({ sessionId, name, cwd } = {}) => gated({ type: 'mcp:connect', sessionId, name, cwd }, 60_000),
|
|
535
680
|
mcpDisconnect: ({ sessionId, name, cwd } = {}) => gated({ type: 'mcp:disconnect', sessionId, name, cwd }, 60_000),
|
|
536
|
-
// OAuth: OpenCode opens the browser and waits for the callback.
|
|
537
|
-
mcpAuthenticate: ({ sessionId, name, cwd } = {}) => gated({ type: 'mcp:authenticate', sessionId, name, cwd }, 5 * 60 * 1000 + 5000),
|
|
538
681
|
// Registers a server on the serve running this session and, with `persist`,
|
|
539
682
|
// saves it to the OpenCode config in the same request (see ocp-v2-status.js).
|
|
540
683
|
mcpAdd: ({ sessionId, name, config, persist, cwd } = {}) => gated({ type: 'mcp:add', sessionId, name, config, persist: persist === true, cwd }, 60_000),
|
|
541
684
|
envStatus: ({ sessionId, cwd } = {}) => gated({ type: 'env:status', sessionId, cwd }),
|
|
542
685
|
};
|
|
543
686
|
|
|
544
|
-
function gated(payload, timeoutMs) {
|
|
545
|
-
return gatedRequest(capabilities, request, payload, timeoutMs);
|
|
687
|
+
function gated(payload, timeoutMs, options) {
|
|
688
|
+
return gatedRequest(capabilities, request, payload, timeoutMs, options);
|
|
546
689
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — OpenCode's providers, as the pickers read them
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
// GET /api/opencode/providers/full?view=compact: the connected providers only,
|
|
5
|
+
// with every field their models carry (the whole models.dev catalog is
|
|
6
|
+
// megabytes, and only Settings → OpenCode lists it). One copy in the data
|
|
7
|
+
// cache (data-cache.js) for every module that reads it: the OpenCode panel's
|
|
8
|
+
// model and variant pickers, its context gauge and composer, the Assistant's
|
|
9
|
+
// and the Studios' model lists. A provider change (`ocp-providers-changed`,
|
|
10
|
+
// which reaches every window: the OpenCode socket where a panel is open, the
|
|
11
|
+
// sync socket everywhere) drops it and asks for it again at once.
|
|
12
|
+
|
|
13
|
+
import { createDataCache } from './data-cache.js';
|
|
14
|
+
import { registerLaunchPrefetch } from './launch-prefetch.js';
|
|
15
|
+
|
|
16
|
+
export const OPENCODE_PROVIDERS_URL = '/api/opencode/providers/full?view=compact';
|
|
17
|
+
|
|
18
|
+
export const opencodeProviders = createDataCache('opencode-providers', {
|
|
19
|
+
ttlMs: 5 * 60_000,
|
|
20
|
+
persist: true,
|
|
21
|
+
load: async (_key, { force }) => {
|
|
22
|
+
const resp = await fetch(force ? `${OPENCODE_PROVIDERS_URL}&refresh=1` : OPENCODE_PROVIDERS_URL);
|
|
23
|
+
// A body that is not JSON (a web page) throws: nothing is kept.
|
|
24
|
+
return resp.json();
|
|
25
|
+
},
|
|
26
|
+
// Only a provider list is kept: `{ ok: false }` (the serve is not running, an error) never is.
|
|
27
|
+
accept: (body) => !!body && body.ok !== false && !!body.data && typeof body.data === 'object' && !Array.isArray(body.data),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/** The parsed body `{ ok, data: { all, default, connected } }`, connected providers only. */
|
|
31
|
+
export function fetchOpencodeProviders({ force = false } = {}) {
|
|
32
|
+
return opencodeProviders.get('', { force });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof document !== 'undefined') {
|
|
36
|
+
document.addEventListener('ocp-providers-changed', () => opencodeProviders.invalidate('', { refetch: true }));
|
|
37
|
+
// Launch: read once the page has painted, so the first OpenCode picker opens from it.
|
|
38
|
+
registerLaunchPrefetch('opencode-providers', () => opencodeProviders.prefetch(''), { order: 8, owner: true });
|
|
39
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun — the page secret's recovery: an open tab outlives a server restart
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// The server tells the owner's own page from a local process by a secret it mints per boot and hands the page as
|
|
6
|
+
// an HttpOnly cookie (lib/page-session.js). The page's code never sees or sends that cookie: the browser does. A
|
|
7
|
+
// restart mints a new secret, and a tab that stayed open still carries the old cookie, so its first owner write
|
|
8
|
+
// (a dispatch, Protect workers, a route card, a Skills Studio install…) would come back 403 UI_ONLY or
|
|
9
|
+
// PAGE_SECRET_REQUIRED and the owner would have to reload. The owner wants zero friction, so this module wraps the
|
|
10
|
+
// page's fetch once: when a same-origin write is refused with one of those two codes, it asks GET /api/page-session
|
|
11
|
+
// (which sets this boot's cookie), then sends the very same request once more and hands back that answer. No
|
|
12
|
+
// reload, no toast (the toast fires on the error jsonFetch throws, and it throws only on the final answer), no lost
|
|
13
|
+
// action. Anything else (a read, another 403, a refusal the refresh did not cure, a body that cannot be sent
|
|
14
|
+
// twice) is handed back as it came, so nothing changes for a request this is not about.
|
|
15
|
+
//
|
|
16
|
+
// No imports and nothing done at load under Node: tests load it with node --test and a fake fetch. In a browser it
|
|
17
|
+
// installs itself on window.fetch when the page loads it (index.html, index2d.html and sidepanel-session.html load
|
|
18
|
+
// it as their first module script, before any module that writes), and once only.
|
|
19
|
+
|
|
20
|
+
/** The route that hands an open tab this boot's cookie (lib/page-session.js PAGE_SECRET_REFRESH_PATH). */
|
|
21
|
+
export const PAGE_SECRET_REFRESH_PATH = '/api/page-session';
|
|
22
|
+
/** The refusals that mean "the page secret is missing or stale", and nothing else. */
|
|
23
|
+
export const PAGE_SECRET_CODES = Object.freeze(['UI_ONLY', 'PAGE_SECRET_REQUIRED']);
|
|
24
|
+
const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
25
|
+
|
|
26
|
+
/** Whether an answer is the server refusing a write for want of this boot's page secret. */
|
|
27
|
+
export function isPageSecretRefusal(status, body) {
|
|
28
|
+
return Number(status) === 403 && !!body && typeof body === 'object' && PAGE_SECRET_CODES.includes(body.code);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* What a request is, for the retry: its method, whether it is same-origin, and the arguments that send it again,
|
|
33
|
+
* or null when it is not a write, goes elsewhere, or cannot be sent twice (a streamed body).
|
|
34
|
+
*/
|
|
35
|
+
export function replayPlan(input, init, origin = null) {
|
|
36
|
+
const isRequest = typeof Request !== 'undefined' && input instanceof Request;
|
|
37
|
+
const method = String(init?.method || (isRequest ? input.method : '') || 'GET').toUpperCase();
|
|
38
|
+
if (SAFE_METHODS.has(method)) return null;
|
|
39
|
+
const url = isRequest ? input.url : (input instanceof URL ? input.href : String(input ?? ''));
|
|
40
|
+
if (!sameOrigin(url, origin)) return null;
|
|
41
|
+
const body = init?.body;
|
|
42
|
+
if (body && typeof body === 'object' && typeof body.getReader === 'function') return null; // a stream is read once
|
|
43
|
+
// fetch(request) reads the request's body: a copy taken before the first send is what the second one sends.
|
|
44
|
+
const again = isRequest ? input.clone() : input;
|
|
45
|
+
return { method, url, args: init === undefined ? [again] : [again, init] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function sameOrigin(url, origin) {
|
|
49
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url) && !url.startsWith('//')) return true; // a path of this page
|
|
50
|
+
if (!origin) return false;
|
|
51
|
+
try { return new URL(url).origin === new URL(origin).origin; } catch { return false; }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A fetch over `fetchImpl` that recovers the page secret once: the refresh is one request at a time (writes refused
|
|
56
|
+
* together share it), the refused request is sent again only when the refresh answered, and the second answer is
|
|
57
|
+
* final whatever it says.
|
|
58
|
+
*/
|
|
59
|
+
export function createPageSessionFetch(fetchImpl, { refreshPath = PAGE_SECRET_REFRESH_PATH, origin = null, onRecover = null } = {}) {
|
|
60
|
+
if (typeof fetchImpl !== 'function') throw new TypeError('createPageSessionFetch needs a fetch');
|
|
61
|
+
let refreshing = null;
|
|
62
|
+
function refreshCookie() {
|
|
63
|
+
if (!refreshing) {
|
|
64
|
+
refreshing = (async () => {
|
|
65
|
+
try {
|
|
66
|
+
const res = await fetchImpl(refreshPath, { method: 'GET', credentials: 'same-origin', cache: 'no-store', headers: { Accept: 'application/json' } });
|
|
67
|
+
return !!res && res.ok === true;
|
|
68
|
+
} catch { return false; } finally { refreshing = null; }
|
|
69
|
+
})();
|
|
70
|
+
}
|
|
71
|
+
return refreshing;
|
|
72
|
+
}
|
|
73
|
+
return async function pageSessionFetch(input, init) {
|
|
74
|
+
const plan = replayPlan(input, init, origin);
|
|
75
|
+
const res = await fetchImpl(input, init);
|
|
76
|
+
if (!plan || !res || res.status !== 403 || typeof res.clone !== 'function') return res;
|
|
77
|
+
let body = null;
|
|
78
|
+
try { body = await res.clone().json(); } catch { return res; }
|
|
79
|
+
if (!isPageSecretRefusal(res.status, body)) return res;
|
|
80
|
+
if (!(await refreshCookie())) return res;
|
|
81
|
+
try { onRecover?.({ method: plan.method, url: plan.url, code: body.code }); } catch { /* a listener's own error */ }
|
|
82
|
+
return fetchImpl(...plan.args);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Wrap `target.fetch` (the window's) once; returns true when it did, false when it already had or there is none. */
|
|
87
|
+
export function installPageSessionRecovery(target = globalThis) {
|
|
88
|
+
if (!target || typeof target.fetch !== 'function' || target.__synabunPageSession) return false;
|
|
89
|
+
const original = target.fetch.bind(target);
|
|
90
|
+
const origin = target.location && typeof target.location.origin === 'string' ? target.location.origin : null;
|
|
91
|
+
target.fetch = createPageSessionFetch(original, { origin });
|
|
92
|
+
try { Object.defineProperty(target, '__synabunPageSession', { value: true, configurable: true }); } catch { target.__synabunPageSession = true; }
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') installPageSessionRecovery(window);
|