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
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
// the face, plus one prop drawn in the face's own pill geometry. Rigs draw
|
|
9
9
|
// from the shared ticker (shared/synabun-ticker.js): 30 fps while a pose
|
|
10
10
|
// loops, 60 fps for blends and reactions, no frames at all while still. One
|
|
11
|
-
// pointermove listener and one IntersectionObserver serve every rig,
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// loop, one pointermove listener and one IntersectionObserver serve every rig,
|
|
12
|
+
// and every rig that is active and on screen plays its own pose: N rigs move
|
|
13
|
+
// at once, each on its own clock. No rig waits for another; a host that wants
|
|
14
|
+
// one moving character among several of its own (an Assistant panel's hero,
|
|
15
|
+
// stage and "Thinking" row) says so with setActive(). Under
|
|
16
|
+
// prefers-reduced-motion every pose is its still frame and changes are
|
|
17
|
+
// instant. A rig tears itself down once its SVG leaves the document.
|
|
16
18
|
//
|
|
17
19
|
// v1 callers are unchanged: createMascot(container, opts) → { el, destroy,
|
|
18
20
|
// look, blink }, idle, blinking every 3-7 s and following the cursor.
|
|
@@ -307,7 +309,7 @@ const MINIS = [
|
|
|
307
309
|
];
|
|
308
310
|
|
|
309
311
|
/**
|
|
310
|
-
* motion: 'loop' (30 fps
|
|
312
|
+
* motion: 'loop' (30 fps), 'blink' (still between slow blinks),
|
|
311
313
|
* 'once' (plays `settle` ms, then still; `hold` before opts.then), 'still'.
|
|
312
314
|
* blinks: random blinks every 3-7 s. tracks: follows the cursor.
|
|
313
315
|
* look: follows look(), easing with this time constant (ms).
|
|
@@ -994,26 +996,15 @@ export function paintMascot(svg, frame) {
|
|
|
994
996
|
painter.paint(frame);
|
|
995
997
|
}
|
|
996
998
|
|
|
997
|
-
// ── Shared runtime: one observer
|
|
999
|
+
// ── Shared runtime: one observer and one motion listener for every rig ──
|
|
1000
|
+
// Nothing here picks a rig: each one decides from its own state (active, on
|
|
1001
|
+
// screen, motion allowed) whether it moves.
|
|
998
1002
|
|
|
999
1003
|
const rigs = new Set();
|
|
1000
|
-
let leadRig = null;
|
|
1001
|
-
let promoteSeq = 0;
|
|
1002
1004
|
let stopMotionWatch = null;
|
|
1003
1005
|
let io = null;
|
|
1004
1006
|
const ioRigs = new WeakMap();
|
|
1005
1007
|
|
|
1006
|
-
/** Only one rig plays a pose loop: the most recently posed one that wants to. */
|
|
1007
|
-
function elect() {
|
|
1008
|
-
let best = null;
|
|
1009
|
-
for (const rig of rigs) if (rig.wantsLead() && (!best || rig.promotedAt() > best.promotedAt())) best = rig;
|
|
1010
|
-
if (best === leadRig) return;
|
|
1011
|
-
const prev = leadRig;
|
|
1012
|
-
leadRig = best;
|
|
1013
|
-
prev?.leadChanged();
|
|
1014
|
-
best?.leadChanged();
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
1008
|
function observe(el, rig) {
|
|
1018
1009
|
if (typeof IntersectionObserver !== 'function') return;
|
|
1019
1010
|
try {
|
|
@@ -1034,13 +1025,11 @@ function register(rig) {
|
|
|
1034
1025
|
rigs.add(rig);
|
|
1035
1026
|
stopMotionWatch ||= onReducedMotionChange(() => {
|
|
1036
1027
|
for (const r of Array.from(rigs)) r.motionChanged();
|
|
1037
|
-
elect();
|
|
1038
1028
|
});
|
|
1039
1029
|
}
|
|
1040
1030
|
|
|
1041
1031
|
function unregister(rig) {
|
|
1042
1032
|
rigs.delete(rig);
|
|
1043
|
-
if (leadRig === rig) { leadRig = null; elect(); }
|
|
1044
1033
|
if (!rigs.size && stopMotionWatch) { stopMotionWatch(); stopMotionWatch = null; }
|
|
1045
1034
|
}
|
|
1046
1035
|
|
|
@@ -1088,14 +1077,12 @@ export function createMascot(container, options) {
|
|
|
1088
1077
|
let active = startActive !== false;
|
|
1089
1078
|
let visible = true;
|
|
1090
1079
|
let seenConnected = svg.isConnected;
|
|
1091
|
-
let promotedAt = (promoteSeq += 1);
|
|
1092
1080
|
let clock = 0; // rig time in ms: the ticker's dt while drawing, real time while still
|
|
1093
1081
|
let frozenAt = tickerNow(); // while not drawing: when the clock was last brought up to date; -1 while drawing
|
|
1094
1082
|
let pose = { name: 'idle', raw: {}, start: 0, then: null };
|
|
1095
1083
|
let settled = false; // a one-shot's opts.then has fired
|
|
1096
1084
|
let blend = null; // { from, start, dur }
|
|
1097
1085
|
let lastFrame = null; // the last frame before blinks and reactions
|
|
1098
|
-
let drawn = false; // has drawn a live frame (a never-drawn rig has nothing to blend from)
|
|
1099
1086
|
let look = { x: 0, y: 0 }; // eased gaze
|
|
1100
1087
|
let track = { x: 0, y: 0 }; // idle: where the cursor (or look()) points
|
|
1101
1088
|
let hostLook = { x: 0, y: 0 };
|
|
@@ -1119,10 +1106,10 @@ export function createMascot(container, options) {
|
|
|
1119
1106
|
|
|
1120
1107
|
const def = () => POSES[pose.name];
|
|
1121
1108
|
const animating = () => !destroyed && active && visible && !isReducedMotion();
|
|
1122
|
-
const isLead = () => leadRig === rig;
|
|
1123
1109
|
const poseTime = () => clock - pose.start;
|
|
1124
1110
|
|
|
1125
|
-
|
|
1111
|
+
/** This pose moves on its own right now: a loop, a patient pose, a one-shot still playing. */
|
|
1112
|
+
function playing() {
|
|
1126
1113
|
if (!animating()) return false;
|
|
1127
1114
|
const { motion, settle } = def();
|
|
1128
1115
|
if (motion === 'loop' || motion === 'blink') return true;
|
|
@@ -1186,7 +1173,6 @@ export function createMascot(container, options) {
|
|
|
1186
1173
|
function nextRate() {
|
|
1187
1174
|
if (!animating()) return 0;
|
|
1188
1175
|
if (blend || blinkStart >= 0 || reactions.length || aim || easing() || miniPopping()) return 60;
|
|
1189
|
-
if (!isLead()) return 0;
|
|
1190
1176
|
const d = def();
|
|
1191
1177
|
const t = poseTime();
|
|
1192
1178
|
if (d.motion === 'loop') return 30;
|
|
@@ -1208,9 +1194,9 @@ export function createMascot(container, options) {
|
|
|
1208
1194
|
const d = def();
|
|
1209
1195
|
const at0 = tickerNow();
|
|
1210
1196
|
let at = Infinity;
|
|
1211
|
-
if (d.blinks
|
|
1197
|
+
if (d.blinks) at = Math.min(at, nextBlinkAt);
|
|
1212
1198
|
if (d.tracks) at = Math.min(at, nextGlanceAt, nextFidgetAt, glance ? glance.until : Infinity);
|
|
1213
|
-
if (d.motion === 'blink'
|
|
1199
|
+
if (d.motion === 'blink') at = Math.min(at, at0 + d.idleFor(poseTime()));
|
|
1214
1200
|
if (d.motion === 'once' && pose.then && !settled) at = Math.min(at, at0 + Math.max(0, d.settle + (d.hold || 0) - poseTime()));
|
|
1215
1201
|
if (!Number.isFinite(at)) return;
|
|
1216
1202
|
wakeTimer = setTimeout(() => {
|
|
@@ -1243,15 +1229,15 @@ export function createMascot(container, options) {
|
|
|
1243
1229
|
function handleDue() {
|
|
1244
1230
|
const d = def();
|
|
1245
1231
|
const t = tickerNow();
|
|
1246
|
-
if (d.blinks &&
|
|
1232
|
+
if (d.blinks && t >= nextBlinkAt) {
|
|
1247
1233
|
nextBlinkAt = t + rand(3000, 7000);
|
|
1248
1234
|
startBlink();
|
|
1249
1235
|
}
|
|
1250
1236
|
if (d.tracks) {
|
|
1251
1237
|
if (glance && t >= glance.until) glance = null;
|
|
1252
1238
|
if (t >= nextGlanceAt) {
|
|
1253
|
-
// Only while the cursor is still
|
|
1254
|
-
if (t - pointerAt < 2500
|
|
1239
|
+
// Only while the cursor is still.
|
|
1240
|
+
if (t - pointerAt < 2500) nextGlanceAt = t + 3000;
|
|
1255
1241
|
else {
|
|
1256
1242
|
const [x, y] = GLANCES[Math.floor(Math.random() * GLANCES.length)];
|
|
1257
1243
|
glance = { x, y, until: t + rand(700, 1000) };
|
|
@@ -1261,7 +1247,6 @@ export function createMascot(container, options) {
|
|
|
1261
1247
|
if (t >= nextFidgetAt) {
|
|
1262
1248
|
const quietFor = t - Math.max(lastInputAt(), pointerAt);
|
|
1263
1249
|
if (quietFor < 20000) nextFidgetAt = t + (20000 - quietFor) + rand(0, 5000);
|
|
1264
|
-
else if (leadRig) nextFidgetAt = t + 10000;
|
|
1265
1250
|
else {
|
|
1266
1251
|
nextFidgetAt = t + rand(45000, 75000);
|
|
1267
1252
|
startReaction(Math.random() < 0.5 ? 'hop' : 'wiggle');
|
|
@@ -1303,8 +1288,7 @@ export function createMascot(container, options) {
|
|
|
1303
1288
|
|
|
1304
1289
|
/** The pose frame this rig would draw now, before blends and overlays. */
|
|
1305
1290
|
function frameNow() {
|
|
1306
|
-
|
|
1307
|
-
return poseFrame(pose.name, poseTime(), { ...pose.raw, look, range, ticks, still: !loopOn });
|
|
1291
|
+
return poseFrame(pose.name, poseTime(), { ...pose.raw, look, range, ticks, still: !playing() });
|
|
1308
1292
|
}
|
|
1309
1293
|
|
|
1310
1294
|
/** Ease from what is on screen to what comes next, unless they already match. */
|
|
@@ -1400,10 +1384,7 @@ export function createMascot(container, options) {
|
|
|
1400
1384
|
handleDue();
|
|
1401
1385
|
if (aim) { aimAt(aim); aim = null; }
|
|
1402
1386
|
easeLook(dt);
|
|
1403
|
-
const wasLead = isLead();
|
|
1404
1387
|
painter.paint(compose());
|
|
1405
|
-
drawn = true;
|
|
1406
|
-
if (wasLead && def().motion === 'once' && poseTime() >= def().settle) elect();
|
|
1407
1388
|
const rate = nextRate();
|
|
1408
1389
|
setRate(rate);
|
|
1409
1390
|
if (!rate) armWake();
|
|
@@ -1497,9 +1478,7 @@ export function createMascot(container, options) {
|
|
|
1497
1478
|
}
|
|
1498
1479
|
scheduleIdle();
|
|
1499
1480
|
}
|
|
1500
|
-
promotedAt = (promoteSeq += 1);
|
|
1501
1481
|
if (animating()) requestFrames(BLEND_MS);
|
|
1502
|
-
elect();
|
|
1503
1482
|
refresh();
|
|
1504
1483
|
return api;
|
|
1505
1484
|
}
|
|
@@ -1537,8 +1516,7 @@ export function createMascot(container, options) {
|
|
|
1537
1516
|
const next = !!on;
|
|
1538
1517
|
if (destroyed || next === active) return api;
|
|
1539
1518
|
active = next;
|
|
1540
|
-
if (active)
|
|
1541
|
-
elect();
|
|
1519
|
+
if (active) revive();
|
|
1542
1520
|
refresh();
|
|
1543
1521
|
return api;
|
|
1544
1522
|
}
|
|
@@ -1560,18 +1538,6 @@ export function createMascot(container, options) {
|
|
|
1560
1538
|
}
|
|
1561
1539
|
|
|
1562
1540
|
const rig = {
|
|
1563
|
-
promotedAt: () => promotedAt,
|
|
1564
|
-
wantsLead,
|
|
1565
|
-
leadChanged() {
|
|
1566
|
-
if (destroyed) return;
|
|
1567
|
-
// Gaining or losing the loop swaps the still frame for the live one: blend
|
|
1568
|
-
// when they differ (a patient pose between blinks, a settled one-shot: no).
|
|
1569
|
-
if (drawn && animating()) {
|
|
1570
|
-
syncClock();
|
|
1571
|
-
blendIn();
|
|
1572
|
-
}
|
|
1573
|
-
refresh();
|
|
1574
|
-
},
|
|
1575
1541
|
visibilityChanged(inView) {
|
|
1576
1542
|
if (destroyed) return;
|
|
1577
1543
|
if (svg.isConnected) seenConnected = true;
|
|
@@ -1579,7 +1545,6 @@ export function createMascot(container, options) {
|
|
|
1579
1545
|
const was = visible;
|
|
1580
1546
|
visible = inView;
|
|
1581
1547
|
if (visible && !was) revive();
|
|
1582
|
-
elect();
|
|
1583
1548
|
refresh(); // also wakes a rig that was built before it was attached
|
|
1584
1549
|
},
|
|
1585
1550
|
motionChanged() {
|
|
@@ -1619,7 +1584,6 @@ export function createMascot(container, options) {
|
|
|
1619
1584
|
if (p) aim = p;
|
|
1620
1585
|
}
|
|
1621
1586
|
}
|
|
1622
|
-
elect();
|
|
1623
1587
|
refresh();
|
|
1624
1588
|
return api;
|
|
1625
1589
|
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — Terminal readiness
|
|
3
|
+
// When a freshly opened terminal can take a typed command, and how to hand it
|
|
4
|
+
// over. DOM-free: ui-terminal.js feeds it the output stream and does the I/O.
|
|
5
|
+
// ═══════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
// CSI, OSC (BEL or ST terminated), charset selection, and the two-byte escapes.
|
|
8
|
+
const ESCAPES_RE = /\x1b\[[\x20-\x3f]*[\x40-\x7e]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[()][AB012]|\x1b[=>78MDEHNOc]/g;
|
|
9
|
+
|
|
10
|
+
// What _sendOnceReady has always stripped and matched for the CLIs (Claude
|
|
11
|
+
// Code, Codex, …). Kept as it was: the loops depend on this exact reading.
|
|
12
|
+
const CLI_ANSI_RE = /\x1b\[[\x20-\x3f]*[\x40-\x7e]|\x1b\][^\x07]*\x07|\x1b[()][AB012]/g;
|
|
13
|
+
const CLI_READY_PATTERNS = [
|
|
14
|
+
/^>\s*$/m, // Claude Code prompt: ">" on its own line
|
|
15
|
+
/\n>\s*$/, // ">" after newline at end of output
|
|
16
|
+
/>\s*$/, // ">" at end of buffer (catch partial lines)
|
|
17
|
+
/❯/, // ❯ (some CLI prompts)
|
|
18
|
+
/\$ $/, // Shell prompt fallback
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// The line editor (zsh's ZLE, readline in bash 5, fish) turns bracketed paste
|
|
22
|
+
// on when it starts reading a line and off when a command runs.
|
|
23
|
+
const PASTE_ON = '\x1b[?2004h';
|
|
24
|
+
const PASTE_OFF = '\x1b[?2004l';
|
|
25
|
+
// Shell integration marks (FinalTerm / OSC 133): B = the prompt has ended,
|
|
26
|
+
// C = a command is running.
|
|
27
|
+
const MARK_PROMPT_END = '\x1b]133;B';
|
|
28
|
+
const MARK_RUNNING = '\x1b]133;C';
|
|
29
|
+
|
|
30
|
+
// The character a prompt ends in: zsh %, bash/sh $, root #, cmd.exe / PowerShell
|
|
31
|
+
// / fish >, and the arrows the common themes use. A reconnect snapshot trims the
|
|
32
|
+
// trailing space, so the space is optional.
|
|
33
|
+
const PROMPT_TAIL_RE = /[%$#>❯➜»›→▶λ][ \t]*$/;
|
|
34
|
+
|
|
35
|
+
const BUFFER_MAX = 16384;
|
|
36
|
+
const BUFFER_KEEP = 8192;
|
|
37
|
+
|
|
38
|
+
// capMs runs from the moment the terminal's socket is open, never from the
|
|
39
|
+
// call: a socket that takes its time must not eat into the wait for a prompt.
|
|
40
|
+
// openGraceMs is how much longer than that a socket may take to open at all.
|
|
41
|
+
export const READY_LIMITS = Object.freeze({
|
|
42
|
+
// A shell takes typeahead, so its limits are short: the worst case is a
|
|
43
|
+
// command typed a moment before the prompt is drawn, never a lost one.
|
|
44
|
+
shell: Object.freeze({ quietMs: 350, capMs: 5000, settleMs: 40, openGraceMs: 2000 }),
|
|
45
|
+
// A CLI started inside the shell swallows input typed before its own prompt.
|
|
46
|
+
cli: Object.freeze({ quietMs: 0, capMs: 15000, settleMs: 500, openGraceMs: 2000 }),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** Which reading a terminal profile gets. */
|
|
50
|
+
export function readinessKind(profile) {
|
|
51
|
+
return profile === 'shell' ? 'shell' : 'cli';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function stripEscapes(text) {
|
|
55
|
+
return String(text || '').replace(ESCAPES_RE, '');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function lastOn(raw, on, off) {
|
|
59
|
+
const at = raw.lastIndexOf(on);
|
|
60
|
+
return at >= 0 && at > raw.lastIndexOf(off);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Read everything a terminal printed so far. Returns the reason it is ready
|
|
65
|
+
* ('line-editor', 'prompt-mark', 'prompt') or null.
|
|
66
|
+
*/
|
|
67
|
+
export function readySignal(raw, kind = 'shell') {
|
|
68
|
+
const text = String(raw || '');
|
|
69
|
+
if (!text) return null;
|
|
70
|
+
if (kind !== 'shell') {
|
|
71
|
+
const clean = text.replace(CLI_ANSI_RE, '');
|
|
72
|
+
return CLI_READY_PATTERNS.some(p => p.test(clean)) ? 'prompt' : null;
|
|
73
|
+
}
|
|
74
|
+
if (lastOn(text, PASTE_ON, PASTE_OFF)) return 'line-editor';
|
|
75
|
+
if (lastOn(text, MARK_PROMPT_END, MARK_RUNNING)) return 'prompt-mark';
|
|
76
|
+
// The line the cursor is on: zsh draws its prompt after "\r \r", so a
|
|
77
|
+
// carriage return starts a line here just like a newline does.
|
|
78
|
+
const clean = stripEscapes(text);
|
|
79
|
+
const line = clean.slice(Math.max(clean.lastIndexOf('\n'), clean.lastIndexOf('\r')) + 1);
|
|
80
|
+
return line.trim() && PROMPT_TAIL_RE.test(line) ? 'prompt' : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Watch one terminal until it can take input, then call onReady(reason) once.
|
|
85
|
+
* output(text) — output arrived (live bytes, or what was already buffered)
|
|
86
|
+
* replace(text) — a snapshot replaced the screen (connect / reconnect)
|
|
87
|
+
* poke() — the emulator parsed something: re-read its line-editor mode
|
|
88
|
+
* start() — the wait begins
|
|
89
|
+
* opened() — the terminal's socket is open
|
|
90
|
+
* cancel()
|
|
91
|
+
* Nothing is decided before opened(): the readiness window (capMs, and the
|
|
92
|
+
* quiet rule) runs from there, in full, however late the socket opens. What
|
|
93
|
+
* was fed in earlier is read at that moment. A socket that never opens ends
|
|
94
|
+
* the wait capMs + openGraceMs after start().
|
|
95
|
+
* Reasons: 'line-editor' | 'prompt-mark' | 'prompt' | 'quiet' | 'timeout'.
|
|
96
|
+
*/
|
|
97
|
+
export function createReadyWatch({
|
|
98
|
+
kind = 'shell',
|
|
99
|
+
onReady,
|
|
100
|
+
lineEditorActive = null,
|
|
101
|
+
limits = READY_LIMITS[kind] || READY_LIMITS.cli,
|
|
102
|
+
timers = { set: (fn, ms) => setTimeout(fn, ms), clear: (id) => clearTimeout(id) },
|
|
103
|
+
} = {}) {
|
|
104
|
+
let buf = '';
|
|
105
|
+
let done = false;
|
|
106
|
+
let started = false;
|
|
107
|
+
let open = false;
|
|
108
|
+
let sawOutput = false;
|
|
109
|
+
let quietTimer = null;
|
|
110
|
+
let capTimer = null;
|
|
111
|
+
let openTimer = null;
|
|
112
|
+
|
|
113
|
+
function clearTimers() {
|
|
114
|
+
if (quietTimer) timers.clear(quietTimer);
|
|
115
|
+
if (capTimer) timers.clear(capTimer);
|
|
116
|
+
if (openTimer) timers.clear(openTimer);
|
|
117
|
+
quietTimer = capTimer = openTimer = null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function finish(reason) {
|
|
121
|
+
if (done) return;
|
|
122
|
+
done = true;
|
|
123
|
+
clearTimers();
|
|
124
|
+
try { onReady?.(reason); } catch {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Something a person could see. A connect snapshot of an empty screen and a
|
|
128
|
+
// shell's terminal queries are escape codes only: not a sign of life yet.
|
|
129
|
+
function noteOutput(text) {
|
|
130
|
+
if (!sawOutput && /\S/.test(stripEscapes(text))) sawOutput = true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function armQuiet() {
|
|
134
|
+
if (done || !open || !sawOutput || !(limits.quietMs > 0)) return;
|
|
135
|
+
if (quietTimer) timers.clear(quietTimer);
|
|
136
|
+
quietTimer = timers.set(() => { quietTimer = null; finish('quiet'); }, limits.quietMs);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function evaluate() {
|
|
140
|
+
if (done || !open) return;
|
|
141
|
+
const signal = readySignal(buf, kind);
|
|
142
|
+
if (signal) { finish(signal); return; }
|
|
143
|
+
if (kind === 'shell' && lineEditorActive) {
|
|
144
|
+
let active = false;
|
|
145
|
+
try { active = lineEditorActive() === true; } catch {}
|
|
146
|
+
if (active) { finish('line-editor'); return; }
|
|
147
|
+
}
|
|
148
|
+
armQuiet();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
output(text) {
|
|
153
|
+
if (done || !text) return;
|
|
154
|
+
noteOutput(text);
|
|
155
|
+
buf += text;
|
|
156
|
+
if (buf.length > BUFFER_MAX) buf = buf.slice(-BUFFER_KEEP);
|
|
157
|
+
evaluate();
|
|
158
|
+
},
|
|
159
|
+
replace(text) {
|
|
160
|
+
if (done) return;
|
|
161
|
+
buf = String(text || '');
|
|
162
|
+
noteOutput(buf);
|
|
163
|
+
evaluate();
|
|
164
|
+
},
|
|
165
|
+
poke() {
|
|
166
|
+
if (done || !open || kind !== 'shell' || !lineEditorActive) return;
|
|
167
|
+
let active = false;
|
|
168
|
+
try { active = lineEditorActive() === true; } catch {}
|
|
169
|
+
if (active) finish('line-editor');
|
|
170
|
+
},
|
|
171
|
+
start() {
|
|
172
|
+
if (done || started) return;
|
|
173
|
+
started = true;
|
|
174
|
+
if (open) return;
|
|
175
|
+
openTimer = timers.set(() => { openTimer = null; finish('timeout'); }, limits.capMs + (limits.openGraceMs || 0));
|
|
176
|
+
},
|
|
177
|
+
opened() {
|
|
178
|
+
if (done || open) return; // a reconnect later on does not restart the window
|
|
179
|
+
started = true;
|
|
180
|
+
open = true;
|
|
181
|
+
if (openTimer) timers.clear(openTimer);
|
|
182
|
+
openTimer = null;
|
|
183
|
+
capTimer = timers.set(() => { capTimer = null; finish('timeout'); }, limits.capMs);
|
|
184
|
+
evaluate();
|
|
185
|
+
},
|
|
186
|
+
cancel() {
|
|
187
|
+
if (done) return;
|
|
188
|
+
done = true;
|
|
189
|
+
clearTimers();
|
|
190
|
+
},
|
|
191
|
+
get done() { return done; },
|
|
192
|
+
get open() { return open; },
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Split typed input into the writes the PTY gets (ConPTY drops long ones). */
|
|
197
|
+
export function inputChunks(text, size = 256) {
|
|
198
|
+
const full = String(text ?? '');
|
|
199
|
+
const out = [];
|
|
200
|
+
for (let i = 0; i < full.length; i += size) out.push(full.slice(i, i + size));
|
|
201
|
+
return out;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Type `text` into a terminal: every chunk in order, each through the socket
|
|
206
|
+
* that is current at that moment (a reconnect swaps it). Waits for an open
|
|
207
|
+
* socket instead of dropping the input, and stops for good the moment a chunk
|
|
208
|
+
* cannot be delivered — a command with a hole in it must never reach Enter.
|
|
209
|
+
* socket() → the session's current socket ({ readyState, send }) or null
|
|
210
|
+
* alive() → false once the terminal is gone
|
|
211
|
+
* Resolves { ok, sent, chunks, reason? } with reason 'closed' | 'no-socket'.
|
|
212
|
+
*/
|
|
213
|
+
export async function typeInto({
|
|
214
|
+
socket,
|
|
215
|
+
alive = () => true,
|
|
216
|
+
text,
|
|
217
|
+
chunkSize = 256,
|
|
218
|
+
gapMs = 30,
|
|
219
|
+
openWaitMs = 10000,
|
|
220
|
+
pollMs = 25,
|
|
221
|
+
OPEN = 1,
|
|
222
|
+
sleep = (ms) => new Promise(r => setTimeout(r, ms)),
|
|
223
|
+
now = () => Date.now(),
|
|
224
|
+
} = {}) {
|
|
225
|
+
const chunks = inputChunks(text, chunkSize);
|
|
226
|
+
let sent = 0;
|
|
227
|
+
for (const chunk of chunks) {
|
|
228
|
+
const deadline = now() + openWaitMs;
|
|
229
|
+
let ws = socket();
|
|
230
|
+
while (alive() && (!ws || ws.readyState !== OPEN) && now() < deadline) {
|
|
231
|
+
// Mid-command the wait is over: what follows a gap would be a different command.
|
|
232
|
+
if (sent > 0) return { ok: false, sent, chunks: chunks.length, reason: 'closed' };
|
|
233
|
+
await sleep(pollMs);
|
|
234
|
+
ws = socket();
|
|
235
|
+
}
|
|
236
|
+
if (!alive()) return { ok: false, sent, chunks: chunks.length, reason: 'closed' };
|
|
237
|
+
if (!ws || ws.readyState !== OPEN) return { ok: false, sent, chunks: chunks.length, reason: 'no-socket' };
|
|
238
|
+
try { ws.send(JSON.stringify({ type: 'input', data: chunk })); }
|
|
239
|
+
catch { return { ok: false, sent, chunks: chunks.length, reason: 'closed' }; }
|
|
240
|
+
sent++;
|
|
241
|
+
if (sent < chunks.length) await sleep(gapMs);
|
|
242
|
+
}
|
|
243
|
+
return { ok: true, sent, chunks: chunks.length };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The whole hand-over of one message: wait until the terminal can take it, let
|
|
248
|
+
* it settle, type it. Everything that touches the page is handed in, so this
|
|
249
|
+
* runs the same under a test clock.
|
|
250
|
+
* socket() → the session's current socket (a reconnect swaps it)
|
|
251
|
+
* alive() → false once the terminal is gone
|
|
252
|
+
* lineEditorActive() → the emulator's bracketed-paste mode
|
|
253
|
+
* buffered → output that arrived before this call
|
|
254
|
+
* subscribe({ output(text, replaced), opened(), parsed() }) → unsubscribe
|
|
255
|
+
* output for every chunk, opened whenever a socket of
|
|
256
|
+
* this session opens, parsed after the emulator parsed
|
|
257
|
+
* onReady(reason, waitedMs)
|
|
258
|
+
* Resolves { ok: true, reason, waitedMs } or { ok: false, reason, sent, chunks }.
|
|
259
|
+
*/
|
|
260
|
+
export function typeWhenReady({
|
|
261
|
+
kind = 'shell',
|
|
262
|
+
text,
|
|
263
|
+
socket,
|
|
264
|
+
alive = () => true,
|
|
265
|
+
lineEditorActive = null,
|
|
266
|
+
buffered = '',
|
|
267
|
+
subscribe = null,
|
|
268
|
+
onReady = () => {},
|
|
269
|
+
OPEN = 1,
|
|
270
|
+
limits = READY_LIMITS[kind] || READY_LIMITS.cli,
|
|
271
|
+
timers = { set: (fn, ms) => setTimeout(fn, ms), clear: (id) => clearTimeout(id) },
|
|
272
|
+
now = () => Date.now(),
|
|
273
|
+
sleep = (ms) => new Promise(r => timers.set(r, ms)),
|
|
274
|
+
} = {}) {
|
|
275
|
+
return new Promise((resolve) => {
|
|
276
|
+
const t0 = now();
|
|
277
|
+
let unsubscribe = null;
|
|
278
|
+
const watch = createReadyWatch({
|
|
279
|
+
kind,
|
|
280
|
+
lineEditorActive,
|
|
281
|
+
limits,
|
|
282
|
+
timers,
|
|
283
|
+
onReady: (reason) => {
|
|
284
|
+
try { unsubscribe?.(); } catch {}
|
|
285
|
+
unsubscribe = null;
|
|
286
|
+
const waitedMs = Math.round(now() - t0);
|
|
287
|
+
try { onReady(reason, waitedMs); } catch {}
|
|
288
|
+
timers.set(async () => {
|
|
289
|
+
const result = await typeInto({ socket, alive, text, OPEN, sleep, now });
|
|
290
|
+
resolve(result.ok
|
|
291
|
+
? { ok: true, reason, waitedMs }
|
|
292
|
+
: { ok: false, reason: result.reason, sent: result.sent, chunks: result.chunks });
|
|
293
|
+
}, limits.settleMs);
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
// Subscribed before anything can be decided: no verdict comes before opened().
|
|
297
|
+
unsubscribe = subscribe?.({
|
|
298
|
+
output: (chunk, replaced) => { if (replaced) watch.replace(chunk); else watch.output(chunk); },
|
|
299
|
+
opened: () => watch.opened(),
|
|
300
|
+
parsed: () => watch.poke(),
|
|
301
|
+
}) || null;
|
|
302
|
+
if (buffered) watch.output(buffered);
|
|
303
|
+
watch.start();
|
|
304
|
+
const ws = socket?.();
|
|
305
|
+
if (ws && ws.readyState === OPEN) watch.opened();
|
|
306
|
+
});
|
|
307
|
+
}
|