synabun 2.0.10 → 2.2.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 +207 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +13 -13
- 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 +30 -17
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +7 -6
- 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 +302 -0
- package/lib/virustotal.mjs +203 -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/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.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/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- 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/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +18 -11
- 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 +22 -63
- 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/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- 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 +14 -14
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +29 -19
- 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/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- 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/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +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 +642 -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/budget-judgments.ts +5 -3
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +81 -21
- package/mcp-server/src/services/server-instructions.ts +29 -64
- 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/typesafe-config.ts +1 -1
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +29 -20
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +592 -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 +3953 -228
- package/neural-interface/i18n/pt-BR.json +3901 -179
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +128 -28
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- 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-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +81 -15
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +1073 -200
- package/neural-interface/lib/assistant-envelope.js +156 -2
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +93 -19
- package/neural-interface/lib/assistant-plan-permissions.js +25 -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 +245 -38
- package/neural-interface/lib/assistant-runtime.js +214 -30
- package/neural-interface/lib/assistant-task-prompt.js +87 -21
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +626 -4
- 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 +84 -0
- package/neural-interface/lib/browser-network-guard.js +476 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +198 -38
- package/neural-interface/lib/claude-agent-bridge.js +11 -2
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +163 -154
- package/neural-interface/lib/cli-resolver.js +13 -3
- package/neural-interface/lib/cli-update-planner.js +52 -41
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +191 -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/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +13 -10
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- 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 +35 -33
- package/neural-interface/lib/mcp-external-servers.js +332 -0
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +177 -25
- package/neural-interface/lib/native-loop-providers.js +965 -66
- package/neural-interface/lib/native-loop-runtime.js +290 -42
- 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 +53 -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/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +793 -0
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +20 -2
- package/neural-interface/lib/rulesets/api.js +7 -6
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +180 -36
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +81 -31
- 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 +298 -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 +285 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +569 -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 +216 -0
- package/neural-interface/lib/skills/eval-confinement.js +399 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +135 -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 +203 -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 +441 -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 +269 -0
- package/neural-interface/lib/skills/runtime-checks.js +358 -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 +530 -0
- package/neural-interface/lib/skills/telemetry.js +119 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +1268 -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-question.js +74 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +238 -0
- package/neural-interface/lib/worker-sandbox.js +329 -0
- package/neural-interface/package-lock.json +34 -12
- package/neural-interface/package.json +3 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +3 -3
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +125 -31
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- 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 +36 -6
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- 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 +105 -44
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +205 -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 +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -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 +151 -19
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +445 -82
- package/neural-interface/public/shared/assistant/asst-route.js +304 -53
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
- package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
- package/neural-interface/public/shared/assistant/asst-state.js +87 -24
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- 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 +34 -10
- package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
- package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
- 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 +127 -44
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +11 -12
- package/neural-interface/public/shared/cli-status.js +11 -10
- package/neural-interface/public/shared/constants.js +5 -4
- 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 +367 -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-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +21 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +30 -15
- 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 +74 -259
- 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-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
- 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 +17 -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 +60 -50
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/provider-icons.js +4 -2
- 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-rules.js +2 -2
- 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/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +222 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +133 -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 +149 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +513 -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 +237 -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 +230 -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-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -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 +282 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +690 -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 +249 -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 +426 -0
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1822 -1756
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/text-cache.js +29 -0
- 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/topright-overflow-logic.js +54 -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-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +111 -140
- package/neural-interface/public/shared/ui-claude-panel.js +376 -82
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- 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-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +33 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +10 -20
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
- package/neural-interface/public/shared/ui-navbar.js +49 -24
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +27 -15
- package/neural-interface/public/shared/ui-settings.js +683 -526
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
- 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 +270 -190
- package/neural-interface/public/shared/ui-tool-updates.js +6 -4
- package/neural-interface/public/shared/ui-tooltip.js +81 -51
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- 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 +312 -59
- package/neural-interface/public/shared/ui-worker-end.js +5 -1
- 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 +3 -3
- 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-questions.js +34 -0
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +2 -2
- 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 +4553 -2855
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +34 -12
- package/package.json +17 -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 +6 -6
- 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
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// String caches need a size budget as well as an entry count: streaming
|
|
2
|
+
// revisions are different keys and may each hold a nearly complete transcript.
|
|
3
|
+
export function createTextCache({ maxEntries = 512, maxChars = 1_000_000, maxEntryChars = 64_000 } = {}) {
|
|
4
|
+
const entries = new Map();
|
|
5
|
+
let chars = 0;
|
|
6
|
+
const drop = key => {
|
|
7
|
+
const value = entries.get(key);
|
|
8
|
+
if (value === undefined) return;
|
|
9
|
+
chars -= key.length + value.length;
|
|
10
|
+
entries.delete(key);
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
get(key) {
|
|
14
|
+
const value = entries.get(key);
|
|
15
|
+
if (value !== undefined) { entries.delete(key); entries.set(key, value); }
|
|
16
|
+
return value;
|
|
17
|
+
},
|
|
18
|
+
set(key, value) {
|
|
19
|
+
drop(key);
|
|
20
|
+
const size = key.length + value.length;
|
|
21
|
+
if (size > Math.min(maxChars, maxEntryChars) || maxEntries < 1) return;
|
|
22
|
+
while (entries.size && (entries.size >= maxEntries || chars + size > maxChars)) drop(entries.keys().next().value);
|
|
23
|
+
entries.set(key, value);
|
|
24
|
+
chars += size;
|
|
25
|
+
},
|
|
26
|
+
clear() { entries.clear(); chars = 0; },
|
|
27
|
+
stats: () => ({ entries: entries.size, chars }),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Shared cc-dropdown rendering; the pure view owns labels and catalog-derived choices.
|
|
2
|
+
import { dropdownHTML, setDropdownItems, dropdownOf } from './cc-dropdown.js';
|
|
3
|
+
import { toolListView, toolListWord, toolsFromInput, strictToolHost, taskToolHost } from './tool-list-view.js';
|
|
4
|
+
import { getCachedToolCatalog, fetchToolCatalog } from './agent-runtime-options.js';
|
|
5
|
+
let translate;
|
|
6
|
+
export function configureToolPickerTranslation(fn) { if (typeof fn === 'function') translate = fn; }
|
|
7
|
+
export { toolsFromInput, strictToolHost, taskToolHost };
|
|
8
|
+
export const toolWord = (key, params) => toolListWord(key, params, translate);
|
|
9
|
+
export function toolPickerHTML(id, tools, options = {}) {
|
|
10
|
+
const catalog = options.catalog || getCachedToolCatalog(options.cwd);
|
|
11
|
+
if (!catalog) return '';
|
|
12
|
+
const view = toolListView(catalog, tools, { translate, ...options });
|
|
13
|
+
return dropdownHTML(id, view.entries, { multiple: true, label: toolWord('label'), classes: 'tool-list-picker',
|
|
14
|
+
summary: view.summary, ...options, classes: `tool-list-picker ${options.classes || ''}`.trim(), attrs: `data-tool-options="${encodeURIComponent(JSON.stringify({ inheritLabel: options.inheritLabel, usesBrowser: options.usesBrowser, taskClass: options.taskClass, cwd: options.cwd, provider: options.provider, includeServers: options.includeServers, externalSelection: catalog.externalServersVersion >= 2 && options.includeServers !== false && options.provider !== 'antigravity', externalRefs: (tools ?? catalog.defaultTools ?? []).filter(id => id.startsWith('mcp:')) }))}"` });
|
|
15
|
+
}
|
|
16
|
+
export function updateToolPicker(input, tools, options = {}) {
|
|
17
|
+
options = { ...JSON.parse(decodeURIComponent(dropdownOf(input)?.dataset.toolOptions || '%7B%7D')), ...options };
|
|
18
|
+
const catalog = options.catalog || getCachedToolCatalog(options.cwd);
|
|
19
|
+
if (!catalog || !input) return;
|
|
20
|
+
const view = toolListView(catalog, tools, { translate, ...options });
|
|
21
|
+
setDropdownItems(input, view.entries);
|
|
22
|
+
const dd = dropdownOf(input);
|
|
23
|
+
if (dd) dd.dataset.toolOptions = encodeURIComponent(JSON.stringify({ inheritLabel: options.inheritLabel, usesBrowser: options.usesBrowser, taskClass: options.taskClass, cwd: options.cwd, provider: options.provider, includeServers: options.includeServers, externalSelection: catalog.externalServersVersion >= 2 && options.includeServers !== false && options.provider !== 'antigravity', externalRefs: (tools ?? catalog.defaultTools ?? []).filter(id => id.startsWith('mcp:')) }));
|
|
24
|
+
const label = dropdownOf(input)?.querySelector('.cc-dropdown-value');
|
|
25
|
+
if (label) { label.textContent = view.summary; label.title = view.summary; }
|
|
26
|
+
}
|
|
27
|
+
export function readToolPicker(input, options = {}) {
|
|
28
|
+
if (!input) return undefined; // old server: do not invent a selection
|
|
29
|
+
const dd = dropdownOf(input);
|
|
30
|
+
const raw = options.requested ? input.value.split(',').filter(id => ![...(dd?.querySelectorAll('[data-automatic="true"]') || [])].some(row => row.dataset.value === id)).join(',') : input.value;
|
|
31
|
+
const stored = JSON.parse(decodeURIComponent(dd?.dataset.toolOptions || '%7B%7D'));
|
|
32
|
+
const value = toolsFromInput(raw, { ...stored, ...options });
|
|
33
|
+
if (value && !stored.externalSelection && stored.externalRefs?.length) return [...value.filter(id => !id.startsWith('mcp:')), ...stored.externalRefs];
|
|
34
|
+
return value?.filter(id => id !== 'memory') ?? value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// A draft changes check rows/counts immediately; only cc-dropdown's close emits change.
|
|
38
|
+
if (typeof document !== 'undefined') document.addEventListener('cc-dropdown-draft', (event) => {
|
|
39
|
+
const dd = dropdownOf(event.target);
|
|
40
|
+
if (!dd?.classList.contains('tool-list-picker')) return;
|
|
41
|
+
const options = JSON.parse(decodeURIComponent(dd.dataset.toolOptions || '%7B%7D'));
|
|
42
|
+
updateToolPicker(event.target, readToolPicker(event.target, { requested: true }), options);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (typeof document !== 'undefined') document.addEventListener('mcp:servers-changed', () => {
|
|
46
|
+
const pickers = [...document.querySelectorAll('.tool-list-picker')];
|
|
47
|
+
for (const dd of pickers) {
|
|
48
|
+
const input = document.getElementById(dd.dataset.for);
|
|
49
|
+
const options = JSON.parse(decodeURIComponent(dd.dataset.toolOptions || '%7B%7D'));
|
|
50
|
+
const tools = readToolPicker(input, { requested: true });
|
|
51
|
+
fetchToolCatalog(false, { cwd: options.cwd }).then(catalog => {
|
|
52
|
+
if (catalog && input?.isConnected) updateToolPicker(input, tools, { ...options, catalog });
|
|
53
|
+
}).catch(() => {});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Read-only legacy conversion uses the server's one catalog, including custom saved names.
|
|
2
|
+
// Failed conversion leaves the old preference intact so it can be retried after a server update.
|
|
3
|
+
export async function migrateStoredTools(storage, key, legacyKey, { entry, fetcher = globalThis.fetch } = {}) {
|
|
4
|
+
let current;
|
|
5
|
+
try { current = JSON.parse(storage.getItem(key) || 'null'); } catch { current = null; }
|
|
6
|
+
const value = entry == null ? current : current?.[entry];
|
|
7
|
+
if (Array.isArray(value)) return value;
|
|
8
|
+
let old = storage.getItem(legacyKey);
|
|
9
|
+
if (entry != null) { try { old = JSON.parse(old || '{}')[entry]; } catch { old = null; } }
|
|
10
|
+
if (typeof old !== 'string' || !old.trim()) return null;
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetcher('/api/mcp/tools/convert', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ value: old }) });
|
|
13
|
+
const result = await response.json();
|
|
14
|
+
if (!response.ok || !result.ok || !Array.isArray(result.tools)) return null;
|
|
15
|
+
const tools = result.tools;
|
|
16
|
+
// A picker may have saved while the conversion was awaiting its reply; never overwrite it.
|
|
17
|
+
let latest;
|
|
18
|
+
try { latest = JSON.parse(storage.getItem(key) || 'null'); } catch { latest = null; }
|
|
19
|
+
const saved = entry == null ? latest : latest?.[entry];
|
|
20
|
+
if (Array.isArray(saved)) return saved;
|
|
21
|
+
storage.setItem(key, JSON.stringify(entry == null ? tools : { ...latest, [entry]: tools }));
|
|
22
|
+
return tools;
|
|
23
|
+
} catch { return null; }
|
|
24
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// DOM-free presentation of the server's catalog. No second group/count/preset table.
|
|
2
|
+
export const TOOL_LIST_COPY = Object.freeze({
|
|
3
|
+
label: 'Tools and MCP servers',
|
|
4
|
+
defaultTools: 'Default tools',
|
|
5
|
+
default: 'Default',
|
|
6
|
+
templateDefault: 'Template default',
|
|
7
|
+
noOverride: 'No override',
|
|
8
|
+
all: 'All SynaBun tools',
|
|
9
|
+
alwaysOn: 'Always-on tools',
|
|
10
|
+
count: '{count} tools',
|
|
11
|
+
countOne: '{count} tool',
|
|
12
|
+
browser: 'Browser and social',
|
|
13
|
+
workspace: 'Workspace',
|
|
14
|
+
other: 'Other',
|
|
15
|
+
addedBrowser: 'Added for browser use',
|
|
16
|
+
addedDesign: 'Added for design work',
|
|
17
|
+
focus: 'Loads every SynaBun tool on demand.',
|
|
18
|
+
strict: 'Loads the selected SynaBun groups.',
|
|
19
|
+
future: 'Applies to future runtimes. Running sessions keep their own tools.',
|
|
20
|
+
servers: 'Your other MCP servers',
|
|
21
|
+
allServers: 'All my servers',
|
|
22
|
+
configuredExternally: 'Configured in provider',
|
|
23
|
+
noServers: 'No external servers',
|
|
24
|
+
blockedServer: 'Blocked by Agents may use it',
|
|
25
|
+
unavailableServer: 'Unavailable on this provider',
|
|
26
|
+
agentAccess: 'Agents may use it',
|
|
27
|
+
agentAccessHelp: 'Applies to task workers and automations on Codex, OpenCode and Claude, including FleetView, plus the OpenCode tools picker. Other sessions you drive keep their servers.',
|
|
28
|
+
loadFailed: 'Could not load the tool catalog. Try again.',
|
|
29
|
+
saveFailed: 'Could not save the tool list. Try again.',
|
|
30
|
+
saved: 'Default tools saved.',
|
|
31
|
+
reloadFailed: 'OpenCode could not reload the requested tools.',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export function toolListWord(key, params = {}, translate) {
|
|
35
|
+
const full = `toolList.${key}`;
|
|
36
|
+
let translated;
|
|
37
|
+
try { translated = translate?.(full, params); } catch {}
|
|
38
|
+
const text = typeof translated === 'string' && translated !== full ? translated : TOOL_LIST_COPY[key] || key;
|
|
39
|
+
return text.replace(/\{(\w+)\}/g, (whole, name) => params[name] ?? whole);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function groupWord(group, field, translate) {
|
|
43
|
+
const key = `toolGroups.${group.id}.${field}`;
|
|
44
|
+
try { const value = translate?.(key); if (typeof value === 'string' && value && value !== key) return value; } catch {}
|
|
45
|
+
return group[field];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const strictToolHost = provider => provider === 'opencode' || provider === 'antigravity';
|
|
49
|
+
export const taskToolHost = provider => strictToolHost(provider) || provider === 'claude-code' || provider === 'codex';
|
|
50
|
+
|
|
51
|
+
/** Hidden-input encoding: inheritance differs from an explicit empty group list. */
|
|
52
|
+
export function toolListInput(tools) {
|
|
53
|
+
return tools == null ? '__inherit__' : tools.join(',');
|
|
54
|
+
}
|
|
55
|
+
export function toolsFromInput(value, { inherit = true, externalSelection = false } = {}) {
|
|
56
|
+
if (value == null || String(value).split(',').includes('__inherit__')) return inherit ? null : (externalSelection ? [] : ['mcp:*']);
|
|
57
|
+
const items = String(value).split(',').filter(id => id && id !== 'memory' && id !== '__no_servers__');
|
|
58
|
+
return [...new Set([...items, ...(!externalSelection && !items.some(id => id.startsWith('mcp:')) ? ['mcp:*'] : [])])];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function toolListView(catalog, tools, { inheritLabel = null, usesBrowser, taskClass,
|
|
62
|
+
provider = 'opencode', translate, includeServers = true } = {}) {
|
|
63
|
+
const word = (key, params) => toolListWord(key, params, translate);
|
|
64
|
+
const inherited = tools == null;
|
|
65
|
+
const source = inherited ? catalog?.defaultTools ?? catalog?.default ?? [] : tools;
|
|
66
|
+
const refs = source.filter(id => id.startsWith('mcp:'));
|
|
67
|
+
const requested = source.filter(id => !id.startsWith('mcp:'));
|
|
68
|
+
const all = requested.includes('all');
|
|
69
|
+
const groups = catalog?.groups || [];
|
|
70
|
+
const chosen = new Set(all ? groups.map(g => g.id) : requested);
|
|
71
|
+
const added = [];
|
|
72
|
+
const add = (id, why) => { if (groups.some(g => g.id === id) && !chosen.has(id)) { chosen.add(id); added.push({ id, why }); } };
|
|
73
|
+
if (usesBrowser || groups.some(g => chosen.has(g.id) && g.browser) || (taskClass === 'design' && usesBrowser !== false)) add('browser', 'addedBrowser');
|
|
74
|
+
if (taskClass === 'design') { add('image', 'addedDesign'); add('styleguide', 'addedDesign'); }
|
|
75
|
+
const entries = [];
|
|
76
|
+
if (inheritLabel) entries.push({ value: '__inherit__', label: inheritLabel, exclusive: true, selected: inherited });
|
|
77
|
+
entries.push({ value: 'all', label: word('all'), caption: catalog?.effect?.[provider] === 'focus' ? word('focus') : null, exclusive: true, scope: 'groups', selected: !inherited && all });
|
|
78
|
+
// A real value for explicit always-on avoids conflating it with the exclusive inheritance row.
|
|
79
|
+
entries.push({ value: 'memory', label: word('alwaysOn'), exclusive: true, scope: 'groups', selected: !inherited && !requested.length });
|
|
80
|
+
for (const section of ['browser', 'workspace', 'other']) {
|
|
81
|
+
const options = groups.filter(g => g.section === section).map(g => {
|
|
82
|
+
const automatic = added.find(a => a.id === g.id);
|
|
83
|
+
return { value: g.id, scope: 'groups', label: `${groupWord(g, 'label', translate)} · ${word(g.count === 1 ? 'countOne' : 'count', { count: g.count })}`,
|
|
84
|
+
caption: automatic ? word(automatic.why) : groupWord(g, 'purpose', translate),
|
|
85
|
+
selected: (!inherited && !all && chosen.has(g.id)) || !!automatic,
|
|
86
|
+
disabled: !!automatic, automatic: !!automatic };
|
|
87
|
+
});
|
|
88
|
+
if (options.length) entries.push({ group: word(section), options });
|
|
89
|
+
}
|
|
90
|
+
if (includeServers && provider !== 'antigravity' && catalog?.externalServersVersion >= 2) {
|
|
91
|
+
const wildcard = refs.includes('mcp:*');
|
|
92
|
+
const rows = (catalog.servers || []).filter(row => row.selectable !== false);
|
|
93
|
+
// A saved unavailable ref stays visible and round-trips; loading a catalog never silently clears it.
|
|
94
|
+
for (const ref of refs) if (ref !== 'mcp:*' && !rows.some(row => row.ref === ref)) rows.push({ ref, label: ref.slice(4), providers: {} });
|
|
95
|
+
const options = [
|
|
96
|
+
{ value: 'mcp:*', scope: 'servers', label: word('allServers'), exclusive: true, selected: !inherited && wildcard },
|
|
97
|
+
{ value: '__no_servers__', scope: 'servers', label: word('noServers'), exclusive: true, selected: !inherited && !refs.length },
|
|
98
|
+
...rows.map(row => {
|
|
99
|
+
const availability = row.providers?.[provider];
|
|
100
|
+
const unavailable = provider && provider !== 'all' ? availability !== 'deliverable' : !Object.values(row.providers || {}).includes('deliverable');
|
|
101
|
+
return { value: row.ref, scope: 'servers', label: row.label || row.ref.slice(4), selected: !inherited && !wildcard && refs.includes(row.ref), disabled: row.blocked || unavailable, caption: row.blocked ? word('blockedServer') : unavailable ? word('unavailableServer') : row.ref };
|
|
102
|
+
}),
|
|
103
|
+
];
|
|
104
|
+
entries.push({ group: word('servers'), options });
|
|
105
|
+
}
|
|
106
|
+
const count = (catalog?.alwaysOn || 0) + groups.filter(g => chosen.has(g.id)).reduce((n, g) => n + g.count, 0);
|
|
107
|
+
const labels = groups.filter(g => chosen.has(g.id)).map(g => groupWord(g, 'label', translate));
|
|
108
|
+
const short = all ? word('all') : labels.length ? `${labels.slice(0, 2).join(', ')}${labels.length > 2 ? ` +${labels.length - 2}` : ''}` : word('alwaysOn');
|
|
109
|
+
const serverLabel = refs.length ? ` · ${refs.includes('mcp:*') ? word('allServers') : refs.map(ref => ref.slice(4)).join(', ')}` : '';
|
|
110
|
+
const summary = `${inherited ? `${inheritLabel || word('default')} · ` : ''}${short} · ${word('count', { count })}${serverLabel}`;
|
|
111
|
+
return { entries, summary, count, added, groups: [...chosen], effect: catalog?.effect?.[provider] || (strictToolHost(provider) ? 'strict' : 'focus') };
|
|
112
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// The top-right toolbar's overflow, what decides (no DOM, no imports: node --test loads it).
|
|
2
|
+
// The page side is ui-topright-overflow.js.
|
|
3
|
+
|
|
4
|
+
// Lowest priority first: the first entries are the first to leave the row for the ⋯ menu.
|
|
5
|
+
export const OVERFLOW_ORDER = [
|
|
6
|
+
'topright-keybinds-btn',
|
|
7
|
+
'invite-overlay',
|
|
8
|
+
'topright-trash-btn',
|
|
9
|
+
'topright-bookmarks-btn',
|
|
10
|
+
'topright-antigravity-panel-btn',
|
|
11
|
+
'topright-opencode-panel-btn',
|
|
12
|
+
'topright-file-explorer-btn',
|
|
13
|
+
'topright-memory-explorer-btn',
|
|
14
|
+
'topright-codex-panel-btn',
|
|
15
|
+
'topright-update-btn',
|
|
16
|
+
'topright-claude-panel-btn',
|
|
17
|
+
'topright-assistant-panel-btn',
|
|
18
|
+
// the very last resort, a band of about 120 px: the toggle too (its entry in the menu shows and hides the tools)
|
|
19
|
+
'topright-tools-btn',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Which entries of OVERFLOW_ORDER leave the row: the fewest, in order, that bring the row's width within `available`.
|
|
24
|
+
* `total` is the row with everything in it and no ⋯; `widths[i]` what entry i takes in the row (its width and the gap
|
|
25
|
+
* before it; 0 when it is not shown at all, and then never listed); `menuWidth` what the ⋯ adds once anything
|
|
26
|
+
* overflows. Pinned entries never leave.
|
|
27
|
+
*/
|
|
28
|
+
export function overflowCount({ total, available, widths, menuWidth, pinned = [] }) {
|
|
29
|
+
if (total <= available) return { count: 0, hidden: [] };
|
|
30
|
+
let need = total + menuWidth;
|
|
31
|
+
const hidden = [];
|
|
32
|
+
for (let i = 0; i < widths.length && need > available; i++) {
|
|
33
|
+
if (pinned.includes(i) || !widths[i]) continue;
|
|
34
|
+
need -= widths[i];
|
|
35
|
+
hidden.push(i);
|
|
36
|
+
}
|
|
37
|
+
return { count: hidden.length, hidden };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Where a dropdown of the bar (workspaces, bookmarks, share) goes across: kept within [minLeft, maxRight] (the band's
|
|
42
|
+
* clip on the left, which already clears the Focus Mode rail and the left panels; the viewport on the right).
|
|
43
|
+
* `left` / `width` are its box as the stylesheet hangs it. Returns the `shift` (px, + is to the right) and the
|
|
44
|
+
* `maxWidth` it may take (null when it fits as it is). Too wide for the room: as wide as the room, flush with minLeft.
|
|
45
|
+
*/
|
|
46
|
+
export function clampDropdownX({ left, width, minLeft, maxRight }) {
|
|
47
|
+
const room = Math.max(0, maxRight - minLeft);
|
|
48
|
+
const w = Math.min(width, room);
|
|
49
|
+
const maxWidth = width > room ? room : null;
|
|
50
|
+
let x = left;
|
|
51
|
+
if (x + w > maxRight) x = maxRight - w;
|
|
52
|
+
if (x < minLeft) x = minLeft;
|
|
53
|
+
return { shift: Math.round(x - left), maxWidth };
|
|
54
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// The mascot as the tour's narrator: the empty state's real rig, in its real
|
|
2
|
+
// box, moved by transform only. Travel is physical: the box springs toward its
|
|
3
|
+
// place (a hop arc, a small crouch on take-off, a stretch and a lean in flight,
|
|
4
|
+
// a landing with a hint of give), so a new place in mid-flight carries on from
|
|
5
|
+
// where it is, at the speed it has. Every frame the body's change of velocity
|
|
6
|
+
// goes to the rig's arms (rig.nudge): they trail on take-off and wobble on
|
|
7
|
+
// arrival; its change of place goes to rig.shift, so a hand keeps pointing at
|
|
8
|
+
// the same control while the body flies, and the rig measures again once the
|
|
9
|
+
// body is still. Pointing is the rig's own (rig.point: arms + gaze). The
|
|
10
|
+
// mascot's keep-out (what it can draw: mascotBounds, plus a margin) is handed
|
|
11
|
+
// to `onMove` every frame it moves, for the ink layers' hole. Frames come from
|
|
12
|
+
// the shared ticker (the rig's own loop), only while the body moves; rects
|
|
13
|
+
// are read once per move, never per frame. Under reduced motion the box is
|
|
14
|
+
// placed, never flown.
|
|
15
|
+
import { subscribe } from '../synabun-ticker.js';
|
|
16
|
+
import { mascotBounds } from '../synabun-mascot.js';
|
|
17
|
+
import { springStep } from './tour-ink.js';
|
|
18
|
+
|
|
19
|
+
const MOVE = [12, 0.74]; // ω (rad/s), ζ: ≈ 3 % overshoot, the --asst-ease-spring landing
|
|
20
|
+
const ARC = [13, 0.62]; // the hop's rise and fall
|
|
21
|
+
const CROUCH = [26, 0.45]; // the take-off squash, rubbery
|
|
22
|
+
const SCALE = [14, 0.72];
|
|
23
|
+
const ARRIVED = { px: 4, speed: 140 }; // close and slow enough for the beat to go on (the spring finishes on its own)
|
|
24
|
+
const KEEP_OUT_MARGIN = 6; // px of clear board round what the mascot draws
|
|
25
|
+
|
|
26
|
+
export function createActor(target, { reduced = () => false, onMove = null } = {}) {
|
|
27
|
+
const rig = target.rig;
|
|
28
|
+
const svg = target.el;
|
|
29
|
+
const box = svg?.parentElement || null; // .asst-empty-mascot: the svg is centred in it, so scale and lean pivot on the face
|
|
30
|
+
const s = { x: 0, y: 0, vx: 0, vy: 0, arc: 0, varc: 0, q: 0, vq: 0, k: 1, vk: 0 };
|
|
31
|
+
const goal = { x: 0, y: 0, k: 1 };
|
|
32
|
+
let stop = null;
|
|
33
|
+
let waiters = [];
|
|
34
|
+
let lastV = { x: 0, y: 0 };
|
|
35
|
+
let lastAt = { x: 0, y: 0 }; // where the body was on the last frame (for rig.shift)
|
|
36
|
+
let place = null; // the last place asked for (a client point or null = home), for a replay after a resize
|
|
37
|
+
let base = null; // { cx, cy, w, h }: the face's centre and size with no transform (one read per move)
|
|
38
|
+
let lastPose = { name: 'idle', opts: undefined };
|
|
39
|
+
|
|
40
|
+
const present = () => !!(box && svg?.isConnected && box.offsetWidth > 0);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The untransformed face: its client centre (one read) and its own size (the SVG's attributes). When the
|
|
44
|
+
* layout under it moved (the board made room, the panel changed), the body keeps its place on screen:
|
|
45
|
+
* the offset and the goal take the shift, so nothing jumps.
|
|
46
|
+
*/
|
|
47
|
+
function readBase() {
|
|
48
|
+
if (!svg) return null;
|
|
49
|
+
const r = svg.getBoundingClientRect();
|
|
50
|
+
const w = Number(svg.getAttribute('width')) || r.width / (s.k || 1);
|
|
51
|
+
const h = Number(svg.getAttribute('height')) || r.height / (s.k || 1);
|
|
52
|
+
// Where the box would be with no transform: its client centre less the offset we set (scale and lean pivot on it).
|
|
53
|
+
const at = { cx: r.left + r.width / 2 - s.x, cy: r.top + r.height / 2 - (s.y + s.arc) };
|
|
54
|
+
const prev = base;
|
|
55
|
+
base = { cx: at.cx, cy: at.cy, w, h };
|
|
56
|
+
if (prev && box?.style.transform && (Math.abs(prev.cx - at.cx) > 0.5 || Math.abs(prev.cy - at.cy) > 0.5)) {
|
|
57
|
+
// The layout moved under a transform we set: hold the body where it is on screen, and its goal too.
|
|
58
|
+
const dx = prev.cx - at.cx;
|
|
59
|
+
const dy = prev.cy - at.cy;
|
|
60
|
+
s.x += dx;
|
|
61
|
+
s.y += dy;
|
|
62
|
+
goal.x += dx;
|
|
63
|
+
goal.y += dy;
|
|
64
|
+
lastAt = { x: lastAt.x + dx, y: lastAt.y + dy };
|
|
65
|
+
write();
|
|
66
|
+
}
|
|
67
|
+
return base;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The face-unit box the pose draws in, as a client rect for the face at (x, y) offset and scale k, plus `margin`. */
|
|
71
|
+
function boundsAt(x, y, k, margin = KEEP_OUT_MARGIN) {
|
|
72
|
+
if (!base) return null;
|
|
73
|
+
const b = mascotBounds(lastPose.name, lastPose.opts);
|
|
74
|
+
const u = (base.w / 280) * k; // CSS px per face unit
|
|
75
|
+
const left = base.cx + x - (base.w * k) / 2;
|
|
76
|
+
const top = base.cy + y - (base.h * k) / 2;
|
|
77
|
+
const rect = { left: left + b.left * u - margin, top: top + b.top * u - margin, right: left + b.right * u + margin, bottom: top + b.bottom * u + margin };
|
|
78
|
+
rect.width = rect.right - rect.left;
|
|
79
|
+
rect.height = rect.bottom - rect.top;
|
|
80
|
+
return rect;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const tellMove = () => { if (onMove && base) try { onMove(boundsAt(s.x, s.y + s.arc, s.k)); } catch { /* the host's */ } };
|
|
84
|
+
|
|
85
|
+
function write() {
|
|
86
|
+
if (!box) return;
|
|
87
|
+
const speed = Math.hypot(s.vx, s.vy + s.varc);
|
|
88
|
+
const stretch = Math.min(0.04, speed / 9000);
|
|
89
|
+
const lean = Math.max(-7, Math.min(7, s.vx * 0.011));
|
|
90
|
+
const sx = s.k * (1 + s.q) * (1 - stretch);
|
|
91
|
+
const sy = s.k * (1 - s.q) * (1 + stretch);
|
|
92
|
+
const still = Math.abs(s.x) < 0.05 && Math.abs(s.y + s.arc) < 0.05 && Math.abs(sx - 1) < 1e-3 && Math.abs(sy - 1) < 1e-3 && Math.abs(lean) < 0.05;
|
|
93
|
+
box.style.transform = still ? '' : `translate(${s.x.toFixed(2)}px, ${(s.y + s.arc).toFixed(2)}px) rotate(${lean.toFixed(2)}deg) scale(${sx.toFixed(4)}, ${sy.toFixed(4)})`;
|
|
94
|
+
tellMove();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Where the face's centre sits with no transform (one read per move). */
|
|
98
|
+
function layoutCentre() {
|
|
99
|
+
const r = svg.getBoundingClientRect();
|
|
100
|
+
return { x: r.left + r.width / 2 - s.x, y: r.top + r.height / 2 - (s.y + s.arc) };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const near = () => Math.hypot(goal.x - s.x, goal.y - s.y) < ARRIVED.px && Math.hypot(s.vx, s.vy) < ARRIVED.speed && Math.abs(s.arc) < ARRIVED.px;
|
|
104
|
+
const still = () => Math.hypot(goal.x - s.x, goal.y - s.y) < 0.2 && Math.hypot(s.vx, s.vy) < 2 && Math.abs(s.arc) < 0.2 && Math.abs(s.varc) < 2
|
|
105
|
+
&& Math.abs(s.q) < 0.001 && Math.abs(s.vq) < 0.01 && Math.abs(s.k - goal.k) < 0.001 && Math.abs(s.vk) < 0.01;
|
|
106
|
+
|
|
107
|
+
function release(all = false) {
|
|
108
|
+
const keep = [];
|
|
109
|
+
for (const w of waiters) { if (all || w.when()) w.resolve(); else keep.push(w); }
|
|
110
|
+
waiters = keep;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function onFrame(_now, dtMs) {
|
|
114
|
+
const dt = dtMs / 1000;
|
|
115
|
+
if (!svg?.isConnected) { halt(); return; } // no layout read per frame: present() is asked once per move
|
|
116
|
+
let r = springStep(s.x, s.vx, goal.x, MOVE[0], MOVE[1], dt); s.x = r.x; s.vx = r.v;
|
|
117
|
+
r = springStep(s.y, s.vy, goal.y, MOVE[0], MOVE[1], dt); s.y = r.x; s.vy = r.v;
|
|
118
|
+
r = springStep(s.arc, s.varc, 0, ARC[0], ARC[1], dt); s.arc = r.x; s.varc = r.v;
|
|
119
|
+
r = springStep(s.q, s.vq, 0, CROUCH[0], CROUCH[1], dt); s.q = r.x; s.vq = r.v;
|
|
120
|
+
r = springStep(s.k, s.vk, goal.k, SCALE[0], SCALE[1], dt); s.k = r.x; s.vk = r.v;
|
|
121
|
+
write();
|
|
122
|
+
// The body's change of velocity this frame: the arms keep their old speed and trail.
|
|
123
|
+
const v = { x: s.vx, y: s.vy + s.varc };
|
|
124
|
+
const dvx = v.x - lastV.x;
|
|
125
|
+
const dvy = v.y - lastV.y;
|
|
126
|
+
lastV = v;
|
|
127
|
+
if (Math.abs(dvx) + Math.abs(dvy) > 1) try { rig.nudge?.(dvx, dvy); } catch { /* an older rig */ }
|
|
128
|
+
// The body moved: a hand that points keeps pointing at the same control (no layout read).
|
|
129
|
+
const at = { x: s.x, y: s.y + s.arc };
|
|
130
|
+
if (rig.pointing) try { rig.shift?.(at.x - lastAt.x, at.y - lastAt.y); } catch { /* an older rig */ }
|
|
131
|
+
lastAt = at;
|
|
132
|
+
release();
|
|
133
|
+
if (still()) {
|
|
134
|
+
Object.assign(s, { x: goal.x, y: goal.y, vx: 0, vy: 0, arc: 0, varc: 0, q: 0, vq: 0, k: goal.k, vk: 0 });
|
|
135
|
+
write();
|
|
136
|
+
halt();
|
|
137
|
+
if (rig.pointing) try { rig.remeasure?.(); } catch { /* an older rig */ } // landed, scale settled: read the rects once more
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function halt() {
|
|
142
|
+
stop?.();
|
|
143
|
+
stop = null;
|
|
144
|
+
lastV = { x: 0, y: 0 };
|
|
145
|
+
release(true);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Fly to `point` (client px; null = home) at `scale`. Resolves once it has
|
|
150
|
+
* arrived closely enough for the next op (the landing finishes on its own),
|
|
151
|
+
* at once under reduced motion or when there is no character on screen.
|
|
152
|
+
*/
|
|
153
|
+
function travel(point, { scale = 1 } = {}) {
|
|
154
|
+
place = { point: point ? { ...point } : null, scale };
|
|
155
|
+
if (!present()) return Promise.resolve();
|
|
156
|
+
const c = readBase() ? { x: base.cx, y: base.cy } : layoutCentre();
|
|
157
|
+
const to = { x: point ? point.x - c.x : 0, y: point ? point.y - c.y : 0, k: scale };
|
|
158
|
+
const dist = Math.hypot(to.x - s.x, to.y - s.y);
|
|
159
|
+
Object.assign(goal, to);
|
|
160
|
+
if (reduced()) {
|
|
161
|
+
halt();
|
|
162
|
+
Object.assign(s, { x: to.x, y: to.y, vx: 0, vy: 0, arc: 0, varc: 0, q: 0, vq: 0, k: to.k, vk: 0 });
|
|
163
|
+
write();
|
|
164
|
+
lastAt = { x: s.x, y: s.y };
|
|
165
|
+
if (rig.pointing) try { rig.remeasure?.(); } catch { /* an older rig */ }
|
|
166
|
+
return Promise.resolve();
|
|
167
|
+
}
|
|
168
|
+
if (dist > 6) {
|
|
169
|
+
// Take-off: a small crouch and a hop, both scaled to the distance (a short move barely hops).
|
|
170
|
+
s.vq += Math.min(2.6, 0.9 + dist / 160);
|
|
171
|
+
s.varc -= Math.min(260, 40 + dist * 1.2);
|
|
172
|
+
}
|
|
173
|
+
if (!stop) { lastV = { x: s.vx, y: s.vy + s.varc }; lastAt = { x: s.x, y: s.y + s.arc }; stop = subscribe(onFrame, { fps: 60 }); }
|
|
174
|
+
return new Promise((resolve) => { waiters.push({ resolve, when: near }); });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** The panel was resized: fly to the same place again (its client point is the caller's to recompute). */
|
|
178
|
+
function replay(point) {
|
|
179
|
+
if (!place) return Promise.resolve();
|
|
180
|
+
return travel(point === undefined ? place.point : point, { scale: place.scale });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* What the mascot draws (mascotBounds for its pose: the eyes over their
|
|
185
|
+
* travel, the smile, its prop), where it lands, as a client rect plus
|
|
186
|
+
* `margin` px: the board keeps its ink out of it.
|
|
187
|
+
*/
|
|
188
|
+
function keepOut(margin = KEEP_OUT_MARGIN) {
|
|
189
|
+
if (!svg) return null;
|
|
190
|
+
if (!base) readBase();
|
|
191
|
+
return boundsAt(goal.x, goal.y, goal.k, margin);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** keepOut() for the face landed at client point `point` (its centre) at `scale`: for choosing a place. */
|
|
195
|
+
function keepOutAt(point, scale = 1, margin = KEEP_OUT_MARGIN) {
|
|
196
|
+
if (!svg) return null;
|
|
197
|
+
if (!base) readBase();
|
|
198
|
+
if (!base) return null;
|
|
199
|
+
return boundsAt(point ? point.x - base.cx : 0, point ? point.y - base.cy : 0, scale, margin);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The face's client rect where it will land (its goal), for ink placed beside it. */
|
|
203
|
+
function rect() {
|
|
204
|
+
if (!svg) return null;
|
|
205
|
+
const r = svg.getBoundingClientRect();
|
|
206
|
+
const k = goal.k / (s.k || 1);
|
|
207
|
+
const cx = r.left + r.width / 2 + (goal.x - s.x);
|
|
208
|
+
const cy = r.top + r.height / 2 + (goal.y - (s.y + s.arc));
|
|
209
|
+
const w = r.width * k;
|
|
210
|
+
const h = r.height * k;
|
|
211
|
+
return { left: cx - w / 2, top: cy - h / 2, right: cx + w / 2, bottom: cy + h / 2, width: w, height: h };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* A point on the landed face's visible edge (the eyes and the smile, not the SVG's box:
|
|
216
|
+
* the eyes span 29-71 % of its width, 17-86 % of its height): 'top' | 'bottom' | 'left' | 'right' | 'center'.
|
|
217
|
+
*/
|
|
218
|
+
function edge(side = 'center') {
|
|
219
|
+
const r = rect();
|
|
220
|
+
if (!r) return null;
|
|
221
|
+
const c = { x: r.left + r.width / 2, y: r.top + r.height * 0.5 };
|
|
222
|
+
if (side === 'top') return { x: c.x, y: r.top + r.height * 0.14 };
|
|
223
|
+
if (side === 'bottom') return { x: c.x, y: r.top + r.height * 0.9 };
|
|
224
|
+
if (side === 'left') return { x: r.left + r.width * 0.26, y: c.y };
|
|
225
|
+
if (side === 'right') return { x: r.left + r.width * 0.74, y: c.y };
|
|
226
|
+
return c;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
rig,
|
|
231
|
+
box,
|
|
232
|
+
present,
|
|
233
|
+
travel,
|
|
234
|
+
replay,
|
|
235
|
+
rect,
|
|
236
|
+
edge,
|
|
237
|
+
keepOut,
|
|
238
|
+
keepOutAt,
|
|
239
|
+
/** Read the untransformed face again (the panel was resized or scrolled). */
|
|
240
|
+
measure() { readBase(); tellMove(); },
|
|
241
|
+
pose(name, opts) { lastPose = { name, opts }; try { rig.setPose(name, opts); } catch { /* gone */ } tellMove(); },
|
|
242
|
+
react(name) { if (!reduced()) try { rig.react(name); } catch { /* gone */ } },
|
|
243
|
+
/** Point with the arms and the eyes (null: put them away); opts: { poke, gap } (rig.point). */
|
|
244
|
+
point(targetEl, opts) { try { rig.point?.(targetEl, opts); } catch { /* an older rig */ } },
|
|
245
|
+
poke() { if (!reduced()) try { rig.poke?.(); } catch { /* an older rig */ } },
|
|
246
|
+
/** Look toward a client point without pointing. */
|
|
247
|
+
look(point) {
|
|
248
|
+
const r = rect();
|
|
249
|
+
if (!r || !point) return;
|
|
250
|
+
const vx = point.x - (r.left + r.width / 2);
|
|
251
|
+
const vy = point.y - (r.top + r.height / 2);
|
|
252
|
+
const d = Math.hypot(vx, vy);
|
|
253
|
+
if (d < 1) { rig.look(0, 0); return; }
|
|
254
|
+
const m = (d / (d + 140)) * 1.25;
|
|
255
|
+
rig.look(Math.max(-1, Math.min(1, (vx / d) * m)), Math.max(-1, Math.min(1, (vy / d) * m)));
|
|
256
|
+
},
|
|
257
|
+
get lastPose() { return lastPose; },
|
|
258
|
+
/** Back to rest at once: no transform, nothing pending. */
|
|
259
|
+
reset() {
|
|
260
|
+
halt();
|
|
261
|
+
Object.assign(s, { x: 0, y: 0, vx: 0, vy: 0, arc: 0, varc: 0, q: 0, vq: 0, k: 1, vk: 0 });
|
|
262
|
+
Object.assign(goal, { x: 0, y: 0, k: 1 });
|
|
263
|
+
if (box) box.style.transform = '';
|
|
264
|
+
place = null;
|
|
265
|
+
},
|
|
266
|
+
get moving() { return !!stop; },
|
|
267
|
+
};
|
|
268
|
+
}
|