synabun 2.0.0 → 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 +57 -0
- package/NOTICE +5 -0
- package/README.md +1 -1
- package/THIRD-PARTY-LICENSES.md +46 -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/lib/start-launcher.js +88 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -3
- package/neural-interface/i18n/en.json +1500 -153
- package/neural-interface/i18n/pt-BR.json +1498 -152
- 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-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/browser-background-tab.js +134 -0
- package/neural-interface/lib/browser-screenshot.js +678 -61
- package/neural-interface/lib/claude-agent-bridge.js +33 -6
- package/neural-interface/lib/claude-model-catalog.js +30 -2
- 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-loop-providers.js +10 -5
- 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/ui-blob-api.js +108 -0
- package/neural-interface/lib/ui-blob-store.js +68 -0
- package/neural-interface/package-lock.json +701 -2
- package/neural-interface/package.json +13 -2
- package/neural-interface/public/install-app.html +9 -6
- package/neural-interface/public/offline.html +3 -2
- package/neural-interface/public/onboarding.html +12 -1
- 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 +18 -58
- 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-render.js +162 -19
- 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 +158 -4
- 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/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 +160 -165
- 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 +29 -1
- package/neural-interface/public/shared/pwa-install.css +3 -3
- package/neural-interface/public/shared/pwa-install.js +100 -1
- 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-user-context.js +154 -0
- package/neural-interface/public/shared/start-bridge.js +238 -19
- package/neural-interface/public/shared/styles.css +1414 -721
- package/neural-interface/public/shared/synabun-mascot.js +20 -56
- package/neural-interface/public/shared/tunnel-view.js +167 -0
- package/neural-interface/public/shared/ui-claude-panel.js +157 -16
- 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-keybinds.js +4 -0
- package/neural-interface/public/shared/ui-loading.js +159 -15
- package/neural-interface/public/shared/ui-menubar.js +12 -30
- 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 +455 -488
- 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 +23 -5
- 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 +2 -2
- 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/vendor-codemirror-entry.js +121 -0
- package/neural-interface/server.js +873 -1028
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/package.json +2 -8
- package/setup.js +44 -7
- package/benchmarks/browser-live-results.json +0 -79
- package/benchmarks/browser-v2-results.json +0 -258
- 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/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,167 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SynaBun Neural Interface — the public address: what the cards say
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// What the two places that start the Cloudflare tunnel show for an answer of
|
|
6
|
+
// GET /api/tunnel/status: the Share menu's Connection block (ui-invite.js) and
|
|
7
|
+
// Settings → Automations → Online access (ui-settings.js). One reading for
|
|
8
|
+
// both, so they never disagree: the state as a word, one sentence about it,
|
|
9
|
+
// the progress of a download, the action that fits, and whether to ask again.
|
|
10
|
+
//
|
|
11
|
+
// No imports and no DOM: `node --test` loads this file as it is
|
|
12
|
+
// (tests/tunnel-view.test.mjs). TUNNEL_COPY is the English of every sentence;
|
|
13
|
+
// `tunnel.*` in i18n/en.json must equal it and i18n/pt-BR.json must have the
|
|
14
|
+
// same keys (the test checks both). The page side is ui-tunnel.js.
|
|
15
|
+
//
|
|
16
|
+
// A server that was started before SynaBun brought its own tunnel program
|
|
17
|
+
// answers without the `cloudflared` part: the cards then work as they did (a
|
|
18
|
+
// tunnel starts when a cloudflared is installed), and where none is, they say
|
|
19
|
+
// that a restart is what is missing. Nothing here ever tells the user to
|
|
20
|
+
// install anything, except on a system Cloudflare publishes no file for.
|
|
21
|
+
|
|
22
|
+
export const TUNNEL_COPY = Object.freeze({
|
|
23
|
+
stateOff: 'Off',
|
|
24
|
+
stateDownloading: 'Getting the tunnel program',
|
|
25
|
+
stateStarting: 'Starting',
|
|
26
|
+
stateRunning: 'On',
|
|
27
|
+
stateFailed: 'Did not start',
|
|
28
|
+
stateUnsupported: 'Not available',
|
|
29
|
+
stateRestart: 'Restart needed',
|
|
30
|
+
idle: 'A public address through Cloudflare, for invite links and remote MCP.',
|
|
31
|
+
idleDownload: 'A public address through Cloudflare, for invite links and remote MCP. The first start downloads the tunnel program ({size} MB).',
|
|
32
|
+
downloading: 'Downloading the tunnel program: {received} of {total} MB',
|
|
33
|
+
starting: 'Waiting for Cloudflare to give an address…',
|
|
34
|
+
restart: 'Restart SynaBun to use the public address: the server that is running was started before it could download the tunnel program.',
|
|
35
|
+
unsupported: 'Cloudflare publishes no tunnel program for this system. If you install cloudflared yourself, SynaBun uses it.',
|
|
36
|
+
errorOffline: 'The tunnel program could not be downloaded: the download server was not reached. Check the connection and try again.',
|
|
37
|
+
errorHttp: 'The tunnel program could not be downloaded: the download server answered with an error. Try again in a moment.',
|
|
38
|
+
errorInterrupted: 'The download stopped before it was complete. Nothing was kept. Try again.',
|
|
39
|
+
errorTimeout: 'The download stalled. Nothing was kept. Try again.',
|
|
40
|
+
errorChecksum: 'The download was not the file SynaBun expects, so it was removed and never run. Try again; if it happens again, something on the network is changing the file.',
|
|
41
|
+
errorUnpack: 'The downloaded file could not be unpacked, so it was removed. Try again.',
|
|
42
|
+
errorDisk: 'The tunnel program could not be saved in SynaBun\'s data folder. Check free space and permissions, then try again.',
|
|
43
|
+
errorLaunch: 'The tunnel program could not be started on this computer. Try again.',
|
|
44
|
+
errorExited: 'Cloudflare gave no address. The tunnel program said: {reason}',
|
|
45
|
+
errorExitedNoReason: 'The tunnel program stopped before Cloudflare gave an address. Try again.',
|
|
46
|
+
errorNoAddress: 'Cloudflare gave no address in time. Try again.',
|
|
47
|
+
errorEnded: 'The tunnel stopped. Start it again for a new address.',
|
|
48
|
+
errorRefused: 'SynaBun refused this request. Start the tunnel from SynaBun on this computer.',
|
|
49
|
+
errorUnknown: 'The tunnel did not start: {reason}',
|
|
50
|
+
errorUnknownNoReason: 'The tunnel did not start. Try again.',
|
|
51
|
+
start: 'Start tunnel',
|
|
52
|
+
stop: 'Stop',
|
|
53
|
+
cancel: 'Cancel',
|
|
54
|
+
retry: 'Try again',
|
|
55
|
+
copyBundled: 'cloudflared {version}, included with SynaBun',
|
|
56
|
+
copyDownloaded: 'cloudflared {version}, downloaded by SynaBun',
|
|
57
|
+
copySystem: 'cloudflared {version}, installed on this computer',
|
|
58
|
+
copySystemWhy: 'SynaBun could not download its own copy, so the one installed on this computer is used.',
|
|
59
|
+
mcpKeyNeeded: 'Remote MCP needs an access key. Create one below; the address to connect is then this one followed by /mcp/ and the key.',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const ERROR_COPY = Object.freeze({
|
|
63
|
+
offline: 'errorOffline', http: 'errorHttp', interrupted: 'errorInterrupted', timeout: 'errorTimeout', checksum: 'errorChecksum',
|
|
64
|
+
unpack: 'errorUnpack', disk: 'errorDisk', launch: 'errorLaunch', no_address: 'errorNoAddress', ended: 'errorEnded',
|
|
65
|
+
unsupported: 'unsupported', refused: 'errorRefused',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/** A TUNNEL_COPY sentence with its `{params}` filled in: the translator when the page gives none. */
|
|
69
|
+
export function fillTunnelCopy(key, params = {}) {
|
|
70
|
+
return String(TUNNEL_COPY[key] ?? key).replace(/\{(\w+)\}/g, (whole, name) => (params[name] != null ? params[name] : whole));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const megabytes = (bytes) => Math.max(0, Number(bytes) || 0) / (1024 * 1024);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* What a card shows for a status.
|
|
77
|
+
*
|
|
78
|
+
* @param {object | null} status the answer of GET /api/tunnel/status (or of the start / stop that came last)
|
|
79
|
+
* @param {object} [o]
|
|
80
|
+
* @param {(key: string, params?: object) => string} [o.t] a key of TUNNEL_COPY → the sentence in the page's language
|
|
81
|
+
* @param {(value: number, digits: number) => string} [o.number] a number as the page's language writes it
|
|
82
|
+
* @returns {{
|
|
83
|
+
* kind: 'restart' | 'unsupported' | 'idle' | 'downloading' | 'starting' | 'running' | 'failed',
|
|
84
|
+
* tone: 'off' | 'busy' | 'ok' | 'warn' | 'err',
|
|
85
|
+
* on: boolean,
|
|
86
|
+
* label: string, detail: string,
|
|
87
|
+
* progress: { percent: number, text: string } | null,
|
|
88
|
+
* url: string | null,
|
|
89
|
+
* action: 'start' | 'stop' | 'cancel' | 'retry' | null, actionLabel: string,
|
|
90
|
+
* copy: string, copyNote: string,
|
|
91
|
+
* poll: boolean,
|
|
92
|
+
* }}
|
|
93
|
+
* `on`: the switch stands on (something runs or is on its way). `action`: what a press does ("cancel" and
|
|
94
|
+
* "stop" are both POST /api/tunnel/stop; "start" and "retry" both POST /api/tunnel/start). `copy`: which
|
|
95
|
+
* cloudflared runs, when one does. `poll`: the state will change by itself, ask again.
|
|
96
|
+
*/
|
|
97
|
+
export function tunnelView(status, { t = fillTunnelCopy, number = (value, digits) => value.toFixed(digits) } = {}) {
|
|
98
|
+
const s = status && typeof status === 'object' ? status : {};
|
|
99
|
+
const tool = s.cloudflared && typeof s.cloudflared === 'object' ? s.cloudflared : null;
|
|
100
|
+
const view = {
|
|
101
|
+
kind: 'idle', tone: 'off', on: false, label: t('stateOff'), detail: t('idle'), progress: null,
|
|
102
|
+
url: typeof s.url === 'string' && s.url ? s.url : null,
|
|
103
|
+
action: 'start', actionLabel: t('start'), copy: '', copyNote: '', poll: false,
|
|
104
|
+
};
|
|
105
|
+
const as = (kind, tone, labelKey, detail, action) => Object.assign(view, {
|
|
106
|
+
kind, tone, label: t(labelKey), detail, action, actionLabel: action ? t(action) : '',
|
|
107
|
+
on: kind === 'downloading' || kind === 'starting' || kind === 'running', poll: kind === 'downloading' || kind === 'starting',
|
|
108
|
+
});
|
|
109
|
+
const running = () => {
|
|
110
|
+
as('running', 'ok', 'stateRunning', view.url, 'stop');
|
|
111
|
+
const source = { bundled: 'copyBundled', downloaded: 'copyDownloaded', system: 'copySystem' }[tool?.source];
|
|
112
|
+
if (source && tool.version) {
|
|
113
|
+
view.copy = t(source, { version: tool.version });
|
|
114
|
+
if (tool.source === 'system' && tool.fallback && tool.fallback.code !== 'unsupported') view.copyNote = t('copySystemWhy');
|
|
115
|
+
}
|
|
116
|
+
return view;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Nothing is known yet (the answer has not arrived): the card as it stands before a first start.
|
|
120
|
+
if (!status || typeof status !== 'object') return view;
|
|
121
|
+
|
|
122
|
+
// A server from before the tunnel program came with SynaBun: no `cloudflared` part in its answer.
|
|
123
|
+
if (!tool) {
|
|
124
|
+
if (view.url) return running();
|
|
125
|
+
if (s.starting || s.running) return as('starting', 'busy', 'stateStarting', t('starting'), 'cancel');
|
|
126
|
+
if (s.available) return as('idle', 'off', 'stateOff', t('idle'), 'start');
|
|
127
|
+
return as('restart', 'warn', 'stateRestart', t('restart'), null);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const state = typeof s.state === 'string' ? s.state : 'idle';
|
|
131
|
+
if (state === 'running' && view.url) return running();
|
|
132
|
+
if (state === 'downloading') {
|
|
133
|
+
const total = Number(tool.progress?.total) || Number(tool.download?.size) || 0;
|
|
134
|
+
const received = Math.min(Number(tool.progress?.received) || 0, total || Infinity);
|
|
135
|
+
const percent = total ? Math.max(0, Math.min(100, Math.floor((received / total) * 100))) : 0;
|
|
136
|
+
as('downloading', 'busy', 'stateDownloading', t('downloading', { received: number(megabytes(received), 1), total: number(megabytes(total), 1) }), 'cancel');
|
|
137
|
+
view.progress = { percent, text: `${percent}%` };
|
|
138
|
+
return view;
|
|
139
|
+
}
|
|
140
|
+
if (state === 'starting' || state === 'running') return as('starting', 'busy', 'stateStarting', t('starting'), 'cancel');
|
|
141
|
+
if (state === 'failed') {
|
|
142
|
+
const error = s.error && typeof s.error === 'object' ? s.error : {};
|
|
143
|
+
if (error.code === 'unsupported') return as('unsupported', 'off', 'stateUnsupported', t('unsupported'), null);
|
|
144
|
+
const reason = typeof error.reason === 'string' && error.reason.trim() ? error.reason.trim() : '';
|
|
145
|
+
let detail;
|
|
146
|
+
if (error.code === 'exited') detail = reason ? t('errorExited', { reason }) : t('errorExitedNoReason');
|
|
147
|
+
else if (ERROR_COPY[error.code]) detail = t(ERROR_COPY[error.code]);
|
|
148
|
+
else detail = typeof error.message === 'string' && error.message.trim() ? t('errorUnknown', { reason: error.message.trim() }) : t('errorUnknownNoReason');
|
|
149
|
+
return as('failed', 'err', 'stateFailed', detail, 'retry');
|
|
150
|
+
}
|
|
151
|
+
// idle
|
|
152
|
+
if (tool.state === 'unsupported') return as('unsupported', 'off', 'stateUnsupported', t('unsupported'), null);
|
|
153
|
+
if (tool.state === 'ready') return as('idle', 'off', 'stateOff', t('idle'), 'start');
|
|
154
|
+
const size = Number(tool.download?.size) || 0;
|
|
155
|
+
return as('idle', 'off', 'stateOff', size ? t('idleDownload', { size: number(megabytes(size), 0) }) : t('idle'), 'start');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The address an assistant outside connects to, or null while there is none to give: the public address
|
|
160
|
+
* followed by /mcp/ and the access key. Without a key there is no such address: the server refuses /mcp from
|
|
161
|
+
* outside (lib/request-gate.js mcpWithoutKey), so the cards offer nothing to copy and say what is missing.
|
|
162
|
+
*/
|
|
163
|
+
export function remoteMcpAddress(url, key) {
|
|
164
|
+
const base = typeof url === 'string' ? url.trim().replace(/\/+$/, '') : '';
|
|
165
|
+
const secret = typeof key === 'string' ? key.trim() : '';
|
|
166
|
+
return base && secret ? `${base}/mcp/${secret}` : null;
|
|
167
|
+
}
|