synabun 2.0.0 → 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 +57 -0
- package/NOTICE +5 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +46 -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/lib/start-launcher.js +88 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/neural-interface/i18n/en.json +1500 -153
- package/neural-interface/i18n/pt-BR.json +1498 -152
- 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-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/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-agent-bridge.js +33 -6
- package/neural-interface/lib/claude-model-catalog.js +30 -2
- 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-loop-providers.js +10 -5
- 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/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/package-lock.json +701 -2
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/install-app.html +9 -6
- package/neural-interface/public/offline.html +3 -2
- package/neural-interface/public/onboarding.html +12 -1
- 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 +18 -58
- 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-render.js +162 -19
- 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 +158 -4
- 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/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 +160 -165
- 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 +29 -1
- 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-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-user-context.js +154 -0
- package/neural-interface/public/shared/start-bridge.js +238 -19
- package/neural-interface/public/shared/styles.css +1414 -721
- package/neural-interface/public/shared/synabun-mascot.js +20 -56
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +157 -16
- 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-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +159 -15
- package/neural-interface/public/shared/ui-menubar.js +12 -30
- 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 +455 -488
- 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 +23 -5
- 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 +2 -2
- 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 +873 -1028
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +2 -8
- package/setup.js +44 -7
- 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
|
@@ -1,13 +1,14 @@
|
|
|
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';
|
|
9
10
|
import {
|
|
10
|
-
START_STORAGE, createStartBridge, fetchStartBeacon, isMacPlatform, isWindowsPlatform,
|
|
11
|
+
START_LIMITS, START_STORAGE, createStartBridge, fetchStartBeacon, isMacPlatform, isWindowsPlatform,
|
|
11
12
|
manualStartCommands, openStartLink, startBeaconTarget, startButtonUsable, startStatusView,
|
|
12
13
|
} from './start-bridge.js';
|
|
13
14
|
// Imported with the app, not when it is needed: once the server is down
|
|
@@ -25,6 +26,12 @@ let _offlineBridge = null;
|
|
|
25
26
|
let _offlineTitle = '';
|
|
26
27
|
// The mascot rig in the overlay, mounted the first time the server is offline.
|
|
27
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;
|
|
28
35
|
|
|
29
36
|
// What the mascot does for each thing the page knows about a start
|
|
30
37
|
// (startStatusView's `mascot`), as poses of the shared rig.
|
|
@@ -83,6 +90,7 @@ export function showLoadingError(title, sub, canStart, serverOffline) {
|
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
clearStartStatus();
|
|
93
|
+
clearRestartLook();
|
|
86
94
|
|
|
87
95
|
if (serverOffline) {
|
|
88
96
|
const $hint = $('loading-server-cmd-hint');
|
|
@@ -131,6 +139,7 @@ function resetLoadingToConnecting() {
|
|
|
131
139
|
if ($action) $action.style.display = 'none';
|
|
132
140
|
if ($actionStatus) $actionStatus.textContent = '';
|
|
133
141
|
clearStartStatus();
|
|
142
|
+
clearRestartLook();
|
|
134
143
|
if (_statusDot) _statusDot.classList.remove('error');
|
|
135
144
|
}
|
|
136
145
|
|
|
@@ -222,6 +231,14 @@ function clearStartStatus() {
|
|
|
222
231
|
if ($trail) $trail.replaceChildren();
|
|
223
232
|
}
|
|
224
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
|
+
|
|
225
242
|
/**
|
|
226
243
|
* The overlay's mascot as the shared rig, so a start can be acted out. The
|
|
227
244
|
* markup's own still drawing stays as the fallback when the rig cannot mount.
|
|
@@ -259,24 +276,51 @@ function renderStart(snap) {
|
|
|
259
276
|
const platform = isWindowsPlatform(navigator) ? 'windows' : isMacPlatform(navigator) ? 'mac' : 'linux';
|
|
260
277
|
const view = startStatusView(snap, { platform });
|
|
261
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');
|
|
262
281
|
|
|
263
282
|
poseMascot(view.mascot);
|
|
264
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
|
+
|
|
265
292
|
const $text = $('loading-text');
|
|
266
293
|
if ($text) {
|
|
267
|
-
const title = view.
|
|
268
|
-
: view.mascot === '
|
|
269
|
-
: view.mascot === '
|
|
270
|
-
:
|
|
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');
|
|
271
299
|
if ($text.textContent !== title) $text.textContent = title;
|
|
272
300
|
}
|
|
273
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
|
+
|
|
274
311
|
const btn = $('loading-action-btn');
|
|
275
312
|
const $label = $('loading-action-label');
|
|
276
|
-
if (btn)
|
|
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
|
+
}
|
|
277
320
|
if ($label) {
|
|
278
321
|
$label.textContent = view.button === 'starting' ? t('loading.starting')
|
|
279
|
-
: view.button === 'retry' ? t('common.retry')
|
|
322
|
+
: view.button === 'retry' ? t('common.retry')
|
|
323
|
+
: view.button === 'back' ? t('loading.restartBack') : t('loading.startServer');
|
|
280
324
|
}
|
|
281
325
|
|
|
282
326
|
const $status = $('loading-action-status');
|
|
@@ -286,7 +330,7 @@ function renderStart(snap) {
|
|
|
286
330
|
const $elapsed = $('loading-action-elapsed');
|
|
287
331
|
if ($elapsed) {
|
|
288
332
|
$elapsed.textContent = view.elapsed;
|
|
289
|
-
$elapsed.setAttribute('aria-label', view.elapsed ? `${t(
|
|
333
|
+
$elapsed.setAttribute('aria-label', view.elapsed ? `${t(`loading.start.${view.elapsedLabel}`)}: ${view.elapsed}` : '');
|
|
290
334
|
}
|
|
291
335
|
|
|
292
336
|
const $hint = $('loading-action-hint');
|
|
@@ -319,13 +363,28 @@ function renderStart(snap) {
|
|
|
319
363
|
*/
|
|
320
364
|
function watchForServer() {
|
|
321
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() {
|
|
322
384
|
mountMascot();
|
|
323
385
|
const beaconAt = startBeaconTarget(window.location);
|
|
324
386
|
const bridge = createStartBridge({
|
|
325
|
-
probe:
|
|
326
|
-
const health = await fetchHealth();
|
|
327
|
-
return !!health && health.ok !== false;
|
|
328
|
-
},
|
|
387
|
+
probe: probeServer,
|
|
329
388
|
launch: () => openStartLink({ document, location: window.location, userAgent: navigator.userAgent }),
|
|
330
389
|
beacon: beaconAt ? () => fetchStartBeacon(beaconAt) : null,
|
|
331
390
|
port: beaconAt ? beaconAt.port : 0,
|
|
@@ -336,13 +395,91 @@ function watchForServer() {
|
|
|
336
395
|
onState(state) {
|
|
337
396
|
if (_offlineBridge !== bridge) return;
|
|
338
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
|
+
}
|
|
339
403
|
resetLoadingToConnecting();
|
|
340
404
|
emit('loading:retried');
|
|
341
405
|
if (_initCallback) _initCallback();
|
|
342
406
|
},
|
|
343
407
|
});
|
|
344
408
|
_offlineBridge = bridge;
|
|
345
|
-
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');
|
|
346
483
|
}
|
|
347
484
|
|
|
348
485
|
// ═══════════════════════════════════════════
|
|
@@ -354,6 +491,8 @@ function watchForServer() {
|
|
|
354
491
|
* Calls /api/health/start and re-triggers init on success.
|
|
355
492
|
*/
|
|
356
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; }
|
|
357
496
|
// Server offline: nothing to call, the OS starts it.
|
|
358
497
|
if (_offlineBridge) { _offlineBridge.start(); return; }
|
|
359
498
|
|
|
@@ -416,6 +555,8 @@ async function handleRetryConnection() {
|
|
|
416
555
|
// fetchHealth uses AbortSignal.timeout(3000) internally
|
|
417
556
|
if (health && health.ok !== false) {
|
|
418
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; }
|
|
419
560
|
resetLoadingToConnecting();
|
|
420
561
|
emit('loading:retried');
|
|
421
562
|
if (_initCallback) _initCallback();
|
|
@@ -463,4 +604,7 @@ export function initLoading({ onInit } = {}) {
|
|
|
463
604
|
// ── Retry connection ──
|
|
464
605
|
const retryBtn = $('loading-retry-btn');
|
|
465
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 : '' }));
|
|
466
610
|
}
|
|
@@ -9,12 +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 { initPwaInstall, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
12
|
+
import { armPwaInstallHandoff, initPwaInstall, installGuideUrl, isStandalone, requestPwaInstall } from './pwa-install.js';
|
|
13
13
|
import { registerAction } from './ui-keybinds.js';
|
|
14
14
|
import { isGuest, hasPermission } from './ui-sync.js';
|
|
15
15
|
import { sendToPanel } from './ui-claude-panel.js';
|
|
16
16
|
import { forceCheckToolUpdates, showUpdateToast, TOOL_LABELS } from './ui-tool-updates.js';
|
|
17
17
|
import { forceCheckSynabunUpdate, openSynabunUpdateModal } from './ui-update.js';
|
|
18
|
+
import { requestServerRestart } from './ui-loading.js';
|
|
18
19
|
|
|
19
20
|
const $ = (id) => document.getElementById(id);
|
|
20
21
|
|
|
@@ -369,6 +370,7 @@ function wireAutomationsMenu() {
|
|
|
369
370
|
// ── Apps Menu (formerly Terminal) ──
|
|
370
371
|
|
|
371
372
|
function wireTerminalMenu() {
|
|
373
|
+
let disarmInstallHandoff = () => {};
|
|
372
374
|
const items = {
|
|
373
375
|
'menu-terminal-assistant': () => emit('assistant:open'),
|
|
374
376
|
'menu-terminal-claude': () => emit('terminal:open', { profile: 'claude-code' }),
|
|
@@ -415,37 +417,14 @@ function wireTerminalMenu() {
|
|
|
415
417
|
'menu-terminal-link': () => emit('link:toggle'),
|
|
416
418
|
'menu-terminal-toggle': () => emit('terminal:toggle'),
|
|
417
419
|
'menu-install-app': async () => {
|
|
420
|
+
disarmInstallHandoff(); // asked for here: this click opens the dialog, no later one does
|
|
418
421
|
const result = await requestPwaInstall();
|
|
419
|
-
if (result === 'instructions') location.assign(
|
|
420
|
-
},
|
|
421
|
-
'menu-restart-server': async () => {
|
|
422
|
-
try {
|
|
423
|
-
// Cache project path before server goes down
|
|
424
|
-
try {
|
|
425
|
-
const h = await fetch('/api/health');
|
|
426
|
-
const hd = await h.json();
|
|
427
|
-
if (hd.projectDir) localStorage.setItem('synabun-project-dir', hd.projectDir);
|
|
428
|
-
} catch {}
|
|
429
|
-
document.title = 'Restarting...';
|
|
430
|
-
await fetch('/api/server/restart', { method: 'POST' });
|
|
431
|
-
|
|
432
|
-
// Poll /api/health until the server has gone down AND come back up.
|
|
433
|
-
// The everDown flag prevents premature reload during the brief window
|
|
434
|
-
// where the old process is still serving requests during shutdown grace.
|
|
435
|
-
const deadline = Date.now() + 15000;
|
|
436
|
-
let everDown = false;
|
|
437
|
-
while (Date.now() < deadline) {
|
|
438
|
-
await new Promise(r => setTimeout(r, 250));
|
|
439
|
-
try {
|
|
440
|
-
const r = await fetch('/api/health', { cache: 'no-store' });
|
|
441
|
-
if (!r.ok) { everDown = true; continue; }
|
|
442
|
-
if (everDown) { location.reload(); return; }
|
|
443
|
-
} catch { everDown = true; }
|
|
444
|
-
}
|
|
445
|
-
// Timeout safety net — reload anyway so the user isn't stranded.
|
|
446
|
-
location.reload();
|
|
447
|
-
} catch {}
|
|
422
|
+
if (result === 'instructions') location.assign(installGuideUrl());
|
|
448
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(); },
|
|
449
428
|
'menu-stop-server': async () => {
|
|
450
429
|
const previousTitle = document.title;
|
|
451
430
|
try {
|
|
@@ -478,6 +457,9 @@ function wireTerminalMenu() {
|
|
|
478
457
|
} });
|
|
479
458
|
const installItem = $('menu-install-app');
|
|
480
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) });
|
|
481
463
|
|
|
482
464
|
}
|
|
483
465
|
|
|
@@ -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 {
|
|
@@ -8,6 +8,8 @@ import { initDetachedAgentSessions } from './ui-sidepanel-sessions.js';
|
|
|
8
8
|
import { state, emit, on } from './state.js';
|
|
9
9
|
import { getVariant } from './registry.js';
|
|
10
10
|
import { KEYS } from './constants.js';
|
|
11
|
+
import { storage } from './storage.js';
|
|
12
|
+
import { t } from './i18n.js';
|
|
11
13
|
import { loadIfaceConfig, saveIfaceConfig, applyIfaceConfig } from './ui-settings.js';
|
|
12
14
|
import { registerAction } from './ui-keybinds.js';
|
|
13
15
|
import { startTutorial } from './ui-tutorial.js';
|
|
@@ -324,33 +326,55 @@ export function initNavbar() {
|
|
|
324
326
|
document.addEventListener('visibilitychange', () => { if (!document.hidden) updateClock(); });
|
|
325
327
|
}
|
|
326
328
|
|
|
327
|
-
// ──
|
|
328
|
-
//
|
|
329
|
-
|
|
329
|
+
// ── The workspace tools toggle (#topright-tools-btn) ──
|
|
330
|
+
// A plain on/off button for the dock (the workspace switcher and the tools), remembered across reloads. The agent
|
|
331
|
+
// buttons and the session pills stay where they are either way. A menu the dock had open closes with it.
|
|
330
332
|
const controls = $('topright-controls');
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
333
|
+
const toolsBtn = $('topright-tools-btn');
|
|
334
|
+
if (controls && toolsBtn) {
|
|
335
|
+
const showTools = (shown) => {
|
|
336
|
+
if (!shown) emit('panel:close-all-dropdowns');
|
|
337
|
+
controls.classList.toggle('tools-hidden', !shown);
|
|
338
|
+
const label = t(shown ? 'toolbar.hideTools' : 'toolbar.showTools');
|
|
339
|
+
toolsBtn.dataset.tooltip = label;
|
|
340
|
+
toolsBtn.setAttribute('aria-label', label);
|
|
341
|
+
toolsBtn.setAttribute('aria-expanded', String(shown));
|
|
337
342
|
};
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
e.stopPropagation();
|
|
344
|
-
const hidden = !controls.classList.contains('collapsed');
|
|
345
|
-
applyToolbarsHidden(hidden);
|
|
346
|
-
localStorage.setItem('synabun-toolbar-collapsed', hidden ? '1' : '0');
|
|
347
|
-
// Close any open dropdowns when hiding
|
|
348
|
-
if (hidden) emit('panel:close-all-dropdowns');
|
|
343
|
+
showTools(storage.getItem(KEYS.TOPRIGHT_TOOLS_HIDDEN) !== 'true');
|
|
344
|
+
toolsBtn.addEventListener('click', () => {
|
|
345
|
+
const shown = controls.classList.contains('tools-hidden');
|
|
346
|
+
showTools(shown);
|
|
347
|
+
storage.setItem(KEYS.TOPRIGHT_TOOLS_HIDDEN, String(!shown));
|
|
349
348
|
});
|
|
349
|
+
}
|
|
350
350
|
|
|
351
|
-
|
|
351
|
+
// ── Session pills in the row: the whole name is the tooltip ──
|
|
352
|
+
// Laid out in a row, a pill keeps its width on hover (styles.css): widening, it would push the others onto another
|
|
353
|
+
// line under the pointer. A name cut short is read from the tooltip instead; a pill that brings a tooltip of its own
|
|
354
|
+
// (the Assistant's) keeps it.
|
|
355
|
+
const tray = $('term-minimized-tray');
|
|
356
|
+
if (controls && tray && controls.contains(tray)) {
|
|
357
|
+
const nameTips = () => {
|
|
358
|
+
for (const pill of tray.children) {
|
|
359
|
+
const name = pill.querySelector('.term-minimized-pill-label')?.textContent.trim() || '';
|
|
360
|
+
if (pill.hasAttribute('data-tooltip') && pill.dataset.tooltip !== pill.dataset.nameTip) {
|
|
361
|
+
delete pill.dataset.nameTip;
|
|
362
|
+
} else if (name) {
|
|
363
|
+
pill.dataset.tooltip = name;
|
|
364
|
+
pill.dataset.nameTip = name;
|
|
365
|
+
} else if (pill.dataset.nameTip != null) {
|
|
366
|
+
pill.removeAttribute('data-tooltip');
|
|
367
|
+
delete pill.dataset.nameTip;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
new MutationObserver(nameTips).observe(tray, { childList: true, subtree: true, characterData: true });
|
|
372
|
+
nameTips();
|
|
352
373
|
}
|
|
353
374
|
|
|
375
|
+
// "Hide all toolbars" is gone: whoever had it on gets every toolbar back, and its key goes with it.
|
|
376
|
+
try { localStorage.removeItem('synabun-toolbar-collapsed'); } catch { /* storage refused: nothing to clear */ }
|
|
377
|
+
|
|
354
378
|
// ── Update alert ──
|
|
355
379
|
initUpdate();
|
|
356
380
|
initToolUpdates();
|