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
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — the desktop app's updates: what the page shows
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Inside the SynaBun desktop app the updater is the app's own (packaging/desktop):
|
|
6
|
+
// it reads the release feed, downloads at once, and installs by itself when
|
|
7
|
+
// SynaBun is idle, after a one-minute notice the user can postpone. The page
|
|
8
|
+
// only shows what the updater reports through window.synabunDesktop.updates
|
|
9
|
+
// (desktop-bridge.js): the top-right badge, the Notifications drawer, the toast
|
|
10
|
+
// of Apps > Check for updates, the update dialog and the notice (countdown,
|
|
11
|
+
// "updated", a failed install) in ui-update.js. One reading of a report for all
|
|
12
|
+
// of them, so they never disagree.
|
|
13
|
+
//
|
|
14
|
+
// No imports and no DOM: `node --test` loads this file as it is
|
|
15
|
+
// (tests/desktop-update-view.test.mjs). DESKTOP_COPY is the English of every
|
|
16
|
+
// sentence; `desktop` in i18n/en.json must equal it and i18n/pt-BR.json must
|
|
17
|
+
// have the same keys with the same {values} (the test checks both). The
|
|
18
|
+
// offline page, which can load nothing, writes DESKTOP_COPY.offline.hint as it
|
|
19
|
+
// is.
|
|
20
|
+
|
|
21
|
+
export const DESKTOP_COPY = Object.freeze({
|
|
22
|
+
update: Object.freeze({
|
|
23
|
+
source: 'SynaBun app',
|
|
24
|
+
tooltip: 'SynaBun update available: v{current} → v{latest}',
|
|
25
|
+
tooltipDownloading: 'Downloading SynaBun v{latest}',
|
|
26
|
+
tooltipReady: 'SynaBun v{latest} is ready: it installs when SynaBun is idle',
|
|
27
|
+
titleAvailable: 'Update available',
|
|
28
|
+
titleDownloading: 'Downloading the update',
|
|
29
|
+
titleDownloaded: 'Update ready',
|
|
30
|
+
titleInstalling: 'Installing the update',
|
|
31
|
+
titleMove: 'Move SynaBun to Applications',
|
|
32
|
+
titleManual: 'Install the update yourself',
|
|
33
|
+
titleError: 'The update did not finish',
|
|
34
|
+
notesLabel: 'What\'s new',
|
|
35
|
+
notesEmpty: 'This release has no notes.',
|
|
36
|
+
snapshot: 'Before v{version} starts for the first time, SynaBun takes a verified snapshot of your data.',
|
|
37
|
+
backup: 'Download full backup',
|
|
38
|
+
backupWorking: 'Creating backup...',
|
|
39
|
+
backupDone: '{file} ({size} MB)',
|
|
40
|
+
backupFailed: 'Backup failed: {reason}',
|
|
41
|
+
later: 'Later',
|
|
42
|
+
download: 'Download update',
|
|
43
|
+
downloadStarting: 'Starting the download.',
|
|
44
|
+
progress: '{transferred} of {total} MB',
|
|
45
|
+
progressUnknown: '{transferred} MB downloaded',
|
|
46
|
+
hide: 'Hide',
|
|
47
|
+
hideHint: 'The download continues while this is hidden. SynaBun installs the update by itself when nothing is running.',
|
|
48
|
+
readyBody: 'SynaBun v{version} is downloaded. It installs by itself once nothing is running: SynaBun shows a one-minute notice, then restarts into it. It also installs when you quit SynaBun.',
|
|
49
|
+
waitingBody: 'Waiting for: {list}.',
|
|
50
|
+
countdownBody: 'SynaBun restarts into v{version} in {seconds} s.',
|
|
51
|
+
postponedBody: 'Postponed until {time}. It also installs when you quit SynaBun.',
|
|
52
|
+
nowBody: 'SynaBun restarts into v{version} as soon as nothing is running.',
|
|
53
|
+
installNow: 'Install now',
|
|
54
|
+
installingBody: 'SynaBun is stopping its server and installing v{version}. It closes and opens again by itself.',
|
|
55
|
+
moveBody: 'macOS is running SynaBun from a disk image or a temporary location, where it cannot update itself. Move it to the Applications folder; SynaBun opens again from there and can update.',
|
|
56
|
+
move: 'Move to Applications',
|
|
57
|
+
manualBody: 'SynaBun cannot replace itself in its current folder. Download the disk image of v{version}, open it and drag SynaBun to the Applications folder.',
|
|
58
|
+
manualReady: 'The disk image of v{version} is downloaded. Open it and drag SynaBun to the Applications folder to replace the old copy.',
|
|
59
|
+
manualFile: 'File: {path}',
|
|
60
|
+
manualDownload: 'Download disk image',
|
|
61
|
+
showFile: 'Show disk image',
|
|
62
|
+
errorFallback: 'SynaBun could not check for updates. Check the connection and try again.',
|
|
63
|
+
errorNext: 'SynaBun keeps the version it runs and tries again at its next check. You can try now, or download the new version yourself.',
|
|
64
|
+
manualLink: 'Download it yourself',
|
|
65
|
+
close: 'Close',
|
|
66
|
+
retry: 'Try again',
|
|
67
|
+
testFeed: 'test feed',
|
|
68
|
+
metaAvailable: 'From the SynaBun app',
|
|
69
|
+
metaDownloading: 'Downloading: {percent}%',
|
|
70
|
+
metaDownloaded: 'Ready: installs when SynaBun is idle',
|
|
71
|
+
metaCountdown: 'Restarting to install it',
|
|
72
|
+
metaPostponed: 'Postponed: installs on quit or later',
|
|
73
|
+
}),
|
|
74
|
+
// What an update waits for (the app's server names it, GET /api/system/activity).
|
|
75
|
+
busy: Object.freeze({
|
|
76
|
+
assistant: 'an Assistant run or dispatched agent',
|
|
77
|
+
'claude-panel': 'a Claude Code panel reply',
|
|
78
|
+
'codex-panel': 'a Codex panel reply',
|
|
79
|
+
'opencode-panel': 'an OpenCode panel reply',
|
|
80
|
+
'claude-cli': 'a Claude Code session in use',
|
|
81
|
+
loop: 'a loop',
|
|
82
|
+
schedule: 'a schedule',
|
|
83
|
+
backup: 'a backup',
|
|
84
|
+
maintenance: 'indexing or an install',
|
|
85
|
+
unknown: 'work SynaBun cannot see the end of',
|
|
86
|
+
test: 'the test switch',
|
|
87
|
+
}),
|
|
88
|
+
// The notice at the bottom right: the countdown before the restart, "updated", a failed install.
|
|
89
|
+
notice: Object.freeze({
|
|
90
|
+
countdownTitle: 'Updating to v{version}',
|
|
91
|
+
countdownLine: 'SynaBun restarts in {seconds} s.',
|
|
92
|
+
later: 'Later',
|
|
93
|
+
postponed: 'SynaBun asks again in an hour, or installs the update when you quit it.',
|
|
94
|
+
updatedTitle: 'SynaBun is updated',
|
|
95
|
+
updatedLine: 'Now v{version}, updated from v{previous}.',
|
|
96
|
+
updatedLineShort: 'Now v{version}.',
|
|
97
|
+
failedTitle: 'The update did not finish',
|
|
98
|
+
details: 'Details',
|
|
99
|
+
close: 'Close',
|
|
100
|
+
}),
|
|
101
|
+
menu: Object.freeze({
|
|
102
|
+
quit: 'Quit SynaBun',
|
|
103
|
+
}),
|
|
104
|
+
offline: Object.freeze({
|
|
105
|
+
hint: 'The SynaBun app restarts its server by itself. If it stays offline, quit SynaBun and open it again.',
|
|
106
|
+
stalled: 'The server has not come back. Quit SynaBun and open it again.',
|
|
107
|
+
failedHint: 'Quit SynaBun and open it again. If the start fails, the start screen says why.',
|
|
108
|
+
}),
|
|
109
|
+
// The window's title bar (desktop-titlebar.js): Windows and Linux open the app's menu from a button in it.
|
|
110
|
+
titleBar: Object.freeze({
|
|
111
|
+
appMenu: 'SynaBun menu',
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/** Where SynaBun is downloaded by hand, when the app names nothing better. */
|
|
116
|
+
export const DESKTOP_RELEASES_URL = 'https://github.com/danilokhury/Synabun/releases/latest';
|
|
117
|
+
|
|
118
|
+
/** A DESKTOP_COPY sentence (`update.download`, `offline.hint`) with its `{params}` filled in: the translator when the page gives none. */
|
|
119
|
+
export function fillDesktopCopy(key, params = {}) {
|
|
120
|
+
const value = String(key ?? '').split('.').reduce((node, part) => (node && typeof node === 'object' ? node[part] : undefined), DESKTOP_COPY);
|
|
121
|
+
if (typeof value !== 'string') return String(key ?? '');
|
|
122
|
+
return value.replace(/\{(\w+)\}/g, (all, name) => (params && params[name] != null ? String(params[name]) : all));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const STATUSES = new Set(['idle', 'checking', 'not-available', 'available', 'downloading', 'downloaded', 'installing', 'error']);
|
|
126
|
+
const INSTALL_MODES = new Set(['restart', 'move-to-applications', 'manual-download']);
|
|
127
|
+
const PHASES = new Set(['waiting', 'countdown', 'postponed']);
|
|
128
|
+
const BUSY_KINDS = Object.keys(DESKTOP_COPY.busy);
|
|
129
|
+
// The statuses in which a version is on offer, between the check that found it and the install.
|
|
130
|
+
const OFFERED = new Set(['available', 'downloading', 'downloaded', 'installing']);
|
|
131
|
+
|
|
132
|
+
const text = (value, max) => (typeof value === 'string' && value.trim() ? value.trim().slice(0, max) : null);
|
|
133
|
+
const amount = (value) => {
|
|
134
|
+
const number = Number(value);
|
|
135
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
136
|
+
};
|
|
137
|
+
const instant = (value) => (typeof value === 'string' && value.length <= 64 && Number.isFinite(Date.parse(value)) ? value : null);
|
|
138
|
+
|
|
139
|
+
function readProgress(value) {
|
|
140
|
+
if (!value || typeof value !== 'object') return null;
|
|
141
|
+
const total = amount(value.total);
|
|
142
|
+
const transferred = total > 0 ? Math.min(amount(value.transferred), total) : amount(value.transferred);
|
|
143
|
+
const given = value.percent === null || value.percent === undefined || value.percent === '' ? NaN : Number(value.percent);
|
|
144
|
+
const percent = Number.isFinite(given) ? given : total > 0 ? (transferred / total) * 100 : 0;
|
|
145
|
+
return { percent: Math.max(0, Math.min(100, percent)), transferred, total, bytesPerSecond: amount(value.bytesPerSecond) };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The automatic install's moment: what it waits for, when it restarts, until when it is postponed. */
|
|
149
|
+
function readAuto(value) {
|
|
150
|
+
if (!value || typeof value !== 'object' || !PHASES.has(value.phase)) return null;
|
|
151
|
+
const busy = (Array.isArray(value.busy) ? value.busy : [])
|
|
152
|
+
.filter((item) => item && typeof item === 'object')
|
|
153
|
+
.map((item) => ({ kind: BUSY_KINDS.includes(item.kind) ? item.kind : 'unknown', count: Math.max(1, Math.floor(Number(item.count)) || 1) }))
|
|
154
|
+
.slice(0, 12);
|
|
155
|
+
return {
|
|
156
|
+
phase: value.phase,
|
|
157
|
+
busy,
|
|
158
|
+
installAt: value.phase === 'countdown' ? instant(value.installAt) : null,
|
|
159
|
+
postponedUntil: value.phase === 'postponed' ? instant(value.postponedUntil) : null,
|
|
160
|
+
now: value.now === true,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function readUpdated(value) {
|
|
165
|
+
if (!value || typeof value !== 'object') return null;
|
|
166
|
+
const version = text(value.version, 64);
|
|
167
|
+
return version ? { version, previous: text(value.previous, 64) } : null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Only SynaBun's own releases page: a report cannot point the page anywhere else. */
|
|
171
|
+
function readReleasesUrl(value) {
|
|
172
|
+
return typeof value === 'string' && /^https:\/\/github\.com\/danilokhury\/Synabun\/releases(?:\/[\w./-]*)?$/.test(value) ? value : DESKTOP_RELEASES_URL;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* One report of the app's updater, checked field by field: whatever is missing
|
|
177
|
+
* or of the wrong kind reads as nothing (an unknown status is 'idle', an
|
|
178
|
+
* unknown install mode is 'restart'), so a page never draws a half answer.
|
|
179
|
+
*/
|
|
180
|
+
export function readDesktopUpdateState(state) {
|
|
181
|
+
const s = state && typeof state === 'object' ? state : {};
|
|
182
|
+
return {
|
|
183
|
+
supported: s.supported === true,
|
|
184
|
+
status: STATUSES.has(s.status) ? s.status : 'idle',
|
|
185
|
+
current: text(s.current, 64) || '',
|
|
186
|
+
latest: text(s.latest, 64),
|
|
187
|
+
notes: text(s.notes, 20000),
|
|
188
|
+
releaseDate: text(s.releaseDate, 64),
|
|
189
|
+
progress: readProgress(s.progress),
|
|
190
|
+
error: text(s.error, 1000),
|
|
191
|
+
checkedAt: text(s.checkedAt, 64),
|
|
192
|
+
install: INSTALL_MODES.has(s.install) ? s.install : 'restart',
|
|
193
|
+
manualFile: text(s.manualFile, 4096),
|
|
194
|
+
testFeed: s.testFeed === true,
|
|
195
|
+
auto: readAuto(s.auto),
|
|
196
|
+
updated: readUpdated(s.updated),
|
|
197
|
+
releasesUrl: readReleasesUrl(s.releasesUrl),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** True when the report offers a version: it is supported, says which one, and is between the check and the install. */
|
|
202
|
+
function offers(s) {
|
|
203
|
+
return s.supported && OFFERED.has(s.status) && !!s.latest;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Whole seconds until `at` (an ISO time), never below 0. */
|
|
207
|
+
export function secondsUntil(at, now = Date.now()) {
|
|
208
|
+
const target = Date.parse(at);
|
|
209
|
+
return Number.isFinite(target) ? Math.max(0, Math.ceil((target - now) / 1000)) : 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* What the rest of the page reads as `_versionData` (ui-update.js), in the
|
|
214
|
+
* shape the npm / Git check gives it: `updateAvailable`, `current`, `latest`,
|
|
215
|
+
* `source`. `desktop: true` says where it came from; the report's own fields
|
|
216
|
+
* ride along for the dialog.
|
|
217
|
+
*/
|
|
218
|
+
export function versionDataFromDesktop(state) {
|
|
219
|
+
const s = readDesktopUpdateState(state);
|
|
220
|
+
const offered = offers(s);
|
|
221
|
+
return {
|
|
222
|
+
desktop: true,
|
|
223
|
+
supported: s.supported,
|
|
224
|
+
updateAvailable: offered,
|
|
225
|
+
current: s.current,
|
|
226
|
+
latest: offered ? s.latest : null,
|
|
227
|
+
source: 'app',
|
|
228
|
+
installedChannel: 'stable',
|
|
229
|
+
installPlan: null,
|
|
230
|
+
status: s.status,
|
|
231
|
+
progress: s.progress,
|
|
232
|
+
error: s.error,
|
|
233
|
+
notes: s.notes,
|
|
234
|
+
install: s.install,
|
|
235
|
+
manualFile: s.manualFile,
|
|
236
|
+
testFeed: s.testFeed,
|
|
237
|
+
checkedAt: s.checkedAt,
|
|
238
|
+
auto: s.auto,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Which page of the dialog a report is: 'available', 'downloading',
|
|
244
|
+
* 'downloaded', 'installing', 'move' (macOS runs this copy where it cannot be
|
|
245
|
+
* replaced: move it to Applications first), 'manual' (a folder SynaBun cannot
|
|
246
|
+
* write: the disk image, by hand), 'error', or 'none' (nothing to show: no
|
|
247
|
+
* update, a check under way, an unsupported run).
|
|
248
|
+
*/
|
|
249
|
+
export function desktopUpdateStep(state) {
|
|
250
|
+
const s = readDesktopUpdateState(state);
|
|
251
|
+
if (!s.supported) return 'none';
|
|
252
|
+
if (s.status === 'error') return 'error';
|
|
253
|
+
if (!offers(s)) return 'none';
|
|
254
|
+
if (s.status === 'downloading') return 'downloading';
|
|
255
|
+
if (s.status === 'installing') return 'installing';
|
|
256
|
+
if (s.install === 'move-to-applications') return 'move';
|
|
257
|
+
if (s.install === 'manual-download') return 'manual';
|
|
258
|
+
return s.status === 'downloaded' ? 'downloaded' : 'available';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** The bar and its words: whole percent (never 100 before it is), megabytes with one decimal. */
|
|
262
|
+
function progressOf(progress, say, number) {
|
|
263
|
+
if (!progress || (!progress.total && !progress.transferred)) return { percent: 0, text: say('downloadStarting') };
|
|
264
|
+
const megabytes = (bytes) => number(bytes / 1048576, 1);
|
|
265
|
+
if (progress.total > 0) {
|
|
266
|
+
return { percent: Math.floor(progress.percent), text: say('progress', { transferred: megabytes(progress.transferred), total: megabytes(progress.total) }) };
|
|
267
|
+
}
|
|
268
|
+
return { percent: null, text: say('progressUnknown', { transferred: megabytes(progress.transferred) }) };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** What an update waits for, as words: "a loop, a Codex panel reply". */
|
|
272
|
+
export function desktopBusyList(busy = [], { t = fillDesktopCopy } = {}) {
|
|
273
|
+
return (Array.isArray(busy) ? busy : []).map((item) => t(`busy.${BUSY_KINDS.includes(item?.kind) ? item.kind : 'unknown'}`)).join(', ');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Everything the update dialog draws for one report, as data:
|
|
278
|
+
* step desktopUpdateStep()
|
|
279
|
+
* dot 1 (offered) · 2 (downloading) · 3 (ready, installing) · 0 (no dots)
|
|
280
|
+
* title the heading
|
|
281
|
+
* body sentences, in order
|
|
282
|
+
* notesLabel, notes the release notes (plain text: drawn as text, line breaks kept)
|
|
283
|
+
* progress { percent (whole, or null when the size is not known), text } while downloading
|
|
284
|
+
* file where the disk image was saved (manual, once it is downloaded)
|
|
285
|
+
* link { href, label }: SynaBun's releases page, after an update that did not finish
|
|
286
|
+
* backup { id: 'backup', label } next to the offer: a full backup, if the user wants one first
|
|
287
|
+
* actions [{ id, kind: 'ghost' | 'primary', label }] in the order they are drawn
|
|
288
|
+
* ids: later, download, hide, install-now, move, manual-download, show-file, close, retry
|
|
289
|
+
* retry what Try again does after an error: 'download' (a version was on offer) or 'check'
|
|
290
|
+
* busy the step is the app working (downloading, installing)
|
|
291
|
+
* ticking a sentence counts down: the page draws it again every second
|
|
292
|
+
* `t` translates `update.<key>` (and `busy.<kind>`) with its params; DESKTOP_COPY
|
|
293
|
+
* is the default. `now` is the time the countdown counts from; `time` writes an
|
|
294
|
+
* ISO time the way the page's language writes a time of day.
|
|
295
|
+
*/
|
|
296
|
+
export function desktopUpdateView(state, {
|
|
297
|
+
t = fillDesktopCopy, number = (value, digits) => value.toFixed(digits), now = Date.now(),
|
|
298
|
+
time = (iso) => new Date(iso).toISOString().slice(11, 16),
|
|
299
|
+
} = {}) {
|
|
300
|
+
const s = readDesktopUpdateState(state);
|
|
301
|
+
const step = desktopUpdateStep(s);
|
|
302
|
+
const say = (key, params) => t(`update.${key}`, params);
|
|
303
|
+
const version = s.latest || '';
|
|
304
|
+
const action = (id, kind, key) => ({ id, kind, label: say(key) });
|
|
305
|
+
const view = {
|
|
306
|
+
step, dot: 0, title: '', body: [], notesLabel: '', notes: null, progress: null, file: null, link: null,
|
|
307
|
+
backup: null, actions: [], retry: null, busy: false, ticking: false,
|
|
308
|
+
current: s.current, latest: s.latest, testFeed: s.testFeed,
|
|
309
|
+
};
|
|
310
|
+
switch (step) {
|
|
311
|
+
case 'available':
|
|
312
|
+
view.dot = 1;
|
|
313
|
+
view.title = say('titleAvailable');
|
|
314
|
+
view.body = [say('snapshot', { version })];
|
|
315
|
+
view.notesLabel = say('notesLabel');
|
|
316
|
+
view.notes = s.notes || say('notesEmpty');
|
|
317
|
+
view.backup = { id: 'backup', label: say('backup') };
|
|
318
|
+
view.actions = [action('later', 'ghost', 'later'), action('download', 'primary', 'download')];
|
|
319
|
+
break;
|
|
320
|
+
case 'downloading':
|
|
321
|
+
view.dot = 2;
|
|
322
|
+
view.title = say('titleDownloading');
|
|
323
|
+
view.progress = progressOf(s.progress, say, number);
|
|
324
|
+
view.body = [say('hideHint')];
|
|
325
|
+
view.actions = [action('hide', 'ghost', 'hide')];
|
|
326
|
+
view.busy = true;
|
|
327
|
+
break;
|
|
328
|
+
case 'downloaded': {
|
|
329
|
+
view.dot = 3;
|
|
330
|
+
view.title = say('titleDownloaded');
|
|
331
|
+
view.body = [say('readyBody', { version })];
|
|
332
|
+
const auto = s.auto;
|
|
333
|
+
if (auto?.phase === 'countdown' && auto.installAt) {
|
|
334
|
+
view.body.push(say('countdownBody', { version, seconds: secondsUntil(auto.installAt, now) }));
|
|
335
|
+
view.ticking = true;
|
|
336
|
+
} else if (auto?.phase === 'postponed' && auto.postponedUntil) {
|
|
337
|
+
view.body.push(say('postponedBody', { time: time(auto.postponedUntil) }));
|
|
338
|
+
} else if (auto?.now) {
|
|
339
|
+
view.body.push(say('nowBody', { version }));
|
|
340
|
+
}
|
|
341
|
+
if (auto?.phase === 'waiting' && auto.busy.length) view.body.push(say('waitingBody', { list: desktopBusyList(auto.busy, { t }) }));
|
|
342
|
+
view.actions = [
|
|
343
|
+
auto?.phase === 'countdown' ? action('later', 'ghost', 'later') : action('close', 'ghost', 'close'),
|
|
344
|
+
action('install-now', 'primary', 'installNow'),
|
|
345
|
+
];
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
case 'installing':
|
|
349
|
+
view.dot = 3;
|
|
350
|
+
view.title = say('titleInstalling');
|
|
351
|
+
view.body = [say('installingBody', { version })];
|
|
352
|
+
view.busy = true;
|
|
353
|
+
break;
|
|
354
|
+
case 'move':
|
|
355
|
+
view.dot = 1;
|
|
356
|
+
view.title = say('titleMove');
|
|
357
|
+
view.body = [say('moveBody')];
|
|
358
|
+
view.actions = [action('later', 'ghost', 'later'), action('move', 'primary', 'move')];
|
|
359
|
+
break;
|
|
360
|
+
case 'manual':
|
|
361
|
+
view.title = say('titleManual');
|
|
362
|
+
if (s.status === 'downloaded') {
|
|
363
|
+
view.dot = 3;
|
|
364
|
+
view.body = [say('manualReady', { version })];
|
|
365
|
+
view.file = s.manualFile ? say('manualFile', { path: s.manualFile }) : null;
|
|
366
|
+
view.actions = [action('close', 'ghost', 'close'), action('show-file', 'primary', 'showFile')];
|
|
367
|
+
} else {
|
|
368
|
+
view.dot = 1;
|
|
369
|
+
view.body = [say('manualBody', { version })];
|
|
370
|
+
view.actions = [action('later', 'ghost', 'later'), action('manual-download', 'primary', 'manualDownload')];
|
|
371
|
+
}
|
|
372
|
+
break;
|
|
373
|
+
case 'error':
|
|
374
|
+
view.title = say('titleError');
|
|
375
|
+
view.body = [s.error || say('errorFallback')];
|
|
376
|
+
view.retry = s.latest ? 'download' : 'check';
|
|
377
|
+
if (s.latest) {
|
|
378
|
+
// A version was on offer and did not arrive or install: the app keeps the old one, and a person can fetch the new one.
|
|
379
|
+
view.body.push(say('errorNext'));
|
|
380
|
+
view.link = { href: s.releasesUrl, label: say('manualLink') };
|
|
381
|
+
}
|
|
382
|
+
view.actions = [action('close', 'ghost', 'close'), action('retry', 'primary', 'retry')];
|
|
383
|
+
break;
|
|
384
|
+
default:
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
return view;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/** The line under the SynaBun item of Notifications > Updates, or '' when there is nothing on offer. */
|
|
391
|
+
export function desktopUpdateMeta(state, { t = fillDesktopCopy } = {}) {
|
|
392
|
+
const s = readDesktopUpdateState(state);
|
|
393
|
+
switch (desktopUpdateStep(s)) {
|
|
394
|
+
case 'downloading': return t('update.metaDownloading', { percent: Math.floor(s.progress?.percent || 0) });
|
|
395
|
+
case 'downloaded':
|
|
396
|
+
if (s.auto?.phase === 'countdown') return t('update.metaCountdown');
|
|
397
|
+
if (s.auto?.phase === 'postponed') return t('update.metaPostponed');
|
|
398
|
+
return t('update.metaDownloaded');
|
|
399
|
+
case 'installing': return t('update.titleInstalling');
|
|
400
|
+
case 'available': case 'move': case 'manual': return t('update.metaAvailable');
|
|
401
|
+
default: return '';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/** The badge's tooltip: what the update is doing, never only that one exists. */
|
|
406
|
+
export function desktopUpdateTooltip(state, { t = fillDesktopCopy } = {}) {
|
|
407
|
+
const s = readDesktopUpdateState(state);
|
|
408
|
+
const params = { current: s.current, latest: s.latest || '' };
|
|
409
|
+
const step = desktopUpdateStep(s);
|
|
410
|
+
if (step === 'downloading') return t('update.tooltipDownloading', params);
|
|
411
|
+
if (step === 'downloaded') return t('update.tooltipReady', params);
|
|
412
|
+
return t('update.tooltip', params);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* The notice at the bottom right, or null:
|
|
417
|
+
* countdown SynaBun is idle and restarts into the update: the seconds left, and Later
|
|
418
|
+
* updated this copy runs after an update (once: the page acknowledges it)
|
|
419
|
+
* failed a version was on offer and did not download or install: why, and the releases page
|
|
420
|
+
* `key` changes only when the notice is another one (a countdown that restarts is another one).
|
|
421
|
+
*/
|
|
422
|
+
export function desktopUpdateNotice(state, { t = fillDesktopCopy, now = Date.now() } = {}) {
|
|
423
|
+
const s = readDesktopUpdateState(state);
|
|
424
|
+
if (!s.supported) return null;
|
|
425
|
+
if (s.status === 'downloaded' && s.latest && s.auto?.phase === 'countdown' && s.auto.installAt) {
|
|
426
|
+
const seconds = secondsUntil(s.auto.installAt, now);
|
|
427
|
+
return {
|
|
428
|
+
kind: 'countdown', key: `countdown:${s.latest}:${s.auto.installAt}`, tone: 'up', seconds,
|
|
429
|
+
title: t('notice.countdownTitle', { version: s.latest }), line: t('notice.countdownLine', { seconds }),
|
|
430
|
+
actions: [{ id: 'later', label: t('notice.later') }], link: null, ticking: true,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
if (s.updated) {
|
|
434
|
+
return {
|
|
435
|
+
kind: 'updated', key: `updated:${s.updated.version}`, tone: 'ok', seconds: null,
|
|
436
|
+
title: t('notice.updatedTitle'),
|
|
437
|
+
line: s.updated.previous ? t('notice.updatedLine', { version: s.updated.version, previous: s.updated.previous }) : t('notice.updatedLineShort', { version: s.updated.version }),
|
|
438
|
+
actions: [{ id: 'dismiss', label: t('notice.close') }], link: null, ticking: false,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
if (s.status === 'error' && s.latest && s.error) {
|
|
442
|
+
return {
|
|
443
|
+
kind: 'failed', key: `failed:${s.latest}:${s.error}`, tone: 'err', seconds: null,
|
|
444
|
+
title: t('notice.failedTitle'), line: s.error,
|
|
445
|
+
actions: [{ id: 'details', label: t('notice.details') }], link: { href: s.releasesUrl, label: t('update.manualLink') }, ticking: false,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* What a finished check ends in, for whoever asked for it (the native menu, the
|
|
453
|
+
* tray, Apps > Check for updates): 'offer' (open the dialog), 'up-to-date',
|
|
454
|
+
* 'error', or 'none' (an unsupported run, or a check still under way).
|
|
455
|
+
*/
|
|
456
|
+
export function desktopCheckOutcome(state) {
|
|
457
|
+
const s = readDesktopUpdateState(state);
|
|
458
|
+
if (!s.supported || s.status === 'checking') return 'none';
|
|
459
|
+
if (offers(s)) return 'offer';
|
|
460
|
+
if (s.status === 'error') return 'error';
|
|
461
|
+
return 'up-to-date';
|
|
462
|
+
}
|