@neuralnomads/codenomad-dev 0.10.3-dev-20260213-ba418a85
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/README.md +126 -0
- package/dist/api-types.js +1 -0
- package/dist/auth/auth-store.js +134 -0
- package/dist/auth/http-auth.js +37 -0
- package/dist/auth/manager.js +128 -0
- package/dist/auth/password-hash.js +32 -0
- package/dist/auth/session-manager.js +17 -0
- package/dist/auth/token-manager.js +27 -0
- package/dist/background-processes/manager.js +437 -0
- package/dist/bin.js +24 -0
- package/dist/config/binaries.js +148 -0
- package/dist/config/location.js +57 -0
- package/dist/config/schema.js +70 -0
- package/dist/config/store.js +200 -0
- package/dist/events/bus.js +41 -0
- package/dist/filesystem/__tests__/search-cache.test.js +40 -0
- package/dist/filesystem/browser.js +285 -0
- package/dist/filesystem/search-cache.js +43 -0
- package/dist/filesystem/search.js +135 -0
- package/dist/index.js +410 -0
- package/dist/integrations/github/bot-signature.js +11 -0
- package/dist/integrations/github/git-ops.js +133 -0
- package/dist/integrations/github/github-types.js +1 -0
- package/dist/integrations/github/job-runner.js +608 -0
- package/dist/integrations/github/octokit.js +58 -0
- package/dist/integrations/github/sanitize-webhook.js +42 -0
- package/dist/integrations/github/webhook-verify.js +21 -0
- package/dist/integrations/github/workspace-context.js +10 -0
- package/dist/integrations/github/worktree-context.js +15 -0
- package/dist/launcher.js +149 -0
- package/dist/loader.js +21 -0
- package/dist/logger.js +109 -0
- package/dist/opencode/request-context.js +39 -0
- package/dist/opencode/worktree-directory.js +42 -0
- package/dist/opencode-config/README.md +32 -0
- package/dist/opencode-config/opencode.jsonc +3 -0
- package/dist/opencode-config/package.json +9 -0
- package/dist/opencode-config/plugin/codenomad.ts +32 -0
- package/dist/opencode-config/plugin/lib/background-process.ts +253 -0
- package/dist/opencode-config/plugin/lib/client.ts +133 -0
- package/dist/opencode-config/plugin/lib/request.ts +214 -0
- package/dist/opencode-config-template/README.md +32 -0
- package/dist/opencode-config-template/opencode.jsonc +3 -0
- package/dist/opencode-config-template/plugin/codenomad.ts +40 -0
- package/dist/opencode-config-template/plugin/lib/background-process.ts +160 -0
- package/dist/opencode-config-template/plugin/lib/client.ts +165 -0
- package/dist/opencode-config.js +26 -0
- package/dist/plugins/channel.js +40 -0
- package/dist/plugins/handlers.js +17 -0
- package/dist/releases/dev-release-monitor.js +75 -0
- package/dist/releases/release-monitor.js +107 -0
- package/dist/server/http-server.js +547 -0
- package/dist/server/network-addresses.js +72 -0
- package/dist/server/routes/auth-pages/login.html +134 -0
- package/dist/server/routes/auth-pages/token.html +93 -0
- package/dist/server/routes/auth.js +134 -0
- package/dist/server/routes/background-processes.js +60 -0
- package/dist/server/routes/config.js +59 -0
- package/dist/server/routes/events.js +43 -0
- package/dist/server/routes/filesystem.js +43 -0
- package/dist/server/routes/github-plugin.js +215 -0
- package/dist/server/routes/github-webhook.js +32 -0
- package/dist/server/routes/meta.js +47 -0
- package/dist/server/routes/plugin.js +52 -0
- package/dist/server/routes/storage.js +52 -0
- package/dist/server/routes/workspaces.js +89 -0
- package/dist/server/routes/worktrees.js +156 -0
- package/dist/server/tls.js +224 -0
- package/dist/storage/instance-store.js +56 -0
- package/dist/ui/__tests__/remote-ui.test.js +46 -0
- package/dist/ui/remote-ui.js +462 -0
- package/dist/workspaces/git-worktrees.js +199 -0
- package/dist/workspaces/instance-events.js +180 -0
- package/dist/workspaces/manager.js +375 -0
- package/dist/workspaces/opencode-auth.js +16 -0
- package/dist/workspaces/runtime.js +346 -0
- package/dist/workspaces/worktree-map.js +116 -0
- package/package.json +49 -0
- package/public/apple-touch-icon-180x180.png +0 -0
- package/public/assets/CodeNomad-Icon-bmTWNPXy.png +0 -0
- package/public/assets/abap-BdImnpbu.js +1 -0
- package/public/assets/actionscript-3-CfeIJUat.js +1 -0
- package/public/assets/ada-bCR0ucgS.js +1 -0
- package/public/assets/andromeeda-C-Jbm3Hp.js +1 -0
- package/public/assets/angular-html-CU67Zn6k.js +1 -0
- package/public/assets/angular-ts-BwZT4LLn.js +1 -0
- package/public/assets/apache-Pmp26Uib.js +1 -0
- package/public/assets/apex-DhZLUxFE.js +1 -0
- package/public/assets/apl-dKokRX4l.js +1 -0
- package/public/assets/applescript-Co6uUVPk.js +1 -0
- package/public/assets/ara-BRHolxvo.js +1 -0
- package/public/assets/asciidoc-Dv7Oe6Be.js +1 -0
- package/public/assets/asm-D_Q5rh1f.js +1 -0
- package/public/assets/astro-CbQHKStN.js +1 -0
- package/public/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/public/assets/awk-DMzUqQB5.js +1 -0
- package/public/assets/ayu-dark-Cv9koXgw.js +1 -0
- package/public/assets/ballerina-BFfxhgS-.js +1 -0
- package/public/assets/bat-BkioyH1T.js +1 -0
- package/public/assets/beancount-k_qm7-4y.js +1 -0
- package/public/assets/berry-D08WgyRC.js +1 -0
- package/public/assets/bibtex-CHM0blh-.js +1 -0
- package/public/assets/bicep-Bmn6On1c.js +1 -0
- package/public/assets/blade-DVc8C-J4.js +1 -0
- package/public/assets/bsl-BO_Y6i37.js +1 -0
- package/public/assets/c-BIGW1oBm.js +1 -0
- package/public/assets/cadence-Bv_4Rxtq.js +1 -0
- package/public/assets/cairo-KRGpt6FW.js +1 -0
- package/public/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/public/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/public/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/public/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/public/assets/clarity-D53aC0YG.js +1 -0
- package/public/assets/clojure-P80f7IUj.js +1 -0
- package/public/assets/cmake-D1j8_8rp.js +1 -0
- package/public/assets/cobol-nwyudZeR.js +1 -0
- package/public/assets/codeowners-Bp6g37R7.js +1 -0
- package/public/assets/codeql-DsOJ9woJ.js +1 -0
- package/public/assets/coffee-Ch7k5sss.js +1 -0
- package/public/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/public/assets/coq-DkFqJrB1.js +1 -0
- package/public/assets/core-BSTVzpXI.js +1 -0
- package/public/assets/cpp-CofmeUqb.js +1 -0
- package/public/assets/crystal-tKQVLTB8.js +1 -0
- package/public/assets/csharp-CX12Zw3r.js +1 -0
- package/public/assets/css-DPfMkruS.js +1 -0
- package/public/assets/csv-fuZLfV_i.js +1 -0
- package/public/assets/cue-D82EKSYY.js +1 -0
- package/public/assets/cypher-COkxafJQ.js +1 -0
- package/public/assets/d-85-TOEBH.js +1 -0
- package/public/assets/dark-plus-eOWES_5F.js +1 -0
- package/public/assets/dart-CF10PKvl.js +1 -0
- package/public/assets/dax-CEL-wOlO.js +1 -0
- package/public/assets/desktop-BmXAJ9_W.js +1 -0
- package/public/assets/diff-D97Zzqfu.js +1 -0
- package/public/assets/docker-BcOcwvcX.js +1 -0
- package/public/assets/dotenv-Da5cRb03.js +1 -0
- package/public/assets/dracula-BzJJZx-M.js +1 -0
- package/public/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/public/assets/dream-maker-BtqSS_iP.js +1 -0
- package/public/assets/edge-BkV0erSs.js +1 -0
- package/public/assets/elixir-CDX3lj18.js +1 -0
- package/public/assets/elm-DbKCFpqz.js +1 -0
- package/public/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/public/assets/erb-BOJIQeun.js +1 -0
- package/public/assets/erlang-DsQrWhSR.js +1 -0
- package/public/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/public/assets/everforest-light-C8M2exoo.js +1 -0
- package/public/assets/fennel-BYunw83y.js +1 -0
- package/public/assets/fish-BvzEVeQv.js +1 -0
- package/public/assets/fluent-C4IJs8-o.js +1 -0
- package/public/assets/fortran-fixed-form-BZjJHVRy.js +1 -0
- package/public/assets/fortran-free-form-D22FLkUw.js +1 -0
- package/public/assets/fsharp-CXgrBDvD.js +1 -0
- package/public/assets/gdresource-B7Tvp0Sc.js +1 -0
- package/public/assets/gdscript-DTMYz4Jt.js +1 -0
- package/public/assets/gdshader-DkwncUOv.js +1 -0
- package/public/assets/genie-D0YGMca9.js +1 -0
- package/public/assets/gherkin-DyxjwDmM.js +1 -0
- package/public/assets/git-commit-F4YmCXRG.js +1 -0
- package/public/assets/git-rebase-r7XF79zn.js +1 -0
- package/public/assets/github-dark-DHJKELXO.js +1 -0
- package/public/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/public/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/public/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/public/assets/github-light-DAi9KRSo.js +1 -0
- package/public/assets/github-light-default-D7oLnXFd.js +1 -0
- package/public/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/public/assets/gleam-BspZqrRM.js +1 -0
- package/public/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/public/assets/glimmer-ts-U6CK756n.js +1 -0
- package/public/assets/glsl-DplSGwfg.js +1 -0
- package/public/assets/gnuplot-DdkO51Og.js +1 -0
- package/public/assets/go-Dn2_MT6a.js +1 -0
- package/public/assets/graphql-ChdNCCLP.js +1 -0
- package/public/assets/groovy-gcz8RCvz.js +1 -0
- package/public/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/public/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/public/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/public/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/public/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/public/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/public/assets/hack-CaT9iCJl.js +1 -0
- package/public/assets/haml-B8DHNrY2.js +1 -0
- package/public/assets/handlebars-BL8al0AC.js +1 -0
- package/public/assets/haskell-Df6bDoY_.js +1 -0
- package/public/assets/haxe-CzTSHFRz.js +1 -0
- package/public/assets/hcl-BWvSN4gD.js +1 -0
- package/public/assets/hjson-D5-asLiD.js +1 -0
- package/public/assets/hlsl-D3lLCCz7.js +1 -0
- package/public/assets/houston-DnULxvSX.js +1 -0
- package/public/assets/html-GMplVEZG.js +1 -0
- package/public/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/public/assets/http-jrhK8wxY.js +1 -0
- package/public/assets/hurl-irOxFIW8.js +1 -0
- package/public/assets/hxml-Bvhsp5Yf.js +1 -0
- package/public/assets/hy-DFXneXwc.js +1 -0
- package/public/assets/imba-DGztddWO.js +1 -0
- package/public/assets/index-D4PT0yE4.js +1 -0
- package/public/assets/index-DN20ggb1.js +1 -0
- package/public/assets/index-DdQ7zIzB.js +1 -0
- package/public/assets/index-Dl-rJJuP.js +1 -0
- package/public/assets/index-Dlo2gDiy.css +1 -0
- package/public/assets/ini-BEwlwnbL.js +1 -0
- package/public/assets/java-CylS5w8V.js +1 -0
- package/public/assets/javascript-wDzz0qaB.js +1 -0
- package/public/assets/jinja-4LBKfQ-Z.js +1 -0
- package/public/assets/jison-wvAkD_A8.js +1 -0
- package/public/assets/json-Cp-IABpG.js +1 -0
- package/public/assets/json5-C9tS-k6U.js +1 -0
- package/public/assets/jsonc-Des-eS-w.js +1 -0
- package/public/assets/jsonl-DcaNXYhu.js +1 -0
- package/public/assets/jsonnet-DFQXde-d.js +1 -0
- package/public/assets/jssm-C2t-YnRu.js +1 -0
- package/public/assets/jsx-g9-lgVsj.js +1 -0
- package/public/assets/julia-C8NyazO9.js +1 -0
- package/public/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/public/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/public/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/public/assets/kdl-DV7GczEv.js +1 -0
- package/public/assets/kotlin-BdnUsdx6.js +1 -0
- package/public/assets/kusto-BvAqAH-y.js +1 -0
- package/public/assets/laserwave-DUszq2jm.js +1 -0
- package/public/assets/latex-BUKiar2Z.js +1 -0
- package/public/assets/lean-DP1Csr6i.js +1 -0
- package/public/assets/less-B1dDrJ26.js +1 -0
- package/public/assets/light-plus-B7mTdjB0.js +1 -0
- package/public/assets/liquid-DYVedYrR.js +1 -0
- package/public/assets/llvm-BtvRca6l.js +1 -0
- package/public/assets/loading-CmEVQgyj.css +1 -0
- package/public/assets/loading-DgqIiz-T.js +1 -0
- package/public/assets/log-2UxHyX5q.js +1 -0
- package/public/assets/logo-BtOb2qkB.js +1 -0
- package/public/assets/lua-BbnMAYS6.js +1 -0
- package/public/assets/luau-CXu1NL6O.js +1 -0
- package/public/assets/main-CSlDZj4f.js +188 -0
- package/public/assets/main-HAZkIolJ.css +19 -0
- package/public/assets/make-CHLpvVh8.js +1 -0
- package/public/assets/markdown-Cvjx9yec.js +1 -0
- package/public/assets/marko-CPi9NSCl.js +1 -0
- package/public/assets/material-theme-D5KoaKCx.js +1 -0
- package/public/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/public/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/public/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/public/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/public/assets/matlab-D7o27uSR.js +1 -0
- package/public/assets/mdc-DUICxH0z.js +1 -0
- package/public/assets/mdx-Cmh6b_Ma.js +1 -0
- package/public/assets/mermaid-DKYwYmdq.js +1 -0
- package/public/assets/min-dark-CafNBF8u.js +1 -0
- package/public/assets/min-light-CTRr51gU.js +1 -0
- package/public/assets/mipsasm-CKIfxQSi.js +1 -0
- package/public/assets/mojo-1DNp92w6.js +1 -0
- package/public/assets/monokai-D4h5O-jR.js +1 -0
- package/public/assets/move-Bu9oaDYs.js +1 -0
- package/public/assets/narrat-DRg8JJMk.js +1 -0
- package/public/assets/nextflow-CUEJCptM.js +1 -0
- package/public/assets/nginx-DknmC5AR.js +1 -0
- package/public/assets/night-owl-C39BiMTA.js +1 -0
- package/public/assets/nim-CVrawwO9.js +1 -0
- package/public/assets/nix-BbRYJGeE.js +1 -0
- package/public/assets/nord-Ddv68eIx.js +1 -0
- package/public/assets/nushell-C-sUppwS.js +1 -0
- package/public/assets/objective-c-DXmwc3jG.js +1 -0
- package/public/assets/objective-cpp-CLxacb5B.js +1 -0
- package/public/assets/ocaml-C0hk2d4L.js +1 -0
- package/public/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/public/assets/one-light-PoHY5YXO.js +1 -0
- package/public/assets/pascal-D93ZcfNL.js +1 -0
- package/public/assets/perl-C0TMdlhV.js +1 -0
- package/public/assets/php-CDn_0X-4.js +1 -0
- package/public/assets/pkl-u5AG7uiY.js +1 -0
- package/public/assets/plastic-3e1v2bzS.js +1 -0
- package/public/assets/plsql-ChMvpjG-.js +1 -0
- package/public/assets/po-BTJTHyun.js +1 -0
- package/public/assets/poimandres-CS3Unz2-.js +1 -0
- package/public/assets/polar-C0HS_06l.js +1 -0
- package/public/assets/postcss-CXtECtnM.js +1 -0
- package/public/assets/powerquery-CEu0bR-o.js +1 -0
- package/public/assets/powershell-Dpen1YoG.js +1 -0
- package/public/assets/prisma-Dd19v3D-.js +1 -0
- package/public/assets/prolog-CbFg5uaA.js +1 -0
- package/public/assets/proto-DyJlTyXw.js +1 -0
- package/public/assets/pug-CGlum2m_.js +1 -0
- package/public/assets/puppet-BMWR74SV.js +1 -0
- package/public/assets/purescript-CklMAg4u.js +1 -0
- package/public/assets/python-B6aJPvgy.js +1 -0
- package/public/assets/qml-3beO22l8.js +1 -0
- package/public/assets/qmldir-C8lEn-DE.js +1 -0
- package/public/assets/qss-IeuSbFQv.js +1 -0
- package/public/assets/r-DiinP2Uv.js +1 -0
- package/public/assets/racket-BqYA7rlc.js +1 -0
- package/public/assets/raku-DXvB9xmW.js +1 -0
- package/public/assets/razor-WgofotgN.js +1 -0
- package/public/assets/red-bN70gL4F.js +1 -0
- package/public/assets/reg-C-SQnVFl.js +1 -0
- package/public/assets/regexp-CDVJQ6XC.js +1 -0
- package/public/assets/rel-C3B-1QV4.js +1 -0
- package/public/assets/riscv-BM1_JUlF.js +1 -0
- package/public/assets/rose-pine-BHrmToEH.js +1 -0
- package/public/assets/rose-pine-dawn-CnK8MTSM.js +1 -0
- package/public/assets/rose-pine-moon-NleAzG8P.js +1 -0
- package/public/assets/rosmsg-BJDFO7_C.js +1 -0
- package/public/assets/rst-B0xPkSld.js +1 -0
- package/public/assets/ruby-BvKwtOVI.js +1 -0
- package/public/assets/rust-B1yitclQ.js +1 -0
- package/public/assets/sas-cz2c8ADy.js +1 -0
- package/public/assets/sass-Cj5Yp3dK.js +1 -0
- package/public/assets/scala-C151Ov-r.js +1 -0
- package/public/assets/scheme-C98Dy4si.js +1 -0
- package/public/assets/scss-OYdSNvt2.js +1 -0
- package/public/assets/sdbl-DVxCFoDh.js +1 -0
- package/public/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/public/assets/shellscript-Yzrsuije.js +1 -0
- package/public/assets/shellsession-BADoaaVG.js +1 -0
- package/public/assets/slack-dark-BthQWCQV.js +1 -0
- package/public/assets/slack-ochin-DqwNpetd.js +1 -0
- package/public/assets/smalltalk-BERRCDM3.js +1 -0
- package/public/assets/snazzy-light-Bw305WKR.js +1 -0
- package/public/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/public/assets/solarized-light-L9t79GZl.js +1 -0
- package/public/assets/solidity-BbcW6ACK.js +1 -0
- package/public/assets/soy-Brmx7dQM.js +1 -0
- package/public/assets/sparql-rVzFXLq3.js +1 -0
- package/public/assets/splunk-BtCnVYZw.js +1 -0
- package/public/assets/sql-BLtJtn59.js +1 -0
- package/public/assets/ssh-config-_ykCGR6B.js +1 -0
- package/public/assets/stata-BH5u7GGu.js +1 -0
- package/public/assets/stylus-BEDo0Tqx.js +1 -0
- package/public/assets/svelte-3Dk4HxPD.js +1 -0
- package/public/assets/swift-Dg5xB15N.js +1 -0
- package/public/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/public/assets/system-verilog-CnnmHF94.js +1 -0
- package/public/assets/systemd-4A_iFExJ.js +1 -0
- package/public/assets/talonscript-CkByrt1z.js +1 -0
- package/public/assets/tasl-QIJgUcNo.js +1 -0
- package/public/assets/tcl-dwOrl1Do.js +1 -0
- package/public/assets/templ-W15q3VgB.js +1 -0
- package/public/assets/terraform-BETggiCN.js +1 -0
- package/public/assets/tex-Cppo0RY3.js +1 -0
- package/public/assets/tokyo-night-hegEt444.js +1 -0
- package/public/assets/toml-vGWfd6FD.js +1 -0
- package/public/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/public/assets/tsv-B_m7g4N7.js +1 -0
- package/public/assets/tsx-COt5Ahok.js +1 -0
- package/public/assets/turtle-BsS91CYL.js +1 -0
- package/public/assets/twig-CO9l9SDP.js +1 -0
- package/public/assets/typescript-BPQ3VLAy.js +1 -0
- package/public/assets/typespec-Df68jz8_.js +1 -0
- package/public/assets/typst-DHCkPAjA.js +1 -0
- package/public/assets/v-BcVCzyr7.js +1 -0
- package/public/assets/vala-CsfeWuGM.js +1 -0
- package/public/assets/vb-D17OF-Vu.js +1 -0
- package/public/assets/verilog-BQ8w6xss.js +1 -0
- package/public/assets/vesper-DU1UobuO.js +1 -0
- package/public/assets/vhdl-CeAyd5Ju.js +1 -0
- package/public/assets/viml-CJc9bBzg.js +1 -0
- package/public/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/public/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/public/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/public/assets/vue-CCoi5OLL.js +1 -0
- package/public/assets/vue-html-DAAvJJDi.js +1 -0
- package/public/assets/vue-vine-_Ih-lPRR.js +1 -0
- package/public/assets/vyper-CDx5xZoG.js +1 -0
- package/public/assets/wasm-CG6Dc4jp.js +1 -0
- package/public/assets/wasm-MzD3tlZU.js +1 -0
- package/public/assets/wenyan-BV7otONQ.js +1 -0
- package/public/assets/wgsl-Dx-B1_4e.js +1 -0
- package/public/assets/wikitext-BhOHFoWU.js +1 -0
- package/public/assets/wit-5i3qLPDT.js +1 -0
- package/public/assets/wolfram-lXgVvXCa.js +1 -0
- package/public/assets/xml-sdJ4AIDG.js +1 -0
- package/public/assets/xsl-CtQFsRM5.js +1 -0
- package/public/assets/yaml-Buea-lGh.js +1 -0
- package/public/assets/zenscript-DVFEvuxE.js +1 -0
- package/public/assets/zig-VOosw3JB.js +1 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +38 -0
- package/public/loading.html +28 -0
- package/public/logo.png +0 -0
- package/public/manifest.webmanifest +1 -0
- package/public/maskable-icon-512x512.png +0 -0
- package/public/monaco/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- package/public/monaco/vs/base/worker/workerMain.js +31 -0
- package/public/monaco/vs/basic-languages/cpp/cpp.js +10 -0
- package/public/monaco/vs/basic-languages/kotlin/kotlin.js +10 -0
- package/public/monaco/vs/basic-languages/markdown/markdown.js +10 -0
- package/public/monaco/vs/basic-languages/python/python.js +10 -0
- package/public/monaco/vs/editor/editor.main.css +8 -0
- package/public/monaco/vs/editor/editor.main.js +798 -0
- package/public/monaco/vs/language/css/cssMode.js +13 -0
- package/public/monaco/vs/language/css/cssWorker.js +77 -0
- package/public/monaco/vs/language/html/htmlMode.js +13 -0
- package/public/monaco/vs/language/html/htmlWorker.js +454 -0
- package/public/monaco/vs/language/json/jsonMode.js +19 -0
- package/public/monaco/vs/language/json/jsonWorker.js +42 -0
- package/public/monaco/vs/language/typescript/tsMode.js +20 -0
- package/public/monaco/vs/language/typescript/tsWorker.js +51328 -0
- package/public/monaco/vs/loader.js +11 -0
- package/public/monaco.worker.js +7 -0
- package/public/pwa-192x192.png +0 -0
- package/public/pwa-512x512.png +0 -0
- package/public/pwa-64x64.png +0 -0
- package/public/registerSW.js +1 -0
- package/public/sw.js +1 -0
- package/public/ui-version.json +3 -0
- package/public/workbox-60d14903.js +1 -0
- package/scripts/copy-auth-pages.mjs +22 -0
- package/scripts/copy-opencode-config.mjs +61 -0
- package/scripts/copy-ui-dist.mjs +21 -0
- package/src/api-types.ts +326 -0
- package/src/auth/auth-store.ts +175 -0
- package/src/auth/http-auth.ts +38 -0
- package/src/auth/manager.ts +163 -0
- package/src/auth/password-hash.ts +49 -0
- package/src/auth/session-manager.ts +23 -0
- package/src/auth/token-manager.ts +32 -0
- package/src/background-processes/manager.ts +519 -0
- package/src/bin.ts +29 -0
- package/src/config/binaries.ts +192 -0
- package/src/config/location.ts +78 -0
- package/src/config/schema.ts +104 -0
- package/src/config/store.ts +244 -0
- package/src/events/bus.ts +45 -0
- package/src/filesystem/__tests__/search-cache.test.ts +61 -0
- package/src/filesystem/browser.ts +353 -0
- package/src/filesystem/search-cache.ts +66 -0
- package/src/filesystem/search.ts +184 -0
- package/src/index.ts +540 -0
- package/src/launcher.ts +177 -0
- package/src/loader.ts +21 -0
- package/src/logger.ts +133 -0
- package/src/opencode-config.ts +31 -0
- package/src/plugins/channel.ts +55 -0
- package/src/plugins/handlers.ts +36 -0
- package/src/releases/dev-release-monitor.ts +118 -0
- package/src/releases/release-monitor.ts +149 -0
- package/src/server/http-server.ts +693 -0
- package/src/server/network-addresses.ts +75 -0
- package/src/server/routes/auth-pages/login.html +134 -0
- package/src/server/routes/auth-pages/token.html +93 -0
- package/src/server/routes/auth.ts +164 -0
- package/src/server/routes/background-processes.ts +85 -0
- package/src/server/routes/config.ts +76 -0
- package/src/server/routes/events.ts +61 -0
- package/src/server/routes/filesystem.ts +54 -0
- package/src/server/routes/meta.ts +58 -0
- package/src/server/routes/plugin.ts +75 -0
- package/src/server/routes/storage.ts +66 -0
- package/src/server/routes/workspaces.ts +113 -0
- package/src/server/routes/worktrees.ts +195 -0
- package/src/server/tls.ts +283 -0
- package/src/storage/instance-store.ts +64 -0
- package/src/ui/__tests__/remote-ui.test.ts +58 -0
- package/src/ui/remote-ui.ts +571 -0
- package/src/workspaces/git-worktrees.ts +241 -0
- package/src/workspaces/instance-events.ts +226 -0
- package/src/workspaces/manager.ts +493 -0
- package/src/workspaces/opencode-auth.ts +22 -0
- package/src/workspaces/runtime.ts +428 -0
- package/src/workspaces/worktree-map.ts +129 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const KEEP_URL_KEYS = new Set(["html_url"]);
|
|
2
|
+
function shouldDropKey(key) {
|
|
3
|
+
if (key === "installation")
|
|
4
|
+
return true;
|
|
5
|
+
if (key === "url")
|
|
6
|
+
return true;
|
|
7
|
+
if (key.endsWith("_url") && !KEEP_URL_KEYS.has(key))
|
|
8
|
+
return true;
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
function sanitizeValue(value) {
|
|
12
|
+
if (Array.isArray(value)) {
|
|
13
|
+
return value.map((item) => sanitizeValue(item));
|
|
14
|
+
}
|
|
15
|
+
if (!value || typeof value !== "object") {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
20
|
+
// Never modify body fields; this preserves user content.
|
|
21
|
+
if (key === "body") {
|
|
22
|
+
out[key] = raw;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (shouldDropKey(key)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
out[key] = sanitizeValue(raw);
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
export function sanitizeGitHubWebhookPayload(payload) {
|
|
33
|
+
// Deep clone first to drop prototypes/functions and ensure deterministic output.
|
|
34
|
+
let cloned;
|
|
35
|
+
try {
|
|
36
|
+
cloned = JSON.parse(JSON.stringify(payload));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
cloned = payload;
|
|
40
|
+
}
|
|
41
|
+
return sanitizeValue(cloned);
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
export function verifyGitHubWebhookSignature(params) {
|
|
3
|
+
const secret = (params.secret ?? "").trim();
|
|
4
|
+
if (!secret)
|
|
5
|
+
return false;
|
|
6
|
+
const signature = (params.signatureHeader ?? "").trim();
|
|
7
|
+
if (!signature.startsWith("sha256="))
|
|
8
|
+
return false;
|
|
9
|
+
const expectedHex = crypto.createHmac("sha256", secret).update(params.body).digest("hex");
|
|
10
|
+
const expected = `sha256=${expectedHex}`;
|
|
11
|
+
try {
|
|
12
|
+
const a = Buffer.from(signature, "utf8");
|
|
13
|
+
const b = Buffer.from(expected, "utf8");
|
|
14
|
+
if (a.length !== b.length)
|
|
15
|
+
return false;
|
|
16
|
+
return crypto.timingSafeEqual(a, b);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const workspaceContext = new Map();
|
|
2
|
+
export function setGitHubWorkspaceContext(workspaceId, context) {
|
|
3
|
+
workspaceContext.set(workspaceId, context);
|
|
4
|
+
}
|
|
5
|
+
export function getGitHubWorkspaceContext(workspaceId) {
|
|
6
|
+
return workspaceContext.get(workspaceId) ?? null;
|
|
7
|
+
}
|
|
8
|
+
export function clearGitHubWorkspaceContext(workspaceId) {
|
|
9
|
+
workspaceContext.delete(workspaceId);
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const worktreeContextByWorkspace = new Map();
|
|
2
|
+
export function setGitHubWorktreeContext(workspaceId, worktreeSlug, context) {
|
|
3
|
+
let map = worktreeContextByWorkspace.get(workspaceId);
|
|
4
|
+
if (!map) {
|
|
5
|
+
map = new Map();
|
|
6
|
+
worktreeContextByWorkspace.set(workspaceId, map);
|
|
7
|
+
}
|
|
8
|
+
map.set(worktreeSlug, context);
|
|
9
|
+
}
|
|
10
|
+
export function getGitHubWorktreeContext(workspaceId, worktreeSlug) {
|
|
11
|
+
return worktreeContextByWorkspace.get(workspaceId)?.get(worktreeSlug) ?? null;
|
|
12
|
+
}
|
|
13
|
+
export function clearGitHubWorktreeContext(workspaceId) {
|
|
14
|
+
worktreeContextByWorkspace.delete(workspaceId);
|
|
15
|
+
}
|
package/dist/launcher.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
const APP_ARGS = (url) => [`--app=${url}`, "--new-window"];
|
|
5
|
+
export async function launchInBrowser(url, logger) {
|
|
6
|
+
const { platform, candidates, manualExamples } = buildPlatformCandidates(url);
|
|
7
|
+
console.log(`Attempting to launch browser (${platform}) using:`);
|
|
8
|
+
candidates.forEach((candidate) => console.log(` - ${candidate.name}: ${candidate.command}`));
|
|
9
|
+
for (const candidate of candidates) {
|
|
10
|
+
const success = await tryLaunch(candidate, url, logger);
|
|
11
|
+
if (success) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
console.error("No supported browser found to launch. Run without --launch and use one of the commands below or install a compatible browser.");
|
|
16
|
+
if (manualExamples.length > 0) {
|
|
17
|
+
console.error("Manual launch commands:");
|
|
18
|
+
manualExamples.forEach((line) => console.error(` ${line}`));
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
async function tryLaunch(candidate, url, logger) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
let resolved = false;
|
|
25
|
+
try {
|
|
26
|
+
const args = candidate.args(url);
|
|
27
|
+
const child = spawn(candidate.command, args, { stdio: "ignore", detached: true });
|
|
28
|
+
child.once("error", (error) => {
|
|
29
|
+
if (resolved)
|
|
30
|
+
return;
|
|
31
|
+
resolved = true;
|
|
32
|
+
logger.debug({ err: error, candidate: candidate.name, command: candidate.command, args }, "Browser launch failed");
|
|
33
|
+
resolve(false);
|
|
34
|
+
});
|
|
35
|
+
child.once("spawn", () => {
|
|
36
|
+
if (resolved)
|
|
37
|
+
return;
|
|
38
|
+
resolved = true;
|
|
39
|
+
logger.info({
|
|
40
|
+
browser: candidate.name,
|
|
41
|
+
command: candidate.command,
|
|
42
|
+
args,
|
|
43
|
+
fullCommand: [candidate.command, ...args].join(" "),
|
|
44
|
+
}, "Launched browser in app mode");
|
|
45
|
+
child.unref();
|
|
46
|
+
resolve(true);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (resolved)
|
|
51
|
+
return;
|
|
52
|
+
resolved = true;
|
|
53
|
+
logger.debug({ err: error, candidate: candidate.name, command: candidate.command }, "Browser spawn threw");
|
|
54
|
+
resolve(false);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function buildPlatformCandidates(url) {
|
|
59
|
+
switch (os.platform()) {
|
|
60
|
+
case "darwin":
|
|
61
|
+
return {
|
|
62
|
+
platform: "macOS",
|
|
63
|
+
candidates: buildMacCandidates(),
|
|
64
|
+
manualExamples: buildMacManualExamples(url),
|
|
65
|
+
};
|
|
66
|
+
case "win32":
|
|
67
|
+
return {
|
|
68
|
+
platform: "Windows",
|
|
69
|
+
candidates: buildWindowsCandidates(),
|
|
70
|
+
manualExamples: buildWindowsManualExamples(url),
|
|
71
|
+
};
|
|
72
|
+
default:
|
|
73
|
+
return {
|
|
74
|
+
platform: "Linux",
|
|
75
|
+
candidates: buildLinuxCandidates(),
|
|
76
|
+
manualExamples: buildLinuxManualExamples(url),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function buildMacCandidates() {
|
|
81
|
+
const apps = [
|
|
82
|
+
{ name: "Google Chrome", path: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" },
|
|
83
|
+
{ name: "Google Chrome Canary", path: "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary" },
|
|
84
|
+
{ name: "Microsoft Edge", path: "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" },
|
|
85
|
+
{ name: "Brave Browser", path: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" },
|
|
86
|
+
{ name: "Chromium", path: "/Applications/Chromium.app/Contents/MacOS/Chromium" },
|
|
87
|
+
{ name: "Vivaldi", path: "/Applications/Vivaldi.app/Contents/MacOS/Vivaldi" },
|
|
88
|
+
{ name: "Arc", path: "/Applications/Arc.app/Contents/MacOS/Arc" },
|
|
89
|
+
];
|
|
90
|
+
return apps.map((entry) => ({ name: entry.name, command: entry.path, args: APP_ARGS }));
|
|
91
|
+
}
|
|
92
|
+
function buildWindowsCandidates() {
|
|
93
|
+
const programFiles = process.env["ProgramFiles"];
|
|
94
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"];
|
|
95
|
+
const localAppData = process.env["LocalAppData"];
|
|
96
|
+
const paths = [
|
|
97
|
+
[programFiles, "Google/Chrome/Application/chrome.exe", "Google Chrome"],
|
|
98
|
+
[programFilesX86, "Google/Chrome/Application/chrome.exe", "Google Chrome (x86)"],
|
|
99
|
+
[localAppData, "Google/Chrome/Application/chrome.exe", "Google Chrome (User)"],
|
|
100
|
+
[programFiles, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge"],
|
|
101
|
+
[programFilesX86, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge (x86)"],
|
|
102
|
+
[localAppData, "Microsoft/Edge/Application/msedge.exe", "Microsoft Edge (User)"],
|
|
103
|
+
[programFiles, "BraveSoftware/Brave-Browser/Application/brave.exe", "Brave"],
|
|
104
|
+
[localAppData, "BraveSoftware/Brave-Browser/Application/brave.exe", "Brave (User)"],
|
|
105
|
+
[programFiles, "Chromium/Application/chromium.exe", "Chromium"],
|
|
106
|
+
];
|
|
107
|
+
return paths
|
|
108
|
+
.filter(([root]) => Boolean(root))
|
|
109
|
+
.map(([root, rel, name]) => ({
|
|
110
|
+
name,
|
|
111
|
+
command: path.join(root, rel),
|
|
112
|
+
args: APP_ARGS,
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
function buildLinuxCandidates() {
|
|
116
|
+
const names = [
|
|
117
|
+
"google-chrome",
|
|
118
|
+
"google-chrome-stable",
|
|
119
|
+
"chromium",
|
|
120
|
+
"chromium-browser",
|
|
121
|
+
"brave-browser",
|
|
122
|
+
"microsoft-edge",
|
|
123
|
+
"microsoft-edge-stable",
|
|
124
|
+
"vivaldi",
|
|
125
|
+
];
|
|
126
|
+
return names.map((name) => ({ name, command: name, args: APP_ARGS }));
|
|
127
|
+
}
|
|
128
|
+
function buildMacManualExamples(url) {
|
|
129
|
+
return [
|
|
130
|
+
`"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --app="${url}" --new-window`,
|
|
131
|
+
`"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge" --app="${url}" --new-window`,
|
|
132
|
+
`"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" --app="${url}" --new-window`,
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
function buildWindowsManualExamples(url) {
|
|
136
|
+
return [
|
|
137
|
+
`"%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe" --app="${url}" --new-window`,
|
|
138
|
+
`"%ProgramFiles%\\Microsoft\\Edge\\Application\\msedge.exe" --app="${url}" --new-window`,
|
|
139
|
+
`"%ProgramFiles%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe" --app="${url}" --new-window`,
|
|
140
|
+
];
|
|
141
|
+
}
|
|
142
|
+
function buildLinuxManualExamples(url) {
|
|
143
|
+
return [
|
|
144
|
+
`google-chrome --app="${url}" --new-window`,
|
|
145
|
+
`chromium --app="${url}" --new-window`,
|
|
146
|
+
`brave-browser --app="${url}" --new-window`,
|
|
147
|
+
`microsoft-edge --app="${url}" --new-window`,
|
|
148
|
+
];
|
|
149
|
+
}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export async function resolve(specifier, context, defaultResolve) {
|
|
2
|
+
try {
|
|
3
|
+
return await defaultResolve(specifier, context, defaultResolve);
|
|
4
|
+
}
|
|
5
|
+
catch (error) {
|
|
6
|
+
if (shouldRetry(specifier, error)) {
|
|
7
|
+
const retried = specifier.endsWith(".js") ? specifier : `${specifier}.js`;
|
|
8
|
+
return defaultResolve(retried, context, defaultResolve);
|
|
9
|
+
}
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function shouldRetry(specifier, error) {
|
|
14
|
+
if (!error || error.code !== "ERR_MODULE_NOT_FOUND") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Transform } from "node:stream";
|
|
2
|
+
import pino from "pino";
|
|
3
|
+
const LEVEL_LABELS = {
|
|
4
|
+
10: "trace",
|
|
5
|
+
20: "debug",
|
|
6
|
+
30: "info",
|
|
7
|
+
40: "warn",
|
|
8
|
+
50: "error",
|
|
9
|
+
60: "fatal",
|
|
10
|
+
};
|
|
11
|
+
const LIFECYCLE_COMPONENTS = new Set(["app", "workspace"]);
|
|
12
|
+
const OMITTED_FIELDS = new Set(["time", "msg", "level", "component", "module"]);
|
|
13
|
+
export function createLogger(options = {}) {
|
|
14
|
+
const level = (options.level ?? process.env.CLI_LOG_LEVEL ?? "info").toLowerCase();
|
|
15
|
+
const destination = options.destination ?? process.env.CLI_LOG_DESTINATION ?? "stdout";
|
|
16
|
+
const baseComponent = options.component ?? "app";
|
|
17
|
+
const loggerOptions = {
|
|
18
|
+
level,
|
|
19
|
+
base: { component: baseComponent },
|
|
20
|
+
timestamp: false,
|
|
21
|
+
};
|
|
22
|
+
if (destination && destination !== "stdout") {
|
|
23
|
+
const stream = pino.destination({ dest: destination, mkdir: true, sync: false });
|
|
24
|
+
return pino(loggerOptions, stream);
|
|
25
|
+
}
|
|
26
|
+
const lifecycleStream = new LifecycleLogStream({ restrictInfoToLifecycle: level === "info" });
|
|
27
|
+
lifecycleStream.pipe(process.stdout);
|
|
28
|
+
return pino(loggerOptions, lifecycleStream);
|
|
29
|
+
}
|
|
30
|
+
class LifecycleLogStream extends Transform {
|
|
31
|
+
constructor(options) {
|
|
32
|
+
super();
|
|
33
|
+
this.options = options;
|
|
34
|
+
this.buffer = "";
|
|
35
|
+
}
|
|
36
|
+
_transform(chunk, _encoding, callback) {
|
|
37
|
+
this.buffer += chunk.toString();
|
|
38
|
+
let newlineIndex = this.buffer.indexOf("\n");
|
|
39
|
+
while (newlineIndex >= 0) {
|
|
40
|
+
const line = this.buffer.slice(0, newlineIndex);
|
|
41
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
42
|
+
this.pushFormatted(line);
|
|
43
|
+
newlineIndex = this.buffer.indexOf("\n");
|
|
44
|
+
}
|
|
45
|
+
callback();
|
|
46
|
+
}
|
|
47
|
+
_flush(callback) {
|
|
48
|
+
if (this.buffer.length > 0) {
|
|
49
|
+
this.pushFormatted(this.buffer);
|
|
50
|
+
this.buffer = "";
|
|
51
|
+
}
|
|
52
|
+
callback();
|
|
53
|
+
}
|
|
54
|
+
pushFormatted(line) {
|
|
55
|
+
if (!line.trim()) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
let entry;
|
|
59
|
+
try {
|
|
60
|
+
entry = JSON.parse(line);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const levelNumber = typeof entry.level === "number" ? entry.level : 30;
|
|
66
|
+
const levelLabel = LEVEL_LABELS[levelNumber] ?? "info";
|
|
67
|
+
const component = entry.component ?? entry.module ?? "app";
|
|
68
|
+
if (this.options.restrictInfoToLifecycle && levelNumber <= 30 && !LIFECYCLE_COMPONENTS.has(component)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const message = typeof entry.msg === "string" ? entry.msg : "";
|
|
72
|
+
const metadata = this.formatMetadata(entry);
|
|
73
|
+
const formatted = metadata.length > 0 ? `[${levelLabel.toUpperCase()}] [${component}] ${message} ${metadata}` : `[${levelLabel.toUpperCase()}] [${component}] ${message}`;
|
|
74
|
+
this.push(`${formatted}\n`);
|
|
75
|
+
}
|
|
76
|
+
formatMetadata(entry) {
|
|
77
|
+
const pairs = [];
|
|
78
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
79
|
+
if (OMITTED_FIELDS.has(key)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (key === "err" && value && typeof value === "object") {
|
|
83
|
+
const err = value;
|
|
84
|
+
const errLabel = err.type ?? "Error";
|
|
85
|
+
const errMessage = err.message ? `: ${err.message}` : "";
|
|
86
|
+
pairs.push(`err=${errLabel}${errMessage}`);
|
|
87
|
+
if (err.stack) {
|
|
88
|
+
pairs.push(`stack="${err.stack}"`);
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
pairs.push(`${key}=${this.stringifyValue(value)}`);
|
|
93
|
+
}
|
|
94
|
+
return pairs.join(" ").trim();
|
|
95
|
+
}
|
|
96
|
+
stringifyValue(value) {
|
|
97
|
+
if (value === undefined)
|
|
98
|
+
return "undefined";
|
|
99
|
+
if (value === null)
|
|
100
|
+
return "null";
|
|
101
|
+
if (typeof value === "string")
|
|
102
|
+
return value;
|
|
103
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
104
|
+
return String(value);
|
|
105
|
+
if (value instanceof Error)
|
|
106
|
+
return value.message ?? value.name;
|
|
107
|
+
return JSON.stringify(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isValidWorktreeSlug } from "../workspaces/git-worktrees";
|
|
2
|
+
import { resolveWorktreeDirectory } from "./worktree-directory";
|
|
3
|
+
const INSTANCE_PROXY_HOST = "127.0.0.1";
|
|
4
|
+
export async function buildOpencodeRequestContext(params) {
|
|
5
|
+
const workspace = params.workspaceManager.get(params.workspaceId);
|
|
6
|
+
if (!workspace) {
|
|
7
|
+
throw new Error("Workspace not found");
|
|
8
|
+
}
|
|
9
|
+
const port = params.workspaceManager.getInstancePort(params.workspaceId);
|
|
10
|
+
if (!port) {
|
|
11
|
+
throw new Error("Workspace instance is not ready");
|
|
12
|
+
}
|
|
13
|
+
if (!isValidWorktreeSlug(params.worktreeSlug)) {
|
|
14
|
+
throw new Error("Invalid worktree slug");
|
|
15
|
+
}
|
|
16
|
+
const directory = await resolveWorktreeDirectory({
|
|
17
|
+
workspaceId: params.workspaceId,
|
|
18
|
+
workspacePath: workspace.path,
|
|
19
|
+
worktreeSlug: params.worktreeSlug,
|
|
20
|
+
logger: params.logger,
|
|
21
|
+
});
|
|
22
|
+
if (!directory) {
|
|
23
|
+
throw new Error("Worktree not found");
|
|
24
|
+
}
|
|
25
|
+
const instanceAuthHeader = params.workspaceManager.getInstanceAuthorizationHeader(params.workspaceId);
|
|
26
|
+
const isNonASCII = /[^\x00-\x7F]/.test(directory);
|
|
27
|
+
const encodedDirectory = isNonASCII ? encodeURIComponent(directory) : directory;
|
|
28
|
+
const headers = {
|
|
29
|
+
"x-opencode-directory": encodedDirectory,
|
|
30
|
+
};
|
|
31
|
+
if (instanceAuthHeader) {
|
|
32
|
+
headers.authorization = instanceAuthHeader;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
baseUrl: `http://${INSTANCE_PROXY_HOST}:${port}`,
|
|
36
|
+
directory,
|
|
37
|
+
headers,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { resolveRepoRoot, listWorktrees } from "../workspaces/git-worktrees";
|
|
2
|
+
const WORKTREE_CACHE_TTL_MS = 2000;
|
|
3
|
+
const worktreeCache = new Map();
|
|
4
|
+
async function getCachedWorktrees(params) {
|
|
5
|
+
const cached = worktreeCache.get(params.workspaceId);
|
|
6
|
+
const now = Date.now();
|
|
7
|
+
if (cached && cached.expiresAt > now) {
|
|
8
|
+
return cached;
|
|
9
|
+
}
|
|
10
|
+
const { repoRoot } = await resolveRepoRoot(params.workspacePath, params.logger);
|
|
11
|
+
const worktrees = await listWorktrees({ repoRoot, workspaceFolder: params.workspacePath, logger: params.logger });
|
|
12
|
+
const entry = {
|
|
13
|
+
expiresAt: now + WORKTREE_CACHE_TTL_MS,
|
|
14
|
+
repoRoot,
|
|
15
|
+
worktrees: worktrees.map((wt) => ({ slug: wt.slug, directory: wt.directory })),
|
|
16
|
+
};
|
|
17
|
+
worktreeCache.set(params.workspaceId, entry);
|
|
18
|
+
return entry;
|
|
19
|
+
}
|
|
20
|
+
export async function resolveWorktreeDirectory(params) {
|
|
21
|
+
const { worktreeSlug } = params;
|
|
22
|
+
const cached = await getCachedWorktrees({
|
|
23
|
+
workspaceId: params.workspaceId,
|
|
24
|
+
workspacePath: params.workspacePath,
|
|
25
|
+
logger: params.logger,
|
|
26
|
+
});
|
|
27
|
+
const match = cached.worktrees.find((wt) => wt.slug === worktreeSlug);
|
|
28
|
+
if (match) {
|
|
29
|
+
return match.directory;
|
|
30
|
+
}
|
|
31
|
+
// If the slug is new (e.g., created moments ago), refresh once.
|
|
32
|
+
worktreeCache.delete(params.workspaceId);
|
|
33
|
+
const refreshed = await getCachedWorktrees({
|
|
34
|
+
workspaceId: params.workspaceId,
|
|
35
|
+
workspacePath: params.workspacePath,
|
|
36
|
+
logger: params.logger,
|
|
37
|
+
});
|
|
38
|
+
return refreshed.worktrees.find((wt) => wt.slug === worktreeSlug)?.directory ?? null;
|
|
39
|
+
}
|
|
40
|
+
export function clearWorktreeDirectoryCache(workspaceId) {
|
|
41
|
+
worktreeCache.delete(workspaceId);
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# opencode-config
|
|
2
|
+
|
|
3
|
+
## TLDR
|
|
4
|
+
Template config + plugins injected into every OpenCode instance that CodeNomad launches. It provides a CodeNomad bridge plugin for local event exchange between the CLI server and opencode.
|
|
5
|
+
|
|
6
|
+
## What it is
|
|
7
|
+
A packaged config directory that CodeNomad copies into `~/.config/codenomad/opencode-config` for production builds or uses directly in dev. OpenCode autoloads any `plugin/*.ts` or `plugin/*.js` from this directory.
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
- CodeNomad sets `OPENCODE_CONFIG_DIR` when spawning each opencode instance (`packages/server/src/workspaces/manager.ts`).
|
|
11
|
+
- This template is synced from `packages/opencode-config` (`packages/server/src/opencode-config.ts`, `packages/server/scripts/copy-opencode-config.mjs`).
|
|
12
|
+
- OpenCode autoloads plugins from `plugin/` (`packages/opencode-config/plugin/codenomad.ts`).
|
|
13
|
+
- The `CodeNomadPlugin` reads `CODENOMAD_INSTANCE_ID` + `CODENOMAD_BASE_URL`, connects to `GET /workspaces/:id/plugin/events`, and posts to `POST /workspaces/:id/plugin/event` (`packages/opencode-config/plugin/lib/client.ts`).
|
|
14
|
+
- The server exposes the plugin routes and maps events into the UI SSE pipeline (`packages/server/src/server/routes/plugin.ts`, `packages/server/src/plugins/handlers.ts`).
|
|
15
|
+
|
|
16
|
+
## Expectations
|
|
17
|
+
- Local-only bridge (no auth/token yet).
|
|
18
|
+
- Plugin must fail startup if it cannot connect after 3 retries.
|
|
19
|
+
- Keep plugin entrypoints thin; put shared logic under `plugin/lib/` to avoid autoloaded helpers.
|
|
20
|
+
- Keep event shapes small and explicit; use `type` + `properties` only.
|
|
21
|
+
|
|
22
|
+
## Ideas
|
|
23
|
+
- Add feature modules under `plugin/lib/features/` (tool lifecycle, permission prompts, custom commands).
|
|
24
|
+
- Expand `/workspaces/:id/plugin/*` with dedicated endpoints as needed.
|
|
25
|
+
- Promote stable event shapes and version tags once the protocol settles.
|
|
26
|
+
|
|
27
|
+
## Pointers
|
|
28
|
+
- Plugin entry: `packages/opencode-config/plugin/codenomad.ts`
|
|
29
|
+
- Plugin client: `packages/opencode-config/plugin/lib/client.ts`
|
|
30
|
+
- Plugin server routes: `packages/server/src/server/routes/plugin.ts`
|
|
31
|
+
- Plugin event handling: `packages/server/src/plugins/handlers.ts`
|
|
32
|
+
- Workspace env injection: `packages/server/src/workspaces/manager.ts`
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin"
|
|
2
|
+
import { createCodeNomadClient, getCodeNomadConfig } from "./lib/client"
|
|
3
|
+
import { createBackgroundProcessTools } from "./lib/background-process"
|
|
4
|
+
|
|
5
|
+
export async function CodeNomadPlugin(input: PluginInput) {
|
|
6
|
+
const config = getCodeNomadConfig()
|
|
7
|
+
const client = createCodeNomadClient(config)
|
|
8
|
+
const backgroundProcessTools = createBackgroundProcessTools(config, { baseDir: input.directory })
|
|
9
|
+
|
|
10
|
+
await client.startEvents((event) => {
|
|
11
|
+
if (event.type === "codenomad.ping") {
|
|
12
|
+
void client.postEvent({
|
|
13
|
+
type: "codenomad.pong",
|
|
14
|
+
properties: {
|
|
15
|
+
ts: Date.now(),
|
|
16
|
+
pingTs: (event.properties as any)?.ts,
|
|
17
|
+
},
|
|
18
|
+
}).catch(() => {})
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
tool: {
|
|
24
|
+
...backgroundProcessTools,
|
|
25
|
+
},
|
|
26
|
+
async event(input: { event: any }) {
|
|
27
|
+
const opencodeEvent = input?.event
|
|
28
|
+
if (!opencodeEvent || typeof opencodeEvent !== "object") return
|
|
29
|
+
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}
|