synabun 2.1.0 → 2.2.1
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 +139 -0
- package/README.md +1 -1
- package/docs/whatsapp.md +11 -11
- package/lib/client-config-repair.js +13 -9
- package/lib/external-tools.js +6 -5
- package/lib/update-snapshot.js +77 -3
- package/lib/virustotal.mjs +12 -1
- package/mcp-server/dist/index.js +1 -1
- package/mcp-server/dist/index.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/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- 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 +2 -1
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +2 -1
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.js +1 -1
- package/mcp-server/dist/services/tool-catalog.js.map +1 -1
- package/mcp-server/dist/services/tool-list.d.ts +1 -1
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.d.ts +2 -2
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.js +1 -1
- package/mcp-server/dist/services/tool-runtime.js.map +1 -1
- 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/tools/agents.d.ts +8 -8
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +10 -9
- package/mcp-server/dist/tools/agents.js.map +1 -1
- 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/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 +8 -8
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/skill-tools.js +11 -8
- package/mcp-server/dist/tools/skill-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/index.ts +1 -1
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +2 -1
- package/mcp-server/src/services/server-instructions.ts +2 -1
- package/mcp-server/src/services/tool-catalog.ts +1 -1
- package/mcp-server/src/services/tool-list.ts +1 -1
- package/mcp-server/src/services/tool-runtime.ts +2 -2
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/tools/agents.ts +10 -9
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +11 -8
- package/neural-interface/i18n/en.json +504 -39
- package/neural-interface/i18n/pt-BR.json +504 -39
- 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 +1 -0
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/codex.js +6 -1
- 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 +76 -9
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +211 -50
- package/neural-interface/lib/assistant-envelope.js +153 -1
- 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 +16 -11
- package/neural-interface/lib/assistant-plan-permissions.js +15 -0
- package/neural-interface/lib/assistant-router.js +237 -35
- package/neural-interface/lib/assistant-runtime.js +158 -12
- package/neural-interface/lib/assistant-task-prompt.js +10 -8
- package/neural-interface/lib/assistant-tools.js +2 -2
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +6 -1
- package/neural-interface/lib/browser-guard-cdp.js +5 -4
- package/neural-interface/lib/browser-network-guard.js +274 -82
- package/neural-interface/lib/browser-tool-policy.js +12 -7
- package/neural-interface/lib/claude-agent-bridge.js +7 -0
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +160 -31
- package/neural-interface/lib/cli-resolver.js +9 -2
- package/neural-interface/lib/cli-update-planner.js +25 -15
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +25 -6
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +9 -2
- 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/mcp-client-config.js +37 -6
- package/neural-interface/lib/mcp-external-servers.js +40 -7
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +147 -25
- package/neural-interface/lib/native-loop-providers.js +423 -23
- package/neural-interface/lib/native-loop-runtime.js +23 -2
- package/neural-interface/lib/opencode-native-boundary.js +165 -22
- package/neural-interface/lib/owner-authority.js +1 -1
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +80 -6
- 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 +3 -0
- package/neural-interface/lib/rulesets/api.js +6 -5
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +89 -10
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +64 -1
- package/neural-interface/lib/skills/catalog.js +5 -1
- package/neural-interface/lib/skills/creation-brief.js +1 -1
- package/neural-interface/lib/skills/creation-sources.js +19 -1
- package/neural-interface/lib/skills/deploy.js +9 -4
- package/neural-interface/lib/skills/draft-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-trace.js +16 -0
- package/neural-interface/lib/skills/export.js +5 -2
- package/neural-interface/lib/skills/known-bridge-digests.json +58 -4
- package/neural-interface/lib/skills/ownership.js +1 -1
- package/neural-interface/lib/skills/roots.js +10 -3
- package/neural-interface/lib/skills/runtime-checks.js +6 -3
- package/neural-interface/lib/skills/service.js +15 -7
- package/neural-interface/lib/skills/telemetry.js +6 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/whatsapp/brain.js +7 -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 +77 -1
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-resume.js +13 -4
- package/neural-interface/lib/worker-sandbox.js +46 -16
- package/neural-interface/package-lock.json +18 -2
- package/neural-interface/package.json +2 -1
- package/neural-interface/public/onboarding.html +1 -1
- package/neural-interface/public/shared/agent-runtime-options.js +89 -11
- 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 +4 -4
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +3 -4
- package/neural-interface/public/shared/assistant/asst-api.js +15 -3
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +56 -9
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-computer.js +26 -2
- package/neural-interface/public/shared/assistant/asst-control.js +48 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +6 -1
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +38 -5
- package/neural-interface/public/shared/assistant/asst-motion-gate.js +80 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +46 -9
- package/neural-interface/public/shared/assistant/asst-render.js +112 -18
- package/neural-interface/public/shared/assistant/asst-route.js +237 -57
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scene-styles.js +55 -23
- package/neural-interface/public/shared/assistant/asst-scenes.js +279 -80
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +4 -4
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +51 -7
- package/neural-interface/public/shared/assistant/asst-slash.js +8 -2
- package/neural-interface/public/shared/assistant/asst-state.js +76 -9
- package/neural-interface/public/shared/assistant/asst-style-cache.js +44 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +58 -4
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +34 -7
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +26 -3
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +11 -10
- package/neural-interface/public/shared/cdx/cdx-render.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-requests.js +11 -1
- package/neural-interface/public/shared/cdx/cdx-styles.js +4 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +75 -5
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +7 -4
- package/neural-interface/public/shared/cli-status.js +9 -8
- package/neural-interface/public/shared/constants.js +3 -2
- package/neural-interface/public/shared/context-menu-model.js +1 -0
- package/neural-interface/public/shared/cp/cp-permissions.js +12 -0
- 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/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 +1 -0
- 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 +21 -4
- package/neural-interface/public/shared/loading-teardown.js +34 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +6 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +28 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +17 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +6 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +101 -68
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +46 -3
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +1 -1
- package/neural-interface/public/shared/settings/settings-skill-folders.js +2 -2
- 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-creation.js +6 -3
- package/neural-interface/public/shared/skills/ss-dialog.js +5 -2
- package/neural-interface/public/shared/skills/ss-lint.js +9 -1
- package/neural-interface/public/shared/skills/ss-profiles.js +44 -6
- package/neural-interface/public/shared/skills/ss-review-view.js +2 -2
- package/neural-interface/public/shared/skills/studio/sx-actions.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-dom.js +2 -1
- 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-inspector.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +9 -6
- package/neural-interface/public/shared/skills/studio/sx-install.js +20 -3
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +144 -35
- package/neural-interface/public/shared/skills/studio/sx-library.js +6 -2
- package/neural-interface/public/shared/skills/studio/sx-main.js +11 -2
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-subject.js +7 -6
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +6 -5
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/storage-retry.js +47 -0
- package/neural-interface/public/shared/storage.js +25 -4
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styles.css +362 -35
- package/neural-interface/public/shared/synabun-mascot.js +27 -8
- package/neural-interface/public/shared/synabun-ticker.js +147 -12
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +2 -2
- package/neural-interface/public/shared/tool-list-view.js +2 -2
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -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 +20 -12
- package/neural-interface/public/shared/ui-claude-panel.js +374 -134
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- 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-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +8 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-loading.js +5 -4
- package/neural-interface/public/shared/ui-menubar.js +2 -2
- package/neural-interface/public/shared/ui-native-loop-router.js +4 -0
- package/neural-interface/public/shared/ui-navbar.js +45 -0
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +41 -10
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +22 -12
- package/neural-interface/public/shared/ui-settings.js +90 -65
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -3
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +3 -3
- package/neural-interface/public/shared/ui-terminal.js +146 -10
- package/neural-interface/public/shared/ui-tool-updates.js +3 -3
- package/neural-interface/public/shared/ui-tooltip.js +71 -46
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1 -1
- package/neural-interface/public/shared/ui-worker-end.js +1 -1
- package/neural-interface/public/shared/whatsapp/wa-view.js +2 -2
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/server.js +731 -466
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +5 -5
- package/neural-interface/templates/rulesets/manifest.json +1 -1
- package/npm-shrinkwrap.json +18 -2
- package/package.json +2 -1
- package/skills/skill-forge/SKILL.md +4 -4
- package/skills/synabun/SKILL.md +1 -1
- package/skills/synabun/modules/schedule.md +3 -3
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -90,9 +90,10 @@
|
|
|
90
90
|
* - `paintMascot(svg, frame)` — draw a frame on any `mascotSvg()`. A still
|
|
91
91
|
* frame (`stillFrame`, or a rig that is not looping) draws its prop at
|
|
92
92
|
* ≥ .7 opacity with strokes of ≥ 1.5 CSS px, so it reads at 28×14.
|
|
93
|
-
* - `mascotCameoSvg()` — two 3×7 px pill eyes (`syna-cameo`
|
|
94
|
-
* `syna-cameo-eye`) for running pills,
|
|
95
|
-
* (never a pause glyph); the host's CSS
|
|
93
|
+
* - `mascotCameoSvg()` — two 3×7 px pill eyes (`syna-cameo` >
|
|
94
|
+
* `syna-cameo-eyes` > svg > `syna-cameo-eye` ×2) for running pills,
|
|
95
|
+
* leaning −12° like the two-pill mark (never a pause glyph); the host's CSS
|
|
96
|
+
* moves the `syna-cameo-eyes` box (an HTML element, so the compositor runs it).
|
|
96
97
|
* - `mascotPropSvg(kind, { width, height })` + `paintMascotProp(svg, kind)`
|
|
97
98
|
* — a kind's prop alone, framed to its own box: the ledger's row glyphs.
|
|
98
99
|
* - `mascotBounds(pose)` — the face-unit box a pose can draw in (the eyes over
|
|
@@ -167,14 +168,18 @@ export function blinkAmount(elapsed) {
|
|
|
167
168
|
/**
|
|
168
169
|
* Two 3×7 px pill eyes for a running pill; the host's CSS moves them. The
|
|
169
170
|
* pair leans −12° like the two-pill mark (the right eye sits higher), so it
|
|
170
|
-
* never reads as a pause glyph.
|
|
171
|
+
* never reads as a pause glyph. What moves is the HTML box around the eyes
|
|
172
|
+
* (`syna-cameo-eyes`), never a part of the SVG: a box's transform runs on
|
|
173
|
+
* the compositor and, when the page draws a frame anyway, restyles one
|
|
174
|
+
* element without laying the SVG out again.
|
|
171
175
|
*/
|
|
172
176
|
export function mascotCameoSvg({ className = '' } = {}) {
|
|
173
|
-
return `<
|
|
177
|
+
return `<span class="syna-cameo${className ? ` ${className}` : ''}" aria-hidden="true"><span class="syna-cameo-eyes">`
|
|
178
|
+
+ '<svg viewBox="0 0 10 7" width="10" height="7" style="display:block;overflow:visible" focusable="false">'
|
|
174
179
|
+ '<g class="syna-cameo-pair" transform="rotate(-12 5 3.5)">'
|
|
175
180
|
+ '<rect class="syna-cameo-eye" x="0" y="0" width="3" height="7" rx="1.5" fill="currentColor"/>'
|
|
176
181
|
+ '<rect class="syna-cameo-eye" x="7" y="0" width="3" height="7" rx="1.5" fill="currentColor"/>'
|
|
177
|
-
+ '</g></svg>';
|
|
182
|
+
+ '</g></svg></span></span>';
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
/** Each prop's own box in face units, to draw it alone (a ledger row's glyph, a suggestion's). */
|
|
@@ -1842,6 +1847,14 @@ function createPainter(svg, uid) {
|
|
|
1842
1847
|
if (value == null) el.removeAttribute(attr);
|
|
1843
1848
|
else el.setAttribute(attr, value);
|
|
1844
1849
|
};
|
|
1850
|
+
/** A prop's writes for this frame: the last value per attribute wins, put() writes it once (paint). */
|
|
1851
|
+
const staged = new Map();
|
|
1852
|
+
const stage = (el, attr, value) => {
|
|
1853
|
+
if (!el) return;
|
|
1854
|
+
let attrs = staged.get(el);
|
|
1855
|
+
if (!attrs) { attrs = new Map(); staged.set(el, attrs); }
|
|
1856
|
+
attrs.set(attr, value);
|
|
1857
|
+
};
|
|
1845
1858
|
/** CSS px per face unit: the SVG's box over its viewBox (xMidYMid meet: the tighter axis). */
|
|
1846
1859
|
const unitPx = () => {
|
|
1847
1860
|
const w = Number(svg.getAttribute?.('width'));
|
|
@@ -1898,8 +1911,14 @@ function createPainter(svg, uid) {
|
|
|
1898
1911
|
put(entry.g, 'display', null);
|
|
1899
1912
|
put(entry.g, 'opacity', op < 0.999 ? n(op) : null);
|
|
1900
1913
|
put(entry.g, 'transform', p.dx || p.dy ? `translate(${n(p.dx || 0)},${n(p.dy || 0)})` : null);
|
|
1901
|
-
|
|
1902
|
-
|
|
1914
|
+
// Live: the drawn values, then the frame's own over them. Both are staged and each attribute is
|
|
1915
|
+
// written once with its final value, so a frame that changes nothing writes nothing (an attribute
|
|
1916
|
+
// written twice a frame, back to its base and on again, restyles and re-lays the SVG out every frame).
|
|
1917
|
+
staged.clear();
|
|
1918
|
+
if (!f.still) for (const b of entry.base) stage(b.el, b.attr, b.value);
|
|
1919
|
+
PROPS[name].update(entry.r, p, stage);
|
|
1920
|
+
for (const [el, attrs] of staged) for (const [attr, value] of attrs) put(el, attr, value);
|
|
1921
|
+
staged.clear();
|
|
1903
1922
|
if (f.still) legible(entry);
|
|
1904
1923
|
}
|
|
1905
1924
|
}
|
|
@@ -9,6 +9,18 @@
|
|
|
9
9
|
// requestFrames(ms) lifts the animation subscribers (≥ 24 fps) to 60 fps for a
|
|
10
10
|
// moment: a pose blend, a hop.
|
|
11
11
|
//
|
|
12
|
+
// A frame is only requested for the vsync a subscriber is due on: a 30 fps
|
|
13
|
+
// rig costs 30 frames a second, not one per vsync. Every frame the page draws
|
|
14
|
+
// makes the browser restyle each running CSS animation on the main thread
|
|
15
|
+
// (composited or not), so a frame nobody needs is never free. Between due
|
|
16
|
+
// frames the loop sleeps on a timer that wakes half a frame before the vsync
|
|
17
|
+
// it wants; the frame interval is learnt from back-to-back frames (60 Hz,
|
|
18
|
+
// 120 Hz displays).
|
|
19
|
+
//
|
|
20
|
+
// A subscriber may name a `target` element: it runs only while that element
|
|
21
|
+
// is on screen (one shared IntersectionObserver), and a loop whose every
|
|
22
|
+
// subscriber is off screen requests nothing at all until one comes back.
|
|
23
|
+
//
|
|
12
24
|
// The loop stops while the tab is hidden (document.hidden, body.app-hidden)
|
|
13
25
|
// and freezes while the UI is dragged (body.ui-interacting): subscribers are
|
|
14
26
|
// skipped, and the first frame after either hands each one a dt of at most
|
|
@@ -20,7 +32,7 @@
|
|
|
20
32
|
// pointermove listener and one keydown listener (both capture phase, so a
|
|
21
33
|
// handler that stops propagation cannot hide input from them).
|
|
22
34
|
//
|
|
23
|
-
// subscribe(fn(now, dt), { fps }) → unsubscribe() (unsubscribe.setFps(n) re-caps)
|
|
35
|
+
// subscribe(fn(now, dt), { fps, target }) → unsubscribe() (unsubscribe.setFps(n) re-caps)
|
|
24
36
|
// requestFrames(ms) 60 fps for the next ms
|
|
25
37
|
// isReducedMotion() live prefers-reduced-motion
|
|
26
38
|
// onReducedMotionChange(fn(on)) → unsubscribe()
|
|
@@ -41,8 +53,10 @@
|
|
|
41
53
|
const FRAME_60 = 1000 / 60;
|
|
42
54
|
const SLOP = 4; // ms of rAF jitter a capped subscriber tolerates before it skips a frame
|
|
43
55
|
const RESUME_DT = 50; // the first dt after a stop or a freeze is at most this
|
|
44
|
-
const SLEEP_OVER = 48; // a wait longer than this sleeps on a timer instead of frames
|
|
45
56
|
const POLL_MS = 250; // how often a stopped loop re-checks when no MutationObserver exists
|
|
57
|
+
const PHASE_MS = 1500; // a frame newer than this still tells where the vsyncs fall
|
|
58
|
+
const MIN_FRAME = 4; // ms: the shortest frame interval believed (240 Hz)
|
|
59
|
+
const MAX_FRAME = 34; // ms: the longest (30 Hz)
|
|
46
60
|
const MAX_BOOST = 5000;
|
|
47
61
|
const LISTEN = { passive: true, capture: true };
|
|
48
62
|
|
|
@@ -84,10 +98,73 @@ let pollId = 0;
|
|
|
84
98
|
let boostUntil = -Infinity;
|
|
85
99
|
let watching = false;
|
|
86
100
|
let observer = null;
|
|
101
|
+
let frameMs = FRAME_60; // the display's frame interval, as back-to-back frames show it
|
|
102
|
+
let lastTs = -Infinity; // the last frame's timestamp: where the vsyncs fall
|
|
103
|
+
let inFrame = false; // frame() is running
|
|
104
|
+
let chained = false; // the frame in flight was requested by the previous one, with no wait between
|
|
105
|
+
const counts = { frames: 0, requests: 0, sleeps: 0 }; // for tests and the idle-CPU suite
|
|
87
106
|
|
|
88
107
|
const capFps = fps => Math.max(1, Math.min(60, Number(fps) > 0 ? Number(fps) : 30));
|
|
89
108
|
const boosted = (sub, t) => t < boostUntil && sub.fps >= 24;
|
|
90
109
|
const intervalOf = (sub, t) => (boosted(sub, t) ? FRAME_60 : 1000 / sub.fps);
|
|
110
|
+
/** A subscriber with a target off screen is parked: it is neither called nor waited for. */
|
|
111
|
+
const parked = sub => sub.target && !sub.seen;
|
|
112
|
+
|
|
113
|
+
// ── Targets: one IntersectionObserver for every subscriber that names an element ──
|
|
114
|
+
|
|
115
|
+
let targetIo = null; // undefined while unavailable
|
|
116
|
+
const targetSubs = new Map(); // element → Set of subs
|
|
117
|
+
const targetSeen = new Map(); // element → on screen as last reported (absent until the first report)
|
|
118
|
+
|
|
119
|
+
function targetObserver() {
|
|
120
|
+
if (targetIo !== null) return targetIo;
|
|
121
|
+
const IO = env ? env.IntersectionObserver : globalThis.IntersectionObserver;
|
|
122
|
+
if (typeof IO !== 'function') { targetIo = undefined; return targetIo; }
|
|
123
|
+
try {
|
|
124
|
+
targetIo = new IO((entries) => {
|
|
125
|
+
let woke = false;
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const set = targetSubs.get(entry.target);
|
|
128
|
+
if (!set) continue;
|
|
129
|
+
const on = !!entry.isIntersecting;
|
|
130
|
+
targetSeen.set(entry.target, on);
|
|
131
|
+
for (const sub of set) {
|
|
132
|
+
if (sub.seen === on) continue;
|
|
133
|
+
sub.seen = on;
|
|
134
|
+
if (on) { sub.resume = true; woke = true; }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (woke && subs.size) wakeNow();
|
|
138
|
+
});
|
|
139
|
+
} catch { targetIo = undefined; }
|
|
140
|
+
return targetIo;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function watchTarget(sub) {
|
|
144
|
+
const el = sub.target;
|
|
145
|
+
const io = targetObserver();
|
|
146
|
+
if (!io) { sub.target = null; return; } // no observer: the target counts as on screen
|
|
147
|
+
let set = targetSubs.get(el);
|
|
148
|
+
if (!set) {
|
|
149
|
+
set = new Set();
|
|
150
|
+
targetSubs.set(el, set);
|
|
151
|
+
try { io.observe(el); } catch { targetSubs.delete(el); sub.target = null; return; }
|
|
152
|
+
}
|
|
153
|
+
set.add(sub);
|
|
154
|
+
// Until the observer's first report the target counts as on screen (it draws at once, as before).
|
|
155
|
+
sub.seen = targetSeen.has(el) ? targetSeen.get(el) : true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function unwatchTarget(sub) {
|
|
159
|
+
const el = sub.target;
|
|
160
|
+
const set = el ? targetSubs.get(el) : null;
|
|
161
|
+
if (!set) return;
|
|
162
|
+
set.delete(sub);
|
|
163
|
+
if (set.size) return;
|
|
164
|
+
targetSubs.delete(el);
|
|
165
|
+
targetSeen.delete(el);
|
|
166
|
+
try { targetIo?.unobserve(el); } catch { /* already gone */ }
|
|
167
|
+
}
|
|
91
168
|
|
|
92
169
|
/** Why the loop is not running: '' (it runs), 'hidden' or 'interacting'. */
|
|
93
170
|
export function tickerPaused() {
|
|
@@ -102,17 +179,20 @@ export function tickerPaused() {
|
|
|
102
179
|
|
|
103
180
|
/**
|
|
104
181
|
* Call `fn(now, dt)` from the shared loop, at most `fps` times a second
|
|
105
|
-
* (1-60, default 30).
|
|
106
|
-
*
|
|
182
|
+
* (1-60, default 30). With `target` (an element) it is called only while that
|
|
183
|
+
* element is on screen. Returns unsubscribe(); unsubscribe.setFps(n) changes
|
|
184
|
+
* the cap in place.
|
|
107
185
|
*/
|
|
108
|
-
export function subscribe(fn, { fps = 30 } = {}) {
|
|
186
|
+
export function subscribe(fn, { fps = 30, target = null } = {}) {
|
|
109
187
|
if (typeof fn !== 'function') return Object.assign(() => {}, { setFps() {} });
|
|
110
|
-
const sub = { fn, fps: capFps(fps), last: -1, born: now(), resume: false };
|
|
188
|
+
const sub = { fn, fps: capFps(fps), last: -1, born: now(), resume: false, target: target && typeof target === 'object' ? target : null, seen: true };
|
|
111
189
|
subs.add(sub);
|
|
190
|
+
if (sub.target) watchTarget(sub);
|
|
112
191
|
watch();
|
|
113
192
|
wakeNow();
|
|
114
193
|
const unsubscribe = () => {
|
|
115
194
|
if (!subs.delete(sub)) return;
|
|
195
|
+
unwatchTarget(sub);
|
|
116
196
|
if (!subs.size) halt();
|
|
117
197
|
};
|
|
118
198
|
unsubscribe.setFps = (next) => {
|
|
@@ -138,31 +218,71 @@ function wakeNow() {
|
|
|
138
218
|
schedule();
|
|
139
219
|
}
|
|
140
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Request the next frame a subscriber is due on, and no other: when the next
|
|
223
|
+
* vsync serves it, at once; otherwise a timer wakes half a frame before the
|
|
224
|
+
* vsync it wants. Nothing at all while every subscriber is parked.
|
|
225
|
+
*/
|
|
141
226
|
function schedule() {
|
|
142
227
|
if (rafId || timerId || !subs.size) return;
|
|
143
228
|
const raf = rafFn();
|
|
144
229
|
if (!raf) return;
|
|
145
230
|
if (tickerPaused()) { stopped(); return; }
|
|
146
231
|
const t = now();
|
|
147
|
-
let
|
|
232
|
+
let due = Infinity;
|
|
148
233
|
for (const sub of subs) {
|
|
149
|
-
|
|
150
|
-
|
|
234
|
+
if (parked(sub)) continue;
|
|
235
|
+
const at = sub.last < 0 ? t : sub.last + intervalOf(sub, t) - SLOP;
|
|
236
|
+
if (at < due) due = at;
|
|
151
237
|
}
|
|
152
|
-
if (
|
|
153
|
-
|
|
238
|
+
if (!Number.isFinite(due)) return; // every subscriber is off screen: the observer wakes the loop
|
|
239
|
+
const phase = lastTs > -Infinity && t - lastTs < PHASE_MS ? lastTs : null;
|
|
240
|
+
let lead;
|
|
241
|
+
if (due <= t) lead = 0;
|
|
242
|
+
else if (phase === null) lead = due - t - frameMs; // no recent vsync to count from: the frame before `due`
|
|
243
|
+
else {
|
|
244
|
+
const k = Math.max(1, Math.ceil((due - phase) / frameMs - 1e-6));
|
|
245
|
+
lead = k === 1 ? 0 : phase + (k - 0.5) * frameMs - t; // half a frame before the vsync that serves `due`
|
|
246
|
+
}
|
|
247
|
+
if (lead > 1) {
|
|
248
|
+
counts.sleeps += 1;
|
|
249
|
+
timerId = later(() => { timerId = 0; schedule(); }, lead);
|
|
154
250
|
return;
|
|
155
251
|
}
|
|
252
|
+
counts.requests += 1;
|
|
253
|
+
chained = inFrame;
|
|
156
254
|
rafId = raf(frame);
|
|
157
255
|
}
|
|
158
256
|
|
|
257
|
+
/** Learn the display's frame interval from two frames requested back to back. */
|
|
258
|
+
function learnInterval(ts) {
|
|
259
|
+
if (!chained || !(lastTs > -Infinity)) return;
|
|
260
|
+
const d = ts - lastTs;
|
|
261
|
+
if (!(d >= MIN_FRAME && d <= MAX_FRAME)) return;
|
|
262
|
+
// Snap down to the shortest seen; drift back up slowly (a dropped frame is two, not a slower display).
|
|
263
|
+
frameMs = Math.min(d, Math.min(MAX_FRAME, frameMs + 0.05));
|
|
264
|
+
}
|
|
265
|
+
|
|
159
266
|
function frame(ts) {
|
|
160
267
|
rafId = 0;
|
|
161
268
|
if (!subs.size) return;
|
|
162
269
|
if (tickerPaused()) { stopped(); return; }
|
|
163
270
|
const t = typeof ts === 'number' && Number.isFinite(ts) ? ts : now();
|
|
271
|
+
counts.frames += 1;
|
|
272
|
+
learnInterval(t);
|
|
273
|
+
lastTs = t;
|
|
274
|
+
chained = false;
|
|
275
|
+
inFrame = true;
|
|
276
|
+
try {
|
|
277
|
+
runSubscribers(t);
|
|
278
|
+
schedule(); // inside the frame: a frame requested from here is the next vsync's (it teaches the interval)
|
|
279
|
+
} finally { inFrame = false; }
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function runSubscribers(t) {
|
|
164
283
|
for (const sub of Array.from(subs)) {
|
|
165
284
|
if (!subs.has(sub)) continue; // unsubscribed by an earlier subscriber this frame
|
|
285
|
+
if (parked(sub)) continue;
|
|
166
286
|
const interval = intervalOf(sub, t);
|
|
167
287
|
if (sub.last >= 0 && t - sub.last < interval - SLOP) continue;
|
|
168
288
|
let dt = t - (sub.last >= 0 ? sub.last : sub.born);
|
|
@@ -172,7 +292,6 @@ function frame(ts) {
|
|
|
172
292
|
sub.last = t;
|
|
173
293
|
try { sub.fn(t, dt); } catch (err) { report(err); }
|
|
174
294
|
}
|
|
175
|
-
schedule();
|
|
176
295
|
}
|
|
177
296
|
|
|
178
297
|
/** The loop stopped (hidden) or froze (drag): mark the jump, wait for the watchers. */
|
|
@@ -334,6 +453,17 @@ function reset() {
|
|
|
334
453
|
halt();
|
|
335
454
|
subs.clear();
|
|
336
455
|
boostUntil = -Infinity;
|
|
456
|
+
try { targetIo?.disconnect(); } catch { /* gone */ }
|
|
457
|
+
targetIo = null;
|
|
458
|
+
targetSubs.clear();
|
|
459
|
+
targetSeen.clear();
|
|
460
|
+
frameMs = FRAME_60;
|
|
461
|
+
lastTs = -Infinity;
|
|
462
|
+
inFrame = false;
|
|
463
|
+
chained = false;
|
|
464
|
+
counts.frames = 0;
|
|
465
|
+
counts.requests = 0;
|
|
466
|
+
counts.sleeps = 0;
|
|
337
467
|
const q = motionQuery;
|
|
338
468
|
if (q && motionFns.size) {
|
|
339
469
|
if (q.removeEventListener) q.removeEventListener('change', onMotionQuery);
|
|
@@ -372,5 +502,10 @@ export const __ticker = {
|
|
|
372
502
|
keyListeners: keyFns.size,
|
|
373
503
|
keyAttached: keyOn,
|
|
374
504
|
motionListeners: motionFns.size,
|
|
505
|
+
parked: Array.from(subs).filter(parked).length,
|
|
506
|
+
targets: targetSubs.size,
|
|
507
|
+
frameMs,
|
|
375
508
|
}),
|
|
509
|
+
/** Frames run, frames requested and timer sleeps since the last reset (the idle-CPU suite reads them). */
|
|
510
|
+
counts: () => ({ ...counts }),
|
|
376
511
|
};
|
|
@@ -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
|
+
}
|
|
@@ -11,7 +11,7 @@ export function toolPickerHTML(id, tools, options = {}) {
|
|
|
11
11
|
if (!catalog) return '';
|
|
12
12
|
const view = toolListView(catalog, tools, { translate, ...options });
|
|
13
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 !== '
|
|
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
15
|
}
|
|
16
16
|
export function updateToolPicker(input, tools, options = {}) {
|
|
17
17
|
options = { ...JSON.parse(decodeURIComponent(dropdownOf(input)?.dataset.toolOptions || '%7B%7D')), ...options };
|
|
@@ -20,7 +20,7 @@ export function updateToolPicker(input, tools, options = {}) {
|
|
|
20
20
|
const view = toolListView(catalog, tools, { translate, ...options });
|
|
21
21
|
setDropdownItems(input, view.entries);
|
|
22
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 !== '
|
|
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
24
|
const label = dropdownOf(input)?.querySelector('.cc-dropdown-value');
|
|
25
25
|
if (label) { label.textContent = view.summary; label.title = view.summary; }
|
|
26
26
|
}
|
|
@@ -45,7 +45,7 @@ function groupWord(group, field, translate) {
|
|
|
45
45
|
return group[field];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
export const strictToolHost = provider => provider === 'opencode' || provider === '
|
|
48
|
+
export const strictToolHost = provider => provider === 'opencode' || provider === 'antigravity';
|
|
49
49
|
export const taskToolHost = provider => strictToolHost(provider) || provider === 'claude-code' || provider === 'codex';
|
|
50
50
|
|
|
51
51
|
/** Hidden-input encoding: inheritance differs from an explicit empty group list. */
|
|
@@ -87,7 +87,7 @@ export function toolListView(catalog, tools, { inheritLabel = null, usesBrowser,
|
|
|
87
87
|
});
|
|
88
88
|
if (options.length) entries.push({ group: word(section), options });
|
|
89
89
|
}
|
|
90
|
-
if (includeServers && provider !== '
|
|
90
|
+
if (includeServers && provider !== 'antigravity' && catalog?.externalServersVersion >= 2) {
|
|
91
91
|
const wildcard = refs.includes('mcp:*');
|
|
92
92
|
const rows = (catalog.servers || []).filter(row => row.selectable !== false);
|
|
93
93
|
// A saved unavailable ref stays visible and round-trips; loading a catalog never silently clears it.
|
|
@@ -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,19 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun — Antigravity Panel (barrel re-export)
|
|
3
|
+
// The Antigravity side panel's entry point: one stable surface for the shared
|
|
4
|
+
// UI modules (navbar, tray, detached session windows, the native-loop router,
|
|
5
|
+
// the File Explorer's Send to). Implementation lives in ./agy/.
|
|
6
|
+
// ═══════════════════════════════════════════
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
toggleAntigravityPanel,
|
|
10
|
+
isAntigravityPanelOpen,
|
|
11
|
+
bootAntigravityPanel,
|
|
12
|
+
openAntigravityWithPrompt,
|
|
13
|
+
attachPathToAntigravity,
|
|
14
|
+
attachAntigravityAutomation,
|
|
15
|
+
detachAntigravityAutomation,
|
|
16
|
+
handleAntigravityAutomationEvent,
|
|
17
|
+
antigravityPanelDefaults,
|
|
18
|
+
endHostedAntigravitySessions,
|
|
19
|
+
} from './agy/agy-panel.js';
|
|
@@ -41,6 +41,8 @@ const hosts = createAssistantHosts({
|
|
|
41
41
|
export const registerAssistantHost = (adapter) => hosts.register(adapter);
|
|
42
42
|
export const assistantOwnerOf = (sessionId) => hosts.ownerOf(sessionId);
|
|
43
43
|
export const fetchLiveAssistantSessions = () => hosts.fetchLive();
|
|
44
|
+
/** The same, or null when the list could not be read (the server is starting): saved tabs are kept then. */
|
|
45
|
+
export const readLiveAssistantSessions = () => hosts.readLive();
|
|
44
46
|
export const isAssistantSessionLive = (meta) => hosts.isLive(meta);
|
|
45
47
|
/** opts: { host, brain, resume, label, floating, prompt } */
|
|
46
48
|
export const openAssistant = (opts = {}) => hosts.open(opts);
|
|
@@ -28,6 +28,9 @@ import {
|
|
|
28
28
|
getEffortLevelsForProfile,
|
|
29
29
|
getModelsForProfile,
|
|
30
30
|
isDynamicModelProfile,
|
|
31
|
+
migrateLaunchRecords,
|
|
32
|
+
migrateProviderId,
|
|
33
|
+
migrateProviderModel,
|
|
31
34
|
modelSelectorValue,
|
|
32
35
|
modelMatchesSelector,
|
|
33
36
|
normalizeEffortForProfile,
|
|
@@ -184,7 +187,7 @@ const AS_ICONS = {
|
|
|
184
187
|
// External SVG logos (fill-based, from public/ directory)
|
|
185
188
|
claude: `<svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" fill-rule="evenodd"><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"/></svg>`,
|
|
186
189
|
openai: `<svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" fill-rule="evenodd"><path d="M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"/></svg>`,
|
|
187
|
-
|
|
190
|
+
antigravity: `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 20 12 4l7.5 16"/><path d="M8.2 20a3.8 3.8 0 0 1 7.6 0"/></svg>`,
|
|
188
191
|
pin: _s('<path d="M8 14v-3"/><path d="M4 11h8"/><path d="M10.5 2.5l3 3-2 2 .5 2-4.5.5.5-4.5 2-.5z"/>'),
|
|
189
192
|
|
|
190
193
|
// UI chrome
|
|
@@ -195,8 +198,8 @@ const AS_ICONS = {
|
|
|
195
198
|
export: _s('<path d="M8 2v8M4 6l4-4 4 4"/><path d="M2 11v2a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-2"/>'),
|
|
196
199
|
};
|
|
197
200
|
|
|
198
|
-
/** Resolve icon key → SVG HTML. Falls back to refresh icon for unknown keys. */
|
|
199
|
-
function icon(key) { return AS_ICONS[key] || AS_ICONS.refresh; }
|
|
201
|
+
/** Resolve icon key → SVG HTML. Falls back to refresh icon for unknown keys ('gemini' reads as 'antigravity'). */
|
|
202
|
+
function icon(key) { return AS_ICONS[migrateProviderId(key)] || AS_ICONS.refresh; }
|
|
200
203
|
|
|
201
204
|
/** Icon keys available for template selection (excludes UI-only icons). */
|
|
202
205
|
const ICON_KEYS = Object.keys(AS_ICONS).filter(k => !['back','forward','down','close','export','plus','bolt','blank'].includes(k));
|
|
@@ -205,10 +208,10 @@ const _modelLoadRequests = new Set();
|
|
|
205
208
|
const _modelLoadAttempts = new Set();
|
|
206
209
|
|
|
207
210
|
// Persistent launch preferences (remembered across launches in session)
|
|
208
|
-
let _launchProfile = storage.getItem('as-launch-profile') || 'claude-code';
|
|
211
|
+
let _launchProfile = migrateProviderId(storage.getItem('as-launch-profile') || 'claude-code');
|
|
209
212
|
const _initialLaunchSelection = normalizeAutomationSelection(
|
|
210
|
-
|
|
211
|
-
storage.getItem('as-launch-model'), storage.getItem('as-launch-context-mode'),
|
|
213
|
+
_launchProfile,
|
|
214
|
+
migrateProviderModel(_launchProfile, storage.getItem('as-launch-model')), storage.getItem('as-launch-context-mode'),
|
|
212
215
|
);
|
|
213
216
|
let _launchModel = _initialLaunchSelection.model;
|
|
214
217
|
let _launchContextMode = _initialLaunchSelection.contextMode || 'default';
|
|
@@ -1114,6 +1117,11 @@ function dynamicModelEmptyText(profileId) {
|
|
|
1114
1117
|
? 'No Claude Code models found — check the Claude CLI install in Settings → Terminal.'
|
|
1115
1118
|
: 'Loading Claude Code models...';
|
|
1116
1119
|
}
|
|
1120
|
+
if (profileId === 'antigravity') {
|
|
1121
|
+
return loaded
|
|
1122
|
+
? 'No Antigravity models found — check the Antigravity CLI install in Settings → Terminal.'
|
|
1123
|
+
: 'Loading Antigravity models...';
|
|
1124
|
+
}
|
|
1117
1125
|
return 'No model selection available';
|
|
1118
1126
|
}
|
|
1119
1127
|
|
|
@@ -2338,7 +2346,7 @@ async function loadData() {
|
|
|
2338
2346
|
await fetchToolCatalog();
|
|
2339
2347
|
// One round trip for the three lists (they were asked one after another), then the agents.
|
|
2340
2348
|
const [templates, folders, active] = await Promise.allSettled([fetchLoopTemplates(), fetchLoopFolders(), fetchActiveLoop()]);
|
|
2341
|
-
_templates = templates.status === 'fulfilled' ? templates.value : [];
|
|
2349
|
+
_templates = templates.status === 'fulfilled' ? migrateLaunchRecords(templates.value) : [];
|
|
2342
2350
|
_folders = folders.status === 'fulfilled' ? folders.value : [];
|
|
2343
2351
|
_activeLoop = active.status === 'fulfilled' ? active.value : null;
|
|
2344
2352
|
await refreshAgents();
|
|
@@ -3153,7 +3161,7 @@ async function saveCurrentTemplate() {
|
|
|
3153
3161
|
try {
|
|
3154
3162
|
if (_selected.id) { await updateLoopTemplate(_selected.id, payload); }
|
|
3155
3163
|
else { const result = await createLoopTemplate(payload); if (result?.id) _selected.id = result.id; }
|
|
3156
|
-
_templates = await fetchLoopTemplates();
|
|
3164
|
+
_templates = migrateLaunchRecords(await fetchLoopTemplates());
|
|
3157
3165
|
const updated = _templates.find(t => t.id === _selected.id);
|
|
3158
3166
|
if (updated) _selected = updated;
|
|
3159
3167
|
_originalContent = task;
|
|
@@ -3259,7 +3267,7 @@ async function customizePreset(preset) {
|
|
|
3259
3267
|
};
|
|
3260
3268
|
const result = await createLoopTemplate(payload);
|
|
3261
3269
|
if (result?.id) {
|
|
3262
|
-
_templates = await fetchLoopTemplates();
|
|
3270
|
+
_templates = migrateLaunchRecords(await fetchLoopTemplates());
|
|
3263
3271
|
const newTpl = _templates.find(t => t.id === result.id);
|
|
3264
3272
|
if (newTpl) {
|
|
3265
3273
|
showToast('Customized \u2014 edit and save your copy');
|
|
@@ -4574,9 +4582,9 @@ function wireInputSync(container) {
|
|
|
4574
4582
|
// ═══════════════════════════════════════════
|
|
4575
4583
|
|
|
4576
4584
|
async function loadScheduleData() {
|
|
4577
|
-
try { _schedules = await fetchSchedules(); } catch { _schedules = []; }
|
|
4585
|
+
try { _schedules = migrateLaunchRecords(await fetchSchedules()); } catch { _schedules = []; }
|
|
4578
4586
|
try { _scheduleTimerData = await fetchScheduleTimers(); } catch { _scheduleTimerData = {}; }
|
|
4579
|
-
try { _quickTimers = await fetchQuickTimers(); } catch { _quickTimers = []; }
|
|
4587
|
+
try { _quickTimers = migrateLaunchRecords(await fetchQuickTimers()); } catch { _quickTimers = []; }
|
|
4580
4588
|
}
|
|
4581
4589
|
|
|
4582
4590
|
const CRON_PRESET_GROUPS = [
|
|
@@ -5095,7 +5103,7 @@ function triggerImport() {
|
|
|
5095
5103
|
showToast('Invalid file format'); return;
|
|
5096
5104
|
}
|
|
5097
5105
|
const result = await importLoopTemplates(data);
|
|
5098
|
-
_templates = await fetchLoopTemplates();
|
|
5106
|
+
_templates = migrateLaunchRecords(await fetchLoopTemplates());
|
|
5099
5107
|
renderView();
|
|
5100
5108
|
showToast(`Imported: ${result.added} added, ${result.updated} updated`);
|
|
5101
5109
|
} catch (err) { showToast('Import failed: ' + err.message); }
|