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
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { assistantEventKey, fmtCost, fmtElapsed, isRemovableRun, isRunIdle, isTerminalRunStatus, modelShortName, providerShortLabel, routeTargetLabel, runTone, summarizeMailbox } from './asst-state.js';
|
|
22
22
|
import { createRouteLine } from './asst-route.js';
|
|
23
|
+
import { closeMenu, isMenuOpen } from './asst-menu.js';
|
|
23
24
|
import { computerToolName, describeComputerAction, frameUrls, markerPercent, openFrameLightbox, parseComputerResult, swapImage } from './asst-computer.js';
|
|
24
25
|
import * as mascotLib from '../synabun-mascot.js';
|
|
25
26
|
import { isReducedMotion, subscribe } from '../synabun-ticker.js';
|
|
@@ -27,6 +28,7 @@ import { KIND_SPECS, callOutcome, commandOf, editDiff, editPaths, fmtDuration, g
|
|
|
27
28
|
import { injectRackStyles } from './asst-rack-styles.js';
|
|
28
29
|
import { formatRunTokens } from './asst-usage.js';
|
|
29
30
|
import { sanitizeHtmlString, sanitizeInto } from './asst-sanitize.js';
|
|
31
|
+
import { automationView } from './asst-automation.js';
|
|
30
32
|
|
|
31
33
|
// ── Markdown (lazy marked, same CDN build as the sidepanels) ───────────────
|
|
32
34
|
let _marked = null;
|
|
@@ -227,7 +229,7 @@ export function updateRunCard(card, run, opts = {}) {
|
|
|
227
229
|
const routeBits = [r.taskClassLabel || r.taskClass || t('assistant.routes.task', 'task')];
|
|
228
230
|
if (r.status === 'pending') routeBits.push(t('assistant.routes.state.pending', 'waiting for your choice'));
|
|
229
231
|
else if (r.decidedBy === 'user') routeBits.push(t('assistant.routes.youChose', 'you chose'));
|
|
230
|
-
else if (r.remembered || r.decidedBy === 'remembered') routeBits.push(t('assistant.routes.remembered', '
|
|
232
|
+
else if (r.remembered || r.decidedBy === 'remembered') routeBits.push(t('assistant.routes.remembered', 'your saved choice'));
|
|
231
233
|
else if (Number.isFinite(Number(r.confidence))) routeBits.push(`${Math.round(Number(r.confidence) <= 1 ? Number(r.confidence) * 100 : Number(r.confidence))}%`);
|
|
232
234
|
const tip = r.target ? `${t('assistant.routes.routedTo', 'Routed to')} ${routeTargetLabel(r.target, { effort: true })}` : t('assistant.routes.title', 'Model routing');
|
|
233
235
|
bits.push(`<span class="asst-run-route" data-tooltip="${esc(tip)}">⇄ ${esc(routeBits.join(', '))}</span>`);
|
|
@@ -434,12 +436,12 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
434
436
|
const scopes = new Map(); // parent_tool_use_id → { container, stream, key }
|
|
435
437
|
const runCards = new Map(); // runId → card element
|
|
436
438
|
const routeLines = new Map(); // routeId → line handle
|
|
439
|
+
const autoRows = new Map(); // traceId → the turn's automation trace row
|
|
437
440
|
let working = null;
|
|
438
441
|
let workingFace = null; // the "Thinking" row's character: { still, rig?, el, target? } (syncWorkingFace)
|
|
439
442
|
let followTail = true;
|
|
440
443
|
let emptyEl = null;
|
|
441
444
|
let hero = null; // the empty state's character: { rig, el, box, parked, leaving, held, dock, egg, target }
|
|
442
|
-
let rigsOn = true; // this panel's rigs may animate (asst-mascot.js lets one panel at a time)
|
|
443
445
|
const mcpWarned = new Set();
|
|
444
446
|
let lastErrorText = ''; // a synthetic API-error message's text, so the result does not repeat it
|
|
445
447
|
let turnFrames = []; // computer cards with inline thumbnails in the current turn
|
|
@@ -539,10 +541,17 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
539
541
|
function hideEmpty({ park = false } = {}) {
|
|
540
542
|
if (!emptyEl) return;
|
|
541
543
|
if (!(park && parkHero())) dropHero();
|
|
544
|
+
closeEmptyMenu();
|
|
542
545
|
emptyEl.remove();
|
|
543
546
|
emptyEl = null;
|
|
544
547
|
}
|
|
545
548
|
|
|
549
|
+
/** A menu opened from the empty state's project picker does not outlive it. */
|
|
550
|
+
function closeEmptyMenu() {
|
|
551
|
+
const btn = emptyEl?.querySelector('.asst-empty-project-btn');
|
|
552
|
+
if (btn && isMenuOpen(btn)) closeMenu();
|
|
553
|
+
}
|
|
554
|
+
|
|
546
555
|
// ── The hero ──
|
|
547
556
|
const cssEase = (name, fallback) => {
|
|
548
557
|
try { return getComputedStyle($msgs).getPropertyValue(name).trim() || fallback; } catch { return fallback; }
|
|
@@ -698,13 +707,6 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
698
707
|
try { hooks.onMascotChange?.(); } catch { /* the director is gone */ }
|
|
699
708
|
}
|
|
700
709
|
|
|
701
|
-
/** Whether this panel's rigs animate (another panel may lead); still frames otherwise. */
|
|
702
|
-
function setRigsEnabled(on) {
|
|
703
|
-
if (rigsOn === !!on) return;
|
|
704
|
-
rigsOn = !!on;
|
|
705
|
-
activateRigs();
|
|
706
|
-
}
|
|
707
|
-
|
|
708
710
|
function prune() {
|
|
709
711
|
const rows = $msgs.children;
|
|
710
712
|
while (rows.length > MAX_MESSAGES && rows[0] !== working) rows[0].remove();
|
|
@@ -757,8 +759,8 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
757
759
|
const a = el('a', 'file-link', match[0]);
|
|
758
760
|
a.href = '#';
|
|
759
761
|
a.title = t('assistant.copyPath', 'Click to copy path');
|
|
760
|
-
|
|
761
|
-
|
|
762
|
+
// The click is taken on the transcript (asst-panel.js → ui-file-links.js): the code editor when it
|
|
763
|
+
// can open the path, else the copy a click has always made.
|
|
762
764
|
frag.appendChild(a);
|
|
763
765
|
last = match.index + match[0].length;
|
|
764
766
|
}
|
|
@@ -1502,7 +1504,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
1502
1504
|
rack.clearTimer = 0;
|
|
1503
1505
|
rack.row.classList.add('is-staged');
|
|
1504
1506
|
if (!rack.rig) {
|
|
1505
|
-
try { rack.rig = mascotLib.createMascot(rack.stage.face, { width: 72, height: 36, rangeX: 10, rangeY: 7,
|
|
1507
|
+
try { rack.rig = mascotLib.createMascot(rack.stage.face, { width: 72, height: 36, rangeX: 10, rangeY: 7, pose: 'idle' }); } catch { rack.rig = null; }
|
|
1506
1508
|
rack.pose = null;
|
|
1507
1509
|
rack.target = rack.rig ? stageTarget(rack) : null;
|
|
1508
1510
|
if (hero?.parked) dropHero(); // the stage is the character now: a hero still on its way out goes at once
|
|
@@ -1564,12 +1566,16 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
1564
1566
|
rack.bubble = { step: null, since: 0, key: '', open: false };
|
|
1565
1567
|
}
|
|
1566
1568
|
|
|
1567
|
-
/**
|
|
1569
|
+
/**
|
|
1570
|
+
* One rig of this transcript animates: the hero, else the newest stage, else
|
|
1571
|
+
* the "Thinking" row's. The rule ends at this renderer: every other panel
|
|
1572
|
+
* runs its own, so N live sessions show N moving characters.
|
|
1573
|
+
*/
|
|
1568
1574
|
function activateRigs() {
|
|
1569
1575
|
const newest = hero?.rig ? null : newestStage();
|
|
1570
|
-
for (const rack of racks) if (rack.rig) rack.rig.setActive?.(
|
|
1571
|
-
hero?.rig?.setActive?.(
|
|
1572
|
-
workingFace?.rig?.setActive?.(
|
|
1576
|
+
for (const rack of racks) if (rack.rig) rack.rig.setActive?.(rack === newest);
|
|
1577
|
+
hero?.rig?.setActive?.(true);
|
|
1578
|
+
workingFace?.rig?.setActive?.(!hero?.rig && !newest);
|
|
1573
1579
|
}
|
|
1574
1580
|
|
|
1575
1581
|
/** The bubble's call: the awake one, else the newest; it holds 900 ms (3 s for thinking) before the next wins. */
|
|
@@ -2634,7 +2640,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
2634
2640
|
return;
|
|
2635
2641
|
}
|
|
2636
2642
|
try {
|
|
2637
|
-
const rig = mascotLib.createMascot(host, { width: 56, height: 28,
|
|
2643
|
+
const rig = mascotLib.createMascot(host, { width: 56, height: 28, pose: 'think' });
|
|
2638
2644
|
const face = { still: false, rig, el: rig.el, held: false };
|
|
2639
2645
|
face.target = { kind: 'working', rig, el: rig.el, hold(on) { face.held = !!on; }, restore() { if (workingFace === face) rig.setPose('think'); } };
|
|
2640
2646
|
workingFace = face;
|
|
@@ -2761,6 +2767,115 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
2761
2767
|
if (line) { line.el.remove(); routeLines.delete(routeId); }
|
|
2762
2768
|
}
|
|
2763
2769
|
|
|
2770
|
+
// ── The automation trace ──
|
|
2771
|
+
// What the harness did for a turn (`synabun.automation`, asst-automation.js):
|
|
2772
|
+
// one disclosure row per turn, upserted by its traceId. It appears where the
|
|
2773
|
+
// turn was sent, moves under the reply when the turn ends and updates in
|
|
2774
|
+
// place when learning finishes. Drawn from the event alone, so the live row
|
|
2775
|
+
// and the replayed one are the same. Opening one keeps the next ones open.
|
|
2776
|
+
let autoUid = 0;
|
|
2777
|
+
const TRACE_OPEN_KEY = 'synabun-asst-trace-open';
|
|
2778
|
+
const traceOpenPref = () => { try { return localStorage.getItem(TRACE_OPEN_KEY) === '1'; } catch { return false; } };
|
|
2779
|
+
|
|
2780
|
+
function buildAutoRow() {
|
|
2781
|
+
const node = el('div', 'asst-route-line asst-auto');
|
|
2782
|
+
const detailId = `asst-auto-detail-${++autoUid}`;
|
|
2783
|
+
node.innerHTML = `
|
|
2784
|
+
<button type="button" class="asst-route-line-head asst-auto-head" aria-expanded="false" aria-controls="${detailId}">
|
|
2785
|
+
<span class="asst-route-glyph asst-icon" aria-hidden="true">${ICON_MEMORY}</span>
|
|
2786
|
+
<span class="asst-route-class asst-auto-title"></span>
|
|
2787
|
+
<span class="asst-route-meta asst-auto-summary"></span>
|
|
2788
|
+
<span class="asst-route-state asst-auto-state"></span>
|
|
2789
|
+
<span class="asst-route-chev" aria-hidden="true">›</span>
|
|
2790
|
+
</button>
|
|
2791
|
+
<div class="asst-route-detail asst-auto-detail" id="${detailId}" hidden></div>`;
|
|
2792
|
+
const head = node.querySelector('.asst-auto-head');
|
|
2793
|
+
const detail = node.querySelector('.asst-auto-detail');
|
|
2794
|
+
const setOpen = (open) => {
|
|
2795
|
+
head.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
2796
|
+
detail.hidden = !open;
|
|
2797
|
+
node.classList.toggle('open', open);
|
|
2798
|
+
};
|
|
2799
|
+
head.addEventListener('click', () => {
|
|
2800
|
+
const open = head.getAttribute('aria-expanded') !== 'true';
|
|
2801
|
+
setOpen(open);
|
|
2802
|
+
try { localStorage.setItem(TRACE_OPEN_KEY, open ? '1' : '0'); } catch { /* no storage: this row only */ }
|
|
2803
|
+
});
|
|
2804
|
+
setOpen(traceOpenPref());
|
|
2805
|
+
return { el: node, detail, atEnd: false };
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
function paintAutoRow(row, ev) {
|
|
2809
|
+
const view = automationView(ev, { t: hooks.t });
|
|
2810
|
+
row.el.dataset.traceId = view.traceId;
|
|
2811
|
+
row.el.dataset.phase = view.phase;
|
|
2812
|
+
row.el.classList.toggle('busy', view.tone === 'busy');
|
|
2813
|
+
row.el.classList.toggle('learned', view.tone === 'learned');
|
|
2814
|
+
row.el.querySelector('.asst-auto-title').textContent = view.title;
|
|
2815
|
+
row.el.querySelector('.asst-auto-summary').textContent = view.summary;
|
|
2816
|
+
const state = row.el.querySelector('.asst-auto-state');
|
|
2817
|
+
state.textContent = view.state;
|
|
2818
|
+
state.hidden = !view.state;
|
|
2819
|
+
row.detail.replaceChildren();
|
|
2820
|
+
for (const group of view.groups) {
|
|
2821
|
+
const box = el('div', 'asst-auto-group');
|
|
2822
|
+
box.dataset.group = group.key;
|
|
2823
|
+
box.appendChild(el('div', 'asst-auto-h', group.title));
|
|
2824
|
+
for (const item of group.rows) {
|
|
2825
|
+
const line = el('div', `asst-auto-row${item.tone ? ` ${item.tone}` : ''}`);
|
|
2826
|
+
if (item.label || item.meta) {
|
|
2827
|
+
const lead = el('div', 'asst-auto-row-head');
|
|
2828
|
+
if (item.label) lead.appendChild(el('span', 'asst-auto-tier', item.label));
|
|
2829
|
+
if (item.meta) lead.appendChild(el('span', 'asst-auto-meta', item.meta));
|
|
2830
|
+
line.appendChild(lead);
|
|
2831
|
+
}
|
|
2832
|
+
// Memory text and the user's own words: always as text, never as markup.
|
|
2833
|
+
if (item.text) line.appendChild(el(item.pre ? 'pre' : 'div', 'asst-auto-text', item.text));
|
|
2834
|
+
if (item.ids.length) {
|
|
2835
|
+
const ids = el('div', 'asst-auto-ids');
|
|
2836
|
+
for (const id of item.ids) {
|
|
2837
|
+
const link = el('button', 'asst-link', String(id).slice(0, 8));
|
|
2838
|
+
link.type = 'button';
|
|
2839
|
+
link.dataset.memoryId = id;
|
|
2840
|
+
link.title = `${t('assistant.automation.open', 'Open memory')} ${id}`;
|
|
2841
|
+
link.setAttribute('aria-label', link.title);
|
|
2842
|
+
link.addEventListener('click', () => hooks.onMemoryClick?.(id, { id }));
|
|
2843
|
+
ids.appendChild(link);
|
|
2844
|
+
}
|
|
2845
|
+
line.appendChild(ids);
|
|
2846
|
+
}
|
|
2847
|
+
box.appendChild(line);
|
|
2848
|
+
}
|
|
2849
|
+
row.detail.appendChild(box);
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
/** Create or update the trace row for `ev.traceId`. */
|
|
2854
|
+
function upsertAutomation(ev) {
|
|
2855
|
+
const id = String(ev?.traceId || '');
|
|
2856
|
+
if (!id) return null;
|
|
2857
|
+
let row = autoRows.get(id);
|
|
2858
|
+
const fresh = !row || !row.el.isConnected;
|
|
2859
|
+
if (fresh) {
|
|
2860
|
+
row = buildAutoRow();
|
|
2861
|
+
autoRows.set(id, row);
|
|
2862
|
+
while (autoRows.size > 200) autoRows.delete(autoRows.keys().next().value);
|
|
2863
|
+
}
|
|
2864
|
+
paintAutoRow(row, ev);
|
|
2865
|
+
// Under the reply once the turn has ended; a later snapshot (learning) never moves it again.
|
|
2866
|
+
const ended = ev.phase !== 'sent';
|
|
2867
|
+
if (fresh || (ended && !row.atEnd)) {
|
|
2868
|
+
// Placed like any row (before "Working…"), but a status line of the harness never dismisses the hero.
|
|
2869
|
+
if (working && working.parentNode === $msgs) $msgs.insertBefore(row.el, working);
|
|
2870
|
+
else $msgs.appendChild(row.el);
|
|
2871
|
+
if (ended) row.atEnd = true;
|
|
2872
|
+
prune();
|
|
2873
|
+
if (racks.size) syncRacks();
|
|
2874
|
+
scrollEnd();
|
|
2875
|
+
}
|
|
2876
|
+
return row.el;
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2764
2879
|
// ── Empty state ──
|
|
2765
2880
|
function showEmpty() {
|
|
2766
2881
|
if (emptyEl || $msgs.querySelector(':scope > :not(.asst-working)')) return;
|
|
@@ -2769,14 +2884,22 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
2769
2884
|
<div class="asst-empty-mascot" aria-hidden="true"></div>
|
|
2770
2885
|
<div class="asst-empty-title" role="heading" aria-level="2">${esc(t('assistant.empty.heading', 'What should we do?'))}</div>
|
|
2771
2886
|
<div class="asst-empty-body">${esc(t('assistant.empty.lead', 'I can use your Mac, look things up on the web, edit files and run commands, and remember or schedule things.'))}</div>
|
|
2887
|
+
<div class="asst-empty-greet"></div>
|
|
2888
|
+
<div class="asst-empty-project" hidden></div>
|
|
2772
2889
|
<div class="asst-suggestions" role="list"></div>`;
|
|
2773
2890
|
const box = emptyEl.querySelector('.asst-empty-mascot');
|
|
2774
2891
|
try {
|
|
2775
|
-
const rig = mascotLib.createMascot(box, { width: 120, height: 60
|
|
2892
|
+
const rig = mascotLib.createMascot(box, { width: 120, height: 60 });
|
|
2776
2893
|
hero = { rig, el: rig.el, box, parked: false, leaving: false, held: false, dock: null, egg: false, leaveTimer: 0 };
|
|
2777
2894
|
hero.target = heroTarget(hero);
|
|
2778
2895
|
wireEgg(hero);
|
|
2779
2896
|
} catch { hero = null; }
|
|
2897
|
+
// The project the conversation works in, under the lead: the host draws the picker (the brain
|
|
2898
|
+
// picker's project field), so it and the toolbar's Working project are one control.
|
|
2899
|
+
const projectSlot = emptyEl.querySelector('.asst-empty-project');
|
|
2900
|
+
let picker = null;
|
|
2901
|
+
try { picker = typeof hooks.mountEmptyProject === 'function' ? hooks.mountEmptyProject(projectSlot) : null; } catch { picker = null; }
|
|
2902
|
+
projectSlot.hidden = !picker;
|
|
2780
2903
|
renderSuggestions();
|
|
2781
2904
|
$msgs.appendChild(emptyEl);
|
|
2782
2905
|
// The host's "Starting…" character flies into place (not on replay or reduced motion).
|
|
@@ -2786,6 +2909,20 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
2786
2909
|
mascotChanged();
|
|
2787
2910
|
}
|
|
2788
2911
|
|
|
2912
|
+
/**
|
|
2913
|
+
* The greeting SynaBun prepared for this return (public/shared/greeting/) takes the lead's place.
|
|
2914
|
+
* The panel calls it once it knows the conversation is new: a restored one is never greeted.
|
|
2915
|
+
*/
|
|
2916
|
+
function offerGreeting() {
|
|
2917
|
+
const owner = emptyEl;
|
|
2918
|
+
if (!owner || owner.dataset.greetingAsked === '1' || typeof hooks.greeting !== 'function') return;
|
|
2919
|
+
owner.dataset.greetingAsked = '1';
|
|
2920
|
+
const slot = owner.querySelector('.asst-empty-greet');
|
|
2921
|
+
Promise.resolve().then(() => hooks.greeting(slot))
|
|
2922
|
+
.then((greeting) => { if (greeting && emptyEl === owner) owner.classList.add('has-greeting'); })
|
|
2923
|
+
.catch(() => { /* no greeting: the lead stays */ });
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2789
2926
|
function renderSuggestions() {
|
|
2790
2927
|
if (!emptyEl) return;
|
|
2791
2928
|
const host = emptyEl.querySelector('.asst-suggestions');
|
|
@@ -3111,6 +3248,9 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3111
3248
|
// The card itself arrives as a control_request; its outcome is a line (the panel's card shows it live).
|
|
3112
3249
|
if (ev.phase !== 'card') appendStatus(clarifyLine(ev), 'info');
|
|
3113
3250
|
return true;
|
|
3251
|
+
case 'synabun.automation':
|
|
3252
|
+
upsertAutomation(ev);
|
|
3253
|
+
return true;
|
|
3114
3254
|
default:
|
|
3115
3255
|
return false;
|
|
3116
3256
|
}
|
|
@@ -3233,6 +3373,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3233
3373
|
scopes.clear();
|
|
3234
3374
|
runCards.clear();
|
|
3235
3375
|
routeLines.clear();
|
|
3376
|
+
autoRows.clear();
|
|
3236
3377
|
turnFrames = [];
|
|
3237
3378
|
rootScope.stream = null;
|
|
3238
3379
|
rootScope.kept = null;
|
|
@@ -3249,6 +3390,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3249
3390
|
seen.clear();
|
|
3250
3391
|
snapshot = null;
|
|
3251
3392
|
waiting = null;
|
|
3393
|
+
closeEmptyMenu();
|
|
3252
3394
|
$msgs.innerHTML = '';
|
|
3253
3395
|
emptyEl = null;
|
|
3254
3396
|
followTail = true;
|
|
@@ -3273,6 +3415,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3273
3415
|
registerRouteLine,
|
|
3274
3416
|
removeRouteLine,
|
|
3275
3417
|
getRouteLine: (routeId) => routeLines.get(routeId) || null,
|
|
3418
|
+
upsertAutomation,
|
|
3276
3419
|
getRunCard: (runId) => runCards.get(runId) || null,
|
|
3277
3420
|
handleEvent,
|
|
3278
3421
|
/** The live gate for an event (false: already drawn); registers what it lets through. */
|
|
@@ -3289,6 +3432,7 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3289
3432
|
hideWorking,
|
|
3290
3433
|
isWorkingShown: () => !!working?.isConnected,
|
|
3291
3434
|
showEmpty,
|
|
3435
|
+
offerGreeting,
|
|
3292
3436
|
refreshEmpty: renderSuggestions,
|
|
3293
3437
|
isEmpty: () => !!emptyEl,
|
|
3294
3438
|
scrollEnd,
|
|
@@ -3296,7 +3440,6 @@ export function createRenderer(transcriptEl, hooks = {}) {
|
|
|
3296
3440
|
md,
|
|
3297
3441
|
/** The character on screen, for the panel's director: { kind, rig, el, hold(on), restore() } or null. */
|
|
3298
3442
|
mascot: visibleMascot,
|
|
3299
|
-
setRigsEnabled,
|
|
3300
3443
|
/** What this turn did: real calls (not the prompt-time recall), whether the last one failed, a turn error. */
|
|
3301
3444
|
turnStats: () => ({ calls: turn.calls, lastFailed: turn.last?.state === 'error', errored: turn.errored }),
|
|
3302
3445
|
/** The text of the turn's last message at the root ('' when it folded into a rack or there was none). */
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Assistant — Model routes editor: where its model lists come from
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
// The data side of the Routes editor (asst-route.js `openRoutesEditor`), kept
|
|
5
|
+
// apart from its markup. No DOM is built here.
|
|
6
|
+
//
|
|
7
|
+
// One list per provider, the one every Assistant model menu shows:
|
|
8
|
+
// loadModelCatalog() of asst-brain-picker.js, which is GET /api/assistant/catalog,
|
|
9
|
+
// itself built from the lists the Claude, Codex and OpenCode panels' own
|
|
10
|
+
// selectors read. Nothing here, and nothing in the editor, may keep a second
|
|
11
|
+
// list of models: a label, a tier, a price or an effort level is read from the
|
|
12
|
+
// catalog row each time it is drawn.
|
|
13
|
+
|
|
14
|
+
import { catalogModelRow, loadModelCatalog, modelCatalogStatus, onModelCatalogChange } from './asst-brain-picker.js';
|
|
15
|
+
import { routeTargetLabel } from './asst-state.js';
|
|
16
|
+
|
|
17
|
+
/** The catalog as the editor opens: a new build, never the copy another menu loaded a minute ago. */
|
|
18
|
+
export function loadRouteModels() {
|
|
19
|
+
return loadModelCatalog({ force: true });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Loading/partial state belongs to the same model source, without changing the catalog shape. */
|
|
23
|
+
export function routeModelsStatus() { return modelCatalogStatus(); }
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The name shown for a saved route's model. The catalog's label for that id wins:
|
|
27
|
+
* a route keeps the label it was saved with, and an alias moves ("haiku" was
|
|
28
|
+
* Haiku 4.5, then Haiku 5.5). A model the catalog no longer lists (removed by its
|
|
29
|
+
* provider, hidden, or its provider is not answering) keeps the saved label,
|
|
30
|
+
* then its id, then the provider's name: never an empty name.
|
|
31
|
+
*/
|
|
32
|
+
export function routeModelLabel(pref, catalog) {
|
|
33
|
+
if (!pref || typeof pref !== 'object') return '';
|
|
34
|
+
const row = pref.provider && pref.model ? catalogModelRow(pref.provider, pref.model, catalog) : null;
|
|
35
|
+
const live = row?.label ? String(row.label).trim() : '';
|
|
36
|
+
return live || routeTargetLabel(pref);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** What the editor draws from a catalog: when this is unchanged, there is nothing to redraw. */
|
|
40
|
+
export function catalogSignature(catalog) {
|
|
41
|
+
if (!catalog || typeof catalog !== 'object') return '';
|
|
42
|
+
return JSON.stringify(Object.keys(catalog).sort().map(provider => [
|
|
43
|
+
provider,
|
|
44
|
+
(Array.isArray(catalog[provider]) ? catalog[provider] : []).map(m => [
|
|
45
|
+
m?.id, m?.label, m?.status ?? null, m?.vision ?? null, m?.outputs?.image ?? null, m?.outputs?.video ?? null,
|
|
46
|
+
(m?.efforts || []).join(','), m?.defaultEffort || '', m?.isDefault === true,
|
|
47
|
+
]),
|
|
48
|
+
]));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Keeps an open editor on the current lists. `apply(catalog)` is called with a
|
|
53
|
+
* newly loaded catalog whenever it differs from the last one applied:
|
|
54
|
+
* - after a change event (a model hidden or shown, a provider listing other
|
|
55
|
+
* models, an OpenCode provider connected or removed): a new build is asked;
|
|
56
|
+
* - when the window is shown again: the catalog is read again, and reloaded
|
|
57
|
+
* once its copy has aged out (no event tells a window that slept).
|
|
58
|
+
* Returns { seed(catalog), stop() }: seed with the catalog the editor loaded
|
|
59
|
+
* itself, stop when it closes. No timer runs while nothing changes.
|
|
60
|
+
*/
|
|
61
|
+
export function watchRouteModels(apply, {
|
|
62
|
+
load = loadModelCatalog,
|
|
63
|
+
subscribe = onModelCatalogChange,
|
|
64
|
+
doc = typeof document !== 'undefined' ? document : null,
|
|
65
|
+
delayMs = 150,
|
|
66
|
+
setTimer = setTimeout,
|
|
67
|
+
clearTimer = clearTimeout,
|
|
68
|
+
} = {}) {
|
|
69
|
+
let stopped = false;
|
|
70
|
+
let timer = null;
|
|
71
|
+
let last = null;
|
|
72
|
+
let run = 0;
|
|
73
|
+
|
|
74
|
+
async function reload(force) {
|
|
75
|
+
const mine = ++run;
|
|
76
|
+
let catalog = null;
|
|
77
|
+
try { catalog = await load({ force }); } catch { return; }
|
|
78
|
+
if (stopped || mine !== run || !catalog) return;
|
|
79
|
+
const signature = catalogSignature(catalog);
|
|
80
|
+
if (signature === last) return;
|
|
81
|
+
last = signature;
|
|
82
|
+
try { apply(catalog); } catch { /* the editor's own failure */ }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Several events for one change (a hide broadcasts twice) become one reload.
|
|
86
|
+
let pendingForce = false;
|
|
87
|
+
function schedule(force) {
|
|
88
|
+
if (stopped) return;
|
|
89
|
+
pendingForce = pendingForce || force;
|
|
90
|
+
if (timer != null) clearTimer(timer);
|
|
91
|
+
timer = setTimer(() => { timer = null; const f = pendingForce; pendingForce = false; reload(f); }, delayMs);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const unsubscribe = subscribe(() => schedule(true));
|
|
95
|
+
const onVisible = () => { if (doc?.visibilityState !== 'hidden') schedule(false); };
|
|
96
|
+
doc?.addEventListener?.('visibilitychange', onVisible);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
seed(catalog) { last = catalogSignature(catalog); },
|
|
100
|
+
stop() {
|
|
101
|
+
stopped = true;
|
|
102
|
+
if (timer != null) clearTimer(timer);
|
|
103
|
+
timer = null;
|
|
104
|
+
try { unsubscribe?.(); } catch { /* ignore */ }
|
|
105
|
+
doc?.removeEventListener?.('visibilitychange', onVisible);
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|