synabun 2.0.10 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +2 -2
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +17 -8
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +1 -1
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +228 -0
- package/lib/virustotal.mjs +192 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +16 -10
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +20 -62
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -10
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +22 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +639 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/neural-interface.ts +79 -20
- package/mcp-server/src/services/server-instructions.ts +27 -63
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +22 -14
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/skill-tools.ts +589 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3463 -200
- package/neural-interface/i18n/pt-BR.json +3411 -151
- package/neural-interface/lib/assistant-api.js +127 -28
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- package/neural-interface/lib/assistant-catalog.js +6 -7
- package/neural-interface/lib/assistant-dispatch.js +871 -156
- package/neural-interface/lib/assistant-envelope.js +3 -1
- package/neural-interface/lib/assistant-persona.js +80 -11
- package/neural-interface/lib/assistant-plan-permissions.js +10 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +13 -8
- package/neural-interface/lib/assistant-runtime.js +56 -18
- package/neural-interface/lib/assistant-task-prompt.js +78 -14
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/backup-service.js +620 -3
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +83 -0
- package/neural-interface/lib/browser-network-guard.js +284 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +186 -31
- package/neural-interface/lib/claude-agent-bridge.js +4 -2
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install.js +18 -138
- package/neural-interface/lib/cli-resolver.js +4 -1
- package/neural-interface/lib/cli-update-planner.js +32 -31
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-worker-app-server.js +172 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/exec-loop-command.js +4 -8
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +0 -29
- package/neural-interface/lib/mcp-external-servers.js +323 -0
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/morelogin.js +30 -0
- package/neural-interface/lib/native-loop-providers.js +547 -47
- package/neural-interface/lib/native-loop-runtime.js +268 -41
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +44 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/peer-identity.js +763 -0
- package/neural-interface/lib/request-gate.js +17 -2
- package/neural-interface/lib/rulesets/api.js +1 -1
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +92 -27
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +17 -30
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +294 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +267 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +564 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +214 -0
- package/neural-interface/lib/skills/eval-confinement.js +397 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +119 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +200 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +262 -0
- package/neural-interface/lib/skills/runtime-checks.js +355 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +522 -0
- package/neural-interface/lib/skills/telemetry.js +113 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/worker-confinement.js +1192 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +229 -0
- package/neural-interface/lib/worker-sandbox.js +299 -0
- package/neural-interface/package-lock.json +18 -12
- package/neural-interface/package.json +2 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +2 -2
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +35 -19
- package/neural-interface/public/shared/api.js +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +33 -2
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +49 -35
- package/neural-interface/public/shared/assistant/asst-control.js +157 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +106 -11
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +401 -77
- package/neural-interface/public/shared/assistant/asst-route.js +83 -12
- package/neural-interface/public/shared/assistant/asst-scenes.js +2 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
- package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
- package/neural-interface/public/shared/assistant/asst-state.js +11 -15
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +59 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +156 -16
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
- package/neural-interface/public/shared/cdx/cdx-panel.js +45 -149
- package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
- package/neural-interface/public/shared/cdx/cdx-render.js +47 -29
- package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +11 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +52 -39
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-view.js +4 -8
- package/neural-interface/public/shared/cli-status.js +2 -2
- package/neural-interface/public/shared/constants.js +2 -2
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +366 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-update-view.js +20 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/html-shell.js +9 -11
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +47 -252
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +6 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +0 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +14 -47
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +219 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +141 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1525 -1779
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-automation-studio.js +91 -128
- package/neural-interface/public/shared/ui-claude-panel.js +77 -5
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-keybinds.js +26 -1
- package/neural-interface/public/shared/ui-menubar.js +8 -18
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +7 -1
- package/neural-interface/public/shared/ui-navbar.js +4 -24
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-schedules-studio.js +507 -423
- package/neural-interface/public/shared/ui-sessions.js +5 -3
- package/neural-interface/public/shared/ui-settings.js +594 -462
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +1 -1
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +124 -180
- package/neural-interface/public/shared/ui-tool-updates.js +3 -1
- package/neural-interface/public/shared/ui-tooltip.js +10 -5
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +311 -58
- package/neural-interface/public/shared/ui-worker-end.js +4 -0
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +3934 -2454
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +18 -12
- package/package.json +16 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +4 -4
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
|
@@ -200,10 +200,15 @@ export async function openZipArchive(path) {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
/** SHA-256 of one entry's bytes; `onBytes(n)` hears how many went by (a progress bar). */
|
|
204
|
+
export async function hashZipEntry(zip, entry, { onBytes = null } = {}) {
|
|
204
205
|
const digest = createHash('sha256');
|
|
205
206
|
await zip.pipeEntry(entry, new Writable({
|
|
206
|
-
write(chunk, _encoding, callback) {
|
|
207
|
+
write(chunk, _encoding, callback) {
|
|
208
|
+
digest.update(chunk);
|
|
209
|
+
if (onBytes) { try { onBytes(chunk.length); } catch { /* reporting never stops a check */ } }
|
|
210
|
+
callback();
|
|
211
|
+
},
|
|
207
212
|
}));
|
|
208
213
|
return digest.digest('hex');
|
|
209
214
|
}
|
|
@@ -249,13 +254,13 @@ export function backupEntryName(prefix, archivePath) {
|
|
|
249
254
|
return prefix ? `${prefix}/${archivePath}` : archivePath;
|
|
250
255
|
}
|
|
251
256
|
|
|
252
|
-
/** Stream every manifest-listed entry through sha256 and compare. */
|
|
253
|
-
export async function verifyBackupChecksums(zip, { prefix, manifest, label = 'Backup verification failed' }) {
|
|
257
|
+
/** Stream every manifest-listed entry through sha256 and compare. `onBytes`: as for hashZipEntry. */
|
|
258
|
+
export async function verifyBackupChecksums(zip, { prefix, manifest, label = 'Backup verification failed', onBytes = null }) {
|
|
254
259
|
for (const [archivePath, expected] of Object.entries(manifest.checksums || {})) {
|
|
255
260
|
const entry = zip.getEntry(backupEntryName(prefix, archivePath));
|
|
256
261
|
if (!entry) throw new Error(`${label}: ${archivePath} is missing`);
|
|
257
262
|
let actual;
|
|
258
|
-
try { actual = `sha256:${await hashZipEntry(zip, entry)}`; }
|
|
263
|
+
try { actual = `sha256:${await hashZipEntry(zip, entry, { onBytes })}`; }
|
|
259
264
|
catch (error) { throw new Error(`${label}: ${archivePath} is unreadable (${error.message})`); }
|
|
260
265
|
if (actual !== expected) throw new Error(`${label}: checksum mismatch for ${archivePath}`);
|
|
261
266
|
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { open, readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { crc32, deflateRawSync } from 'node:zlib';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A ZIP writer for snapshots that have to be quick at any size: the pre-update
|
|
7
|
+
* snapshot is written while SynaBun restarts into a new version, and its
|
|
8
|
+
* database can be several gigabytes.
|
|
9
|
+
*
|
|
10
|
+
* Every entry is written in one pass. Its CRC-32 (zlib's native crc32) and its
|
|
11
|
+
* SHA-256 come from the same bytes as they go to disk, so nothing is read again
|
|
12
|
+
* to checksum it. An entry marked `store` (a SQLite database, a file that is
|
|
13
|
+
* already compressed) goes in as it is; anything else is deflated in memory,
|
|
14
|
+
* which is only ever asked of small files. ZIP64 records are written whenever
|
|
15
|
+
* a size, an offset or the entry count needs them, in exactly the shape
|
|
16
|
+
* backup-zip-reader.js reads (and Info-ZIP's unzip -t accepts).
|
|
17
|
+
*
|
|
18
|
+
* The CRC of a streamed entry is unknown until its last byte, so its local
|
|
19
|
+
* header is written with a zero CRC and patched in place afterwards: no data
|
|
20
|
+
* descriptors, and the sizes in every header are the real ones.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const SIG_LOCAL = 0x04034b50;
|
|
24
|
+
const SIG_CENTRAL = 0x02014b50;
|
|
25
|
+
const SIG_EOCD = 0x06054b50;
|
|
26
|
+
const SIG_ZIP64_EOCD = 0x06064b50;
|
|
27
|
+
const SIG_ZIP64_LOCATOR = 0x07064b50;
|
|
28
|
+
const UTF8_NAMES = 0x0800;
|
|
29
|
+
const MAX32 = 0xffffffff;
|
|
30
|
+
const MAX16 = 0xffff;
|
|
31
|
+
const CHUNK = 4 * 1024 * 1024;
|
|
32
|
+
// Files above this are never deflated in memory (the writer is for snapshots, where those are databases).
|
|
33
|
+
export const MAX_DEFLATE_BYTES = 64 * 1024 * 1024;
|
|
34
|
+
|
|
35
|
+
/** MS-DOS date and time (local time, two-second steps), as ZIP headers carry them. */
|
|
36
|
+
function dosDateTime(date) {
|
|
37
|
+
const year = Math.min(2107, Math.max(1980, date.getFullYear()));
|
|
38
|
+
return {
|
|
39
|
+
time: (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2),
|
|
40
|
+
date: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function zip64Extra(fields) {
|
|
45
|
+
if (!fields.length) return Buffer.alloc(0);
|
|
46
|
+
const extra = Buffer.alloc(4 + fields.length * 8);
|
|
47
|
+
extra.writeUInt16LE(0x0001, 0);
|
|
48
|
+
extra.writeUInt16LE(fields.length * 8, 2);
|
|
49
|
+
fields.forEach((value, index) => extra.writeBigUInt64LE(BigInt(value), 4 + index * 8));
|
|
50
|
+
return extra;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Write `entries` into a new file at `path` (it must not exist).
|
|
55
|
+
* entries [{ name, diskPath, store }] or [{ name, data: Buffer|string, store }]; `data` may be a
|
|
56
|
+
* function, called when its turn comes with what was written so far ([{ name, size, crc32,
|
|
57
|
+
* sha256 }]): a manifest that lists the checksums of the entries before it
|
|
58
|
+
* onProgress({ bytes, totalBytes }) as data goes in, at most every 64 MB and at the end
|
|
59
|
+
* forceZip64 write ZIP64 records even when nothing needs them (tests)
|
|
60
|
+
* Resolves { bytes, entries: [{ name, size, crc32, sha256 }] } (sha256 in hex).
|
|
61
|
+
*/
|
|
62
|
+
export async function writeZipArchive(path, entries, { onProgress = null, now = () => new Date(), forceZip64 = false } = {}) {
|
|
63
|
+
const report = typeof onProgress === 'function' ? onProgress : () => {};
|
|
64
|
+
const stamp = dosDateTime(now());
|
|
65
|
+
// Sizes first, so the progress has a total and a stored entry's headers carry its real size.
|
|
66
|
+
const planned = [];
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
const name = String(entry?.name || '');
|
|
69
|
+
if (!name || name.startsWith('/') || name.includes('\\') || name.split('/').includes('..')) throw new Error(`Invalid archive entry name: ${name}`);
|
|
70
|
+
if (typeof entry.data === 'function') {
|
|
71
|
+
planned.push({ name, make: entry.data, size: 0, store: entry.store === true });
|
|
72
|
+
} else if (entry.data !== undefined) {
|
|
73
|
+
const data = Buffer.isBuffer(entry.data) ? entry.data : Buffer.from(String(entry.data), 'utf8');
|
|
74
|
+
planned.push({ name, data, size: data.length, store: entry.store === true });
|
|
75
|
+
} else {
|
|
76
|
+
const size = (await stat(entry.diskPath)).size;
|
|
77
|
+
const store = entry.store === true || size > MAX_DEFLATE_BYTES;
|
|
78
|
+
planned.push({ name, diskPath: entry.diskPath, size, store });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let totalBytes = planned.reduce((sum, item) => sum + item.size, 0);
|
|
82
|
+
let doneBytes = 0;
|
|
83
|
+
let reportedAt = 0;
|
|
84
|
+
const progress = (force = false) => {
|
|
85
|
+
if (force || doneBytes - reportedAt >= 64 * 1024 * 1024) {
|
|
86
|
+
reportedAt = doneBytes;
|
|
87
|
+
try { report({ bytes: doneBytes, totalBytes }); } catch { /* reporting never stops a snapshot */ }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const handle = await open(path, 'wx');
|
|
92
|
+
const written = [];
|
|
93
|
+
let offset = 0;
|
|
94
|
+
try {
|
|
95
|
+
const write = async (buffer) => {
|
|
96
|
+
let at = 0;
|
|
97
|
+
while (at < buffer.length) {
|
|
98
|
+
const { bytesWritten } = await handle.write(buffer, at, buffer.length - at, offset + at);
|
|
99
|
+
at += bytesWritten;
|
|
100
|
+
}
|
|
101
|
+
offset += buffer.length;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
for (const item of planned) {
|
|
105
|
+
if (item.make) {
|
|
106
|
+
const made = item.make(written.map(entry => ({ name: entry.name, size: entry.size, crc32: entry.crc, sha256: entry.sha256 })));
|
|
107
|
+
item.data = Buffer.isBuffer(made) ? made : Buffer.from(String(made), 'utf8');
|
|
108
|
+
item.size = item.data.length;
|
|
109
|
+
totalBytes += item.size;
|
|
110
|
+
}
|
|
111
|
+
const nameBytes = Buffer.from(item.name, 'utf8');
|
|
112
|
+
const localOffset = offset;
|
|
113
|
+
let crc = 0;
|
|
114
|
+
const digest = createHash('sha256');
|
|
115
|
+
let payload = null;
|
|
116
|
+
if (item.data !== undefined) {
|
|
117
|
+
crc = crc32(item.data, 0);
|
|
118
|
+
digest.update(item.data);
|
|
119
|
+
payload = item.store ? item.data : deflateRawSync(item.data, { level: 6 });
|
|
120
|
+
} else if (!item.store) {
|
|
121
|
+
const data = await readFile(item.diskPath);
|
|
122
|
+
if (data.length !== item.size) throw new Error(`${item.name} changed while it was archived`);
|
|
123
|
+
crc = crc32(data, 0);
|
|
124
|
+
digest.update(data);
|
|
125
|
+
payload = deflateRawSync(data, { level: 6 });
|
|
126
|
+
}
|
|
127
|
+
const method = item.store ? 0 : 8;
|
|
128
|
+
const compressedSize = payload ? payload.length : item.size;
|
|
129
|
+
const zip64 = forceZip64 || item.size >= MAX32 || compressedSize >= MAX32 || localOffset >= MAX32;
|
|
130
|
+
const localExtra = zip64 ? zip64Extra([item.size, compressedSize]) : Buffer.alloc(0);
|
|
131
|
+
const header = Buffer.alloc(30);
|
|
132
|
+
header.writeUInt32LE(SIG_LOCAL, 0);
|
|
133
|
+
header.writeUInt16LE(zip64 ? 45 : method === 8 ? 20 : 10, 4);
|
|
134
|
+
header.writeUInt16LE(UTF8_NAMES, 6);
|
|
135
|
+
header.writeUInt16LE(method, 8);
|
|
136
|
+
header.writeUInt16LE(stamp.time, 10);
|
|
137
|
+
header.writeUInt16LE(stamp.date, 12);
|
|
138
|
+
header.writeUInt32LE(crc >>> 0, 14);
|
|
139
|
+
header.writeUInt32LE(zip64 ? MAX32 : compressedSize, 18);
|
|
140
|
+
header.writeUInt32LE(zip64 ? MAX32 : item.size, 22);
|
|
141
|
+
header.writeUInt16LE(nameBytes.length, 26);
|
|
142
|
+
header.writeUInt16LE(localExtra.length, 28);
|
|
143
|
+
await write(Buffer.concat([header, nameBytes, localExtra]));
|
|
144
|
+
|
|
145
|
+
if (payload) {
|
|
146
|
+
await write(payload);
|
|
147
|
+
doneBytes += item.size;
|
|
148
|
+
progress();
|
|
149
|
+
} else {
|
|
150
|
+
// Streamed: CRC and SHA-256 of the very bytes that go to disk, exactly `size` of them.
|
|
151
|
+
// Two buffers: the next chunk is being read while this one is hashed and written.
|
|
152
|
+
const source = await open(item.diskPath, 'r');
|
|
153
|
+
try {
|
|
154
|
+
const size = Math.min(CHUNK, Math.max(1, item.size));
|
|
155
|
+
const buffers = [Buffer.allocUnsafe(size), Buffer.allocUnsafe(size)];
|
|
156
|
+
let left = item.size;
|
|
157
|
+
let position = 0;
|
|
158
|
+
let turn = 0;
|
|
159
|
+
let reading = left > 0 ? source.read(buffers[0], 0, Math.min(size, left), 0) : null;
|
|
160
|
+
while (left > 0) {
|
|
161
|
+
const { bytesRead } = await reading;
|
|
162
|
+
if (bytesRead === 0) throw new Error(`${item.name} ended before its ${item.size} bytes (it changed while it was archived)`);
|
|
163
|
+
const chunk = buffers[turn].subarray(0, bytesRead);
|
|
164
|
+
left -= bytesRead;
|
|
165
|
+
position += bytesRead;
|
|
166
|
+
reading = left > 0 ? source.read(buffers[1 - turn], 0, Math.min(size, left), position) : null;
|
|
167
|
+
crc = crc32(chunk, crc);
|
|
168
|
+
digest.update(chunk);
|
|
169
|
+
await write(chunk);
|
|
170
|
+
turn = 1 - turn;
|
|
171
|
+
doneBytes += bytesRead;
|
|
172
|
+
progress();
|
|
173
|
+
}
|
|
174
|
+
} finally {
|
|
175
|
+
await source.close();
|
|
176
|
+
}
|
|
177
|
+
const crcBuffer = Buffer.alloc(4);
|
|
178
|
+
crcBuffer.writeUInt32LE(crc >>> 0, 0);
|
|
179
|
+
await handle.write(crcBuffer, 0, 4, localOffset + 14);
|
|
180
|
+
}
|
|
181
|
+
written.push({ name: item.name, nameBytes, method, crc: crc >>> 0, size: item.size, compressedSize, localOffset, zip64, sha256: digest.digest('hex') });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// The central directory: one record per entry, then the end records.
|
|
185
|
+
const directoryOffset = offset;
|
|
186
|
+
const records = [];
|
|
187
|
+
for (const entry of written) {
|
|
188
|
+
const overflow = [];
|
|
189
|
+
if (forceZip64 || entry.size >= MAX32) overflow.push(entry.size);
|
|
190
|
+
if (forceZip64 || entry.compressedSize >= MAX32) overflow.push(entry.compressedSize);
|
|
191
|
+
if (forceZip64 || entry.localOffset >= MAX32) overflow.push(entry.localOffset);
|
|
192
|
+
const extra = zip64Extra(overflow);
|
|
193
|
+
const record = Buffer.alloc(46);
|
|
194
|
+
record.writeUInt32LE(SIG_CENTRAL, 0);
|
|
195
|
+
record.writeUInt16LE((3 << 8) | 45, 4);
|
|
196
|
+
record.writeUInt16LE(entry.zip64 ? 45 : entry.method === 8 ? 20 : 10, 6);
|
|
197
|
+
record.writeUInt16LE(UTF8_NAMES, 8);
|
|
198
|
+
record.writeUInt16LE(entry.method, 10);
|
|
199
|
+
record.writeUInt16LE(stamp.time, 12);
|
|
200
|
+
record.writeUInt16LE(stamp.date, 14);
|
|
201
|
+
record.writeUInt32LE(entry.crc, 16);
|
|
202
|
+
record.writeUInt32LE(forceZip64 || entry.compressedSize >= MAX32 ? MAX32 : entry.compressedSize, 20);
|
|
203
|
+
record.writeUInt32LE(forceZip64 || entry.size >= MAX32 ? MAX32 : entry.size, 24);
|
|
204
|
+
record.writeUInt16LE(entry.nameBytes.length, 28);
|
|
205
|
+
record.writeUInt16LE(extra.length, 30);
|
|
206
|
+
record.writeUInt16LE(0, 32);
|
|
207
|
+
record.writeUInt16LE(0, 34);
|
|
208
|
+
record.writeUInt16LE(0, 36);
|
|
209
|
+
// A regular file, rw-r--r-- (unzip and ditto give it these permissions).
|
|
210
|
+
record.writeUInt32LE((0o100644 << 16) >>> 0, 38);
|
|
211
|
+
record.writeUInt32LE(forceZip64 || entry.localOffset >= MAX32 ? MAX32 : entry.localOffset, 42);
|
|
212
|
+
records.push(record, entry.nameBytes, extra);
|
|
213
|
+
}
|
|
214
|
+
const directory = Buffer.concat(records);
|
|
215
|
+
await write(directory);
|
|
216
|
+
const directorySize = directory.length;
|
|
217
|
+
const needs64 = forceZip64 || written.length >= MAX16 || directorySize >= MAX32 || directoryOffset >= MAX32;
|
|
218
|
+
if (needs64) {
|
|
219
|
+
const zip64At = offset;
|
|
220
|
+
const record = Buffer.alloc(56);
|
|
221
|
+
record.writeUInt32LE(SIG_ZIP64_EOCD, 0);
|
|
222
|
+
record.writeBigUInt64LE(44n, 4);
|
|
223
|
+
record.writeUInt16LE((3 << 8) | 45, 12);
|
|
224
|
+
record.writeUInt16LE(45, 14);
|
|
225
|
+
record.writeUInt32LE(0, 16);
|
|
226
|
+
record.writeUInt32LE(0, 20);
|
|
227
|
+
record.writeBigUInt64LE(BigInt(written.length), 24);
|
|
228
|
+
record.writeBigUInt64LE(BigInt(written.length), 32);
|
|
229
|
+
record.writeBigUInt64LE(BigInt(directorySize), 40);
|
|
230
|
+
record.writeBigUInt64LE(BigInt(directoryOffset), 48);
|
|
231
|
+
const locator = Buffer.alloc(20);
|
|
232
|
+
locator.writeUInt32LE(SIG_ZIP64_LOCATOR, 0);
|
|
233
|
+
locator.writeUInt32LE(0, 4);
|
|
234
|
+
locator.writeBigUInt64LE(BigInt(zip64At), 8);
|
|
235
|
+
locator.writeUInt32LE(1, 16);
|
|
236
|
+
await write(Buffer.concat([record, locator]));
|
|
237
|
+
}
|
|
238
|
+
const end = Buffer.alloc(22);
|
|
239
|
+
end.writeUInt32LE(SIG_EOCD, 0);
|
|
240
|
+
end.writeUInt16LE(0, 4);
|
|
241
|
+
end.writeUInt16LE(0, 6);
|
|
242
|
+
end.writeUInt16LE(needs64 ? MAX16 : written.length, 8);
|
|
243
|
+
end.writeUInt16LE(needs64 ? MAX16 : written.length, 10);
|
|
244
|
+
end.writeUInt32LE(needs64 ? MAX32 : directorySize, 12);
|
|
245
|
+
end.writeUInt32LE(needs64 ? MAX32 : directoryOffset, 16);
|
|
246
|
+
end.writeUInt16LE(0, 20);
|
|
247
|
+
await write(end);
|
|
248
|
+
await handle.sync();
|
|
249
|
+
progress(true);
|
|
250
|
+
} finally {
|
|
251
|
+
await handle.close();
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
bytes: offset,
|
|
255
|
+
entries: written.map(entry => ({ name: entry.name, size: entry.size, crc32: entry.crc, sha256: entry.sha256 })),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
@@ -19,6 +19,9 @@ export async function measureBrowserPhase(name, work) {
|
|
|
19
19
|
|
|
20
20
|
export function assertBrowserRequestActive(req) {
|
|
21
21
|
const state = req?.browserRequest || requests.getStore();
|
|
22
|
+
if (state?.protectionError) {
|
|
23
|
+
throw Object.assign(new Error(`Browser network protection unavailable: ${state.protectionError}`), { code: 'BROWSER_NETWORK_GUARD_UNAVAILABLE' });
|
|
24
|
+
}
|
|
22
25
|
if (state && (state.signal.aborted || Date.now() >= state.deadline)) {
|
|
23
26
|
const error = new Error(state.actionStarted
|
|
24
27
|
? 'Browser request expired after execution began; outcome is uncertain. Inspect the page before retrying.'
|
|
@@ -48,9 +51,13 @@ export async function runBrowserRequest(req, work, fallback = 10000) {
|
|
|
48
51
|
let timer, abort;
|
|
49
52
|
try {
|
|
50
53
|
return await Promise.race([
|
|
51
|
-
Promise.resolve().then(work),
|
|
54
|
+
Promise.resolve().then(() => { assertBrowserRequestActive(req); return work(); }),
|
|
52
55
|
new Promise((_, reject) => {
|
|
53
|
-
const fail = () =>
|
|
56
|
+
const fail = () => {
|
|
57
|
+
if (state?.protectionError) {
|
|
58
|
+
try { assertBrowserRequestActive(req); } catch (error) { reject(error); }
|
|
59
|
+
} else reject(Object.assign(new Error('Browser operation deadline exceeded; inspect state before retrying.'), { code: 'BROWSER_OPERATION_TIMEOUT' }));
|
|
60
|
+
};
|
|
54
61
|
timer = setTimeout(fail, Math.max(1, Math.min(fallback, state ? state.deadline - Date.now() : fallback)));
|
|
55
62
|
abort = fail;
|
|
56
63
|
state?.signal.addEventListener('abort', abort, { once: true });
|
|
@@ -89,6 +96,7 @@ export function browserRequestMiddleware(req, res, next) {
|
|
|
89
96
|
const deadline = Number.isFinite(requestedDeadline) && requestedDeadline > 0
|
|
90
97
|
? Math.min(requestedDeadline, Date.now() + 120_000) : Date.now() + 120_000;
|
|
91
98
|
const state = { requestId, deadline, signal: controller.signal, actionStarted: false, phases: {}, counts: {} };
|
|
99
|
+
state.cancelForProtection = reason => { state.protectionError = String(reason); controller.abort(); };
|
|
92
100
|
req.browserRequest = state;
|
|
93
101
|
res.setHeader('X-Synabun-Request-Id', requestId);
|
|
94
102
|
let responseBytes = 0;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// A separate, flattened CDP transport. Browser-level Target.setAutoAttach
|
|
2
|
+
// requires flat sessions; Playwright's public CDPSession cannot address those
|
|
3
|
+
// child session IDs. Do not reach into its private connection or patch Runtime.
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
import WebSocket from 'ws';
|
|
6
|
+
|
|
7
|
+
export class GuardCdpConnection extends EventEmitter {
|
|
8
|
+
constructor(socket) {
|
|
9
|
+
super();
|
|
10
|
+
this.socket = socket;
|
|
11
|
+
this.pending = new Map();
|
|
12
|
+
this.sequence = 0;
|
|
13
|
+
this.closed = false;
|
|
14
|
+
socket.on('message', data => {
|
|
15
|
+
let message;
|
|
16
|
+
try { message = JSON.parse(String(data)); } catch { return; }
|
|
17
|
+
if (message.id) {
|
|
18
|
+
const pending = this.pending.get(message.id);
|
|
19
|
+
if (!pending) return;
|
|
20
|
+
clearTimeout(pending.timer);
|
|
21
|
+
this.pending.delete(message.id);
|
|
22
|
+
if (message.error) pending.reject(Object.assign(new Error(`${pending.method} [session=${pending.sessionId || 'browser'}]: ${message.error.message}`), {
|
|
23
|
+
code: message.error.code, method: pending.method, sessionId: pending.sessionId,
|
|
24
|
+
protocolMessage: message.error.message,
|
|
25
|
+
...(!pending.sessionId ? { targetType: 'browser', targetId: 'root' } : {}),
|
|
26
|
+
})); else pending.resolve(message.result);
|
|
27
|
+
} else this.emit('event', message);
|
|
28
|
+
});
|
|
29
|
+
socket.on('close', () => { this.closed = true; this.rejectSession(); this.emit('close'); });
|
|
30
|
+
socket.on('error', error => { this.rejectSession(undefined, error); });
|
|
31
|
+
}
|
|
32
|
+
send(method, params = {}, sessionId) {
|
|
33
|
+
if (this.closed || this.closing) return Promise.reject(new Error('Network guard CDP transport closed'));
|
|
34
|
+
const id = ++this.sequence;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const timer = setTimeout(() => { this.pending.delete(id); reject(new Error(`Network guard: ${method} timed out`)); }, 5000);
|
|
37
|
+
this.pending.set(id, { resolve, reject, timer, sessionId, method });
|
|
38
|
+
const failed = error => {
|
|
39
|
+
if (!error) return;
|
|
40
|
+
const pending = this.pending.get(id);
|
|
41
|
+
if (pending) { clearTimeout(timer); this.pending.delete(id); reject(error); }
|
|
42
|
+
};
|
|
43
|
+
try { this.socket.send(JSON.stringify({ id, method, params, ...(sessionId ? { sessionId } : {}) }), failed); }
|
|
44
|
+
catch (error) { failed(error); }
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
rejectSession(sessionId, error = new Error('Network guard target detached')) {
|
|
48
|
+
for (const [id, pending] of this.pending) {
|
|
49
|
+
if (sessionId && pending.sessionId !== sessionId) continue;
|
|
50
|
+
clearTimeout(pending.timer); this.pending.delete(id); pending.reject(error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
detach() {
|
|
54
|
+
if (this.detaching) return this.detaching;
|
|
55
|
+
this.closing = true;
|
|
56
|
+
this.rejectSession();
|
|
57
|
+
this.detaching = new Promise(resolve => {
|
|
58
|
+
if (this.closed) return resolve();
|
|
59
|
+
const finish = () => { clearTimeout(timer); this.socket.removeListener('close', finish); resolve(); };
|
|
60
|
+
// Closing our transport never closes browser targets. Await the actual
|
|
61
|
+
// disconnect; terminate only this socket if the peer misses its close ACK.
|
|
62
|
+
const timer = setTimeout(() => { this.socket.terminate?.(); finish(); }, 1000);
|
|
63
|
+
this.socket.once('close', finish);
|
|
64
|
+
try { this.socket.close(); } catch { this.socket.terminate?.(); finish(); }
|
|
65
|
+
});
|
|
66
|
+
return this.detaching;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function connectGuardCdp(endpoint) {
|
|
71
|
+
let address = endpoint;
|
|
72
|
+
if (!/^wss?:\/\//.test(address)) {
|
|
73
|
+
// The owned DevTools JSON API, not page retrieval. No cookies or profile
|
|
74
|
+
// configuration are read or written; use the same endpoint as Playwright.
|
|
75
|
+
const response = await fetch(new URL('/json/version', endpoint), { signal: AbortSignal.timeout(5000) });
|
|
76
|
+
if (!response.ok) throw new Error(`Network guard: DevTools endpoint answered ${response.status}`);
|
|
77
|
+
address = (await response.json()).webSocketDebuggerUrl;
|
|
78
|
+
}
|
|
79
|
+
if (typeof address !== 'string' || !/^wss?:\/\//.test(address)) throw new Error('Network guard: no DevTools WebSocket endpoint');
|
|
80
|
+
const socket = new WebSocket(address, { handshakeTimeout: 5000, maxPayload: 16 * 1024 * 1024 });
|
|
81
|
+
await new Promise((resolve, reject) => { socket.once('open', resolve); socket.once('error', reject); });
|
|
82
|
+
return new GuardCdpConnection(socket);
|
|
83
|
+
}
|