@akira-tl/forgerelay 0.1.0
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 +45 -0
- package/LICENSE +22 -0
- package/NOTICE.md +19 -0
- package/README.md +270 -0
- package/dist/apply-patch.js +402 -0
- package/dist/artifact-error.js +8 -0
- package/dist/artifact-tools.js +377 -0
- package/dist/cli.js +597 -0
- package/dist/config.js +224 -0
- package/dist/db/client.js +29 -0
- package/dist/db/migrations.js +189 -0
- package/dist/db/schema.js +85 -0
- package/dist/git-worktrees.js +255 -0
- package/dist/git.js +41 -0
- package/dist/incoming-artifacts.js +378 -0
- package/dist/local-agent-adapters.js +653 -0
- package/dist/local-agent-availability.js +119 -0
- package/dist/local-agent-path.js +25 -0
- package/dist/local-agent-profiles.js +136 -0
- package/dist/local-agent-runtime.js +48 -0
- package/dist/local-agent-store.js +145 -0
- package/dist/local-agent-targets.js +80 -0
- package/dist/logger.js +69 -0
- package/dist/mcp/server-instructions.js +78 -0
- package/dist/mcp-sessions.js +56 -0
- package/dist/oauth-provider.js +237 -0
- package/dist/oauth-store.js +138 -0
- package/dist/pi-tools.js +81 -0
- package/dist/process-platform.js +49 -0
- package/dist/process-sessions.js +337 -0
- package/dist/request-meta.js +9 -0
- package/dist/review-checkpoints.js +219 -0
- package/dist/roots.js +37 -0
- package/dist/server-shutdown.js +12 -0
- package/dist/server.js +1596 -0
- package/dist/skills.js +89 -0
- package/dist/ui/.vite/manifest.json +2521 -0
- package/dist/ui/assets/abap-CLvhMVsD.js +1 -0
- package/dist/ui/assets/actionscript-3--17pq3dv.js +1 -0
- package/dist/ui/assets/ada-C5qYipkI.js +1 -0
- package/dist/ui/assets/andromeeda-vGVdxbeo.js +1 -0
- package/dist/ui/assets/angular-html-CovppXt5.js +1 -0
- package/dist/ui/assets/angular-ts-0Y9l6YXu.js +1 -0
- package/dist/ui/assets/apache-U0d_L8uA.js +1 -0
- package/dist/ui/assets/apex-CGTLDQj6.js +1 -0
- package/dist/ui/assets/apl-BmBhiklA.js +1 -0
- package/dist/ui/assets/applescript-CCn79oCD.js +1 -0
- package/dist/ui/assets/ara-4CJ0cIlV.js +1 -0
- package/dist/ui/assets/asciidoc-DE70LPWp.js +1 -0
- package/dist/ui/assets/asm-Cmm7eHzH.js +1 -0
- package/dist/ui/assets/astro-BAmqcqyV.js +1 -0
- package/dist/ui/assets/aurora-x-CDeNXAV0.js +1 -0
- package/dist/ui/assets/awk-BWXHIvNe.js +1 -0
- package/dist/ui/assets/ayu-dark-DluEY0Gj.js +1 -0
- package/dist/ui/assets/ayu-light-C3h-C4tm.js +1 -0
- package/dist/ui/assets/ayu-mirage-Bqwy1Gya.js +1 -0
- package/dist/ui/assets/ballerina-B7ZEbQpA.js +1 -0
- package/dist/ui/assets/bat-Bo4NYOV-.js +1 -0
- package/dist/ui/assets/beancount-D-usSTwE.js +1 -0
- package/dist/ui/assets/berry-DKpUyyne.js +1 -0
- package/dist/ui/assets/bibtex-Ci_nEsc7.js +1 -0
- package/dist/ui/assets/bicep-CUHmPFLl.js +1 -0
- package/dist/ui/assets/bird2-C2hNVINV.js +1 -0
- package/dist/ui/assets/blade-BjFcmRJo.js +1 -0
- package/dist/ui/assets/bsl-BkkzgIyY.js +1 -0
- package/dist/ui/assets/c-CaOJn4x0.js +1 -0
- package/dist/ui/assets/c3-CnJL0r0V.js +1 -0
- package/dist/ui/assets/cadence-CQ2zXKGN.js +1 -0
- package/dist/ui/assets/cairo-DLTphjLi.js +1 -0
- package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
- package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
- package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
- package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
- package/dist/ui/assets/clarity-SemFz856.js +1 -0
- package/dist/ui/assets/clojure-DqKBuwfJ.js +1 -0
- package/dist/ui/assets/cmake-Bj61d0ZC.js +1 -0
- package/dist/ui/assets/cobol-DR4zWFMt.js +1 -0
- package/dist/ui/assets/codeowners-C8r90Shi.js +1 -0
- package/dist/ui/assets/codeql-oeQT6MSM.js +1 -0
- package/dist/ui/assets/coffee-ReGSThmM.js +1 -0
- package/dist/ui/assets/common-lisp-Cv5bFMCO.js +1 -0
- package/dist/ui/assets/coq-BrsZFFmf.js +1 -0
- package/dist/ui/assets/cpp-CnlQh6MO.js +1 -0
- package/dist/ui/assets/crystal-BrpPbH1U.js +1 -0
- package/dist/ui/assets/csharp-Ct8U2NOr.js +1 -0
- package/dist/ui/assets/css-DRBEvyPU.js +1 -0
- package/dist/ui/assets/csv-Dx-8-gkx.js +1 -0
- package/dist/ui/assets/cue-CE9AQfxI.js +1 -0
- package/dist/ui/assets/cypher-ClKdZ_lG.js +1 -0
- package/dist/ui/assets/d-qD-0Kul2.js +1 -0
- package/dist/ui/assets/dark-plus-Cs2F2srj.js +1 -0
- package/dist/ui/assets/dart-DkHntEIa.js +1 -0
- package/dist/ui/assets/dax-BkyTk9wS.js +1 -0
- package/dist/ui/assets/desktop-Dlh5hvp9.js +1 -0
- package/dist/ui/assets/diff-woXpYk--.js +1 -0
- package/dist/ui/assets/docker-IyjqRm3v.js +1 -0
- package/dist/ui/assets/dotenv-_5a1GRtc.js +1 -0
- package/dist/ui/assets/dracula-BHWKrbxM.js +1 -0
- package/dist/ui/assets/dracula-soft-5eyTD99u.js +1 -0
- package/dist/ui/assets/dream-maker-DW3nJb8Q.js +1 -0
- package/dist/ui/assets/edge-cfwpdvl9.js +1 -0
- package/dist/ui/assets/elixir-7owrJxb6.js +1 -0
- package/dist/ui/assets/elm-udiOjODk.js +1 -0
- package/dist/ui/assets/emacs-lisp-C9PiwqqW.js +1 -0
- package/dist/ui/assets/erb-8ctXHMkS.js +1 -0
- package/dist/ui/assets/erlang-Cphh6RMH.js +1 -0
- package/dist/ui/assets/everforest-dark-sB-x3p7T.js +1 -0
- package/dist/ui/assets/everforest-light-Df2xbC6M.js +1 -0
- package/dist/ui/assets/fennel-DQxkIbk2.js +1 -0
- package/dist/ui/assets/fish-BJitypiv.js +1 -0
- package/dist/ui/assets/fluent-C03EYrpw.js +1 -0
- package/dist/ui/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
- package/dist/ui/assets/fortran-free-form-CYNrtFtB.js +1 -0
- package/dist/ui/assets/fsharp-D13ZGOAj.js +1 -0
- package/dist/ui/assets/gdresource-C0sCabJj.js +1 -0
- package/dist/ui/assets/gdscript-Cp2uCuqX.js +1 -0
- package/dist/ui/assets/gdshader-CBce3t8t.js +1 -0
- package/dist/ui/assets/genie-CV2tkWYe.js +1 -0
- package/dist/ui/assets/gherkin-DExj1W_8.js +1 -0
- package/dist/ui/assets/git-commit-BSykSTBG.js +1 -0
- package/dist/ui/assets/git-rebase-P0V_qK1w.js +1 -0
- package/dist/ui/assets/github-dark-C-LZuMrd.js +1 -0
- package/dist/ui/assets/github-dark-default-DXG-b-1a.js +1 -0
- package/dist/ui/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
- package/dist/ui/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
- package/dist/ui/assets/github-light-EUqPIrTm.js +1 -0
- package/dist/ui/assets/github-light-default-BXViO-2h.js +1 -0
- package/dist/ui/assets/github-light-high-contrast-B68TUdTA.js +1 -0
- package/dist/ui/assets/gleam-CSRkHgEL.js +1 -0
- package/dist/ui/assets/glimmer-js-CZ14ED7U.js +1 -0
- package/dist/ui/assets/glimmer-ts-DtBSFP-o.js +1 -0
- package/dist/ui/assets/glsl-BX2BkZJK.js +1 -0
- package/dist/ui/assets/gn-ilITqXS6.js +1 -0
- package/dist/ui/assets/gnuplot-7GGW24-e.js +1 -0
- package/dist/ui/assets/go-BJwz_mda.js +1 -0
- package/dist/ui/assets/graphql-Dj_cPv4w.js +1 -0
- package/dist/ui/assets/groovy-CacY0gHj.js +1 -0
- package/dist/ui/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
- package/dist/ui/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
- package/dist/ui/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
- package/dist/ui/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
- package/dist/ui/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
- package/dist/ui/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
- package/dist/ui/assets/hack-DGRkd8xn.js +1 -0
- package/dist/ui/assets/haml-BAPSvujW.js +1 -0
- package/dist/ui/assets/handlebars-PYksdULG.js +1 -0
- package/dist/ui/assets/haskell-D8IpX4py.js +1 -0
- package/dist/ui/assets/haxe-OTjmBuCE.js +1 -0
- package/dist/ui/assets/hcl-Dh228itO.js +1 -0
- package/dist/ui/assets/heavy-payload-BjE0LSUi.js +4 -0
- package/dist/ui/assets/hjson-CxZEssPk.js +1 -0
- package/dist/ui/assets/hlsl-Cvrh5tZx.js +1 -0
- package/dist/ui/assets/horizon-CE9ld1lL.js +1 -0
- package/dist/ui/assets/horizon-bright-Br1oVSNq.js +1 -0
- package/dist/ui/assets/houston-CsvMBhTu.js +1 -0
- package/dist/ui/assets/html-DloAPGZ1.js +1 -0
- package/dist/ui/assets/html-derivative-C6q86ZrS.js +1 -0
- package/dist/ui/assets/http-fPvYDvHA.js +1 -0
- package/dist/ui/assets/hurl-Dbir4WvE.js +1 -0
- package/dist/ui/assets/hxml-B0Qn7Nwc.js +1 -0
- package/dist/ui/assets/hy-CZbG8q4J.js +1 -0
- package/dist/ui/assets/imba-DsUTQ-LC.js +1 -0
- package/dist/ui/assets/ini-B5eOa1yu.js +1 -0
- package/dist/ui/assets/java-DvkqXg3z.js +1 -0
- package/dist/ui/assets/javascript-TONTV6Ty.js +1 -0
- package/dist/ui/assets/jinja-OM1F5Gct.js +1 -0
- package/dist/ui/assets/jison-CBttugts.js +1 -0
- package/dist/ui/assets/json-Db5oY-7J.js +1 -0
- package/dist/ui/assets/json5-BR5RXkoi.js +1 -0
- package/dist/ui/assets/jsonc-CYpm1nAK.js +1 -0
- package/dist/ui/assets/jsonl-CmCQp5Yx.js +1 -0
- package/dist/ui/assets/jsonnet-CJTPZ8u_.js +1 -0
- package/dist/ui/assets/jssm-DXw9l8Rf.js +1 -0
- package/dist/ui/assets/jsx-DKeJCgsc.js +1 -0
- package/dist/ui/assets/julia-NlIPhXaL.js +1 -0
- package/dist/ui/assets/just-BXBJB-mX.js +1 -0
- package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
- package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +1 -0
- package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +1 -0
- package/dist/ui/assets/kdl-CsD5j6eV.js +1 -0
- package/dist/ui/assets/kotlin-DhhofPvG.js +1 -0
- package/dist/ui/assets/kusto-BUv0MjJC.js +1 -0
- package/dist/ui/assets/laserwave-C_8bwKvT.js +1 -0
- package/dist/ui/assets/latex-CGK-6yDy.js +1 -0
- package/dist/ui/assets/lean-CewbzKMR.js +1 -0
- package/dist/ui/assets/less-DVTAwKKz.js +1 -0
- package/dist/ui/assets/light-plus-DVQuIRkW.js +1 -0
- package/dist/ui/assets/liquid-D7waQ0MY.js +1 -0
- package/dist/ui/assets/llvm-Cm23YOpf.js +1 -0
- package/dist/ui/assets/log-BNLmms1o.js +1 -0
- package/dist/ui/assets/logo-Cluzi2Zq.js +1 -0
- package/dist/ui/assets/lua-C_kkt4h1.js +1 -0
- package/dist/ui/assets/luau-CNKltnaQ.js +1 -0
- package/dist/ui/assets/make-Dixweg8N.js +1 -0
- package/dist/ui/assets/markdown-BYOwaDjH.js +1 -0
- package/dist/ui/assets/marko-BokXuCts.js +1 -0
- package/dist/ui/assets/material-theme-Bm3Qr25_.js +1 -0
- package/dist/ui/assets/material-theme-darker-2IIEA8gg.js +1 -0
- package/dist/ui/assets/material-theme-lighter-uhdI0v04.js +1 -0
- package/dist/ui/assets/material-theme-ocean-CHQ94UKr.js +1 -0
- package/dist/ui/assets/material-theme-palenight-B5W6OYN7.js +1 -0
- package/dist/ui/assets/matlab-D7qyCx1q.js +1 -0
- package/dist/ui/assets/mdc-Bk0nnUJA.js +1 -0
- package/dist/ui/assets/mdx-DQZ5AkYe.js +1 -0
- package/dist/ui/assets/mermaid-Bk4SNUv9.js +1 -0
- package/dist/ui/assets/min-dark-BSWPekZh.js +1 -0
- package/dist/ui/assets/min-light-DDpmG2fV.js +1 -0
- package/dist/ui/assets/mipsasm-BMqwQI7S.js +1 -0
- package/dist/ui/assets/mojo-BgCJLMeH.js +1 -0
- package/dist/ui/assets/monokai-CdkpiU2Y.js +1 -0
- package/dist/ui/assets/moonbit-CaWjb8XO.js +1 -0
- package/dist/ui/assets/move-B1IS1UjX.js +1 -0
- package/dist/ui/assets/narrat-_X_XdTYD.js +1 -0
- package/dist/ui/assets/nextflow-Bbiyy34d.js +1 -0
- package/dist/ui/assets/nextflow-groovy-Dc_ddanL.js +1 -0
- package/dist/ui/assets/nginx-jM6NF9TV.js +1 -0
- package/dist/ui/assets/night-owl-DhmEMT88.js +1 -0
- package/dist/ui/assets/night-owl-light-eJ-hLW7d.js +1 -0
- package/dist/ui/assets/nim-hYsL-WKb.js +1 -0
- package/dist/ui/assets/nix-IvuFDN5E.js +1 -0
- package/dist/ui/assets/nord-Cb4Vim4T.js +1 -0
- package/dist/ui/assets/nushell-DcLAeLz5.js +1 -0
- package/dist/ui/assets/objective-c-D1A_Heim.js +1 -0
- package/dist/ui/assets/objective-cpp-BsSzOQcm.js +1 -0
- package/dist/ui/assets/ocaml-O90oeIOV.js +1 -0
- package/dist/ui/assets/odin-B1RWQWA5.js +1 -0
- package/dist/ui/assets/one-dark-pro-CLwyXe_n.js +1 -0
- package/dist/ui/assets/one-light-D7Lr4KcI.js +1 -0
- package/dist/ui/assets/openscad-BUDT5pXO.js +1 -0
- package/dist/ui/assets/pascal-4ZHwLPI5.js +1 -0
- package/dist/ui/assets/perl-DBI_cUHJ.js +1 -0
- package/dist/ui/assets/php-BX_aQhFl.js +1 -0
- package/dist/ui/assets/pierre-dark-sU4Zdns8.js +1 -0
- package/dist/ui/assets/pierre-dark-soft-HXgun5vs.js +1 -0
- package/dist/ui/assets/pierre-light-DWBk51d8.js +1 -0
- package/dist/ui/assets/pierre-light-soft-CodEzPxf.js +1 -0
- package/dist/ui/assets/pkl-ot-7Btpt.js +1 -0
- package/dist/ui/assets/plastic-DQwYfKfQ.js +1 -0
- package/dist/ui/assets/plsql-DGHpHOYJ.js +1 -0
- package/dist/ui/assets/po-BiJDBrnU.js +1 -0
- package/dist/ui/assets/poimandres-DRFjx7u4.js +1 -0
- package/dist/ui/assets/polar-C7UOKdEL.js +1 -0
- package/dist/ui/assets/postcss-BXeXVLqQ.js +1 -0
- package/dist/ui/assets/powerquery-DNMTfnFr.js +1 -0
- package/dist/ui/assets/powershell-DshXNtvi.js +1 -0
- package/dist/ui/assets/prisma-BsRQq5mF.js +1 -0
- package/dist/ui/assets/prolog-iXnhIJG7.js +1 -0
- package/dist/ui/assets/proto-DB4EqR-F.js +1 -0
- package/dist/ui/assets/pug-DwFAYy1e.js +1 -0
- package/dist/ui/assets/puppet-CDv2pdJW.js +1 -0
- package/dist/ui/assets/purescript-9MfHhQsQ.js +1 -0
- package/dist/ui/assets/python-gzcpVVnB.js +1 -0
- package/dist/ui/assets/qml-eLSwQUKt.js +1 -0
- package/dist/ui/assets/qmldir-DCQb3MpD.js +1 -0
- package/dist/ui/assets/qss-Fe1Jh2GI.js +1 -0
- package/dist/ui/assets/r-BMnQsMLf.js +1 -0
- package/dist/ui/assets/racket-DcIDlBhZ.js +1 -0
- package/dist/ui/assets/raku-B3gFvitq.js +1 -0
- package/dist/ui/assets/razor-CgciiMyw.js +1 -0
- package/dist/ui/assets/red-CJ3rzSJv.js +1 -0
- package/dist/ui/assets/reg-CRGYupPL.js +1 -0
- package/dist/ui/assets/regexp-ZrURNrn5.js +1 -0
- package/dist/ui/assets/rel-BtDbiS_P.js +1 -0
- package/dist/ui/assets/review-payload-HGkpJjjm.js +1 -0
- package/dist/ui/assets/riscv-Ckw8ddFX.js +1 -0
- package/dist/ui/assets/ron-VUp2lXgN.js +1 -0
- package/dist/ui/assets/rose-pine-BthvhNj6.js +1 -0
- package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
- package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +1 -0
- package/dist/ui/assets/rosmsg-CAekHB0j.js +1 -0
- package/dist/ui/assets/rst-EoAOr3M6.js +1 -0
- package/dist/ui/assets/ruby-Dqx5_Rqw.js +1 -0
- package/dist/ui/assets/rust-Cfkwpbl8.js +1 -0
- package/dist/ui/assets/sas-Bf6xPLSX.js +1 -0
- package/dist/ui/assets/sass-DXrisJhu.js +1 -0
- package/dist/ui/assets/scala-DKOlJaKm.js +1 -0
- package/dist/ui/assets/scheme-DQCgrYNe.js +1 -0
- package/dist/ui/assets/scrollbar-DX4Ujotb.js +287 -0
- package/dist/ui/assets/scss-DDpW3yTd.js +1 -0
- package/dist/ui/assets/sdbl-bTVj8UrX.js +1 -0
- package/dist/ui/assets/shaderlab-TOUzSsQk.js +1 -0
- package/dist/ui/assets/shellscript-DayAQ-W9.js +1 -0
- package/dist/ui/assets/shellsession-jPr_lSnA.js +1 -0
- package/dist/ui/assets/slack-dark-DnToyrRv.js +1 -0
- package/dist/ui/assets/slack-ochin-B2OO5cIa.js +1 -0
- package/dist/ui/assets/smalltalk-B16xEiuN.js +1 -0
- package/dist/ui/assets/snazzy-light-4G7pJPwS.js +1 -0
- package/dist/ui/assets/solarized-dark-DV17i1UV.js +1 -0
- package/dist/ui/assets/solarized-light-DSh2HLQt.js +1 -0
- package/dist/ui/assets/solidity-CKzVLygQ.js +1 -0
- package/dist/ui/assets/soy-X9adks8G.js +1 -0
- package/dist/ui/assets/sparql-D_iOobhT.js +1 -0
- package/dist/ui/assets/splunk-BC2Px7Mm.js +1 -0
- package/dist/ui/assets/sql-Bmt09AIR.js +1 -0
- package/dist/ui/assets/ssh-config-BgfXC-Er.js +1 -0
- package/dist/ui/assets/stata-DVkNpH8r.js +1 -0
- package/dist/ui/assets/stylus-B6D30XZt.js +1 -0
- package/dist/ui/assets/surrealql-eEXzMb8j.js +1 -0
- package/dist/ui/assets/svelte-CFoBxZF3.js +1 -0
- package/dist/ui/assets/swift-DonLKvLd.js +1 -0
- package/dist/ui/assets/synthwave-84-nFMaYfgc.js +1 -0
- package/dist/ui/assets/system-verilog-DJ5XKQeo.js +1 -0
- package/dist/ui/assets/systemd-BxMlprV5.js +1 -0
- package/dist/ui/assets/talonscript-CohzipZa.js +1 -0
- package/dist/ui/assets/tasl-DMoTqEGO.js +1 -0
- package/dist/ui/assets/tcl-CZd0xW_V.js +1 -0
- package/dist/ui/assets/templ-Da_324JF.js +1 -0
- package/dist/ui/assets/terraform-DswuEJGm.js +1 -0
- package/dist/ui/assets/tex-HAzlmKJ0.js +1 -0
- package/dist/ui/assets/tokyo-night-oM2G3aXe.js +1 -0
- package/dist/ui/assets/toml-CcmNWLt0.js +1 -0
- package/dist/ui/assets/ts-tags-7iLrNH8p.js +1 -0
- package/dist/ui/assets/tsv-sltzmVWM.js +1 -0
- package/dist/ui/assets/tsx-gZaXf8PJ.js +1 -0
- package/dist/ui/assets/turtle-ByJddavk.js +1 -0
- package/dist/ui/assets/twig-CLpQ7p1N.js +1 -0
- package/dist/ui/assets/typescript-B2WWCRI2.js +1 -0
- package/dist/ui/assets/typespec-B88KGewJ.js +1 -0
- package/dist/ui/assets/typst-DI99ib-x.js +1 -0
- package/dist/ui/assets/v-DETTlOr0.js +1 -0
- package/dist/ui/assets/vala-zf12oZj6.js +1 -0
- package/dist/ui/assets/vb-Djn5o6TS.js +1 -0
- package/dist/ui/assets/verilog-CiiDBU1e.js +1 -0
- package/dist/ui/assets/vesper-D5bVUKB1.js +1 -0
- package/dist/ui/assets/vhdl-BroJfC0k.js +1 -0
- package/dist/ui/assets/viml-DvXPmvsu.js +1 -0
- package/dist/ui/assets/vitesse-black-fwtXNY1n.js +1 -0
- package/dist/ui/assets/vitesse-dark-BZCL-v6S.js +1 -0
- package/dist/ui/assets/vitesse-light-VbXTXTou.js +1 -0
- package/dist/ui/assets/vue-No_8Jygd.js +1 -0
- package/dist/ui/assets/vue-html-kHJg98Kk.js +1 -0
- package/dist/ui/assets/vue-vine-Df4cEYaN.js +1 -0
- package/dist/ui/assets/vyper-CgoNMtux.js +1 -0
- package/dist/ui/assets/wasm-BnjxR4X6.js +1 -0
- package/dist/ui/assets/wasm-ByWQv1Qj.js +1 -0
- package/dist/ui/assets/wenyan-C8pVoKbM.js +1 -0
- package/dist/ui/assets/wgsl-BsKzXJz4.js +1 -0
- package/dist/ui/assets/wikitext-ClFFjSW2.js +1 -0
- package/dist/ui/assets/wit-DdvCle-K.js +1 -0
- package/dist/ui/assets/wolfram-DLL8P-h_.js +1 -0
- package/dist/ui/assets/workspace-app-C_wsC6VL.js +117 -0
- package/dist/ui/assets/workspace-app-DHvE2ojW.css +1 -0
- package/dist/ui/assets/xml-DUZ05dpG.js +1 -0
- package/dist/ui/assets/xsl-Bwp3w2OF.js +1 -0
- package/dist/ui/assets/yaml-IA_-TEM1.js +1 -0
- package/dist/ui/assets/zenscript-BnlCZFoB.js +1 -0
- package/dist/ui/assets/zig-CMLA9XwU.js +1 -0
- package/dist/ui/workspace-app.html +15 -0
- package/dist/user-config.js +97 -0
- package/dist/workspace-store.js +162 -0
- package/dist/workspaces.js +528 -0
- package/docs/agent-profile-schema.md +119 -0
- package/docs/artifact-exchange.md +63 -0
- package/docs/chatgpt-coding-workflow.md +183 -0
- package/docs/configuration.md +197 -0
- package/docs/gotchas.md +243 -0
- package/docs/roadmap.md +195 -0
- package/docs/security.md +142 -0
- package/docs/setup.md +132 -0
- package/docs/versioning.md +189 -0
- package/examples/agents/claude-implementer.md +30 -0
- package/examples/agents/codex-explorer.md +27 -0
- package/examples/agents/codex-qa-tester.md +29 -0
- package/examples/agents/codex-worker.md +25 -0
- package/examples/agents/copilot-reviewer.md +25 -0
- package/examples/agents/cursor-agent-worker.md +26 -0
- package/examples/agents/opencode-explorer.md +27 -0
- package/examples/agents/pi-reviewer.md +27 -0
- package/package.json +102 -0
- package/scripts/dev-server.mjs +120 -0
- package/scripts/fix-node-pty-permissions.mjs +22 -0
- package/scripts/release-version.mjs +207 -0
- package/skills/subagent-delegation/SKILL.md +132 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { expandHomePath } from "./roots.js";
|
|
5
|
+
import { forgerelayAgentsDir, forgerelaySkillsDir, loadForgeRelayFiles } from "./user-config.js";
|
|
6
|
+
const DEFAULT_OAUTH_ACCESS_TOKEN_TTL_SECONDS = 60 * 60;
|
|
7
|
+
const DEFAULT_OAUTH_REFRESH_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
8
|
+
const DEFAULT_ARTIFACT_MAX_FILE_BYTES = 100 * 1024 * 1024;
|
|
9
|
+
function parsePort(value) {
|
|
10
|
+
if (value === undefined || value === "")
|
|
11
|
+
return 7676;
|
|
12
|
+
const port = Number(value);
|
|
13
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
14
|
+
throw new Error(`Invalid PORT: ${value}`);
|
|
15
|
+
}
|
|
16
|
+
return port;
|
|
17
|
+
}
|
|
18
|
+
function parseAllowedRoots(value) {
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
const roots = value.map((entry) => entry.trim()).filter(Boolean);
|
|
21
|
+
return (roots.length > 0 ? roots : [process.cwd()]).map((root) => resolve(expandHomePath(root)));
|
|
22
|
+
}
|
|
23
|
+
const rawRoots = value
|
|
24
|
+
?.split(",")
|
|
25
|
+
.map((entry) => entry.trim())
|
|
26
|
+
.filter(Boolean) ?? [];
|
|
27
|
+
const roots = rawRoots.length > 0 ? rawRoots : [process.cwd()];
|
|
28
|
+
return roots.map((root) => resolve(expandHomePath(root)));
|
|
29
|
+
}
|
|
30
|
+
function parseAllowedHosts(value, derivedHosts) {
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
return normalizeAllowedHosts(value, derivedHosts);
|
|
33
|
+
}
|
|
34
|
+
const rawHosts = value
|
|
35
|
+
?.split(",")
|
|
36
|
+
.map((entry) => entry.trim())
|
|
37
|
+
.filter(Boolean) ?? [];
|
|
38
|
+
return normalizeAllowedHosts(rawHosts, derivedHosts);
|
|
39
|
+
}
|
|
40
|
+
function normalizeAllowedHosts(rawHosts, derivedHosts) {
|
|
41
|
+
const hosts = rawHosts.length > 0 ? rawHosts : derivedHosts;
|
|
42
|
+
if (hosts.includes("*"))
|
|
43
|
+
return ["*"];
|
|
44
|
+
return Array.from(new Set(hosts.map((host) => host.trim()).filter(Boolean)));
|
|
45
|
+
}
|
|
46
|
+
function parseBoolean(value) {
|
|
47
|
+
return ["1", "true", "yes", "on"].includes(value?.toLowerCase() ?? "");
|
|
48
|
+
}
|
|
49
|
+
function productEnv(env, suffix) {
|
|
50
|
+
return env[`FORGERELAY_${suffix}`] ?? env[`DEVSPACE_${suffix}`];
|
|
51
|
+
}
|
|
52
|
+
function parseToolMode(env) {
|
|
53
|
+
const mode = productEnv(env, "TOOL_MODE");
|
|
54
|
+
if (mode === "minimal" || mode === "full" || mode === "codex")
|
|
55
|
+
return mode;
|
|
56
|
+
if (mode)
|
|
57
|
+
throw new Error(`Invalid FORGERELAY_TOOL_MODE: ${mode}`);
|
|
58
|
+
const legacyMinimal = productEnv(env, "MINIMAL_TOOLS");
|
|
59
|
+
if (legacyMinimal !== undefined) {
|
|
60
|
+
return parseBoolean(legacyMinimal) ? "minimal" : "full";
|
|
61
|
+
}
|
|
62
|
+
return "minimal";
|
|
63
|
+
}
|
|
64
|
+
function parseWorkflowInstructions(value, fallback) {
|
|
65
|
+
const resolved = value !== undefined ? value : fallback;
|
|
66
|
+
if (resolved === false || resolved === undefined)
|
|
67
|
+
return resolved;
|
|
68
|
+
const instructions = resolved.trim();
|
|
69
|
+
return instructions.length > 0 ? instructions : false;
|
|
70
|
+
}
|
|
71
|
+
function parseAppendInstructions(value, fallback) {
|
|
72
|
+
const instructions = (value ?? fallback)?.trim();
|
|
73
|
+
return instructions ? instructions : undefined;
|
|
74
|
+
}
|
|
75
|
+
function parseLogLevel(value) {
|
|
76
|
+
if (!value || value === "info")
|
|
77
|
+
return "info";
|
|
78
|
+
if (["silent", "error", "warn", "debug"].includes(value))
|
|
79
|
+
return value;
|
|
80
|
+
throw new Error(`Invalid FORGERELAY_LOG_LEVEL: ${value}`);
|
|
81
|
+
}
|
|
82
|
+
function parseLogFormat(value) {
|
|
83
|
+
if (!value || value === "json")
|
|
84
|
+
return "json";
|
|
85
|
+
if (value === "pretty")
|
|
86
|
+
return "pretty";
|
|
87
|
+
throw new Error(`Invalid FORGERELAY_LOG_FORMAT: ${value}`);
|
|
88
|
+
}
|
|
89
|
+
function parsePathList(value) {
|
|
90
|
+
return (value
|
|
91
|
+
?.split(",")
|
|
92
|
+
.map((entry) => entry.trim())
|
|
93
|
+
.filter(Boolean) ?? []);
|
|
94
|
+
}
|
|
95
|
+
function parseStringList(value, fallback) {
|
|
96
|
+
const entries = value
|
|
97
|
+
?.split(",")
|
|
98
|
+
.map((entry) => entry.trim())
|
|
99
|
+
.filter(Boolean);
|
|
100
|
+
return entries && entries.length > 0 ? entries : fallback;
|
|
101
|
+
}
|
|
102
|
+
function parsePositiveInteger(value, fallback, name, max = Number.MAX_SAFE_INTEGER) {
|
|
103
|
+
if (!value)
|
|
104
|
+
return fallback;
|
|
105
|
+
const parsed = Number(value);
|
|
106
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > max) {
|
|
107
|
+
throw new Error(`Invalid ${name}: ${value}`);
|
|
108
|
+
}
|
|
109
|
+
return parsed;
|
|
110
|
+
}
|
|
111
|
+
function parseLoggingConfig(env) {
|
|
112
|
+
const requests = productEnv(env, "LOG_REQUESTS");
|
|
113
|
+
const toolCalls = productEnv(env, "LOG_TOOL_CALLS");
|
|
114
|
+
return {
|
|
115
|
+
level: parseLogLevel(productEnv(env, "LOG_LEVEL")),
|
|
116
|
+
format: parseLogFormat(productEnv(env, "LOG_FORMAT")),
|
|
117
|
+
requests: requests === undefined ? true : parseBoolean(requests),
|
|
118
|
+
assets: parseBoolean(productEnv(env, "LOG_ASSETS")),
|
|
119
|
+
toolCalls: toolCalls === undefined ? true : parseBoolean(toolCalls),
|
|
120
|
+
shellCommands: parseBoolean(productEnv(env, "LOG_SHELL_COMMANDS")),
|
|
121
|
+
trustProxy: parseBoolean(productEnv(env, "TRUST_PROXY")),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function parseWidgetMode(value) {
|
|
125
|
+
if (!value || value === "full")
|
|
126
|
+
return "full";
|
|
127
|
+
if (value === "off" || value === "changes")
|
|
128
|
+
return value;
|
|
129
|
+
throw new Error(`Invalid FORGERELAY_WIDGETS: ${value}`);
|
|
130
|
+
}
|
|
131
|
+
function parseRequiredSecret(value, name) {
|
|
132
|
+
const secret = value?.trim();
|
|
133
|
+
if (!secret) {
|
|
134
|
+
throw new Error(`${name} is required for ForgeRelay OAuth. Run: forgerelay init`);
|
|
135
|
+
}
|
|
136
|
+
if (secret.length < 16) {
|
|
137
|
+
throw new Error(`${name} must be at least 16 characters long.`);
|
|
138
|
+
}
|
|
139
|
+
return secret;
|
|
140
|
+
}
|
|
141
|
+
function parseOAuthConfig(env, ownerToken) {
|
|
142
|
+
return {
|
|
143
|
+
ownerToken: parseRequiredSecret(productEnv(env, "OAUTH_OWNER_TOKEN") ?? ownerToken, "FORGERELAY_OAUTH_OWNER_TOKEN"),
|
|
144
|
+
accessTokenTtlSeconds: parsePositiveInteger(productEnv(env, "OAUTH_ACCESS_TOKEN_TTL_SECONDS"), DEFAULT_OAUTH_ACCESS_TOKEN_TTL_SECONDS, "FORGERELAY_OAUTH_ACCESS_TOKEN_TTL_SECONDS"),
|
|
145
|
+
refreshTokenTtlSeconds: parsePositiveInteger(productEnv(env, "OAUTH_REFRESH_TOKEN_TTL_SECONDS"), DEFAULT_OAUTH_REFRESH_TOKEN_TTL_SECONDS, "FORGERELAY_OAUTH_REFRESH_TOKEN_TTL_SECONDS"),
|
|
146
|
+
scopes: parseStringList(productEnv(env, "OAUTH_SCOPES"), ["devspace"]),
|
|
147
|
+
allowedRedirectHosts: parseStringList(productEnv(env, "OAUTH_ALLOWED_REDIRECT_HOSTS"), [
|
|
148
|
+
"chatgpt.com",
|
|
149
|
+
"localhost",
|
|
150
|
+
"127.0.0.1",
|
|
151
|
+
]),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function defaultStateDir() {
|
|
155
|
+
const current = join(homedir(), ".local", "share", "forgerelay");
|
|
156
|
+
const legacy = join(homedir(), ".local", "share", "devspace");
|
|
157
|
+
return existsSync(current) || !existsSync(legacy) ? current : legacy;
|
|
158
|
+
}
|
|
159
|
+
function defaultWorktreeRoot() {
|
|
160
|
+
const current = join(homedir(), ".forgerelay", "worktrees");
|
|
161
|
+
const legacy = join(homedir(), ".devspace", "worktrees");
|
|
162
|
+
return existsSync(current) || !existsSync(legacy) ? current : legacy;
|
|
163
|
+
}
|
|
164
|
+
function defaultAgentDir() {
|
|
165
|
+
return join(homedir(), ".codex");
|
|
166
|
+
}
|
|
167
|
+
export function loadConfig(env = process.env) {
|
|
168
|
+
const files = loadForgeRelayFiles(env);
|
|
169
|
+
const host = env.HOST ?? files.config.host ?? "127.0.0.1";
|
|
170
|
+
const port = parsePort(env.PORT ?? files.config.port);
|
|
171
|
+
const publicBaseUrl = parsePublicBaseUrl(productEnv(env, "PUBLIC_BASE_URL") ?? files.config.publicBaseUrl ?? localPublicBaseUrl(host, port));
|
|
172
|
+
const derivedAllowedHosts = [
|
|
173
|
+
"localhost",
|
|
174
|
+
"127.0.0.1",
|
|
175
|
+
"::1",
|
|
176
|
+
host,
|
|
177
|
+
new URL(publicBaseUrl).hostname,
|
|
178
|
+
...(files.config.allowedHosts ?? []),
|
|
179
|
+
];
|
|
180
|
+
return {
|
|
181
|
+
host,
|
|
182
|
+
port,
|
|
183
|
+
oauth: parseOAuthConfig(env, files.auth.ownerToken),
|
|
184
|
+
allowedRoots: parseAllowedRoots(productEnv(env, "ALLOWED_ROOTS") ?? files.config.allowedRoots),
|
|
185
|
+
allowedHosts: parseAllowedHosts(productEnv(env, "ALLOWED_HOSTS"), derivedAllowedHosts),
|
|
186
|
+
publicBaseUrl,
|
|
187
|
+
toolMode: parseToolMode(env),
|
|
188
|
+
workflowInstructions: parseWorkflowInstructions(productEnv(env, "WORKFLOW_INSTRUCTIONS"), files.config.workflowInstructions),
|
|
189
|
+
appendInstructions: parseAppendInstructions(productEnv(env, "APPEND_INSTRUCTIONS"), files.config.appendInstructions),
|
|
190
|
+
widgets: parseWidgetMode(productEnv(env, "WIDGETS")),
|
|
191
|
+
stateDir: resolve(expandHomePath(productEnv(env, "STATE_DIR") ?? files.config.stateDir ?? defaultStateDir())),
|
|
192
|
+
worktreeRoot: resolve(expandHomePath(productEnv(env, "WORKTREE_ROOT") ?? files.config.worktreeRoot ?? defaultWorktreeRoot())),
|
|
193
|
+
artifactsEnabled: productEnv(env, "ARTIFACTS") === undefined
|
|
194
|
+
? files.config.artifactsEnabled === true
|
|
195
|
+
: parseBoolean(productEnv(env, "ARTIFACTS")),
|
|
196
|
+
artifactMaxFileBytes: parsePositiveInteger(productEnv(env, "ARTIFACT_MAX_FILE_BYTES") ?? numberConfigValue(files.config.artifactMaxFileBytes), DEFAULT_ARTIFACT_MAX_FILE_BYTES, "FORGERELAY_ARTIFACT_MAX_FILE_BYTES"),
|
|
197
|
+
skillsEnabled: productEnv(env, "SKILLS") === undefined ? true : parseBoolean(productEnv(env, "SKILLS")),
|
|
198
|
+
skillPaths: parsePathList(productEnv(env, "SKILL_PATHS")),
|
|
199
|
+
devspaceSkillsDir: forgerelaySkillsDir(env),
|
|
200
|
+
devspaceAgentsDir: forgerelayAgentsDir(env),
|
|
201
|
+
subagents: productEnv(env, "SUBAGENTS") === undefined
|
|
202
|
+
? files.config.subagents === true
|
|
203
|
+
: parseBoolean(productEnv(env, "SUBAGENTS")),
|
|
204
|
+
agentDir: resolve(expandHomePath(productEnv(env, "AGENT_DIR") ?? files.config.agentDir ?? defaultAgentDir())),
|
|
205
|
+
logging: parseLoggingConfig(env),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function numberConfigValue(value) {
|
|
209
|
+
return value === undefined ? undefined : String(value);
|
|
210
|
+
}
|
|
211
|
+
function parsePublicBaseUrl(value) {
|
|
212
|
+
const parsed = new URL(value);
|
|
213
|
+
parsed.hash = "";
|
|
214
|
+
parsed.search = "";
|
|
215
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "");
|
|
216
|
+
return parsed.toString().replace(/\/$/, "");
|
|
217
|
+
}
|
|
218
|
+
function localPublicBaseUrl(host, port) {
|
|
219
|
+
const publicHost = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
220
|
+
const formattedHost = publicHost.includes(":") && !publicHost.startsWith("[")
|
|
221
|
+
? `[${publicHost}]`
|
|
222
|
+
: publicHost;
|
|
223
|
+
return `http://${formattedHost}:${port}`;
|
|
224
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import Database from "better-sqlite3";
|
|
4
|
+
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
5
|
+
import * as schema from "./schema.js";
|
|
6
|
+
import { migrateDatabase } from "./migrations.js";
|
|
7
|
+
export function databasePath(stateDir) {
|
|
8
|
+
return join(stateDir, "devspace.sqlite");
|
|
9
|
+
}
|
|
10
|
+
export function openDatabase(stateDir) {
|
|
11
|
+
mkdirSync(stateDir, { recursive: true, mode: 0o700 });
|
|
12
|
+
chmodSync(stateDir, 0o700);
|
|
13
|
+
const path = databasePath(stateDir);
|
|
14
|
+
const sqlite = new Database(path);
|
|
15
|
+
chmodSync(path, 0o600);
|
|
16
|
+
sqlite.pragma("journal_mode = WAL");
|
|
17
|
+
sqlite.pragma("synchronous = NORMAL");
|
|
18
|
+
sqlite.pragma("busy_timeout = 5000");
|
|
19
|
+
sqlite.pragma("foreign_keys = ON");
|
|
20
|
+
migrateDatabase(sqlite);
|
|
21
|
+
return {
|
|
22
|
+
sqlite,
|
|
23
|
+
db: createDrizzleDatabase(sqlite),
|
|
24
|
+
close: () => sqlite.close(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function createDrizzleDatabase(sqlite) {
|
|
28
|
+
return drizzle(sqlite, { schema });
|
|
29
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const migrations = [
|
|
2
|
+
{
|
|
3
|
+
version: 1,
|
|
4
|
+
name: "workspace-state",
|
|
5
|
+
up: migrateWorkspaceState,
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
version: 2,
|
|
9
|
+
name: "oauth-state",
|
|
10
|
+
up: migrateOAuthState,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
version: 3,
|
|
14
|
+
name: "local-agent-sessions",
|
|
15
|
+
up: migrateLocalAgentSessions,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
version: 4,
|
|
19
|
+
name: "workspace-conversation-bindings",
|
|
20
|
+
up: migrateWorkspaceConversationBindings,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
version: 5,
|
|
24
|
+
name: "workspace-worktree-branches",
|
|
25
|
+
up: migrateWorkspaceWorktreeBranches,
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
export function migrateDatabase(sqlite) {
|
|
29
|
+
const migrate = sqlite.transaction(() => {
|
|
30
|
+
sqlite.exec(`
|
|
31
|
+
create table if not exists devspace_schema_migrations (
|
|
32
|
+
version integer primary key,
|
|
33
|
+
name text not null,
|
|
34
|
+
applied_at text not null
|
|
35
|
+
);
|
|
36
|
+
`);
|
|
37
|
+
const applied = new Set(sqlite.prepare("select version from devspace_schema_migrations").all().map((row) => row.version));
|
|
38
|
+
const recordMigration = sqlite.prepare("insert into devspace_schema_migrations (version, name, applied_at) values (?, ?, ?)");
|
|
39
|
+
for (const migration of migrations) {
|
|
40
|
+
if (applied.has(migration.version))
|
|
41
|
+
continue;
|
|
42
|
+
migration.up(sqlite);
|
|
43
|
+
recordMigration.run(migration.version, migration.name, new Date().toISOString());
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
migrate.immediate();
|
|
47
|
+
}
|
|
48
|
+
function migrateWorkspaceState(sqlite) {
|
|
49
|
+
sqlite.exec(`
|
|
50
|
+
create table if not exists workspace_sessions (
|
|
51
|
+
id text primary key,
|
|
52
|
+
root text not null,
|
|
53
|
+
status text not null default 'active',
|
|
54
|
+
mode text not null default 'checkout',
|
|
55
|
+
source_root text,
|
|
56
|
+
base_ref text,
|
|
57
|
+
base_sha text,
|
|
58
|
+
managed text not null default 'false',
|
|
59
|
+
created_at text not null,
|
|
60
|
+
last_used_at text not null
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
create index if not exists workspace_sessions_root_idx
|
|
64
|
+
on workspace_sessions(root, last_used_at desc);
|
|
65
|
+
|
|
66
|
+
create index if not exists workspace_sessions_status_idx
|
|
67
|
+
on workspace_sessions(status, last_used_at desc);
|
|
68
|
+
|
|
69
|
+
create table if not exists loaded_agent_files (
|
|
70
|
+
workspace_session_id text not null,
|
|
71
|
+
path text not null,
|
|
72
|
+
content_hash text not null,
|
|
73
|
+
content text not null,
|
|
74
|
+
loaded_at text not null,
|
|
75
|
+
last_seen_at text not null,
|
|
76
|
+
primary key (workspace_session_id, path),
|
|
77
|
+
foreign key (workspace_session_id)
|
|
78
|
+
references workspace_sessions(id)
|
|
79
|
+
on delete cascade
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
create index if not exists loaded_agent_files_path_idx
|
|
83
|
+
on loaded_agent_files(path);
|
|
84
|
+
`);
|
|
85
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "mode", "text not null default 'checkout'");
|
|
86
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "source_root", "text");
|
|
87
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "base_ref", "text");
|
|
88
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "base_sha", "text");
|
|
89
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "managed", "text not null default 'false'");
|
|
90
|
+
}
|
|
91
|
+
function migrateOAuthState(sqlite) {
|
|
92
|
+
sqlite.exec(`
|
|
93
|
+
create table if not exists oauth_clients (
|
|
94
|
+
client_id text primary key,
|
|
95
|
+
client_json text not null,
|
|
96
|
+
issued_at integer not null
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
create index if not exists oauth_clients_issued_at_idx
|
|
100
|
+
on oauth_clients(issued_at desc);
|
|
101
|
+
|
|
102
|
+
create table if not exists oauth_access_tokens (
|
|
103
|
+
token_hash text primary key,
|
|
104
|
+
client_id text not null,
|
|
105
|
+
scopes_json text not null,
|
|
106
|
+
expires_at integer not null,
|
|
107
|
+
resource text,
|
|
108
|
+
foreign key (client_id) references oauth_clients(client_id) on delete cascade
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
create index if not exists oauth_access_tokens_client_id_idx
|
|
112
|
+
on oauth_access_tokens(client_id);
|
|
113
|
+
|
|
114
|
+
create index if not exists oauth_access_tokens_expires_at_idx
|
|
115
|
+
on oauth_access_tokens(expires_at);
|
|
116
|
+
|
|
117
|
+
create table if not exists oauth_refresh_tokens (
|
|
118
|
+
token_hash text primary key,
|
|
119
|
+
client_id text not null,
|
|
120
|
+
scopes_json text not null,
|
|
121
|
+
expires_at integer not null,
|
|
122
|
+
resource text,
|
|
123
|
+
foreign key (client_id) references oauth_clients(client_id) on delete cascade
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
create index if not exists oauth_refresh_tokens_client_id_idx
|
|
127
|
+
on oauth_refresh_tokens(client_id);
|
|
128
|
+
|
|
129
|
+
create index if not exists oauth_refresh_tokens_expires_at_idx
|
|
130
|
+
on oauth_refresh_tokens(expires_at);
|
|
131
|
+
`);
|
|
132
|
+
}
|
|
133
|
+
function migrateLocalAgentSessions(sqlite) {
|
|
134
|
+
sqlite.exec(`
|
|
135
|
+
create table if not exists local_agent_sessions (
|
|
136
|
+
id text primary key,
|
|
137
|
+
workspace_id text,
|
|
138
|
+
workspace_root text not null,
|
|
139
|
+
profile_name text not null,
|
|
140
|
+
provider text not null,
|
|
141
|
+
model text,
|
|
142
|
+
thinking text,
|
|
143
|
+
provider_session_id text,
|
|
144
|
+
status text not null,
|
|
145
|
+
latest_response text,
|
|
146
|
+
error text,
|
|
147
|
+
created_at text not null,
|
|
148
|
+
updated_at text not null
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
create index if not exists local_agent_sessions_workspace_id_idx
|
|
152
|
+
on local_agent_sessions(workspace_id, updated_at desc);
|
|
153
|
+
|
|
154
|
+
create index if not exists local_agent_sessions_workspace_root_idx
|
|
155
|
+
on local_agent_sessions(workspace_root, updated_at desc);
|
|
156
|
+
|
|
157
|
+
create index if not exists local_agent_sessions_provider_session_id_idx
|
|
158
|
+
on local_agent_sessions(provider_session_id);
|
|
159
|
+
`);
|
|
160
|
+
addColumnIfMissing(sqlite, "local_agent_sessions", "thinking", "text");
|
|
161
|
+
}
|
|
162
|
+
function migrateWorkspaceConversationBindings(sqlite) {
|
|
163
|
+
sqlite.exec(`
|
|
164
|
+
create table if not exists workspace_conversation_bindings (
|
|
165
|
+
conversation_scope_id text not null,
|
|
166
|
+
target_key text not null,
|
|
167
|
+
workspace_session_id text not null,
|
|
168
|
+
created_at text not null,
|
|
169
|
+
last_used_at text not null,
|
|
170
|
+
primary key (conversation_scope_id, target_key),
|
|
171
|
+
foreign key (workspace_session_id)
|
|
172
|
+
references workspace_sessions(id)
|
|
173
|
+
on delete cascade
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
create index if not exists workspace_conversation_bindings_workspace_idx
|
|
177
|
+
on workspace_conversation_bindings(workspace_session_id);
|
|
178
|
+
`);
|
|
179
|
+
}
|
|
180
|
+
function migrateWorkspaceWorktreeBranches(sqlite) {
|
|
181
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "branch", "text");
|
|
182
|
+
addColumnIfMissing(sqlite, "workspace_sessions", "target_branch", "text");
|
|
183
|
+
}
|
|
184
|
+
function addColumnIfMissing(sqlite, table, column, definition) {
|
|
185
|
+
const columns = sqlite.prepare(`pragma table_info(${table})`).all();
|
|
186
|
+
if (columns.some((existingColumn) => existingColumn.name === column))
|
|
187
|
+
return;
|
|
188
|
+
sqlite.exec(`alter table ${table} add column ${column} ${definition}`);
|
|
189
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { index, integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
2
|
+
export const workspaceSessions = sqliteTable("workspace_sessions", {
|
|
3
|
+
id: text("id").primaryKey(),
|
|
4
|
+
root: text("root").notNull(),
|
|
5
|
+
status: text("status").notNull().default("active"),
|
|
6
|
+
mode: text("mode").notNull().default("checkout"),
|
|
7
|
+
sourceRoot: text("source_root"),
|
|
8
|
+
baseRef: text("base_ref"),
|
|
9
|
+
baseSha: text("base_sha"),
|
|
10
|
+
branch: text("branch"),
|
|
11
|
+
targetBranch: text("target_branch"),
|
|
12
|
+
managed: text("managed").notNull().default("false"),
|
|
13
|
+
createdAt: text("created_at").notNull(),
|
|
14
|
+
lastUsedAt: text("last_used_at").notNull(),
|
|
15
|
+
}, (table) => [
|
|
16
|
+
index("workspace_sessions_root_idx").on(table.root, table.lastUsedAt),
|
|
17
|
+
index("workspace_sessions_status_idx").on(table.status, table.lastUsedAt),
|
|
18
|
+
]);
|
|
19
|
+
export const loadedAgentFiles = sqliteTable("loaded_agent_files", {
|
|
20
|
+
workspaceSessionId: text("workspace_session_id")
|
|
21
|
+
.notNull()
|
|
22
|
+
.references(() => workspaceSessions.id, { onDelete: "cascade" }),
|
|
23
|
+
path: text("path").notNull(),
|
|
24
|
+
contentHash: text("content_hash").notNull(),
|
|
25
|
+
content: text("content").notNull(),
|
|
26
|
+
loadedAt: text("loaded_at").notNull(),
|
|
27
|
+
lastSeenAt: text("last_seen_at").notNull(),
|
|
28
|
+
}, (table) => [
|
|
29
|
+
primaryKey({ columns: [table.workspaceSessionId, table.path] }),
|
|
30
|
+
index("loaded_agent_files_path_idx").on(table.path),
|
|
31
|
+
]);
|
|
32
|
+
export const workspaceConversationBindings = sqliteTable("workspace_conversation_bindings", {
|
|
33
|
+
conversationScopeId: text("conversation_scope_id").notNull(),
|
|
34
|
+
targetKey: text("target_key").notNull(),
|
|
35
|
+
workspaceSessionId: text("workspace_session_id")
|
|
36
|
+
.notNull()
|
|
37
|
+
.references(() => workspaceSessions.id, { onDelete: "cascade" }),
|
|
38
|
+
createdAt: text("created_at").notNull(),
|
|
39
|
+
lastUsedAt: text("last_used_at").notNull(),
|
|
40
|
+
}, (table) => [
|
|
41
|
+
primaryKey({ columns: [table.conversationScopeId, table.targetKey] }),
|
|
42
|
+
index("workspace_conversation_bindings_workspace_idx").on(table.workspaceSessionId),
|
|
43
|
+
]);
|
|
44
|
+
export const oauthClients = sqliteTable("oauth_clients", {
|
|
45
|
+
clientId: text("client_id").primaryKey(),
|
|
46
|
+
clientJson: text("client_json").notNull(),
|
|
47
|
+
issuedAt: integer("issued_at").notNull(),
|
|
48
|
+
});
|
|
49
|
+
export const oauthAccessTokens = sqliteTable("oauth_access_tokens", {
|
|
50
|
+
tokenHash: text("token_hash").primaryKey(),
|
|
51
|
+
clientId: text("client_id")
|
|
52
|
+
.notNull()
|
|
53
|
+
.references(() => oauthClients.clientId, { onDelete: "cascade" }),
|
|
54
|
+
scopesJson: text("scopes_json").notNull(),
|
|
55
|
+
expiresAt: integer("expires_at").notNull(),
|
|
56
|
+
resource: text("resource"),
|
|
57
|
+
});
|
|
58
|
+
export const oauthRefreshTokens = sqliteTable("oauth_refresh_tokens", {
|
|
59
|
+
tokenHash: text("token_hash").primaryKey(),
|
|
60
|
+
clientId: text("client_id")
|
|
61
|
+
.notNull()
|
|
62
|
+
.references(() => oauthClients.clientId, { onDelete: "cascade" }),
|
|
63
|
+
scopesJson: text("scopes_json").notNull(),
|
|
64
|
+
expiresAt: integer("expires_at").notNull(),
|
|
65
|
+
resource: text("resource"),
|
|
66
|
+
});
|
|
67
|
+
export const localAgentSessions = sqliteTable("local_agent_sessions", {
|
|
68
|
+
id: text("id").primaryKey(),
|
|
69
|
+
workspaceId: text("workspace_id"),
|
|
70
|
+
workspaceRoot: text("workspace_root").notNull(),
|
|
71
|
+
profileName: text("profile_name").notNull(),
|
|
72
|
+
provider: text("provider").notNull(),
|
|
73
|
+
model: text("model"),
|
|
74
|
+
thinking: text("thinking"),
|
|
75
|
+
providerSessionId: text("provider_session_id"),
|
|
76
|
+
status: text("status").notNull(),
|
|
77
|
+
latestResponse: text("latest_response"),
|
|
78
|
+
error: text("error"),
|
|
79
|
+
createdAt: text("created_at").notNull(),
|
|
80
|
+
updatedAt: text("updated_at").notNull(),
|
|
81
|
+
}, (table) => [
|
|
82
|
+
index("local_agent_sessions_workspace_id_idx").on(table.workspaceId, table.updatedAt),
|
|
83
|
+
index("local_agent_sessions_workspace_root_idx").on(table.workspaceRoot, table.updatedAt),
|
|
84
|
+
index("local_agent_sessions_provider_session_id_idx").on(table.providerSessionId),
|
|
85
|
+
]);
|