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
|
@@ -20,8 +20,8 @@ import { escapeHtml } from './utils.js';
|
|
|
20
20
|
import * as kit from './settings/settings-kit.js';
|
|
21
21
|
import { emit, on } from './state.js';
|
|
22
22
|
import {
|
|
23
|
-
waView, confirmLine, formatCountdown,
|
|
24
|
-
brainChoiceInUse, brainChoiceLabel, brainChoiceNotes,
|
|
23
|
+
waView, confirmLine, formatCountdown, levelLabel, modeLabel, chooseNote, connectorSize, brainLimitText,
|
|
24
|
+
brainChoiceInUse, brainChoiceLabel, brainChoiceNotes, connectionWarningText, transcriptionLine,
|
|
25
25
|
localizedCopy, localize, setTranslator,
|
|
26
26
|
} from './whatsapp/wa-view.js';
|
|
27
27
|
import { normalizePhone, PHONE_ERRORS as PHONE_ERROR_SOURCE } from './whatsapp/wa-phone.js';
|
|
@@ -59,8 +59,9 @@ const attr = (s) => String(s ?? '').replace(/&/g, '&').replace(/"/g, '"
|
|
|
59
59
|
const esc = (s) => escapeHtml(String(s ?? ''));
|
|
60
60
|
const num = (n) => Number(n || 0).toLocaleString('en-US');
|
|
61
61
|
const btn = (id, label, cls = '', extra = '') => `<button class="wa-btn${cls ? ` ${cls}` : ''}" id="${id}" type="button" ${extra}>${esc(label)}</button>`;
|
|
62
|
-
// `named`: the row's <strong id="<id>-label"> and <small id="<id>-help"> name and describe the switch
|
|
63
|
-
|
|
62
|
+
// `named`: the row's <strong id="<id>-label"> and <small id="<id>-help"> name and describe the switch
|
|
63
|
+
// (`alsoDescribedBy`: the id of one more line that describes it, such as a status line).
|
|
64
|
+
const toggle = (id, named = false, alsoDescribedBy = '') => `<label class="recall-toggle"><input type="checkbox" id="${id}"${named ? ` aria-labelledby="${id}-label" aria-describedby="${id}-help${alsoDescribedBy ? ` ${alsoDescribedBy}` : ''}"` : ''}><span class="recall-toggle-track"></span></label>`;
|
|
64
65
|
const tile = (id, label) => `<div class="db-stat"><span class="db-stat-label">${esc(label)}</span><span class="db-stat-value" id="${id}">—</span></div>`;
|
|
65
66
|
const radios = (name, options, invId = '') => `<div class="wa-radios" role="radiogroup"${invId ? ` ${kit.inv(invId)}` : ''}>${options.map((o) => `
|
|
66
67
|
<label class="wa-radio"><input type="radio" name="${name}" value="${attr(o.value)}"><span><strong>${esc(o.label)}</strong>${o.hint ? `<small>${esc(o.hint)}</small>` : ''}</span></label>`).join('')}</div>`;
|
|
@@ -114,6 +115,7 @@ export function buildWhatsAppTab() {
|
|
|
114
115
|
<ol class="wa-steps" id="wa-steps" hidden>${steps}</ol>
|
|
115
116
|
|
|
116
117
|
${section({ id: 'wa-sec-setup', badgeId: 'wa-setup-badge', body: `
|
|
118
|
+
<div class="wa-callout wa-callout-warn" id="wa-conn-warning" role="status" hidden></div>
|
|
117
119
|
<div class="wa-pane" data-pane="loading"><div class="settings-hint">${kit.te('settings.redesign.whatsapp.askingSynabunForTheWhatsappStatus')}</div></div>
|
|
118
120
|
<div class="wa-pane" data-pane="unavailable" hidden><div class="settings-hint" id="wa-unavailable-text"></div></div>
|
|
119
121
|
|
|
@@ -233,6 +235,7 @@ export function buildWhatsAppTab() {
|
|
|
233
235
|
<div class="settings-field"><label>${kit.te('settings.redesign.whatsapp.longAnswers')}</label>${radios('wa-max', MAX_MESSAGE_OPTIONS, 'WA045')}<div class="settings-hint">${kit.te('settings.redesign.whatsapp.longerAnswersAreCutThereWith')}</div></div>
|
|
234
236
|
<div class="settings-field"><label>${kit.te('settings.redesign.whatsapp.freshConversation')}</label>${radios('wa-rotation', ROTATION_OPTIONS, 'WA046')}</div>
|
|
235
237
|
<div class="settings-field" id="wa-trigger-field"><label>${kit.te('settings.redesign.whatsapp.inMessageYourself')}</label>${radios('wa-trigger', TRIGGER_OPTIONS, 'WA047')}</div>
|
|
238
|
+
<div class="settings-field wa-toggle-row" id="wa-voice-field" hidden><span><strong id="wa-voice-label">${kit.te('settings.redesign.whatsapp.transcribeVoiceNotes')}</strong><small id="wa-voice-help">${kit.te('settings.redesign.whatsapp.voiceNotesAreTurnedIntoText')}</small><small id="wa-voice-status" role="status"></small></span>${toggle('wa-voice', true, 'wa-voice-status')}</div>
|
|
236
239
|
<div class="settings-field"><label>${kit.te('settings.redesign.whatsapp.commandsYouCanSend')}</label>
|
|
237
240
|
<ul class="wa-commands">${COMMANDS.map((c) => `<li><code>${esc(c.name)}</code> ${esc(c.text)}</li>`).join('')}</ul>
|
|
238
241
|
<div class="settings-hint">${kit.te('settings.redesign.whatsapp.answerAQuestionOrAnApproval')}</div>
|
|
@@ -381,6 +384,10 @@ export function wireWhatsAppTab(overlay, { toast = () => {} } = {}) {
|
|
|
381
384
|
const pane = state.showChoose && ['link_expired', 'logged_out'].includes(status?.state) ? 'choose' : view.pane;
|
|
382
385
|
for (const el of tabBody.querySelectorAll('.wa-pane')) show(el, el.dataset.pane === pane);
|
|
383
386
|
renderPaneActions(view);
|
|
387
|
+
// A 440 / 403 the link keeps retrying: why, while it lasts (status.warning).
|
|
388
|
+
const warning = connectionWarningText(status);
|
|
389
|
+
setText($('wa-conn-warning'), warning);
|
|
390
|
+
show($('wa-conn-warning'), !!warning);
|
|
384
391
|
renderSetupDetails(status, view, pane);
|
|
385
392
|
renderConnector(status);
|
|
386
393
|
renderConversation(status);
|
|
@@ -422,7 +429,7 @@ export function wireWhatsAppTab(overlay, { toast = () => {} } = {}) {
|
|
|
422
429
|
[kit.tx('settings.redesign.whatsapp.mode'), modeLabel(s.mode)],
|
|
423
430
|
[kit.tx('settings.redesign.whatsapp.account'), [s.account?.name && s.account.name !== '~' ? s.account.name : null, s.account?.masked].filter(Boolean).join(' · ') || '—'],
|
|
424
431
|
[kit.tx('settings.redesign.whatsapp.owner'), s.owner?.masked ? `${s.owner.masked}${s.owner.boundAt ? (" " + kit.tx('settings.redesign.whatsapp.ownerSince', { date: new Date(s.owner.boundAt).toLocaleDateString() })) : ''}` : '—'],
|
|
425
|
-
[kit.tx('settings.redesign.whatsapp.level'),
|
|
432
|
+
[kit.tx('settings.redesign.whatsapp.level'), levelLabel(s.level)],
|
|
426
433
|
];
|
|
427
434
|
const html = lines.map(([k, v]) => `<div><strong>${esc(k)}</strong> ${esc(v)}</div>`).join('');
|
|
428
435
|
if ($('wa-connected-facts').innerHTML !== html) $('wa-connected-facts').innerHTML = html;
|
|
@@ -457,6 +464,13 @@ export function wireWhatsAppTab(overlay, { toast = () => {} } = {}) {
|
|
|
457
464
|
setRadio('wa-rotation', cfg.rotation);
|
|
458
465
|
setRadio('wa-trigger', cfg.selfTrigger);
|
|
459
466
|
show($('wa-trigger-field'), s.mode !== 'dedicated');
|
|
467
|
+
// Voice notes (a server without them sends neither the field nor status.transcription: the row stays hidden).
|
|
468
|
+
const voiceKnown = typeof cfg.transcriptionEnabled === 'boolean' && !!s.transcription;
|
|
469
|
+
show($('wa-voice-field'), voiceKnown);
|
|
470
|
+
if (voiceKnown) {
|
|
471
|
+
setChecked($('wa-voice'), cfg.transcriptionEnabled);
|
|
472
|
+
setText($('wa-voice-status'), transcriptionLine(s));
|
|
473
|
+
}
|
|
460
474
|
const session = s.session;
|
|
461
475
|
setText($('wa-session-line'), session?.id ? kit.tx('settings.redesign.whatsapp.sessionCurrent', { title: session.title || kit.tx('settings.redesign.whatsapp.whatsappConversation') }) : kit.tx('settings.redesign.whatsapp.noConversationYetYourFirstMessage'));
|
|
462
476
|
$('wa-open-conversation').disabled = !session?.id;
|
|
@@ -562,7 +576,7 @@ export function wireWhatsAppTab(overlay, { toast = () => {} } = {}) {
|
|
|
562
576
|
const box = $('wa-allow-box');
|
|
563
577
|
const e = state.escalation;
|
|
564
578
|
if (!e || Date.now() > e.expiresAt) { show(box, false); return; }
|
|
565
|
-
const html = `<strong>${kit.te('settings.redesign.whatsapp.nowOnYourPhone')}</strong> ${kit.te('settings.redesign.whatsapp.send')} <code class="wa-allow-code">ALLOW ${esc(e.code)}</code> ${kit.te('settings.redesign.whatsapp.inTheWhatsappChatWithSynabun')} <span id="wa-allow-countdown">${esc(formatCountdown(e.expiresAt - Date.now()))}</span>${kit.te('settings.redesign.whatsapp.
|
|
579
|
+
const html = `<strong>${kit.te('settings.redesign.whatsapp.nowOnYourPhone')}</strong> ${kit.te('settings.redesign.whatsapp.send')} <code class="wa-allow-code">ALLOW ${esc(e.code)}</code> ${kit.te('settings.redesign.whatsapp.inTheWhatsappChatWithSynabun')} <span id="wa-allow-countdown">${esc(formatCountdown(e.expiresAt - Date.now()))}</span>${kit.te('settings.redesign.whatsapp.autonomousUntilTurnedOff')}`;
|
|
566
580
|
if (box.dataset.sig !== e.code) { box.innerHTML = html; box.dataset.sig = e.code; }
|
|
567
581
|
show(box, true);
|
|
568
582
|
}
|
|
@@ -847,6 +861,7 @@ export function wireWhatsAppTab(overlay, { toast = () => {} } = {}) {
|
|
|
847
861
|
radioSave('wa-rotation', 'rotation');
|
|
848
862
|
radioSave('wa-trigger', 'selfTrigger');
|
|
849
863
|
$('wa-forward').addEventListener('change', () => putConfig({ forwardBackground: $('wa-forward').checked }));
|
|
864
|
+
$('wa-voice').addEventListener('change', () => putConfig({ transcriptionEnabled: $('wa-voice').checked }));
|
|
850
865
|
$('wa-label').addEventListener('input', renderLabelPreview);
|
|
851
866
|
$('wa-label-save').addEventListener('click', () => putConfig({ replyLabel: $('wa-label').value.trim() || null }).then((r) => { if (r.ok !== false) toast(kit.tx('settings.redesign.whatsapp.replyLabelSaved')); }));
|
|
852
867
|
|
|
@@ -2882,6 +2882,11 @@ export function isSidepanelKeyTarget(el) {
|
|
|
2882
2882
|
return !!el?.closest?.('[data-sidepanel-provider]');
|
|
2883
2883
|
}
|
|
2884
2884
|
|
|
2885
|
+
// A key pressed inside the File Explorer's code editor (shared/editor/editor-panel.js) is the editor's.
|
|
2886
|
+
export function isEditorPanelKeyTarget(el) {
|
|
2887
|
+
return !!el?.closest?.('#fe-editor-panel');
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2885
2890
|
function onKeyDown(e) {
|
|
2886
2891
|
if (!isWhiteboardActive()) return;
|
|
2887
2892
|
|
|
@@ -2897,6 +2902,13 @@ function onKeyDown(e) {
|
|
|
2897
2902
|
// Nor while it is inside a side panel: Escape there stops a turn, and Delete, Backspace or
|
|
2898
2903
|
// Ctrl+A/Z/C on one of its controls is not a board edit.
|
|
2899
2904
|
if (isSidepanelKeyTarget(e.target) || isSidepanelKeyTarget(ae)) return;
|
|
2905
|
+
// Nor while it is inside the code editor's panel: on one of its tabs, header or status-bar buttons, in one of
|
|
2906
|
+
// its menus, its palette or its popover (all attached inside the panel), M, Delete, Backspace or
|
|
2907
|
+
// Ctrl+A/Z/Y/C is the editor's key, or nobody's, and never a board edit.
|
|
2908
|
+
if (isEditorPanelKeyTarget(e.target) || isEditorPanelKeyTarget(ae)) return;
|
|
2909
|
+
// Nor while it is in the File Explorer, or in what it opens over the page (its menu, preview and questions):
|
|
2910
|
+
// Delete there deletes a file, and a letter is the name of a row being typed.
|
|
2911
|
+
if (ae?.closest?.('#file-explorer-panel, .fe-ctx-flyout, .fe-modal-overlay, .fe-git-popover')) return;
|
|
2900
2912
|
|
|
2901
2913
|
const isEditingText = !!document.activeElement?.closest('.wb-text.editing');
|
|
2902
2914
|
const editingListLi = document.activeElement?.closest('.wb-list.editing li') || null;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — how a dispatched worker's tab ends: the page side
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// What the three provider sidepanels (Claude Code, Codex, OpenCode) share for
|
|
6
|
+
// the end of a worker the Assistant dispatched: following the run until it
|
|
7
|
+
// has something to show, asking the dispatcher how it went (GET
|
|
8
|
+
// /api/assistant/runs/:runId, then its `assistant:dispatch` events), the card
|
|
9
|
+
// itself, and the way back to the Assistant session that dispatched it. What
|
|
10
|
+
// the card says is worker-end.js; where it goes in a transcript, how it looks
|
|
11
|
+
// and how its tab closes are each panel's own (every panel passes its own
|
|
12
|
+
// classes and its own close action, so the card wears that panel's styles).
|
|
13
|
+
//
|
|
14
|
+
// The way back closes the worker's tab with the close the panel's own X runs
|
|
15
|
+
// (it never deletes the run record: the Assistant still reads its result, and
|
|
16
|
+
// the agents dock still lists it) and then shows the session through
|
|
17
|
+
// `assistant:show` with the sidepanel as the host for a session that is open
|
|
18
|
+
// nowhere: the terminal tab or the sidepanel that has it keeps it. Closing the
|
|
19
|
+
// tab of a worker that finished its task completes its run instead of
|
|
20
|
+
// stopping it (endWorkerRunOnClose): the Assistant reads it as done, never as
|
|
21
|
+
// stopped by the user.
|
|
22
|
+
|
|
23
|
+
import { emit, on } from './state.js';
|
|
24
|
+
import { t } from './i18n.js';
|
|
25
|
+
import { TERMINAL_STATES, WORKER_END_CLASS, isDispatchedRun, isRunWorking, mayHaveEnded, workerEndView } from './worker-end.js';
|
|
26
|
+
|
|
27
|
+
export { WORKER_END_CLASS };
|
|
28
|
+
|
|
29
|
+
const translate = (key, params) => t(`workerEnd.${key}`, params);
|
|
30
|
+
|
|
31
|
+
// runId → { run, dispatch, settled, wasWorking, busy, apply, readKey, sig }
|
|
32
|
+
const _runs = new Map();
|
|
33
|
+
let _wired = false;
|
|
34
|
+
|
|
35
|
+
function newer(next, current) {
|
|
36
|
+
if (!current) return true;
|
|
37
|
+
const a = Number(next?.version) || 0;
|
|
38
|
+
const b = Number(current?.version) || 0;
|
|
39
|
+
if (a !== b) return a > b;
|
|
40
|
+
return String(next?.updatedAt || '') >= String(current?.updatedAt || '');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function wire() {
|
|
44
|
+
if (_wired) return;
|
|
45
|
+
_wired = true;
|
|
46
|
+
// Every change of a run the dispatcher makes (a turn, a result, the end, a
|
|
47
|
+
// failure's cause judged later) reaches the tab without another request.
|
|
48
|
+
on('sync:assistant:dispatch', (message) => {
|
|
49
|
+
const view = message?.run;
|
|
50
|
+
const entry = view?.runId ? _runs.get(view.runId) : null;
|
|
51
|
+
if (!entry || !newer(view, entry.dispatch)) return;
|
|
52
|
+
noteDispatch(entry, view);
|
|
53
|
+
paint(entry);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function noteDispatch(entry, view) {
|
|
58
|
+
entry.dispatch = view;
|
|
59
|
+
entry.settled = true;
|
|
60
|
+
// What the run was doing before it ended: a stop in the middle of a turn is a stop.
|
|
61
|
+
if (!TERMINAL_STATES.has(String(view.state || ''))) entry.wasWorking = isRunWorking(null, view);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function paint(entry) {
|
|
65
|
+
const view = workerEndView(entry.run, entry.dispatch, { t: translate, busy: entry.busy, stoppedMidTurn: entry.wasWorking });
|
|
66
|
+
// An ended run is drawn once the dispatcher has answered: never "Stopped" first and "Task complete" a moment later.
|
|
67
|
+
if (view && !entry.settled) return;
|
|
68
|
+
const sig = view?.sig || '';
|
|
69
|
+
if (sig === entry.sig) return;
|
|
70
|
+
entry.sig = sig;
|
|
71
|
+
try { entry.apply(view); } catch (error) { console.warn('[worker-end] a panel failed to draw the end of a run', error); }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function read(entry) {
|
|
75
|
+
const run = entry.run;
|
|
76
|
+
const key = `${run.status}|${run.turnState || ''}|${run.version || 0}`;
|
|
77
|
+
if (entry.readKey === key) return;
|
|
78
|
+
entry.readKey = key;
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(`/api/assistant/runs/${encodeURIComponent(run.runId)}`);
|
|
81
|
+
const data = response.ok ? await response.json() : null;
|
|
82
|
+
if (_runs.get(run.runId) !== entry) return;
|
|
83
|
+
if (data?.run && newer(data.run, entry.dispatch)) noteDispatch(entry, data.run);
|
|
84
|
+
} catch {
|
|
85
|
+
if (_runs.get(run.runId) !== entry) return;
|
|
86
|
+
}
|
|
87
|
+
// No answer (an older server, a run the dispatcher no longer keeps): the runtime's own reading is drawn.
|
|
88
|
+
entry.settled = true;
|
|
89
|
+
paint(entry);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Follow a run attached to a provider tab. Call it on every attach (the
|
|
94
|
+
* router attaches again on each change of the run): `apply(view)` is called
|
|
95
|
+
* with the card to show, or null to take it away, only when that changes.
|
|
96
|
+
* A run the Assistant did not dispatch gets `apply(null)` and is not followed.
|
|
97
|
+
*
|
|
98
|
+
* @param {object} run the runtime descriptor the panel was attached with
|
|
99
|
+
* @param {object} o
|
|
100
|
+
* @param {(view: object | null) => void} o.apply draw the card (or remove it)
|
|
101
|
+
* @param {boolean} [o.busy] the tab sees background work of the run still going
|
|
102
|
+
*/
|
|
103
|
+
export function trackWorkerEnd(run, { apply, busy = false } = {}) {
|
|
104
|
+
if (!run?.runId || typeof apply !== 'function') return;
|
|
105
|
+
if (!isDispatchedRun(run)) {
|
|
106
|
+
_runs.delete(run.runId);
|
|
107
|
+
apply(null);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
wire();
|
|
111
|
+
let entry = _runs.get(run.runId);
|
|
112
|
+
if (!entry) {
|
|
113
|
+
entry = { run: null, dispatch: null, settled: false, wasWorking: false, busy: false, apply, readKey: '', sig: null };
|
|
114
|
+
_runs.set(run.runId, entry);
|
|
115
|
+
}
|
|
116
|
+
entry.apply = apply;
|
|
117
|
+
entry.busy = !!busy;
|
|
118
|
+
if (newer(run, entry.run)) entry.run = run;
|
|
119
|
+
if (!TERMINAL_STATES.has(String(entry.run.status || '')) && !TERMINAL_STATES.has(String(entry.dispatch?.state || ''))) {
|
|
120
|
+
entry.wasWorking = isRunWorking(entry.run, null);
|
|
121
|
+
}
|
|
122
|
+
paint(entry);
|
|
123
|
+
if (mayHaveEnded(entry.run)) read(entry);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** The tab saw its background work change: the card of a warm worker waits for it. */
|
|
127
|
+
export function updateWorkerEndBusy(runId, busy) {
|
|
128
|
+
const entry = _runs.get(runId);
|
|
129
|
+
if (!entry || entry.busy === !!busy) return;
|
|
130
|
+
entry.busy = !!busy;
|
|
131
|
+
paint(entry);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The tab of the run closed (or let the run go): stop following it. */
|
|
135
|
+
export function forgetWorkerEnd(runId) {
|
|
136
|
+
if (runId) _runs.delete(runId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The run reported its task done and waits warm for a follow-up, with no
|
|
141
|
+
* background work of its own going: its card is (or would be) a warm "Task
|
|
142
|
+
* complete". Known only for a run the tab follows, so ask before forgetWorkerEnd().
|
|
143
|
+
*/
|
|
144
|
+
export function isFinishedWarmWorker(runId, { busy = false } = {}) {
|
|
145
|
+
const entry = runId ? _runs.get(runId) : null;
|
|
146
|
+
if (!entry?.settled || !entry.run) return false;
|
|
147
|
+
const view = workerEndView(entry.run, entry.dispatch, { busy: busy || entry.busy, stoppedMidTurn: entry.wasWorking });
|
|
148
|
+
return view?.kind === 'complete' && view.warm;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* End the run of a worker tab the user closes (its X, or Back to Assistant).
|
|
153
|
+
* A worker that finished its task and waits warm for a follow-up is completed
|
|
154
|
+
* (POST /api/assistant/runs/:runId/tab-closed: completed, reason `tab_closed`,
|
|
155
|
+
* its result untouched). Any other run, a run the server finds working after
|
|
156
|
+
* all, and a server without that route get `stop()`: the panel's own stop,
|
|
157
|
+
* what its X always did. Decided when called: call it before forgetWorkerEnd().
|
|
158
|
+
*
|
|
159
|
+
* @param {string} runId
|
|
160
|
+
* @param {() => void} stop the panel's stop (POST /api/loop/stop)
|
|
161
|
+
* @param {object} [o]
|
|
162
|
+
* @param {boolean} [o.busy] the tab sees background work of the run still going
|
|
163
|
+
* @returns {Promise<'completed' | 'stopped'>}
|
|
164
|
+
*/
|
|
165
|
+
export function endWorkerRunOnClose(runId, stop, { busy = false } = {}) {
|
|
166
|
+
const stopped = () => { stop(); return 'stopped'; };
|
|
167
|
+
if (!isFinishedWarmWorker(runId, { busy })) return Promise.resolve(stopped());
|
|
168
|
+
return fetch(`/api/assistant/runs/${encodeURIComponent(runId)}/tab-closed`, {
|
|
169
|
+
method: 'POST',
|
|
170
|
+
headers: { 'Content-Type': 'application/json' },
|
|
171
|
+
body: '{}',
|
|
172
|
+
}).then(async (response) => {
|
|
173
|
+
const data = response.ok ? await response.json().catch(() => null) : null;
|
|
174
|
+
return data?.ok ? 'completed' : stopped();
|
|
175
|
+
}).catch(stopped);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Show the Assistant session that dispatched a run: focused where it is open
|
|
180
|
+
* (the terminal tab or the sidepanel), else opened in the Assistant sidepanel.
|
|
181
|
+
*/
|
|
182
|
+
export function backToAssistant(assistantSessionId) {
|
|
183
|
+
if (!assistantSessionId) return false;
|
|
184
|
+
emit('assistant:show', { sessionId: assistantSessionId, host: 'sidepanel' });
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The card. Every element takes the owning panel's classes, so it is drawn in
|
|
190
|
+
* that panel's type and colours; `data-tone` (ok, warn, err, off) is what the
|
|
191
|
+
* panel's styles colour the title by, and the title always says the state in
|
|
192
|
+
* words. The button is there only for a run with a dispatching session, and
|
|
193
|
+
* works once.
|
|
194
|
+
*
|
|
195
|
+
* @param {object} view a workerEndView() result
|
|
196
|
+
* @param {object} [o]
|
|
197
|
+
* @param {{ card?: string, title?: string, detail?: string, meta?: string, note?: string, actions?: string, button?: string }} [o.classes]
|
|
198
|
+
* @param {(view: object) => (void | boolean | Promise<void | boolean>)} [o.onBack] close the tab, then
|
|
199
|
+
* backToAssistant(); `false` when the tab stayed (the button works again)
|
|
200
|
+
*/
|
|
201
|
+
export function buildWorkerEndCard(view, { classes = {}, onBack = null } = {}) {
|
|
202
|
+
const card = document.createElement('div');
|
|
203
|
+
card.className = [WORKER_END_CLASS, classes.card].filter(Boolean).join(' ');
|
|
204
|
+
card.dataset.workerEnd = view.kind;
|
|
205
|
+
card.dataset.tone = view.tone;
|
|
206
|
+
card.setAttribute('role', 'status');
|
|
207
|
+
|
|
208
|
+
const title = document.createElement('div');
|
|
209
|
+
title.className = ['worker-end-title', classes.title].filter(Boolean).join(' ');
|
|
210
|
+
title.textContent = view.title;
|
|
211
|
+
card.appendChild(title);
|
|
212
|
+
|
|
213
|
+
for (const part of ['detail', 'meta', 'note']) {
|
|
214
|
+
if (!view[part]) continue;
|
|
215
|
+
const el = document.createElement('div');
|
|
216
|
+
el.className = [`worker-end-${part}`, classes[part]].filter(Boolean).join(' ');
|
|
217
|
+
el.textContent = view[part];
|
|
218
|
+
card.appendChild(el);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (view.assistantSessionId && typeof onBack === 'function') {
|
|
222
|
+
const actions = document.createElement('div');
|
|
223
|
+
actions.className = ['worker-end-actions', classes.actions].filter(Boolean).join(' ');
|
|
224
|
+
const button = document.createElement('button');
|
|
225
|
+
button.type = 'button';
|
|
226
|
+
button.className = ['worker-end-back', classes.button].filter(Boolean).join(' ');
|
|
227
|
+
button.textContent = view.backLabel;
|
|
228
|
+
button.title = view.backHint;
|
|
229
|
+
button.addEventListener('click', () => {
|
|
230
|
+
if (button.disabled) return;
|
|
231
|
+
button.disabled = true;
|
|
232
|
+
Promise.resolve()
|
|
233
|
+
.then(() => onBack(view))
|
|
234
|
+
// `false`: the panel asked first and the user kept the tab.
|
|
235
|
+
.then((done) => { if (done === false) button.disabled = false; })
|
|
236
|
+
.catch((error) => {
|
|
237
|
+
console.warn('[worker-end] going back to the Assistant failed', error);
|
|
238
|
+
button.disabled = false;
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
actions.appendChild(button);
|
|
242
|
+
card.appendChild(actions);
|
|
243
|
+
}
|
|
244
|
+
return card;
|
|
245
|
+
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Save/load full scene snapshots: open cards, graph node positions,
|
|
6
6
|
// camera state (3D), active category filters, and selection.
|
|
7
|
-
//
|
|
7
|
+
// The switcher leads the top-right dock; Snap to grid and Tile terminals are on
|
|
8
|
+
// the whiteboard rail and in View.
|
|
8
9
|
// Export/import as JSON for backup.
|
|
9
10
|
//
|
|
10
11
|
// Events emitted:
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
import { state, emit, on } from './state.js';
|
|
21
22
|
import { KEYS } from './constants.js';
|
|
22
23
|
import { storage } from './storage.js';
|
|
24
|
+
import { t } from './i18n.js';
|
|
23
25
|
import { posStore } from './node-positions-store.js';
|
|
24
26
|
import { getVariant } from './registry.js';
|
|
25
27
|
import {
|
|
@@ -525,18 +527,13 @@ function updateIndicator() {
|
|
|
525
527
|
if (!indicator || !nameEl) return;
|
|
526
528
|
|
|
527
529
|
const activeId = getActiveId();
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
nameEl.textContent = 'No workspace';
|
|
539
|
-
indicator.classList.remove('has-workspace');
|
|
530
|
+
const active = activeId ? getWorkspaces().find(w => w.id === activeId) : null;
|
|
531
|
+
nameEl.textContent = active ? active.name : 'No workspace';
|
|
532
|
+
indicator.classList.toggle('has-workspace', !!active);
|
|
533
|
+
// The name is cut short in the bar, or not shown at all where the band is narrow: the tooltip has it whole.
|
|
534
|
+
const label = active ? t('toolbar.workspaceActive', { name: active.name }) : t('toolbar.workspaceNone');
|
|
535
|
+
indicator.dataset.tooltip = label;
|
|
536
|
+
indicator.setAttribute('aria-label', label);
|
|
540
537
|
}
|
|
541
538
|
|
|
542
539
|
|
|
@@ -552,6 +549,7 @@ function openDropdown() {
|
|
|
552
549
|
_isOpen = true;
|
|
553
550
|
dropdown.style.display = '';
|
|
554
551
|
indicator?.classList.add('open');
|
|
552
|
+
indicator?.setAttribute('aria-expanded', 'true');
|
|
555
553
|
renderList();
|
|
556
554
|
|
|
557
555
|
emit('panel:close-all-dropdowns-except', 'workspace');
|
|
@@ -565,6 +563,7 @@ function closeDropdown() {
|
|
|
565
563
|
_isOpen = false;
|
|
566
564
|
dropdown.style.display = 'none';
|
|
567
565
|
indicator?.classList.remove('open');
|
|
566
|
+
indicator?.setAttribute('aria-expanded', 'false');
|
|
568
567
|
}
|
|
569
568
|
|
|
570
569
|
function toggleDropdown() {
|
|
@@ -668,25 +667,33 @@ export function initWorkspaces() {
|
|
|
668
667
|
});
|
|
669
668
|
}
|
|
670
669
|
|
|
671
|
-
// Grid snap toggle
|
|
670
|
+
// Grid snap: the whiteboard rail's toggle and View → Snap to grid (the rail shows in Focus Mode only)
|
|
672
671
|
const gridBtn = $('ws-grid-toggle');
|
|
672
|
+
const gridMenu = $('menu-toggle-grid-snap');
|
|
673
|
+
const showGridSnap = () => {
|
|
674
|
+
gridBtn?.classList.toggle('active', state.gridSnap);
|
|
675
|
+
gridBtn?.setAttribute('aria-pressed', String(state.gridSnap));
|
|
676
|
+
gridMenu?.classList.toggle('active', state.gridSnap);
|
|
677
|
+
document.body.classList.toggle('grid-active', state.gridSnap);
|
|
678
|
+
};
|
|
679
|
+
const toggleGridSnap = () => {
|
|
680
|
+
state.gridSnap = !state.gridSnap;
|
|
681
|
+
showGridSnap();
|
|
682
|
+
storage.setItem(KEYS.GRID_SNAP, state.gridSnap);
|
|
683
|
+
};
|
|
684
|
+
if (storage.getItem(KEYS.GRID_SNAP) === 'true') {
|
|
685
|
+
state.gridSnap = true;
|
|
686
|
+
showGridSnap();
|
|
687
|
+
}
|
|
673
688
|
if (gridBtn) {
|
|
674
|
-
const saved = storage.getItem(KEYS.GRID_SNAP);
|
|
675
|
-
if (saved === 'true') {
|
|
676
|
-
state.gridSnap = true;
|
|
677
|
-
gridBtn.classList.add('active');
|
|
678
|
-
document.body.classList.add('grid-active');
|
|
679
|
-
}
|
|
680
689
|
gridBtn.addEventListener('click', (e) => {
|
|
681
690
|
e.stopPropagation();
|
|
682
|
-
|
|
683
|
-
gridBtn.classList.toggle('active', state.gridSnap);
|
|
684
|
-
document.body.classList.toggle('grid-active', state.gridSnap);
|
|
685
|
-
storage.setItem(KEYS.GRID_SNAP, state.gridSnap);
|
|
691
|
+
toggleGridSnap();
|
|
686
692
|
});
|
|
687
693
|
}
|
|
694
|
+
if (gridMenu) gridMenu.addEventListener('click', toggleGridSnap);
|
|
688
695
|
|
|
689
|
-
// Tile floating terminals
|
|
696
|
+
// Tile floating terminals: the rail's button and View → Tile terminals
|
|
690
697
|
const tileBtn = $('ws-tile-btn');
|
|
691
698
|
if (tileBtn) {
|
|
692
699
|
tileBtn.addEventListener('click', (e) => {
|
|
@@ -694,12 +701,19 @@ export function initWorkspaces() {
|
|
|
694
701
|
tileFloatingTerminals();
|
|
695
702
|
});
|
|
696
703
|
}
|
|
704
|
+
const tileMenu = $('menu-tile-terminals');
|
|
705
|
+
if (tileMenu) {
|
|
706
|
+
tileMenu.addEventListener('click', () => {
|
|
707
|
+
emit('panel:close-all-dropdowns');
|
|
708
|
+
tileFloatingTerminals();
|
|
709
|
+
});
|
|
710
|
+
}
|
|
697
711
|
|
|
698
|
-
// Close dropdown on click outside
|
|
712
|
+
// Close dropdown on click outside (the session pills hang inside #topright-controls, but are not the toolbar)
|
|
699
713
|
document.addEventListener('click', (e) => {
|
|
700
714
|
if (!_isOpen) return;
|
|
701
715
|
const container = $('topright-controls') || $('workspace-overlay');
|
|
702
|
-
if (container && !container.contains(e.target)) {
|
|
716
|
+
if (container && (!container.contains(e.target) || e.target.closest('#term-minimized-tray'))) {
|
|
703
717
|
closeDropdown();
|
|
704
718
|
}
|
|
705
719
|
});
|
|
@@ -69,7 +69,7 @@ export const MODE_CARDS = Object.freeze([
|
|
|
69
69
|
export const LEVEL_CARDS = Object.freeze([
|
|
70
70
|
{ id: 'read-only', title: 'Read-only', body: 'SynaBun answers, researches and plans. It never changes files, runs commands or starts agents from WhatsApp; a plan can only be approved on this computer.' },
|
|
71
71
|
{ id: 'ask', title: 'Ask on my phone', badge: 'Default', body: 'Before anything that would change your files, run a command or start an agent, SynaBun asks on WhatsApp and acts only on your yes. Any other message approves nothing: the conversation just carries on.' },
|
|
72
|
-
{ id: 'autonomous', title: 'Autonomous', body: 'SynaBun acts without asking, like the Assistant on this computer. Turning it on takes a second click here and an ALLOW code sent from your phone within 5 minutes. It
|
|
72
|
+
{ id: 'autonomous', title: 'Autonomous', body: 'SynaBun acts without asking, like the Assistant on this computer. Turning it on takes a second click here and an ALLOW code sent from your phone within 5 minutes. It stays on until you turn it off. Autonomous can read any file your computer account can, including SynaBun\'s WhatsApp login. Use it only with a locked phone, ideally on a second number.' },
|
|
73
73
|
]);
|
|
74
74
|
|
|
75
75
|
/** Ask and Autonomous need a Claude brain: the Safety warning when the WhatsApp conversation runs on another one (status.brainLimit). */
|
|
@@ -155,9 +155,35 @@ export const ROTATION_OPTIONS = Object.freeze([
|
|
|
155
155
|
]);
|
|
156
156
|
export const TRIGGER_OPTIONS = Object.freeze([
|
|
157
157
|
{ value: 'all', label: 'Every message in "Message yourself"', hint: 'Everything you write in your own chat goes to SynaBun.' },
|
|
158
|
-
{ value: 'prefix', label: 'Only messages that start with sb', hint: 'Keep using "Message yourself" for notes; start a message with sb (or sb:) to talk to SynaBun. Commands like /stop, the ALLOW code and replies to SynaBun\'s own messages always reach it.' },
|
|
158
|
+
{ value: 'prefix', label: 'Only messages that start with sb', hint: 'Keep using "Message yourself" for notes; start a message with sb (or sb:) to talk to SynaBun, or say "sb" first in a voice note. Commands like /stop, the ALLOW code and replies to SynaBun\'s own messages always reach it.' },
|
|
159
159
|
]);
|
|
160
160
|
|
|
161
|
+
/** Voice notes (status.transcription): what each missing part is called. */
|
|
162
|
+
export const VOICE_PARTS = Object.freeze({
|
|
163
|
+
engine: 'whisper.cpp (whisper-cli)',
|
|
164
|
+
model: 'the speech model (ggml-small.bin)',
|
|
165
|
+
ffmpeg: 'FFmpeg',
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* The line under the voice-note switch: transcribed here, set up but off, or what is missing
|
|
169
|
+
* ('' for a server without voice notes).
|
|
170
|
+
*/
|
|
171
|
+
export function transcriptionLine(status) {
|
|
172
|
+
const t = status?.transcription;
|
|
173
|
+
if (!t || typeof t !== 'object') return '';
|
|
174
|
+
if (t.available === true) {
|
|
175
|
+
return t.enabled === false
|
|
176
|
+
? say('voice.readyOff', 'Voice notes can be transcribed on this computer; turned off.')
|
|
177
|
+
: say('voice.ready', 'Voice notes are transcribed on this computer.');
|
|
178
|
+
}
|
|
179
|
+
const invalid = Array.isArray(t.invalid) ? t.invalid : [];
|
|
180
|
+
const parts = (Array.isArray(t.missing) ? t.missing : []).filter((id) => Object.prototype.hasOwnProperty.call(VOICE_PARTS, id)).map((id) => {
|
|
181
|
+
const name = pick('voice.part', VOICE_PARTS, id);
|
|
182
|
+
return invalid.includes(id) ? say('voice.partInvalid', '{name}: the path set for it does not work', { name }) : name;
|
|
183
|
+
});
|
|
184
|
+
return say('voice.notSetUp', 'Voice notes: not set up — missing {missing}.', { missing: parts.length ? parts.join(', ') : say('voice.part.tools', 'the transcription tools') });
|
|
185
|
+
}
|
|
186
|
+
|
|
161
187
|
export const COMMANDS = Object.freeze([
|
|
162
188
|
{ name: '/status', text: 'what SynaBun is doing, its spend and level' },
|
|
163
189
|
{ name: '/stop', text: 'stop the current task, its agents and anything waiting for your answer' },
|
|
@@ -170,12 +196,13 @@ export const COMMANDS = Object.freeze([
|
|
|
170
196
|
]);
|
|
171
197
|
|
|
172
198
|
export const LIMITS = Object.freeze([
|
|
173
|
-
'Text and pictures (up to 4 per message, 5 MB each)
|
|
199
|
+
'Text and pictures (up to 4 per message, 5 MB each), and voice notes transcribed on this computer (up to 10 minutes and 20 MB each). Videos, documents and stickers are not read yet.',
|
|
174
200
|
'At most 20 messages a minute and 300 a day; 5 messages can wait in line while SynaBun works.',
|
|
175
201
|
'Messages older than 10 minutes when SynaBun comes back online are skipped (it tells you how many).',
|
|
176
202
|
'Answers are split into messages of 3,500 characters; the rest stays in SynaBun.',
|
|
177
203
|
'Computer use from WhatsApp is off until you turn it on above. Then: never at Read-only or while paused, after one yes per task at Ask on my phone, and without asking while Autonomous is active. Agents started from WhatsApp never get it.',
|
|
178
204
|
'Levels, models and settings change only here, never from the phone.',
|
|
205
|
+
'A voice note is an ordinary message: it never approves anything and never runs a command. Approvals take a typed yes.',
|
|
179
206
|
]);
|
|
180
207
|
|
|
181
208
|
export const PRIVACY_STAYS = Object.freeze([
|
|
@@ -213,6 +240,7 @@ export const HELP = Object.freeze({
|
|
|
213
240
|
'With "Only messages that start with sb", a note without sb never reaches SynaBun and is not logged; commands, the ALLOW code and replies to SynaBun\'s messages always get through.',
|
|
214
241
|
'The QR code expires after about a minute. Press "Show a new code" and scan faster, or link with your phone number instead.',
|
|
215
242
|
'Stuck on "Reconnecting"? Check this computer\'s internet connection, then press Reconnect now.',
|
|
243
|
+
'Voice notes not transcribed? This computer needs whisper.cpp, its speech model and FFmpeg, which you install yourself; the line under "Transcribe voice notes" says what is missing.',
|
|
216
244
|
],
|
|
217
245
|
browserTools: 'Not the same as the WhatsApp browser tools. The whatsapp MCP profile lets agents read WhatsApp Web in SynaBun\'s browser; this tab is you chatting with SynaBun from your phone. They do not share a session.',
|
|
218
246
|
uninstall: 'Uninstalling SynaBun does not unlink WhatsApp. Use Unlink or Remove here first, or log SynaBun out under WhatsApp → Settings → Linked devices.',
|
|
@@ -252,8 +280,11 @@ export const INSTALL_ERRORS = Object.freeze({
|
|
|
252
280
|
UNKNOWN: 'Something unexpected happened. The install log has the details.',
|
|
253
281
|
});
|
|
254
282
|
|
|
283
|
+
// RECONNECT_LIMIT and REPLACED only come from a server older than this page (the link now retries
|
|
284
|
+
// forever, and a 440 is retried with a warning: WARNING_TEXT); HOST_HELD is a connector process of
|
|
285
|
+
// another SynaBun version (crashes are always retried).
|
|
255
286
|
export const ERROR_TEXT = Object.freeze({
|
|
256
|
-
HOST_HELD: 'The WhatsApp connector
|
|
287
|
+
HOST_HELD: 'The WhatsApp connector does not match this SynaBun version (it was updated while SynaBun ran), so SynaBun stopped it. Restart SynaBun to load the matching one.',
|
|
257
288
|
HOST_UNAVAILABLE: 'The WhatsApp connector did not start.',
|
|
258
289
|
REPLACED: 'Another copy of this WhatsApp link connected from somewhere else and took over. Reconnect here to take it back.',
|
|
259
290
|
LOCKED: 'Another SynaBun is using the WhatsApp session files. Close it, then reconnect.',
|
|
@@ -272,7 +303,20 @@ export const LOGOUT_TEXT = Object.freeze({
|
|
|
272
303
|
removed: { title: 'Logged out from the phone', sub: 'SynaBun was removed under Linked devices, or WhatsApp ended the session. Link again to keep chatting.' },
|
|
273
304
|
inactive: { title: 'Logged out after a long time offline', sub: 'WhatsApp logs out linked devices that stay offline for a long time. Link again to keep chatting.' },
|
|
274
305
|
banned: { title: 'WhatsApp refused this account', sub: 'WhatsApp blocked the account from linking devices, possibly a temporary or permanent ban. Check the WhatsApp app on the phone.' },
|
|
306
|
+
invalid_session: { title: 'The saved WhatsApp session is invalid', sub: 'WhatsApp rejected this device session (badSession). Link again to pair it; automatic retries cannot repair the credentials.' },
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
/** Why a saved session keeps retrying (status.warning: 440 another copy, 403 a refused account). */
|
|
310
|
+
export const WARNING_TEXT = Object.freeze({
|
|
311
|
+
replaced: 'Another copy is using this WhatsApp session. SynaBun retries every 5 minutes; close the other copy or unlink and link again.',
|
|
312
|
+
forbidden: 'WhatsApp refused this account; it may be restricted or banned. SynaBun retries every 5 minutes; check WhatsApp on the phone.',
|
|
275
313
|
});
|
|
314
|
+
/** The warning Settings shows while the link retries a 440 / 403 ('' for none, or once the link is not up or retrying). */
|
|
315
|
+
export function connectionWarningText(status) {
|
|
316
|
+
if (!Object.prototype.hasOwnProperty.call(WARNING_TEXT, status?.warning)) return '';
|
|
317
|
+
if (!['connected', 'reconnecting', 'paused'].includes(status?.state)) return '';
|
|
318
|
+
return pick('warning', WARNING_TEXT, status.warning);
|
|
319
|
+
}
|
|
276
320
|
|
|
277
321
|
export const ACTIVITY_KINDS = Object.freeze({
|
|
278
322
|
inbound: 'Received', reply: 'Sent', ignored: 'Ignored', state: 'Status', security: 'Security', error: 'Problem', settings: 'Settings',
|
|
@@ -355,9 +399,8 @@ export function waView(status, { now = Date.now() } = {}) {
|
|
|
355
399
|
}
|
|
356
400
|
case 'connected': {
|
|
357
401
|
const who = accountLine(s);
|
|
358
|
-
const until = s.level === 'autonomous' && s.levelExpiresAt ? ` ${say('view.connected.until', 'until {time}', { time: clockTime(s.levelExpiresAt) })}` : '';
|
|
359
402
|
// A Codex / OpenCode brain holds the conversation at read-only whatever the level.
|
|
360
|
-
const applies = s.brainLimit?.provider ? say('view.connected.readOnlyBrain', 'Read-only ({brain} brain)', { brain: s.brainLimit.label || s.brainLimit.provider }) :
|
|
403
|
+
const applies = s.brainLimit?.provider ? say('view.connected.readOnlyBrain', 'Read-only ({brain} brain)', { brain: s.brainLimit.label || s.brainLimit.provider }) : level;
|
|
361
404
|
return view('ok', say('view.connected.title', 'Connected'), [mode, who, applies].filter(Boolean).join(' · '), { primary: button('open-conversation', say('button.openConversation', 'Open conversation')), secondary: button('test', say('button.test', 'Send a test message')), step: 'done', pane: 'connected', nav: 'connected' });
|
|
362
405
|
}
|
|
363
406
|
case 'reconnecting': {
|
|
@@ -404,8 +447,8 @@ export function localizedCopy() {
|
|
|
404
447
|
COMMANDS: localize('commands', COMMANDS), LIMITS: localize('limits', LIMITS),
|
|
405
448
|
PRIVACY_STAYS: localize('privacyStays', PRIVACY_STAYS), PRIVACY_NEVER: localize('privacyNever', PRIVACY_NEVER),
|
|
406
449
|
HELP: localize('help', HELP), STAGE_TEXT: localize('stage', STAGE_TEXT), INSTALL_ERRORS: localize('installError', INSTALL_ERRORS),
|
|
407
|
-
ERROR_TEXT: localize('error', ERROR_TEXT), LOGOUT_TEXT: localize('logout', LOGOUT_TEXT), ACTIVITY_KINDS: localize('activity', ACTIVITY_KINDS),
|
|
450
|
+
ERROR_TEXT: localize('error', ERROR_TEXT), LOGOUT_TEXT: localize('logout', LOGOUT_TEXT), WARNING_TEXT: localize('warning', WARNING_TEXT), ACTIVITY_KINDS: localize('activity', ACTIVITY_KINDS),
|
|
408
451
|
LEVEL_LABELS: localize('levelLabel', LEVEL_LABELS), PHONE_HINT: localize('phoneHint', PHONE_HINT), TEST_HINT: localize('testHint', TEST_HINT),
|
|
409
|
-
BRAIN_COPY: localize('brainCopy', BRAIN_COPY),
|
|
452
|
+
BRAIN_COPY: localize('brainCopy', BRAIN_COPY), VOICE_PARTS: localize('voice.part', VOICE_PARTS),
|
|
410
453
|
};
|
|
411
454
|
}
|