synabun 2.0.0 → 2.0.7
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 +97 -0
- package/NOTICE +5 -0
- package/README.md +2 -1
- package/THIRD-PARTY-LICENSES.md +59 -0
- package/benchmarks/fixtures/browser/README.md +1 -1
- package/benchmarks/fixtures/desktop/README.md +1 -1
- package/docs/whatsapp.md +153 -18
- package/hooks/claude-code/pre-compact.mjs +11 -0
- package/hooks/claude-code/prompt-submit.mjs +60 -184
- package/hooks/claude-code/session-start.mjs +73 -16
- package/hooks/claude-code/shared.mjs +26 -3
- package/hooks/claude-code/stop.mjs +5 -5
- package/lib/child-path.js +303 -0
- package/lib/claude-hooks.js +2 -1
- package/lib/data-home-migration.js +2 -0
- package/lib/desktop-app.js +265 -0
- package/lib/external-tools.js +7 -3
- package/lib/log-redact.js +102 -0
- package/lib/packaged-runtime.js +138 -11
- package/lib/start-launcher.js +88 -1
- package/mcp-server/dist/http.d.ts +3 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +15 -4
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +9 -6
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/budget-judgments.js +153 -0
- package/mcp-server/dist/services/budget-judgments.js.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +41 -4
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +11 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -1
- package/mcp-server/dist/services/identity.js +24 -0
- package/mcp-server/dist/services/identity.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +13 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +34 -2
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +4 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -7
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +34 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
- package/mcp-server/dist/tui.js +2 -1
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/dist/version.d.ts +5 -0
- package/mcp-server/dist/version.d.ts.map +1 -0
- package/mcp-server/dist/version.js +21 -0
- package/mcp-server/dist/version.js.map +1 -0
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/mcp-server/run.mjs +15 -9
- package/mcp-server/src/http.ts +18 -3
- package/mcp-server/src/index.ts +9 -6
- package/mcp-server/src/services/budget-judgments.ts +183 -0
- package/mcp-server/src/services/codex-config-heal.ts +35 -4
- package/mcp-server/src/services/identity.ts +27 -0
- package/mcp-server/src/services/neural-interface.ts +34 -2
- package/mcp-server/src/services/typesafe-config.ts +4 -1
- package/mcp-server/src/tools/agents.ts +33 -14
- package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
- package/mcp-server/src/tui.ts +2 -1
- package/mcp-server/src/version.ts +22 -0
- package/neural-interface/i18n/en.json +2126 -209
- package/neural-interface/i18n/pt-BR.json +2123 -207
- package/neural-interface/lib/account-usage.js +163 -0
- package/neural-interface/lib/assistant-api.js +316 -57
- package/neural-interface/lib/assistant-brains/claude.js +19 -2
- package/neural-interface/lib/assistant-brains/codex.js +3 -0
- package/neural-interface/lib/assistant-brains/opencode.js +17 -4
- package/neural-interface/lib/assistant-budget-planner.js +390 -0
- package/neural-interface/lib/assistant-budget-split.js +408 -0
- package/neural-interface/lib/assistant-budget.js +94 -95
- package/neural-interface/lib/assistant-catalog.js +179 -27
- package/neural-interface/lib/assistant-config.js +91 -14
- package/neural-interface/lib/assistant-dispatch.js +494 -138
- package/neural-interface/lib/assistant-hidden-models.js +393 -66
- package/neural-interface/lib/assistant-jev.js +26 -3
- package/neural-interface/lib/assistant-memory.js +24 -10
- package/neural-interface/lib/assistant-persona.js +73 -12
- package/neural-interface/lib/assistant-plan-permissions.js +8 -1
- package/neural-interface/lib/assistant-pricing.js +21 -6
- package/neural-interface/lib/assistant-route-accounts.js +14 -0
- package/neural-interface/lib/assistant-route-gate.js +19 -3
- package/neural-interface/lib/assistant-router.js +373 -42
- package/neural-interface/lib/assistant-runtime.js +488 -59
- package/neural-interface/lib/assistant-task-prompt.js +13 -3
- package/neural-interface/lib/assistant-test-density.js +142 -0
- package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
- package/neural-interface/lib/assistant-user-context.js +908 -0
- package/neural-interface/lib/assistant-user-knowledge.js +328 -0
- package/neural-interface/lib/assistant-user-learn.js +404 -0
- package/neural-interface/lib/assistant-user-threads.js +226 -0
- package/neural-interface/lib/assistant-user-writer.js +183 -0
- package/neural-interface/lib/augmented-path.js +317 -53
- package/neural-interface/lib/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-accounts.js +342 -31
- package/neural-interface/lib/claude-agent-bridge.js +123 -9
- package/neural-interface/lib/claude-executable.js +6 -1
- package/neural-interface/lib/claude-model-catalog.js +33 -5
- package/neural-interface/lib/claude-panel-auth.js +221 -0
- package/neural-interface/lib/claude-profile-api-key.js +62 -0
- package/neural-interface/lib/claude-temporary.js +46 -7
- package/neural-interface/lib/cli-install-api.js +137 -0
- package/neural-interface/lib/cli-install.js +797 -0
- package/neural-interface/lib/cli-path.js +130 -0
- package/neural-interface/lib/cli-resolver.js +744 -0
- package/neural-interface/lib/cli-update-planner.js +143 -7
- package/neural-interface/lib/cloudflared/install.js +533 -0
- package/neural-interface/lib/cloudflared/manager.js +545 -0
- package/neural-interface/lib/cloudflared/pins.js +115 -0
- package/neural-interface/lib/cloudflared/pins.json +63 -0
- package/neural-interface/lib/cloudflared/tunnel.js +265 -0
- package/neural-interface/lib/codex-account-auth.js +178 -0
- package/neural-interface/lib/codex-accounts.js +489 -0
- package/neural-interface/lib/codex-capabilities.js +2 -1
- package/neural-interface/lib/codex-compat-rpc.js +8 -2
- package/neural-interface/lib/codex-mcp-approvals.js +5 -1
- package/neural-interface/lib/codex-panel-auth.js +62 -0
- package/neural-interface/lib/codex-session-settings.js +1 -1
- package/neural-interface/lib/codex-settings-schema.js +120 -0
- package/neural-interface/lib/desktop/config.js +3 -0
- package/neural-interface/lib/editor-completion-endpoint.js +264 -0
- package/neural-interface/lib/editor-completion-opencode.js +436 -0
- package/neural-interface/lib/editor-completion.js +714 -0
- package/neural-interface/lib/editor-config.js +149 -0
- package/neural-interface/lib/editor-files-api.js +268 -0
- package/neural-interface/lib/editor-git-api.js +134 -0
- package/neural-interface/lib/file-explorer-api.js +1039 -0
- package/neural-interface/lib/file-explorer-system.js +355 -0
- package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
- package/neural-interface/lib/file-explorer-watch.js +239 -0
- package/neural-interface/lib/git-bash/bzip2.js +339 -0
- package/neural-interface/lib/git-bash/claude-settings.js +73 -0
- package/neural-interface/lib/git-bash/extract-worker.js +34 -0
- package/neural-interface/lib/git-bash/install.js +529 -0
- package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
- package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
- package/neural-interface/lib/git-bash/manager.js +268 -0
- package/neural-interface/lib/git-bash/pins.js +206 -0
- package/neural-interface/lib/git-bash/pins.json +34 -0
- package/neural-interface/lib/git-bash/resolver.js +194 -0
- package/neural-interface/lib/git-diff-api.js +103 -0
- package/neural-interface/lib/git-read.js +234 -0
- package/neural-interface/lib/greeting/api.js +89 -0
- package/neural-interface/lib/greeting/budgets.js +90 -0
- package/neural-interface/lib/greeting/engine.js +461 -0
- package/neural-interface/lib/greeting/facts.js +320 -0
- package/neural-interface/lib/greeting/sources.js +252 -0
- package/neural-interface/lib/greeting/writer.js +139 -0
- package/neural-interface/lib/http-guards.js +189 -13
- package/neural-interface/lib/install-details.js +145 -0
- package/neural-interface/lib/machine-names.js +88 -0
- package/neural-interface/lib/mcp-installer.js +14 -2
- package/neural-interface/lib/memory-api.js +31 -7
- package/neural-interface/lib/native-loop-providers.js +26 -8
- package/neural-interface/lib/native-loop-runtime.js +9 -4
- package/neural-interface/lib/os-path.js +319 -0
- package/neural-interface/lib/plugin-installer.js +4 -2
- package/neural-interface/lib/project-storage.js +5 -7
- package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
- package/neural-interface/lib/pty-host/core.js +2 -1
- package/neural-interface/lib/pty-host/manager.js +27 -2
- package/neural-interface/lib/remote-policy.js +20 -11
- package/neural-interface/lib/request-gate.js +589 -0
- package/neural-interface/lib/session-title-generator.js +4 -3
- package/neural-interface/lib/system-about.js +340 -0
- package/neural-interface/lib/system-activity.js +66 -0
- package/neural-interface/lib/terminal-env.js +11 -3
- package/neural-interface/lib/terminal-path.js +55 -0
- package/neural-interface/lib/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/lib/virtual-socket.js +12 -1
- package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
- package/neural-interface/lib/whatsapp/bridge.js +78 -34
- package/neural-interface/lib/whatsapp/commands.js +13 -14
- package/neural-interface/lib/whatsapp/config.js +134 -20
- package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
- package/neural-interface/lib/whatsapp/host-core.js +168 -35
- package/neural-interface/lib/whatsapp/inbound.js +5 -3
- package/neural-interface/lib/whatsapp/local-file.js +524 -0
- package/neural-interface/lib/whatsapp/manager.js +92 -32
- package/neural-interface/lib/whatsapp/paths.js +11 -1
- package/neural-interface/lib/whatsapp/protocol.js +65 -5
- package/neural-interface/lib/whatsapp/redact.js +63 -0
- package/neural-interface/lib/whatsapp/service.js +343 -91
- package/neural-interface/lib/whatsapp/transcription.js +463 -0
- package/neural-interface/package-lock.json +701 -2
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/index.html +2 -0
- package/neural-interface/public/index2d.html +2 -0
- package/neural-interface/public/install-app.html +9 -6
- package/neural-interface/public/offline.html +19 -3
- package/neural-interface/public/onboarding.html +107 -2
- package/neural-interface/public/shared/account-i18n.js +7 -0
- package/neural-interface/public/shared/account-menu.js +539 -0
- package/neural-interface/public/shared/account-usage.js +19 -0
- package/neural-interface/public/shared/account-view.js +335 -0
- package/neural-interface/public/shared/agent-runtime-options.js +50 -14
- package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
- package/neural-interface/public/shared/assistant/asst-api.js +32 -2
- package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +430 -81
- package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
- package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
- package/neural-interface/public/shared/assistant/asst-mascot.js +140 -61
- package/neural-interface/public/shared/assistant/asst-menu.js +27 -11
- package/neural-interface/public/shared/assistant/asst-panel.js +198 -42
- package/neural-interface/public/shared/assistant/asst-render.js +197 -23
- package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
- package/neural-interface/public/shared/assistant/asst-route.js +95 -343
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +534 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
- package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
- package/neural-interface/public/shared/assistant/asst-state.js +186 -2
- package/neural-interface/public/shared/assistant/asst-styles.js +247 -11
- package/neural-interface/public/shared/blob-store.js +111 -22
- package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
- package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
- package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +80 -118
- package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
- package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +164 -107
- package/neural-interface/public/shared/cdx/cdx-tabs.js +348 -668
- package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
- package/neural-interface/public/shared/claude-account-view.js +3 -0
- package/neural-interface/public/shared/cli-install-view.js +392 -0
- package/neural-interface/public/shared/cli-status.js +282 -22
- package/neural-interface/public/shared/constants.js +6 -1
- package/neural-interface/public/shared/cp/cp-events.js +2 -1
- package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +61 -0
- package/neural-interface/public/shared/desktop-bridge.js +39 -0
- package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
- package/neural-interface/public/shared/desktop-titlebar.js +153 -0
- package/neural-interface/public/shared/desktop-update-view.js +462 -0
- package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
- package/neural-interface/public/shared/editor/editor-ai.js +619 -0
- package/neural-interface/public/shared/editor/editor-commands.js +212 -0
- package/neural-interface/public/shared/editor/editor-compare.js +103 -0
- package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
- package/neural-interface/public/shared/editor/editor-doc.js +257 -0
- package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
- package/neural-interface/public/shared/editor/editor-git.js +95 -0
- package/neural-interface/public/shared/editor/editor-languages.js +156 -0
- package/neural-interface/public/shared/editor/editor-lint.js +229 -0
- package/neural-interface/public/shared/editor/editor-loader.js +51 -0
- package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
- package/neural-interface/public/shared/editor/editor-menu.js +233 -0
- package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
- package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
- package/neural-interface/public/shared/editor/editor-palette.js +125 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
- package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
- package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
- package/neural-interface/public/shared/editor/editor-safety.js +500 -0
- package/neural-interface/public/shared/editor/editor-search.js +352 -0
- package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
- package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
- package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
- package/neural-interface/public/shared/editor/editor-theme.js +244 -0
- package/neural-interface/public/shared/editor/editor-view.js +332 -0
- package/neural-interface/public/shared/explorer/fx-api.js +216 -0
- package/neural-interface/public/shared/explorer/fx-links.js +204 -0
- package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
- package/neural-interface/public/shared/explorer/fx-main.js +865 -0
- package/neural-interface/public/shared/explorer/fx-names.js +87 -0
- package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
- package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
- package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
- package/neural-interface/public/shared/file-links.js +339 -0
- package/neural-interface/public/shared/git-bash-view.js +145 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
- package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
- package/neural-interface/public/shared/html-shell.js +161 -165
- package/neural-interface/public/shared/i18n.js +19 -1
- package/neural-interface/public/shared/install-details-view.js +86 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +131 -17
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +22 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +158 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
- package/neural-interface/public/shared/pwa-install-page.js +32 -2
- package/neural-interface/public/shared/pwa-install.css +3 -3
- package/neural-interface/public/shared/pwa-install.js +100 -1
- package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
- package/neural-interface/public/shared/settings/settings-about.js +254 -0
- package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
- package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
- package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
- package/neural-interface/public/shared/settings/settings-ia.js +33 -4
- package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
- package/neural-interface/public/shared/showcase-privacy.js +489 -0
- package/neural-interface/public/shared/start-bridge.js +238 -19
- package/neural-interface/public/shared/storage.js +30 -3
- package/neural-interface/public/shared/styles.css +1710 -770
- package/neural-interface/public/shared/synabun-mascot.js +68 -58
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +369 -229
- package/neural-interface/public/shared/ui-cli-banner.js +355 -0
- package/neural-interface/public/shared/ui-detail.js +15 -0
- package/neural-interface/public/shared/ui-explorer.js +22 -0
- package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
- package/neural-interface/public/shared/ui-file-links.js +103 -0
- package/neural-interface/public/shared/ui-git-bash.js +124 -0
- package/neural-interface/public/shared/ui-help.js +26 -0
- package/neural-interface/public/shared/ui-invite.js +126 -116
- package/neural-interface/public/shared/ui-judgments.js +10 -1
- package/neural-interface/public/shared/ui-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +187 -19
- package/neural-interface/public/shared/ui-menubar.js +25 -33
- package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
- package/neural-interface/public/shared/ui-navbar.js +48 -22
- package/neural-interface/public/shared/ui-provider-auth.js +104 -0
- package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
- package/neural-interface/public/shared/ui-sessions.js +9 -3
- package/neural-interface/public/shared/ui-settings.js +509 -490
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
- package/neural-interface/public/shared/ui-sync.js +22 -0
- package/neural-interface/public/shared/ui-terminal.js +40 -5
- package/neural-interface/public/shared/ui-tool-updates.js +5 -0
- package/neural-interface/public/shared/ui-tunnel.js +130 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
- package/neural-interface/public/shared/ui-update.js +594 -5
- package/neural-interface/public/shared/ui-whatsapp.js +21 -6
- package/neural-interface/public/shared/ui-whiteboard.js +12 -0
- package/neural-interface/public/shared/ui-worker-end.js +245 -0
- package/neural-interface/public/shared/ui-workspaces.js +41 -27
- package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
- package/neural-interface/public/shared/worker-end.js +253 -0
- package/neural-interface/public/sw.js +2 -2
- package/neural-interface/public/variant/2d/main.js +10 -1
- package/neural-interface/public/variant/3d/main.js +10 -1
- package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
- package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
- package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
- package/neural-interface/scripts/build-vendor.mjs +78 -2
- package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
- package/neural-interface/server.js +2085 -1629
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +5 -8
- package/setup.js +53 -15
- package/benchmarks/browser-live-results.json +0 -79
- package/benchmarks/browser-v2-results.json +0 -258
- package/neural-interface/lib/codex-capabilities.d.ts +0 -41
- package/neural-interface/public/category-logos/claude.svg +0 -1
- package/neural-interface/public/category-logos/gemini-color.svg +0 -1
- package/neural-interface/public/category-logos/openai.svg +0 -1
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude.svg +0 -1
- package/neural-interface/public/gallery.svg +0 -6
- package/neural-interface/public/leonardoai.svg +0 -1
- package/neural-interface/public/mcp.svg +0 -4
- package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
- package/neural-interface/public/pin-svgrepo-com.svg +0 -25
- package/neural-interface/public/sessionicon.svg +0 -8
- package/neural-interface/public/toolbar-album.svg +0 -8
- package/neural-interface/public/toolbar-question.svg +0 -6
- package/neural-interface/public/toolbar-sessions.svg +0 -6
- package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// send/stop) · file input. The other runtime controls live in the toolbar.
|
|
13
13
|
|
|
14
14
|
import { matchSlashCommands, SLASH_COMMANDS } from './asst-slash.js';
|
|
15
|
+
import { isLongPaste, typedText } from './asst-automation.js';
|
|
15
16
|
|
|
16
17
|
const TEXT_EXTENSIONS = new Set([
|
|
17
18
|
'txt', 'md', 'js', 'ts', 'jsx', 'tsx', 'json', 'html', 'css', 'scss', 'less', 'xml', 'svg',
|
|
@@ -151,6 +152,7 @@ export function createComposer(hostEl, hooks = {}) {
|
|
|
151
152
|
files: [], // { name, content }
|
|
152
153
|
uploads: [], // { name, size, mime, path, status: 'uploading'|'done', progress, controller }
|
|
153
154
|
memories: [], // node objects
|
|
155
|
+
pastes: [], // long text pastes still to be told apart from typed words (asst-automation.js typedText)
|
|
154
156
|
slashOpen: false,
|
|
155
157
|
slashIndex: 0,
|
|
156
158
|
slashItems: [],
|
|
@@ -321,6 +323,9 @@ export function createComposer(hostEl, hooks = {}) {
|
|
|
321
323
|
if (!text && !state.images.length && !state.files.length && !state.uploads.length && !state.memories.length) return;
|
|
322
324
|
const payload = {
|
|
323
325
|
text,
|
|
326
|
+
// What the user typed, without the long pastes: all SynaBun may learn about them from (the prompt keeps everything).
|
|
327
|
+
typed: typedText(text, state.pastes),
|
|
328
|
+
pastes: state.pastes.slice(),
|
|
324
329
|
images: state.images.slice(),
|
|
325
330
|
files: state.files.slice(),
|
|
326
331
|
uploads: state.uploads.map(({ name, size, mime, path }) => ({ name, size, mime, path })),
|
|
@@ -334,6 +339,7 @@ export function createComposer(hostEl, hooks = {}) {
|
|
|
334
339
|
state.files = [];
|
|
335
340
|
state.uploads = [];
|
|
336
341
|
state.memories = [];
|
|
342
|
+
state.pastes = [];
|
|
337
343
|
renderAttachments();
|
|
338
344
|
closeSlash();
|
|
339
345
|
autoResize();
|
|
@@ -409,9 +415,12 @@ export function createComposer(hostEl, hooks = {}) {
|
|
|
409
415
|
return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
|
|
410
416
|
}
|
|
411
417
|
|
|
412
|
-
// ── Paste (images) ──
|
|
418
|
+
// ── Paste (images; long text is remembered as pasted, not typed) ──
|
|
413
419
|
textarea.addEventListener('paste', (e) => {
|
|
414
420
|
if (!e.clipboardData) return;
|
|
421
|
+
let pasted = '';
|
|
422
|
+
try { pasted = e.clipboardData.getData?.('text/plain') || ''; } catch { pasted = ''; }
|
|
423
|
+
if (isLongPaste(pasted)) state.pastes = [...state.pastes, pasted].slice(-20);
|
|
415
424
|
for (const item of e.clipboardData.items) {
|
|
416
425
|
if (item.type.startsWith('image/')) {
|
|
417
426
|
const blob = item.getAsFile();
|
|
@@ -596,6 +605,7 @@ export function createComposer(hostEl, hooks = {}) {
|
|
|
596
605
|
state.files.push(...(payload.files || []));
|
|
597
606
|
state.uploads.push(...(payload.uploads || []).map((u) => ({ ...u, status: 'done', progress: 1 })));
|
|
598
607
|
state.memories.push(...(payload.memories || []));
|
|
608
|
+
state.pastes = [...state.pastes, ...(payload.pastes || [])].slice(-20);
|
|
599
609
|
renderAttachments();
|
|
600
610
|
autoResize();
|
|
601
611
|
updateSlash();
|
|
@@ -12,20 +12,25 @@
|
|
|
12
12
|
// success, error once, when a turn that did real work ends (then idle)
|
|
13
13
|
// watch while you type: eyes on the caret column, look() at most
|
|
14
14
|
// every 120 ms; back 1.5 s after the last key, at once on send
|
|
15
|
+
// project/budget attention owned by this panel's empty-state chip/menu;
|
|
16
|
+
// commits react once; a menu prevents idle sleep
|
|
15
17
|
// sleep the hero only, after 90 s with no input while nothing runs;
|
|
16
18
|
// the rig wakes itself on a pointer move or a key
|
|
17
19
|
//
|
|
18
20
|
// Anything else is the renderer's pose: the hero idles, the "Thinking" row's
|
|
19
21
|
// character thinks, the stage acts out its call. A pose the director sets is
|
|
20
22
|
// held: the renderer leaves it alone until the director lets go and asks it
|
|
21
|
-
// to restore its own.
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
23
|
+
// to restore its own. A director knows its own panel only: nothing in this
|
|
24
|
+
// module is shared between directors, so every open session dresses and
|
|
25
|
+
// animates its own character at the same time as every other one (a rig that
|
|
26
|
+
// is off screen parks itself: synabun-mascot.js). Pure logic: the clock,
|
|
27
|
+
// timers and page input come in through `env`, so node:test drives it with
|
|
28
|
+
// fakes (tests/assistant-mascot.test.mjs).
|
|
25
29
|
|
|
26
30
|
export const MASCOT_TIMING = Object.freeze({
|
|
27
31
|
watchEveryMs: 120,
|
|
28
32
|
watchIdleMs: 1500,
|
|
33
|
+
controlDwellMs: 1500,
|
|
29
34
|
sleepAfterMs: 90_000,
|
|
30
35
|
realWorkMs: 3000,
|
|
31
36
|
oneShotMs: Object.freeze({ success: 1000, error: 900 }),
|
|
@@ -60,32 +65,19 @@ export function lookToward(box, point, { horizontal = false } = {}) {
|
|
|
60
65
|
return { x: unit((vx / d) * m), y: unit((vy / d) * m) };
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
// ── One panel animates: the visible one used last ──
|
|
64
|
-
const directors = new Set();
|
|
65
|
-
let lead = null;
|
|
66
|
-
let seq = 0;
|
|
67
|
-
|
|
68
|
-
function elect() {
|
|
69
|
-
let best = null;
|
|
70
|
-
for (const d of directors) if (d.visible() && (!best || d.activeAt() > best.activeAt())) best = d;
|
|
71
|
-
if (!best) for (const d of directors) if (!best || d.activeAt() > best.activeAt()) best = d;
|
|
72
|
-
if (best === lead) return;
|
|
73
|
-
const prev = lead;
|
|
74
|
-
lead = best;
|
|
75
|
-
prev?.leadChanged();
|
|
76
|
-
best?.leadChanged();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
68
|
/**
|
|
80
|
-
* createMascotDirector({ getTarget, caret,
|
|
81
|
-
* getTarget() → the renderer's visible mascot { kind: 'hero'|'stage',
|
|
82
|
-
* parked?(), hold(on), restore() } or null; caret() → the caret's
|
|
83
|
-
* point or null
|
|
84
|
-
*
|
|
69
|
+
* createMascotDirector({ getTarget, caret, env })
|
|
70
|
+
* getTarget() → the renderer's visible mascot { kind: 'hero'|'stage'|'working',
|
|
71
|
+
* rig, el, parked?(), hold(on), restore() } or null; caret() → the caret's
|
|
72
|
+
* client point or null.
|
|
73
|
+
* Control API: attend(owner, { pose, rectOf, options, open }), leave(owner),
|
|
74
|
+
* controlCommitted({ pose, options, reaction }); type(present, pointOf?) also
|
|
75
|
+
* watches a budget amount field using the same throttling as the composer.
|
|
85
76
|
* env: { now, setTimeout, clearTimeout, input(fn) → unsubscribe (page pointer
|
|
86
77
|
* and key input), lastInputAt() }.
|
|
78
|
+
* All of its state is its own: one director per panel, any number at once.
|
|
87
79
|
*/
|
|
88
|
-
export function createMascotDirector({ getTarget = () => null, caret = () => null,
|
|
80
|
+
export function createMascotDirector({ getTarget = () => null, caret = () => null, env = {} } = {}) {
|
|
89
81
|
const now = env.now || (() => Date.now());
|
|
90
82
|
const later = env.setTimeout || ((fn, ms) => setTimeout(fn, ms));
|
|
91
83
|
const cancel = env.clearTimeout || ((id) => clearTimeout(id));
|
|
@@ -97,6 +89,9 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
97
89
|
let holding = false; // hold(true) is in force on `target`
|
|
98
90
|
let shown = ''; // the pose (and then) set on `target`
|
|
99
91
|
let typing = false;
|
|
92
|
+
let typingPoint = null;
|
|
93
|
+
let attention = null; // { owner, pose, rectOf, options, open }; this panel's empty-state control
|
|
94
|
+
let attentionTimer = 0;
|
|
100
95
|
let typingTimer = 0;
|
|
101
96
|
let lookTimer = 0;
|
|
102
97
|
let lookedAt = -Infinity;
|
|
@@ -108,7 +103,6 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
108
103
|
let sleepTimer = 0;
|
|
109
104
|
let lastInput = now();
|
|
110
105
|
let stopInput = null;
|
|
111
|
-
let activeAt = (seq += 1);
|
|
112
106
|
|
|
113
107
|
const safe = (fn) => { try { return fn(); } catch { return undefined; } };
|
|
114
108
|
const boxOf = (t) => safe(() => t.el?.getBoundingClientRect?.()) || null;
|
|
@@ -121,9 +115,16 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
121
115
|
const point = card && card.width ? { x: card.left + Math.min(card.width * 0.3, 160), y: card.top + Math.min(card.height / 2, 28) } : null;
|
|
122
116
|
return { pose: 'blocked', look: lookToward(boxOf(t), point) };
|
|
123
117
|
}
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
const attentionLook = () => {
|
|
119
|
+
const rect = attention && safe(attention.rectOf);
|
|
120
|
+
return lookToward(boxOf(t), rect && { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 });
|
|
121
|
+
};
|
|
122
|
+
if (oneShot && oneShot.target === t) return { pose: oneShot.pose, opts: oneShot.opts || { then: 'idle' }, ...(attention ? { look: attentionLook() } : {}) };
|
|
123
|
+
if (typing) return { pose: 'watch', look: lookToward(boxOf(t), safe(typingPoint || caret), { horizontal: true }) };
|
|
126
124
|
if (sleeping && t.kind === 'hero' && !safe(() => t.parked?.())) return { pose: 'sleep' };
|
|
125
|
+
if (attention && t.kind === 'hero' && !safe(() => t.parked?.())) {
|
|
126
|
+
return { pose: attention.pose, opts: safe(attention.options) || {}, look: attentionLook() };
|
|
127
|
+
}
|
|
127
128
|
return null;
|
|
128
129
|
}
|
|
129
130
|
|
|
@@ -151,7 +152,7 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
151
152
|
return;
|
|
152
153
|
}
|
|
153
154
|
if (!holding) { holding = true; safe(() => t.hold(true)); }
|
|
154
|
-
const key = `${want.pose}|${want.opts?.then || ''}`;
|
|
155
|
+
const key = `${want.pose}|${want.opts?.then || ''}|${!!want.opts?.unlimited}`;
|
|
155
156
|
if (key !== shown) { shown = key; safe(() => t.rig.setPose(want.pose, want.opts)); }
|
|
156
157
|
if (want.look) safe(() => t.rig.look(want.look.x, want.look.y));
|
|
157
158
|
}
|
|
@@ -170,7 +171,7 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
170
171
|
|
|
171
172
|
function canSleep() {
|
|
172
173
|
const t = target;
|
|
173
|
-
return !destroyed && !!t && t.kind === 'hero' && !safe(() => t.parked?.()) && !turnActive && !typing && !blocked && !offline && !oneShot;
|
|
174
|
+
return !destroyed && !!t && t.kind === 'hero' && !safe(() => t.parked?.()) && !turnActive && !typing && !attention?.open && !blocked && !offline && !oneShot;
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
function armSleep() {
|
|
@@ -192,18 +193,20 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
192
193
|
if (lookTimer) { cancel(lookTimer); lookTimer = 0; }
|
|
193
194
|
if (!typing) return;
|
|
194
195
|
typing = false;
|
|
196
|
+
typingPoint = null;
|
|
195
197
|
apply();
|
|
196
198
|
armSleep();
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
/** The draft changed: `present` false (an empty draft) ends the watch. */
|
|
200
|
-
function type(present = true) {
|
|
202
|
+
function type(present = true, pointOf = null) {
|
|
201
203
|
if (destroyed) return;
|
|
202
|
-
touch();
|
|
203
204
|
noteInput();
|
|
204
205
|
if (!present) { stopTyping(); return; }
|
|
206
|
+
if (oneShot?.control) dropOneShot(); // a new edit resumes watching after an acknowledgement
|
|
205
207
|
const first = !typing;
|
|
206
208
|
typing = true;
|
|
209
|
+
typingPoint = typeof pointOf === 'function' ? pointOf : null;
|
|
207
210
|
if (sleepTimer) { cancel(sleepTimer); sleepTimer = 0; }
|
|
208
211
|
if (typingTimer) cancel(typingTimer);
|
|
209
212
|
typingTimer = later(() => { typingTimer = 0; stopTyping(); }, MASCOT_TIMING.watchIdleMs);
|
|
@@ -237,27 +240,53 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
237
240
|
armSleep();
|
|
238
241
|
}
|
|
239
242
|
|
|
240
|
-
function
|
|
241
|
-
|
|
242
|
-
|
|
243
|
+
function clearAttention() {
|
|
244
|
+
if (attentionTimer) { cancel(attentionTimer); attentionTimer = 0; }
|
|
245
|
+
attention = null;
|
|
243
246
|
}
|
|
244
247
|
|
|
245
|
-
const self = {
|
|
246
|
-
visible: () => !destroyed && safe(isVisible) !== false,
|
|
247
|
-
activeAt: () => activeAt,
|
|
248
|
-
leadChanged() { if (!destroyed) safe(() => setEnabled(lead === self)); },
|
|
249
|
-
};
|
|
250
|
-
directors.add(self);
|
|
251
|
-
touch();
|
|
252
|
-
if (lead !== self) self.leadChanged();
|
|
253
|
-
|
|
254
248
|
return {
|
|
255
249
|
/** The draft changed (typing): the mascot watches the caret column. */
|
|
256
250
|
type,
|
|
257
251
|
/** Blur, or the draft went away. */
|
|
258
252
|
stopTyping,
|
|
253
|
+
/** Chip previews relax after a short dwell; only open menus hold attention and block sleep. */
|
|
254
|
+
attend(owner, spec) {
|
|
255
|
+
if (destroyed || (attention?.open && attention.owner !== owner && !spec.open)) return;
|
|
256
|
+
noteInput();
|
|
257
|
+
clearAttention();
|
|
258
|
+
attention = { owner, ...spec };
|
|
259
|
+
if (!attention.open) attentionTimer = later(() => {
|
|
260
|
+
clearAttention();
|
|
261
|
+
apply();
|
|
262
|
+
armSleep();
|
|
263
|
+
}, MASCOT_TIMING.controlDwellMs);
|
|
264
|
+
apply();
|
|
265
|
+
armSleep();
|
|
266
|
+
},
|
|
267
|
+
leave(owner) {
|
|
268
|
+
if (attention?.owner !== owner) return;
|
|
269
|
+
clearAttention();
|
|
270
|
+
apply();
|
|
271
|
+
armSleep();
|
|
272
|
+
},
|
|
273
|
+
/** Only acknowledged user commits call this; loads, live updates and keystrokes do not. */
|
|
274
|
+
controlCommitted({ pose, options = {}, reaction = 'nod' }) {
|
|
275
|
+
if (destroyed) return;
|
|
276
|
+
const t = safe(getTarget);
|
|
277
|
+
if (!t || t.kind !== 'hero' || safe(() => t.parked?.()) || turnActive || offline || blocked) return;
|
|
278
|
+
stopTyping();
|
|
279
|
+
noteInput();
|
|
280
|
+
dropOneShot();
|
|
281
|
+
const shot = { pose, opts: options, target: t, timer: 0, control: true };
|
|
282
|
+
shot.timer = later(() => { if (oneShot !== shot) return; oneShot = null; apply(); armSleep(); }, 900);
|
|
283
|
+
oneShot = shot;
|
|
284
|
+
apply();
|
|
285
|
+
safe(() => t.rig.react(reaction));
|
|
286
|
+
armSleep();
|
|
287
|
+
},
|
|
259
288
|
/** A prompt went out: the watch hands over at once (the renderer gives the hero to the "Thinking" row). */
|
|
260
|
-
sent() {
|
|
289
|
+
sent() { clearAttention(); dropOneShot(); stopTyping(); apply(); armSleep(); },
|
|
261
290
|
/** A card waits on the user (`rectOf()` → its box), or none (null). */
|
|
262
291
|
setBlocked(rectOf) {
|
|
263
292
|
blocked = typeof rectOf === 'function' ? rectOf : null;
|
|
@@ -278,6 +307,7 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
278
307
|
},
|
|
279
308
|
turnStarted() {
|
|
280
309
|
turnActive = true;
|
|
310
|
+
clearAttention();
|
|
281
311
|
dropOneShot();
|
|
282
312
|
if (sleeping) sleeping = false;
|
|
283
313
|
apply();
|
|
@@ -285,29 +315,78 @@ export function createMascotDirector({ getTarget = () => null, caret = () => nul
|
|
|
285
315
|
},
|
|
286
316
|
/** The turn ended with `pose` ('success' | 'error' | null): played once on the rig on screen. */
|
|
287
317
|
turnEnded,
|
|
288
|
-
/** The renderer's visible mascot changed
|
|
289
|
-
retarget() {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (t && t !== target && t.kind === 'stage') touch();
|
|
293
|
-
apply();
|
|
294
|
-
},
|
|
295
|
-
/** The user is here (focus, a click): this panel animates. */
|
|
296
|
-
touch() { touch(); noteInput(); },
|
|
297
|
-
/** The host showed or hid the panel. */
|
|
298
|
-
visibilityChanged() { elect(); },
|
|
299
|
-
isLead: () => lead === self,
|
|
318
|
+
/** The renderer's visible mascot changed. */
|
|
319
|
+
retarget() { apply(); },
|
|
320
|
+
/** The user is here (focus, a click): a sleeping hero wakes, the quiet starts over. */
|
|
321
|
+
touch() { if (!destroyed) noteInput(); },
|
|
300
322
|
/** For tests and devtools: what the director holds right now. */
|
|
301
|
-
state: () => ({ target: target?.kind || null, pose: shown.split('|')[0] || null, typing, blocked: !!blocked, offline, sleeping, oneShot: oneShot?.pose || null
|
|
323
|
+
state: () => ({ target: target?.kind || null, pose: shown.split('|')[0] || null, typing, attention: attention?.pose || null, menuOpen: !!attention?.open, blocked: !!blocked, offline, sleeping, oneShot: oneShot?.pose || null }),
|
|
302
324
|
destroy() {
|
|
303
325
|
if (destroyed) return;
|
|
304
326
|
if (target && holding) safe(() => target.hold(false));
|
|
305
327
|
destroyed = true;
|
|
328
|
+
clearAttention();
|
|
306
329
|
for (const id of [typingTimer, lookTimer, sleepTimer]) if (id) cancel(id);
|
|
307
330
|
dropOneShot();
|
|
308
331
|
if (stopInput) { safe(stopInput); stopInput = null; }
|
|
309
|
-
|
|
310
|
-
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Wire one empty-state chip and its body-level menu to its panel's director. No rig or clock here. */
|
|
337
|
+
export function createMascotControl(anchor, { director = () => null, pose, options = () => ({}) } = {}) {
|
|
338
|
+
const owner = {};
|
|
339
|
+
let menu = null, preview = null, watched = false, destroyed = false;
|
|
340
|
+
const listeners = [];
|
|
341
|
+
const listen = (node, event, fn) => { node.addEventListener(event, fn); listeners.push(() => node.removeEventListener(event, fn)); };
|
|
342
|
+
function attend(node = anchor) {
|
|
343
|
+
if (destroyed) return;
|
|
344
|
+
preview = node;
|
|
345
|
+
director()?.attend(owner, { pose, options, open: !!menu, rectOf: () => node.getBoundingClientRect() });
|
|
346
|
+
}
|
|
347
|
+
const leave = () => { if (!menu) { preview = null; director()?.leave(owner); } };
|
|
348
|
+
listen(anchor, 'pointerenter', () => attend(menu || anchor));
|
|
349
|
+
listen(anchor, 'focus', () => attend(menu || anchor));
|
|
350
|
+
listen(anchor, 'pointerleave', () => { if (document.activeElement !== anchor) leave(); });
|
|
351
|
+
listen(anchor, 'blur', leave);
|
|
352
|
+
let stopMenu = () => {};
|
|
353
|
+
return {
|
|
354
|
+
open(node) {
|
|
355
|
+
if (destroyed || !node) return;
|
|
356
|
+
stopMenu();
|
|
357
|
+
menu = node;
|
|
358
|
+
const follow = e => {
|
|
359
|
+
const option = e.target.closest?.('.asst-dd-item, input, label, button');
|
|
360
|
+
if (option && node.contains(option)) attend(option);
|
|
361
|
+
};
|
|
362
|
+
const type = e => {
|
|
363
|
+
if (!e.target.matches?.('.asst-budget-input')) return;
|
|
364
|
+
watched = true;
|
|
365
|
+
director()?.type(true, () => {
|
|
366
|
+
const r = e.target.getBoundingClientRect();
|
|
367
|
+
return { x: r.left + Math.min(r.width - 12, 12 + e.target.value.length * 7), y: r.top + r.height / 2 };
|
|
368
|
+
});
|
|
369
|
+
};
|
|
370
|
+
node.addEventListener('pointerover', follow);
|
|
371
|
+
node.addEventListener('focusin', follow);
|
|
372
|
+
node.addEventListener('input', type);
|
|
373
|
+
stopMenu = () => {
|
|
374
|
+
node.removeEventListener('pointerover', follow);
|
|
375
|
+
node.removeEventListener('focusin', follow);
|
|
376
|
+
node.removeEventListener('input', type);
|
|
377
|
+
};
|
|
378
|
+
attend(node.contains(document.activeElement) ? document.activeElement : node);
|
|
379
|
+
},
|
|
380
|
+
close() {
|
|
381
|
+
stopMenu(); menu = null; preview = null;
|
|
382
|
+
if (watched) { director()?.stopTyping(); watched = false; }
|
|
383
|
+
director()?.leave(owner);
|
|
384
|
+
},
|
|
385
|
+
commit(reaction) { if (!destroyed) director()?.controlCommitted({ pose, options: options(), reaction }); },
|
|
386
|
+
refresh() { if (preview) attend(preview); },
|
|
387
|
+
destroy() {
|
|
388
|
+
this.close(); destroyed = true;
|
|
389
|
+
for (const off of listeners) off();
|
|
311
390
|
},
|
|
312
391
|
};
|
|
313
392
|
}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// info { label, value } → non-interactive row
|
|
22
22
|
// tag { label } → non-interactive badge row
|
|
23
23
|
// input { placeholder, value, onSubmit } → inline text field
|
|
24
|
+
// `restoreFocus` on an item or input sends focus back to the anchor once it is chosen.
|
|
24
25
|
// Keys: ↑/↓ move, Home/End jump, Enter/Space activate, Esc closes (focus back
|
|
25
26
|
// to the anchor), Tab closes. The optional filter hides non-matching items and
|
|
26
27
|
// any group left empty.
|
|
@@ -72,6 +73,7 @@ export function closeMenu({ restoreFocus = false } = {}) {
|
|
|
72
73
|
menu.remove();
|
|
73
74
|
if (anchor?.isConnected) {
|
|
74
75
|
if (anchor.getAttribute('aria-haspopup')) anchor.setAttribute('aria-expanded', 'false');
|
|
76
|
+
anchor.removeAttribute('aria-controls');
|
|
75
77
|
if (restoreFocus) { try { anchor.focus({ preventScroll: true }); } catch { /* detached */ } }
|
|
76
78
|
}
|
|
77
79
|
try { onClose?.(); } catch { /* listener error */ }
|
|
@@ -115,7 +117,7 @@ function buildItems(list, items, { role, onActivate }) {
|
|
|
115
117
|
input.value = spec.value || '';
|
|
116
118
|
input.setAttribute('aria-label', spec.label || spec.placeholder || 'Value');
|
|
117
119
|
input.dataset.submit = '1';
|
|
118
|
-
input._asstSubmit = (value) => { closeMenu(); spec.onSubmit?.(value); };
|
|
120
|
+
input._asstSubmit = (value) => { closeMenu({ restoreFocus: !!spec.restoreFocus }); spec.onSubmit?.(value); };
|
|
119
121
|
list.appendChild(input);
|
|
120
122
|
continue;
|
|
121
123
|
}
|
|
@@ -160,7 +162,7 @@ function buildItems(list, items, { role, onActivate }) {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
/** Hide items that do not match `query`, then any header/separator left without items. */
|
|
163
|
-
export function applyMenuFilter(list, query) {
|
|
165
|
+
export function applyMenuFilter(list, query, emptyLabel = 'No matches') {
|
|
164
166
|
const q = String(query || '').trim().toLowerCase();
|
|
165
167
|
const rows = [...list.children];
|
|
166
168
|
for (const row of rows) {
|
|
@@ -192,7 +194,7 @@ export function applyMenuFilter(list, query) {
|
|
|
192
194
|
let empty = list.querySelector('.asst-dd-empty.asst-dd-noresults');
|
|
193
195
|
const hasItem = rows.some(r => !r.hidden && (r.classList.contains('asst-dd-item') || r.classList.contains('asst-dd-input')));
|
|
194
196
|
if (q && !hasItem) {
|
|
195
|
-
if (!empty) { empty = el('div', 'asst-dd-empty asst-dd-noresults',
|
|
197
|
+
if (!empty) { empty = el('div', 'asst-dd-empty asst-dd-noresults', emptyLabel); list.appendChild(empty); }
|
|
196
198
|
empty.hidden = false;
|
|
197
199
|
} else if (empty) empty.hidden = true;
|
|
198
200
|
}
|
|
@@ -286,13 +288,15 @@ export function openMenu(anchor, opts = {}) {
|
|
|
286
288
|
closeMenu({ restoreFocus: !!item.restoreFocus });
|
|
287
289
|
item.onSelect?.(item, node);
|
|
288
290
|
};
|
|
289
|
-
|
|
290
|
-
|
|
291
|
+
if (opts.content) list.appendChild(opts.content);
|
|
292
|
+
else buildItems(list, items, { role, onActivate: activate });
|
|
293
|
+
if (width) menu.style.minWidth = opts.repositionOnResize ? `min(${width}px, calc(100vw - 16px))` : `${width}px`;
|
|
294
|
+
if (width && opts.repositionOnResize) menu.style.width = `min(${width}px, calc(100vw - 16px))`;
|
|
291
295
|
document.body.appendChild(menu);
|
|
292
296
|
positionMenu(menu, anchor, placement);
|
|
293
297
|
|
|
294
298
|
if (filterInput) {
|
|
295
|
-
filterInput.addEventListener('input', () => { applyMenuFilter(list, filterInput.value); positionMenu(menu, anchor, placement); });
|
|
299
|
+
filterInput.addEventListener('input', () => { applyMenuFilter(list, filterInput.value, opts.filterEmptyLabel); positionMenu(menu, anchor, placement); });
|
|
296
300
|
}
|
|
297
301
|
|
|
298
302
|
const onDocDown = (e) => {
|
|
@@ -308,6 +312,15 @@ export function openMenu(anchor, opts = {}) {
|
|
|
308
312
|
const nodes = focusables(menu);
|
|
309
313
|
const idx = nodes.indexOf(document.activeElement);
|
|
310
314
|
if (e.key === 'Escape') { e.preventDefault(); e.stopPropagation(); closeMenu({ restoreFocus: true }); return; }
|
|
315
|
+
if (role === 'dialog') {
|
|
316
|
+
if (e.key === 'Tab') {
|
|
317
|
+
const fields = [...menu.querySelectorAll('button, input')].filter(node => !node.disabled && !node.hidden);
|
|
318
|
+
const index = fields.indexOf(document.activeElement);
|
|
319
|
+
if (e.shiftKey && index <= 0) { e.preventDefault(); fields.at(-1)?.focus(); }
|
|
320
|
+
else if (!e.shiftKey && (index < 0 || index === fields.length - 1)) { e.preventDefault(); fields[0]?.focus(); }
|
|
321
|
+
}
|
|
322
|
+
return; // native number/switch keys and Enter belong to the form
|
|
323
|
+
}
|
|
311
324
|
if (e.key === 'Tab') { closeMenu(); return; }
|
|
312
325
|
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
313
326
|
e.preventDefault(); e.stopPropagation();
|
|
@@ -341,21 +354,24 @@ export function openMenu(anchor, opts = {}) {
|
|
|
341
354
|
// Keep single-letter global keybinds out of an open menu.
|
|
342
355
|
e.stopPropagation();
|
|
343
356
|
};
|
|
344
|
-
const onResize = () => closeMenu();
|
|
357
|
+
const onResize = () => opts.repositionOnResize ? positionMenu(menu, anchor, placement) : closeMenu();
|
|
358
|
+
const onBlur = () => closeMenu();
|
|
345
359
|
document.addEventListener('mousedown', onDocDown, true);
|
|
346
|
-
|
|
360
|
+
const keyTarget = role === 'dialog' ? window : document;
|
|
361
|
+
keyTarget.addEventListener('keydown', onKey, true);
|
|
347
362
|
window.addEventListener('resize', onResize);
|
|
348
|
-
window.addEventListener('blur',
|
|
363
|
+
window.addEventListener('blur', onBlur);
|
|
349
364
|
const cleanup = () => {
|
|
350
365
|
document.removeEventListener('mousedown', onDocDown, true);
|
|
351
|
-
|
|
366
|
+
keyTarget.removeEventListener('keydown', onKey, true);
|
|
352
367
|
window.removeEventListener('resize', onResize);
|
|
353
|
-
window.removeEventListener('blur',
|
|
368
|
+
window.removeEventListener('blur', onBlur);
|
|
354
369
|
};
|
|
355
370
|
|
|
356
371
|
_open = { menu, anchor, onClose, cleanup };
|
|
357
372
|
if (anchor.getAttribute('aria-haspopup')) anchor.setAttribute('aria-expanded', 'true');
|
|
358
373
|
anchor.setAttribute('aria-controls', menu.id);
|
|
374
|
+
opts.onOpen?.(menu);
|
|
359
375
|
|
|
360
376
|
const selected = list.querySelector('.asst-dd-item[data-checked="1"]:not([disabled])');
|
|
361
377
|
const first = focusables(menu).find(n => n.classList.contains('asst-dd-item')) || focusables(menu)[0];
|