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
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
// ── Skill bundles: export, and import through a staging area ──
|
|
2
|
+
// A bundle is a JSON document (`synabun-skill-bundle`) holding one skill folder, or one command or agent file
|
|
3
|
+
// with its icon. Version 2, written by the export, keeps every file byte for byte: text as text, anything else
|
|
4
|
+
// as base64, each with its size, its SHA-256 and whether it is executable, plus the folders (an empty one too)
|
|
5
|
+
// and the entries it left out on purpose (hidden files, node_modules) with the reason. Version 1, written before,
|
|
6
|
+
// is still read; it never carried modes or hashes.
|
|
7
|
+
//
|
|
8
|
+
// An import never writes into a folder Claude Code, Codex or OpenCode reads skills from. It is checked whole
|
|
9
|
+
// first (format, version, type, name, the head file, every path, every value, sizes, two names for one file),
|
|
10
|
+
// then written into a staging folder under the data home (DATA_HOME/data/skills/staging/<id>/), scanned
|
|
11
|
+
// (lib/skills/scan.js) and linted, and answered with what it is: its files, its digest, the scan's findings, the
|
|
12
|
+
// problems, what it would collide with. Installing it is a second request that names the staged digest: the
|
|
13
|
+
// files are read again from staging and must still be exactly those bytes, the scan must be of them and allow
|
|
14
|
+
// it (a review gate needs the person's confirmation of that digest), and the files are written into place all or
|
|
15
|
+
// nothing. Nothing of a staged import runs, loads or is sent anywhere.
|
|
16
|
+
|
|
17
|
+
import { lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync } from 'node:fs';
|
|
18
|
+
import { randomBytes } from 'node:crypto';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { PathConfineError, isInside, isPlainName, realPathOf } from '../path-confine.js';
|
|
21
|
+
import { canonicalInside, makeConfinedDir, readConfinedFile, writeConfinedFile } from '../confined-fs.js';
|
|
22
|
+
import { SYSTEM_NAMES, fileEntry, manifestDigest, readManifest, sha256 } from './digest.js';
|
|
23
|
+
import { findHiddenChars } from '../../public/shared/skills/ss-unicode.js';
|
|
24
|
+
import { isEditableText } from '../../public/shared/skills/ss-doc.js';
|
|
25
|
+
|
|
26
|
+
export const BUNDLE_FORMAT = 'synabun-skill-bundle';
|
|
27
|
+
export const BUNDLE_VERSION = 2;
|
|
28
|
+
export const BUNDLE_TYPES = Object.freeze(['skill', 'command', 'agent']);
|
|
29
|
+
export const BUNDLE_LIMITS = Object.freeze({
|
|
30
|
+
maxEntries: 2000,
|
|
31
|
+
maxDepth: 16,
|
|
32
|
+
maxPathChars: 512,
|
|
33
|
+
maxSegmentBytes: 255,
|
|
34
|
+
maxFileBytes: 8 * 1024 * 1024,
|
|
35
|
+
maxTotalBytes: 18 * 1024 * 1024, // decoded; with base64 and JSON around it, a bundle stays under the 25 MB request limit
|
|
36
|
+
maxHeadBytes: 2 * 1024 * 1024, // the head file is read whole by the library: bigger, and it would not be listed
|
|
37
|
+
maxJsonChars: 24 * 1024 * 1024, // an export longer than this could not be imported again
|
|
38
|
+
maxNameChars: 128,
|
|
39
|
+
stagingTtlMs: 24 * 60 * 60 * 1000,
|
|
40
|
+
});
|
|
41
|
+
export const ICON_EXTENSIONS = Object.freeze(['.png', '.svg', '.jpg', '.jpeg', '.webp']);
|
|
42
|
+
|
|
43
|
+
export class BundleError extends PathConfineError {
|
|
44
|
+
constructor(status, message, { code = 'invalid_bundle', problems = [] } = {}) {
|
|
45
|
+
super(status, message);
|
|
46
|
+
this.code = code;
|
|
47
|
+
this.problems = problems;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Why a path inside a bundle cannot be written, or null. Portable rules: what one system writes, all can. */
|
|
52
|
+
export function bundlePathProblem(rel, { maxDepth = BUNDLE_LIMITS.maxDepth, maxPathChars = BUNDLE_LIMITS.maxPathChars, maxSegmentBytes = BUNDLE_LIMITS.maxSegmentBytes } = {}) {
|
|
53
|
+
if (typeof rel !== 'string' || rel === '') return 'it is empty';
|
|
54
|
+
if (rel.length > maxPathChars) return `it is longer than ${maxPathChars} characters`;
|
|
55
|
+
if (rel.includes('\0')) return 'it holds a NUL character';
|
|
56
|
+
if (rel.includes('\\')) return 'it holds a backslash';
|
|
57
|
+
if (rel.startsWith('/') || /^[A-Za-z]:/.test(rel)) return 'it is absolute';
|
|
58
|
+
const segments = rel.split('/');
|
|
59
|
+
if (segments.length > maxDepth) return `it is more than ${maxDepth} folders deep`;
|
|
60
|
+
for (const seg of segments) {
|
|
61
|
+
if (seg === '') return 'it has an empty part (//)';
|
|
62
|
+
if (seg === '.' || seg === '..') return 'it climbs out of its folder (. or ..)';
|
|
63
|
+
if (Buffer.byteLength(seg, 'utf8') > maxSegmentBytes) return `a part is longer than ${maxSegmentBytes} bytes`;
|
|
64
|
+
if (/[\u0000-\u001F\u007F-\u009F]/.test(seg)) return 'it holds a control character';
|
|
65
|
+
if (findHiddenChars(seg, { identifier: true }).length) return 'it holds a character nobody can see';
|
|
66
|
+
if (/[<>:"|?*]/.test(seg)) return 'it holds a character Windows cannot store (< > : " | ? *)';
|
|
67
|
+
if (/[ .]$/.test(seg)) return 'a part ends with a dot or a space';
|
|
68
|
+
if (/^(?:con|prn|aux|nul|com[0-9]|lpt[0-9])(?:\..*)?$/i.test(seg)) return 'a part is a name Windows reserves';
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Why a name cannot be what an artifact is installed under, or null. */
|
|
74
|
+
export function bundleNameProblem(name) {
|
|
75
|
+
if (typeof name !== 'string' || !name) return 'it is empty';
|
|
76
|
+
if (!isPlainName(name)) return 'it is not one plain name';
|
|
77
|
+
if (name.length > BUNDLE_LIMITS.maxNameChars) return `it is longer than ${BUNDLE_LIMITS.maxNameChars} characters`;
|
|
78
|
+
if (name.startsWith('.')) return 'it starts with a dot';
|
|
79
|
+
return bundlePathProblem(name, { maxDepth: 1 });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// One character class, no nested repetition: a regular expression that stays linear on a 20 MB string.
|
|
83
|
+
const BASE64_CHARS = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
84
|
+
|
|
85
|
+
/** Canonical base64 only (what Buffer writes back is what was sent), or null. */
|
|
86
|
+
export function decodeBase64(value) {
|
|
87
|
+
if (typeof value !== 'string' || value.length % 4 !== 0 || !BASE64_CHARS.test(value)) return null;
|
|
88
|
+
const bytes = Buffer.from(value, 'base64');
|
|
89
|
+
return bytes.toString('base64') === value ? bytes : null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const fold = (p) => String(p).normalize('NFC').toLowerCase();
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Check a bundle and decode it. Nothing is written.
|
|
96
|
+
* @returns {{ type, name, version, files: { path, bytes, executable }[], dirs: string[], excluded: object[], head: string, digest: string, entries: object[] }}
|
|
97
|
+
* @throws {BundleError} 400 with every problem found (`problems: [{ path, message }]`)
|
|
98
|
+
*/
|
|
99
|
+
export function readBundle(bundle, limits = BUNDLE_LIMITS) {
|
|
100
|
+
const problems = [];
|
|
101
|
+
const fail = (message, code = 'invalid_bundle') => { throw new BundleError(400, message, { code, problems }); };
|
|
102
|
+
if (!bundle || typeof bundle !== 'object' || Array.isArray(bundle)) fail('That is not a SynaBun skill bundle.');
|
|
103
|
+
if (bundle.format !== BUNDLE_FORMAT) fail('That is not a SynaBun skill bundle.');
|
|
104
|
+
const version = bundle.version;
|
|
105
|
+
if (version !== 1 && version !== 2) fail(`Bundle version ${JSON.stringify(version ?? null)} is not one this SynaBun reads (1 or 2).`, 'unsupported_version');
|
|
106
|
+
const { type, name } = bundle;
|
|
107
|
+
if (!BUNDLE_TYPES.includes(type)) fail('The bundle\'s type must be skill, command or agent.');
|
|
108
|
+
const nameProblem = bundleNameProblem(name);
|
|
109
|
+
if (nameProblem) fail(`The bundle's name cannot be used: ${nameProblem}.`, 'invalid_name');
|
|
110
|
+
const files = bundle.files;
|
|
111
|
+
if (!files || typeof files !== 'object' || Array.isArray(files)) fail('The bundle holds no files.');
|
|
112
|
+
const keys = Object.keys(files);
|
|
113
|
+
if (!keys.length) fail('The bundle holds no files.');
|
|
114
|
+
if (keys.length > limits.maxEntries) fail(`The bundle holds ${keys.length} files; the limit is ${limits.maxEntries}.`, 'too_large');
|
|
115
|
+
|
|
116
|
+
const out = [];
|
|
117
|
+
const dropped = [];
|
|
118
|
+
let total = 0;
|
|
119
|
+
for (const rel of keys) {
|
|
120
|
+
// A file the system writes by itself (.DS_Store…) is not part of a skill: left out, and said so.
|
|
121
|
+
if (typeof rel === 'string' && SYSTEM_NAMES.has(rel.split('/').pop())) { dropped.push({ path: rel, reason: 'system file' }); continue; }
|
|
122
|
+
const pathProblem = bundlePathProblem(rel, limits);
|
|
123
|
+
if (pathProblem) { problems.push({ path: rel, message: `This path cannot be written: ${pathProblem}.` }); continue; }
|
|
124
|
+
if (type !== 'skill' && rel.includes('/')) { problems.push({ path: rel, message: 'A command or an agent bundle holds files of one folder only.' }); continue; }
|
|
125
|
+
const value = files[rel];
|
|
126
|
+
let bytes = null; let executable = false;
|
|
127
|
+
if (version === 1) {
|
|
128
|
+
if (typeof value === 'string') bytes = Buffer.from(value, 'utf-8');
|
|
129
|
+
else if (value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 1 && typeof value.base64 === 'string') {
|
|
130
|
+
bytes = decodeBase64(value.base64);
|
|
131
|
+
if (!bytes) { problems.push({ path: rel, message: 'Its base64 content is not valid.' }); continue; }
|
|
132
|
+
} else { problems.push({ path: rel, message: 'Its content is neither text nor { base64 }.' }); continue; }
|
|
133
|
+
} else {
|
|
134
|
+
if (!value || typeof value !== 'object' || Array.isArray(value) || typeof value.data !== 'string') { problems.push({ path: rel, message: 'Its entry is not { encoding, data, size, sha256 }.' }); continue; }
|
|
135
|
+
if (value.encoding === 'utf-8') bytes = Buffer.from(value.data, 'utf-8');
|
|
136
|
+
else if (value.encoding === 'base64') {
|
|
137
|
+
bytes = decodeBase64(value.data);
|
|
138
|
+
if (!bytes) { problems.push({ path: rel, message: 'Its base64 content is not valid.' }); continue; }
|
|
139
|
+
} else { problems.push({ path: rel, message: `Its encoding ${JSON.stringify(value.encoding ?? null)} is not utf-8 or base64.` }); continue; }
|
|
140
|
+
if (value.size !== undefined && value.size !== bytes.length) { problems.push({ path: rel, message: `It says ${value.size} bytes but holds ${bytes.length}.` }); continue; }
|
|
141
|
+
if (value.sha256 !== undefined && value.sha256 !== sha256(bytes)) { problems.push({ path: rel, message: 'Its content does not match its SHA-256: it was changed or damaged.' }); continue; }
|
|
142
|
+
if (value.executable !== undefined && typeof value.executable !== 'boolean') { problems.push({ path: rel, message: '"executable" must be true or false.' }); continue; }
|
|
143
|
+
executable = value.executable === true;
|
|
144
|
+
}
|
|
145
|
+
if (bytes.length > limits.maxFileBytes) { problems.push({ path: rel, message: `It is larger than ${Math.round(limits.maxFileBytes / (1024 * 1024))} MB.` }); continue; }
|
|
146
|
+
total += bytes.length;
|
|
147
|
+
out.push({ path: rel, bytes, executable });
|
|
148
|
+
}
|
|
149
|
+
if (total > limits.maxTotalBytes) problems.push({ path: null, message: `The bundle holds ${Math.round(total / (1024 * 1024))} MB; the limit is ${Math.round(limits.maxTotalBytes / (1024 * 1024))} MB.` });
|
|
150
|
+
|
|
151
|
+
// Folders: the ones it names (an empty folder is kept), and every folder on the way to a file.
|
|
152
|
+
const dirs = new Set();
|
|
153
|
+
if (version === 2 && bundle.dirs !== undefined) {
|
|
154
|
+
if (!Array.isArray(bundle.dirs)) problems.push({ path: null, message: '"dirs" must be a list of folders.' });
|
|
155
|
+
else for (const d of bundle.dirs) {
|
|
156
|
+
const p = bundlePathProblem(d, limits);
|
|
157
|
+
if (p) problems.push({ path: String(d), message: `This folder cannot be made: ${p}.` });
|
|
158
|
+
else if (type !== 'skill') problems.push({ path: d, message: 'A command or an agent bundle holds no folders.' });
|
|
159
|
+
else dirs.add(d);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
for (const f of out) {
|
|
163
|
+
const parts = f.path.split('/');
|
|
164
|
+
for (let i = 1; i < parts.length; i++) dirs.add(parts.slice(0, i).join('/'));
|
|
165
|
+
}
|
|
166
|
+
// Two names for one entry on a volume that ignores case and Unicode form, or a file where a folder must be.
|
|
167
|
+
const seen = new Map();
|
|
168
|
+
for (const p of [...out.map((f) => f.path), ...dirs]) {
|
|
169
|
+
const key = fold(p);
|
|
170
|
+
if (seen.has(key) && seen.get(key) !== p) problems.push({ path: p, message: `"${p}" and "${seen.get(key)}" name the same entry on macOS and Windows.` });
|
|
171
|
+
else seen.set(key, p);
|
|
172
|
+
}
|
|
173
|
+
const fileKeys = new Set(out.map((f) => fold(f.path)));
|
|
174
|
+
for (const d of dirs) if (fileKeys.has(fold(d))) problems.push({ path: d, message: `"${d}" is both a file and a folder.` });
|
|
175
|
+
|
|
176
|
+
// The head file: what makes it a skill, a command or an agent.
|
|
177
|
+
const headPath = type === 'skill' ? 'SKILL.md' : `${name}.md`;
|
|
178
|
+
const head = out.find((f) => f.path === headPath);
|
|
179
|
+
if (!head) { if (!problems.some((p) => p.path === headPath)) problems.push({ path: headPath, message: `The bundle has no ${headPath}: it would not be found as a ${type}.` }); }
|
|
180
|
+
else if (!isEditableText(head.bytes)) problems.push({ path: headPath, message: `${headPath} is not UTF-8 text.` });
|
|
181
|
+
else if (head.bytes.length > limits.maxHeadBytes) problems.push({ path: headPath, message: `${headPath} is larger than ${Math.round(limits.maxHeadBytes / (1024 * 1024))} MB: the library could not list it.` });
|
|
182
|
+
if (type !== 'skill') {
|
|
183
|
+
const icons = new Set(ICON_EXTENSIONS.map((ext) => `${name}.icon${ext}`));
|
|
184
|
+
for (const f of out) if (f.path !== headPath && !icons.has(f.path)) problems.push({ path: f.path, message: `A ${type} bundle holds ${headPath} and its icon only.` });
|
|
185
|
+
}
|
|
186
|
+
if (problems.length) {
|
|
187
|
+
throw new BundleError(400, problems.length === 1 ? `The bundle cannot be imported: ${problems[0].path ? `${problems[0].path}: ` : ''}${problems[0].message}` : `The bundle cannot be imported: ${problems.length} problems.`, { problems });
|
|
188
|
+
}
|
|
189
|
+
const entries = [...[...dirs].map((d) => ({ path: d, type: 'dir' })), ...out.map((f) => fileEntry(f.path, f.bytes, { executable: f.executable }))];
|
|
190
|
+
return {
|
|
191
|
+
type, name, version, files: out.sort((a, b) => (a.path < b.path ? -1 : 1)), dirs: [...dirs].sort(),
|
|
192
|
+
excluded: [...dropped, ...(Array.isArray(bundle.excluded) ? bundle.excluded.filter((e) => e && typeof e.path === 'string').slice(0, 200).map((e) => ({ path: String(e.path).slice(0, 512), reason: String(e.reason ?? '').slice(0, 64) })) : [])],
|
|
193
|
+
head: head.bytes.toString('utf-8'), headPath, digest: manifestDigest(entries), entries,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* A version 2 bundle of an artifact's files.
|
|
199
|
+
* @param {{ type, name, files: { path, bytes, executable }[], dirs?: string[], excluded?: { path, reason }[] }} o
|
|
200
|
+
* @returns {{ bundle: object, json: string, digest: string }}
|
|
201
|
+
* @throws {BundleError} 413 when the bundle could not be imported again
|
|
202
|
+
*/
|
|
203
|
+
export function buildBundle({ type, name, files, dirs = [], excluded = [] }, limits = BUNDLE_LIMITS) {
|
|
204
|
+
const entries = [];
|
|
205
|
+
// No prototype: a file named `__proto__` (or `constructor`) is a file of the bundle like any other.
|
|
206
|
+
const out = Object.create(null);
|
|
207
|
+
let total = 0;
|
|
208
|
+
for (const f of files.slice().sort((a, b) => (a.path < b.path ? -1 : 1))) {
|
|
209
|
+
total += f.bytes.length;
|
|
210
|
+
const text = isEditableText(f.bytes);
|
|
211
|
+
out[f.path] = {
|
|
212
|
+
encoding: text ? 'utf-8' : 'base64', data: text ? f.bytes.toString('utf-8') : f.bytes.toString('base64'),
|
|
213
|
+
size: f.bytes.length, sha256: sha256(f.bytes), ...(f.executable ? { executable: true } : {}),
|
|
214
|
+
};
|
|
215
|
+
entries.push(fileEntry(f.path, f.bytes, { executable: f.executable }));
|
|
216
|
+
}
|
|
217
|
+
const allDirs = new Set(dirs);
|
|
218
|
+
for (const f of files) { const parts = f.path.split('/'); for (let i = 1; i < parts.length; i++) allDirs.add(parts.slice(0, i).join('/')); }
|
|
219
|
+
for (const d of allDirs) entries.push({ path: d, type: 'dir' });
|
|
220
|
+
const digest = manifestDigest(entries);
|
|
221
|
+
const bundle = { format: BUNDLE_FORMAT, version: BUNDLE_VERSION, type, name, digest, files: out, dirs: [...allDirs].sort(), excluded };
|
|
222
|
+
if (total > limits.maxTotalBytes || files.length > limits.maxEntries) throw new BundleError(413, 'This is too large to export as one bundle: it could not be imported again.', { code: 'too_large' });
|
|
223
|
+
const json = JSON.stringify(bundle, null, 2);
|
|
224
|
+
if (json.length > limits.maxJsonChars) throw new BundleError(413, 'This is too large to export as one bundle: it could not be imported again.', { code: 'too_large' });
|
|
225
|
+
return { bundle, json, digest };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* The files of a skill folder for an export: every regular file and folder, each by its own name. A link is
|
|
230
|
+
* never followed, wherever it leads (`notes.md -> .env` would export the secret under another name, `vendor ->
|
|
231
|
+
* node_modules` a dependency tree): it is left out and named, like hidden entries, node_modules, system files
|
|
232
|
+
* and special files. The limits of an import hold while the folder is read, from each entry's size before its
|
|
233
|
+
* bytes are: a folder too large to be imported again is refused (413) without being read into memory.
|
|
234
|
+
*/
|
|
235
|
+
export function collectFolder(realBase, limits = BUNDLE_LIMITS) {
|
|
236
|
+
const files = []; const dirs = []; const excluded = [];
|
|
237
|
+
let total = 0; let count = 0;
|
|
238
|
+
const tooLarge = (message) => new BundleError(413, message, { code: 'too_large' });
|
|
239
|
+
const megabytes = (n) => `${Math.round(n / (1024 * 1024))} MB`;
|
|
240
|
+
const walk = (realDir, rel, depth, names) => {
|
|
241
|
+
for (const name of names.sort()) {
|
|
242
|
+
const path = rel ? `${rel}/${name}` : name;
|
|
243
|
+
const left = name.startsWith('.') ? 'hidden' : name === 'node_modules' ? 'node_modules' : SYSTEM_NAMES.has(name) ? 'system file' : null;
|
|
244
|
+
if (left) { excluded.push({ path, reason: left }); continue; }
|
|
245
|
+
const full = join(realDir, name);
|
|
246
|
+
let st;
|
|
247
|
+
try { st = lstatSync(full); } catch { excluded.push({ path, reason: 'unreadable' }); continue; }
|
|
248
|
+
if (st.isSymbolicLink()) { excluded.push({ path, reason: 'link' }); continue; }
|
|
249
|
+
if (!st.isDirectory() && !st.isFile()) { excluded.push({ path, reason: 'not a regular file' }); continue; }
|
|
250
|
+
if (++count > limits.maxEntries) throw tooLarge(`This skill has more than ${limits.maxEntries} files and folders: it could not be imported again as one bundle.`);
|
|
251
|
+
if (st.isDirectory()) {
|
|
252
|
+
if (depth + 1 >= limits.maxDepth) throw tooLarge(`"${path}" is more than ${limits.maxDepth} folders deep: it could not be imported again.`);
|
|
253
|
+
let children;
|
|
254
|
+
try { children = readdirSync(full); } catch { excluded.push({ path, reason: 'unreadable' }); continue; }
|
|
255
|
+
dirs.push(path);
|
|
256
|
+
walk(full, path, depth + 1, children);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (st.size > limits.maxFileBytes) throw tooLarge(`"${path}" is larger than ${megabytes(limits.maxFileBytes)}: it could not be imported again.`);
|
|
260
|
+
if (total + st.size > limits.maxTotalBytes) throw tooLarge(`This skill holds more than ${megabytes(limits.maxTotalBytes)}: it could not be imported again as one bundle.`);
|
|
261
|
+
// Opened without following a link (one put there since the look above is refused), and bounded: a file
|
|
262
|
+
// that grew since is not read past the limit.
|
|
263
|
+
const bytes = readConfinedFile(realBase, full, { maxBytes: limits.maxFileBytes });
|
|
264
|
+
total += bytes.length;
|
|
265
|
+
if (total > limits.maxTotalBytes) throw tooLarge(`This skill holds more than ${megabytes(limits.maxTotalBytes)}: it could not be imported again as one bundle.`);
|
|
266
|
+
files.push({ path, bytes, executable: (st.mode & 0o111) !== 0 });
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
let top;
|
|
270
|
+
try { top = readdirSync(realBase); } catch (err) { throw new BundleError(500, `The skill's folder could not be read (${err.code || err.message}).`, { code: 'unreadable' }); }
|
|
271
|
+
walk(realBase, '', 0, top);
|
|
272
|
+
return { files, dirs, excluded };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ── Staging ──
|
|
276
|
+
|
|
277
|
+
const STAGING_ID_RE = /^[0-9a-f]{24}$/;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The staging area of imports.
|
|
281
|
+
* @param {object} o
|
|
282
|
+
* @param {string} o.dir DATA_HOME/data/skills/staging
|
|
283
|
+
* @param {() => string[]} [o.liveRoots] every folder a runtime reads skills from: staging is refused inside one
|
|
284
|
+
*/
|
|
285
|
+
export function createImportStaging({ dir, liveRoots = () => [], now = () => Date.now(), random = () => randomBytes(12).toString('hex') }) {
|
|
286
|
+
function ensureOutsideLiveRoots() {
|
|
287
|
+
// Where it would be, links resolved, is checked before anything is made: not even an empty folder is put
|
|
288
|
+
// where a runtime reads skills from.
|
|
289
|
+
let planned;
|
|
290
|
+
try { planned = realPathOf(dir); } catch (err) { throw new BundleError(500, `The staging folder cannot be used: ${err.message}`, { code: 'staging_unavailable' }); }
|
|
291
|
+
const unsafe = (place) => {
|
|
292
|
+
for (const root of liveRoots()) {
|
|
293
|
+
let rootReal;
|
|
294
|
+
try { rootReal = realPathOf(root); } catch { continue; }
|
|
295
|
+
if (isInside(rootReal, place, { allowRoot: true }) || isInside(place, rootReal, { allowRoot: true })) return rootReal;
|
|
296
|
+
}
|
|
297
|
+
return null;
|
|
298
|
+
};
|
|
299
|
+
const refuse = (place, root) => new BundleError(500, `The staging folder (${place}) is inside a folder a runtime reads skills from (${root}): imports are refused until the data home moves.`, { code: 'staging_unsafe' });
|
|
300
|
+
const before = unsafe(planned);
|
|
301
|
+
if (before) throw refuse(planned, before);
|
|
302
|
+
let real;
|
|
303
|
+
try { mkdirSync(dir, { recursive: true, mode: 0o700 }); real = realpathSync(dir); } catch (err) { throw new BundleError(500, `The staging folder cannot be made: ${err.message}`, { code: 'staging_unavailable' }); }
|
|
304
|
+
const after = unsafe(real);
|
|
305
|
+
if (after) throw refuse(real, after);
|
|
306
|
+
return real;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function prune(real) {
|
|
310
|
+
let names = [];
|
|
311
|
+
try { names = readdirSync(real); } catch { return; }
|
|
312
|
+
for (const n of names) {
|
|
313
|
+
if (!STAGING_ID_RE.test(n)) continue;
|
|
314
|
+
try {
|
|
315
|
+
const meta = JSON.parse(readFileSync(join(real, n, 'staging.json'), 'utf8'));
|
|
316
|
+
if (now() - Date.parse(meta.stagedAt) > BUNDLE_LIMITS.stagingTtlMs) rmSync(join(real, n), { recursive: true, force: true });
|
|
317
|
+
} catch {
|
|
318
|
+
try { if (now() - lstatSync(join(real, n)).mtimeMs > BUNDLE_LIMITS.stagingTtlMs) rmSync(join(real, n), { recursive: true, force: true }); } catch { /* next time */ }
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Put a checked bundle into staging. @param {object} read readBundle()'s result @param {object} meta what the
|
|
325
|
+
* install will need (scope, destination, scan, lint…), stored beside the files
|
|
326
|
+
* @returns {string} the staging id
|
|
327
|
+
*/
|
|
328
|
+
function stage(read, meta) {
|
|
329
|
+
const real = ensureOutsideLiveRoots();
|
|
330
|
+
prune(real);
|
|
331
|
+
const id = random();
|
|
332
|
+
if (!STAGING_ID_RE.test(id)) throw new BundleError(500, 'Bad staging id.');
|
|
333
|
+
const home = join(real, id);
|
|
334
|
+
mkdirSync(home, { mode: 0o700 });
|
|
335
|
+
const filesDir = join(home, 'files');
|
|
336
|
+
mkdirSync(filesDir, { mode: 0o700 });
|
|
337
|
+
try {
|
|
338
|
+
for (const d of read.dirs) makeConfinedDir(filesDir, join(filesDir, d));
|
|
339
|
+
// Staged files are never executable: what they would be is in the manifest, and is applied on install.
|
|
340
|
+
for (const f of read.files) writeConfinedFile(filesDir, join(filesDir, f.path), f.bytes, { exclusive: true, mode: 0o600 });
|
|
341
|
+
const record = {
|
|
342
|
+
schemaVersion: 1, stagingId: id, stagedAt: new Date(now()).toISOString(), type: read.type, name: read.name, version: read.version,
|
|
343
|
+
digest: read.digest, headPath: read.headPath,
|
|
344
|
+
manifest: read.entries.map((e) => (e.type === 'dir' ? { path: e.path, type: 'dir' } : { path: e.path, type: 'file', size: e.size, sha256: e.sha256, executable: !!e.executable })),
|
|
345
|
+
excluded: read.excluded, ...meta,
|
|
346
|
+
};
|
|
347
|
+
writeConfinedFile(home, join(home, 'staging.json'), `${JSON.stringify(record, null, 2)}\n`, { exclusive: true, mode: 0o600 });
|
|
348
|
+
return id;
|
|
349
|
+
} catch (err) {
|
|
350
|
+
rmSync(home, { recursive: true, force: true });
|
|
351
|
+
throw err;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* A staged import, its files read again from staging and checked against its manifest.
|
|
357
|
+
* @returns {{ record: object, files: { path, bytes, executable }[], dirs: string[], digest: string }}
|
|
358
|
+
*/
|
|
359
|
+
function load(id) {
|
|
360
|
+
if (typeof id !== 'string' || !STAGING_ID_RE.test(id)) throw new BundleError(400, 'Not a staging id.', { code: 'invalid_staging_id' });
|
|
361
|
+
const real = ensureOutsideLiveRoots();
|
|
362
|
+
const home = join(real, id);
|
|
363
|
+
let record;
|
|
364
|
+
try { record = JSON.parse(readConfinedFile(home, join(home, 'staging.json'), { maxBytes: 4 * 1024 * 1024, encoding: 'utf-8' })); } catch { throw new BundleError(404, 'That import is no longer staged: import it again.', { code: 'staging_gone' }); }
|
|
365
|
+
const filesDir = join(home, 'files');
|
|
366
|
+
const files = []; const dirs = [];
|
|
367
|
+
for (const e of record.manifest || []) {
|
|
368
|
+
if (e.type === 'dir') { dirs.push(e.path); continue; }
|
|
369
|
+
const bytes = readConfinedFile(filesDir, join(filesDir, e.path), { maxBytes: BUNDLE_LIMITS.maxFileBytes });
|
|
370
|
+
files.push({ path: e.path, bytes, executable: !!e.executable });
|
|
371
|
+
}
|
|
372
|
+
const entries = [...dirs.map((d) => ({ path: d, type: 'dir' })), ...files.map((f) => fileEntry(f.path, f.bytes, { executable: f.executable }))];
|
|
373
|
+
const digest = manifestDigest(entries);
|
|
374
|
+
// What is in staging now must be what was staged (and nothing more).
|
|
375
|
+
const onDisk = readManifest(filesDir);
|
|
376
|
+
const stagedNow = onDisk.entries.map((e) => (e.type === 'file' ? { ...e, executable: !!(record.manifest.find((m) => m.path === e.path) || {}).executable } : e));
|
|
377
|
+
if (digest !== record.digest || manifestDigest(stagedNow) !== record.digest) {
|
|
378
|
+
throw new BundleError(409, 'The staged files changed since they were checked: import the bundle again.', { code: 'staging_changed' });
|
|
379
|
+
}
|
|
380
|
+
return { record, files, dirs, digest };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function discard(id) {
|
|
384
|
+
if (typeof id !== 'string' || !STAGING_ID_RE.test(id)) throw new BundleError(400, 'Not a staging id.', { code: 'invalid_staging_id' });
|
|
385
|
+
const real = ensureOutsideLiveRoots();
|
|
386
|
+
const home = join(real, id);
|
|
387
|
+
try { lstatSync(home); } catch { return false; }
|
|
388
|
+
rmSync(home, { recursive: true, force: true });
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return { stage, load, discard, ensureOutsideLiveRoots };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Write a staged skill folder into place: a new folder, all of it or none of it.
|
|
397
|
+
* @param {{ dir: string, anchor?: string }} root the skills folder it goes into
|
|
398
|
+
* @param {string} destination root.dir/<name>
|
|
399
|
+
* @returns {string} the folder's canonical path
|
|
400
|
+
*/
|
|
401
|
+
export function writeSkillFolder(root, destination, { files, dirs }) {
|
|
402
|
+
const rootReal = realPathOf(root.dir);
|
|
403
|
+
mkdirSync(rootReal, { recursive: true });
|
|
404
|
+
const real = canonicalInside(rootReal, destination);
|
|
405
|
+
try { mkdirSync(real); } catch (err) {
|
|
406
|
+
if (err?.code === 'EEXIST') throw new BundleError(409, `"${destination}" already exists. Nothing was written.`, { code: 'exists' });
|
|
407
|
+
throw err;
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
if (realpathSync(real) !== real) throw new PathConfineError(409, 'That path changed while it was being used. Nothing was done; try again.');
|
|
411
|
+
for (const d of dirs) makeConfinedDir(real, join(real, d));
|
|
412
|
+
for (const f of files) writeConfinedFile(real, join(real, f.path), f.bytes, { exclusive: true, mode: f.executable ? 0o755 : 0o644 });
|
|
413
|
+
} catch (err) {
|
|
414
|
+
rmSync(real, { recursive: true, force: true });
|
|
415
|
+
throw err;
|
|
416
|
+
}
|
|
417
|
+
return real;
|
|
418
|
+
}
|