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
|
@@ -29,11 +29,13 @@ import { emit, on, state as appState } from '../state.js';
|
|
|
29
29
|
import { storage } from '../storage.js';
|
|
30
30
|
import { KEYS } from '../constants.js';
|
|
31
31
|
import { t } from '../i18n.js';
|
|
32
|
+
import { forgetGreeting, mountGreeting } from '../greeting/greeting-card.js';
|
|
32
33
|
import { notify, NOTIF_TYPE } from '../ui-notifications.js';
|
|
33
34
|
import { getProviderMeta } from '../provider-icons.js';
|
|
34
35
|
import { isGuest, hasPermission } from '../ui-sync.js';
|
|
35
36
|
import { getWhiteboardElementById } from '../ui-whiteboard.js';
|
|
36
37
|
import { focusNativeLoopRun } from '../ui-native-loop-router.js';
|
|
38
|
+
import { wireFileLinks } from '../ui-file-links.js';
|
|
37
39
|
import { injectAssistantStyles } from './asst-styles.js';
|
|
38
40
|
import { createAssistantSocket } from './asst-ws.js';
|
|
39
41
|
import { createRenderer, ICON_ASSISTANT, mdInto } from './asst-render.js';
|
|
@@ -42,7 +44,7 @@ import { lastInputAt, onKey, onPointer } from '../synabun-ticker.js';
|
|
|
42
44
|
import { buildControlResponse, closedControlState, normalizeControlRequest, renderControlCard } from './asst-control.js';
|
|
43
45
|
import { buildPromptText, createComposer } from './asst-composer.js';
|
|
44
46
|
import { buildDispatchSpec, parseSlashCommand, slashHelpMarkdown } from './asst-slash.js';
|
|
45
|
-
import { createBrainPicker } from './asst-brain-picker.js';
|
|
47
|
+
import { cachedProjects, createBrainPicker, testDensityLabel } from './asst-brain-picker.js';
|
|
46
48
|
import { createRovingToolbar } from './asst-roving.js';
|
|
47
49
|
import { openAccountsManager } from './asst-accounts.js';
|
|
48
50
|
import { createAgentsDock } from './asst-agents-dock.js';
|
|
@@ -52,9 +54,9 @@ import { createRouteModeControl, openModelsManager, openRoutesEditor, refreshMod
|
|
|
52
54
|
import { budgetChipText, budgetTone, openBudgetEditor } from './asst-budget.js';
|
|
53
55
|
import { computerRemoteView, createComputerPanel, createComputerToggle, normalizeComputerRemote, openFrameLightbox, closeFrameLightbox, requestDesktopStop } from './asst-computer.js';
|
|
54
56
|
import {
|
|
55
|
-
applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
|
|
56
|
-
brainModePatch, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, providerShortLabel, readStoredBrain, runFromPayload,
|
|
57
|
-
serializeTabState, tabStorageKey,
|
|
57
|
+
applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
|
|
58
|
+
brainModePatch, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerShortLabel, readStoredBrain, runFromPayload,
|
|
59
|
+
serializeTabState, tabStorageKey, userSessionTitle,
|
|
58
60
|
} from './asst-state.js';
|
|
59
61
|
import {
|
|
60
62
|
closeAssistantSession, dispatchAssistantRun, escalateAssistantRun, focusAssistantRun, getAssistantRun,
|
|
@@ -93,10 +95,6 @@ function num(value) {
|
|
|
93
95
|
return value != null && value !== '' && Number.isFinite(n) ? n : null;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
function basename(path) {
|
|
97
|
-
return String(path || '').split(/[\\/]/).filter(Boolean).pop() || String(path || '');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
98
|
function relativeTime(value) {
|
|
101
99
|
const ms = new Date(value || 0).getTime();
|
|
102
100
|
if (!ms) return '';
|
|
@@ -109,6 +107,10 @@ function relativeTime(value) {
|
|
|
109
107
|
return `${Math.floor(hrs / 24)}d`;
|
|
110
108
|
}
|
|
111
109
|
|
|
110
|
+
// Renames on their way to a session record. One writer for the page, not one per tab: a write
|
|
111
|
+
// outlives the tab that asked for it, and every Sessions menu waits for all of them.
|
|
112
|
+
const renames = createRenameWriter({ patch: patchAssistantSession });
|
|
113
|
+
|
|
112
114
|
function clipCopy(text) {
|
|
113
115
|
if (navigator.clipboard?.writeText) navigator.clipboard.writeText(text).catch(() => {});
|
|
114
116
|
}
|
|
@@ -116,17 +118,21 @@ function clipCopy(text) {
|
|
|
116
118
|
/**
|
|
117
119
|
* mountAssistant(viewport, { sessionId, brain, host, session })
|
|
118
120
|
* host: { id: 'terminal'|'sidepanel', notifySource: 'cli'|'panel',
|
|
119
|
-
* setLabel(text),
|
|
121
|
+
* setLabel(text), setName?(text, renamed) (a rename that was not saved: the tab's name and its
|
|
122
|
+
* renamed flag go back, saved label included), setStatus('idle'|'working'|'action'|'done'), setBrain(brain),
|
|
120
123
|
* isVisible() → bool, toolbarSlot?: Element (where the toolbar goes; default the root),
|
|
121
124
|
* takeHeroOrigin?() → DOMRect | null (a character the host showed while starting: the empty state's flies in from it) }
|
|
122
125
|
* The hooks may fire during mount, before this returns.
|
|
123
|
-
* The tab label is always "SynaBun"; a user rename arrives via controller.setTitle
|
|
126
|
+
* The tab label is always "SynaBun"; a user rename arrives via controller.setTitle
|
|
127
|
+
* and is written to the session record (saveRename), where every session list reads it.
|
|
124
128
|
*/
|
|
125
129
|
export function mountAssistant(viewport, { sessionId, brain, host = {}, session = null } = {}) {
|
|
126
130
|
injectAssistantStyles();
|
|
127
131
|
const saved = deserializeTabState(storage.getItem(tabStorageKey(sessionId)));
|
|
132
|
+
let greetingId = null; // the greeting this conversation opened with, until its first prompt carries it
|
|
133
|
+
const defaultTitle = tt('assistant.defaultTitle', 'SynaBun');
|
|
128
134
|
const st = createTabState(sessionId, brain || session?.brain || saved?.brain || readStoredBrain(storage), {
|
|
129
|
-
title:
|
|
135
|
+
title: defaultTitle,
|
|
130
136
|
// The agents tray starts collapsed; it only expands on request.
|
|
131
137
|
dockOpen: saved ? saved.dockOpen : storage.getItem(KEYS.ASSISTANT_DOCK_OPEN) === '1',
|
|
132
138
|
dockShowAll: saved ? saved.dockShowAll : storage.getItem(KEYS.ASSISTANT_DOCK_SHOW_ALL) === '1',
|
|
@@ -135,6 +141,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
135
141
|
providerSessionId: session?.providerSessionId || null,
|
|
136
142
|
routeMode: saved?.routeMode ?? null,
|
|
137
143
|
computerUse: saved?.computerUse ?? null,
|
|
144
|
+
testDensity: saved?.testDensity ?? null,
|
|
138
145
|
usageView: saved?.usageView || null,
|
|
139
146
|
});
|
|
140
147
|
Object.assign(st, {
|
|
@@ -144,7 +151,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
144
151
|
engine: '',
|
|
145
152
|
sdkVersion: '',
|
|
146
153
|
routing: null, // server view { mode, effectiveMode, defaultMode, askBelow }
|
|
147
|
-
features: { routing: null, computer: null }, // null = unknown yet
|
|
154
|
+
features: { routing: null, computer: null, testDensity: null, rename: null }, // null = unknown yet
|
|
155
|
+
testDensityEffective: null, // server view: the level in effect
|
|
148
156
|
brainCapabilities: null,
|
|
149
157
|
computerEffective: st.computerUse === true,
|
|
150
158
|
desktopSupported: null,
|
|
@@ -152,8 +160,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
152
160
|
desktopActive: false,
|
|
153
161
|
desktopProbe: false,
|
|
154
162
|
routingProbe: false,
|
|
155
|
-
sessionTitle: String(session?.title || ''), // the server's name (first prompt): history + notifications
|
|
163
|
+
sessionTitle: String(session?.title || ''), // the server's name (the user's rename, else the first prompt): history + notifications
|
|
156
164
|
});
|
|
165
|
+
let recordName = userSessionTitle(session); // the name the session record holds as the user's ('' = never renamed)
|
|
157
166
|
const controls = new Map(); // requestId → { card, origin, kind }
|
|
158
167
|
// Cards answered here (requestId → card): one the server closed before the answer
|
|
159
168
|
// arrived (control_cancelled after it) says so instead of keeping "Allowed".
|
|
@@ -253,6 +262,45 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
253
262
|
try { host.setLabel?.(st.title); } catch { /* ignore */ }
|
|
254
263
|
}
|
|
255
264
|
|
|
265
|
+
/** What the session record says about its name (a session view: the rename's answer, a broadcast, an attach). */
|
|
266
|
+
function applyRecordName(meta) {
|
|
267
|
+
if (!meta || typeof meta !== 'object' || !meta.title || (meta.id && meta.id !== sessionId)) return;
|
|
268
|
+
st.sessionTitle = String(meta.title);
|
|
269
|
+
recordName = userSessionTitle(meta);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* A rename names the session, not this tab: it goes to the session record, which the Sessions
|
|
274
|
+
* menu and every other list read, through the page's one writer (`renames`). A host also calls
|
|
275
|
+
* setTitle when it mounts a renamed tab (`restored`): the name the record already holds is not
|
|
276
|
+
* written again, one it lacks (a rename made before the record kept names) is, and it never
|
|
277
|
+
* replaces a name on its way. "SynaBun" is no name: it is written only to take a rename back.
|
|
278
|
+
* `from` is the name the tab had before: a write that fails puts it back (renameFailed).
|
|
279
|
+
*/
|
|
280
|
+
function saveRename(from, restored = false) {
|
|
281
|
+
if (destroyed || (restored && renames.pending(sessionId))) return;
|
|
282
|
+
renames.save(sessionId, st.title, {
|
|
283
|
+
from, recordName, recordTitle: st.sessionTitle, keepsRenames: st.features.rename === true, defaultTitle,
|
|
284
|
+
onSaved: applyRecordName,
|
|
285
|
+
onFailed: renameFailed,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* A rename that did not reach the record: the tab goes back to the name the record answers to,
|
|
291
|
+
* in the host and in the label it saved, and the transcript says so. A name with nothing to go
|
|
292
|
+
* back to (a restored one, or the name the tab already shows) stays: the next mount sends it again.
|
|
293
|
+
*/
|
|
294
|
+
function renameFailed({ name, back }) {
|
|
295
|
+
const previous = back || defaultTitle;
|
|
296
|
+
if (destroyed || previous === st.title) return;
|
|
297
|
+
st.userRenamed = previous !== defaultTitle;
|
|
298
|
+
st.title = previous;
|
|
299
|
+
try { host.setName?.(previous, st.userRenamed); } catch { /* ignore */ }
|
|
300
|
+
persist();
|
|
301
|
+
renderer.appendStatus(tt('assistant.status.renameFailed', 'Could not save the name “{name}”. The session is still called “{previous}”.', { name, previous }), 'warn');
|
|
302
|
+
}
|
|
303
|
+
|
|
256
304
|
/** Notifications say which conversation: the rename, else the session's first-prompt title. */
|
|
257
305
|
function notifyLabel() {
|
|
258
306
|
return st.userRenamed ? st.title : (st.sessionTitle || st.title);
|
|
@@ -378,6 +426,20 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
378
426
|
return st.features.routing === true;
|
|
379
427
|
}
|
|
380
428
|
|
|
429
|
+
// ── File links ──
|
|
430
|
+
// A link to a file the code editor can open opens it there (shared with the other panels): one listener
|
|
431
|
+
// for the transcript, whatever drew the message. A relative path is a path in the brain's project.
|
|
432
|
+
wireFileLinks(transcriptEl, {
|
|
433
|
+
cwd: () => st.brain?.project || '',
|
|
434
|
+
textLinks: 'a.file-link',
|
|
435
|
+
// A path the editor does not open keeps what a click on it did: it is copied.
|
|
436
|
+
copyPath: (link) => {
|
|
437
|
+
clipCopy((link.textContent || '').replace(/:\d+$/, ''));
|
|
438
|
+
link.style.opacity = '0.5';
|
|
439
|
+
setTimeout(() => { link.style.opacity = ''; }, 300);
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
|
|
381
443
|
// ── Renderer ──
|
|
382
444
|
const renderer = createRenderer(transcriptEl, {
|
|
383
445
|
t,
|
|
@@ -389,10 +451,18 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
389
451
|
onReadRun: (runId) => readRun(runId),
|
|
390
452
|
onEscalateRun: (runId, target) => escalateRun(runId, target),
|
|
391
453
|
onMemoryClick: (id) => { if (id) emit('memory:open', { id }); },
|
|
454
|
+
// The greeting this conversation opens with (lib/greeting/ decides whether there is one): its id
|
|
455
|
+
// goes back with the first prompt, so the brain is told once what was said.
|
|
456
|
+
greeting: (slot) => (guestBlocked() ? null : mountGreeting(slot, {
|
|
457
|
+
surface: 'assistant', session: sessionId, cwd: st.brain?.project || null, t,
|
|
458
|
+
onOpenMemory: (id) => { if (id) emit('memory:open', { id }); },
|
|
459
|
+
}).then((greeting) => { greetingId = greeting?.id || null; return greeting; })),
|
|
392
460
|
brainLabel: () => brainModelLabel(),
|
|
393
461
|
onChangeRoutes: () => openRoutes(),
|
|
394
462
|
onRouteEvent: (ev) => handleRouteCardEvent(ev),
|
|
395
463
|
emptySuggestions: () => emptySuggestions(),
|
|
464
|
+
// "Choose a project" in the empty state is the toolbar's Working project field (asst-brain-picker.js).
|
|
465
|
+
mountEmptyProject: (slot) => picker.mountEmptyProject(slot),
|
|
396
466
|
onSuggestion: (template) => composer.fillTemplate(template),
|
|
397
467
|
heroOrigin: () => { try { return host.takeHeroOrigin?.() || null; } catch { return null; } },
|
|
398
468
|
onMascotChange: () => director?.retarget(),
|
|
@@ -424,7 +494,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
424
494
|
});
|
|
425
495
|
|
|
426
496
|
function emptySuggestions() {
|
|
427
|
-
const project = st.brain.project
|
|
497
|
+
const project = projectLabel(st.brain.project, cachedProjects()) || tt('assistant.empty.thisProject', 'this project');
|
|
428
498
|
const list = [];
|
|
429
499
|
if (computerAvailable()) list.push({ id: 'computer', label: tt('assistant.empty.suggestComputer', 'Use my Mac to…'), template: tt('assistant.empty.templateComputer', 'Use my Mac to {caret}') });
|
|
430
500
|
list.push({ id: 'web', label: tt('assistant.empty.suggestWeb', 'Look up … on the web'), template: tt('assistant.empty.templateWeb', 'Look up {caret} on the web') });
|
|
@@ -455,8 +525,6 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
455
525
|
director = createMascotDirector({
|
|
456
526
|
getTarget: () => renderer.mascot(),
|
|
457
527
|
caret: () => composer.caretPoint(),
|
|
458
|
-
setEnabled: (on) => renderer.setRigsEnabled(on),
|
|
459
|
-
isVisible: () => visible(),
|
|
460
528
|
env: {
|
|
461
529
|
input: (fn) => { const offPointer = onPointer(fn); const offKey = onKey(fn); return () => { offPointer(); offKey(); }; },
|
|
462
530
|
lastInputAt,
|
|
@@ -490,6 +558,11 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
490
558
|
getMenuAnchor: () => moreBtn,
|
|
491
559
|
// Composer fields open upward, toolbar fields downward.
|
|
492
560
|
menuPlacement: 'auto',
|
|
561
|
+
// Test density sits right after the permission mode; hidden on a server that does not know it.
|
|
562
|
+
getTestDensity: () => testDensityView(),
|
|
563
|
+
onTestDensity: (level) => setTestDensity(level),
|
|
564
|
+
// The registered projects arrived: their labels name the project in the fields and the "Fix … in" suggestion.
|
|
565
|
+
onProjects: () => { picker.render(); renderer.refreshEmpty(); },
|
|
493
566
|
});
|
|
494
567
|
|
|
495
568
|
const computerToggle = createComputerToggle(barGroups.computer, {
|
|
@@ -823,8 +896,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
823
896
|
function applySessionMeta(meta) {
|
|
824
897
|
if (!meta || typeof meta !== 'object') return;
|
|
825
898
|
if (meta.id && meta.id !== sessionId) return;
|
|
826
|
-
// The server's title names the conversation (history, notifications)
|
|
827
|
-
|
|
899
|
+
// The server's title names the conversation (history, notifications); the tab's name is the host's.
|
|
900
|
+
applyRecordName(meta);
|
|
828
901
|
if (meta.brain && typeof meta.brain === 'object') {
|
|
829
902
|
const next = normalizeBrain({ ...st.brain, ...meta.brain, provider: meta.brain.provider || meta.brain.brain || st.brain.provider });
|
|
830
903
|
if (JSON.stringify(next) !== JSON.stringify(st.brain)) { st.brain = next; picker.render(); host.setBrain?.(next); persist(); }
|
|
@@ -847,7 +920,11 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
847
920
|
if (meta.features && typeof meta.features === 'object') {
|
|
848
921
|
if (typeof meta.features.routing === 'boolean') st.features.routing = meta.features.routing;
|
|
849
922
|
if (typeof meta.features.computer === 'boolean') st.features.computer = meta.features.computer;
|
|
923
|
+
if (typeof meta.features.testDensity === 'boolean') st.features.testDensity = meta.features.testDensity;
|
|
924
|
+
if (typeof meta.features.rename === 'boolean') st.features.rename = meta.features.rename;
|
|
850
925
|
}
|
|
926
|
+
if ('testDensityExplicit' in meta) st.testDensity = normalizeTestDensity(meta.testDensityExplicit, null);
|
|
927
|
+
if (meta.testDensity) st.testDensityEffective = normalizeTestDensity(meta.testDensity);
|
|
851
928
|
if (typeof meta.computerUse === 'boolean') st.computerEffective = meta.computerUse;
|
|
852
929
|
if ('computerUseExplicit' in meta) st.computerUse = normalizeComputerMode(meta.computerUseExplicit, null);
|
|
853
930
|
// A WhatsApp conversation: what is in effect and why (not a per-conversation switch). null on the desktop.
|
|
@@ -872,6 +949,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
872
949
|
if (destroyed) return;
|
|
873
950
|
routeChip.setVisible(routingAvailable());
|
|
874
951
|
routeChip.render();
|
|
952
|
+
picker.render();
|
|
875
953
|
const showComputer = st.features.computer === true || st.desktopSupported === true;
|
|
876
954
|
computerToggle.set({
|
|
877
955
|
visible: showComputer,
|
|
@@ -920,7 +998,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
920
998
|
|
|
921
999
|
function routeModeView() {
|
|
922
1000
|
const r = st.routing || {};
|
|
923
|
-
return { mode: normalizeRouteMode(st.routeMode, null) || r.mode || null, effectiveMode: r.effectiveMode, defaultMode: r.defaultMode };
|
|
1001
|
+
return { mode: normalizeRouteMode(st.routeMode, null) || r.mode || null, effectiveMode: r.effectiveMode, defaultMode: r.defaultMode, askBelow: r.askBelow };
|
|
924
1002
|
}
|
|
925
1003
|
|
|
926
1004
|
function setRouteMode(mode, { quiet = false } = {}) {
|
|
@@ -943,6 +1021,31 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
943
1021
|
if (last && last !== st.routing.effectiveMode) setRouteMode(last, { quiet: true });
|
|
944
1022
|
}
|
|
945
1023
|
|
|
1024
|
+
/** The level the composer shows: this session's, else the server's; null while the server does not know the setting. */
|
|
1025
|
+
function testDensityView() {
|
|
1026
|
+
if (st.features.testDensity !== true) return null;
|
|
1027
|
+
return normalizeTestDensity(st.testDensity || st.testDensityEffective);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
function setTestDensity(level, { quiet = false } = {}) {
|
|
1031
|
+
const next = normalizeTestDensity(level);
|
|
1032
|
+
st.testDensity = next;
|
|
1033
|
+
st.testDensityEffective = next;
|
|
1034
|
+
picker.render();
|
|
1035
|
+
persist();
|
|
1036
|
+
sock.send({ type: 'set_test_density', level: next });
|
|
1037
|
+
try { storage.setItem(KEYS.ASSISTANT_TEST_DENSITY, next); } catch { /* storage unavailable */ }
|
|
1038
|
+
if (!quiet) renderer.appendStatus(tt('assistant.status.testDensity', 'Test density: {level}', { level: testDensityLabel(next, t) }));
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/** Fresh tabs inherit the last-used test density (like the route mode). */
|
|
1042
|
+
function applyLastUsedTestDensity() {
|
|
1043
|
+
if (saved || st.features.testDensity !== true || st.testDensity != null) return;
|
|
1044
|
+
let last = null;
|
|
1045
|
+
try { last = normalizeTestDensity(storage.getItem(KEYS.ASSISTANT_TEST_DENSITY), null); } catch { last = null; }
|
|
1046
|
+
if (last && last !== testDensityView()) setTestDensity(last, { quiet: true });
|
|
1047
|
+
}
|
|
1048
|
+
|
|
946
1049
|
/** A WhatsApp conversation's Computer switch says why it is what it is (the status line of the transcript). */
|
|
947
1050
|
function explainRemoteComputer() {
|
|
948
1051
|
const view = computerRemoteView(st.computerRemote, t);
|
|
@@ -1170,6 +1273,10 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1170
1273
|
request_id: `q-${Date.now().toString(36)}-${(querySeq += 1)}`,
|
|
1171
1274
|
};
|
|
1172
1275
|
if (payload.images?.length) msg.images = payload.images.map(i => ({ base64: i.base64, mediaType: i.mediaType }));
|
|
1276
|
+
// The typed words apart from long pastes (asst-composer.js): what the server may learn about the user from.
|
|
1277
|
+
if (typeof payload.typed === 'string') msg.typed = payload.typed;
|
|
1278
|
+
// The greeting shown when this conversation opened: echoed once, with the first prompt.
|
|
1279
|
+
if (greetingId) { msg.greetingId = greetingId; greetingId = null; forgetGreeting('assistant', sessionId); }
|
|
1173
1280
|
const row = renderer.appendUser(payload.display ?? payload.text, { images: payload.images, files: [...(payload.files || []), ...(payload.uploads || [])], memories: payload.memories });
|
|
1174
1281
|
director.sent();
|
|
1175
1282
|
sentQueries.set(msg.request_id, { payload, row });
|
|
@@ -1178,7 +1285,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1178
1285
|
setRunning(true);
|
|
1179
1286
|
sock.send(msg);
|
|
1180
1287
|
// Name the conversation like the server will (its first prompt) — not the tab.
|
|
1181
|
-
if (!st.sessionTitle || /^(?:SynaBun|Assistant(?: \d+)?)$/.test(st.sessionTitle)) {
|
|
1288
|
+
if (!st.userRenamed && (!st.sessionTitle || /^(?:SynaBun|Assistant(?: \d+)?)$/.test(st.sessionTitle))) {
|
|
1182
1289
|
const guess = String(payload.text || '').split('\n')[0].trim().slice(0, 60);
|
|
1183
1290
|
if (guess) st.sessionTitle = guess;
|
|
1184
1291
|
}
|
|
@@ -1222,7 +1329,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1222
1329
|
return true;
|
|
1223
1330
|
case 'resume':
|
|
1224
1331
|
if (parsed.sessionId) resume(parsed.sessionId);
|
|
1225
|
-
else sock.send({ type: 'list_sessions' });
|
|
1332
|
+
else renames.settled().then(() => { if (!destroyed) sock.send({ type: 'list_sessions' }); }); // a rename on its way is in the list
|
|
1226
1333
|
return true;
|
|
1227
1334
|
case 'stop':
|
|
1228
1335
|
if (parsed.all) await stopAll();
|
|
@@ -1357,6 +1464,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1357
1464
|
picker.render();
|
|
1358
1465
|
host.setBrain?.(st.brain);
|
|
1359
1466
|
persist();
|
|
1467
|
+
if (before.project !== st.brain.project) renderer.refreshEmpty();
|
|
1360
1468
|
if (meta.silent) return;
|
|
1361
1469
|
if (meta.requiresSwitch) {
|
|
1362
1470
|
const b = st.brain;
|
|
@@ -1366,7 +1474,6 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1366
1474
|
} else if (before.permissionMode !== st.brain.permissionMode || !!before.planMode !== !!st.brain.planMode) {
|
|
1367
1475
|
sock.send({ type: 'set_permission_mode', mode: st.brain.permissionMode, planMode: st.brain.planMode === true });
|
|
1368
1476
|
}
|
|
1369
|
-
if (before.project !== st.brain.project) renderer.refreshEmpty();
|
|
1370
1477
|
patchAssistantSession(sessionId, { brain: st.brain }).catch((err) => {
|
|
1371
1478
|
// Refused (a model disabled in Assistant → Models): undo, so the refused
|
|
1372
1479
|
// brain is neither shown nor saved as the last used one — the next start
|
|
@@ -1374,6 +1481,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1374
1481
|
if (err?.code !== 'MODEL_DISABLED' || destroyed || st.brain !== applied) return;
|
|
1375
1482
|
st.brain = before;
|
|
1376
1483
|
picker.render();
|
|
1484
|
+
if (applied.project !== before.project) renderer.refreshEmpty();
|
|
1377
1485
|
host.setBrain?.(before);
|
|
1378
1486
|
persist();
|
|
1379
1487
|
if (!meta.requiresSwitch) renderer.appendError(err.message || String(err));
|
|
@@ -1384,7 +1492,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1384
1492
|
async function focusRun(runId) {
|
|
1385
1493
|
if (!runId) return;
|
|
1386
1494
|
focusAssistantRun(runId).catch(() => {});
|
|
1387
|
-
|
|
1495
|
+
// The user's own Focus: a run whose tab was closed opens again.
|
|
1496
|
+
try { await focusNativeLoopRun(runId, { reopen: true }); } catch { /* router not ready */ }
|
|
1388
1497
|
}
|
|
1389
1498
|
|
|
1390
1499
|
async function stopRun(runId) {
|
|
@@ -1615,6 +1724,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1615
1724
|
providerIcon,
|
|
1616
1725
|
getBrain: () => st.brain,
|
|
1617
1726
|
brainName: () => brainModelLabel(),
|
|
1727
|
+
getRouting: () => st.routing,
|
|
1618
1728
|
onToast: toast,
|
|
1619
1729
|
onSaved: (routing) => {
|
|
1620
1730
|
if (routing?.defaultMode) {
|
|
@@ -1667,7 +1777,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1667
1777
|
e.stopPropagation();
|
|
1668
1778
|
if (isMenuOpen(sessionsBtn)) { closeMenu(); return; }
|
|
1669
1779
|
let list = [];
|
|
1670
|
-
|
|
1780
|
+
// A rename still on its way to a record is in the list this opens: this tab's, another tab's, a closed one's.
|
|
1781
|
+
try { await renames.settled(); list = await listAssistantSessions(); } catch { /* server not ready */ }
|
|
1671
1782
|
if (!destroyed) showSessionsMenu(list);
|
|
1672
1783
|
});
|
|
1673
1784
|
function toggleDock() {
|
|
@@ -1755,6 +1866,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1755
1866
|
if (force) renderer.clear();
|
|
1756
1867
|
if (Array.isArray(transcript) && transcript.length) renderer.renderTranscript(transcript);
|
|
1757
1868
|
renderer.showEmpty(); // no-op once the transcript has rows
|
|
1869
|
+
// A conversation with nothing in it yet may be greeted; a restored one never is.
|
|
1870
|
+
if (Array.isArray(transcript) && !transcript.length && !(Number(meta?.turns) > 0)) renderer.offerGreeting();
|
|
1758
1871
|
for (const run of (Array.isArray(data?.runs) ? data.runs : [])) dock.upsertRun(run);
|
|
1759
1872
|
} catch (err) {
|
|
1760
1873
|
console.warn('[assistant] could not restore the conversation', err);
|
|
@@ -1774,6 +1887,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1774
1887
|
if (destroyed) return;
|
|
1775
1888
|
probeFeatures();
|
|
1776
1889
|
applyLastUsedRouteMode();
|
|
1890
|
+
applyLastUsedTestDensity();
|
|
1777
1891
|
sock.connect();
|
|
1778
1892
|
});
|
|
1779
1893
|
fetchUsage();
|
|
@@ -1784,7 +1898,15 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1784
1898
|
getBrain: () => st.brain,
|
|
1785
1899
|
setBrain: (b, meta) => applyBrain(b, meta || { requiresSwitch: false, field: 'external' }),
|
|
1786
1900
|
getTitle: () => st.title,
|
|
1787
|
-
|
|
1901
|
+
/** A rename (the host's tab, float header or ✎), or with `restored` the name a host puts back when it mounts a renamed tab. */
|
|
1902
|
+
setTitle: (text, { restored = false } = {}) => {
|
|
1903
|
+
const next = String(text || '').trim();
|
|
1904
|
+
if (!next) return;
|
|
1905
|
+
const from = restored ? next : st.title; // a restored name has none to go back to
|
|
1906
|
+
st.userRenamed = next !== defaultTitle; // the default name is no rename
|
|
1907
|
+
setTitle(next);
|
|
1908
|
+
saveRename(from, restored);
|
|
1909
|
+
},
|
|
1788
1910
|
isRunning: () => st.running,
|
|
1789
1911
|
isConnected: () => st.connected,
|
|
1790
1912
|
send: (text, extra = {}) => submit({ text: String(text ?? ''), images: extra.images || [], files: extra.files || [], uploads: extra.uploads || [], memories: extra.memories || [] }),
|
|
@@ -1799,12 +1921,12 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
|
|
|
1799
1921
|
insertText: (text) => composer.insertText(text),
|
|
1800
1922
|
/** A file path from the explorer ("send to panel") → the composer, as inline code. */
|
|
1801
1923
|
attachPath: (path) => { if (path) { composer.insertText(`\`${path}\` `); composer.focus(); } },
|
|
1802
|
-
/** The server's name for the conversation (
|
|
1924
|
+
/** The server's name for the conversation (the user's rename, else the first prompt): tooltips. */
|
|
1803
1925
|
getConversationTitle: () => st.sessionTitle || '',
|
|
1804
1926
|
getStatus: () => st.status || 'idle',
|
|
1805
1927
|
focus: () => composer.focus(),
|
|
1806
|
-
onShown: () => { syncTabLabel(); renderer.scrollEnd(true); if (visible()) composer.focus(); director.touch();
|
|
1807
|
-
onHidden: () => { closeMenu(); picker.close(); director.stopTyping();
|
|
1928
|
+
onShown: () => { syncTabLabel(); renderer.scrollEnd(true); if (visible()) composer.focus(); director.touch(); },
|
|
1929
|
+
onHidden: () => { closeMenu(); picker.close(); director.stopTyping(); },
|
|
1808
1930
|
counts: () => dock.counts(),
|
|
1809
1931
|
destroy: ({ closeServer = false } = {}) => {
|
|
1810
1932
|
if (destroyed) return;
|