synabun 2.0.0-beta → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/NOTICE +5 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +51 -0
- package/benchmarks/fixtures/browser/README.md +1 -1
- package/benchmarks/fixtures/desktop/README.md +1 -1
- package/docs/whatsapp.md +2 -2
- package/hooks/claude-code/pre-compact.mjs +11 -0
- package/hooks/claude-code/prompt-submit.mjs +60 -184
- package/hooks/claude-code/session-start.mjs +73 -16
- package/hooks/claude-code/shared.mjs +20 -0
- package/hooks/claude-code/stop.mjs +5 -5
- package/launcher.mjs +40 -0
- package/lib/claude-hooks.js +61 -8
- package/lib/client-config-repair.js +4 -3
- package/lib/data-home-migration.js +4 -0
- package/lib/desktop-pwa.js +206 -0
- package/lib/external-tools.js +221 -0
- package/lib/first-launch-protection.js +5 -0
- package/lib/packaged-runtime.js +110 -0
- package/lib/start-launcher.js +1396 -0
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/neural-interface/i18n/en.json +1540 -154
- package/neural-interface/i18n/pt-BR.json +1538 -153
- package/neural-interface/lib/assistant-api.js +62 -6
- package/neural-interface/lib/assistant-brains/claude.js +4 -0
- package/neural-interface/lib/assistant-catalog.js +179 -27
- package/neural-interface/lib/assistant-config.js +31 -2
- package/neural-interface/lib/assistant-dispatch.js +62 -13
- package/neural-interface/lib/assistant-envelope.js +9 -6
- package/neural-interface/lib/assistant-hidden-models.js +393 -66
- package/neural-interface/lib/assistant-memory.js +24 -10
- package/neural-interface/lib/assistant-persona.js +6 -2
- package/neural-interface/lib/assistant-pricing.js +21 -6
- package/neural-interface/lib/assistant-runtime.js +181 -12
- package/neural-interface/lib/assistant-task-prompt.js +13 -3
- package/neural-interface/lib/assistant-test-density.js +142 -0
- package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
- package/neural-interface/lib/assistant-user-context.js +908 -0
- package/neural-interface/lib/assistant-user-knowledge.js +328 -0
- package/neural-interface/lib/assistant-user-learn.js +404 -0
- package/neural-interface/lib/assistant-user-threads.js +226 -0
- package/neural-interface/lib/assistant-user-writer.js +181 -0
- package/neural-interface/lib/augmented-path.js +23 -3
- package/neural-interface/lib/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-language.js +83 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-agent-bridge.js +87 -153
- package/neural-interface/lib/claude-executable.js +241 -0
- package/neural-interface/lib/claude-model-catalog.js +82 -93
- package/neural-interface/lib/claude-temporary.js +46 -7
- package/neural-interface/lib/cloudflared/install.js +533 -0
- package/neural-interface/lib/cloudflared/manager.js +545 -0
- package/neural-interface/lib/cloudflared/pins.js +115 -0
- package/neural-interface/lib/cloudflared/pins.json +63 -0
- package/neural-interface/lib/cloudflared/tunnel.js +265 -0
- package/neural-interface/lib/editor-completion-endpoint.js +264 -0
- package/neural-interface/lib/editor-completion-opencode.js +436 -0
- package/neural-interface/lib/editor-completion.js +714 -0
- package/neural-interface/lib/editor-config.js +149 -0
- package/neural-interface/lib/editor-files-api.js +268 -0
- package/neural-interface/lib/editor-git-api.js +134 -0
- package/neural-interface/lib/file-explorer-api.js +1039 -0
- package/neural-interface/lib/file-explorer-system.js +355 -0
- package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
- package/neural-interface/lib/file-explorer-watch.js +239 -0
- package/neural-interface/lib/git-diff-api.js +103 -0
- package/neural-interface/lib/git-read.js +202 -0
- package/neural-interface/lib/greeting/api.js +89 -0
- package/neural-interface/lib/greeting/budgets.js +90 -0
- package/neural-interface/lib/greeting/engine.js +461 -0
- package/neural-interface/lib/greeting/facts.js +320 -0
- package/neural-interface/lib/greeting/sources.js +252 -0
- package/neural-interface/lib/greeting/writer.js +139 -0
- package/neural-interface/lib/http-guards.js +189 -13
- package/neural-interface/lib/machine-names.js +88 -0
- package/neural-interface/lib/memory-api.js +31 -7
- package/neural-interface/lib/native-binary-runtime.js +69 -337
- package/neural-interface/lib/native-loop-providers.js +40 -49
- package/neural-interface/lib/offline-page.js +54 -0
- package/neural-interface/lib/plugin-installer.js +4 -2
- package/neural-interface/lib/project-storage.js +5 -7
- package/neural-interface/lib/request-gate.js +589 -0
- package/neural-interface/lib/session-title-generator.js +5 -0
- package/neural-interface/lib/synabun-update-plan.js +19 -0
- package/neural-interface/lib/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/package-lock.json +701 -253
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/install-app.html +34 -0
- package/neural-interface/public/manifest.json +2 -0
- package/neural-interface/public/offline.html +402 -66
- package/neural-interface/public/onboarding.html +264 -147
- package/neural-interface/public/shared/agent-runtime-options.js +22 -6
- package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +312 -62
- package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
- package/neural-interface/public/shared/assistant/asst-mascot.js +26 -64
- package/neural-interface/public/shared/assistant/asst-menu.js +12 -8
- package/neural-interface/public/shared/assistant/asst-panel.js +150 -28
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +0 -3
- package/neural-interface/public/shared/assistant/asst-render.js +219 -67
- package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
- package/neural-interface/public/shared/assistant/asst-route.js +23 -329
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +495 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
- package/neural-interface/public/shared/assistant/asst-state.js +185 -1
- package/neural-interface/public/shared/assistant/asst-styles.js +162 -6
- package/neural-interface/public/shared/blob-store.js +111 -22
- package/neural-interface/public/shared/cdx/cdx-panel.js +32 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
- package/neural-interface/public/shared/cdx/cdx-styles.js +36 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +87 -4
- package/neural-interface/public/shared/command-runner-model.js +30 -0
- package/neural-interface/public/shared/constants.js +6 -1
- package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +15 -0
- package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
- package/neural-interface/public/shared/editor/editor-ai.js +619 -0
- package/neural-interface/public/shared/editor/editor-commands.js +212 -0
- package/neural-interface/public/shared/editor/editor-compare.js +103 -0
- package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
- package/neural-interface/public/shared/editor/editor-doc.js +257 -0
- package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
- package/neural-interface/public/shared/editor/editor-git.js +95 -0
- package/neural-interface/public/shared/editor/editor-languages.js +156 -0
- package/neural-interface/public/shared/editor/editor-lint.js +229 -0
- package/neural-interface/public/shared/editor/editor-loader.js +51 -0
- package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
- package/neural-interface/public/shared/editor/editor-menu.js +233 -0
- package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
- package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
- package/neural-interface/public/shared/editor/editor-palette.js +125 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
- package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
- package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
- package/neural-interface/public/shared/editor/editor-safety.js +500 -0
- package/neural-interface/public/shared/editor/editor-search.js +352 -0
- package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
- package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
- package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
- package/neural-interface/public/shared/editor/editor-theme.js +244 -0
- package/neural-interface/public/shared/editor/editor-view.js +332 -0
- package/neural-interface/public/shared/explorer/fx-api.js +216 -0
- package/neural-interface/public/shared/explorer/fx-links.js +204 -0
- package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
- package/neural-interface/public/shared/explorer/fx-main.js +865 -0
- package/neural-interface/public/shared/explorer/fx-names.js +87 -0
- package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
- package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
- package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
- package/neural-interface/public/shared/file-links.js +339 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
- package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
- package/neural-interface/public/shared/html-shell.js +169 -170
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +99 -17
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +5 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +40 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
- package/neural-interface/public/shared/pwa-install-page.js +62 -0
- package/neural-interface/public/shared/pwa-install.css +12 -0
- package/neural-interface/public/shared/pwa-install.js +127 -0
- package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
- package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
- package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
- package/neural-interface/public/shared/settings/settings-ia.js +18 -4
- package/neural-interface/public/shared/settings/settings-rules.js +160 -0
- package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
- package/neural-interface/public/shared/start-bridge.js +802 -0
- package/neural-interface/public/shared/styleguide/sg-colors.js +5 -2
- package/neural-interface/public/shared/styleguide/sg-import-export.js +4 -3
- package/neural-interface/public/shared/styleguide/sg-kit.js +4 -1
- package/neural-interface/public/shared/styleguide/sg-panel.js +9 -1
- package/neural-interface/public/shared/styleguide/sg-typography.js +1 -0
- package/neural-interface/public/shared/styles.css +2219 -1117
- package/neural-interface/public/shared/synabun-mascot.js +20 -56
- package/neural-interface/public/shared/term-ready.js +307 -0
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +160 -19
- package/neural-interface/public/shared/ui-command-runner.js +251 -468
- package/neural-interface/public/shared/ui-detail.js +15 -0
- package/neural-interface/public/shared/ui-explorer.js +22 -0
- package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
- package/neural-interface/public/shared/ui-file-links.js +103 -0
- package/neural-interface/public/shared/ui-help.js +26 -0
- package/neural-interface/public/shared/ui-invite.js +126 -116
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +367 -12
- package/neural-interface/public/shared/ui-menubar.js +21 -55
- package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
- package/neural-interface/public/shared/ui-navbar.js +45 -21
- package/neural-interface/public/shared/ui-settings.js +491 -547
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
- package/neural-interface/public/shared/ui-sync.js +16 -0
- package/neural-interface/public/shared/ui-terminal.js +153 -149
- package/neural-interface/public/shared/ui-tunnel.js +130 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
- package/neural-interface/public/shared/ui-whiteboard.js +12 -0
- package/neural-interface/public/shared/ui-worker-end.js +245 -0
- package/neural-interface/public/shared/ui-workspaces.js +41 -27
- package/neural-interface/public/shared/worker-end.js +251 -0
- package/neural-interface/public/sw.js +3 -1
- package/neural-interface/public/variant/2d/main.js +2 -1
- package/neural-interface/public/variant/3d/main.js +2 -1
- package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
- package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
- package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
- package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
- package/neural-interface/scripts/build-vendor.mjs +78 -2
- package/neural-interface/scripts/rebuild-pty.js +15 -12
- package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
- package/neural-interface/server.js +1092 -1212
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +13 -7
- package/postinstall.js +11 -81
- package/setup.js +111 -6
- package/benchmarks/browser-live-results.json +0 -79
- package/benchmarks/browser-v2-results.json +0 -258
- package/docs/browser-v2.md +0 -109
- package/docs/hook-integrity.md +0 -89
- package/docs/judgments.md +0 -182
- package/docs/style-guide.md +0 -246
- package/neural-interface/lib/codex-capabilities.d.ts +0 -41
- package/neural-interface/public/category-logos/claude.svg +0 -1
- package/neural-interface/public/category-logos/gemini-color.svg +0 -1
- package/neural-interface/public/category-logos/openai.svg +0 -1
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude.svg +0 -1
- package/neural-interface/public/gallery.svg +0 -6
- package/neural-interface/public/leonardoai.svg +0 -1
- package/neural-interface/public/mcp.svg +0 -4
- package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
- package/neural-interface/public/pin-svgrepo-com.svg +0 -25
- package/neural-interface/public/sessionicon.svg +0 -8
- package/neural-interface/public/toolbar-album.svg +0 -8
- package/neural-interface/public/toolbar-question.svg +0 -6
- package/neural-interface/public/toolbar-sessions.svg +0 -6
- package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
- package/scripts/audit-claude-hook-usage.mjs +0 -12
- package/scripts/audit-memory-duplicates.mjs +0 -44
- package/scripts/measure-claude-hook-overhead.mjs +0 -77
- package/scripts/recover-user-config.mjs +0 -254
- package/skills/synabun/synabunicon.png +0 -0
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
// open. `synabun.route` events (phase card|auto|decided|pending|expired|
|
|
17
17
|
// declined|cancelled) update the line in place by routeId.
|
|
18
18
|
|
|
19
|
-
import { clampEffortId, getEffortLevelsForModel, modelEffortIds } from '../agent-runtime-options.js';
|
|
20
19
|
import { getProviderMeta } from '../provider-icons.js';
|
|
21
|
-
import { fetchManageCatalog,
|
|
22
|
-
import { catalogModelRow, fmtModelPrice, hiddenModelFor, ICON_CARET, invalidateModelCatalog,
|
|
20
|
+
import { fetchManageCatalog, patchHiddenModels } from './asst-api.js';
|
|
21
|
+
import { catalogModelRow, fmtModelPrice, hiddenModelFor, ICON_CARET, invalidateModelCatalog, openModelMenu } from './asst-brain-picker.js';
|
|
22
|
+
// The Routes editor's model lists (where they come from, how they stay current): asst-route-models.js.
|
|
23
23
|
import { closeMenu, isMenuOpen, openMenu } from './asst-menu.js';
|
|
24
24
|
import { decorateControlHead } from './asst-control.js';
|
|
25
25
|
import {
|
|
@@ -63,13 +63,12 @@ export function routeModeLabel(mode, t) {
|
|
|
63
63
|
return tr('assistant.routes.mode.unsure', 'Ask when unsure');
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function routeModeDescription(mode, model, t) {
|
|
66
|
+
export function routeModeDescription(mode, model, t, askBelow = 0.75) {
|
|
67
67
|
const tr = tf(t);
|
|
68
|
-
const who = str(model) || tr('assistant.routes.theBrain', 'The assistant');
|
|
69
68
|
const m = normalizeRouteMode(mode, DEFAULT_ROUTE_MODE);
|
|
70
|
-
if (m === 'always-ask') return tr('assistant.routes.mode.alwaysDesc', '
|
|
71
|
-
if (m === 'never') return tr('assistant.routes.mode.neverDesc', '
|
|
72
|
-
return tr('assistant.routes.mode.unsureDesc', '{
|
|
69
|
+
if (m === 'always-ask') return tr('assistant.routes.mode.alwaysDesc', 'Confirm every actionable task.');
|
|
70
|
+
if (m === 'never') return tr('assistant.routes.mode.neverDesc', 'Run saved routes immediately; otherwise the assistant chooses.');
|
|
71
|
+
return tr('assistant.routes.mode.unsureDesc', 'Confirm below {pct}% confidence or when a model cannot run the task.', { pct: Math.round(askBelow * 100) });
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
// ── Pure model ──────────────────────────────────────────────────────────────
|
|
@@ -208,7 +207,7 @@ function badgeText(o, n, tr) {
|
|
|
208
207
|
const pct = fmtConfidence(n?.confidence);
|
|
209
208
|
switch (o.badge) {
|
|
210
209
|
case 'suggested': return pct ? tr('assistant.routes.badge.suggestedPct', 'Suggested · {pct}', { pct }) : tr('assistant.routes.badge.suggested', 'Suggested');
|
|
211
|
-
case 'remembered': return tr('assistant.routes.badge.remembered', '
|
|
210
|
+
case 'remembered': return tr('assistant.routes.badge.remembered', 'Your choice');
|
|
212
211
|
case 'current': return tr('assistant.routes.badge.current', 'Current');
|
|
213
212
|
case 'capable':
|
|
214
213
|
if (!n?.requires && n?.visionOnly) return tr('assistant.routes.badge.canSee', 'Can see');
|
|
@@ -344,6 +343,13 @@ export function designRouteSight(pref, catalog) {
|
|
|
344
343
|
return row.status === 'unavailable' ? 'unavailable' : 'ok';
|
|
345
344
|
}
|
|
346
345
|
|
|
346
|
+
/** Saved ids may resolve through a listed alias; all metadata still comes from this catalog. */
|
|
347
|
+
export function routeCatalogRow(pref, catalog) {
|
|
348
|
+
if (!pref?.provider || !catalog) return null;
|
|
349
|
+
const rows = Array.isArray(catalog[pref.provider]) ? catalog[pref.provider] : [];
|
|
350
|
+
return pref.model ? catalogModelRow(pref.provider, pref.model, catalog) || aliasRow(pref.provider, pref.model, rows) : rows.find(m => m.isDefault) || null;
|
|
351
|
+
}
|
|
352
|
+
|
|
347
353
|
/** Text parts of a route line (pure). */
|
|
348
354
|
export function routeLineParts(route, phase = 'decided', { brainLabel = '', t = null } = {}) {
|
|
349
355
|
const tr = tf(t);
|
|
@@ -366,9 +372,9 @@ export function routeLineParts(route, phase = 'decided', { brainLabel = '', t =
|
|
|
366
372
|
switch (str(r.decidedBy)) {
|
|
367
373
|
case 'brain': decided = tr('assistant.routes.decidedBy', 'decided by {model}', { model: brainLabel || tr('assistant.routes.theBrainLower', 'the assistant') }); break;
|
|
368
374
|
case 'user': decided = tr('assistant.routes.youChose', 'you chose'); break;
|
|
369
|
-
case 'remembered': decided = tr('assistant.routes.remembered', '
|
|
375
|
+
case 'remembered': decided = tr('assistant.routes.remembered', 'your saved choice'); break;
|
|
370
376
|
case 'timeout': decided = tr('assistant.routes.timeout', 'default after timeout'); break;
|
|
371
|
-
default: decided = r.remembered ? tr('assistant.routes.remembered', '
|
|
377
|
+
default: decided = r.remembered ? tr('assistant.routes.remembered', 'your saved choice') : '';
|
|
372
378
|
}
|
|
373
379
|
const meta = [];
|
|
374
380
|
if (effort && effort !== 'off') meta.push(effort);
|
|
@@ -598,7 +604,7 @@ export function createRouteModeControl(hostEl, hooks = {}) {
|
|
|
598
604
|
kind: 'radio',
|
|
599
605
|
id,
|
|
600
606
|
label: routeModeLabel(id, hooks.t),
|
|
601
|
-
desc: routeModeDescription(id, model, hooks.t),
|
|
607
|
+
desc: routeModeDescription(id, model, hooks.t, hooks.getMode?.()?.askBelow ?? 0.75),
|
|
602
608
|
selected: id === mode,
|
|
603
609
|
onSelect: () => { if (id !== mode) hooks.onChange?.(id); },
|
|
604
610
|
})),
|
|
@@ -779,7 +785,7 @@ export function renderRouteCard(container, input, hooks = {}) {
|
|
|
779
785
|
state.other = {
|
|
780
786
|
id: 'other', kind, provider: target.provider, model: target.model, effort: null,
|
|
781
787
|
label: target.label || '', badge: null, number: options.length + 1, here: false,
|
|
782
|
-
title: target.label || target.model, badgeText: tr('assistant.routes.badge.other', 'Your
|
|
788
|
+
title: target.label || target.model, badgeText: tr('assistant.routes.badge.other', 'Your choice'),
|
|
783
789
|
vision: target.vision === true, price: target.price || null, reason: '', warning: null, disabled: false,
|
|
784
790
|
};
|
|
785
791
|
state.selectedId = 'other';
|
|
@@ -798,7 +804,7 @@ export function renderRouteCard(container, input, hooks = {}) {
|
|
|
798
804
|
rememberInput.type = 'checkbox';
|
|
799
805
|
rememberInput.addEventListener('change', () => { state.remember = rememberInput.checked; });
|
|
800
806
|
// `remember.label` is the task-class label ("Code"), not a sentence.
|
|
801
|
-
const text = tr('assistant.routes.rememberFor', '
|
|
807
|
+
const text = tr('assistant.routes.rememberFor', 'Use this choice for {taskClass} tasks', { taskClass: (n.remember.label || n.taskClassLabel).toLowerCase() });
|
|
802
808
|
label.append(rememberInput, el('span', null, text));
|
|
803
809
|
if (n.remember.current) label.appendChild(el('span', 'asst-route-remember-current', tr('assistant.routes.rememberCurrent', 'now: {current}', { current: n.remember.current })));
|
|
804
810
|
card.appendChild(label);
|
|
@@ -1005,321 +1011,9 @@ export function renderRouteCard(container, input, hooks = {}) {
|
|
|
1005
1011
|
return entry;
|
|
1006
1012
|
}
|
|
1007
1013
|
|
|
1008
|
-
// ── Routes editor (
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
/**
|
|
1013
|
-
* "Model routes…" editor. hooks: { t, providerIcon, getBrain() → brain, onSaved(routing), onClose() }
|
|
1014
|
-
* Returns { el, close } (async: resolves after the first load).
|
|
1015
|
-
*/
|
|
1016
|
-
export async function openRoutesEditor(hooks = {}) {
|
|
1017
|
-
if (_editor) { _editor.close(); }
|
|
1018
|
-
const tr = tf(hooks.t);
|
|
1019
|
-
const overlay = el('div', 'asst-modal-overlay');
|
|
1020
|
-
overlay.setAttribute('role', 'dialog');
|
|
1021
|
-
overlay.setAttribute('aria-modal', 'true');
|
|
1022
|
-
overlay.setAttribute('aria-label', tr('assistant.routes.editorTitle', 'Model routes'));
|
|
1023
|
-
const modal = el('div', 'asst-modal asst-routes-modal');
|
|
1024
|
-
modal.innerHTML = `
|
|
1025
|
-
<div class="asst-modal-head"><span class="asst-icon" aria-hidden="true">${ICON_ROUTE}</span><span>${esc(tr('assistant.routes.editorTitle', 'Model routes'))}</span><button type="button" class="asst-iconbtn asst-modal-close" aria-label="${esc(tr('common.close', 'Close'))}">${ICON_X}</button></div>
|
|
1026
|
-
<div class="asst-modal-body"><div class="asst-modal-note">${esc(tr('common.loading', 'Loading...'))}</div></div>
|
|
1027
|
-
<div class="asst-modal-foot">
|
|
1028
|
-
<button type="button" class="asst-btn asst-btn-secondary asst-routes-reset-all">${esc(tr('assistant.routes.resetAll', 'Reset all'))}</button>
|
|
1029
|
-
<span class="asst-modal-spacer"></span>
|
|
1030
|
-
<button type="button" class="asst-btn asst-btn-secondary asst-routes-cancel">${esc(tr('common.cancel', 'Cancel'))}</button>
|
|
1031
|
-
<button type="button" class="asst-btn asst-btn-primary asst-routes-save">${esc(tr('common.save', 'Save'))}</button>
|
|
1032
|
-
</div>`;
|
|
1033
|
-
overlay.appendChild(modal);
|
|
1034
|
-
const body = modal.querySelector('.asst-modal-body');
|
|
1035
|
-
const saveBtn = modal.querySelector('.asst-routes-save');
|
|
1036
|
-
const resetAllBtn = modal.querySelector('.asst-routes-reset-all');
|
|
1037
|
-
const returnTo = document.activeElement;
|
|
1038
|
-
|
|
1039
|
-
const state = { data: null, catalog: null, version: null, defaultMode: DEFAULT_ROUTE_MODE, prefs: {}, patch: {}, error: '', conflict: false, saving: false };
|
|
1040
|
-
|
|
1041
|
-
function close() {
|
|
1042
|
-
if (!overlay.isConnected) return;
|
|
1043
|
-
closeMenu();
|
|
1044
|
-
document.removeEventListener('keydown', onKey, true);
|
|
1045
|
-
overlay.remove();
|
|
1046
|
-
_editor = null;
|
|
1047
|
-
try { hooks.onClose?.(); } catch { /* ignore */ }
|
|
1048
|
-
if (returnTo?.isConnected) { try { returnTo.focus({ preventScroll: true }); } catch { /* ignore */ } }
|
|
1049
|
-
}
|
|
1050
|
-
function onKey(e) {
|
|
1051
|
-
if (e.key === 'Escape') {
|
|
1052
|
-
if (isMenuOpen()) return; // the menu closes itself first
|
|
1053
|
-
e.preventDefault(); e.stopPropagation(); close();
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
|
-
e.stopPropagation();
|
|
1057
|
-
}
|
|
1058
|
-
document.addEventListener('keydown', onKey, true);
|
|
1059
|
-
overlay.addEventListener('mousedown', (e) => { if (e.target === overlay) close(); });
|
|
1060
|
-
modal.querySelector('.asst-modal-close').addEventListener('click', close);
|
|
1061
|
-
modal.querySelector('.asst-routes-cancel').addEventListener('click', close);
|
|
1062
|
-
document.body.appendChild(overlay);
|
|
1063
|
-
_editor = { close };
|
|
1064
|
-
|
|
1065
|
-
function effectivePref(key) {
|
|
1066
|
-
return Object.prototype.hasOwnProperty.call(state.patch, key) ? state.patch[key] : (state.prefs[key] || null);
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
function sourceOf(key) {
|
|
1070
|
-
if (Object.prototype.hasOwnProperty.call(state.patch, key)) return state.patch[key] ? 'yours' : 'default';
|
|
1071
|
-
const pref = state.prefs[key];
|
|
1072
|
-
if (!pref) return 'default';
|
|
1073
|
-
return pref.by === 'user' ? 'yours' : 'remembered';
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
function sourceLabel(source) {
|
|
1077
|
-
if (source === 'disabled') return tr('assistant.routes.source.disabled', 'disabled');
|
|
1078
|
-
if (source === 'incapable') return tr('assistant.routes.source.incapable', 'incapable');
|
|
1079
|
-
if (source === 'yours') return tr('assistant.routes.source.yours', 'yours');
|
|
1080
|
-
if (source === 'remembered') return tr('assistant.routes.source.remembered', 'remembered');
|
|
1081
|
-
return tr('assistant.routes.source.default', 'default');
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
/** Does the route's model generate `medium`? true | false | null (the catalog cannot tell). */
|
|
1085
|
-
function routeMakes(pref, medium) {
|
|
1086
|
-
if (!medium || !pref?.provider || !state.catalog) return null;
|
|
1087
|
-
const rows = Array.isArray(state.catalog[pref.provider]) ? state.catalog[pref.provider] : [];
|
|
1088
|
-
const row = pref.model ? catalogModelRow(pref.provider, pref.model, state.catalog) : rows.find(m => m.isDefault) || null;
|
|
1089
|
-
if (!row?.outputs || typeof row.outputs !== 'object') return null;
|
|
1090
|
-
return row.outputs[medium] === true;
|
|
1091
|
-
}
|
|
1092
|
-
/** No model in the loaded catalog makes `medium` (false while the catalog has no output data). */
|
|
1093
|
-
function noMaker(medium) {
|
|
1094
|
-
const rows = Object.values(state.catalog || {}).flatMap(list => (Array.isArray(list) ? list : []));
|
|
1095
|
-
return rows.some(m => m?.outputs && typeof m.outputs === 'object') && !rows.some(m => m?.outputs?.[medium] === true);
|
|
1096
|
-
}
|
|
1097
|
-
/** No model in the loaded catalog can see (false while no catalog is loaded). */
|
|
1098
|
-
function noSeer() {
|
|
1099
|
-
const rows = Object.values(state.catalog || {}).flatMap(list => (Array.isArray(list) ? list : []));
|
|
1100
|
-
return rows.length > 0 && !rows.some(m => m?.vision === true);
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
function taskRows() {
|
|
1104
|
-
const classes = Array.isArray(state.data?.taskClasses) ? state.data.taskClasses.filter(c => c?.id) : [];
|
|
1105
|
-
const rows = classes.map(c => ({
|
|
1106
|
-
id: String(c.id), label: str(c.label) || humanizeClass(c.id), description: str(c.description), defaultKind: str(c.defaultKind) || 'direct',
|
|
1107
|
-
// Image / video creation: only models that generate the medium, always on a worker; design: only models that can see.
|
|
1108
|
-
requires: c.requires === 'image' || c.requires === 'video' ? c.requires : null, dispatchOnly: c.dispatchOnly === true, visionOnly: c.vision === true,
|
|
1109
|
-
}));
|
|
1110
|
-
if (!rows.some(r => r.id === 'vision')) rows.push({ id: 'vision', label: tr('assistant.routes.visionRow', 'Screenshots & images'), description: tr('assistant.routes.visionDesc', 'Used when a task needs a model that can see.'), defaultKind: 'direct' });
|
|
1111
|
-
return rows;
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
function render() {
|
|
1115
|
-
body.innerHTML = '';
|
|
1116
|
-
if (state.error) {
|
|
1117
|
-
const banner = el('div', 'asst-routes-error');
|
|
1118
|
-
banner.setAttribute('role', 'alert');
|
|
1119
|
-
banner.appendChild(el('span', null, state.error));
|
|
1120
|
-
if (state.conflict) {
|
|
1121
|
-
const reload = el('button', 'asst-btn asst-btn-secondary', tr('assistant.routes.reload', 'Reload'));
|
|
1122
|
-
reload.type = 'button';
|
|
1123
|
-
reload.addEventListener('click', () => load());
|
|
1124
|
-
banner.appendChild(reload);
|
|
1125
|
-
}
|
|
1126
|
-
body.appendChild(banner);
|
|
1127
|
-
}
|
|
1128
|
-
if (!state.data) return;
|
|
1129
|
-
|
|
1130
|
-
// When to ask (default route mode)
|
|
1131
|
-
const modeSection = el('section', 'asst-routes-section');
|
|
1132
|
-
modeSection.appendChild(el('div', 'asst-routes-section-title', tr('assistant.routes.whenToAsk', 'When to ask')));
|
|
1133
|
-
const modes = el('div', 'asst-routes-modes');
|
|
1134
|
-
modes.setAttribute('role', 'radiogroup');
|
|
1135
|
-
modes.setAttribute('aria-label', tr('assistant.routes.whenToAsk', 'When to ask'));
|
|
1136
|
-
const brainName = hooks.brainName?.() || '';
|
|
1137
|
-
for (const id of ROUTE_MODES) {
|
|
1138
|
-
const b = el('button', 'asst-routes-mode');
|
|
1139
|
-
b.type = 'button';
|
|
1140
|
-
b.setAttribute('role', 'radio');
|
|
1141
|
-
b.setAttribute('aria-checked', state.defaultMode === id ? 'true' : 'false');
|
|
1142
|
-
b.dataset.mode = id;
|
|
1143
|
-
b.innerHTML = `<span class="asst-routes-mode-label">${esc(routeModeLabel(id, hooks.t))}</span><span class="asst-routes-mode-desc">${esc(routeModeDescription(id, brainName, hooks.t))}</span>`;
|
|
1144
|
-
b.addEventListener('click', () => { state.defaultMode = id; render(); modal.querySelector(`.asst-routes-mode[data-mode="${id}"]`)?.focus(); });
|
|
1145
|
-
modes.appendChild(b);
|
|
1146
|
-
}
|
|
1147
|
-
modeSection.appendChild(modes);
|
|
1148
|
-
body.appendChild(modeSection);
|
|
1149
|
-
|
|
1150
|
-
// Task routes
|
|
1151
|
-
const section = el('section', 'asst-routes-section');
|
|
1152
|
-
section.appendChild(el('div', 'asst-routes-section-title', tr('assistant.routes.taskRoutes', 'Task routes')));
|
|
1153
|
-
const list = el('div', 'asst-routes-list');
|
|
1154
|
-
for (const row of taskRows()) list.appendChild(taskRow(row));
|
|
1155
|
-
section.appendChild(list);
|
|
1156
|
-
body.appendChild(section);
|
|
1157
|
-
saveBtn.disabled = state.saving;
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
function taskRow(row) {
|
|
1161
|
-
const pref = effectivePref(row.id);
|
|
1162
|
-
const medium = row.requires || null;
|
|
1163
|
-
const seeing = !medium && row.visionOnly === true;
|
|
1164
|
-
// A saved route onto a model the user hid is never applied (the brain decides); nor, for
|
|
1165
|
-
// image / video creation, one onto a model that cannot generate the medium, or for design one
|
|
1166
|
-
// the router would skip (not known to see, missing from the catalog, unavailable).
|
|
1167
|
-
const sight = seeing && pref ? designRouteSight(pref, state.catalog) : null;
|
|
1168
|
-
const source = pref?.model && hiddenModelFor(pref.provider, pref.model) ? 'disabled'
|
|
1169
|
-
: medium && pref && routeMakes(pref, medium) === false ? 'incapable'
|
|
1170
|
-
: sight && sight !== 'ok' ? 'incapable' : sourceOf(row.id);
|
|
1171
|
-
const emptyLabel = medium ? tr('assistant.routes.noCapableModel', 'No model in your catalog can make {medium} yet.', { medium: mediumWords(medium, tr) })
|
|
1172
|
-
: seeing ? tr('assistant.routes.noSeeingModel', 'No model in your catalog can see images yet.') : '';
|
|
1173
|
-
const node = el('div', 'asst-routes-row');
|
|
1174
|
-
node.dataset.taskClass = row.id;
|
|
1175
|
-
const main = el('div', 'asst-routes-row-main');
|
|
1176
|
-
main.appendChild(el('div', 'asst-routes-row-label', row.label));
|
|
1177
|
-
if (row.description) main.appendChild(el('div', 'asst-routes-row-desc', row.description));
|
|
1178
|
-
if ((medium && noMaker(medium)) || (seeing && noSeer())) main.appendChild(el('div', 'asst-routes-row-note', emptyLabel));
|
|
1179
|
-
node.appendChild(main);
|
|
1180
|
-
|
|
1181
|
-
const modelBtn = el('button', 'asst-dd asst-routes-model');
|
|
1182
|
-
modelBtn.type = 'button';
|
|
1183
|
-
modelBtn.setAttribute('aria-haspopup', 'menu');
|
|
1184
|
-
const label = pref ? routeTargetLabel(pref) : tr('assistant.routes.brainDecides', 'Let the brain decide');
|
|
1185
|
-
modelBtn.innerHTML = `${pref?.provider ? `<span class="asst-icon" aria-hidden="true" style="color:${esc(providerColor(pref.provider))}">${providerIconHtml(pref.provider, hooks)}</span>` : ''}<span class="asst-dd-label"></span>`;
|
|
1186
|
-
modelBtn.querySelector('.asst-dd-label').textContent = label;
|
|
1187
|
-
modelBtn.setAttribute('aria-label', `${row.label}: ${label}`);
|
|
1188
|
-
modelBtn.addEventListener('click', (e) => {
|
|
1189
|
-
e.stopPropagation();
|
|
1190
|
-
if (isMenuOpen(modelBtn)) { closeMenu(); return; }
|
|
1191
|
-
openModelMenu(modelBtn, {
|
|
1192
|
-
brain: hooks.getBrain?.() || null,
|
|
1193
|
-
t: hooks.t,
|
|
1194
|
-
includeHere: true,
|
|
1195
|
-
hereLabel: tr('assistant.routes.brainDecides', 'Let the brain decide'),
|
|
1196
|
-
title: row.label,
|
|
1197
|
-
current: pref ? { provider: pref.provider, model: pref.model } : null,
|
|
1198
|
-
onToast: hooks.onToast,
|
|
1199
|
-
// Image / video creation: only models that generate the medium (no custom id: its output is unknown);
|
|
1200
|
-
// design: only models that can see.
|
|
1201
|
-
...(medium ? { accept: (_p, m) => m?.outputs?.[medium] === true, allowCustom: false, emptyLabel } : {}),
|
|
1202
|
-
...(seeing ? { accept: (_p, m) => m?.vision === true && m?.status !== 'unavailable', allowCustom: false, emptyLabel } : {}),
|
|
1203
|
-
onSelect: (target) => {
|
|
1204
|
-
if (target?.here) state.patch[row.id] = null;
|
|
1205
|
-
else if (target?.model) {
|
|
1206
|
-
// The effort survives when the new model runs it; otherwise the nearest level it does.
|
|
1207
|
-
const ids = modelEffortIds(catalogModelRow(target.provider, target.model, state.catalog));
|
|
1208
|
-
const effort = !pref?.effort ? null : (ids ? clampEffortId(pref.effort, ids) : (pref.provider === target.provider ? pref.effort : null));
|
|
1209
|
-
state.patch[row.id] = { kind: row.defaultKind || 'direct', provider: target.provider, model: target.model, effort, label: target.label || '' };
|
|
1210
|
-
}
|
|
1211
|
-
render();
|
|
1212
|
-
modal.querySelector(`.asst-routes-row[data-task-class="${CSS.escape(row.id)}"] .asst-routes-model`)?.focus();
|
|
1213
|
-
},
|
|
1214
|
-
});
|
|
1215
|
-
});
|
|
1216
|
-
node.appendChild(modelBtn);
|
|
1217
|
-
|
|
1218
|
-
// Exactly the selected model's levels (the provider list only for an unknown model).
|
|
1219
|
-
const modelRow = pref?.provider ? catalogModelRow(pref.provider, pref.model, state.catalog) : null;
|
|
1220
|
-
const efforts = pref?.provider ? getEffortLevelsForModel(pref.provider, modelRow) : [];
|
|
1221
|
-
if (pref && efforts.some(e => e.id !== 'off')) {
|
|
1222
|
-
const effortBtn = el('button', 'asst-dd asst-routes-effort');
|
|
1223
|
-
effortBtn.type = 'button';
|
|
1224
|
-
effortBtn.setAttribute('aria-haspopup', 'menu');
|
|
1225
|
-
const level = efforts.find(e => e.id === pref.effort);
|
|
1226
|
-
const autoLabel = modelRow?.defaultEffort
|
|
1227
|
-
? tr('assistant.routes.effortAutoDefault', 'auto ({effort})', { effort: efforts.find(e => e.id === modelRow.defaultEffort)?.label?.toLowerCase() || modelRow.defaultEffort })
|
|
1228
|
-
: tr('assistant.routes.effortAuto', 'auto effort');
|
|
1229
|
-
const effortLabel = level ? level.label
|
|
1230
|
-
: pref.effort ? tr('assistant.routes.effortUnsupported', '{effort} · unsupported', { effort: pref.effort })
|
|
1231
|
-
: autoLabel;
|
|
1232
|
-
effortBtn.innerHTML = '<span class="asst-dd-label"></span>';
|
|
1233
|
-
effortBtn.querySelector('.asst-dd-label').textContent = effortLabel;
|
|
1234
|
-
effortBtn.setAttribute('aria-label', `${tr('assistant.brain.effort', 'Thinking effort')}: ${effortLabel}`);
|
|
1235
|
-
effortBtn.addEventListener('click', (e) => {
|
|
1236
|
-
e.stopPropagation();
|
|
1237
|
-
if (isMenuOpen(effortBtn)) { closeMenu(); return; }
|
|
1238
|
-
openMenu(effortBtn, {
|
|
1239
|
-
title: tr('assistant.brain.effort', 'Thinking effort'),
|
|
1240
|
-
role: 'menu',
|
|
1241
|
-
items: [
|
|
1242
|
-
{ kind: 'radio', id: '', label: autoLabel, selected: !pref.effort, onSelect: () => { state.patch[row.id] = { ...pref, effort: null }; render(); } },
|
|
1243
|
-
...efforts.filter(x => x.id !== 'off').map(x => ({ kind: 'radio', id: x.id, label: x.label, desc: x.desc || '', selected: pref.effort === x.id, onSelect: () => { state.patch[row.id] = { ...pref, effort: x.id }; render(); } })),
|
|
1244
|
-
],
|
|
1245
|
-
});
|
|
1246
|
-
});
|
|
1247
|
-
node.appendChild(effortBtn);
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
const badge = el('span', 'asst-routes-source', sourceLabel(source));
|
|
1251
|
-
badge.dataset.source = source;
|
|
1252
|
-
if (source === 'incapable') {
|
|
1253
|
-
badge.setAttribute('data-tooltip', !seeing ? tr('assistant.routes.incapableTip', "This model can't generate {medium}, so the route is not applied.", { medium: mediumWords(medium, tr) })
|
|
1254
|
-
: sight === 'blind' ? tr('assistant.routes.incapableSeeTip', "This model can't see images, so the route is not applied.")
|
|
1255
|
-
: sight === 'unavailable' ? tr('assistant.routes.unavailableTip', "This model isn't available right now, so the route is not applied.")
|
|
1256
|
-
: tr('assistant.routes.unknownSeeTip', "This model isn't known to see images, so the route is not applied."));
|
|
1257
|
-
}
|
|
1258
|
-
node.appendChild(badge);
|
|
1259
|
-
|
|
1260
|
-
const reset = el('button', 'asst-iconbtn asst-routes-reset', '↺');
|
|
1261
|
-
reset.type = 'button';
|
|
1262
|
-
reset.setAttribute('aria-label', tr('assistant.routes.reset', 'Reset {taskClass}', { taskClass: row.label }));
|
|
1263
|
-
reset.setAttribute('data-tooltip', tr('assistant.routes.resetTip', 'Back to default'));
|
|
1264
|
-
reset.hidden = source === 'default';
|
|
1265
|
-
reset.addEventListener('click', () => { state.patch[row.id] = null; render(); });
|
|
1266
|
-
node.appendChild(reset);
|
|
1267
|
-
return node;
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
async function load() {
|
|
1271
|
-
state.error = '';
|
|
1272
|
-
state.conflict = false;
|
|
1273
|
-
try {
|
|
1274
|
-
const [data, catalog] = await Promise.all([getRouting(), loadModelCatalog().catch(() => null)]);
|
|
1275
|
-
state.catalog = catalog || null;
|
|
1276
|
-
state.data = data || {};
|
|
1277
|
-
state.version = data?.version ?? null;
|
|
1278
|
-
state.defaultMode = normalizeRouteMode(data?.routing?.defaultMode, DEFAULT_ROUTE_MODE);
|
|
1279
|
-
state.prefs = obj(data?.routing?.preferences) ? { ...data.routing.preferences } : {};
|
|
1280
|
-
state.patch = {};
|
|
1281
|
-
} catch (err) {
|
|
1282
|
-
state.data = null;
|
|
1283
|
-
state.error = err?.status === 404
|
|
1284
|
-
? tr('assistant.routes.unavailable', 'Model routing is not available on this server yet.')
|
|
1285
|
-
: `${tr('assistant.routes.loadFailed', 'Could not load model routes')}: ${err?.message || err}`;
|
|
1286
|
-
}
|
|
1287
|
-
render();
|
|
1288
|
-
modal.querySelector('.asst-routes-mode[aria-checked="true"]')?.focus();
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
resetAllBtn.addEventListener('click', () => {
|
|
1292
|
-
for (const key of new Set([...Object.keys(state.prefs), ...Object.keys(state.patch)])) state.patch[key] = null;
|
|
1293
|
-
render();
|
|
1294
|
-
});
|
|
1295
|
-
|
|
1296
|
-
saveBtn.addEventListener('click', async () => {
|
|
1297
|
-
if (!state.data || state.saving) return;
|
|
1298
|
-
state.saving = true;
|
|
1299
|
-
saveBtn.disabled = true;
|
|
1300
|
-
const patch = { defaultMode: state.defaultMode };
|
|
1301
|
-
if (Object.keys(state.patch).length) patch.preferences = { ...state.patch };
|
|
1302
|
-
try {
|
|
1303
|
-
const res = await putRouting(patch, state.version);
|
|
1304
|
-
try { hooks.onSaved?.(res?.routing || null, res); } catch { /* ignore */ }
|
|
1305
|
-
close();
|
|
1306
|
-
} catch (err) {
|
|
1307
|
-
state.saving = false;
|
|
1308
|
-
if (err?.status === 409 || err?.code === 'VERSION_CONFLICT') {
|
|
1309
|
-
state.error = tr('assistant.routes.conflict', 'Changed elsewhere — reload');
|
|
1310
|
-
state.conflict = true;
|
|
1311
|
-
} else if (err?.code === 'ROUTING_INVALID') {
|
|
1312
|
-
state.error = tr('assistant.routes.invalidField', 'Invalid routing setting: {field}', { field: err?.message || '' });
|
|
1313
|
-
} else {
|
|
1314
|
-
state.error = `${tr('assistant.routes.saveFailed', 'Could not save')}: ${err?.message || err}`;
|
|
1315
|
-
}
|
|
1316
|
-
render();
|
|
1317
|
-
}
|
|
1318
|
-
});
|
|
1319
|
-
|
|
1320
|
-
await load();
|
|
1321
|
-
return { el: overlay, close };
|
|
1322
|
-
}
|
|
1014
|
+
// ── Routes editor (draft, modes, task choices) ───────────────────────────────
|
|
1015
|
+
// Its model lists still come only through asst-route-models.js.
|
|
1016
|
+
export { openRoutesEditor } from './asst-routes-editor.js';
|
|
1323
1017
|
|
|
1324
1018
|
// ── Models manager (Assistant → Models…) ───────────────────────────────────
|
|
1325
1019
|
|