synabun 2.0.0-beta → 2.0.5
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 +65 -0
- package/NOTICE +5 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +51 -0
- package/benchmarks/fixtures/browser/README.md +1 -1
- package/benchmarks/fixtures/desktop/README.md +1 -1
- package/docs/whatsapp.md +2 -2
- 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 +20 -0
- package/hooks/claude-code/stop.mjs +5 -5
- package/launcher.mjs +40 -0
- package/lib/claude-hooks.js +61 -8
- package/lib/client-config-repair.js +4 -3
- package/lib/data-home-migration.js +4 -0
- package/lib/desktop-pwa.js +206 -0
- package/lib/external-tools.js +221 -0
- package/lib/first-launch-protection.js +5 -0
- package/lib/packaged-runtime.js +110 -0
- package/lib/start-launcher.js +1396 -0
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/neural-interface/i18n/en.json +1540 -154
- package/neural-interface/i18n/pt-BR.json +1538 -153
- package/neural-interface/lib/assistant-api.js +62 -6
- package/neural-interface/lib/assistant-brains/claude.js +4 -0
- package/neural-interface/lib/assistant-catalog.js +179 -27
- package/neural-interface/lib/assistant-config.js +31 -2
- package/neural-interface/lib/assistant-dispatch.js +62 -13
- package/neural-interface/lib/assistant-envelope.js +9 -6
- package/neural-interface/lib/assistant-hidden-models.js +393 -66
- package/neural-interface/lib/assistant-memory.js +24 -10
- package/neural-interface/lib/assistant-persona.js +6 -2
- package/neural-interface/lib/assistant-pricing.js +21 -6
- package/neural-interface/lib/assistant-runtime.js +181 -12
- 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 +181 -0
- package/neural-interface/lib/augmented-path.js +23 -3
- package/neural-interface/lib/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-language.js +83 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-agent-bridge.js +87 -153
- package/neural-interface/lib/claude-executable.js +241 -0
- package/neural-interface/lib/claude-model-catalog.js +82 -93
- package/neural-interface/lib/claude-temporary.js +46 -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/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-diff-api.js +103 -0
- package/neural-interface/lib/git-read.js +202 -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/machine-names.js +88 -0
- package/neural-interface/lib/memory-api.js +31 -7
- package/neural-interface/lib/native-binary-runtime.js +69 -337
- package/neural-interface/lib/native-loop-providers.js +40 -49
- package/neural-interface/lib/offline-page.js +54 -0
- package/neural-interface/lib/plugin-installer.js +4 -2
- package/neural-interface/lib/project-storage.js +5 -7
- package/neural-interface/lib/request-gate.js +589 -0
- package/neural-interface/lib/session-title-generator.js +5 -0
- package/neural-interface/lib/synabun-update-plan.js +19 -0
- package/neural-interface/lib/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/package-lock.json +701 -253
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/install-app.html +34 -0
- package/neural-interface/public/manifest.json +2 -0
- package/neural-interface/public/offline.html +402 -66
- package/neural-interface/public/onboarding.html +264 -147
- package/neural-interface/public/shared/agent-runtime-options.js +22 -6
- package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +312 -62
- package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
- package/neural-interface/public/shared/assistant/asst-mascot.js +26 -64
- package/neural-interface/public/shared/assistant/asst-menu.js +12 -8
- package/neural-interface/public/shared/assistant/asst-panel.js +150 -28
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +0 -3
- package/neural-interface/public/shared/assistant/asst-render.js +219 -67
- package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
- package/neural-interface/public/shared/assistant/asst-route.js +23 -329
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +495 -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-state.js +185 -1
- package/neural-interface/public/shared/assistant/asst-styles.js +162 -6
- package/neural-interface/public/shared/blob-store.js +111 -22
- package/neural-interface/public/shared/cdx/cdx-panel.js +32 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
- package/neural-interface/public/shared/cdx/cdx-styles.js +36 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +87 -4
- package/neural-interface/public/shared/command-runner-model.js +30 -0
- package/neural-interface/public/shared/constants.js +6 -1
- package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +15 -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/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 +169 -170
- 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 +99 -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 +5 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +40 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
- package/neural-interface/public/shared/pwa-install-page.js +62 -0
- package/neural-interface/public/shared/pwa-install.css +12 -0
- package/neural-interface/public/shared/pwa-install.js +127 -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 +18 -4
- package/neural-interface/public/shared/settings/settings-rules.js +160 -0
- package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
- package/neural-interface/public/shared/start-bridge.js +802 -0
- package/neural-interface/public/shared/styleguide/sg-colors.js +5 -2
- package/neural-interface/public/shared/styleguide/sg-import-export.js +4 -3
- package/neural-interface/public/shared/styleguide/sg-kit.js +4 -1
- package/neural-interface/public/shared/styleguide/sg-panel.js +9 -1
- package/neural-interface/public/shared/styleguide/sg-typography.js +1 -0
- package/neural-interface/public/shared/styles.css +2219 -1117
- package/neural-interface/public/shared/synabun-mascot.js +20 -56
- package/neural-interface/public/shared/term-ready.js +307 -0
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +160 -19
- package/neural-interface/public/shared/ui-command-runner.js +251 -468
- 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-help.js +26 -0
- package/neural-interface/public/shared/ui-invite.js +126 -116
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +367 -12
- package/neural-interface/public/shared/ui-menubar.js +21 -55
- 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 +45 -21
- package/neural-interface/public/shared/ui-settings.js +491 -547
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
- package/neural-interface/public/shared/ui-sync.js +16 -0
- package/neural-interface/public/shared/ui-terminal.js +153 -149
- 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-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/worker-end.js +251 -0
- package/neural-interface/public/sw.js +3 -1
- package/neural-interface/public/variant/2d/main.js +2 -1
- package/neural-interface/public/variant/3d/main.js +2 -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/rebuild-pty.js +15 -12
- package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
- package/neural-interface/server.js +1092 -1212
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +13 -7
- package/postinstall.js +11 -81
- package/setup.js +111 -6
- package/benchmarks/browser-live-results.json +0 -79
- package/benchmarks/browser-v2-results.json +0 -258
- package/docs/browser-v2.md +0 -109
- package/docs/hook-integrity.md +0 -89
- package/docs/judgments.md +0 -182
- package/docs/style-guide.md +0 -246
- 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/scripts/audit-claude-hook-usage.mjs +0 -12
- package/scripts/audit-memory-duplicates.mjs +0 -44
- package/scripts/measure-claude-hook-overhead.mjs +0 -77
- package/scripts/recover-user-config.mjs +0 -254
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -1,17 +1,52 @@
|
|
|
1
1
|
// ═══════════════════════════════════════════
|
|
2
2
|
// SynaBun Neural Interface — Loading Overlay
|
|
3
|
-
// Health check, server start, server-offline retry, command copy
|
|
3
|
+
// Health check, server start, server-offline retry, command copy,
|
|
4
|
+
// and the restart the user asked for (the same screen, one more reason)
|
|
4
5
|
// ═══════════════════════════════════════════
|
|
5
6
|
|
|
6
7
|
import { fetchHealth, startHealth } from './api.js';
|
|
7
|
-
import { emit } from './state.js';
|
|
8
|
+
import { emit, on } from './state.js';
|
|
8
9
|
import { t } from './i18n.js';
|
|
10
|
+
import {
|
|
11
|
+
START_LIMITS, START_STORAGE, createStartBridge, fetchStartBeacon, isMacPlatform, isWindowsPlatform,
|
|
12
|
+
manualStartCommands, openStartLink, startBeaconTarget, startButtonUsable, startStatusView,
|
|
13
|
+
} from './start-bridge.js';
|
|
14
|
+
// Imported with the app, not when it is needed: once the server is down
|
|
15
|
+
// nothing more can be fetched, and that is exactly when the overlay wants it.
|
|
16
|
+
import { createMascot } from './synabun-mascot.js';
|
|
9
17
|
|
|
10
18
|
const $ = (id) => document.getElementById(id);
|
|
11
19
|
|
|
12
20
|
// ── Internal refs (resolved once on init) ──
|
|
13
21
|
let _statusDot = null;
|
|
14
22
|
let _initCallback = null;
|
|
23
|
+
// The server-offline state: watches for the server and owns the Start button.
|
|
24
|
+
let _offlineBridge = null;
|
|
25
|
+
// The title the overlay was given for "offline" (a start replaces it while it runs).
|
|
26
|
+
let _offlineTitle = '';
|
|
27
|
+
// The mascot rig in the overlay, mounted the first time the server is offline.
|
|
28
|
+
let _mascot = null;
|
|
29
|
+
// The overlay was put over the running app for a restart. Everything the page
|
|
30
|
+
// held (sockets, terminals, panel sessions) was the old server's, so once the
|
|
31
|
+
// server is back the page loads again instead of carrying on.
|
|
32
|
+
let _restartShown = false;
|
|
33
|
+
// The tab's title from before the restart, for when it is refused.
|
|
34
|
+
let _restartTitle = null;
|
|
35
|
+
|
|
36
|
+
// What the mascot does for each thing the page knows about a start
|
|
37
|
+
// (startStatusView's `mascot`), as poses of the shared rig.
|
|
38
|
+
const MASCOT_POSE = {
|
|
39
|
+
asleep: 'sleep',
|
|
40
|
+
waking: 'wait',
|
|
41
|
+
working: 'think',
|
|
42
|
+
ready: 'success',
|
|
43
|
+
failed: 'error',
|
|
44
|
+
stalled: 'offline',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function stored(key) {
|
|
48
|
+
try { return localStorage.getItem(key); } catch { return null; }
|
|
49
|
+
}
|
|
15
50
|
|
|
16
51
|
// ═══════════════════════════════════════════
|
|
17
52
|
// PUBLIC API
|
|
@@ -38,18 +73,32 @@ export function showLoadingError(title, sub, canStart, serverOffline) {
|
|
|
38
73
|
const $sub = $('loading-sub');
|
|
39
74
|
if ($text) $text.textContent = title;
|
|
40
75
|
if ($sub) $sub.textContent = sub;
|
|
76
|
+
if (serverOffline) _offlineTitle = title;
|
|
41
77
|
|
|
78
|
+
// Offline, the button asks the OS to start the server (synabun://start); it
|
|
79
|
+
// is left out only when that launcher is known not to be registered.
|
|
80
|
+
const offlineStart = !!serverOffline && startButtonUsable(stored(START_STORAGE.launcher));
|
|
42
81
|
const $action = $('loading-action');
|
|
43
|
-
|
|
82
|
+
const $btn = $('loading-action-btn');
|
|
83
|
+
if (canStart || offlineStart) {
|
|
44
84
|
if ($action) $action.style.display = 'block';
|
|
85
|
+
if ($btn) $btn.disabled = false;
|
|
45
86
|
const $label = $('loading-action-label');
|
|
46
|
-
if ($label) $label.textContent = t('common.start');
|
|
87
|
+
if ($label) $label.textContent = serverOffline ? t('loading.startServer') : t('common.start');
|
|
47
88
|
} else {
|
|
48
89
|
if ($action) $action.style.display = 'none';
|
|
49
90
|
}
|
|
50
91
|
|
|
51
|
-
|
|
52
|
-
|
|
92
|
+
clearStartStatus();
|
|
93
|
+
clearRestartLook();
|
|
94
|
+
|
|
95
|
+
if (serverOffline) {
|
|
96
|
+
const $hint = $('loading-server-cmd-hint');
|
|
97
|
+
if ($hint) $hint.textContent = offlineStart ? t('loading.runCommandOr') : t('loading.runCommandSetup');
|
|
98
|
+
watchForServer();
|
|
99
|
+
} else {
|
|
100
|
+
stopWatchingForServer();
|
|
101
|
+
}
|
|
53
102
|
}
|
|
54
103
|
|
|
55
104
|
/**
|
|
@@ -78,6 +127,7 @@ function resetLoadingToConnecting() {
|
|
|
78
127
|
if (!$overlay) return;
|
|
79
128
|
|
|
80
129
|
$overlay.classList.remove('error', 'server-offline');
|
|
130
|
+
stopWatchingForServer();
|
|
81
131
|
|
|
82
132
|
const $text = $('loading-text');
|
|
83
133
|
const $sub = $('loading-sub');
|
|
@@ -88,6 +138,8 @@ function resetLoadingToConnecting() {
|
|
|
88
138
|
if ($sub) $sub.textContent = t('loading.initializingNeural');
|
|
89
139
|
if ($action) $action.style.display = 'none';
|
|
90
140
|
if ($actionStatus) $actionStatus.textContent = '';
|
|
141
|
+
clearStartStatus();
|
|
142
|
+
clearRestartLook();
|
|
91
143
|
if (_statusDot) _statusDot.classList.remove('error');
|
|
92
144
|
}
|
|
93
145
|
|
|
@@ -95,6 +147,24 @@ function resetLoadingToConnecting() {
|
|
|
95
147
|
// HEALTH CHECK (called during init)
|
|
96
148
|
// ═══════════════════════════════════════════
|
|
97
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Keep what a health answer says about this install for the moment the server
|
|
152
|
+
* is down and cannot be asked: where it lives, how it was installed, and
|
|
153
|
+
* whether the Start Server launcher is registered.
|
|
154
|
+
*/
|
|
155
|
+
export function rememberHealth(health) {
|
|
156
|
+
if (!health) return;
|
|
157
|
+
try {
|
|
158
|
+
if (health.projectDir) {
|
|
159
|
+
localStorage.setItem('synabun-project-dir', health.projectDir);
|
|
160
|
+
}
|
|
161
|
+
if (health.install) localStorage.setItem(START_STORAGE.install, health.install);
|
|
162
|
+
if (health.startLauncher) localStorage.setItem(START_STORAGE.launcher, health.startLauncher);
|
|
163
|
+
if (health.entry) localStorage.setItem(START_STORAGE.entry, health.entry);
|
|
164
|
+
} catch {}
|
|
165
|
+
if (health.projectDir) updateCmdText(health.projectDir);
|
|
166
|
+
}
|
|
167
|
+
|
|
98
168
|
/**
|
|
99
169
|
* Run the health check pre-flight. If the database is unhealthy,
|
|
100
170
|
* show the appropriate loading error. Returns true if healthy (or
|
|
@@ -104,9 +174,7 @@ function resetLoadingToConnecting() {
|
|
|
104
174
|
export async function checkHealth() {
|
|
105
175
|
try {
|
|
106
176
|
const health = await fetchHealth();
|
|
107
|
-
|
|
108
|
-
localStorage.setItem('synabun-project-dir', health.projectDir);
|
|
109
|
-
}
|
|
177
|
+
rememberHealth(health);
|
|
110
178
|
if (!health.ok) {
|
|
111
179
|
const messages = {
|
|
112
180
|
db_missing: [t('loading.health.databaseUnreachable.title'), health.detail || t('loading.health.databaseUnreachable.sub')],
|
|
@@ -132,7 +200,286 @@ export async function checkHealth() {
|
|
|
132
200
|
*/
|
|
133
201
|
function updateCmdText(projectDir) {
|
|
134
202
|
const cmdEl = $('loading-cmd-text');
|
|
135
|
-
if (cmdEl)
|
|
203
|
+
if (!cmdEl) return;
|
|
204
|
+
const commands = manualStartCommands({
|
|
205
|
+
projectDir,
|
|
206
|
+
install: stored(START_STORAGE.install),
|
|
207
|
+
entry: stored(START_STORAGE.entry),
|
|
208
|
+
windows: isWindowsPlatform(navigator),
|
|
209
|
+
});
|
|
210
|
+
// One box: the command for this install (the checkout's when it is not known).
|
|
211
|
+
cmdEl.textContent = commands[commands.length - 1].command;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ═══════════════════════════════════════════
|
|
215
|
+
// INTERNAL — Server offline: Start Server + reconnect
|
|
216
|
+
// ═══════════════════════════════════════════
|
|
217
|
+
|
|
218
|
+
function stopWatchingForServer() {
|
|
219
|
+
if (_offlineBridge) _offlineBridge.stop();
|
|
220
|
+
_offlineBridge = null;
|
|
221
|
+
poseMascot('asleep');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** The lines a start writes under the button, emptied. */
|
|
225
|
+
function clearStartStatus() {
|
|
226
|
+
for (const id of ['loading-action-status', 'loading-action-elapsed', 'loading-action-hint', 'loading-action-log']) {
|
|
227
|
+
const el = $(id);
|
|
228
|
+
if (el) el.textContent = '';
|
|
229
|
+
}
|
|
230
|
+
const $trail = $('loading-action-trail');
|
|
231
|
+
if ($trail) $trail.replaceChildren();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** What a restart changed about the overlay's look, undone. */
|
|
235
|
+
function clearRestartLook() {
|
|
236
|
+
const $overlay = $('loading-overlay');
|
|
237
|
+
if ($overlay) $overlay.classList.remove('over-app', 'restart-busy', 'restart-refused');
|
|
238
|
+
const btn = $('loading-action-btn');
|
|
239
|
+
if (btn) btn.style.display = '';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* The overlay's mascot as the shared rig, so a start can be acted out. The
|
|
244
|
+
* markup's own still drawing stays as the fallback when the rig cannot mount.
|
|
245
|
+
*/
|
|
246
|
+
function mountMascot() {
|
|
247
|
+
if (_mascot) return;
|
|
248
|
+
const host = $('loading-mascot');
|
|
249
|
+
if (!host) return;
|
|
250
|
+
try {
|
|
251
|
+
const still = host.querySelector('svg');
|
|
252
|
+
_mascot = createMascot(host, { width: 160, height: 80, pose: 'sleep', active: false });
|
|
253
|
+
if (still && still !== _mascot.el) still.style.display = 'none';
|
|
254
|
+
} catch {
|
|
255
|
+
_mascot = null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** 'asleep' is the still sleeping face (the overlay's own bob and z carry it); every other state plays its pose. */
|
|
260
|
+
function poseMascot(state) {
|
|
261
|
+
const host = $('loading-mascot');
|
|
262
|
+
if (host) host.setAttribute('data-state', state);
|
|
263
|
+
if (!_mascot) return;
|
|
264
|
+
try {
|
|
265
|
+
_mascot.setPose(MASCOT_POSE[state] || 'sleep');
|
|
266
|
+
_mascot.setActive(state !== 'asleep');
|
|
267
|
+
} catch {}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Draw one snapshot of the start: the sentence (a live region, written only
|
|
272
|
+
* when it changes), the page's own clock, and the steps the launcher reported
|
|
273
|
+
* with the time each one happened. Nothing here is estimated.
|
|
274
|
+
*/
|
|
275
|
+
function renderStart(snap) {
|
|
276
|
+
const platform = isWindowsPlatform(navigator) ? 'windows' : isMacPlatform(navigator) ? 'mac' : 'linux';
|
|
277
|
+
const view = startStatusView(snap, { platform });
|
|
278
|
+
const say = (line) => (line ? t(`loading.start.${line.key}`, line.params) : '');
|
|
279
|
+
// A restart this page asked for or was told of, while it runs.
|
|
280
|
+
const restarting = !!snap.restart && (view.busy || view.state === 'online');
|
|
281
|
+
|
|
282
|
+
poseMascot(view.mascot);
|
|
283
|
+
|
|
284
|
+
const $overlay = $('loading-overlay');
|
|
285
|
+
if ($overlay) {
|
|
286
|
+
// While a restart runs there is nothing to press and no command to type;
|
|
287
|
+
// refused, the server is still there and only the way back is offered.
|
|
288
|
+
$overlay.classList.toggle('restart-busy', restarting);
|
|
289
|
+
$overlay.classList.toggle('restart-refused', view.state === 'refused');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const $text = $('loading-text');
|
|
293
|
+
if ($text) {
|
|
294
|
+
const title = view.heading ? t(`loading.start.${view.heading}`)
|
|
295
|
+
: view.mascot === 'waking' || view.mascot === 'working' ? t('loading.start.headingStarting')
|
|
296
|
+
: view.mascot === 'ready' ? t('loading.start.headingReady')
|
|
297
|
+
: view.mascot === 'failed' ? t('loading.start.headingFailed')
|
|
298
|
+
: _offlineTitle || t('loading.serverOffline');
|
|
299
|
+
if ($text.textContent !== title) $text.textContent = title;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Under the title: whose restart this is, for as long as it is one.
|
|
303
|
+
const $sub = $('loading-sub');
|
|
304
|
+
if ($sub && _restartShown) {
|
|
305
|
+
const sub = view.state === 'refused' ? t('loading.restartSubRefused')
|
|
306
|
+
: restarting ? (snap.restart.asked ? t('loading.restartSubAsked') : t('loading.restartSubTold'))
|
|
307
|
+
: t('loading.serverNotRunning');
|
|
308
|
+
if ($sub.textContent !== sub) $sub.textContent = sub;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const btn = $('loading-action-btn');
|
|
312
|
+
const $label = $('loading-action-label');
|
|
313
|
+
if (btn) {
|
|
314
|
+
btn.disabled = view.busy || view.state === 'online';
|
|
315
|
+
// No dead button: when a restart did not bring the server back, Start is
|
|
316
|
+
// offered only if its launcher is there (the command below always is).
|
|
317
|
+
const startOffered = view.button === 'start' || view.button === 'retry';
|
|
318
|
+
btn.style.display = _restartShown && startOffered && !startButtonUsable(stored(START_STORAGE.launcher)) ? 'none' : '';
|
|
319
|
+
}
|
|
320
|
+
if ($label) {
|
|
321
|
+
$label.textContent = view.button === 'starting' ? t('loading.starting')
|
|
322
|
+
: view.button === 'retry' ? t('common.retry')
|
|
323
|
+
: view.button === 'back' ? t('loading.restartBack') : t('loading.startServer');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const $status = $('loading-action-status');
|
|
327
|
+
const line = say(view.headline);
|
|
328
|
+
if ($status && $status.textContent !== line) $status.textContent = line;
|
|
329
|
+
|
|
330
|
+
const $elapsed = $('loading-action-elapsed');
|
|
331
|
+
if ($elapsed) {
|
|
332
|
+
$elapsed.textContent = view.elapsed;
|
|
333
|
+
$elapsed.setAttribute('aria-label', view.elapsed ? `${t(`loading.start.${view.elapsedLabel}`)}: ${view.elapsed}` : '');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const $hint = $('loading-action-hint');
|
|
337
|
+
if ($hint) $hint.textContent = say(view.hint);
|
|
338
|
+
|
|
339
|
+
const $trail = $('loading-action-trail');
|
|
340
|
+
if ($trail) {
|
|
341
|
+
$trail.replaceChildren(...view.trail.map((row) => {
|
|
342
|
+
const item = document.createElement('li');
|
|
343
|
+
const what = document.createElement('span');
|
|
344
|
+
what.textContent = t(`loading.start.${row.key}`);
|
|
345
|
+
const when = document.createElement('span');
|
|
346
|
+
when.className = 'at';
|
|
347
|
+
when.textContent = row.time;
|
|
348
|
+
item.append(what, when);
|
|
349
|
+
return item;
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const $log = $('loading-action-log');
|
|
354
|
+
if ($log) $log.textContent = view.error?.log ? t('loading.start.failedLog', { path: view.error.log }) : '';
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* While the overlay says the server is offline: keep asking for it, and let
|
|
359
|
+
* the Start button hand the OS a synabun://start link. Reconnects by itself
|
|
360
|
+
* the moment the server answers, however it was started. While a start is
|
|
361
|
+
* under way it shows what the launcher itself reports (its beacon), never a
|
|
362
|
+
* guess: see start-bridge.js.
|
|
363
|
+
*/
|
|
364
|
+
function watchForServer() {
|
|
365
|
+
if (_offlineBridge) return;
|
|
366
|
+
openBridge().watch();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Is the server answering, which server is it (`bootId`), and does it say it
|
|
371
|
+
* is on its way out for a restart. One that predates those two says neither.
|
|
372
|
+
*/
|
|
373
|
+
async function probeServer() {
|
|
374
|
+
const health = await fetchHealth();
|
|
375
|
+
return {
|
|
376
|
+
up: !!health && health.ok !== false,
|
|
377
|
+
boot: typeof health?.bootId === 'string' ? health.bootId : '',
|
|
378
|
+
stopping: health?.restarting === true,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** The bridge behind the overlay, for either reason it is up: the server is offline, or it is being restarted. */
|
|
383
|
+
function openBridge() {
|
|
384
|
+
mountMascot();
|
|
385
|
+
const beaconAt = startBeaconTarget(window.location);
|
|
386
|
+
const bridge = createStartBridge({
|
|
387
|
+
probe: probeServer,
|
|
388
|
+
launch: () => openStartLink({ document, location: window.location, userAgent: navigator.userAgent }),
|
|
389
|
+
beacon: beaconAt ? () => fetchStartBeacon(beaconAt) : null,
|
|
390
|
+
port: beaconAt ? beaconAt.port : 0,
|
|
391
|
+
onUpdate(snap) {
|
|
392
|
+
if (_offlineBridge !== bridge) return;
|
|
393
|
+
renderStart(snap);
|
|
394
|
+
},
|
|
395
|
+
onState(state) {
|
|
396
|
+
if (_offlineBridge !== bridge) return;
|
|
397
|
+
if (state !== 'online') return;
|
|
398
|
+
// Back from a restart: the page loads again, after the frame that says so.
|
|
399
|
+
if (_restartShown) {
|
|
400
|
+
setTimeout(() => window.location.reload(), START_LIMITS.reloadDelayMs);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
resetLoadingToConnecting();
|
|
404
|
+
emit('loading:retried');
|
|
405
|
+
if (_initCallback) _initCallback();
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
_offlineBridge = bridge;
|
|
409
|
+
return bridge;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// ═══════════════════════════════════════════
|
|
413
|
+
// Restart Server
|
|
414
|
+
// ═══════════════════════════════════════════
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* The user chose Restart Server. The screen changes here, in the click: the
|
|
418
|
+
* overlay is up and says a restart was asked for before the request has even
|
|
419
|
+
* left, and nothing on the way to that first frame waits for the network.
|
|
420
|
+
* From there it shows what is really known (start-bridge.js `restart()`): the
|
|
421
|
+
* server's answer, its own word that it is shutting down, the probe that finds
|
|
422
|
+
* it gone, the supervisor's report of bringing it back. The page loads again
|
|
423
|
+
* by itself when another server than the one that was asked answers.
|
|
424
|
+
*/
|
|
425
|
+
export function requestServerRestart() {
|
|
426
|
+
return beginRestart({ request: postRestart });
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** Ask for the restart: { ok, boot } when the server says it will, { ok: false, status, message } when it will not. */
|
|
430
|
+
async function postRestart() {
|
|
431
|
+
const res = await fetch('/api/server/restart', { method: 'POST', signal: AbortSignal.timeout(10000) });
|
|
432
|
+
let body = null;
|
|
433
|
+
try { body = await res.json(); } catch {}
|
|
434
|
+
if (!res.ok || !body || body.ok === false) {
|
|
435
|
+
return { ok: false, status: res.status, message: String(body?.error || body?.message || '') };
|
|
436
|
+
}
|
|
437
|
+
return { ok: true, boot: typeof body.bootId === 'string' ? body.bootId : '' };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Show the restart: this window asked for it (`request`), or the server told
|
|
442
|
+
* every window that it is restarting (`announced`, over the sync socket).
|
|
443
|
+
*/
|
|
444
|
+
function beginRestart({ request = null, announced = false, boot = '' } = {}) {
|
|
445
|
+
// Already on screen (this window asked, and here is the server saying so too).
|
|
446
|
+
if (_restartShown && _offlineBridge) {
|
|
447
|
+
_offlineBridge.restart({ announced, boot });
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
// The overlay is up because the server is offline: there is nothing to restart.
|
|
451
|
+
if (_offlineBridge) return false;
|
|
452
|
+
const $overlay = $('loading-overlay');
|
|
453
|
+
if (!$overlay) return false;
|
|
454
|
+
|
|
455
|
+
_restartShown = true;
|
|
456
|
+
_restartTitle = document.title;
|
|
457
|
+
document.title = t('loading.start.headingRestarting');
|
|
458
|
+
_offlineTitle = t('loading.serverOffline');
|
|
459
|
+
// `over-app`: no fade-in and above whatever is open. The screen is there in the frame of the click.
|
|
460
|
+
$overlay.classList.add('over-app', 'error', 'server-offline');
|
|
461
|
+
$overlay.classList.remove('hidden');
|
|
462
|
+
// Nothing behind the screen keeps the keyboard (a terminal, an editor).
|
|
463
|
+
try { document.activeElement?.blur?.(); } catch {}
|
|
464
|
+
if (_statusDot) _statusDot.classList.add('error');
|
|
465
|
+
const $action = $('loading-action');
|
|
466
|
+
if ($action) $action.style.display = 'block';
|
|
467
|
+
const $hint = $('loading-server-cmd-hint');
|
|
468
|
+
if ($hint) $hint.textContent = startButtonUsable(stored(START_STORAGE.launcher)) ? t('loading.runCommandOr') : t('loading.runCommandSetup');
|
|
469
|
+
const $retry = $('loading-retry-status');
|
|
470
|
+
if ($retry) $retry.textContent = '';
|
|
471
|
+
clearStartStatus();
|
|
472
|
+
return openBridge().restart({ request, announced, boot });
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/** The restart did not happen and the server is still there: give the app back. */
|
|
476
|
+
function dismissRestart() {
|
|
477
|
+
resetLoadingToConnecting();
|
|
478
|
+
_restartShown = false;
|
|
479
|
+
if (_restartTitle !== null) document.title = _restartTitle;
|
|
480
|
+
_restartTitle = null;
|
|
481
|
+
const $overlay = $('loading-overlay');
|
|
482
|
+
if ($overlay) $overlay.classList.add('hidden');
|
|
136
483
|
}
|
|
137
484
|
|
|
138
485
|
// ═══════════════════════════════════════════
|
|
@@ -144,6 +491,11 @@ function updateCmdText(projectDir) {
|
|
|
144
491
|
* Calls /api/health/start and re-triggers init on success.
|
|
145
492
|
*/
|
|
146
493
|
async function handleStartAction() {
|
|
494
|
+
// A restart the server refused: the button is the way back to the app.
|
|
495
|
+
if (_offlineBridge && _offlineBridge.state === 'refused') { dismissRestart(); return; }
|
|
496
|
+
// Server offline: nothing to call, the OS starts it.
|
|
497
|
+
if (_offlineBridge) { _offlineBridge.start(); return; }
|
|
498
|
+
|
|
147
499
|
const btn = $('loading-action-btn');
|
|
148
500
|
const $status = $('loading-action-status');
|
|
149
501
|
const $label = $('loading-action-label');
|
|
@@ -165,8 +517,6 @@ async function handleStartAction() {
|
|
|
165
517
|
if ($label) $label.textContent = t('common.retry');
|
|
166
518
|
}
|
|
167
519
|
} catch (err) {
|
|
168
|
-
// Server is unreachable — try protocol handler as fallback
|
|
169
|
-
window.location.href = 'synabun://start';
|
|
170
520
|
if ($status) $status.textContent = t('loading.somethingWrong');
|
|
171
521
|
if (btn) btn.disabled = false;
|
|
172
522
|
if ($label) $label.textContent = t('common.retry');
|
|
@@ -205,6 +555,8 @@ async function handleRetryConnection() {
|
|
|
205
555
|
// fetchHealth uses AbortSignal.timeout(3000) internally
|
|
206
556
|
if (health && health.ok !== false) {
|
|
207
557
|
if ($status) $status.textContent = t('loading.connectedLoading');
|
|
558
|
+
// After a restart the page loads again (see openBridge).
|
|
559
|
+
if (_restartShown) { window.location.reload(); return; }
|
|
208
560
|
resetLoadingToConnecting();
|
|
209
561
|
emit('loading:retried');
|
|
210
562
|
if (_initCallback) _initCallback();
|
|
@@ -252,4 +604,7 @@ export function initLoading({ onInit } = {}) {
|
|
|
252
604
|
// ── Retry connection ──
|
|
253
605
|
const retryBtn = $('loading-retry-btn');
|
|
254
606
|
if (retryBtn) retryBtn.addEventListener('click', handleRetryConnection);
|
|
607
|
+
|
|
608
|
+
// ── The server says it is restarting (ui-sync.js): every window shows it ──
|
|
609
|
+
on('server:restarting', (msg) => beginRestart({ announced: true, boot: typeof msg?.bootId === 'string' ? msg.bootId : '' }));
|
|
255
610
|
}
|
|
@@ -9,11 +9,13 @@ import { storage } from './storage.js';
|
|
|
9
9
|
import { KEYS } from './constants.js';
|
|
10
10
|
import { getMenuItems } from './registry.js';
|
|
11
11
|
import { openHelp } from './ui-help.js';
|
|
12
|
+
import { armPwaInstallHandoff, initPwaInstall, installGuideUrl, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
12
13
|
import { registerAction } from './ui-keybinds.js';
|
|
13
14
|
import { isGuest, hasPermission } from './ui-sync.js';
|
|
14
15
|
import { sendToPanel } from './ui-claude-panel.js';
|
|
15
16
|
import { forceCheckToolUpdates, showUpdateToast, TOOL_LABELS } from './ui-tool-updates.js';
|
|
16
17
|
import { forceCheckSynabunUpdate, openSynabunUpdateModal } from './ui-update.js';
|
|
18
|
+
import { requestServerRestart } from './ui-loading.js';
|
|
17
19
|
|
|
18
20
|
const $ = (id) => document.getElementById(id);
|
|
19
21
|
|
|
@@ -83,7 +85,7 @@ export function initMenubar() {
|
|
|
83
85
|
const dropdown = document.querySelector('.menubar-item.open .menubar-dropdown');
|
|
84
86
|
if (!dropdown) return;
|
|
85
87
|
|
|
86
|
-
const allItems = [...dropdown.querySelectorAll('.menu-item:not(.disabled)')];
|
|
88
|
+
const allItems = [...dropdown.querySelectorAll('.menu-item:not(.disabled):not([hidden])')];
|
|
87
89
|
if (allItems.length === 0) return;
|
|
88
90
|
|
|
89
91
|
const focused = dropdown.querySelector('.menu-item.focused');
|
|
@@ -368,6 +370,7 @@ function wireAutomationsMenu() {
|
|
|
368
370
|
// ── Apps Menu (formerly Terminal) ──
|
|
369
371
|
|
|
370
372
|
function wireTerminalMenu() {
|
|
373
|
+
let disarmInstallHandoff = () => {};
|
|
371
374
|
const items = {
|
|
372
375
|
'menu-terminal-assistant': () => emit('assistant:open'),
|
|
373
376
|
'menu-terminal-claude': () => emit('terminal:open', { profile: 'claude-code' }),
|
|
@@ -413,45 +416,15 @@ function wireTerminalMenu() {
|
|
|
413
416
|
'menu-command-runner': () => emit('command-runner:open'),
|
|
414
417
|
'menu-terminal-link': () => emit('link:toggle'),
|
|
415
418
|
'menu-terminal-toggle': () => emit('terminal:toggle'),
|
|
416
|
-
'menu-install-app':
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (outcome === 'accepted') {
|
|
421
|
-
window._pwaInstallPrompt = null;
|
|
422
|
-
const el = $('menu-install-app');
|
|
423
|
-
if (el) el.style.display = 'none';
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
},
|
|
427
|
-
'menu-restart-server': async () => {
|
|
428
|
-
try {
|
|
429
|
-
// Cache project path before server goes down
|
|
430
|
-
try {
|
|
431
|
-
const h = await fetch('/api/health');
|
|
432
|
-
const hd = await h.json();
|
|
433
|
-
if (hd.projectDir) localStorage.setItem('synabun-project-dir', hd.projectDir);
|
|
434
|
-
} catch {}
|
|
435
|
-
document.title = 'Restarting...';
|
|
436
|
-
await fetch('/api/server/restart', { method: 'POST' });
|
|
437
|
-
|
|
438
|
-
// Poll /api/health until the server has gone down AND come back up.
|
|
439
|
-
// The everDown flag prevents premature reload during the brief window
|
|
440
|
-
// where the old process is still serving requests during shutdown grace.
|
|
441
|
-
const deadline = Date.now() + 15000;
|
|
442
|
-
let everDown = false;
|
|
443
|
-
while (Date.now() < deadline) {
|
|
444
|
-
await new Promise(r => setTimeout(r, 250));
|
|
445
|
-
try {
|
|
446
|
-
const r = await fetch('/api/health', { cache: 'no-store' });
|
|
447
|
-
if (!r.ok) { everDown = true; continue; }
|
|
448
|
-
if (everDown) { location.reload(); return; }
|
|
449
|
-
} catch { everDown = true; }
|
|
450
|
-
}
|
|
451
|
-
// Timeout safety net — reload anyway so the user isn't stranded.
|
|
452
|
-
location.reload();
|
|
453
|
-
} catch {}
|
|
419
|
+
'menu-install-app': async () => {
|
|
420
|
+
disarmInstallHandoff(); // asked for here: this click opens the dialog, no later one does
|
|
421
|
+
const result = await requestPwaInstall();
|
|
422
|
+
if (result === 'instructions') location.assign(installGuideUrl());
|
|
454
423
|
},
|
|
424
|
+
// The restart screen is drawn in this click, before anything is asked of
|
|
425
|
+
// the network; from there it follows the restart and loads the page again
|
|
426
|
+
// when the server is back (ui-loading.js requestServerRestart).
|
|
427
|
+
'menu-restart-server': () => { requestServerRestart(); },
|
|
455
428
|
'menu-stop-server': async () => {
|
|
456
429
|
const previousTitle = document.title;
|
|
457
430
|
try {
|
|
@@ -478,23 +451,16 @@ function wireTerminalMenu() {
|
|
|
478
451
|
registerAction('toggle-terminal', () => emit('terminal:toggle'));
|
|
479
452
|
registerAction('toggle-terminal-alt', () => emit('terminal:toggle'));
|
|
480
453
|
|
|
481
|
-
|
|
482
|
-
window.addEventListener('beforeinstallprompt', (e) => {
|
|
483
|
-
e.preventDefault();
|
|
484
|
-
window._pwaInstallPrompt = e;
|
|
454
|
+
initPwaInstall({ changed: value => {
|
|
485
455
|
const el = $('menu-install-app');
|
|
486
|
-
if (el) el.style.display = '';
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
if (window.matchMedia('(display-mode: standalone)').matches || navigator.standalone) {
|
|
495
|
-
const el = $('menu-install-app');
|
|
496
|
-
if (el) el.style.display = 'none';
|
|
497
|
-
}
|
|
456
|
+
if (el) el.style.display = value === 'installed' ? 'none' : '';
|
|
457
|
+
} });
|
|
458
|
+
const installItem = $('menu-install-app');
|
|
459
|
+
if (installItem && !isStandalone()) installItem.style.display = '';
|
|
460
|
+
// Sent on by the launcher's guide page: the browser's install dialog opens from the first click or key press,
|
|
461
|
+
// for this one page load. The event it uses is spent, so the menu item goes to the guide page after that.
|
|
462
|
+
disarmInstallHandoff = armPwaInstallHandoff({ leave: event => !!installItem?.contains(event.target) });
|
|
463
|
+
|
|
498
464
|
}
|
|
499
465
|
|
|
500
466
|
// ── Variant menu items injection ──
|
|
@@ -92,3 +92,14 @@ export class LocalReleaseTracker {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The saved list of dismissed runs (localStorage, `[{ runId, at }]`) without
|
|
98
|
+
* one run: what the agents dock's Focus leaves when it reopens a closed tab.
|
|
99
|
+
* Anything unreadable becomes an empty list.
|
|
100
|
+
*/
|
|
101
|
+
export function withoutDismissed(raw, runId) {
|
|
102
|
+
let stored;
|
|
103
|
+
try { stored = JSON.parse(raw || '[]'); } catch { stored = []; }
|
|
104
|
+
return JSON.stringify((Array.isArray(stored) ? stored : []).filter((entry) => entry?.runId && entry.runId !== runId));
|
|
105
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isNewerRunDescriptor,
|
|
8
8
|
LocalReleaseTracker,
|
|
9
9
|
resolveRouteClaim,
|
|
10
|
+
withoutDismissed,
|
|
10
11
|
} from './ui-native-loop-router-state.js';
|
|
11
12
|
|
|
12
13
|
const DISMISSED_KEY = 'synabun-native-loop-dismissed';
|
|
@@ -48,6 +49,15 @@ function mergeDismissed(raw) {
|
|
|
48
49
|
|
|
49
50
|
try { mergeDismissed(localStorage.getItem(DISMISSED_KEY)); } catch {}
|
|
50
51
|
|
|
52
|
+
// A closed tab's run is dismissed: nothing routes it back here by itself (a
|
|
53
|
+
// reconcile, a late event, another window's claim). Only the user asks for it
|
|
54
|
+
// again, with the agents dock's Focus (focusNativeLoopRun with `reopen`).
|
|
55
|
+
function undismiss(runId) {
|
|
56
|
+
if (!_dismissed.delete(runId)) return false;
|
|
57
|
+
try { localStorage.setItem(DISMISSED_KEY, withoutDismissed(localStorage.getItem(DISMISSED_KEY), runId)); } catch {}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
function persistDismissed() {
|
|
52
62
|
try {
|
|
53
63
|
const existing = JSON.parse(localStorage.getItem(DISMISSED_KEY) || '[]');
|
|
@@ -279,10 +289,13 @@ export function getNativeLoopRun(runId) {
|
|
|
279
289
|
* Bring a dispatched run's sidepanel tab to the front. Attaches with
|
|
280
290
|
* focus:true even when this window already owns the claim (the normal route
|
|
281
291
|
* path only focuses on first attach). Falls back to a fetch when the run has
|
|
282
|
-
* not been broadcast to this window yet.
|
|
292
|
+
* not been broadcast to this window yet. With `reopen` (the user's own Focus,
|
|
293
|
+
* in the agents dock) a run whose tab was closed opens again: a live run
|
|
294
|
+
* attaches as it would have, an ended one with its transcript and end card.
|
|
283
295
|
*/
|
|
284
|
-
export async function focusNativeLoopRun(runId) {
|
|
296
|
+
export async function focusNativeLoopRun(runId, { reopen = false } = {}) {
|
|
285
297
|
if (!runId || _suspended) return false;
|
|
298
|
+
if (reopen) undismiss(runId);
|
|
286
299
|
let run = getNativeLoopRun(runId);
|
|
287
300
|
if (!run) {
|
|
288
301
|
try {
|