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,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SynaBun — external tools stay external
|
|
3
|
+
*
|
|
4
|
+
* Claude Code, Codex, OpenCode and Gemini CLI are programs of their own. The
|
|
5
|
+
* user installs them; SynaBun finds what is installed (PATH, Homebrew, npm, the
|
|
6
|
+
* native installers' folders) and talks to it, through a thin JavaScript SDK
|
|
7
|
+
* where there is one. It never installs, ships or runs a copy of its own.
|
|
8
|
+
*
|
|
9
|
+
* npm has no way to say "this SDK, without the program it carries": the Claude
|
|
10
|
+
* Agent SDK brings the Claude Code executable as a per-platform optional
|
|
11
|
+
* dependency, and @openai/codex-sdk depends on the whole Codex CLI. So the rule
|
|
12
|
+
* is kept in three places, all reading the one list below:
|
|
13
|
+
*
|
|
14
|
+
* the lockfiles hold none of these packages and no edge to one
|
|
15
|
+
* (scripts/strip-external-tools.mjs), so npm never
|
|
16
|
+
* downloads them
|
|
17
|
+
* an install removes any that came anyway (the neural-interface
|
|
18
|
+
* postinstall, the server at start)
|
|
19
|
+
* a packaged build removes them from what it stages and refuses a bundle
|
|
20
|
+
* that holds one (packaging/lib/stage.mjs, verify.mjs)
|
|
21
|
+
*
|
|
22
|
+
* The SDKs stay: every call hands them the user's executable
|
|
23
|
+
* (pathToClaudeCodeExecutable, codexPathOverride), so the payload they would
|
|
24
|
+
* otherwise look for is never needed.
|
|
25
|
+
*
|
|
26
|
+
* Only node:fs and node:path here: the install scripts import this on any
|
|
27
|
+
* Node, before a single dependency exists.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
31
|
+
import { join } from 'node:path';
|
|
32
|
+
|
|
33
|
+
const PLATFORMS = '(?:darwin|linux|win32|windows|android)';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Each tool: the command the user runs, the packages that ARE the tool (never
|
|
37
|
+
* a dependency of SynaBun), and how its per-platform payload packages are
|
|
38
|
+
* named. A name is what a package is installed as, under node_modules.
|
|
39
|
+
*/
|
|
40
|
+
export const EXTERNAL_TOOLS = Object.freeze([
|
|
41
|
+
Object.freeze({
|
|
42
|
+
id: 'claude-code',
|
|
43
|
+
label: 'Claude Code',
|
|
44
|
+
command: 'claude',
|
|
45
|
+
packages: Object.freeze(['@anthropic-ai/claude-code']),
|
|
46
|
+
// The CLI's own platform packages, and the same executable as the Agent SDK carries it.
|
|
47
|
+
patterns: Object.freeze([
|
|
48
|
+
new RegExp(`^@anthropic-ai/claude-code-${PLATFORMS}-`),
|
|
49
|
+
new RegExp(`^@anthropic-ai/claude-agent-sdk-${PLATFORMS}-`),
|
|
50
|
+
]),
|
|
51
|
+
}),
|
|
52
|
+
Object.freeze({
|
|
53
|
+
id: 'codex',
|
|
54
|
+
label: 'Codex',
|
|
55
|
+
command: 'codex',
|
|
56
|
+
packages: Object.freeze(['@openai/codex']),
|
|
57
|
+
// (@openai/codex-sdk is the JavaScript client and is not matched.)
|
|
58
|
+
patterns: Object.freeze([new RegExp(`^@openai/codex-${PLATFORMS}-`)]),
|
|
59
|
+
}),
|
|
60
|
+
Object.freeze({
|
|
61
|
+
id: 'opencode',
|
|
62
|
+
label: 'OpenCode',
|
|
63
|
+
command: 'opencode',
|
|
64
|
+
packages: Object.freeze(['opencode-ai']),
|
|
65
|
+
// (@opencode-ai/sdk is the JavaScript client and is not matched.)
|
|
66
|
+
patterns: Object.freeze([new RegExp(`^opencode-${PLATFORMS}-`)]),
|
|
67
|
+
}),
|
|
68
|
+
Object.freeze({
|
|
69
|
+
id: 'gemini',
|
|
70
|
+
label: 'Gemini CLI',
|
|
71
|
+
command: 'gemini',
|
|
72
|
+
packages: Object.freeze(['@google/gemini-cli', '@google/gemini-cli-core']),
|
|
73
|
+
patterns: Object.freeze([]),
|
|
74
|
+
}),
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
/** The file names a tool's command can have in a `.bin` folder or on disk. */
|
|
78
|
+
const COMMAND_SUFFIXES = ['', '.cmd', '.ps1', '.bat', '.exe'];
|
|
79
|
+
const COMMAND_FILES = new Map(EXTERNAL_TOOLS.flatMap(tool => COMMAND_SUFFIXES.map(suffix => [`${tool.command}${suffix}`, tool])));
|
|
80
|
+
|
|
81
|
+
/** The tool a package name belongs to, or null: `@openai/codex` yes, `@openai/codex-sdk` no. */
|
|
82
|
+
export function externalToolOf(packageName) {
|
|
83
|
+
const name = String(packageName || '');
|
|
84
|
+
if (!name) return null;
|
|
85
|
+
return EXTERNAL_TOOLS.find(tool => tool.packages.includes(name) || tool.patterns.some(pattern => pattern.test(name))) || null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The package a lockfile path installs: what follows its last `node_modules/`. */
|
|
89
|
+
export function packageNameOfLockPath(path) {
|
|
90
|
+
const value = String(path || '').replace(/\\/g, '/');
|
|
91
|
+
const at = value.lastIndexOf('node_modules/');
|
|
92
|
+
return at < 0 ? '' : value.slice(at + 'node_modules/'.length);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const EDGE_FIELDS = ['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta', 'devDependencies'];
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* What a lockfile (package-lock.json, or the hidden node_modules/.package-lock.json)
|
|
99
|
+
* still holds of external tools: `packages` are the entries that would be
|
|
100
|
+
* installed, `edges` the dependencies other entries declare on one.
|
|
101
|
+
*/
|
|
102
|
+
export function externalToolsInLock(lock) {
|
|
103
|
+
const packages = [];
|
|
104
|
+
const edges = [];
|
|
105
|
+
for (const [path, entry] of Object.entries(lock?.packages || {})) {
|
|
106
|
+
const tool = externalToolOf(packageNameOfLockPath(path));
|
|
107
|
+
if (tool) { packages.push({ path, tool: tool.id, version: entry?.version || null }); continue; }
|
|
108
|
+
for (const field of EDGE_FIELDS) {
|
|
109
|
+
for (const name of Object.keys(entry?.[field] || {})) {
|
|
110
|
+
const wanted = externalToolOf(name);
|
|
111
|
+
if (wanted) edges.push({ from: path || '(root)', field, name, tool: wanted.id });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { packages, edges };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Take every external tool out of a lockfile object, in place: its entries, and
|
|
120
|
+
* the edges that would make npm fetch them again. Returns what was removed.
|
|
121
|
+
* A lockfile left this way installs the SDKs and nothing they would carry.
|
|
122
|
+
*/
|
|
123
|
+
export function stripExternalToolsFromLock(lock) {
|
|
124
|
+
const found = externalToolsInLock(lock);
|
|
125
|
+
for (const item of found.packages) delete lock.packages[item.path];
|
|
126
|
+
for (const edge of found.edges) {
|
|
127
|
+
const entry = lock.packages[edge.from === '(root)' ? '' : edge.from];
|
|
128
|
+
if (!entry?.[edge.field]) continue;
|
|
129
|
+
delete entry[edge.field][edge.name];
|
|
130
|
+
if (!Object.keys(entry[edge.field]).length) delete entry[edge.field];
|
|
131
|
+
}
|
|
132
|
+
return found;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const list = (folder) => { try { return readdirSync(folder, { withFileTypes: true }); } catch { return []; } };
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Every external-tool package and command installed under one node_modules
|
|
139
|
+
* folder, nested trees included: [{ kind: 'package' | 'command', name, tool, path }].
|
|
140
|
+
*/
|
|
141
|
+
export function externalToolsInstalledIn(nodeModules, { depth = 6 } = {}) {
|
|
142
|
+
const found = [];
|
|
143
|
+
const visitModules = (folder, left) => {
|
|
144
|
+
for (const entry of list(folder)) {
|
|
145
|
+
if (entry.name === '.bin') {
|
|
146
|
+
for (const file of list(join(folder, '.bin'))) {
|
|
147
|
+
const tool = COMMAND_FILES.get(file.name);
|
|
148
|
+
if (tool) found.push({ kind: 'command', name: file.name, tool: tool.id, path: join(folder, '.bin', file.name) });
|
|
149
|
+
}
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (entry.name.startsWith('.') || !(entry.isDirectory() || entry.isSymbolicLink())) continue;
|
|
153
|
+
const names = entry.name.startsWith('@')
|
|
154
|
+
? list(join(folder, entry.name)).filter(scoped => scoped.isDirectory() || scoped.isSymbolicLink()).map(scoped => `${entry.name}/${scoped.name}`)
|
|
155
|
+
: [entry.name];
|
|
156
|
+
for (const name of names) {
|
|
157
|
+
const path = join(folder, ...name.split('/'));
|
|
158
|
+
const tool = externalToolOf(name);
|
|
159
|
+
if (tool) { found.push({ kind: 'package', name, tool: tool.id, path }); continue; }
|
|
160
|
+
if (left > 0 && existsSync(join(path, 'node_modules'))) visitModules(join(path, 'node_modules'), left - 1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
visitModules(nodeModules, depth);
|
|
165
|
+
return found;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Remove what externalToolsInstalledIn() finds, and the same entries from npm's
|
|
170
|
+
* hidden lockfile, so that npm's own record matches the folder. Never throws:
|
|
171
|
+
* `failed` lists what could not be removed (a read-only install, a file in use).
|
|
172
|
+
* Does nothing, and writes nothing, when there is nothing to remove.
|
|
173
|
+
*/
|
|
174
|
+
export function pruneExternalTools(nodeModules, { log = null } = {}) {
|
|
175
|
+
const result = { removed: [], failed: [] };
|
|
176
|
+
for (const item of externalToolsInstalledIn(nodeModules)) {
|
|
177
|
+
try {
|
|
178
|
+
rmSync(item.path, { recursive: true, force: true });
|
|
179
|
+
result.removed.push(item);
|
|
180
|
+
if (log) log(`removed ${item.kind} ${item.name} (${item.tool} is installed separately): ${item.path}`);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
result.failed.push({ ...item, error: error?.message || String(error) });
|
|
183
|
+
if (log) log(`could not remove ${item.path}: ${error?.message || error}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (!result.removed.length) return result;
|
|
187
|
+
const hidden = join(nodeModules, '.package-lock.json');
|
|
188
|
+
try {
|
|
189
|
+
const lock = JSON.parse(readFileSync(hidden, 'utf8'));
|
|
190
|
+
const stripped = stripExternalToolsFromLock(lock);
|
|
191
|
+
if (stripped.packages.length || stripped.edges.length) writeFileSync(hidden, JSON.stringify(lock, null, 2) + '\n');
|
|
192
|
+
} catch { /* no hidden lockfile, or not ours to repair */ }
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Why a file of a packaged application is an external tool's, or null. By path
|
|
198
|
+
* alone, forward or back slashes: a package folder, or a command in a `.bin`
|
|
199
|
+
* folder. `native` says the file is a native executable; then the tool's own
|
|
200
|
+
* file name anywhere is one too (`claude`, `codex.exe` ...).
|
|
201
|
+
*/
|
|
202
|
+
export function externalToolPayloadReason(relativePath, { native = false } = {}) {
|
|
203
|
+
const path = String(relativePath || '').replace(/\\/g, '/');
|
|
204
|
+
const parts = path.split('/');
|
|
205
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
206
|
+
if (parts[i] !== 'node_modules') continue;
|
|
207
|
+
if (parts[i + 1] === '.bin') {
|
|
208
|
+
const tool = i + 2 === parts.length - 1 ? COMMAND_FILES.get(parts[i + 2]) : null;
|
|
209
|
+
if (tool) return `the ${tool.label} command (${parts[i + 2]})`;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const name = parts[i + 1].startsWith('@') ? `${parts[i + 1]}/${parts[i + 2] || ''}` : parts[i + 1];
|
|
213
|
+
const tool = externalToolOf(name);
|
|
214
|
+
if (tool) return `the package ${name} (${tool.label})`;
|
|
215
|
+
}
|
|
216
|
+
if (native) {
|
|
217
|
+
const tool = COMMAND_FILES.get(parts[parts.length - 1]);
|
|
218
|
+
if (tool) return `the ${tool.label} executable`;
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
@@ -59,6 +59,7 @@ async function handoffSnapshotProblem({ handoff, version, backupService }) {
|
|
|
59
59
|
* @param {string} input.version the version about to launch
|
|
60
60
|
* @param {() => Promise<{createVerifiedBackup: Function, verifyBackupArchive: Function, applyBackupRetention: Function}>} [input.loadBackupService]
|
|
61
61
|
* @param {{info?: Function, ok?: Function, warn?: Function}} [input.log]
|
|
62
|
+
* @param {(detail: {step?: string, files?: number, bytes?: number, skippedFiles?: number}) => void} [input.onProgress] called when a snapshot starts and at each of its steps
|
|
62
63
|
* @returns {Promise<
|
|
63
64
|
* {status: 'not-due', reason: 'current-version' | 'no-state'} |
|
|
64
65
|
* {status: 'protected', snapshotPath: string, created: boolean, recorded: boolean} |
|
|
@@ -70,10 +71,12 @@ export async function protectFirstLaunchAfterUpdate({
|
|
|
70
71
|
version,
|
|
71
72
|
loadBackupService = () => import('../neural-interface/lib/backup-service.js'),
|
|
72
73
|
log = {},
|
|
74
|
+
onProgress = noop,
|
|
73
75
|
} = {}) {
|
|
74
76
|
const info = log.info || noop;
|
|
75
77
|
const ok = log.ok || noop;
|
|
76
78
|
const warn = log.warn || noop;
|
|
79
|
+
const progress = (detail) => { try { onProgress(detail); } catch { /* reporting never stops a snapshot */ } };
|
|
77
80
|
|
|
78
81
|
const manifestPath = resolve(dataHome, DATA_HOME_MANIFEST);
|
|
79
82
|
const handoffPath = resolve(dataHome, 'data', 'update-handoff.json');
|
|
@@ -105,6 +108,7 @@ export async function protectFirstLaunchAfterUpdate({
|
|
|
105
108
|
let service;
|
|
106
109
|
try {
|
|
107
110
|
info(`Protecting user state before first launch of v${version}...`);
|
|
111
|
+
progress({});
|
|
108
112
|
service = await backupService();
|
|
109
113
|
const snapshot = await service.createVerifiedBackup({
|
|
110
114
|
dataHome,
|
|
@@ -115,6 +119,7 @@ export async function protectFirstLaunchAfterUpdate({
|
|
|
115
119
|
// Without this the checksum and archive phases run silently for minutes
|
|
116
120
|
// on a large data home, which users read as a hang and kill.
|
|
117
121
|
onProgress: ({ phase, files, bytes, skippedFiles, skippedBytes }) => {
|
|
122
|
+
progress({ step: phase, files, bytes, skippedFiles });
|
|
118
123
|
const size = bytes ? ` (${(bytes / 1024 / 1024).toFixed(0)} MB)` : '';
|
|
119
124
|
if (phase === 'collect') {
|
|
120
125
|
info(` ${files} files to protect${size}`);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SynaBun — packaged application runtime
|
|
3
|
+
*
|
|
4
|
+
* A packaged build (packaging/) ships this package next to its own Node
|
|
5
|
+
* runtime, behind one native entry executable:
|
|
6
|
+
*
|
|
7
|
+
* <resources>/synabun-package.json written by the builder: what was built
|
|
8
|
+
* <resources>/runtime/ the Node that runs everything
|
|
9
|
+
* <resources>/app/ this package (PACKAGE_ROOT)
|
|
10
|
+
*
|
|
11
|
+
* This module answers one question for the rest of the code: is this that kind
|
|
12
|
+
* of install, and if so, what should the outside world run? An npm or Git
|
|
13
|
+
* install has no manifest next to its package root; every function here then
|
|
14
|
+
* says so and nothing changes for it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
18
|
+
import { basename, delimiter, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
19
|
+
import { PACKAGE_ROOT } from './paths.js';
|
|
20
|
+
|
|
21
|
+
export const PACKAGE_MANIFEST = 'synabun-package.json';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set by the native entry: where it lives for the outside world. For an
|
|
25
|
+
* AppImage that is the image file, never the mount it is running from.
|
|
26
|
+
*/
|
|
27
|
+
export const PACKAGED_ENTRY_ENV = 'SYNABUN_PACKAGED_ENTRY';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* What the builder recorded about this install, or null when the package is
|
|
31
|
+
* not inside a packaged application. Never throws.
|
|
32
|
+
*/
|
|
33
|
+
export function readPackagedRuntime({ packageRoot = PACKAGE_ROOT, env = process.env } = {}) {
|
|
34
|
+
const root = resolve(packageRoot);
|
|
35
|
+
const resources = dirname(root);
|
|
36
|
+
const manifestPath = join(resources, PACKAGE_MANIFEST);
|
|
37
|
+
let manifest;
|
|
38
|
+
try { manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); } catch { return null; }
|
|
39
|
+
// A manifest that does not describe this directory is somebody else's.
|
|
40
|
+
if (!manifest || manifest.synabunPackage !== 1 || basename(root) !== (manifest.app || 'app')) return null;
|
|
41
|
+
|
|
42
|
+
const recorded = typeof manifest.entry === 'string' && manifest.entry ? resolve(resources, manifest.entry) : null;
|
|
43
|
+
const entry = [env[PACKAGED_ENTRY_ENV], recorded]
|
|
44
|
+
.find(candidate => typeof candidate === 'string' && isAbsolute(candidate) && existsSync(candidate)) || null;
|
|
45
|
+
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
resources,
|
|
48
|
+
packageRoot: root,
|
|
49
|
+
manifestPath,
|
|
50
|
+
version: String(manifest.version || ''),
|
|
51
|
+
target: String(manifest.target?.id || ''),
|
|
52
|
+
platform: String(manifest.target?.platform || ''),
|
|
53
|
+
arch: String(manifest.target?.arch || ''),
|
|
54
|
+
artifact: manifest.artifact ? String(manifest.artifact) : null,
|
|
55
|
+
entry,
|
|
56
|
+
runtimeBin: resolve(resources, String(manifest.runtime?.bin || 'runtime/bin')),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let cached;
|
|
61
|
+
|
|
62
|
+
/** readPackagedRuntime() for this process, read once. */
|
|
63
|
+
export function packagedRuntime() {
|
|
64
|
+
if (cached === undefined) cached = readPackagedRuntime();
|
|
65
|
+
return cached;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Whether a path only lasts as long as this run: macOS starts a quarantined
|
|
70
|
+
* copy from a random AppTranslocation folder, and an AppImage runs from a
|
|
71
|
+
* mount that is gone when it exits. Nothing that outlives the process (a hook
|
|
72
|
+
* command, a line a person is told to type) may point at such a path.
|
|
73
|
+
*/
|
|
74
|
+
export function isTransientPath(path, env = process.env) {
|
|
75
|
+
const value = String(path || '').replace(/\\/g, '/');
|
|
76
|
+
if (!value) return false;
|
|
77
|
+
if (/\/AppTranslocation\//.test(value) || /\/\.mount_[^/]+\//.test(value)) return true;
|
|
78
|
+
const mount = String(env.APPDIR || '').replace(/\\/g, '/').replace(/\/+$/, '');
|
|
79
|
+
return Boolean(mount) && value.startsWith(`${mount}/`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The entry executable when it outlives this run, otherwise null. */
|
|
83
|
+
export function durableEntry(runtime = packagedRuntime(), env = process.env) {
|
|
84
|
+
const entry = runtime?.entry || null;
|
|
85
|
+
return entry && !isTransientPath(entry, env) ? entry : null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The command an MCP client runs for SynaBun's stdio server. A packaged
|
|
90
|
+
* application answers through its entry executable (`<entry> mcp`): the client
|
|
91
|
+
* has no Node of its own to find, and the entry's path outlives an update that
|
|
92
|
+
* moves the files behind it.
|
|
93
|
+
*/
|
|
94
|
+
export function mcpStdioCommand(scriptPath, { packageRoot = PACKAGE_ROOT, env = process.env, runtime } = {}) {
|
|
95
|
+
const found = runtime === undefined ? readPackagedRuntime({ packageRoot, env }) : runtime;
|
|
96
|
+
if (found?.entry) return { command: found.entry.replace(/\\/g, '/'), args: ['mcp'] };
|
|
97
|
+
return { command: 'node', args: [scriptPath] };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* `env` with the packaged runtime first on PATH, so that `node`, `npm` and
|
|
102
|
+
* `npx` started by name are the ones that came with the application.
|
|
103
|
+
*/
|
|
104
|
+
export function withPackagedPath(env = process.env, runtime = packagedRuntime()) {
|
|
105
|
+
if (!runtime) return env;
|
|
106
|
+
const key = Object.keys(env).find(name => name.toUpperCase() === 'PATH') || 'PATH';
|
|
107
|
+
const parts = String(env[key] || '').split(delimiter).filter(Boolean);
|
|
108
|
+
if (parts[0] === runtime.runtimeBin) return env;
|
|
109
|
+
return { ...env, [key]: [runtime.runtimeBin, ...parts.filter(part => part !== runtime.runtimeBin)].join(delimiter) };
|
|
110
|
+
}
|