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
|
@@ -25,17 +25,12 @@ import { detectProject as memoryProject } from '../../mcp-server/dist/config.js'
|
|
|
25
25
|
// WS bound, so page-refresh reattach is the same object.
|
|
26
26
|
|
|
27
27
|
import { query, startup } from '@anthropic-ai/claude-agent-sdk';
|
|
28
|
-
import { CLAUDE_EFFORT_LEVELS
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
clearNativeBinaryCache,
|
|
32
|
-
isNativeBinaryLaunchFailure,
|
|
33
|
-
planRuntimeRecovery,
|
|
34
|
-
resolveClaudeExecutableOverride,
|
|
35
|
-
} from './native-binary-runtime.js';
|
|
28
|
+
import { CLAUDE_EFFORT_LEVELS } from './claude-model-catalog.js';
|
|
29
|
+
import { CLAUDE_NOT_INSTALLED, resolveClaudeSdkExecutable } from './claude-executable.js';
|
|
30
|
+
import { diagnoseLaunchFailure, isNativeBinaryLaunchFailure } from './native-binary-runtime.js';
|
|
36
31
|
import { normalizePanelSession, startSignature, applyPanelSessionOptions, liveSettingsPatch, normalizeMcpServers, mergeTabMcpServers } from './claude-panel-session.js';
|
|
37
32
|
import { SESSION_REQUESTS, runSessionRequest, slimRewind, slimMcpStatus } from './claude-panel-requests.js';
|
|
38
|
-
import { applyTemporaryOptions, plansDirsOf, planFileOfToolCall, removeTemporaryPlanFiles } from './claude-temporary.js';
|
|
33
|
+
import { applyTemporaryOptions, plansDirsOf, snapshotPlanFiles, planFileOfToolCall, removeTemporaryPlanFiles } from './claude-temporary.js';
|
|
39
34
|
import { rootBypassBlock } from './claude-bypass-policy.js';
|
|
40
35
|
import { randomUUID } from 'node:crypto';
|
|
41
36
|
import { dirname, join } from 'node:path';
|
|
@@ -112,6 +107,7 @@ export const PANEL_CAPABILITIES = Object.freeze([
|
|
|
112
107
|
'message_flags', // session.hookEvents / promptSuggestions / subagentText / agentSummaries → the matching SDK options
|
|
113
108
|
'task_control', // inbound `stop_task` / `background_tasks` → `task_control_result`; system/session_crons events
|
|
114
109
|
'origin_human', // a query marked `typed: true` is sent with origin {kind:'human'}
|
|
110
|
+
'greeting', // query `greetingId`: the model is told once what SynaBun greeted the user with (lib/greeting/)
|
|
115
111
|
'session_requests', // inbound `session_request {id, what, args}` → `session_response`: context_usage, usage, mcp_status, mcp_reconnect, mcp_toggle, rewind_preview
|
|
116
112
|
'rewind_stats', // `rewind_result` carries filesChanged / insertions / deletions
|
|
117
113
|
'session_title', // query `title` names a new session where the CLI reads it
|
|
@@ -231,7 +227,7 @@ function log(...args) { console.log('[claude-sdk]', ...args); }
|
|
|
231
227
|
|
|
232
228
|
// Panel sessions, a temporary chat (lib/claude-temporary.js): the plan files
|
|
233
229
|
// Claude Code wrote for one that still have to be removed. path → { plansDirs,
|
|
234
|
-
// since, ended, last }. One is removed once the pump of the process that wrote
|
|
230
|
+
// since, before, ended, last }. One is removed once the pump of the process that wrote
|
|
235
231
|
// it has settled (`ended`), and stays owed after that removal, whether it
|
|
236
232
|
// removed the file or found none: the pump settles when the SDK's own cleanup
|
|
237
233
|
// stops waiting for the process, which can be before the process is gone, and
|
|
@@ -348,15 +344,9 @@ export class ClaudeSession {
|
|
|
348
344
|
this.lastPrompt = null;
|
|
349
345
|
this.stallRetries = 0;
|
|
350
346
|
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
this._nativeRepairTried = false;
|
|
355
|
-
this._fallbackBin = null;
|
|
356
|
-
// The installed CLI the current Query runs on because it is newer than the
|
|
357
|
-
// bundled one (see ensureQuery). Per-Query, not a latch: a launch failure is
|
|
358
|
-
// latched process-wide in claude-model-catalog.js instead.
|
|
359
|
-
this._alignedBin = null;
|
|
347
|
+
// The Claude Code executable the current Query was started with (see
|
|
348
|
+
// ensureQuery): what a launch failure is diagnosed against.
|
|
349
|
+
this._claudeExecutable = null;
|
|
360
350
|
|
|
361
351
|
this.pendingPerms = new Map(); // requestId → { toolName, resolve, input, kind, wire }
|
|
362
352
|
this.alwaysAllowed = new Set();
|
|
@@ -499,6 +489,31 @@ export class ClaudeSession {
|
|
|
499
489
|
return null;
|
|
500
490
|
}
|
|
501
491
|
}
|
|
492
|
+
// Which Claude Code runs this session: the user's own installation, always.
|
|
493
|
+
// SynaBun carries none (lib/external-tools.js at the package root) and the
|
|
494
|
+
// SDK is never left to look for one. The host answers (deps.claudeExecutable,
|
|
495
|
+
// lib/claude-executable.js): an explicit override from cli-config.json
|
|
496
|
+
// ("claude-skin": { "sdkExecutable": "…" }), else the installed Claude Code.
|
|
497
|
+
// The model picker lists that same installation's models, so an alias means
|
|
498
|
+
// in the session what it meant in the picker.
|
|
499
|
+
//
|
|
500
|
+
// Nothing installed is an ordinary state: the start is refused with the
|
|
501
|
+
// sentence the panel shows its install help on, and nothing was started.
|
|
502
|
+
// The SDK itself is never called without an executable; only a host that
|
|
503
|
+
// brings its own query factory and no resolver (a test) starts without one.
|
|
504
|
+
let executable = null;
|
|
505
|
+
if (typeof deps.claudeExecutable === 'function') {
|
|
506
|
+
try { executable = deps.claudeExecutable() || null; } catch { executable = null; }
|
|
507
|
+
} else if (deps.sdkExecutable) {
|
|
508
|
+
executable = resolveClaudeSdkExecutable({ sdkExecutable: deps.sdkExecutable });
|
|
509
|
+
}
|
|
510
|
+
const ownFactory = typeof (warm ? deps.startupFactory : deps.queryFactory) === 'function';
|
|
511
|
+
if (!executable?.path && (typeof deps.claudeExecutable === 'function' || !ownFactory)) {
|
|
512
|
+
this._closeWarm();
|
|
513
|
+
this._startRefused = { code: 'claude_not_installed', message: executable?.reason || CLAUDE_NOT_INSTALLED };
|
|
514
|
+
log(`session create refused: no Claude Code to run (${executable?.reason || 'not installed'})`);
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
502
517
|
if (this._warm) {
|
|
503
518
|
const w = this._warm;
|
|
504
519
|
this._warm = null;
|
|
@@ -588,8 +603,9 @@ export class ClaudeSession {
|
|
|
588
603
|
// `typesafe:'off'` on a query (the live skin test) keeps this CLI's hooks
|
|
589
604
|
// from paying for judgments: they read the kill switch from their env.
|
|
590
605
|
// (Panel sessions: the CLI reports running / idle / requires_action only when
|
|
591
|
-
// asked to; `idle` is its own word that a turn is over. See _noteSessionState.
|
|
592
|
-
|
|
606
|
+
// asked to; `idle` is its own word that a turn is over. See _noteSessionState.
|
|
607
|
+
// SYNABUN_PANEL_SESSION tells the user-level SynaBun hooks that the panel greets here, not they.)
|
|
608
|
+
env: { ...cleanEnv(), ...(this.typesafeOff ? { SYNABUN_TYPESAFE: 'off' } : {}), ...(sessionOpts.env || {}), ...(accountEnv || {}), ...(this.panel ? { CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS: '1', SYNABUN_PANEL_SESSION: '1' } : {}) },
|
|
593
609
|
abortController: this.abortController,
|
|
594
610
|
stderr: (text) => {
|
|
595
611
|
const t = String(text || '').trim();
|
|
@@ -629,6 +645,16 @@ export class ClaudeSession {
|
|
|
629
645
|
// Resuming a session whose prompt cache has expired pays to write it
|
|
630
646
|
// again: the CLI says how much at SessionStart.
|
|
631
647
|
options.hooks = mergeHookMatchers(options.hooks, {
|
|
648
|
+
// The greeting SynaBun showed when this conversation opened (lib/greeting/): said to the
|
|
649
|
+
// model once, with the first prompt, as background. The model is never asked to greet.
|
|
650
|
+
UserPromptSubmit: [{
|
|
651
|
+
hooks: [async () => {
|
|
652
|
+
const note = gen === this._queryGen ? this._greetingNote : '';
|
|
653
|
+
if (!note) return {};
|
|
654
|
+
this._greetingNote = '';
|
|
655
|
+
return { hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext: note } };
|
|
656
|
+
}],
|
|
657
|
+
}],
|
|
632
658
|
SessionStart: [{
|
|
633
659
|
hooks: [async (input) => {
|
|
634
660
|
if (gen === this._queryGen && input?.prompt_cache_likely_expired === true && Number(input?.estimated_cache_write_usd) > 0) {
|
|
@@ -730,54 +756,26 @@ export class ClaudeSession {
|
|
|
730
756
|
// (Which of the session's MCP connections is SynaBun's is asked of the live process when a tool of one is called.)
|
|
731
757
|
applyTemporaryOptions(options, { mcpUrl: deps.mcpUrl || '', mcpStatus: () => this.q?.mcpServerStatus?.() });
|
|
732
758
|
this._tempPlansDirs = plansDirsOf(options.env, { cwd: workDir, settings: options.settings });
|
|
733
|
-
if (!this._tempSince)
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
// 1. an explicit override — cli-config.json → "claude-skin": { "sdkExecutable": "…" },
|
|
737
|
-
// either a .js entrypoint (launched via node) or a native binary path;
|
|
738
|
-
// 2. the installed CLI we fell back to after the bundled one failed to launch;
|
|
739
|
-
// 3. the installed CLI when it is newer than the bundled one. The model picker
|
|
740
|
-
// lists the installed CLI's models, and an older binary resolves the same
|
|
741
|
-
// alias to an older model (alignedClaudeExecutable, claude-model-catalog.js);
|
|
742
|
-
// 4. the SDK's bundled, version-matched CLI.
|
|
743
|
-
//
|
|
744
|
-
// The SDK uses pathToClaudeCodeExecutable verbatim with zero validation, so
|
|
745
|
-
// everything is vetted here first — notably a bare command name, which would
|
|
746
|
-
// ENOENT under the SDK's spawn(shell:false).
|
|
747
|
-
const sdkExec = deps.sdkExecutable;
|
|
748
|
-
const override = resolveClaudeExecutableOverride(sdkExec);
|
|
749
|
-
this._alignedBin = null;
|
|
750
|
-
let runtimeLabel = 'bundled';
|
|
751
|
-
if (override.path) {
|
|
752
|
-
options.pathToClaudeCodeExecutable = override.path;
|
|
753
|
-
runtimeLabel = 'override';
|
|
754
|
-
} else if (sdkExec) {
|
|
755
|
-
log('ignoring sdkExecutable override:', override.reason);
|
|
756
|
-
this.send({ type: 'stderr', text: `Ignoring sdkExecutable override — ${override.reason}` });
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
if (!options.pathToClaudeCodeExecutable) {
|
|
760
|
-
let aligned = null;
|
|
761
|
-
if (!this._fallbackBin) {
|
|
762
|
-
try { aligned = deps.alignedClaudeBin?.() || null; } catch { aligned = null; }
|
|
763
|
-
}
|
|
764
|
-
if (this._fallbackBin) {
|
|
765
|
-
// A previous turn proved the bundled binary unusable; stay on the CLI we
|
|
766
|
-
// already fell back to rather than re-failing every turn.
|
|
767
|
-
options.pathToClaudeCodeExecutable = this._fallbackBin;
|
|
768
|
-
runtimeLabel = 'fallback';
|
|
769
|
-
} else if (aligned) {
|
|
770
|
-
options.pathToClaudeCodeExecutable = aligned;
|
|
771
|
-
this._alignedBin = aligned;
|
|
772
|
-
runtimeLabel = aligned;
|
|
773
|
-
} else {
|
|
774
|
-
// Called for its side effect only: this stats the binary the SDK is about
|
|
775
|
-
// to resolve and restores the execute bit if it is missing. We
|
|
776
|
-
// deliberately do NOT pass the resolved path on — letting the SDK resolve
|
|
777
|
-
// for itself keeps us correct even if its resolution logic changes.
|
|
778
|
-
claudeRuntime();
|
|
759
|
+
if (!this._tempSince) {
|
|
760
|
+
this._tempPlansBefore = snapshotPlanFiles(this._tempPlansDirs);
|
|
761
|
+
this._tempSince = Date.now();
|
|
779
762
|
}
|
|
780
763
|
}
|
|
764
|
+
// The executable resolved at the top of this call. The SDK uses
|
|
765
|
+
// pathToClaudeCodeExecutable verbatim with zero validation, so it was vetted
|
|
766
|
+
// there — notably a bare command name, which would ENOENT under the SDK's
|
|
767
|
+
// spawn(shell:false).
|
|
768
|
+
let runtimeLabel = 'unset';
|
|
769
|
+
this._claudeExecutable = null;
|
|
770
|
+
if (executable?.ignored) {
|
|
771
|
+
log('ignoring sdkExecutable override:', executable.ignored);
|
|
772
|
+
this.send({ type: 'stderr', text: `Ignoring sdkExecutable override — ${executable.ignored}` });
|
|
773
|
+
}
|
|
774
|
+
if (executable?.path) {
|
|
775
|
+
options.pathToClaudeCodeExecutable = executable.path;
|
|
776
|
+
this._claudeExecutable = executable.path;
|
|
777
|
+
runtimeLabel = executable.source === 'override' ? 'override' : executable.path;
|
|
778
|
+
}
|
|
781
779
|
|
|
782
780
|
if (warm) {
|
|
783
781
|
// Start the process now; hand it the input queue when the first prompt comes.
|
|
@@ -1096,7 +1094,7 @@ export class ClaudeSession {
|
|
|
1096
1094
|
// stay owed and are swept once more when it can no longer be alive.
|
|
1097
1095
|
_removeTemporaryPlans() {
|
|
1098
1096
|
if (!this._tempPlans?.size) return;
|
|
1099
|
-
const owed = { plansDirs: this._tempPlansDirs, since: this._tempSince, ended: false, last: false };
|
|
1097
|
+
const owed = { plansDirs: this._tempPlansDirs, since: this._tempSince, before: this._tempPlansBefore, ended: false, last: false };
|
|
1100
1098
|
for (const path of this._tempPlans) _temporaryPlansOwed.set(path, owed);
|
|
1101
1099
|
this._tempPlans.clear();
|
|
1102
1100
|
Promise.resolve(this.pumpPromise).catch(() => {}).then(() => {
|
|
@@ -1115,6 +1113,7 @@ export class ClaudeSession {
|
|
|
1115
1113
|
this._tempLive = false;
|
|
1116
1114
|
this._tempOver = false;
|
|
1117
1115
|
this._tempSince = 0;
|
|
1116
|
+
this._tempPlansBefore = null;
|
|
1118
1117
|
}
|
|
1119
1118
|
|
|
1120
1119
|
// Whether this message makes, keeps or may not make the conversation a
|
|
@@ -1256,94 +1255,18 @@ export class ClaudeSession {
|
|
|
1256
1255
|
}
|
|
1257
1256
|
|
|
1258
1257
|
/**
|
|
1259
|
-
* The
|
|
1258
|
+
* The user's Claude Code would not start.
|
|
1260
1259
|
*
|
|
1261
1260
|
* The SDK's own message for this always blames a musl/glibc mismatch, which is
|
|
1262
|
-
* only ever right on Linux —
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1265
|
-
*
|
|
1266
|
-
* Recovery is: re-stat and repair → retry once → fall back to the user's
|
|
1267
|
-
* installed CLI with a visible notice → give up with an accurate diagnosis.
|
|
1261
|
+
* only ever right on Linux — elsewhere the cause is a missing execute bit, a
|
|
1262
|
+
* quarantined download, a build for another processor or a file that is gone.
|
|
1263
|
+
* There is no other runtime to move to (SynaBun carries none), so the turn
|
|
1264
|
+
* ends with what is wrong with that installation and how to fix it.
|
|
1268
1265
|
*/
|
|
1269
1266
|
_recoverNativeRuntime(err) {
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
// its own repair path below if it fails too.
|
|
1274
|
-
if (this._alignedBin) {
|
|
1275
|
-
const failed = this._alignedBin;
|
|
1276
|
-
this._alignedBin = null;
|
|
1277
|
-
markAlignedClaudeExecutableFailed(failed);
|
|
1278
|
-
log(`aligned CLI failed to launch (${failed}) — using the bundled runtime`);
|
|
1279
|
-
this.sendEvent({
|
|
1280
|
-
type: 'system',
|
|
1281
|
-
subtype: 'runtime_notice',
|
|
1282
|
-
level: 'warn',
|
|
1283
|
-
message: `Your installed Claude CLI (${failed}) failed to launch; using the bundled runtime instead.`,
|
|
1284
|
-
});
|
|
1285
|
-
this._recreateQuery(prompt);
|
|
1286
|
-
return;
|
|
1287
|
-
}
|
|
1288
|
-
// The cached verdict predates the failure; re-stat so a repair performed by
|
|
1289
|
-
// another session (or the boot sweep) is visible.
|
|
1290
|
-
clearNativeBinaryCache();
|
|
1291
|
-
const runtime = claudeRuntime();
|
|
1292
|
-
|
|
1293
|
-
let fallbackBin = this._fallbackBin;
|
|
1294
|
-
if (!fallbackBin) {
|
|
1295
|
-
// getClaudeBin()'s last resort is the bare string 'claude'. The SDK spawns
|
|
1296
|
-
// with shell:false, so a bare name is a guaranteed ENOENT — the override
|
|
1297
|
-
// validator rejects it, leaving fallbackBin null and giving the user a
|
|
1298
|
-
// real diagnosis instead of a second, more confusing failure.
|
|
1299
|
-
const candidate = resolveClaudeExecutableOverride(deps.getClaudeBin?.());
|
|
1300
|
-
if (candidate.ok && candidate.path) fallbackBin = candidate.path;
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
const plan = planRuntimeRecovery({
|
|
1304
|
-
err,
|
|
1305
|
-
runtime,
|
|
1306
|
-
fallbackBin,
|
|
1307
|
-
alreadyTried: this._nativeRepairTried,
|
|
1308
|
-
});
|
|
1309
|
-
log(`native runtime recovery: action=${plan.action} state=${runtime.state} kind=${plan.kind}`);
|
|
1310
|
-
|
|
1311
|
-
if (plan.action === 'retry') {
|
|
1312
|
-
this._nativeRepairTried = true;
|
|
1313
|
-
this.sendEvent({ type: 'system', subtype: 'runtime_notice', level: 'warn', message: plan.message });
|
|
1314
|
-
this._recreateQuery(prompt);
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
if (plan.action === 'fallback') {
|
|
1319
|
-
this._fallbackBin = fallbackBin;
|
|
1320
|
-
this.sendEvent({ type: 'system', subtype: 'runtime_notice', level: 'warn', message: plan.message });
|
|
1321
|
-
// Report-only: the fallback CLI may be a different version than the SDK
|
|
1322
|
-
// was built against, and alias ids like "opus[1m]" resolve per-binary — so
|
|
1323
|
-
// a picked model can silently launch as another version.
|
|
1324
|
-
this._announceSkew(fallbackBin);
|
|
1325
|
-
this._recreateQuery(prompt);
|
|
1326
|
-
return;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
this._finishTurnWithError(plan.message);
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
_announceSkew(bin) {
|
|
1333
|
-
Promise.resolve()
|
|
1334
|
-
.then(() => checkClaudeCliSkew(bin, { log: () => {} }))
|
|
1335
|
-
.then((skew) => {
|
|
1336
|
-
if (!skew?.skewed || this.destroyed) return;
|
|
1337
|
-
this.sendEvent({
|
|
1338
|
-
type: 'system',
|
|
1339
|
-
subtype: 'runtime_notice',
|
|
1340
|
-
level: 'warn',
|
|
1341
|
-
message: `Version skew: your installed Claude CLI is ${skew.discovered}, but the bundled `
|
|
1342
|
-
+ `runtime is ${skew.bundled}. Model aliases and effort levels resolve per-binary, so `
|
|
1343
|
-
+ 'behaviour may differ until the bundled binary is repaired.',
|
|
1344
|
-
});
|
|
1345
|
-
})
|
|
1346
|
-
.catch(() => {});
|
|
1267
|
+
const dx = diagnoseLaunchFailure({ err, executable: this._claudeExecutable });
|
|
1268
|
+
log(`Claude Code failed to launch: kind=${dx.kind} executable=${this._claudeExecutable || 'unset'}`);
|
|
1269
|
+
this._finishTurnWithError(dx.message);
|
|
1347
1270
|
}
|
|
1348
1271
|
|
|
1349
1272
|
_pushUserText(text, images, { human = false } = {}) {
|
|
@@ -2222,7 +2145,7 @@ export class ClaudeSession {
|
|
|
2222
2145
|
// AskUserQuestion answers arrive as updatedInput {questions, answers} from the
|
|
2223
2146
|
// existing frontend card. The CLI's AskUserQuestion tool reads ONLY the
|
|
2224
2147
|
// top-level `answers` map, looked up by each question's exact `question` text
|
|
2225
|
-
// (verified against the
|
|
2148
|
+
// (verified against the CLI itself: missing/empty map → "The user did not
|
|
2226
2149
|
// answer the questions."). So: keep the original questions, pass the answers
|
|
2227
2150
|
// map through, and re-key any answer the panel stored under a fallback key
|
|
2228
2151
|
// (text/header) back onto the question text.
|
|
@@ -2904,6 +2827,17 @@ export class ClaudeSession {
|
|
|
2904
2827
|
} catch {}
|
|
2905
2828
|
}
|
|
2906
2829
|
|
|
2830
|
+
// The panel echoes the id of the greeting it showed when this conversation opened: the model is
|
|
2831
|
+
// told once, with this prompt (the UserPromptSubmit hook in _startQuery). A slash command takes none.
|
|
2832
|
+
// (A prompt the person typed in the panel is also them being here, whether or not the user-level hooks are installed.)
|
|
2833
|
+
if (this.panel && !warmOnly && msg.typed === true && typeof prompt === 'string' && prompt.trim() && typeof deps.greetingActivity === 'function') {
|
|
2834
|
+
try { deps.greetingActivity({ cwd: cwd || this.cwd || null, words: prompt, temporary: this.temporary === true }); } catch { /* the prompt goes on */ }
|
|
2835
|
+
}
|
|
2836
|
+
if (this.panel && !warmOnly && typeof msg.greetingId === 'string' && typeof deps.greetingNote === 'function') {
|
|
2837
|
+
try { this._greetingNote = String(deps.greetingNote(msg.greetingId, { skip: typeof prompt === 'string' && prompt.trimStart().startsWith('/') }) || ''); }
|
|
2838
|
+
catch { this._greetingNote = ''; }
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2907
2841
|
// SynaBun skill injection runs FIRST; unrecognized /commands pass through to the CLI
|
|
2908
2842
|
if (prompt && prompt.startsWith('/')) {
|
|
2909
2843
|
try {
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// ── Which Claude Code runs: the user's own installation ──
|
|
2
|
+
//
|
|
3
|
+
// Claude Code is installed by the user, separately from SynaBun (the native
|
|
4
|
+
// installer, Homebrew, npm). Nothing in SynaBun carries a copy: the Claude
|
|
5
|
+
// Agent SDK is installed without the executable it would otherwise bring (see
|
|
6
|
+
// lib/external-tools.js at the package root), so every SDK call has to be told
|
|
7
|
+
// which executable to start. This module is where that answer comes from, for
|
|
8
|
+
// the side panel, the Assistant's Claude brain, native loops, session titles
|
|
9
|
+
// and the model probe alike:
|
|
10
|
+
//
|
|
11
|
+
// resolveClaudeLauncher what a terminal or a shell would start: the
|
|
12
|
+
// user's configured command, else the first
|
|
13
|
+
// `claude` on PATH that is not inside SynaBun
|
|
14
|
+
// resolveClaudeSdkExecutable what the SDK can start. It spawns with
|
|
15
|
+
// shell:false, so an npm command file on Windows
|
|
16
|
+
// is followed to the executable behind it
|
|
17
|
+
//
|
|
18
|
+
// A missing installation is an ordinary state, not a failure: both answer with
|
|
19
|
+
// `path: null` and the caller says CLAUDE_NOT_INSTALLED.
|
|
20
|
+
//
|
|
21
|
+
// Every dependency is injectable (platform, PATH, the file system), so Windows
|
|
22
|
+
// resolution is tested from any host. Nothing here throws.
|
|
23
|
+
|
|
24
|
+
import { accessSync, constants, existsSync, statSync } from 'node:fs';
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
import { getAugmentedPath } from './augmented-path.js';
|
|
27
|
+
import { resolveClaudeExecutableOverride } from './native-binary-runtime.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* What a session says when no Claude Code is installed. The words "Claude CLI
|
|
31
|
+
* not found" are what the side panel shows its install help on.
|
|
32
|
+
*/
|
|
33
|
+
export const CLAUDE_NOT_INSTALLED = 'Claude CLI not found. Claude Code is installed separately from SynaBun: install it, then send your message again.';
|
|
34
|
+
|
|
35
|
+
/** A real executable first, then the command files a shell can run. */
|
|
36
|
+
const WINDOWS_LAUNCHER_ORDER = ['.exe', '.cmd', '.bat', '.ps1'];
|
|
37
|
+
|
|
38
|
+
const pathFor = (platform) => (platform === 'win32' ? path.win32 : path.posix);
|
|
39
|
+
|
|
40
|
+
function unique(values, pathImpl, insensitive) {
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const value of values) {
|
|
44
|
+
const text = String(value || '').trim();
|
|
45
|
+
if (!text) continue;
|
|
46
|
+
const normal = pathImpl.normalize(text);
|
|
47
|
+
const key = insensitive ? normal.toLowerCase() : normal;
|
|
48
|
+
if (seen.has(key)) continue;
|
|
49
|
+
seen.add(key);
|
|
50
|
+
out.push(normal);
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The launcher Windows should start, from a list in PATH order (as `where`
|
|
57
|
+
* prints it, or findOnPath below). PATH order decides between folders; inside
|
|
58
|
+
* one folder a real executable beats a command file, and npm's extensionless
|
|
59
|
+
* shell script (which Windows cannot start) is only ever the last resort.
|
|
60
|
+
*/
|
|
61
|
+
export function selectWindowsLauncher(launchers = [], accept = () => true) {
|
|
62
|
+
const accepted = unique(launchers, path.win32, true).filter(accept);
|
|
63
|
+
const folders = new Map();
|
|
64
|
+
for (const launcher of accepted) {
|
|
65
|
+
const folder = path.win32.dirname(launcher).toLowerCase();
|
|
66
|
+
if (!folders.has(folder)) folders.set(folder, []);
|
|
67
|
+
folders.get(folder).push(launcher);
|
|
68
|
+
}
|
|
69
|
+
for (const group of folders.values()) {
|
|
70
|
+
for (const extension of WINDOWS_LAUNCHER_ORDER) {
|
|
71
|
+
const hit = group.find(launcher => launcher.toLowerCase().endsWith(extension));
|
|
72
|
+
if (hit) return hit;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return accepted[0] || null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function defaultIsLaunchable(file, platform) {
|
|
79
|
+
try {
|
|
80
|
+
if (!statSync(file).isFile()) return false;
|
|
81
|
+
if (platform !== 'win32') accessSync(file, constants.X_OK);
|
|
82
|
+
return true;
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** PATH without any `node_modules/.bin` folder: a dependency's command is never the user's tool. */
|
|
89
|
+
export function withoutPackageBins(pathValue, platform = process.platform) {
|
|
90
|
+
const delimiter = platform === 'win32' ? ';' : ':';
|
|
91
|
+
return String(pathValue || '').split(delimiter)
|
|
92
|
+
.filter(entry => entry && !/[\\/]node_modules[\\/]\.bin[\\/]?$/i.test(entry))
|
|
93
|
+
.join(delimiter);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Every file a command name resolves to, in PATH order, read from the file
|
|
98
|
+
* system (no `which`, no shell: a folder with a space in its name is just a
|
|
99
|
+
* folder). On Windows each folder is tried with the launcher extensions, then
|
|
100
|
+
* bare.
|
|
101
|
+
*/
|
|
102
|
+
export function findOnPath(command, {
|
|
103
|
+
platform = process.platform,
|
|
104
|
+
pathValue = getAugmentedPath(),
|
|
105
|
+
isLaunchable = defaultIsLaunchable,
|
|
106
|
+
} = {}) {
|
|
107
|
+
const name = String(command || '').trim();
|
|
108
|
+
if (!name) return [];
|
|
109
|
+
const pathImpl = pathFor(platform);
|
|
110
|
+
const windows = platform === 'win32';
|
|
111
|
+
const names = windows && !pathImpl.extname(name) ? [...WINDOWS_LAUNCHER_ORDER.map(extension => name + extension), name] : [name];
|
|
112
|
+
const found = [];
|
|
113
|
+
for (const folder of String(pathValue || '').split(windows ? ';' : ':')) {
|
|
114
|
+
if (!folder) continue;
|
|
115
|
+
for (const candidate of names) {
|
|
116
|
+
const file = pathImpl.join(folder, candidate);
|
|
117
|
+
if (isLaunchable(file, platform)) found.push(file);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return unique(found, pathImpl, windows);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The Claude Code a terminal would start.
|
|
125
|
+
*
|
|
126
|
+
* configured cli-config.json → "claude-code": { "command": "…" } (Settings > Terminal):
|
|
127
|
+
* a path is taken as it is, a name is looked up on PATH
|
|
128
|
+
* path the first `claude` on PATH
|
|
129
|
+
*
|
|
130
|
+
* Never a file inside SynaBun (`isInsideSynabun`) and never one from a
|
|
131
|
+
* `node_modules/.bin` folder on PATH: a copy that came with a dependency must
|
|
132
|
+
* not stand in for the user's own.
|
|
133
|
+
*
|
|
134
|
+
* @returns {{path: string|null, source: 'configured'|'path'|'missing', rejected: string[]}}
|
|
135
|
+
*/
|
|
136
|
+
export function resolveClaudeLauncher({
|
|
137
|
+
configured = '',
|
|
138
|
+
platform = process.platform,
|
|
139
|
+
pathValue = getAugmentedPath(),
|
|
140
|
+
isInsideSynabun = () => false,
|
|
141
|
+
exists = existsSync,
|
|
142
|
+
isLaunchable = defaultIsLaunchable,
|
|
143
|
+
} = {}) {
|
|
144
|
+
const pathImpl = pathFor(platform);
|
|
145
|
+
const windows = platform === 'win32';
|
|
146
|
+
const rejected = [];
|
|
147
|
+
const outside = (file) => {
|
|
148
|
+
if (!isInsideSynabun(file)) return true;
|
|
149
|
+
rejected.push(file);
|
|
150
|
+
return false;
|
|
151
|
+
};
|
|
152
|
+
const lookup = (command) => {
|
|
153
|
+
const hits = findOnPath(command, { platform, pathValue: withoutPackageBins(pathValue, platform), isLaunchable }).filter(outside);
|
|
154
|
+
return (windows ? selectWindowsLauncher(hits) : hits[0]) || null;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const wanted = String(configured || '').trim();
|
|
158
|
+
if (wanted && wanted !== 'claude') {
|
|
159
|
+
const isPath = wanted.includes('/') || (windows && wanted.includes('\\'));
|
|
160
|
+
if (isPath) {
|
|
161
|
+
if (exists(wanted) && outside(wanted)) return { path: pathImpl.normalize(wanted), source: 'configured', rejected };
|
|
162
|
+
} else {
|
|
163
|
+
const hit = lookup(wanted);
|
|
164
|
+
if (hit) return { path: hit, source: 'configured', rejected };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const hit = lookup('claude');
|
|
169
|
+
return hit ? { path: hit, source: 'path', rejected } : { path: null, source: 'missing', rejected };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Where the executable behind an npm command file is, most likely first. npm
|
|
174
|
+
* puts `claude.cmd` next to `node_modules\@anthropic-ai\claude-code`, whose
|
|
175
|
+
* `bin\claude.exe` is the program (older releases: `cli.js`, run by Node). A
|
|
176
|
+
* `.bin` folder has the package one level up instead.
|
|
177
|
+
*/
|
|
178
|
+
export function windowsClaudeTargets(launcher) {
|
|
179
|
+
const pathImpl = path.win32;
|
|
180
|
+
const folder = pathImpl.dirname(String(launcher || ''));
|
|
181
|
+
const roots = [pathImpl.join(folder, 'node_modules')];
|
|
182
|
+
if (pathImpl.basename(folder).toLowerCase() === '.bin') roots.push(pathImpl.dirname(folder));
|
|
183
|
+
return roots.flatMap((root) => {
|
|
184
|
+
const packageDir = pathImpl.join(root, '@anthropic-ai', 'claude-code');
|
|
185
|
+
return [pathImpl.join(packageDir, 'bin', 'claude.exe'), pathImpl.join(packageDir, 'cli.js')];
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The executable an Agent SDK call is given as `pathToClaudeCodeExecutable`.
|
|
191
|
+
*
|
|
192
|
+
* override cli-config.json → "claude-skin": { "sdkExecutable": "…" }, when it is usable
|
|
193
|
+
* installed the user's Claude Code (`launcher`, from resolveClaudeLauncher)
|
|
194
|
+
*
|
|
195
|
+
* The SDK starts this path itself, without a shell, so it has to be a program
|
|
196
|
+
* or a script: on Windows a `.cmd`, `.bat` or `.ps1` launcher is followed to
|
|
197
|
+
* what it runs. `path: null` means there is nothing to start; `reason` says
|
|
198
|
+
* why in a sentence a person can act on, `ignored` why an override was passed
|
|
199
|
+
* over.
|
|
200
|
+
*
|
|
201
|
+
* @returns {{path: string|null, source: 'override'|'installed'|'missing', kind: string|null, reason: string|null, ignored: string|null, launcher: string|null}}
|
|
202
|
+
*/
|
|
203
|
+
export function resolveClaudeSdkExecutable({
|
|
204
|
+
launcher = null,
|
|
205
|
+
sdkExecutable = null,
|
|
206
|
+
platform = process.platform,
|
|
207
|
+
exists = existsSync,
|
|
208
|
+
isInsideSynabun = () => false,
|
|
209
|
+
validate = resolveClaudeExecutableOverride,
|
|
210
|
+
} = {}) {
|
|
211
|
+
const answer = (fields) => ({ path: null, source: 'missing', kind: null, reason: null, ignored: null, launcher: launcher || null, ...fields });
|
|
212
|
+
let ignored = null;
|
|
213
|
+
|
|
214
|
+
const explicit = typeof sdkExecutable === 'string' ? sdkExecutable.trim() : '';
|
|
215
|
+
if (explicit) {
|
|
216
|
+
const verdict = validate(explicit, { platform });
|
|
217
|
+
if (verdict.ok && verdict.path) return answer({ path: verdict.path, source: 'override', kind: verdict.kind });
|
|
218
|
+
ignored = verdict.reason || `Not usable: ${explicit}`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const installed = typeof launcher === 'string' ? launcher.trim() : '';
|
|
222
|
+
// A bare name is what "nothing was found" looks like to older callers.
|
|
223
|
+
if (!installed || !(installed.includes('/') || installed.includes('\\'))) return answer({ reason: CLAUDE_NOT_INSTALLED, ignored });
|
|
224
|
+
|
|
225
|
+
const candidates = platform === 'win32' && !/\.exe$/i.test(installed) && !/\.[cm]?js$/i.test(installed)
|
|
226
|
+
? windowsClaudeTargets(installed).filter(file => exists(file))
|
|
227
|
+
: [installed];
|
|
228
|
+
let refusal = null;
|
|
229
|
+
for (const candidate of candidates) {
|
|
230
|
+
if (isInsideSynabun(candidate)) { refusal = `${candidate} is inside SynaBun, not an installation of Claude Code`; continue; }
|
|
231
|
+
const verdict = validate(candidate, { platform });
|
|
232
|
+
if (verdict.ok && verdict.path) return answer({ path: verdict.path, source: 'installed', kind: verdict.kind, ignored });
|
|
233
|
+
refusal = verdict.reason || `Not usable: ${candidate}`;
|
|
234
|
+
}
|
|
235
|
+
return answer({
|
|
236
|
+
reason: refusal
|
|
237
|
+
? `Claude Code was found at ${installed}, but it cannot be started from there: ${refusal}.`
|
|
238
|
+
: `Claude Code was found at ${installed}, but not the program that command runs. Reinstall Claude Code, or name its executable in cli-config.json ("claude-skin": { "sdkExecutable": "…" }).`,
|
|
239
|
+
ignored,
|
|
240
|
+
});
|
|
241
|
+
}
|