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
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SETTINGS — Code editor (the pane)
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Two sections. "Editing": one control for each `editing` preference (text size, wrapping, the minimap,
|
|
6
|
+
// indentation, what a save does); the editor's own View menu changes the same preferences, and each follows the
|
|
7
|
+
// other. "AI autocomplete": the switch, where suggestions come from, the model list with its Test buttons and
|
|
8
|
+
// "Find fastest", the endpoint (kind, address, model, request shape, key set or not), the files that are never
|
|
9
|
+
// sent, and today's use. settings-code-editor.js reads the server's answers and decides what is true; this asks
|
|
10
|
+
// and draws. Every change is saved as it is made (PUT /api/editor/config with only what changed) and the
|
|
11
|
+
// section then shows what the server stored: a change that could not be saved goes back to where it was.
|
|
12
|
+
//
|
|
13
|
+
// The endpoint's key is write-only here: the field is always empty, and the page only ever learns whether a key
|
|
14
|
+
// is set.
|
|
15
|
+
|
|
16
|
+
import { on } from '../state.js';
|
|
17
|
+
import * as kit from './settings-kit.js';
|
|
18
|
+
import { getSettingsPage, pageKeys } from './settings-ia.js';
|
|
19
|
+
import { AI_EXCLUDE_DEFAULTS } from '../editor/editor-prefs.js';
|
|
20
|
+
import {
|
|
21
|
+
EDITING_FIELDS, describeEditorAi, describeEditorEditing, describeEditorFastest, describeEditorModels, describeEditorSaveFailure, describeEditorTest,
|
|
22
|
+
describeEditorUsage, editingChange, editingOptionLabel, isEndpointUrl, parseExcludeList, readEditorAiResponse, readEditorEditingResponse,
|
|
23
|
+
} from './settings-code-editor.js';
|
|
24
|
+
|
|
25
|
+
const K = 'settings.redesign.code_editor';
|
|
26
|
+
const CONFIG_URL = '/api/editor/config';
|
|
27
|
+
const COMPLETE_URL = '/api/editor/complete';
|
|
28
|
+
const c = (key, params) => kit.te(`${K}.${key}`, params);
|
|
29
|
+
/** The id of the control of an editing preference. */
|
|
30
|
+
const editingId = (key) => `edt-ed-${key}`;
|
|
31
|
+
|
|
32
|
+
// One row for each editing preference: a switch, or a list of its choices. Switched off until the server answered.
|
|
33
|
+
function editingRow(field) {
|
|
34
|
+
const id = editingId(field.key);
|
|
35
|
+
if (field.kind === 'toggle') return kit.toggleField(field.id, kit.switchInput(id, { attrs: 'disabled' }), { forId: id });
|
|
36
|
+
const options = field.values.map((value) => `<option value="${value}">${kit.esc(editingOptionLabel(field.key, value, { tx: kit.tx }))}</option>`).join('');
|
|
37
|
+
return kit.field(field.id, `
|
|
38
|
+
<select class="stg-input" id="${id}" aria-describedby="${id}-help" disabled>${options}</select>`, { forId: id });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildCodeEditorTab() {
|
|
42
|
+
const view = describeEditorAi(null, { tx: kit.tx });
|
|
43
|
+
const option = (value, key) => `<option value="${value}">${c(key)}</option>`;
|
|
44
|
+
return `
|
|
45
|
+
<div class="stg-pane" data-stg-pane="editor">
|
|
46
|
+
${kit.card({
|
|
47
|
+
id: 'stg-sec-editor-editing', section: 'code_editor.editing',
|
|
48
|
+
body: `
|
|
49
|
+
<div class="stg-help edt-note" id="edt-ed-note" role="status" data-stg-data hidden></div>
|
|
50
|
+
${EDITING_FIELDS.map(editingRow).join('')}
|
|
51
|
+
<div class="stg-help edt-save-status" id="edt-ed-save-status" role="alert" data-stg-data hidden></div>`,
|
|
52
|
+
})}
|
|
53
|
+
${kit.card({
|
|
54
|
+
id: 'stg-sec-editor-ai', section: 'code_editor.ai_autocomplete',
|
|
55
|
+
// empty until the server has answered: the stylesheet hides an empty status word
|
|
56
|
+
status: kit.pill(kit.esc(view.pill.text), { state: view.pill.state, id: 'edt-ai-pill' }),
|
|
57
|
+
body: `
|
|
58
|
+
<div class="stg-help edt-note" id="edt-ai-note" role="status" data-stg-data hidden></div>
|
|
59
|
+
${kit.toggleField('EDT001', kit.switchInput('edt-ai-enabled', { attrs: 'disabled' }), { forId: 'edt-ai-enabled' })}
|
|
60
|
+
${kit.field('EDT002', `
|
|
61
|
+
<select class="stg-input" id="edt-ai-engine" aria-describedby="edt-ai-engine-help" disabled>
|
|
62
|
+
${option('opencode', 'engine.opencode')}${option('endpoint', 'engine.endpoint')}
|
|
63
|
+
</select>`, { forId: 'edt-ai-engine' })}
|
|
64
|
+
|
|
65
|
+
<div class="edt-engine" id="edt-ai-opencode">
|
|
66
|
+
<div class="stg-field edt-models-field" ${kit.inv('EDT003')}>
|
|
67
|
+
<div class="edt-models-head">
|
|
68
|
+
<label id="edt-ai-models-title">${kit.L('EDT003')}</label>
|
|
69
|
+
<button type="button" class="stg-action-btn" id="edt-ai-fastest" ${kit.inv('EDT004')} title="${kit.H('EDT004')}" disabled>${kit.L('EDT004')}</button>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="stg-help" id="edt-ai-models-help">${kit.H('EDT003')}</div>
|
|
72
|
+
<div class="stg-help edt-result" id="edt-ai-fastest-result" role="status" aria-live="polite" data-stg-data hidden></div>
|
|
73
|
+
<div class="edt-models" id="edt-ai-models" role="radiogroup" aria-labelledby="edt-ai-models-title" aria-describedby="edt-ai-models-help" data-stg-data data-stg-search="off"></div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class="edt-engine" id="edt-ai-endpoint" hidden>
|
|
78
|
+
${kit.field('EDT005', `
|
|
79
|
+
<select class="stg-input" id="edt-ai-kind" aria-describedby="edt-ai-kind-help" disabled>
|
|
80
|
+
${option('ollama', 'kind.ollama')}${option('openai', 'kind.openai')}
|
|
81
|
+
</select>`, { forId: 'edt-ai-kind' })}
|
|
82
|
+
${kit.field('EDT006', `
|
|
83
|
+
<div class="settings-key-row">
|
|
84
|
+
<input id="edt-ai-url" type="url" inputmode="url" autocomplete="off" spellcheck="false" aria-describedby="edt-ai-url-help" disabled>
|
|
85
|
+
</div>`, { forId: 'edt-ai-url' })}
|
|
86
|
+
${kit.field('EDT007', `
|
|
87
|
+
<div class="settings-key-row">
|
|
88
|
+
<input id="edt-ai-endpoint-model" type="text" autocomplete="off" spellcheck="false" aria-describedby="edt-ai-endpoint-model-help" disabled>
|
|
89
|
+
</div>`, { forId: 'edt-ai-endpoint-model' })}
|
|
90
|
+
${kit.field('EDT008', `
|
|
91
|
+
<select class="stg-input" id="edt-ai-shape" aria-describedby="edt-ai-shape-help" disabled>
|
|
92
|
+
${option('fim', 'shape.fim')}${option('chat', 'shape.chat')}
|
|
93
|
+
</select>`, { forId: 'edt-ai-shape' })}
|
|
94
|
+
${kit.field('EDT009', `
|
|
95
|
+
<div class="settings-key-row edt-key-row">
|
|
96
|
+
<input id="edt-ai-key" type="password" autocomplete="off" spellcheck="false" aria-describedby="edt-ai-key-help edt-ai-key-state" disabled>
|
|
97
|
+
<button type="button" class="stg-action-btn" id="edt-ai-key-save" disabled>${c('key.save')}</button>
|
|
98
|
+
<button type="button" class="cc-copy-btn stg-text-btn" id="edt-ai-key-remove" hidden>${c('key.remove')}</button>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="stg-help edt-key-state" id="edt-ai-key-state" role="status" data-stg-data></div>`, { forId: 'edt-ai-key' })}
|
|
101
|
+
<div class="stg-field" ${kit.inv('EDT010')}>
|
|
102
|
+
<div class="stg-action-row" style="align-items:center">
|
|
103
|
+
<button type="button" class="stg-action-btn" id="edt-ai-endpoint-test" aria-describedby="edt-ai-endpoint-test-help" disabled>${kit.L('EDT010')}</button>
|
|
104
|
+
<span class="stg-help edt-result" id="edt-ai-endpoint-result" role="status" aria-live="polite" data-stg-data style="margin:0"></span>
|
|
105
|
+
</div>
|
|
106
|
+
${kit.help('EDT010', { forId: 'edt-ai-endpoint-test' })}
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="stg-field edt-exclude-field" ${kit.inv('EDT011')}>
|
|
111
|
+
<label for="edt-ai-exclude">${kit.L('EDT011')}</label>
|
|
112
|
+
<div class="stg-help" id="edt-ai-exclude-help">${kit.H('EDT011')}</div>
|
|
113
|
+
<textarea class="edt-exclude" id="edt-ai-exclude" rows="6" autocomplete="off" autocapitalize="off" spellcheck="false" aria-describedby="edt-ai-exclude-help edt-ai-exclude-count" data-stg-search="off" disabled></textarea>
|
|
114
|
+
<div class="stg-action-row" style="align-items:center">
|
|
115
|
+
<button type="button" class="cc-copy-btn stg-text-btn" id="edt-ai-exclude-reset" ${kit.inv('EDT012')} title="${kit.H('EDT012')}" disabled>${kit.L('EDT012')}</button>
|
|
116
|
+
<span class="stg-help" id="edt-ai-exclude-count" data-stg-data style="margin:0"></span>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div class="stg-field edt-usage-field" ${kit.inv('EDT013')}>
|
|
121
|
+
<label id="edt-ai-usage-label">${kit.L('EDT013')}</label>
|
|
122
|
+
<div class="stg-help" id="edt-ai-usage" aria-labelledby="edt-ai-usage-label" title="${kit.H('EDT013')}" data-stg-data></div>
|
|
123
|
+
</div>
|
|
124
|
+
<div class="stg-help edt-save-status" id="edt-ai-save-status" role="alert" data-stg-data hidden></div>`,
|
|
125
|
+
})}
|
|
126
|
+
</div>`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Load the section and wire its controls. Called once per opened Settings panel.
|
|
131
|
+
* @param {HTMLElement} overlay the Settings panel
|
|
132
|
+
* @param {{ fetchImpl?: typeof fetch }} [o]
|
|
133
|
+
*/
|
|
134
|
+
export function wireCodeEditorTab(overlay, { fetchImpl = (...args) => fetch(...args) } = {}) {
|
|
135
|
+
const pane = kit.paneOf(overlay, 'editor');
|
|
136
|
+
if (!pane) return;
|
|
137
|
+
const $ = (id) => pane.querySelector(`#${id}`);
|
|
138
|
+
const tx = kit.tx;
|
|
139
|
+
const alive = () => document.body.contains(overlay);
|
|
140
|
+
const providersPage = (() => { const page = getSettingsPage('ai-connections'); return page ? tx(pageKeys(page).title) : ''; })();
|
|
141
|
+
|
|
142
|
+
let editing = null; // what the server answered about the editing preferences, or null until it has
|
|
143
|
+
let reading = null; // what the server answered (readEditorAiResponse), or null until it has
|
|
144
|
+
let view = describeEditorAi(reading, { tx });
|
|
145
|
+
let models = null; // what GET …/models answered, or null while it is asked
|
|
146
|
+
let busy = false; // a test or "Find fastest" is running: one at a time
|
|
147
|
+
const results = new Map(); // model id → the result of its last test, for this panel
|
|
148
|
+
|
|
149
|
+
const request = async (method, url, body) => {
|
|
150
|
+
try {
|
|
151
|
+
const res = await fetchImpl(url, { method, headers: body === undefined ? {} : { 'Content-Type': 'application/json' }, body: body === undefined ? undefined : JSON.stringify(body) });
|
|
152
|
+
return { status: res.status, body: await res.json().catch(() => null) };
|
|
153
|
+
} catch (error) {
|
|
154
|
+
return { status: 0, body: null, error: error?.message || '' };
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const say = (node, text, tone = '') => {
|
|
159
|
+
if (!node) return;
|
|
160
|
+
node.textContent = text || '';
|
|
161
|
+
node.hidden = !text;
|
|
162
|
+
if (tone) node.dataset.edtTone = tone; else delete node.dataset.edtTone;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// ── Editing ──
|
|
166
|
+
|
|
167
|
+
function drawEditing() {
|
|
168
|
+
const shown = describeEditorEditing(editing, { tx });
|
|
169
|
+
say($('edt-ed-note'), shown.note?.text || '', shown.note?.tone === 'neutral' ? 'neutral' : '');
|
|
170
|
+
for (const field of EDITING_FIELDS) {
|
|
171
|
+
const node = $(editingId(field.key));
|
|
172
|
+
if (!node) continue;
|
|
173
|
+
if (field.kind === 'toggle') node.checked = shown.values[field.key];
|
|
174
|
+
else node.value = shown.values[field.key];
|
|
175
|
+
node.disabled = !shown.ready;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Save one editing preference; the section then shows what the server holds, whichever way it went. */
|
|
180
|
+
async function saveEditing(field, node) {
|
|
181
|
+
const change = editingChange(field.key, field.kind === 'toggle' ? node.checked : node.value);
|
|
182
|
+
if (!change) { drawEditing(); return; }
|
|
183
|
+
const answer = await request('PUT', CONFIG_URL, change);
|
|
184
|
+
if (!alive()) return;
|
|
185
|
+
const stored = readEditorEditingResponse(answer);
|
|
186
|
+
const ok = stored.state === 'ready';
|
|
187
|
+
if (ok) {
|
|
188
|
+
editing = stored;
|
|
189
|
+
if (reading?.state === 'ready' && answer.body.config.ai) reading = { ...reading, config: answer.body.config };
|
|
190
|
+
}
|
|
191
|
+
say($('edt-ed-save-status'), ok ? '' : describeEditorSaveFailure(answer, { tx }));
|
|
192
|
+
drawEditing();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (const field of EDITING_FIELDS) {
|
|
196
|
+
const node = $(editingId(field.key));
|
|
197
|
+
node?.addEventListener('change', () => { saveEditing(field, node); });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── Drawing ──
|
|
201
|
+
|
|
202
|
+
function draw() {
|
|
203
|
+
view = describeEditorAi(reading, { tx });
|
|
204
|
+
const off = !view.ready;
|
|
205
|
+
say($('edt-ai-note'), view.note?.text || '', view.note?.tone === 'neutral' ? 'neutral' : '');
|
|
206
|
+
const pill = $('edt-ai-pill');
|
|
207
|
+
if (pill) { pill.textContent = view.pill.text; pill.dataset.state = view.pill.state; }
|
|
208
|
+
const set = (id, change) => { const node = $(id); if (node) change(node); };
|
|
209
|
+
set('edt-ai-enabled', (node) => { node.checked = view.enabled; node.disabled = off; });
|
|
210
|
+
set('edt-ai-engine', (node) => { node.value = view.engine; node.disabled = off; });
|
|
211
|
+
$('edt-ai-opencode').hidden = view.engine !== 'opencode';
|
|
212
|
+
$('edt-ai-endpoint').hidden = view.engine !== 'endpoint';
|
|
213
|
+
set('edt-ai-kind', (node) => { node.value = view.endpoint.kind; node.disabled = off; });
|
|
214
|
+
set('edt-ai-shape', (node) => { node.value = view.endpoint.shape; node.disabled = off; });
|
|
215
|
+
// A field that holds the keyboard keeps what is being typed into it.
|
|
216
|
+
const typing = (node) => node === document.activeElement;
|
|
217
|
+
set('edt-ai-url', (node) => { if (!typing(node)) node.value = view.endpoint.url; node.placeholder = view.urlPlaceholder; node.disabled = off; });
|
|
218
|
+
set('edt-ai-endpoint-model', (node) => { if (!typing(node)) node.value = view.endpoint.model; node.disabled = off; });
|
|
219
|
+
set('edt-ai-key', (node) => { node.placeholder = view.keyPlaceholder; node.disabled = off; });
|
|
220
|
+
set('edt-ai-key-save', (node) => { node.disabled = off || !$('edt-ai-key').value.trim(); });
|
|
221
|
+
set('edt-ai-key-remove', (node) => { node.hidden = off || !view.hasKey; });
|
|
222
|
+
set('edt-ai-key-state', (node) => { if (!node.dataset.edtTone) node.textContent = view.keyState; node.dataset.edtKey = view.hasKey ? 'set' : 'none'; });
|
|
223
|
+
set('edt-ai-endpoint-test', (node) => { node.disabled = off || busy || !(view.endpoint.url && view.endpoint.model); });
|
|
224
|
+
set('edt-ai-exclude', (node) => { if (!typing(node)) node.value = view.exclude; node.disabled = off; });
|
|
225
|
+
set('edt-ai-exclude-reset', (node) => { node.disabled = off; });
|
|
226
|
+
set('edt-ai-exclude-count', (node) => { node.textContent = view.excludeCount; });
|
|
227
|
+
drawModels();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function drawModels() {
|
|
231
|
+
const box = $('edt-ai-models');
|
|
232
|
+
if (!box) return;
|
|
233
|
+
const list = view.ready ? describeEditorModels(models, view.model, { tx, providersPage }) : { state: 'unavailable', message: '', canStart: false, rows: [] };
|
|
234
|
+
box.dataset.edtModels = list.state;
|
|
235
|
+
const fastest = $('edt-ai-fastest');
|
|
236
|
+
if (fastest) fastest.disabled = !view.ready || busy;
|
|
237
|
+
const row = (model) => {
|
|
238
|
+
const id = kit.esc(model.id);
|
|
239
|
+
const result = results.get(model.id);
|
|
240
|
+
return `
|
|
241
|
+
<div class="edt-model${model.selected ? ' selected' : ''}" data-edt-model="${id}">
|
|
242
|
+
<label class="edt-model-pick">
|
|
243
|
+
<input type="radio" name="edt-ai-model" value="${id}"${model.selected ? ' checked' : ''} aria-label="${c('models.pick', { model: model.label })}">
|
|
244
|
+
<span class="edt-model-name">${kit.esc(model.label)}</span>
|
|
245
|
+
<span class="edt-model-meta">${kit.esc(model.listed ? `${model.provider} · ${model.meta}` : model.meta)}</span>
|
|
246
|
+
</label>
|
|
247
|
+
<button type="button" class="cc-copy-btn stg-text-btn edt-model-test" data-edt-test="${id}" aria-label="${c('models.testNamed', { model: model.label })}"${busy ? ' disabled' : ''}>${c('models.test')}</button>
|
|
248
|
+
<div class="stg-help edt-model-result" role="status" aria-live="polite"${result ? ` data-edt-tone="${result.tone}"` : ' hidden'}>${result ? kit.esc(result.text) : ''}</div>
|
|
249
|
+
</div>`;
|
|
250
|
+
};
|
|
251
|
+
const message = list.message
|
|
252
|
+
? `<div class="stg-help edt-models-message">${kit.esc(list.message)}${list.canStart ? ` <button type="button" class="cc-copy-btn stg-text-btn" id="edt-ai-models-start">${c('models.start')}</button>` : ''}</div>`
|
|
253
|
+
: '';
|
|
254
|
+
box.innerHTML = list.rows.map(row).join('') + message;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ── Loading ──
|
|
258
|
+
|
|
259
|
+
async function loadModels({ start = false } = {}) {
|
|
260
|
+
if (view.engine !== 'opencode' && !start) return;
|
|
261
|
+
models = null;
|
|
262
|
+
drawModels();
|
|
263
|
+
const answer = await request('GET', `${COMPLETE_URL}/models${start ? '?start=1' : ''}`);
|
|
264
|
+
if (!alive()) return;
|
|
265
|
+
models = answer;
|
|
266
|
+
drawModels();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function loadUsage() {
|
|
270
|
+
const answer = await request('GET', `${COMPLETE_URL}/usage`);
|
|
271
|
+
if (!alive()) return;
|
|
272
|
+
const usage = $('edt-ai-usage');
|
|
273
|
+
if (usage) usage.textContent = describeEditorUsage(answer.status === 200 ? answer.body?.today : null, { tx });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async function load() {
|
|
277
|
+
const [config, caps] = await Promise.all([request('GET', CONFIG_URL), request('GET', '/api/editor/capabilities')]);
|
|
278
|
+
if (!alive()) return;
|
|
279
|
+
editing = readEditorEditingResponse(config);
|
|
280
|
+
drawEditing();
|
|
281
|
+
reading = readEditorAiResponse({ ...config, capabilities: Array.isArray(caps.body?.capabilities) ? caps.body.capabilities : null });
|
|
282
|
+
draw();
|
|
283
|
+
if (reading.state !== 'ready') return;
|
|
284
|
+
loadModels();
|
|
285
|
+
loadUsage();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ── Saving ──
|
|
289
|
+
|
|
290
|
+
/** Save a partial change; the section then shows what the server holds, whichever way it went. */
|
|
291
|
+
async function save(partial) {
|
|
292
|
+
const answer = await request('PUT', CONFIG_URL, partial);
|
|
293
|
+
if (!alive()) return false;
|
|
294
|
+
const ok = answer.status === 200 && answer.body?.ok === true && !!answer.body.config?.ai;
|
|
295
|
+
if (ok) reading = { state: 'ready', config: answer.body.config, hasEndpointKey: answer.body.hasEndpointKey === true, reason: null };
|
|
296
|
+
if (ok && editing?.state === 'ready' && answer.body.config.editing) editing = { ...editing, editing: answer.body.config.editing };
|
|
297
|
+
say($('edt-ai-save-status'), ok ? '' : describeEditorSaveFailure(answer, { tx }));
|
|
298
|
+
draw();
|
|
299
|
+
return ok;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const enabled = $('edt-ai-enabled');
|
|
303
|
+
enabled?.addEventListener('change', () => { save({ ai: { enabled: enabled.checked } }); });
|
|
304
|
+
$('edt-ai-engine')?.addEventListener('change', async (event) => {
|
|
305
|
+
if (await save({ ai: { engine: event.target.value } }) && view.engine === 'opencode' && !models) loadModels();
|
|
306
|
+
});
|
|
307
|
+
$('edt-ai-kind')?.addEventListener('change', (event) => { save({ ai: { endpoint: { kind: event.target.value } } }); });
|
|
308
|
+
$('edt-ai-shape')?.addEventListener('change', (event) => { save({ ai: { endpoint: { shape: event.target.value } } }); });
|
|
309
|
+
$('edt-ai-url')?.addEventListener('change', (event) => {
|
|
310
|
+
const url = event.target.value.trim();
|
|
311
|
+
// Not an address: nothing is sent, and the field says why instead of silently emptying itself.
|
|
312
|
+
if (url && !isEndpointUrl(url)) { say($('edt-ai-save-status'), tx(`${K}.url.invalid`)); return; }
|
|
313
|
+
save({ ai: { endpoint: { url } } });
|
|
314
|
+
});
|
|
315
|
+
$('edt-ai-endpoint-model')?.addEventListener('change', (event) => { save({ ai: { endpoint: { model: event.target.value.trim() } } }); });
|
|
316
|
+
$('edt-ai-exclude')?.addEventListener('change', (event) => { save({ ai: { exclude: parseExcludeList(event.target.value) } }); });
|
|
317
|
+
$('edt-ai-exclude-reset')?.addEventListener('click', () => { save({ ai: { exclude: [...AI_EXCLUDE_DEFAULTS] } }); });
|
|
318
|
+
|
|
319
|
+
// The key: written, never read back.
|
|
320
|
+
const keyInput = $('edt-ai-key');
|
|
321
|
+
const keyState = $('edt-ai-key-state');
|
|
322
|
+
keyInput?.addEventListener('input', () => { $('edt-ai-key-save').disabled = !view.ready || !keyInput.value.trim(); });
|
|
323
|
+
async function saveKey(value) {
|
|
324
|
+
const answer = await request('PUT', CONFIG_URL, { endpointKey: value });
|
|
325
|
+
if (!alive()) return;
|
|
326
|
+
const ok = answer.status === 200 && answer.body?.ok === true;
|
|
327
|
+
if (ok) {
|
|
328
|
+
reading = { state: 'ready', config: answer.body.config, hasEndpointKey: answer.body.hasEndpointKey === true, reason: null };
|
|
329
|
+
keyInput.value = '';
|
|
330
|
+
say(keyState, tx(value ? `${K}.key.saved` : `${K}.key.removed`), 'ok');
|
|
331
|
+
} else {
|
|
332
|
+
say(keyState, describeEditorSaveFailure(answer, { tx }), 'err');
|
|
333
|
+
}
|
|
334
|
+
draw();
|
|
335
|
+
// The line goes back to saying whether a key is set.
|
|
336
|
+
setTimeout(() => { if (alive()) { delete keyState.dataset.edtTone; keyState.textContent = view.keyState; } }, 4000);
|
|
337
|
+
}
|
|
338
|
+
$('edt-ai-key-save')?.addEventListener('click', () => { const value = keyInput.value.trim(); if (value) saveKey(value); });
|
|
339
|
+
keyInput?.addEventListener('keydown', (event) => { if (event.key === 'Enter' && keyInput.value.trim()) { event.preventDefault(); saveKey(keyInput.value.trim()); } });
|
|
340
|
+
$('edt-ai-key-remove')?.addEventListener('click', () => saveKey(''));
|
|
341
|
+
|
|
342
|
+
// ── Tests ──
|
|
343
|
+
|
|
344
|
+
async function runTest(body) {
|
|
345
|
+
busy = true;
|
|
346
|
+
draw();
|
|
347
|
+
const answer = await request('POST', `${COMPLETE_URL}/test`, body);
|
|
348
|
+
busy = false;
|
|
349
|
+
return answer;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
$('edt-ai-models')?.addEventListener('change', (event) => {
|
|
353
|
+
const radio = event.target.closest?.('input[name="edt-ai-model"]');
|
|
354
|
+
if (radio?.checked) save({ ai: { model: radio.value } });
|
|
355
|
+
});
|
|
356
|
+
$('edt-ai-models')?.addEventListener('click', async (event) => {
|
|
357
|
+
if (event.target.closest?.('#edt-ai-models-start')) { loadModels({ start: true }); return; }
|
|
358
|
+
const button = event.target.closest?.('[data-edt-test]');
|
|
359
|
+
if (!button || busy) return;
|
|
360
|
+
const model = button.dataset.edtTest;
|
|
361
|
+
results.set(model, { tone: '', text: tx(`${K}.test.running`) });
|
|
362
|
+
const answer = await runTest({ engine: 'opencode', model });
|
|
363
|
+
if (!alive()) return;
|
|
364
|
+
results.set(model, describeEditorTest(answer.status === 200 ? answer.body?.results?.[0] : null, { tx }));
|
|
365
|
+
draw();
|
|
366
|
+
loadUsage();
|
|
367
|
+
});
|
|
368
|
+
$('edt-ai-fastest')?.addEventListener('click', async () => {
|
|
369
|
+
if (busy) return;
|
|
370
|
+
const line = $('edt-ai-fastest-result');
|
|
371
|
+
say(line, tx(`${K}.fastest.running`));
|
|
372
|
+
const answer = await runTest({ fastest: true });
|
|
373
|
+
if (!alive()) return;
|
|
374
|
+
const body = answer.status === 200 ? answer.body : null;
|
|
375
|
+
for (const result of Array.isArray(body?.results) ? body.results : []) results.set(result.model, describeEditorTest(result, { tx }));
|
|
376
|
+
const found = describeEditorFastest(body, { tx });
|
|
377
|
+
say(line, found.text, found.tone);
|
|
378
|
+
if (found.model) await save({ ai: { model: found.model } });
|
|
379
|
+
else draw();
|
|
380
|
+
// the list may have come from a serve that was just started for this
|
|
381
|
+
if (!models || models.body?.available === false) loadModels();
|
|
382
|
+
loadUsage();
|
|
383
|
+
});
|
|
384
|
+
$('edt-ai-endpoint-test')?.addEventListener('click', async () => {
|
|
385
|
+
if (busy) return;
|
|
386
|
+
const line = $('edt-ai-endpoint-result');
|
|
387
|
+
say(line, tx(`${K}.test.running`));
|
|
388
|
+
const answer = await runTest({ engine: 'endpoint' });
|
|
389
|
+
if (!alive()) return;
|
|
390
|
+
const result = describeEditorTest(answer.status === 200 ? answer.body?.results?.[0] : null, { tx });
|
|
391
|
+
say(line, result.text, result.tone);
|
|
392
|
+
draw();
|
|
393
|
+
loadUsage();
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// The editor's View menu, its AI popover, or another window, changed the preferences.
|
|
397
|
+
const off = on('sync:editor:config-changed', (message) => {
|
|
398
|
+
if (!alive() || !message?.config) return;
|
|
399
|
+
if (editing?.state === 'ready' && message.config.editing) {
|
|
400
|
+
editing = { ...editing, editing: message.config.editing };
|
|
401
|
+
drawEditing();
|
|
402
|
+
}
|
|
403
|
+
if (reading?.state !== 'ready' || !message.config.ai) return;
|
|
404
|
+
reading = { ...reading, config: message.config, hasEndpointKey: typeof message.hasEndpointKey === 'boolean' ? message.hasEndpointKey : reading.hasEndpointKey };
|
|
405
|
+
draw();
|
|
406
|
+
});
|
|
407
|
+
overlay.addEventListener('settings-close', off, { once: true });
|
|
408
|
+
|
|
409
|
+
drawEditing();
|
|
410
|
+
draw();
|
|
411
|
+
load();
|
|
412
|
+
}
|