@coreplane/switchboard 1.203.0 → 1.205.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/dist/assets/config/config.example.yaml +32 -3
- package/dist/assets/deploy/cloudflare-memory/worker.ts +129 -3
- package/dist/assets/deploy/cloudflare-memory/wrangler.template.jsonc +7 -2
- package/dist/assets/deploy/cloudflare-sandbox/worker.ts +4 -1
- package/dist/assets/package-lock.json +291 -97
- package/dist/assets/package.json +1 -1
- package/dist/assets/project.json +1 -1
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/agents/registry.ts +466 -0
- package/dist/assets/src/config/profile.ts +200 -0
- package/dist/assets/src/core/delivery.ts +775 -0
- package/dist/assets/src/core/deliverySnapshotStore.ts +200 -0
- package/dist/assets/src/core/runLedger/types.ts +6 -0
- package/dist/assets/src/core/runRecord.ts +44 -0
- package/dist/assets/src/core/ship/contract.ts +502 -0
- package/dist/assets/src/core/workerError.ts +12 -0
- package/dist/assets/web/dist/.vite/manifest.json +2770 -70
- package/dist/assets/web/dist/assets/AppShell-lYVcj-k7.js +1 -0
- package/dist/assets/web/dist/assets/{CostsPage-XQ-fQzdz.js → CostsPage-DGSE48l1.js} +1 -1
- package/dist/assets/web/dist/assets/DeliveryPage-Cx7kQC_e.js +1 -0
- package/dist/assets/web/dist/assets/NotFoundPage-BzWS4Ca1.js +1 -0
- package/dist/assets/web/dist/assets/ResidentDetailPage-Bcasasjb.js +1 -0
- package/dist/assets/web/dist/assets/ResidentsIndexPage-BJwyrphn.js +1 -0
- package/dist/assets/web/dist/assets/RunRoutePage-6eStApqP.js +12 -0
- package/dist/assets/web/dist/assets/RunRoutePage-f6TSNPeW.css +1 -0
- package/dist/assets/web/dist/assets/RunsIndexPage-CWrkv7v8.js +1 -0
- package/dist/assets/web/dist/assets/RunsTabs-DEICQ4FY.js +1 -0
- package/dist/assets/web/dist/assets/ScheduledPage-BX2py1X3.js +1 -0
- package/dist/assets/web/dist/assets/StatusDot-CwCK84JN.js +1 -0
- package/dist/assets/web/dist/assets/Tooltip-CFC88_-Z.js +1 -0
- package/dist/assets/web/dist/assets/abap-CLvhMVsD.js +1 -0
- package/dist/assets/web/dist/assets/actionscript-3-Cs6JJXT5.js +1 -0
- package/dist/assets/web/dist/assets/ada-C5qYipkI.js +1 -0
- package/dist/assets/web/dist/assets/ahk-CA9gdOdF.js +1 -0
- package/dist/assets/web/dist/assets/ahk2-_6rzW9BS.js +1 -0
- package/dist/assets/web/dist/assets/andromeeda-vGVdxbeo.js +1 -0
- package/dist/assets/web/dist/assets/angular-html-Cw130Zyi.js +1 -0
- package/dist/assets/web/dist/assets/angular-ts-DY1m4C2s.js +1 -0
- package/dist/assets/web/dist/assets/apache-U0d_L8uA.js +1 -0
- package/dist/assets/web/dist/assets/apex-KFGFyKwG.js +1 -0
- package/dist/assets/web/dist/assets/apl-W6Ty7v05.js +1 -0
- package/dist/assets/web/dist/assets/applescript-CCn79oCD.js +1 -0
- package/dist/assets/web/dist/assets/ara-4CJ0cIlV.js +1 -0
- package/dist/assets/web/dist/assets/asciidoc-SCjQUq34.js +1 -0
- package/dist/assets/web/dist/assets/asm-Cmm7eHzH.js +1 -0
- package/dist/assets/web/dist/assets/astro-DlLVHwVk.js +1 -0
- package/dist/assets/web/dist/assets/aurora-x-CDeNXAV0.js +1 -0
- package/dist/assets/web/dist/assets/awk-BWXHIvNe.js +1 -0
- package/dist/assets/web/dist/assets/ayu-dark-DluEY0Gj.js +1 -0
- package/dist/assets/web/dist/assets/ayu-light-C3h-C4tm.js +1 -0
- package/dist/assets/web/dist/assets/ayu-mirage-Bqwy1Gya.js +1 -0
- package/dist/assets/web/dist/assets/ballerina-B7ZEbQpA.js +1 -0
- package/dist/assets/web/dist/assets/bat-qdxAdBWQ.js +1 -0
- package/dist/assets/web/dist/assets/beancount-D-usSTwE.js +1 -0
- package/dist/assets/web/dist/assets/berry-DKpUyyne.js +1 -0
- package/dist/assets/web/dist/assets/bibtex-Ci_nEsc7.js +1 -0
- package/dist/assets/web/dist/assets/bicep-CUHmPFLl.js +1 -0
- package/dist/assets/web/dist/assets/bird2-CYIUgYqB.js +1 -0
- package/dist/assets/web/dist/assets/blade-Bco3tDh4.js +1 -0
- package/dist/assets/web/dist/assets/bsl-_VjlB9mv.js +1 -0
- package/dist/assets/web/dist/assets/c-1LaFY_cj.js +1 -0
- package/dist/assets/web/dist/assets/c3-D0apG41V.js +1 -0
- package/dist/assets/web/dist/assets/cadence-CQ2zXKGN.js +1 -0
- package/dist/assets/web/dist/assets/cairo-DLTphjLi.js +1 -0
- package/dist/assets/web/dist/assets/catppuccin-frappe-C9Q5zVZY.js +1 -0
- package/dist/assets/web/dist/assets/catppuccin-latte-CtsyrtPq.js +1 -0
- package/dist/assets/web/dist/assets/catppuccin-macchiato-R8nAf1vR.js +1 -0
- package/dist/assets/web/dist/assets/catppuccin-mocha-DjuaAJKi.js +1 -0
- package/dist/assets/web/dist/assets/chapel-B-OvrOL5.js +1 -0
- package/dist/assets/web/dist/assets/clarity-CtfBBspg.js +1 -0
- package/dist/assets/web/dist/assets/clojure-DqKBuwfJ.js +1 -0
- package/dist/assets/web/dist/assets/cmake-Bj61d0ZC.js +1 -0
- package/dist/assets/web/dist/assets/cobol-Ch3EPlHu.js +1 -0
- package/dist/assets/web/dist/assets/codeowners-C8r90Shi.js +1 -0
- package/dist/assets/web/dist/assets/codeql-oeQT6MSM.js +1 -0
- package/dist/assets/web/dist/assets/coffee-hZuITnto.js +1 -0
- package/dist/assets/web/dist/assets/common-lisp-Cv5bFMCO.js +1 -0
- package/dist/assets/web/dist/assets/coq-DuBRPxYg.js +1 -0
- package/dist/assets/web/dist/assets/cpp-B8iRVo8m.js +1 -0
- package/dist/assets/web/dist/assets/crystal-DKveI7lr.js +1 -0
- package/dist/assets/web/dist/assets/csharp-oqKa8noW.js +1 -0
- package/dist/assets/web/dist/assets/css-_2_CD-rr.js +1 -0
- package/dist/assets/web/dist/assets/csv-Dx-8-gkx.js +1 -0
- package/dist/assets/web/dist/assets/cue-CE9AQfxI.js +1 -0
- package/dist/assets/web/dist/assets/cypher-ClKdZ_lG.js +1 -0
- package/dist/assets/web/dist/assets/d-qD-0Kul2.js +1 -0
- package/dist/assets/web/dist/assets/dark-plus-Cs2F2srj.js +1 -0
- package/dist/assets/web/dist/assets/dart-CnvKMtbv.js +1 -0
- package/dist/assets/web/dist/assets/dax-BkyTk9wS.js +1 -0
- package/dist/assets/web/dist/assets/desktop-Dlh5hvp9.js +1 -0
- package/dist/assets/web/dist/assets/diff-woXpYk--.js +1 -0
- package/dist/assets/web/dist/assets/dist-BoLiHpua.js +1547 -0
- package/dist/assets/web/dist/assets/docker-IyjqRm3v.js +1 -0
- package/dist/assets/web/dist/assets/dotenv-_5a1GRtc.js +1 -0
- package/dist/assets/web/dist/assets/dracula-BHWKrbxM.js +1 -0
- package/dist/assets/web/dist/assets/dracula-soft-5eyTD99u.js +1 -0
- package/dist/assets/web/dist/assets/dream-maker-DW3nJb8Q.js +1 -0
- package/dist/assets/web/dist/assets/edge-BenMDPct.js +1 -0
- package/dist/assets/web/dist/assets/elixir-CBbdEqG6.js +1 -0
- package/dist/assets/web/dist/assets/elm-DMub_2lY.js +1 -0
- package/dist/assets/web/dist/assets/emacs-lisp-c_oH4hRZ.js +1 -0
- package/dist/assets/web/dist/assets/erb-CI9He_Up.js +1 -0
- package/dist/assets/web/dist/assets/erlang-Cphh6RMH.js +1 -0
- package/dist/assets/web/dist/assets/everforest-dark-sB-x3p7T.js +1 -0
- package/dist/assets/web/dist/assets/everforest-light-Df2xbC6M.js +1 -0
- package/dist/assets/web/dist/assets/{favicon-CFfbl2AI.js → favicon-CWPcvWvp.js} +1 -1
- package/dist/assets/web/dist/assets/fennel-DQxkIbk2.js +1 -0
- package/dist/assets/web/dist/assets/fish-BJitypiv.js +1 -0
- package/dist/assets/web/dist/assets/fluent-C03EYrpw.js +1 -0
- package/dist/assets/web/dist/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
- package/dist/assets/web/dist/assets/fortran-free-form-CYNrtFtB.js +1 -0
- package/dist/assets/web/dist/assets/fsharp-D13ZGOAj.js +1 -0
- package/dist/assets/web/dist/assets/gdresource-xMC7jr7x.js +1 -0
- package/dist/assets/web/dist/assets/gdscript-DYvRD3hg.js +1 -0
- package/dist/assets/web/dist/assets/gdshader-CBce3t8t.js +1 -0
- package/dist/assets/web/dist/assets/genie-CV2tkWYe.js +1 -0
- package/dist/assets/web/dist/assets/gherkin-DExj1W_8.js +1 -0
- package/dist/assets/web/dist/assets/git-commit-BSykSTBG.js +1 -0
- package/dist/assets/web/dist/assets/git-rebase-BBfhnyF8.js +1 -0
- package/dist/assets/web/dist/assets/github-dark-C-LZuMrd.js +1 -0
- package/dist/assets/web/dist/assets/github-dark-default-DXG-b-1a.js +1 -0
- package/dist/assets/web/dist/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
- package/dist/assets/web/dist/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
- package/dist/assets/web/dist/assets/github-light-EUqPIrTm.js +1 -0
- package/dist/assets/web/dist/assets/github-light-default-BXViO-2h.js +1 -0
- package/dist/assets/web/dist/assets/github-light-high-contrast-B68TUdTA.js +1 -0
- package/dist/assets/web/dist/assets/gleam-CSRkHgEL.js +1 -0
- package/dist/assets/web/dist/assets/glimmer-js-CR9Fxrau.js +1 -0
- package/dist/assets/web/dist/assets/glimmer-ts-CwFwX_XS.js +1 -0
- package/dist/assets/web/dist/assets/glsl-Daiodp1r.js +1 -0
- package/dist/assets/web/dist/assets/gn-ilITqXS6.js +1 -0
- package/dist/assets/web/dist/assets/gnuplot-7GGW24-e.js +1 -0
- package/dist/assets/web/dist/assets/go-rLFTqkRN.js +1 -0
- package/dist/assets/web/dist/assets/graphql-DZvrsEkB.js +1 -0
- package/dist/assets/web/dist/assets/groovy-CacY0gHj.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
- package/dist/assets/web/dist/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
- package/dist/assets/web/dist/assets/hack-BaXOzdg7.js +1 -0
- package/dist/assets/web/dist/assets/haml-CMskq_VA.js +1 -0
- package/dist/assets/web/dist/assets/handlebars-Dhw_f7jD.js +1 -0
- package/dist/assets/web/dist/assets/haskell-D8IpX4py.js +1 -0
- package/dist/assets/web/dist/assets/haxe-C8oCnwJJ.js +1 -0
- package/dist/assets/web/dist/assets/hcl-Dh228itO.js +1 -0
- package/dist/assets/web/dist/assets/hjson-CxZEssPk.js +1 -0
- package/dist/assets/web/dist/assets/hlsl-Cvrh5tZx.js +1 -0
- package/dist/assets/web/dist/assets/horizon-CE9ld1lL.js +1 -0
- package/dist/assets/web/dist/assets/horizon-bright-DSNQnXHK.js +1 -0
- package/dist/assets/web/dist/assets/houston-CsvMBhTu.js +1 -0
- package/dist/assets/web/dist/assets/html-C9k99z0z.js +1 -0
- package/dist/assets/web/dist/assets/html-derivative-VckPItXN.js +1 -0
- package/dist/assets/web/dist/assets/http-DXU_3h9v.js +1 -0
- package/dist/assets/web/dist/assets/hurl-KU24JNdp.js +1 -0
- package/dist/assets/web/dist/assets/hxml-Dcm88srW.js +1 -0
- package/dist/assets/web/dist/assets/hy-CZbG8q4J.js +1 -0
- package/dist/assets/web/dist/assets/imba-DsUTQ-LC.js +1 -0
- package/dist/assets/web/dist/assets/indexFormat-B-pd4r7Y.js +1 -0
- package/dist/assets/web/dist/assets/ini-B5eOa1yu.js +1 -0
- package/dist/assets/web/dist/assets/java-BbZjTNgf.js +1 -0
- package/dist/assets/web/dist/assets/javascript-DXCdqcZZ.js +1 -0
- package/dist/assets/web/dist/assets/jinja-pDlsjTVp.js +1 -0
- package/dist/assets/web/dist/assets/jison-DsXDk66e.js +1 -0
- package/dist/assets/web/dist/assets/json-tCxXfRgG.js +1 -0
- package/dist/assets/web/dist/assets/json5-BR5RXkoi.js +1 -0
- package/dist/assets/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
- package/dist/assets/web/dist/assets/jsonl-CmCQp5Yx.js +1 -0
- package/dist/assets/web/dist/assets/jsonnet-CJTPZ8u_.js +1 -0
- package/dist/assets/web/dist/assets/jssm-DXw9l8Rf.js +1 -0
- package/dist/assets/web/dist/assets/jsx-B0ZYkCmi.js +1 -0
- package/dist/assets/web/dist/assets/julia-BLzzeI6x.js +1 -0
- package/dist/assets/web/dist/assets/just-DvD2_60c.js +1 -0
- package/dist/assets/web/dist/assets/kanagawa-dragon-Bozd7klA.js +1 -0
- package/dist/assets/web/dist/assets/kanagawa-lotus-BmuOG9ZW.js +1 -0
- package/dist/assets/web/dist/assets/kanagawa-wave-BML5mF2J.js +1 -0
- package/dist/assets/web/dist/assets/kdl-CsD5j6eV.js +1 -0
- package/dist/assets/web/dist/assets/kotlin-DhhofPvG.js +1 -0
- package/dist/assets/web/dist/assets/kusto-C7mF5XQf.js +1 -0
- package/dist/assets/web/dist/assets/laserwave-C_8bwKvT.js +1 -0
- package/dist/assets/web/dist/assets/latex-511zn3h7.js +1 -0
- package/dist/assets/web/dist/assets/lean-CewbzKMR.js +1 -0
- package/dist/assets/web/dist/assets/less-DVTAwKKz.js +1 -0
- package/dist/assets/web/dist/assets/light-plus-DVQuIRkW.js +1 -0
- package/dist/assets/web/dist/assets/liquid-BD0BkMox.js +1 -0
- package/dist/assets/web/dist/assets/llvm-DqHOMS-s.js +1 -0
- package/dist/assets/web/dist/assets/log-BNLmms1o.js +1 -0
- package/dist/assets/web/dist/assets/logo-Cluzi2Zq.js +1 -0
- package/dist/assets/web/dist/assets/lua-NFicKm6N.js +1 -0
- package/dist/assets/web/dist/assets/luau-C2pBCSgt.js +1 -0
- package/dist/assets/web/dist/assets/main-i3ZNDRLK.css +1 -0
- package/dist/assets/web/dist/assets/main-tYcFk9Dc.js +28 -0
- package/dist/assets/web/dist/assets/make-Dixweg8N.js +1 -0
- package/dist/assets/web/dist/assets/markdown-BYOwaDjH.js +1 -0
- package/dist/assets/web/dist/assets/marko-1-G_nEXK.js +1 -0
- package/dist/assets/web/dist/assets/material-theme-Bm3Qr25_.js +1 -0
- package/dist/assets/web/dist/assets/material-theme-darker-2IIEA8gg.js +1 -0
- package/dist/assets/web/dist/assets/material-theme-lighter-uhdI0v04.js +1 -0
- package/dist/assets/web/dist/assets/material-theme-ocean-CHQ94UKr.js +1 -0
- package/dist/assets/web/dist/assets/material-theme-palenight-B5W6OYN7.js +1 -0
- package/dist/assets/web/dist/assets/matlab-D7qyCx1q.js +1 -0
- package/dist/assets/web/dist/assets/mdc-DUe3AQLp.js +1 -0
- package/dist/assets/web/dist/assets/mdx-DQZ5AkYe.js +1 -0
- package/dist/assets/web/dist/assets/mermaid-BxpfTIzt.js +1 -0
- package/dist/assets/web/dist/assets/min-dark-BSWPekZh.js +1 -0
- package/dist/assets/web/dist/assets/min-light-DDpmG2fV.js +1 -0
- package/dist/assets/web/dist/assets/mipsasm-BMqwQI7S.js +1 -0
- package/dist/assets/web/dist/assets/mojo-fg40_ntQ.js +1 -0
- package/dist/assets/web/dist/assets/monokai-B_bV9PQ9.js +1 -0
- package/dist/assets/web/dist/assets/moonbit-DgjMoLWr.js +1 -0
- package/dist/assets/web/dist/assets/move-BYnGhZoM.js +1 -0
- package/dist/assets/web/dist/assets/narrat-_X_XdTYD.js +1 -0
- package/dist/assets/web/dist/assets/nextflow-BJtWHP5T.js +1 -0
- package/dist/assets/web/dist/assets/nextflow-groovy-DJMQeKeT.js +1 -0
- package/dist/assets/web/dist/assets/nginx-Dg379_bA.js +1 -0
- package/dist/assets/web/dist/assets/night-owl-DhmEMT88.js +1 -0
- package/dist/assets/web/dist/assets/night-owl-light-eJ-hLW7d.js +1 -0
- package/dist/assets/web/dist/assets/nim-BnFq97ZO.js +1 -0
- package/dist/assets/web/dist/assets/nix-IvuFDN5E.js +1 -0
- package/dist/assets/web/dist/assets/nord-Cb4Vim4T.js +1 -0
- package/dist/assets/web/dist/assets/nsis-CjNLYCLg.js +1 -0
- package/dist/assets/web/dist/assets/nushell-DHYfO66s.js +1 -0
- package/dist/assets/web/dist/assets/objective-c-D1A_Heim.js +1 -0
- package/dist/assets/web/dist/assets/objective-cpp-BsSzOQcm.js +1 -0
- package/dist/assets/web/dist/assets/ocaml-O90oeIOV.js +1 -0
- package/dist/assets/web/dist/assets/odin-B1RWQWA5.js +1 -0
- package/dist/assets/web/dist/assets/one-dark-pro-CLwyXe_n.js +1 -0
- package/dist/assets/web/dist/assets/one-light-D7Lr4KcI.js +1 -0
- package/dist/assets/web/dist/assets/openscad-BUDT5pXO.js +1 -0
- package/dist/assets/web/dist/assets/org-F0uiwGvq.js +1 -0
- package/dist/assets/web/dist/assets/pascal-4ZHwLPI5.js +1 -0
- package/dist/assets/web/dist/assets/perl-B0euczkl.js +1 -0
- package/dist/assets/web/dist/assets/php-DkL3k_n7.js +1 -0
- package/dist/assets/web/dist/assets/pierre-dark-CpLgRqie.js +1 -0
- package/dist/assets/web/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
- package/dist/assets/web/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
- package/dist/assets/web/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
- package/dist/assets/web/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
- package/dist/assets/web/dist/assets/pierre-light-CoaEpmwp.js +1 -0
- package/dist/assets/web/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
- package/dist/assets/web/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
- package/dist/assets/web/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
- package/dist/assets/web/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
- package/dist/assets/web/dist/assets/pkl-ot-7Btpt.js +1 -0
- package/dist/assets/web/dist/assets/plastic-DQwYfKfQ.js +1 -0
- package/dist/assets/web/dist/assets/plsql-DGHpHOYJ.js +1 -0
- package/dist/assets/web/dist/assets/po-BiJDBrnU.js +1 -0
- package/dist/assets/web/dist/assets/poimandres-DRFjx7u4.js +1 -0
- package/dist/assets/web/dist/assets/polar-C7UOKdEL.js +1 -0
- package/dist/assets/web/dist/assets/postcss-BXeXVLqQ.js +1 -0
- package/dist/assets/web/dist/assets/powerquery-DNMTfnFr.js +1 -0
- package/dist/assets/web/dist/assets/powershell-CCSX75yM.js +1 -0
- package/dist/assets/web/dist/assets/prisma-DMgNhnYS.js +1 -0
- package/dist/assets/web/dist/assets/prolog-iXnhIJG7.js +1 -0
- package/dist/assets/web/dist/assets/proto-DB4EqR-F.js +1 -0
- package/dist/assets/web/dist/assets/pug-L_OjjZP4.js +1 -0
- package/dist/assets/web/dist/assets/puppet-CDv2pdJW.js +1 -0
- package/dist/assets/web/dist/assets/purescript-9MfHhQsQ.js +1 -0
- package/dist/assets/web/dist/assets/python-gzcpVVnB.js +1 -0
- package/dist/assets/web/dist/assets/qml-BMjB00Zz.js +1 -0
- package/dist/assets/web/dist/assets/qmldir-DCQb3MpD.js +1 -0
- package/dist/assets/web/dist/assets/qss-Fe1Jh2GI.js +1 -0
- package/dist/assets/web/dist/assets/r-DoeLdnqR.js +1 -0
- package/dist/assets/web/dist/assets/racket-DcIDlBhZ.js +1 -0
- package/dist/assets/web/dist/assets/raku-B3gFvitq.js +1 -0
- package/dist/assets/web/dist/assets/razor-BzYNkAWy.js +1 -0
- package/dist/assets/web/dist/assets/rbs-C0MpOrj4.js +1 -0
- package/dist/assets/web/dist/assets/red-DX1BQOs8.js +1 -0
- package/dist/assets/web/dist/assets/reg-CRGYupPL.js +1 -0
- package/dist/assets/web/dist/assets/regexp-CPmElMk3.js +1 -0
- package/dist/assets/web/dist/assets/rel-BtDbiS_P.js +1 -0
- package/dist/assets/web/dist/assets/riscv-Ckw8ddFX.js +1 -0
- package/dist/assets/web/dist/assets/ron-VUp2lXgN.js +1 -0
- package/dist/assets/web/dist/assets/rose-pine-aMsaMD1D.js +1 -0
- package/dist/assets/web/dist/assets/rose-pine-dawn-8PwUyIlP.js +1 -0
- package/dist/assets/web/dist/assets/rose-pine-moon-DO-qXg-I.js +1 -0
- package/dist/assets/web/dist/assets/rosmsg-CAekHB0j.js +1 -0
- package/dist/assets/web/dist/assets/rst-DrsjgfI7.js +1 -0
- package/dist/assets/web/dist/assets/ruby-cB42ppvx.js +1 -0
- package/dist/assets/web/dist/assets/rust-Cfkwpbl8.js +1 -0
- package/dist/assets/web/dist/assets/sas-R5Y3NM_I.js +1 -0
- package/dist/assets/web/dist/assets/sass-DXrisJhu.js +1 -0
- package/dist/assets/web/dist/assets/scala-BiFt_7mu.js +1 -0
- package/dist/assets/web/dist/assets/scheme-DQCgrYNe.js +1 -0
- package/dist/assets/web/dist/assets/scss-C-zWxV9s.js +1 -0
- package/dist/assets/web/dist/assets/sdbl-bTVj8UrX.js +1 -0
- package/dist/assets/web/dist/assets/seed-DeKSHrt2.js +6 -0
- package/dist/assets/web/dist/assets/shaderlab-TOUzSsQk.js +1 -0
- package/dist/assets/web/dist/assets/shellscript-oJF96aAU.js +1 -0
- package/dist/assets/web/dist/assets/shellsession-CznECKyi.js +1 -0
- package/dist/assets/web/dist/assets/slack-dark-DnToyrRv.js +1 -0
- package/dist/assets/web/dist/assets/slack-ochin-B2OO5cIa.js +1 -0
- package/dist/assets/web/dist/assets/smalltalk-BHpQb5nM.js +1 -0
- package/dist/assets/web/dist/assets/smithy-Dgaz7aur.js +1 -0
- package/dist/assets/web/dist/assets/snazzy-light-4G7pJPwS.js +1 -0
- package/dist/assets/web/dist/assets/solarized-dark-UdsmMDCL.js +1 -0
- package/dist/assets/web/dist/assets/solarized-light-C1IUL_tW.js +1 -0
- package/dist/assets/web/dist/assets/solidity-Bj7E1mRn.js +1 -0
- package/dist/assets/web/dist/assets/soy-wjHLSRag.js +1 -0
- package/dist/assets/web/dist/assets/sparql-D_iOobhT.js +1 -0
- package/dist/assets/web/dist/assets/splunk-BC2Px7Mm.js +1 -0
- package/dist/assets/web/dist/assets/sql-C_BM8IOW.js +1 -0
- package/dist/assets/web/dist/assets/ssh-config-BgfXC-Er.js +1 -0
- package/dist/assets/web/dist/assets/stata-D31HO8aQ.js +1 -0
- package/dist/assets/web/dist/assets/stylus-B6D30XZt.js +1 -0
- package/dist/assets/web/dist/assets/surrealql-CKCLyplA.js +1 -0
- package/dist/assets/web/dist/assets/svelte-3geWk2iu.js +1 -0
- package/dist/assets/web/dist/assets/swift-CyEgAFGc.js +1 -0
- package/dist/assets/web/dist/assets/synthwave-84-nFMaYfgc.js +1 -0
- package/dist/assets/web/dist/assets/system-verilog-Dh5ihWbf.js +1 -0
- package/dist/assets/web/dist/assets/systemd-BxMlprV5.js +1 -0
- package/dist/assets/web/dist/assets/talonscript-CohzipZa.js +1 -0
- package/dist/assets/web/dist/assets/tasl-DMoTqEGO.js +1 -0
- package/dist/assets/web/dist/assets/tcl-CZd0xW_V.js +1 -0
- package/dist/assets/web/dist/assets/templ-DiJr_hTD.js +1 -0
- package/dist/assets/web/dist/assets/terraform-DswuEJGm.js +1 -0
- package/dist/assets/web/dist/assets/tex-BEJGWyeF.js +1 -0
- package/dist/assets/web/dist/assets/tokyo-night-oM2G3aXe.js +1 -0
- package/dist/assets/web/dist/assets/toml-CcmNWLt0.js +1 -0
- package/dist/assets/web/dist/assets/ts-tags-C8Mzdpxx.js +1 -0
- package/dist/assets/web/dist/assets/tsv-sltzmVWM.js +1 -0
- package/dist/assets/web/dist/assets/tsx-UQiSm_p3.js +1 -0
- package/dist/assets/web/dist/assets/turtle-ByJddavk.js +1 -0
- package/dist/assets/web/dist/assets/twig-_Pvzkeo9.js +1 -0
- package/dist/assets/web/dist/assets/typescript-BWMkINKK.js +1 -0
- package/dist/assets/web/dist/assets/typespec-BRdr0IET.js +1 -0
- package/dist/assets/web/dist/assets/typst-Bdg9m-e7.js +1 -0
- package/dist/assets/web/dist/assets/v-DBj4K9d_.js +1 -0
- package/dist/assets/web/dist/assets/vala-zf12oZj6.js +1 -0
- package/dist/assets/web/dist/assets/vb-DOwzaHZ0.js +1 -0
- package/dist/assets/web/dist/assets/verilog-B2gwz-sJ.js +1 -0
- package/dist/assets/web/dist/assets/vesper-DdrHHSXu.js +1 -0
- package/dist/assets/web/dist/assets/vhdl-BroJfC0k.js +1 -0
- package/dist/assets/web/dist/assets/viml-DvXPmvsu.js +1 -0
- package/dist/assets/web/dist/assets/vitesse-black-fwtXNY1n.js +1 -0
- package/dist/assets/web/dist/assets/vitesse-dark-BZCL-v6S.js +1 -0
- package/dist/assets/web/dist/assets/vitesse-light-VbXTXTou.js +1 -0
- package/dist/assets/web/dist/assets/vue-CDZrrAZ8.js +1 -0
- package/dist/assets/web/dist/assets/vue-html-tAlpNhfN.js +1 -0
- package/dist/assets/web/dist/assets/vue-vine-C27UF_rh.js +1 -0
- package/dist/assets/web/dist/assets/vyper-CgoNMtux.js +1 -0
- package/dist/assets/web/dist/assets/wallClock-61NpVkY6.js +1 -0
- package/dist/assets/web/dist/assets/wasm-BnjxR4X6.js +1 -0
- package/dist/assets/web/dist/assets/wasm-ByWQv1Qj.js +1 -0
- package/dist/assets/web/dist/assets/wenyan-C8pVoKbM.js +1 -0
- package/dist/assets/web/dist/assets/wgsl-BsKzXJz4.js +1 -0
- package/dist/assets/web/dist/assets/wikitext-ClFFjSW2.js +1 -0
- package/dist/assets/web/dist/assets/wit-DdvCle-K.js +1 -0
- package/dist/assets/web/dist/assets/wolfram-DLL8P-h_.js +1 -0
- package/dist/assets/web/dist/assets/xml-CxeDr9Zh.js +1 -0
- package/dist/assets/web/dist/assets/xsl-Bpi0uUnM.js +1 -0
- package/dist/assets/web/dist/assets/yaml-BtUgZ1GN.js +1 -0
- package/dist/assets/web/dist/assets/zenscript-BnlCZFoB.js +1 -0
- package/dist/assets/web/dist/assets/zig-CMLA9XwU.js +1 -0
- package/dist/cli.js +1120 -252
- package/package.json +1 -1
- package/dist/assets/web/dist/assets/AppShell-Bw3-_TTE.js +0 -1
- package/dist/assets/web/dist/assets/DeliveryPage-BRwcQyr7.js +0 -1
- package/dist/assets/web/dist/assets/NotFoundPage-RjH-9dPy.js +0 -1
- package/dist/assets/web/dist/assets/ResidentDetailPage-BRy5wkv9.js +0 -1
- package/dist/assets/web/dist/assets/ResidentsIndexPage-DAEVLN8j.js +0 -1
- package/dist/assets/web/dist/assets/RunRoutePage-B1KHmkZ9.js +0 -126
- package/dist/assets/web/dist/assets/RunRoutePage-CdbrbqU2.css +0 -1
- package/dist/assets/web/dist/assets/RunsIndexPage-3hUWFpFV.js +0 -1
- package/dist/assets/web/dist/assets/RunsTabs-Qn_5TVJU.js +0 -1
- package/dist/assets/web/dist/assets/ScheduledPage-DysVvVm1.js +0 -1
- package/dist/assets/web/dist/assets/StatusDot-Bug2a6T6.js +0 -1
- package/dist/assets/web/dist/assets/Tooltip-C2eEUbwn.js +0 -1
- package/dist/assets/web/dist/assets/main-0uhp-taL.js +0 -28
- package/dist/assets/web/dist/assets/main-Xickfv8V.css +0 -1
- package/dist/assets/web/dist/assets/seed-B8mQEhhw.js +0 -6
- package/dist/assets/web/dist/assets/wallClock-DI4HIEN5.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -615,8 +615,8 @@ var init_policy = __esm({
|
|
|
615
615
|
};
|
|
616
616
|
PLACEHOLDER = /\{([^{}]*)\}/g;
|
|
617
617
|
PolicyError = class extends Error {
|
|
618
|
-
constructor(
|
|
619
|
-
super(`authz policy: ${
|
|
618
|
+
constructor(message2, rule) {
|
|
619
|
+
super(`authz policy: ${message2} (rule ${describeRule(rule)})`);
|
|
620
620
|
this.name = "PolicyError";
|
|
621
621
|
}
|
|
622
622
|
};
|
|
@@ -1188,6 +1188,42 @@ var init_schedules = __esm({
|
|
|
1188
1188
|
}
|
|
1189
1189
|
});
|
|
1190
1190
|
|
|
1191
|
+
// ../../src/execution/bashTimeout.ts
|
|
1192
|
+
function clampBashTimeout(requested) {
|
|
1193
|
+
if (typeof requested !== "number" || !Number.isFinite(requested)) return BASH_TIMEOUT_MS;
|
|
1194
|
+
return Math.min(Math.max(Math.trunc(requested), BASH_TIMEOUT_MIN_MS), BASH_TIMEOUT_MAX_MS);
|
|
1195
|
+
}
|
|
1196
|
+
function bashBudgetWithinRun(wantedMs, remainingMs) {
|
|
1197
|
+
const secs = (ms) => Math.max(0, Math.round(ms / 1e3));
|
|
1198
|
+
const cap = Math.trunc(remainingMs - RUN_DEADLINE_RESERVE_MS);
|
|
1199
|
+
if (cap < BASH_TIMEOUT_MIN_MS) {
|
|
1200
|
+
return {
|
|
1201
|
+
kind: "exhausted",
|
|
1202
|
+
note: `run budget exhausted \u2014 ${secs(remainingMs)}s of wall clock left, inside the ${secs(RUN_DEADLINE_RESERVE_MS)}s write-up reserve, so the command was not run; write up what you have now`
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
if (cap >= wantedMs) return { kind: "unchanged" };
|
|
1206
|
+
return {
|
|
1207
|
+
kind: "clipped",
|
|
1208
|
+
timeoutMs: cap,
|
|
1209
|
+
note: `[timeout clipped to ${secs(cap)}s \u2014 the run's wall clock ends in ${secs(remainingMs)}s]`
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
function bashTimeoutNote(timeoutMs) {
|
|
1213
|
+
return `aborted at the ${Math.round(timeoutMs / 1e3)}s command timeout (pass the bash tool's timeoutMs for longer commands, max ${BASH_TIMEOUT_MAX_MS} ms)`;
|
|
1214
|
+
}
|
|
1215
|
+
var BASH_TIMEOUT_MS, BASH_TIMEOUT_MIN_MS, BASH_TIMEOUT_MAX_MS, RUN_DEADLINE_RESERVE_MS, EXEC_CALL_MARGIN_MS;
|
|
1216
|
+
var init_bashTimeout = __esm({
|
|
1217
|
+
"../../src/execution/bashTimeout.ts"() {
|
|
1218
|
+
"use strict";
|
|
1219
|
+
BASH_TIMEOUT_MS = 5 * 6e4;
|
|
1220
|
+
BASH_TIMEOUT_MIN_MS = 1e3;
|
|
1221
|
+
BASH_TIMEOUT_MAX_MS = 20 * 6e4;
|
|
1222
|
+
RUN_DEADLINE_RESERVE_MS = 6e4;
|
|
1223
|
+
EXEC_CALL_MARGIN_MS = 3e4;
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1191
1227
|
// ../../src/core/ship/contract.ts
|
|
1192
1228
|
function parsePlanUnit(planMarkdown, unitId) {
|
|
1193
1229
|
const lines = planMarkdown.split("\n");
|
|
@@ -1485,6 +1521,9 @@ var init_contract = __esm({
|
|
|
1485
1521
|
});
|
|
1486
1522
|
|
|
1487
1523
|
// ../../src/agents/registry.ts
|
|
1524
|
+
function machineNeedsRepo(machine) {
|
|
1525
|
+
return machine === "repo-cold" || machine === "repo-resident";
|
|
1526
|
+
}
|
|
1488
1527
|
function getAgent(name) {
|
|
1489
1528
|
const a = AGENTS[name];
|
|
1490
1529
|
if (!a) {
|
|
@@ -1492,11 +1531,14 @@ function getAgent(name) {
|
|
|
1492
1531
|
}
|
|
1493
1532
|
return a;
|
|
1494
1533
|
}
|
|
1495
|
-
var PR_DESCRIPTION_TEMPLATE, NEVER_MERGE, CONTRACT_HEADINGS_LIST, UNIT_CONTRACT, UNIT_HANDOFF, CODING_SYSTEM, CODING_SYSTEM_RESIDENT, REVIEW_VERDICT_INSTRUCTION, REVIEW_SPEC_CHECK, REVIEW_UNIT_CONTRACT, REVIEW_WHOLE_CHANGE, REVIEW_SYSTEM, REVIEW_SYSTEM_RESIDENT, RESEARCH_SYSTEM, GENERAL_SYSTEM, AGENTS;
|
|
1534
|
+
var MACHINE_CLASSES, IDENTITIES, PR_DESCRIPTION_TEMPLATE, NEVER_MERGE, CONTRACT_HEADINGS_LIST, UNIT_CONTRACT, UNIT_HANDOFF, CODING_SYSTEM, CODING_SYSTEM_RESIDENT, REVIEW_VERDICT_INSTRUCTION, REVIEW_SPEC_CHECK, REVIEW_UNIT_CONTRACT, REVIEW_WHOLE_CHANGE, REVIEW_SYSTEM, REVIEW_SYSTEM_RESIDENT, RESEARCH_SYSTEM, GENERAL_SYSTEM, EXPLORE_SYSTEM, AGENTS;
|
|
1496
1535
|
var init_registry = __esm({
|
|
1497
1536
|
"../../src/agents/registry.ts"() {
|
|
1498
1537
|
"use strict";
|
|
1538
|
+
init_bashTimeout();
|
|
1499
1539
|
init_contract();
|
|
1540
|
+
MACHINE_CLASSES = ["none", "blank", "repo-cold", "repo-resident"];
|
|
1541
|
+
IDENTITIES = ["none", "read", "write"];
|
|
1500
1542
|
PR_DESCRIPTION_TEMPLATE = `PR description \u2014 submit it with the submit_pr_description tool for EVERY PR (this is the default, not something to wait to be asked for). Switchboard renders the GitHub body from the object you submit, so never author PR-body markdown yourself. Content contract per field (each renders as its own section): prose is unwrapped \u2014 no hard line breaks inside a paragraph. Always hyperlink the triggering issue/request. Never fabricate validation \u2014 state exactly what you ran and the real result. Keep each field concise, not padded.
|
|
1501
1543
|
EVERY PR includes one that already exists when you push \u2014 opened by a person, by dependabot, or by an earlier run. After EVERY push to such a PR: read its current title and body (\`github_issue_get\` with the PR number works for pull requests; \`gh pr view\` where gh exists), judge them against the change as it now stands at the pushed head, and submit the object that describes the PR as it is NOW \u2014 carry forward what the existing body says that is still true (a dependency bump's release notes belong in whatWhy), add what you changed, and anchor the Tour at the new head. Switchboard replaces the PR's title and body with your rendering. A description that describes an earlier state of its branch is a bug; "it is someone else's PR" is never a reason to leave it.
|
|
1502
1544
|
- **title**: the PR title \u2014 one line naming the change, specific enough to pick out of a PR list.
|
|
@@ -1648,18 +1690,34 @@ Answer directly and concisely. Use Slack-friendly formatting (no markdown header
|
|
|
1648
1690
|
Your tools work without a workspace: the GitHub tools \u2014 \`github_repos\` (the org repositories you can reach), \`github_tree\` / \`github_file\` / \`github_search_code\` (browse, read, search their code and docs, private repos included), \`github_issue_list\` / \`github_issue_get\` (read issues), \`github_issue_create\` / \`github_issue_update\` / \`github_issue_comment\` / \`github_issue_delete\` (act on issues) \u2014 and \`web_fetch\` (read a public URL). Use them: when the user names a repo loosely ("the switchboard app"), resolve it with github_repos (or the thread) rather than asking; when asked about one of our repos, read it before answering. Report exactly what a tool did (issue number + URL) \u2014 never claim an action you did not perform, and never fabricate file contents, URLs, or command output.
|
|
1649
1691
|
|
|
1650
1692
|
You cannot run commands, clone repositories, edit code, or review pull requests, and you cannot search the web. Other Switchboard agents can: for code changes or PRs tell the user to re-send with \`agent:coding\`; for a PR review, \`agent:review\`; for a web-research question, \`agent:research\` (e.g. "\`agent:coding fix the failing login test in acme/api\`", "\`agent:research compare X and Y\`"). Delete an issue only when the user explicitly asked to delete it (closing is an update).`;
|
|
1693
|
+
EXPLORE_SYSTEM = `You are Switchboard's explore agent: a long, read-only investigation of a repository, answering a request from Slack.
|
|
1694
|
+
|
|
1695
|
+
You work in a fresh sandbox with a shell (bash), read_file, and a read-scoped GitHub credential: git and gh are authenticated for reads, so clone the target repository into your workspace first (\`gh repo clone <owner/name>\` or \`git clone\`; check out the ref the request names), install what you need and run whatever the investigation calls for \u2014 builds, test suites, benchmarks, \`act\` (Docker is available). You cannot push. Your other tools: \`web_search\` and \`web_fetch\` (sources and pages), the GitHub reads \u2014 \`github_repos\`, \`github_tree\` / \`github_file\` (browse and read our repos at any ref), \`github_search_code\`, \`github_issue_list\` / \`github_issue_get\` \u2014 and \`list_skills\` / \`use_skill\`.
|
|
1696
|
+
|
|
1697
|
+
THE DELIVERABLE IS A CLAIM TABLE. Turn the request into the claims it makes or asks about \u2014 explicit ones ("the suite runs in 4 minutes") and the implicit ones a careful engineer would check \u2014 and verify each one by running it, not by reading about it. One row per claim: the claim, the exact command you ran to check it, the number or output it produced, and a verdict (holds / does not hold / could not check \u2014 and why). Numbers over adjectives: measure a duration, count the failures, quote the version. Say what you did not get to.
|
|
1698
|
+
|
|
1699
|
+
TIME. Your budget is up to two hours \u2014 less when a boundary or the request's \`budget:\` directive clipped it, which the runtime-config block above says \u2014 and the wrap-up warning tells you when to stop starting new checks. A single command is capped at ${BASH_TIMEOUT_MAX_MS / 6e4} minutes (pass the bash tool's \`timeoutMs\`, up to ${BASH_TIMEOUT_MAX_MS} ms, for a long one). A job that needs longer \u2014 a full suite, a build, a pipeline run \u2014 is started detached and polled across tool calls: \`setsid -f sh -c '<command> > /tmp/job.log 2>&1; echo $? > /tmp/job.exit'\`, then \`tail -n 40 /tmp/job.log\` and \`cat /tmp/job.exit\` on later calls (a plain background job dies with the command that started it; a \`setsid -f\` job outlives it). Batch commands into few tool calls; never explore file by file.
|
|
1700
|
+
|
|
1701
|
+
READ-ONLY: NEVER open a pull request, and never commit or push \u2014 no branch, no \`gh pr create\`, no PR or issue write of any kind. You hold a read credential and your job is to find out, not to change. If the investigation shows a change is needed, say exactly what and where in your write-up and point the user at \`agent:coding\`.
|
|
1702
|
+
|
|
1703
|
+
Maintain the user-facing status card with the update_status tool: post your plan as a checklist (\u25CB pending) once you have it, and update items as they start (\u2731) and finish (\u2713 \u2014 only after they actually happened). Items are short outcomes ("Clone and install", "Time the full suite"), never commands.
|
|
1704
|
+
|
|
1705
|
+
Report outcomes faithfully: a check you could not run is "could not check", never a guess. Use Slack-friendly formatting (no markdown headers; *bold*, bullets, code blocks \u2014 render the claim table as aligned rows inside a code block). Your final message is posted to Slack: lead with the overall verdict in one line, then the claim table, then what a follow-up should do.`;
|
|
1651
1706
|
AGENTS = {
|
|
1652
1707
|
general: {
|
|
1653
1708
|
name: "general",
|
|
1654
1709
|
description: "Default assistant on the configured model: answers directly, reads the org's repos and manages their issues over GitHub, reads URLs. No workspace or shell.",
|
|
1655
1710
|
system: GENERAL_SYSTEM,
|
|
1656
1711
|
toolset: "assistant",
|
|
1712
|
+
// The GitHub tools are REST in the bot process, so a general ask never
|
|
1713
|
+
// provisions a workspace or sandbox (docs/reference/specs/agent-general.md item 4)
|
|
1714
|
+
// and mints no credential of its own.
|
|
1715
|
+
machine: "none",
|
|
1716
|
+
identity: "none",
|
|
1657
1717
|
maxTurns: 8,
|
|
1658
1718
|
// a repo read is 2-3 calls (repos → tree → file); an issue action 1-2; still fast
|
|
1659
1719
|
maxTokens: 16e3,
|
|
1660
1720
|
maxMinutes: 5
|
|
1661
|
-
// No `resources`: the GitHub tools are REST in the bot process, so a
|
|
1662
|
-
// general ask still never provisions a workspace or sandbox (item 4).
|
|
1663
1721
|
},
|
|
1664
1722
|
coding: {
|
|
1665
1723
|
name: "coding",
|
|
@@ -1677,7 +1735,9 @@ You cannot run commands, clone repositories, edit code, or review pull requests,
|
|
|
1677
1735
|
cacheTtl: "1h",
|
|
1678
1736
|
// No built-in effort: the deployment decides (`defaults.efforts.coding`,
|
|
1679
1737
|
// `config set channel efforts.coding=…`, or `effort:` per request).
|
|
1680
|
-
|
|
1738
|
+
machine: "repo-resident",
|
|
1739
|
+
identity: "write"
|
|
1740
|
+
// pushes branches and opens pull requests
|
|
1681
1741
|
},
|
|
1682
1742
|
review: {
|
|
1683
1743
|
name: "review",
|
|
@@ -1685,7 +1745,9 @@ You cannot run commands, clone repositories, edit code, or review pull requests,
|
|
|
1685
1745
|
system: REVIEW_SYSTEM,
|
|
1686
1746
|
residentSystem: REVIEW_SYSTEM_RESIDENT,
|
|
1687
1747
|
toolset: "readonly",
|
|
1688
|
-
|
|
1748
|
+
machine: "repo-resident",
|
|
1749
|
+
identity: "read",
|
|
1750
|
+
// a read-scoped token and a read-only worktree: it cannot post or push from inside
|
|
1689
1751
|
maxTurns: 30,
|
|
1690
1752
|
// backstop only; wall clock is the real budget (12 bound at ~4 min in practice)
|
|
1691
1753
|
maxTokens: 64e3,
|
|
@@ -1701,27 +1763,52 @@ You cannot run commands, clone repositories, edit code, or review pull requests,
|
|
|
1701
1763
|
// pipeline orchestrator (src/core/shipPipeline.ts), whose child rounds run
|
|
1702
1764
|
// on the coding/review defs above — runAgent is never called with THIS def.
|
|
1703
1765
|
system: "You are Switchboard's ship pipeline. This prompt is never sent to a model \u2014 the pipeline orchestrates coding and review child runs on their own definitions.",
|
|
1704
|
-
// Full toolset
|
|
1705
|
-
//
|
|
1706
|
-
//
|
|
1707
|
-
//
|
|
1766
|
+
// Full toolset and the coding machine class, so repo and PR resolution
|
|
1767
|
+
// gate a ship thread like a coding one. `maxMinutes` is the pipeline's
|
|
1768
|
+
// wall clock (docs/reference/specs/agent-ship.md item 8): the ship preset's
|
|
1769
|
+
// declared budget, which a deployment's `ship.maxMinutes` knob replaces
|
|
1770
|
+
// (`shipPresetFor`) and a boundary or a `budget:` directive clips like any
|
|
1771
|
+
// preset's; every child round runs its own agent's budget clipped to what
|
|
1772
|
+
// remains of it. Turns and tokens are placeholders: no model call is ever
|
|
1773
|
+
// made with this def.
|
|
1708
1774
|
toolset: "full",
|
|
1775
|
+
machine: "repo-resident",
|
|
1776
|
+
identity: "write",
|
|
1709
1777
|
maxTurns: 1,
|
|
1710
1778
|
maxTokens: 16e3,
|
|
1711
|
-
maxMinutes:
|
|
1712
|
-
resources: { repo: "required" }
|
|
1779
|
+
maxMinutes: 120
|
|
1713
1780
|
},
|
|
1714
1781
|
research: {
|
|
1715
1782
|
name: "research",
|
|
1716
1783
|
description: "Answers questions with web search, URL reading, and read access to the org's repos and issues over GitHub. No workspace.",
|
|
1717
1784
|
system: RESEARCH_SYSTEM,
|
|
1718
1785
|
toolset: "web",
|
|
1719
|
-
|
|
1786
|
+
machine: "none",
|
|
1720
1787
|
// web I/O only; no workspace is provisioned
|
|
1788
|
+
identity: "none",
|
|
1721
1789
|
maxTurns: 12,
|
|
1722
1790
|
maxTokens: 24e3,
|
|
1723
1791
|
maxMinutes: 8,
|
|
1724
1792
|
effort: "medium"
|
|
1793
|
+
},
|
|
1794
|
+
explore: {
|
|
1795
|
+
name: "explore",
|
|
1796
|
+
description: "Long, read-only investigation of a repository in a cold sandbox: runs builds, suites and pipelines, searches the web, and reports a claim table with commands and numbers. Never opens a PR. Up to two hours.",
|
|
1797
|
+
system: EXPLORE_SYSTEM,
|
|
1798
|
+
toolset: "explore",
|
|
1799
|
+
// Always a cold per-thread sandbox with the checkout, never the resident a
|
|
1800
|
+
// review depends on: a two-hour job shares no container with anyone.
|
|
1801
|
+
machine: "repo-cold",
|
|
1802
|
+
identity: "read",
|
|
1803
|
+
// a read-scoped token: it can clone and read, never push — whatever the caller holds
|
|
1804
|
+
maxTurns: 150,
|
|
1805
|
+
// a backstop for a two-hour loop of batched checks; the wall clock is the budget
|
|
1806
|
+
maxTokens: 64e3,
|
|
1807
|
+
maxMinutes: 120,
|
|
1808
|
+
// A detached job polled across calls makes long steps: a 5m cache entry
|
|
1809
|
+
// would expire between them, so the 2× write buys reads for the whole run.
|
|
1810
|
+
cacheTtl: "1h"
|
|
1811
|
+
// No built-in effort: the deployment decides, as for coding.
|
|
1725
1812
|
}
|
|
1726
1813
|
};
|
|
1727
1814
|
}
|
|
@@ -2010,8 +2097,8 @@ var init_web = __esm({
|
|
|
2010
2097
|
"../../src/tools/web.ts"() {
|
|
2011
2098
|
"use strict";
|
|
2012
2099
|
WebSearchUnavailableError = class extends Error {
|
|
2013
|
-
constructor(
|
|
2014
|
-
super(
|
|
2100
|
+
constructor(message2) {
|
|
2101
|
+
super(message2);
|
|
2015
2102
|
this.name = "WebSearchUnavailableError";
|
|
2016
2103
|
}
|
|
2017
2104
|
};
|
|
@@ -2049,8 +2136,8 @@ var init_web = __esm({
|
|
|
2049
2136
|
return records.map((r) => r.address);
|
|
2050
2137
|
};
|
|
2051
2138
|
BlockedUrlError = class extends Error {
|
|
2052
|
-
constructor(
|
|
2053
|
-
super(
|
|
2139
|
+
constructor(message2) {
|
|
2140
|
+
super(message2);
|
|
2054
2141
|
this.name = "BlockedUrlError";
|
|
2055
2142
|
}
|
|
2056
2143
|
};
|
|
@@ -2319,6 +2406,38 @@ function validateScopeEfforts(layer, source2) {
|
|
|
2319
2406
|
}
|
|
2320
2407
|
}
|
|
2321
2408
|
}
|
|
2409
|
+
function boundaryProblem(path, raw) {
|
|
2410
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return `${path} must be a mapping`;
|
|
2411
|
+
for (const key of unknownKeys(raw, BOUNDARY_KEYS)) return `${path}: unknown field ${key}`;
|
|
2412
|
+
const b = raw;
|
|
2413
|
+
if (b.maxMinutes !== void 0 && (!Number.isInteger(b.maxMinutes) || b.maxMinutes < MIN_BOUNDARY_MINUTES))
|
|
2414
|
+
return `${path}.maxMinutes must be an integer >= ${MIN_BOUNDARY_MINUTES}`;
|
|
2415
|
+
if (b.maxIdentity !== void 0 && !IDENTITIES.includes(b.maxIdentity))
|
|
2416
|
+
return `${path}.maxIdentity is "${String(b.maxIdentity)}" \u2014 valid identities: ${IDENTITIES.join(", ")}`;
|
|
2417
|
+
if (b.machines !== void 0) {
|
|
2418
|
+
if (!Array.isArray(b.machines)) return `${path}.machines must be a list of classes`;
|
|
2419
|
+
if (b.machines.length === 0) return `${path}.machines must name at least one class`;
|
|
2420
|
+
for (const m of b.machines) {
|
|
2421
|
+
if (!MACHINE_CLASSES.includes(m))
|
|
2422
|
+
return `${path}.machines names "${String(m)}" \u2014 valid classes: ${MACHINE_CLASSES.join(", ")}`;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
return void 0;
|
|
2426
|
+
}
|
|
2427
|
+
function validateBoundaries(layer, source2) {
|
|
2428
|
+
const check = (path, raw) => {
|
|
2429
|
+
if (raw === void 0) return;
|
|
2430
|
+
const problem = boundaryProblem(path, raw);
|
|
2431
|
+
if (problem) throw new Error(`${source2}: ${problem}`);
|
|
2432
|
+
};
|
|
2433
|
+
check("defaults.boundary", layer.defaults?.boundary);
|
|
2434
|
+
for (const [kind, scopes] of [
|
|
2435
|
+
["channels", layer.channels],
|
|
2436
|
+
["users", layer.users]
|
|
2437
|
+
]) {
|
|
2438
|
+
for (const [id, scope] of Object.entries(scopes ?? {})) check(`${kind}.${id}.boundary`, scope.boundary);
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2322
2441
|
function validateMcpServers(layer, source2) {
|
|
2323
2442
|
const check = (path, tier, servers) => {
|
|
2324
2443
|
if (servers === void 0) return;
|
|
@@ -2371,6 +2490,7 @@ function validateMcpServers(layer, source2) {
|
|
|
2371
2490
|
function validateConfig(cfg) {
|
|
2372
2491
|
for (const key of unknownKeys(cfg, CONFIG_KEYS)) throw new Error(`config.yaml: unknown key \`${key}\``);
|
|
2373
2492
|
validateScopeEfforts(cfg, "config.yaml");
|
|
2493
|
+
validateBoundaries(cfg, "config.yaml");
|
|
2374
2494
|
validateMcpServers(cfg, "config.yaml");
|
|
2375
2495
|
if (typeof cfg.organization !== "string" || cfg.organization.trim() === "") {
|
|
2376
2496
|
throw new Error(
|
|
@@ -2470,7 +2590,7 @@ function validateRuntimeOverrides(ro) {
|
|
|
2470
2590
|
}
|
|
2471
2591
|
}
|
|
2472
2592
|
}
|
|
2473
|
-
var MAX_INSTRUCTIONS_LENGTH, CONFIG_KEYS, SELF_IMPROVEMENT_KEYS;
|
|
2593
|
+
var MAX_INSTRUCTIONS_LENGTH, CONFIG_KEYS, SELF_IMPROVEMENT_KEYS, BOUNDARY_KEYS, MIN_BOUNDARY_MINUTES;
|
|
2474
2594
|
var init_validate = __esm({
|
|
2475
2595
|
"../../src/config/validate.ts"() {
|
|
2476
2596
|
"use strict";
|
|
@@ -2512,6 +2632,90 @@ var init_validate = __esm({
|
|
|
2512
2632
|
minRuns: true,
|
|
2513
2633
|
top: true
|
|
2514
2634
|
};
|
|
2635
|
+
BOUNDARY_KEYS = { maxMinutes: true, maxIdentity: true, machines: true };
|
|
2636
|
+
MIN_BOUNDARY_MINUTES = 2;
|
|
2637
|
+
}
|
|
2638
|
+
});
|
|
2639
|
+
|
|
2640
|
+
// ../../src/config/profile.ts
|
|
2641
|
+
function clipSourceLabel(scope) {
|
|
2642
|
+
return scope === "directive" ? "budget directive" : `${scope} boundary`;
|
|
2643
|
+
}
|
|
2644
|
+
function identityWithin(identity2, cap) {
|
|
2645
|
+
return IDENTITY_ORDER[identity2] <= IDENTITY_ORDER[cap];
|
|
2646
|
+
}
|
|
2647
|
+
function declaredProfile(preset) {
|
|
2648
|
+
return { machine: preset.machine, identity: preset.identity, minutes: preset.maxMinutes };
|
|
2649
|
+
}
|
|
2650
|
+
function budgetedAgent(agent, profile) {
|
|
2651
|
+
return { ...agent, maxMinutes: profile.minutes };
|
|
2652
|
+
}
|
|
2653
|
+
function intersectBoundaries(layers) {
|
|
2654
|
+
const out = {};
|
|
2655
|
+
for (const { scope, boundary } of layers) {
|
|
2656
|
+
if (boundary.maxMinutes !== void 0 && (!out.maxMinutes || boundary.maxMinutes < out.maxMinutes.value)) {
|
|
2657
|
+
out.maxMinutes = { value: boundary.maxMinutes, scope };
|
|
2658
|
+
}
|
|
2659
|
+
if (boundary.maxIdentity !== void 0 && (!out.maxIdentity || !identityWithin(out.maxIdentity.value, boundary.maxIdentity))) {
|
|
2660
|
+
out.maxIdentity = { value: boundary.maxIdentity, scope };
|
|
2661
|
+
}
|
|
2662
|
+
if (boundary.machines !== void 0) {
|
|
2663
|
+
const allowed = boundary.machines;
|
|
2664
|
+
const value = (out.machines ? out.machines.value : allowed).filter((m) => allowed.includes(m)).sort((a, b) => MACHINE_ORDER[a] - MACHINE_ORDER[b]);
|
|
2665
|
+
out.machines = { value, by: [...out.machines?.by ?? [], { scope, machines: [...allowed] }] };
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
return out.maxMinutes || out.maxIdentity || out.machines ? out : void 0;
|
|
2669
|
+
}
|
|
2670
|
+
function effectiveProfile(preset, directives, boundary) {
|
|
2671
|
+
if (boundary?.maxIdentity && !identityWithin(preset.identity, boundary.maxIdentity.value)) {
|
|
2672
|
+
return {
|
|
2673
|
+
kind: "refused",
|
|
2674
|
+
refusal: {
|
|
2675
|
+
axis: "identity",
|
|
2676
|
+
needs: preset.identity,
|
|
2677
|
+
cap: boundary.maxIdentity.value,
|
|
2678
|
+
scope: boundary.maxIdentity.scope
|
|
2679
|
+
}
|
|
2680
|
+
};
|
|
2681
|
+
}
|
|
2682
|
+
if (boundary?.machines && !boundary.machines.value.includes(preset.machine)) {
|
|
2683
|
+
return {
|
|
2684
|
+
kind: "refused",
|
|
2685
|
+
refusal: {
|
|
2686
|
+
axis: "machine",
|
|
2687
|
+
needs: preset.machine,
|
|
2688
|
+
allowed: boundary.machines.value,
|
|
2689
|
+
scopes: boundary.machines.by.filter((b) => !b.machines.includes(preset.machine)).map((b) => b.scope)
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
}
|
|
2693
|
+
let minutes = preset.maxMinutes;
|
|
2694
|
+
let boundedBy;
|
|
2695
|
+
if (directives.budget !== void 0 && directives.budget < minutes) {
|
|
2696
|
+
minutes = directives.budget;
|
|
2697
|
+
boundedBy = "directive";
|
|
2698
|
+
}
|
|
2699
|
+
if (boundary?.maxMinutes && boundary.maxMinutes.value < minutes) {
|
|
2700
|
+
minutes = boundary.maxMinutes.value;
|
|
2701
|
+
boundedBy = boundary.maxMinutes.scope;
|
|
2702
|
+
}
|
|
2703
|
+
return {
|
|
2704
|
+
kind: "profile",
|
|
2705
|
+
profile: {
|
|
2706
|
+
machine: preset.machine,
|
|
2707
|
+
identity: preset.identity,
|
|
2708
|
+
minutes,
|
|
2709
|
+
...boundedBy !== void 0 ? { boundedBy } : {}
|
|
2710
|
+
}
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2713
|
+
var IDENTITY_ORDER, MACHINE_ORDER;
|
|
2714
|
+
var init_profile = __esm({
|
|
2715
|
+
"../../src/config/profile.ts"() {
|
|
2716
|
+
"use strict";
|
|
2717
|
+
IDENTITY_ORDER = { none: 0, read: 1, write: 2 };
|
|
2718
|
+
MACHINE_ORDER = { none: 0, blank: 1, "repo-cold": 2, "repo-resident": 3 };
|
|
2515
2719
|
}
|
|
2516
2720
|
});
|
|
2517
2721
|
|
|
@@ -2590,6 +2794,7 @@ function formatConfigDescription(d) {
|
|
|
2590
2794
|
const orgMcp = d.org?.mcpServers && Object.keys(d.org.mcpServers).length > 0 ? `, mcp ${Object.keys(d.org.mcpServers).map((n2) => `\`${n2}\``).join(" ")}` : "";
|
|
2591
2795
|
const lines = [
|
|
2592
2796
|
`*Effective for you in this channel:* ${effective}`,
|
|
2797
|
+
...d.effective.boundary ? [`*Effective boundary:* ${fmtEffectiveBoundary(d.effective.boundary)}`] : [],
|
|
2593
2798
|
`*Defaults:* ${defaults}${orgMcp}`,
|
|
2594
2799
|
`*Channel scope:* ${fmtScope(d.channel)}`,
|
|
2595
2800
|
`*Your scope:* ${fmtScope(d.user)}`
|
|
@@ -2614,8 +2819,26 @@ function fmtScope(s) {
|
|
|
2614
2819
|
parts.push(
|
|
2615
2820
|
`mcp ${Object.keys(s.mcpServers).map((n2) => `\`${n2}\``).join(" ")}`
|
|
2616
2821
|
);
|
|
2822
|
+
if (s.boundary) parts.push(`boundary ${fmtBoundary(s.boundary)}`);
|
|
2617
2823
|
return parts.length > 0 ? parts.join(", ") : "_none_";
|
|
2618
2824
|
}
|
|
2825
|
+
function fmtBoundary(b) {
|
|
2826
|
+
const parts = [];
|
|
2827
|
+
if (b.maxMinutes !== void 0) parts.push(`maxMinutes=${b.maxMinutes}`);
|
|
2828
|
+
if (b.maxIdentity !== void 0) parts.push(`maxIdentity=${b.maxIdentity}`);
|
|
2829
|
+
if (b.machines !== void 0) parts.push(`machines=${b.machines.join(",")}`);
|
|
2830
|
+
return parts.length > 0 ? parts.join(" ") : "(caps nothing)";
|
|
2831
|
+
}
|
|
2832
|
+
function fmtEffectiveBoundary(b) {
|
|
2833
|
+
const parts = [];
|
|
2834
|
+
if (b.maxMinutes) parts.push(`maxMinutes ${b.maxMinutes.value} (${b.maxMinutes.scope})`);
|
|
2835
|
+
if (b.maxIdentity) parts.push(`maxIdentity \`${b.maxIdentity.value}\` (${b.maxIdentity.scope})`);
|
|
2836
|
+
if (b.machines)
|
|
2837
|
+
parts.push(
|
|
2838
|
+
`machines ${b.machines.value.map((m) => `\`${m}\``).join(", ")} (${b.machines.by.map((l) => l.scope).join(", ")})`
|
|
2839
|
+
);
|
|
2840
|
+
return parts.join(", ");
|
|
2841
|
+
}
|
|
2619
2842
|
function fmtModels(m) {
|
|
2620
2843
|
return Object.entries(m).map(([k, v]) => `\`${k}=${v}\``).join(" ");
|
|
2621
2844
|
}
|
|
@@ -2632,6 +2855,7 @@ var init_config = __esm({
|
|
|
2632
2855
|
init_schedules();
|
|
2633
2856
|
init_registry();
|
|
2634
2857
|
init_validate();
|
|
2858
|
+
init_profile();
|
|
2635
2859
|
FileOverridesBacking = class {
|
|
2636
2860
|
path;
|
|
2637
2861
|
constructor(path) {
|
|
@@ -2752,6 +2976,7 @@ var init_config = __esm({
|
|
|
2752
2976
|
doc.users ??= {};
|
|
2753
2977
|
validateInstructions(doc, `overrides (${this.backing.describe()})`);
|
|
2754
2978
|
validateScopeEfforts(doc, `overrides (${this.backing.describe()})`);
|
|
2979
|
+
validateBoundaries(doc, `overrides (${this.backing.describe()})`);
|
|
2755
2980
|
validateMcpServers(
|
|
2756
2981
|
{ channels: doc.channels, users: doc.users, defaults: doc.org },
|
|
2757
2982
|
`overrides (${this.backing.describe()})`
|
|
@@ -2843,22 +3068,43 @@ var init_config = __esm({
|
|
|
2843
3068
|
return { channel: this.channelScope(channelId), user: this.userScope(userId) };
|
|
2844
3069
|
}
|
|
2845
3070
|
/**
|
|
2846
|
-
* Resolve which agent, model, and effort serve a request
|
|
2847
|
-
*
|
|
2848
|
-
*
|
|
2849
|
-
*
|
|
2850
|
-
*
|
|
3071
|
+
* Resolve which agent, model, and effort serve a request, and the boundary
|
|
3072
|
+
* every run on this path meets.
|
|
3073
|
+
* Agent: request directive > user scope > channel scope > default.
|
|
3074
|
+
* Model: request directive > (user > channel) forced model
|
|
3075
|
+
* > (user > channel > defaults) per-agent model.
|
|
3076
|
+
* Effort: the same ladder as model; unset at every layer → undefined.
|
|
3077
|
+
* Boundary: NOT a ladder — the defaults', the channel's and the user's
|
|
3078
|
+
* boundaries intersect (the smallest budget, the lowest identity,
|
|
3079
|
+
* the classes every layer allows), so a scope can only tighten what
|
|
3080
|
+
* the layers below it allow; no layer set → absent.
|
|
2851
3081
|
*/
|
|
2852
3082
|
resolve(opts) {
|
|
2853
3083
|
const ch = this.channelScope(opts.channelId);
|
|
2854
3084
|
const us = this.userScope(opts.userId);
|
|
2855
3085
|
const agentName = opts.request.agent ?? us.agent ?? ch.agent ?? this.config.defaults.agent;
|
|
3086
|
+
const boundary = intersectBoundaries(this.boundaryLayers(ch, us));
|
|
2856
3087
|
const modelRef2 = opts.request.model ?? us.model ?? ch.model ?? us.models?.[agentName] ?? ch.models?.[agentName] ?? this.config.defaults.models[agentName] ?? this.config.defaults.models["general"];
|
|
2857
3088
|
if (!modelRef2) {
|
|
2858
3089
|
throw new Error(`No model configured for agent "${agentName}" \u2014 set defaults.models.${agentName} in config.yaml`);
|
|
2859
3090
|
}
|
|
2860
3091
|
const effort2 = opts.request.effort ?? us.effort ?? ch.effort ?? us.efforts?.[agentName] ?? ch.efforts?.[agentName] ?? this.config.defaults.efforts?.[agentName];
|
|
2861
|
-
return {
|
|
3092
|
+
return {
|
|
3093
|
+
agentName,
|
|
3094
|
+
modelRef: modelRef2,
|
|
3095
|
+
...effort2 !== void 0 ? { effort: effort2 } : {},
|
|
3096
|
+
...boundary !== void 0 ? { boundary } : {}
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
/** The boundary layers on a path, in resolution order, keeping only the
|
|
3100
|
+
* scopes that set one — `intersectBoundaries` names each axis's scope from it. */
|
|
3101
|
+
boundaryLayers(channel, user) {
|
|
3102
|
+
const layers = [
|
|
3103
|
+
["defaults", this.config.defaults.boundary],
|
|
3104
|
+
["channel", channel.boundary],
|
|
3105
|
+
["user", user.boundary]
|
|
3106
|
+
];
|
|
3107
|
+
return layers.flatMap(([scope, boundary]) => boundary ? [{ scope, boundary }] : []);
|
|
2862
3108
|
}
|
|
2863
3109
|
// ---- authorization gates ----------------------------------------------------
|
|
2864
3110
|
// Every gate reads the grants table (authorization.md item 9): what an actor
|
|
@@ -2983,7 +3229,8 @@ var init_config = __esm({
|
|
|
2983
3229
|
effective: {
|
|
2984
3230
|
agent: resolved.agentName,
|
|
2985
3231
|
model: resolved.modelRef,
|
|
2986
|
-
...resolved.effort ? { effort: resolved.effort } : {}
|
|
3232
|
+
...resolved.effort ? { effort: resolved.effort } : {},
|
|
3233
|
+
...resolved.boundary ? { boundary: resolved.boundary } : {}
|
|
2987
3234
|
},
|
|
2988
3235
|
defaults: {
|
|
2989
3236
|
agent: this.config.defaults.agent,
|
|
@@ -3967,8 +4214,8 @@ var init_tracer = __esm({
|
|
|
3967
4214
|
delete this.rec.errorMessage;
|
|
3968
4215
|
return;
|
|
3969
4216
|
}
|
|
3970
|
-
const
|
|
3971
|
-
this.rec.errorMessage = redactAndCap(
|
|
4217
|
+
const message2 = err2 instanceof Error ? err2.message : String(err2);
|
|
4218
|
+
this.rec.errorMessage = redactAndCap(message2, ERROR_MESSAGE_CAP);
|
|
3972
4219
|
}
|
|
3973
4220
|
setAttrs(attrs) {
|
|
3974
4221
|
this.rec.attrs = { ...this.rec.attrs, ...attrs };
|
|
@@ -4187,7 +4434,7 @@ function isExampleProfile(p) {
|
|
|
4187
4434
|
return p.account === EXAMPLE_ACCOUNT;
|
|
4188
4435
|
}
|
|
4189
4436
|
var WORKER_KINDS, PROFILE_PATH, PROFILE_EXAMPLE_PATH, PROFILE_ENV, hostname, endpoint, source, IMAGE_MODES, profileSchema, EXAMPLE_ACCOUNT;
|
|
4190
|
-
var
|
|
4437
|
+
var init_profile2 = __esm({
|
|
4191
4438
|
"../../src/deploy/profile.ts"() {
|
|
4192
4439
|
"use strict";
|
|
4193
4440
|
WORKER_KINDS = ["memory", "bot", "resident", "sandbox"];
|
|
@@ -4452,7 +4699,7 @@ var init_plan = __esm({
|
|
|
4452
4699
|
init_configDocument();
|
|
4453
4700
|
init_images();
|
|
4454
4701
|
init_operatorRoot();
|
|
4455
|
-
|
|
4702
|
+
init_profile2();
|
|
4456
4703
|
UNSET_ENV = ["CLOUDFLARE_ACCOUNT_ID"];
|
|
4457
4704
|
SANDBOX_CONTAINER_CLASS = "SwitchboardSandbox";
|
|
4458
4705
|
SANDBOX_BEARER_ENV = "SANDBOX_TOKEN";
|
|
@@ -5203,7 +5450,7 @@ var init_wranglerTemplate = __esm({
|
|
|
5203
5450
|
"use strict";
|
|
5204
5451
|
init_images();
|
|
5205
5452
|
init_plan();
|
|
5206
|
-
|
|
5453
|
+
init_profile2();
|
|
5207
5454
|
init_images();
|
|
5208
5455
|
TEMPLATE_FILE = "wrangler.template.jsonc";
|
|
5209
5456
|
RENDERED_FILE = "wrangler.jsonc";
|
|
@@ -5402,7 +5649,7 @@ var init_restart = __esm({
|
|
|
5402
5649
|
init_ingressTokens();
|
|
5403
5650
|
init_authorize();
|
|
5404
5651
|
init_liveGate();
|
|
5405
|
-
|
|
5652
|
+
init_profile2();
|
|
5406
5653
|
RESTART_TOKEN_ENV = "SWITCHBOARD_DEPLOY_TOKEN";
|
|
5407
5654
|
RESTART_SCOPE = "deploy:write";
|
|
5408
5655
|
RESTART_AUTHORIZE_PATH = "/admin/restart/authorize";
|
|
@@ -6383,7 +6630,7 @@ var init_run = __esm({
|
|
|
6383
6630
|
init_wranglerTemplate();
|
|
6384
6631
|
init_configSource();
|
|
6385
6632
|
init_images();
|
|
6386
|
-
|
|
6633
|
+
init_profile2();
|
|
6387
6634
|
init_restart();
|
|
6388
6635
|
init_wranglerTemplate();
|
|
6389
6636
|
init_sandboxLiveGate();
|
|
@@ -6865,8 +7112,8 @@ var init_registryTransferHost = __esm({
|
|
|
6865
7112
|
SHORT_MS = 6e4;
|
|
6866
7113
|
LONG_MS = 30 * 6e4;
|
|
6867
7114
|
TransferProblem = class extends Error {
|
|
6868
|
-
constructor(
|
|
6869
|
-
super(
|
|
7115
|
+
constructor(message2, unauthorized = false) {
|
|
7116
|
+
super(message2);
|
|
6870
7117
|
this.unauthorized = unauthorized;
|
|
6871
7118
|
}
|
|
6872
7119
|
unauthorized;
|
|
@@ -7493,7 +7740,7 @@ var TEMPLATE_PATHS;
|
|
|
7493
7740
|
var init_host3 = __esm({
|
|
7494
7741
|
"../../src/setup/host.ts"() {
|
|
7495
7742
|
"use strict";
|
|
7496
|
-
|
|
7743
|
+
init_profile2();
|
|
7497
7744
|
init_packageRoot();
|
|
7498
7745
|
init_host();
|
|
7499
7746
|
init_meatProcess();
|
|
@@ -7505,42 +7752,6 @@ var init_host3 = __esm({
|
|
|
7505
7752
|
}
|
|
7506
7753
|
});
|
|
7507
7754
|
|
|
7508
|
-
// ../../src/execution/bashTimeout.ts
|
|
7509
|
-
function clampBashTimeout(requested) {
|
|
7510
|
-
if (typeof requested !== "number" || !Number.isFinite(requested)) return BASH_TIMEOUT_MS;
|
|
7511
|
-
return Math.min(Math.max(Math.trunc(requested), BASH_TIMEOUT_MIN_MS), BASH_TIMEOUT_MAX_MS);
|
|
7512
|
-
}
|
|
7513
|
-
function bashBudgetWithinRun(wantedMs, remainingMs) {
|
|
7514
|
-
const secs = (ms) => Math.max(0, Math.round(ms / 1e3));
|
|
7515
|
-
const cap = Math.trunc(remainingMs - RUN_DEADLINE_RESERVE_MS);
|
|
7516
|
-
if (cap < BASH_TIMEOUT_MIN_MS) {
|
|
7517
|
-
return {
|
|
7518
|
-
kind: "exhausted",
|
|
7519
|
-
note: `run budget exhausted \u2014 ${secs(remainingMs)}s of wall clock left, inside the ${secs(RUN_DEADLINE_RESERVE_MS)}s write-up reserve, so the command was not run; write up what you have now`
|
|
7520
|
-
};
|
|
7521
|
-
}
|
|
7522
|
-
if (cap >= wantedMs) return { kind: "unchanged" };
|
|
7523
|
-
return {
|
|
7524
|
-
kind: "clipped",
|
|
7525
|
-
timeoutMs: cap,
|
|
7526
|
-
note: `[timeout clipped to ${secs(cap)}s \u2014 the run's wall clock ends in ${secs(remainingMs)}s]`
|
|
7527
|
-
};
|
|
7528
|
-
}
|
|
7529
|
-
function bashTimeoutNote(timeoutMs) {
|
|
7530
|
-
return `aborted at the ${Math.round(timeoutMs / 1e3)}s command timeout (pass the bash tool's timeoutMs for longer commands, max ${BASH_TIMEOUT_MAX_MS} ms)`;
|
|
7531
|
-
}
|
|
7532
|
-
var BASH_TIMEOUT_MS, BASH_TIMEOUT_MIN_MS, BASH_TIMEOUT_MAX_MS, RUN_DEADLINE_RESERVE_MS, EXEC_CALL_MARGIN_MS;
|
|
7533
|
-
var init_bashTimeout = __esm({
|
|
7534
|
-
"../../src/execution/bashTimeout.ts"() {
|
|
7535
|
-
"use strict";
|
|
7536
|
-
BASH_TIMEOUT_MS = 5 * 6e4;
|
|
7537
|
-
BASH_TIMEOUT_MIN_MS = 1e3;
|
|
7538
|
-
BASH_TIMEOUT_MAX_MS = 20 * 6e4;
|
|
7539
|
-
RUN_DEADLINE_RESERVE_MS = 6e4;
|
|
7540
|
-
EXEC_CALL_MARGIN_MS = 3e4;
|
|
7541
|
-
}
|
|
7542
|
-
});
|
|
7543
|
-
|
|
7544
7755
|
// ../../src/execution/executor.ts
|
|
7545
7756
|
import { execFile } from "node:child_process";
|
|
7546
7757
|
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
@@ -7598,15 +7809,15 @@ var init_executor = __esm({
|
|
|
7598
7809
|
init_bashTimeout();
|
|
7599
7810
|
ExecInfraError = class extends Error {
|
|
7600
7811
|
infra = true;
|
|
7601
|
-
constructor(
|
|
7602
|
-
super(
|
|
7812
|
+
constructor(message2) {
|
|
7813
|
+
super(message2);
|
|
7603
7814
|
this.name = "ExecInfraError";
|
|
7604
7815
|
}
|
|
7605
7816
|
};
|
|
7606
7817
|
ExecCapacityError = class extends Error {
|
|
7607
7818
|
capacity = true;
|
|
7608
|
-
constructor(
|
|
7609
|
-
super(
|
|
7819
|
+
constructor(message2) {
|
|
7820
|
+
super(message2);
|
|
7610
7821
|
this.name = "ExecCapacityError";
|
|
7611
7822
|
}
|
|
7612
7823
|
};
|
|
@@ -8901,9 +9112,19 @@ var init_residentState = __esm({
|
|
|
8901
9112
|
import { resolve as resolve7 } from "node:path";
|
|
8902
9113
|
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
8903
9114
|
async function makeExecutor(opts, ctx, span) {
|
|
8904
|
-
|
|
9115
|
+
const machine = ctx.profile.machine;
|
|
9116
|
+
if (machine === "none") {
|
|
8905
9117
|
return { executor: new NullExecutor(ctx.agent.name), backend: "local" };
|
|
8906
9118
|
}
|
|
9119
|
+
if (machine === "blank") {
|
|
9120
|
+
return {
|
|
9121
|
+
executor: await makePerThreadExecutor(opts, { threadKey: ctx.threadKey, resolveEnvs: async () => ({}) }),
|
|
9122
|
+
backend: perThreadBackend(opts)
|
|
9123
|
+
};
|
|
9124
|
+
}
|
|
9125
|
+
if (machine === "repo-cold") {
|
|
9126
|
+
return { executor: await makePerThreadExecutor(opts, perThreadCheckout(ctx)), backend: perThreadBackend(opts) };
|
|
9127
|
+
}
|
|
8907
9128
|
let note;
|
|
8908
9129
|
let failedAttach;
|
|
8909
9130
|
if (ctx.repo && opts.execution?.resident) {
|
|
@@ -8916,7 +9137,7 @@ async function makeExecutor(opts, ctx, span) {
|
|
|
8916
9137
|
if (probe.kind === "status" && isServiceable(probe.state, probe.reason)) {
|
|
8917
9138
|
try {
|
|
8918
9139
|
const nonWarm = probe.state === "warm" ? void 0 : oneLine(`${probe.state}${probe.reason ? ` (${probe.reason})` : ""}`);
|
|
8919
|
-
const readonly = ctx.
|
|
9140
|
+
const readonly = ctx.profile.identity === "read" ? true : void 0;
|
|
8920
9141
|
return await openResident(
|
|
8921
9142
|
{
|
|
8922
9143
|
baseUrl: resident.baseUrl,
|
|
@@ -8946,7 +9167,7 @@ async function makeExecutor(opts, ctx, span) {
|
|
|
8946
9167
|
}
|
|
8947
9168
|
}
|
|
8948
9169
|
return {
|
|
8949
|
-
executor: await makePerThreadExecutor(opts, ctx),
|
|
9170
|
+
executor: await makePerThreadExecutor(opts, perThreadCheckout(ctx)),
|
|
8950
9171
|
note,
|
|
8951
9172
|
backend: perThreadBackend(opts),
|
|
8952
9173
|
...failedAttach ? { trace: failedAttach.steps } : {}
|
|
@@ -9041,8 +9262,16 @@ function localWorkspaceDir(baseDir, threadKey) {
|
|
|
9041
9262
|
const safe = threadKey.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
9042
9263
|
return resolve7(baseDir, safe);
|
|
9043
9264
|
}
|
|
9044
|
-
|
|
9045
|
-
|
|
9265
|
+
function perThreadCheckout(ctx) {
|
|
9266
|
+
return {
|
|
9267
|
+
threadKey: ctx.threadKey,
|
|
9268
|
+
repo: ctx.repo,
|
|
9269
|
+
ref: ctx.ref,
|
|
9270
|
+
resolveEnvs: () => githubEnvs(ctx.profile.identity)
|
|
9271
|
+
};
|
|
9272
|
+
}
|
|
9273
|
+
async function makePerThreadExecutor(opts, input) {
|
|
9274
|
+
const { threadKey } = input;
|
|
9046
9275
|
const type = opts.execution?.type ?? "local";
|
|
9047
9276
|
if (type === "local") {
|
|
9048
9277
|
const dir = localWorkspaceDir(opts.workspaceDir, threadKey);
|
|
@@ -9058,9 +9287,9 @@ async function makePerThreadExecutor(opts, ctx) {
|
|
|
9058
9287
|
threadKey,
|
|
9059
9288
|
timeoutMs: (opts.execution?.timeoutMinutes ?? 30) * 6e4,
|
|
9060
9289
|
statePath: resolve7(opts.dataDir, "sandboxes.json"),
|
|
9061
|
-
resolveEnvs:
|
|
9062
|
-
repo:
|
|
9063
|
-
ref:
|
|
9290
|
+
resolveEnvs: input.resolveEnvs,
|
|
9291
|
+
repo: input.repo,
|
|
9292
|
+
ref: input.ref
|
|
9064
9293
|
});
|
|
9065
9294
|
}
|
|
9066
9295
|
if (type === "cloudflare") {
|
|
@@ -9074,15 +9303,19 @@ async function makePerThreadExecutor(opts, ctx) {
|
|
|
9074
9303
|
url: opts.execution.url,
|
|
9075
9304
|
token: token.reveal(),
|
|
9076
9305
|
threadKey,
|
|
9077
|
-
resolveEnvs:
|
|
9078
|
-
repo:
|
|
9079
|
-
ref:
|
|
9306
|
+
resolveEnvs: input.resolveEnvs,
|
|
9307
|
+
repo: input.repo,
|
|
9308
|
+
ref: input.ref
|
|
9080
9309
|
});
|
|
9081
9310
|
}
|
|
9082
9311
|
throw new Error(`Unknown execution.type "${type}" (valid: local, e2b, cloudflare)`);
|
|
9083
9312
|
}
|
|
9084
|
-
|
|
9085
|
-
|
|
9313
|
+
function githubTokenScopeFor(identity2) {
|
|
9314
|
+
return identity2 === "none" ? void 0 : identity2;
|
|
9315
|
+
}
|
|
9316
|
+
async function githubEnvs(identity2) {
|
|
9317
|
+
const scope = githubTokenScopeFor(identity2);
|
|
9318
|
+
if (scope === void 0) return {};
|
|
9086
9319
|
const token = await resolveGithubToken(scope);
|
|
9087
9320
|
return token ? { GH_TOKEN: token } : {};
|
|
9088
9321
|
}
|
|
@@ -9113,7 +9346,7 @@ var init_factory = __esm({
|
|
|
9113
9346
|
agentName;
|
|
9114
9347
|
fail() {
|
|
9115
9348
|
throw new Error(
|
|
9116
|
-
`Agent "${this.agentName}"
|
|
9349
|
+
`Agent "${this.agentName}" runs on machine class "none", so it has no execution workspace. Declare a machine class that provisions one (\`repo-resident\`, \`repo-cold\` or \`blank\`) if its tools need one.`
|
|
9117
9350
|
);
|
|
9118
9351
|
}
|
|
9119
9352
|
async exec() {
|
|
@@ -9151,9 +9384,9 @@ function parseFindings(body) {
|
|
|
9151
9384
|
function isAgentLogin(login, identities) {
|
|
9152
9385
|
return login.endsWith("[bot]") || identities.agentLogins.includes(login);
|
|
9153
9386
|
}
|
|
9154
|
-
function coauthorsOf(
|
|
9387
|
+
function coauthorsOf(message2) {
|
|
9155
9388
|
const out = [];
|
|
9156
|
-
for (const line3 of
|
|
9389
|
+
for (const line3 of message2.split("\n")) {
|
|
9157
9390
|
const m = /^\s*co-authored-by:\s*(.+?)\s*$/i.exec(line3);
|
|
9158
9391
|
if (m) out.push(m[1]);
|
|
9159
9392
|
}
|
|
@@ -9346,9 +9579,25 @@ function indicatorLines(x) {
|
|
|
9346
9579
|
`agent runs: ${x.agentRuns.count} \xB7 ${x.agentRuns.minutes.toFixed(1)} min`
|
|
9347
9580
|
];
|
|
9348
9581
|
}
|
|
9349
|
-
function
|
|
9582
|
+
function snapshotAgeText(snapshotAt, nowMs) {
|
|
9583
|
+
const minutes = Math.max(0, Math.floor((nowMs - Date.parse(snapshotAt)) / 6e4));
|
|
9584
|
+
if (!Number.isFinite(minutes)) return "";
|
|
9585
|
+
const unit = (n2, word) => `${n2} ${word}${n2 === 1 ? "" : "s"} ago`;
|
|
9586
|
+
if (minutes < 1) return "just now";
|
|
9587
|
+
if (minutes < 90) return unit(minutes, "minute");
|
|
9588
|
+
const hours2 = Math.round(minutes / 60);
|
|
9589
|
+
if (hours2 < 48) return unit(hours2, "hour");
|
|
9590
|
+
return unit(Math.round(hours2 / 24), "day");
|
|
9591
|
+
}
|
|
9592
|
+
function asOf(snapshotAt, nowMs) {
|
|
9593
|
+
return `as of ${snapshotAt.slice(0, 10)} ${snapshotAt.slice(11, 16)} UTC, ${snapshotAgeText(snapshotAt, nowMs)}`;
|
|
9594
|
+
}
|
|
9595
|
+
function renderDeliveryReport(report2, nowMs = systemClock()) {
|
|
9350
9596
|
const lines = [
|
|
9351
|
-
|
|
9597
|
+
[
|
|
9598
|
+
`${report2.repo} \xB7 ${report2.range.since} \u2192 ${report2.range.until} \xB7 ${report2.range.weeks} week${report2.range.weeks === 1 ? "" : "s"}`,
|
|
9599
|
+
...report2.snapshotAt !== void 0 ? [asOf(report2.snapshotAt, nowMs)] : []
|
|
9600
|
+
].join(" \xB7 ")
|
|
9352
9601
|
];
|
|
9353
9602
|
if (report2.truncated) lines.push("(the newest pull requests only \u2014 the fetch stopped before the range's start)");
|
|
9354
9603
|
for (const w of report2.weeks) {
|
|
@@ -9390,6 +9639,18 @@ function stringList(raw, what, valid = () => true) {
|
|
|
9390
9639
|
throw new Error(`${what} must be a list of ${what.endsWith("repos") ? "owner/name repositories" : "names"}`);
|
|
9391
9640
|
return raw;
|
|
9392
9641
|
}
|
|
9642
|
+
function snapshotConfig(raw) {
|
|
9643
|
+
if (raw === void 0) return { everyMinutes: SNAPSHOT_EVERY_MINUTES.default };
|
|
9644
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
9645
|
+
throw new Error("delivery.snapshot must be a mapping");
|
|
9646
|
+
const every = raw.everyMinutes;
|
|
9647
|
+
if (every === void 0) return { everyMinutes: SNAPSHOT_EVERY_MINUTES.default };
|
|
9648
|
+
if (typeof every !== "number" || !Number.isInteger(every) || every < SNAPSHOT_EVERY_MINUTES.min || every > SNAPSHOT_EVERY_MINUTES.max)
|
|
9649
|
+
throw new Error(
|
|
9650
|
+
`delivery.snapshot.everyMinutes must be a whole number of minutes between ${SNAPSHOT_EVERY_MINUTES.min} and ${SNAPSHOT_EVERY_MINUTES.max}`
|
|
9651
|
+
);
|
|
9652
|
+
return { everyMinutes: every };
|
|
9653
|
+
}
|
|
9393
9654
|
function parseDeliveryConfig(raw) {
|
|
9394
9655
|
if (raw === void 0 || raw === null) return void 0;
|
|
9395
9656
|
if (typeof raw !== "object" || Array.isArray(raw)) throw new Error("delivery: must be a mapping");
|
|
@@ -9398,7 +9659,8 @@ function parseDeliveryConfig(raw) {
|
|
|
9398
9659
|
repos: stringList(r.repos, "delivery.repos", (s) => REPO_SLUG.test(s)),
|
|
9399
9660
|
reviewers: stringList(r.reviewers, "delivery.reviewers"),
|
|
9400
9661
|
agentLogins: stringList(r.agentLogins, "delivery.agentLogins"),
|
|
9401
|
-
agentCoauthors: stringList(r.agentCoauthors, "delivery.agentCoauthors")
|
|
9662
|
+
agentCoauthors: stringList(r.agentCoauthors, "delivery.agentCoauthors"),
|
|
9663
|
+
snapshot: snapshotConfig(r.snapshot)
|
|
9402
9664
|
};
|
|
9403
9665
|
}
|
|
9404
9666
|
function createDeliveryService(cfg, source2, opts = {}) {
|
|
@@ -9408,9 +9670,10 @@ function createDeliveryService(cfg, source2, opts = {}) {
|
|
|
9408
9670
|
repos: () => [...cfg?.repos ?? []],
|
|
9409
9671
|
async report(repo, o) {
|
|
9410
9672
|
if (!REPO_SLUG.test(repo)) throw new Error(`repository must be owner/name, got ${JSON.stringify(repo)}`);
|
|
9411
|
-
const
|
|
9673
|
+
const at = now();
|
|
9674
|
+
const range = resolveDeliveryRange({ since: o.since, weeks: o.weeks }, at);
|
|
9412
9675
|
const [fetched, process2, runs] = await Promise.all([
|
|
9413
|
-
source2.fetchPullRequests(repo, range),
|
|
9676
|
+
source2.fetchPullRequests(repo, range, o.fresh ? { fresh: true } : void 0),
|
|
9414
9677
|
opts.identities?.() ?? Promise.resolve({}),
|
|
9415
9678
|
o.runs?.(range) ?? Promise.resolve([])
|
|
9416
9679
|
]);
|
|
@@ -9419,18 +9682,22 @@ function createDeliveryService(cfg, source2, opts = {}) {
|
|
|
9419
9682
|
agentLogins: [.../* @__PURE__ */ new Set([...cfg?.agentLogins ?? [], ...process2.agentLogins ?? []])],
|
|
9420
9683
|
agentCoauthors: [.../* @__PURE__ */ new Set([...cfg?.agentCoauthors ?? [], ...process2.agentCoauthors ?? []])]
|
|
9421
9684
|
};
|
|
9422
|
-
return
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9685
|
+
return {
|
|
9686
|
+
...buildDeliveryReport({
|
|
9687
|
+
repo,
|
|
9688
|
+
range,
|
|
9689
|
+
prs: fetched.prs,
|
|
9690
|
+
runs,
|
|
9691
|
+
identities,
|
|
9692
|
+
truncated: fetched.truncated
|
|
9693
|
+
}),
|
|
9694
|
+
// A source behind a snapshot says when it read; a bare one read just now.
|
|
9695
|
+
snapshotAt: fetched.fetchedAt ?? at.toISOString()
|
|
9696
|
+
};
|
|
9430
9697
|
}
|
|
9431
9698
|
};
|
|
9432
9699
|
}
|
|
9433
|
-
var FINDING_SEVERITIES, DAY_MS, HOUR_MS, emptyCounts, CI_TRIGGERS, CI_DECISIVE, byTime, EMPTY_IDENTITIES, DEFAULT_WEEKS, MAX_WEEKS, ISO_DAY, pct, hours, REPO_SLUG, DELIVERY_OFF_MESSAGE, NullDeliveryService;
|
|
9700
|
+
var FINDING_SEVERITIES, DAY_MS, HOUR_MS, emptyCounts, CI_TRIGGERS, CI_DECISIVE, byTime, EMPTY_IDENTITIES, DEFAULT_WEEKS, MAX_WEEKS, ISO_DAY, pct, hours, SNAPSHOT_EVERY_MINUTES, REPO_SLUG, DELIVERY_OFF_MESSAGE, NullDeliveryService;
|
|
9434
9701
|
var init_delivery = __esm({
|
|
9435
9702
|
"../../src/core/delivery.ts"() {
|
|
9436
9703
|
"use strict";
|
|
@@ -9458,6 +9725,7 @@ var init_delivery = __esm({
|
|
|
9458
9725
|
ISO_DAY = /^\d{4}-\d{2}-\d{2}$/;
|
|
9459
9726
|
pct = (share) => share === null ? "\u2014" : `${Math.round(share * 100)}%`;
|
|
9460
9727
|
hours = (h, digits2 = 1) => h === null ? "\u2014" : `${h.toFixed(digits2)} h`;
|
|
9728
|
+
SNAPSHOT_EVERY_MINUTES = Object.freeze({ default: 60, min: 5, max: 1440 });
|
|
9461
9729
|
REPO_SLUG = /^(?!\.+\/)[\w.-]+\/(?!\.+$)[\w.-]+$/;
|
|
9462
9730
|
DELIVERY_OFF_MESSAGE = "Delivery indicators aren't available \u2014 this process has no GitHub credential (the GitHub App triple or GH_TOKEN); set one, then name repositories under delivery.repos.";
|
|
9463
9731
|
NullDeliveryService = class {
|
|
@@ -9711,12 +9979,16 @@ var init_githubDelivery = __esm({
|
|
|
9711
9979
|
const json = async (res) => res.status === 404 ? void 0 : res.json();
|
|
9712
9980
|
const merged = [];
|
|
9713
9981
|
let truncated = false;
|
|
9982
|
+
let oldestUpdated;
|
|
9714
9983
|
for (let page2 = 1; ; page2++) {
|
|
9715
9984
|
const res = await get(
|
|
9716
9985
|
"pulls",
|
|
9717
9986
|
`/repos/${repo}/pulls?state=closed&sort=updated&direction=desc&per_page=${PAGE_SIZE}&page=${page2}`
|
|
9718
9987
|
);
|
|
9719
9988
|
const items = parsePullListPage(await json(res));
|
|
9989
|
+
for (const item of items) {
|
|
9990
|
+
if (!oldestUpdated || Date.parse(item.updatedAt) < Date.parse(oldestUpdated.updatedAt)) oldestUpdated = item;
|
|
9991
|
+
}
|
|
9720
9992
|
const selected = selectMerged(items, range);
|
|
9721
9993
|
merged.push(...selected.merged);
|
|
9722
9994
|
if (selected.olderSeen || items.length < PAGE_SIZE) break;
|
|
@@ -9725,6 +9997,7 @@ var init_githubDelivery = __esm({
|
|
|
9725
9997
|
break;
|
|
9726
9998
|
}
|
|
9727
9999
|
}
|
|
10000
|
+
const completeFrom = truncated && oldestUpdated ? oldestUpdated.updatedAt : `${range.since}T00:00:00Z`;
|
|
9728
10001
|
const issues = /* @__PURE__ */ new Map();
|
|
9729
10002
|
const issueOf = (n2) => {
|
|
9730
10003
|
let p = issues.get(n2);
|
|
@@ -9771,12 +10044,257 @@ var init_githubDelivery = __esm({
|
|
|
9771
10044
|
...issue ? { issue } : {}
|
|
9772
10045
|
};
|
|
9773
10046
|
});
|
|
9774
|
-
return { prs, truncated };
|
|
10047
|
+
return { prs, truncated, completeFrom };
|
|
10048
|
+
}
|
|
10049
|
+
};
|
|
10050
|
+
}
|
|
10051
|
+
});
|
|
10052
|
+
|
|
10053
|
+
// ../../src/core/deliverySnapshot.ts
|
|
10054
|
+
function snapshotAgeMinutes(snapshotAt, nowMs) {
|
|
10055
|
+
return Math.max(0, Math.floor((nowMs - Date.parse(snapshotAt)) / 6e4));
|
|
10056
|
+
}
|
|
10057
|
+
function serve(snapshot, range) {
|
|
10058
|
+
return {
|
|
10059
|
+
prs: snapshot.prs,
|
|
10060
|
+
truncated: dayStart(range.since) < Date.parse(snapshot.completeFrom),
|
|
10061
|
+
fetchedAt: snapshot.snapshotAt
|
|
10062
|
+
};
|
|
10063
|
+
}
|
|
10064
|
+
var SNAPSHOT_WEEKS, SNAPSHOT_TICK_MS, dayStart, message, SnapshottingDeliverySource;
|
|
10065
|
+
var init_deliverySnapshot = __esm({
|
|
10066
|
+
"../../src/core/deliverySnapshot.ts"() {
|
|
10067
|
+
"use strict";
|
|
10068
|
+
init_delivery();
|
|
10069
|
+
init_clock();
|
|
10070
|
+
SNAPSHOT_WEEKS = 13;
|
|
10071
|
+
SNAPSHOT_TICK_MS = 6e4;
|
|
10072
|
+
dayStart = (day) => Date.parse(`${day}T00:00:00Z`);
|
|
10073
|
+
message = (err2) => err2 instanceof Error ? err2.message : String(err2);
|
|
10074
|
+
SnapshottingDeliverySource = class {
|
|
10075
|
+
constructor(inner, store, opts = {}) {
|
|
10076
|
+
this.inner = inner;
|
|
10077
|
+
this.store = store;
|
|
10078
|
+
this.now = opts.now ?? (() => new Date(systemClock()));
|
|
10079
|
+
this.warn = opts.warn ?? (() => void 0);
|
|
10080
|
+
this.weeks = opts.weeks ?? SNAPSHOT_WEEKS;
|
|
10081
|
+
}
|
|
10082
|
+
inner;
|
|
10083
|
+
store;
|
|
10084
|
+
memory = /* @__PURE__ */ new Map();
|
|
10085
|
+
/** Store reads in flight, one per repository. */
|
|
10086
|
+
loading = /* @__PURE__ */ new Map();
|
|
10087
|
+
/** GitHub reads in flight, one per repository: concurrent callers share it. */
|
|
10088
|
+
refreshing = /* @__PURE__ */ new Map();
|
|
10089
|
+
now;
|
|
10090
|
+
warn;
|
|
10091
|
+
weeks;
|
|
10092
|
+
async fetchPullRequests(repo, range, opts) {
|
|
10093
|
+
const snapshot = opts?.fresh ? void 0 : await this.current(repo);
|
|
10094
|
+
if (snapshot && range.since >= snapshot.range.since) return serve(snapshot, range);
|
|
10095
|
+
if (range.since < this.window().since) return this.live(repo, range);
|
|
10096
|
+
return serve(await this.refresh(repo), range);
|
|
10097
|
+
}
|
|
10098
|
+
/** The repository's snapshot as this process knows it: memory, else the store, read once. */
|
|
10099
|
+
current(repo) {
|
|
10100
|
+
const known = this.memory.get(repo);
|
|
10101
|
+
if (known) return Promise.resolve(known);
|
|
10102
|
+
let loading = this.loading.get(repo);
|
|
10103
|
+
if (!loading) {
|
|
10104
|
+
loading = this.store.get(repo).then((stored) => {
|
|
10105
|
+
if (stored) this.memory.set(repo, stored);
|
|
10106
|
+
return stored;
|
|
10107
|
+
}).catch((err2) => {
|
|
10108
|
+
this.warn(`delivery snapshot for ${repo} not read from the store: ${message(err2)}`);
|
|
10109
|
+
return void 0;
|
|
10110
|
+
}).finally(() => this.loading.delete(repo));
|
|
10111
|
+
this.loading.set(repo, loading);
|
|
10112
|
+
}
|
|
10113
|
+
return loading;
|
|
10114
|
+
}
|
|
10115
|
+
/** Read the window from GitHub now, keep it in memory and store it. One read at a time per repository. */
|
|
10116
|
+
refresh(repo) {
|
|
10117
|
+
let refreshing = this.refreshing.get(repo);
|
|
10118
|
+
if (!refreshing) {
|
|
10119
|
+
refreshing = this.read(repo).finally(() => this.refreshing.delete(repo));
|
|
10120
|
+
this.refreshing.set(repo, refreshing);
|
|
10121
|
+
}
|
|
10122
|
+
return refreshing;
|
|
10123
|
+
}
|
|
10124
|
+
/**
|
|
10125
|
+
* Keep every named repository's snapshot within `everyMinutes`: a tick a
|
|
10126
|
+
* minute (unref'd — it never holds the process open) refreshes the ones
|
|
10127
|
+
* missing or older than the interval, one repository at a time, and runs
|
|
10128
|
+
* once at start so a stale snapshot after a restart is refreshed at once
|
|
10129
|
+
* and a young one is left alone. A failing refresh is a warning; the next
|
|
10130
|
+
* tick tries again. `tick()` is the pass itself, for tests.
|
|
10131
|
+
*/
|
|
10132
|
+
startRefreshLoop(opts) {
|
|
10133
|
+
let running;
|
|
10134
|
+
const pass = async () => {
|
|
10135
|
+
for (const repo of opts.repos) {
|
|
10136
|
+
try {
|
|
10137
|
+
const current = await this.current(repo);
|
|
10138
|
+
if (current && snapshotAgeMinutes(current.snapshotAt, this.now().getTime()) < opts.everyMinutes) continue;
|
|
10139
|
+
await this.refresh(repo);
|
|
10140
|
+
} catch (err2) {
|
|
10141
|
+
this.warn(`delivery snapshot for ${repo} not refreshed: ${message(err2)}`);
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10144
|
+
};
|
|
10145
|
+
const tick = () => running ??= pass().finally(() => {
|
|
10146
|
+
running = void 0;
|
|
10147
|
+
});
|
|
10148
|
+
const start2 = opts.setInterval ?? ((fn, ms) => {
|
|
10149
|
+
const t = setInterval(fn, ms);
|
|
10150
|
+
t.unref?.();
|
|
10151
|
+
return t;
|
|
10152
|
+
});
|
|
10153
|
+
const stop = opts.clearInterval ?? ((t) => clearInterval(t));
|
|
10154
|
+
const timer = start2(() => void tick(), SNAPSHOT_TICK_MS);
|
|
10155
|
+
timer.unref?.();
|
|
10156
|
+
void tick();
|
|
10157
|
+
return { stop: () => stop(timer), tick };
|
|
10158
|
+
}
|
|
10159
|
+
window() {
|
|
10160
|
+
return resolveDeliveryRange({ weeks: this.weeks }, this.now());
|
|
10161
|
+
}
|
|
10162
|
+
async live(repo, range) {
|
|
10163
|
+
const startedAt = this.now();
|
|
10164
|
+
const fetched = await this.inner.fetchPullRequests(repo, range);
|
|
10165
|
+
return { prs: fetched.prs, truncated: fetched.truncated, fetchedAt: startedAt.toISOString() };
|
|
10166
|
+
}
|
|
10167
|
+
async read(repo) {
|
|
10168
|
+
const startedAt = this.now();
|
|
10169
|
+
const range = resolveDeliveryRange({ weeks: this.weeks }, startedAt);
|
|
10170
|
+
const fetched = await this.inner.fetchPullRequests(repo, range);
|
|
10171
|
+
const snapshot = {
|
|
10172
|
+
repo,
|
|
10173
|
+
snapshotAt: startedAt.toISOString(),
|
|
10174
|
+
range,
|
|
10175
|
+
prs: fetched.prs,
|
|
10176
|
+
truncated: fetched.truncated,
|
|
10177
|
+
completeFrom: fetched.completeFrom ?? `${range.since}T00:00:00Z`
|
|
10178
|
+
};
|
|
10179
|
+
this.memory.set(repo, snapshot);
|
|
10180
|
+
try {
|
|
10181
|
+
await this.store.put(snapshot);
|
|
10182
|
+
} catch (err2) {
|
|
10183
|
+
this.warn(`delivery snapshot for ${repo} not stored: ${message(err2)}`);
|
|
10184
|
+
}
|
|
10185
|
+
return snapshot;
|
|
9775
10186
|
}
|
|
9776
10187
|
};
|
|
9777
10188
|
}
|
|
9778
10189
|
});
|
|
9779
10190
|
|
|
10191
|
+
// ../../src/core/workerError.ts
|
|
10192
|
+
async function errorSuffix(res) {
|
|
10193
|
+
const text = await res.text().catch(() => "");
|
|
10194
|
+
try {
|
|
10195
|
+
const parsed = JSON.parse(text);
|
|
10196
|
+
return parsed?.error ? `: ${String(parsed.error)}` : "";
|
|
10197
|
+
} catch {
|
|
10198
|
+
return "";
|
|
10199
|
+
}
|
|
10200
|
+
}
|
|
10201
|
+
var init_workerError = __esm({
|
|
10202
|
+
"../../src/core/workerError.ts"() {
|
|
10203
|
+
"use strict";
|
|
10204
|
+
}
|
|
10205
|
+
});
|
|
10206
|
+
|
|
10207
|
+
// ../../src/core/deliverySnapshotStore.ts
|
|
10208
|
+
function isPullRequestFacts(v) {
|
|
10209
|
+
if (typeof v !== "object" || v === null) return false;
|
|
10210
|
+
const p = v;
|
|
10211
|
+
return typeof p.number === "number" && Number.isFinite(p.number) && typeof p.title === "string" && typeof p.author === "string" && isInstant(p.createdAt) && isInstant(p.mergedAt) && (p.firstHeadSha === void 0 || typeof p.firstHeadSha === "string") && Array.isArray(p.ci) && Array.isArray(p.reviews) && Array.isArray(p.pushes) && (p.issue === void 0 || typeof p.issue === "object" && p.issue !== null);
|
|
10212
|
+
}
|
|
10213
|
+
function isDeliverySnapshot(v) {
|
|
10214
|
+
if (typeof v !== "object" || v === null) return false;
|
|
10215
|
+
const s = v;
|
|
10216
|
+
if (typeof s.repo !== "string" || !REPO_SLUG.test(s.repo)) return false;
|
|
10217
|
+
if (!isInstant(s.snapshotAt) || !isInstant(s.completeFrom)) return false;
|
|
10218
|
+
if (typeof s.truncated !== "boolean") return false;
|
|
10219
|
+
const range = s.range;
|
|
10220
|
+
if (typeof range !== "object" || range === null || typeof range.since !== "string" || !ISO_DAY2.test(range.since) || typeof range.until !== "string" || !ISO_DAY2.test(range.until) || typeof range.weeks !== "number" || !Number.isFinite(range.weeks))
|
|
10221
|
+
return false;
|
|
10222
|
+
return Array.isArray(s.prs) && s.prs.every(isPullRequestFacts);
|
|
10223
|
+
}
|
|
10224
|
+
function buildDeliverySnapshotStore(config, secrets, warn) {
|
|
10225
|
+
const worker = [config.runtimeOverrides, config.runHistory, config.schedules, config.memory].find(
|
|
10226
|
+
(block) => block?.worker?.baseUrl
|
|
10227
|
+
)?.worker;
|
|
10228
|
+
if (!worker) {
|
|
10229
|
+
warn(
|
|
10230
|
+
"delivery snapshots are kept in memory \u2014 a restart loses them and the first request after one reads GitHub live. Name the state Worker (runHistory.worker, runtimeOverrides.worker, schedules.worker or memory.worker) to keep them on it."
|
|
10231
|
+
);
|
|
10232
|
+
return new InMemoryDeliverySnapshotStore();
|
|
10233
|
+
}
|
|
10234
|
+
const tokenEnv = worker.tokenEnv ?? DEFAULT_TOKEN_ENV;
|
|
10235
|
+
const token = secrets.named(tokenEnv);
|
|
10236
|
+
if (!token) {
|
|
10237
|
+
warn(
|
|
10238
|
+
`the state Worker is configured but ${tokenEnv} is unset \u2014 delivery snapshots are kept in memory and a restart loses them. Set ${tokenEnv} to the state Worker's bearer.`
|
|
10239
|
+
);
|
|
10240
|
+
return new InMemoryDeliverySnapshotStore();
|
|
10241
|
+
}
|
|
10242
|
+
return new WorkerDeliverySnapshotStore({ baseUrl: worker.baseUrl, token: token.reveal() });
|
|
10243
|
+
}
|
|
10244
|
+
var ISO_DAY2, isInstant, InMemoryDeliverySnapshotStore, SNAPSHOT_WORKER_TIMEOUT_MS, WorkerDeliverySnapshotStore, DEFAULT_TOKEN_ENV;
|
|
10245
|
+
var init_deliverySnapshotStore = __esm({
|
|
10246
|
+
"../../src/core/deliverySnapshotStore.ts"() {
|
|
10247
|
+
"use strict";
|
|
10248
|
+
init_delivery();
|
|
10249
|
+
init_workerError();
|
|
10250
|
+
ISO_DAY2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
10251
|
+
isInstant = (v) => typeof v === "string" && Number.isFinite(Date.parse(v));
|
|
10252
|
+
InMemoryDeliverySnapshotStore = class {
|
|
10253
|
+
byRepo = /* @__PURE__ */ new Map();
|
|
10254
|
+
async get(repo) {
|
|
10255
|
+
const s = this.byRepo.get(repo);
|
|
10256
|
+
return s ? structuredClone(s) : void 0;
|
|
10257
|
+
}
|
|
10258
|
+
async put(snapshot) {
|
|
10259
|
+
this.byRepo.set(snapshot.repo, structuredClone(snapshot));
|
|
10260
|
+
}
|
|
10261
|
+
};
|
|
10262
|
+
SNAPSHOT_WORKER_TIMEOUT_MS = 3e4;
|
|
10263
|
+
WorkerDeliverySnapshotStore = class {
|
|
10264
|
+
constructor(opts) {
|
|
10265
|
+
this.opts = opts;
|
|
10266
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
10267
|
+
this.fetchImpl = opts.fetch ?? fetch;
|
|
10268
|
+
}
|
|
10269
|
+
opts;
|
|
10270
|
+
baseUrl;
|
|
10271
|
+
fetchImpl;
|
|
10272
|
+
async get(repo) {
|
|
10273
|
+
const res = await this.post("/delivery/get", { repo });
|
|
10274
|
+
if (!res.ok) throw new Error(`state Worker /delivery/get HTTP ${res.status}${await errorSuffix(res)}`);
|
|
10275
|
+
const data = await res.json().catch(() => ({}));
|
|
10276
|
+
if (data.snapshot === null || data.snapshot === void 0) return void 0;
|
|
10277
|
+
if (!isDeliverySnapshot(data.snapshot))
|
|
10278
|
+
throw new Error(`state Worker /delivery/get: the answer for ${repo} is not a delivery snapshot`);
|
|
10279
|
+
return data.snapshot;
|
|
10280
|
+
}
|
|
10281
|
+
async put(snapshot) {
|
|
10282
|
+
const res = await this.post("/delivery/put", { snapshot });
|
|
10283
|
+
if (!res.ok) throw new Error(`state Worker /delivery/put HTTP ${res.status}${await errorSuffix(res)}`);
|
|
10284
|
+
}
|
|
10285
|
+
post(path, body) {
|
|
10286
|
+
return this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
10287
|
+
method: "POST",
|
|
10288
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${this.opts.token}` },
|
|
10289
|
+
body: JSON.stringify(body),
|
|
10290
|
+
signal: AbortSignal.timeout(SNAPSHOT_WORKER_TIMEOUT_MS)
|
|
10291
|
+
});
|
|
10292
|
+
}
|
|
10293
|
+
};
|
|
10294
|
+
DEFAULT_TOKEN_ENV = "MEMORY_TOKEN";
|
|
10295
|
+
}
|
|
10296
|
+
});
|
|
10297
|
+
|
|
9780
10298
|
// ../../src/core/runDuration.ts
|
|
9781
10299
|
function runDurationMs(stamps, now) {
|
|
9782
10300
|
const end = stamps.finishedAt ?? now;
|
|
@@ -10659,8 +11177,8 @@ function bindCommands(registry, deps) {
|
|
|
10659
11177
|
settle: (id, value, caller) => registry.settle(id, value, caller, deps)
|
|
10660
11178
|
};
|
|
10661
11179
|
}
|
|
10662
|
-
function fail(error,
|
|
10663
|
-
return { ok: false, error, status: ERROR_STATUS[error], message, decidedBy };
|
|
11180
|
+
function fail(error, message2, decidedBy = "registry") {
|
|
11181
|
+
return { ok: false, error, status: ERROR_STATUS[error], message: message2, decidedBy };
|
|
10664
11182
|
}
|
|
10665
11183
|
function rawInput(input) {
|
|
10666
11184
|
const args = typeof input === "object" && input !== null && Array.isArray(input.args) ? input.args : [];
|
|
@@ -10779,8 +11297,8 @@ var init_commandRegistry = __esm({
|
|
|
10779
11297
|
CAMEL_KEY = /^[a-z][A-Za-z0-9]*$/;
|
|
10780
11298
|
flag = z4.union([z4.boolean(), z4.enum(["true", "false"]).transform((v) => v === "true")]);
|
|
10781
11299
|
CommandError = class extends Error {
|
|
10782
|
-
constructor(code,
|
|
10783
|
-
super(
|
|
11300
|
+
constructor(code, message2) {
|
|
11301
|
+
super(message2);
|
|
10784
11302
|
this.code = code;
|
|
10785
11303
|
this.name = "CommandError";
|
|
10786
11304
|
}
|
|
@@ -10934,12 +11452,13 @@ function summarizeScope(s) {
|
|
|
10934
11452
|
function registerConfigCommands(registry) {
|
|
10935
11453
|
for (const cmd of configCommands) registry.register(cmd);
|
|
10936
11454
|
}
|
|
10937
|
-
var defineCommand2, scopeArg, channelOption, effort, effortLevels, modelRef, who, configShow, configSet, configClear, quote, configInstructions, configCommands;
|
|
11455
|
+
var defineCommand2, scopeArg, channelOption, effort, effortLevels, modelRef, boundaryOption, who, configShow, configSet, configClear, quote, configInstructions, configCommands;
|
|
10938
11456
|
var init_config3 = __esm({
|
|
10939
11457
|
"../../src/core/commands/config.ts"() {
|
|
10940
11458
|
"use strict";
|
|
10941
11459
|
init_config();
|
|
10942
11460
|
init_validate();
|
|
11461
|
+
init_registry();
|
|
10943
11462
|
init_effort();
|
|
10944
11463
|
init_authorize();
|
|
10945
11464
|
init_commandRegistry();
|
|
@@ -10953,6 +11472,11 @@ var init_config3 = __esm({
|
|
|
10953
11472
|
effort = z5.enum(EFFORT_LEVELS);
|
|
10954
11473
|
effortLevels = `<${EFFORT_LEVELS.join("|")}>`;
|
|
10955
11474
|
modelRef = z5.string().min(1);
|
|
11475
|
+
boundaryOption = z5.object({
|
|
11476
|
+
maxMinutes: z5.coerce.number().int().min(MIN_BOUNDARY_MINUTES).optional().describe(`cap the wall-clock budget of every run in this scope (minutes, >= ${MIN_BOUNDARY_MINUTES})`),
|
|
11477
|
+
maxIdentity: z5.enum(IDENTITIES).optional().describe(`cap the identity runs may act as <${IDENTITIES.join("|")}> \u2014 a preset above it is refused`),
|
|
11478
|
+
machines: z5.string().optional().describe(`the machine classes runs may execute on, comma-separated from ${MACHINE_CLASSES.join(", ")}`)
|
|
11479
|
+
}).optional();
|
|
10956
11480
|
who = (scope) => scope === "channel" ? "channel" : "your";
|
|
10957
11481
|
configShow = defineCommand2({
|
|
10958
11482
|
id: "config.show",
|
|
@@ -10979,11 +11503,12 @@ var init_config3 = __esm({
|
|
|
10979
11503
|
models: z5.record(z5.string(), modelRef).optional().describe("per-agent model: --models.<agent> provider/model"),
|
|
10980
11504
|
effort: effort.optional().describe(`force a model effort ${effortLevels}`),
|
|
10981
11505
|
efforts: z5.record(z5.string(), effort).optional().describe(`per-agent effort: --efforts.<agent> ${effortLevels}`),
|
|
11506
|
+
boundary: boundaryOption,
|
|
10982
11507
|
channel: channelOption
|
|
10983
11508
|
}),
|
|
10984
11509
|
action: "config:write",
|
|
10985
11510
|
effect: "write",
|
|
10986
|
-
describe: "Set the agent, model, or
|
|
11511
|
+
describe: "Set the agent, model, effort or boundary for a channel (gated) or for yourself; per-agent forms take --models.<agent> / --efforts.<agent>, the boundary's axes --boundary.<axis> (a boundary caps every run in the scope and never grants).",
|
|
10987
11512
|
render: (output) => {
|
|
10988
11513
|
const o = output;
|
|
10989
11514
|
return `Updated ${who(o.scope)} scope. Now: ${JSON.stringify(o.effective)}`;
|
|
@@ -11012,10 +11537,26 @@ var init_config3 = __esm({
|
|
|
11012
11537
|
if (options.models) patch.models = options.models;
|
|
11013
11538
|
if (options.effort !== void 0) patch.effort = options.effort;
|
|
11014
11539
|
if (options.efforts) patch.efforts = options.efforts;
|
|
11540
|
+
if (options.boundary) {
|
|
11541
|
+
const { machines, ...axes } = options.boundary;
|
|
11542
|
+
const boundary = { ...axes };
|
|
11543
|
+
if (machines !== void 0) {
|
|
11544
|
+
const classes = machines.split(",").map((m) => m.trim());
|
|
11545
|
+
if (classes.length === 0 || classes.some((m) => !MACHINE_CLASSES.includes(m)))
|
|
11546
|
+
throw new CommandError(
|
|
11547
|
+
"invalid_input",
|
|
11548
|
+
`boundary.machines: expected a comma-separated list of ${MACHINE_CLASSES.join(", ")}`
|
|
11549
|
+
);
|
|
11550
|
+
boundary.machines = classes;
|
|
11551
|
+
}
|
|
11552
|
+
const problem = boundaryProblem("boundary", boundary);
|
|
11553
|
+
if (problem) throw new CommandError("invalid_input", problem);
|
|
11554
|
+
if (Object.keys(boundary).length > 0) patch.boundary = boundary;
|
|
11555
|
+
}
|
|
11015
11556
|
if (Object.keys(patch).length === 0)
|
|
11016
11557
|
throw new CommandError(
|
|
11017
11558
|
"invalid_input",
|
|
11018
|
-
"nothing to set: pass --agent, --model, --models.<agent>, --effort, or --
|
|
11559
|
+
"nothing to set: pass --agent, --model, --models.<agent>, --effort, --efforts.<agent>, or --boundary.<maxMinutes|maxIdentity|machines>"
|
|
11019
11560
|
);
|
|
11020
11561
|
let effective;
|
|
11021
11562
|
if (args.scope === "channel") {
|
|
@@ -12225,6 +12766,17 @@ var init_runFriction = __esm({
|
|
|
12225
12766
|
});
|
|
12226
12767
|
|
|
12227
12768
|
// ../../src/core/runRecord.ts
|
|
12769
|
+
function isRunProfileRecord(v) {
|
|
12770
|
+
if (typeof v !== "object" || v === null) return false;
|
|
12771
|
+
const p = v;
|
|
12772
|
+
if (typeof p.preset !== "string") return false;
|
|
12773
|
+
if (typeof p.machine !== "string" || !Object.hasOwn(MACHINE_CLASSES_IN_RECORD, p.machine)) return false;
|
|
12774
|
+
if (typeof p.identity !== "string" || !Object.hasOwn(IDENTITIES_IN_RECORD, p.identity)) return false;
|
|
12775
|
+
if (!isFiniteNumber(p.minutes) || p.minutes <= 0) return false;
|
|
12776
|
+
if (p.boundedBy !== void 0 && (typeof p.boundedBy !== "string" || !Object.hasOwn(BOUNDARY_SCOPES_IN_RECORD, p.boundedBy)))
|
|
12777
|
+
return false;
|
|
12778
|
+
return true;
|
|
12779
|
+
}
|
|
12228
12780
|
function storedEventSeqs(events) {
|
|
12229
12781
|
let prev = 0;
|
|
12230
12782
|
for (const e of events) {
|
|
@@ -12350,6 +12902,7 @@ function isRunRecord(v) {
|
|
|
12350
12902
|
return false;
|
|
12351
12903
|
if (!isOptionalString(r.activity) || !isOptionalString(r.sourceUrl) || !isOptionalString(r.userName)) return false;
|
|
12352
12904
|
if (r.handoff !== void 0 && !isHandoffShape(r.handoff)) return false;
|
|
12905
|
+
if (r.profile !== void 0 && !isRunProfileRecord(r.profile)) return false;
|
|
12353
12906
|
if (typeof r.channelId !== "string" || typeof r.userId !== "string" || typeof r.threadKey !== "string") return false;
|
|
12354
12907
|
if (r.channelVisibility !== void 0 && !CHANNEL_VISIBILITIES2.includes(r.channelVisibility))
|
|
12355
12908
|
return false;
|
|
@@ -12476,7 +13029,7 @@ function dropSpanPairsFromTheMiddle(events, eventBudget) {
|
|
|
12476
13029
|
}
|
|
12477
13030
|
return events.filter((_, k) => !dropped.has(k));
|
|
12478
13031
|
}
|
|
12479
|
-
var RUN_STATUSES, RUN_ID_PATTERN, RUN_LIST_DEFAULT_LIMIT, RUN_LIST_MAX_LIMIT, RUN_EVENTS_DEFAULT_PAGE, RUN_EVENTS_MAX_PAGE, CHANNEL_VISIBILITIES2, KIB, MIB, GIB2, DEFAULT_RETENTION_POLICY, RETENTION_BOUNDS, MAX_RECORD_BYTES, MAX_EVENT_BYTES, ELLIPSIS, encoder;
|
|
13032
|
+
var RUN_STATUSES, RUN_ID_PATTERN, MACHINE_CLASSES_IN_RECORD, IDENTITIES_IN_RECORD, BOUNDARY_SCOPES_IN_RECORD, RUN_LIST_DEFAULT_LIMIT, RUN_LIST_MAX_LIMIT, RUN_EVENTS_DEFAULT_PAGE, RUN_EVENTS_MAX_PAGE, CHANNEL_VISIBILITIES2, KIB, MIB, GIB2, DEFAULT_RETENTION_POLICY, RETENTION_BOUNDS, MAX_RECORD_BYTES, MAX_EVENT_BYTES, ELLIPSIS, encoder;
|
|
12480
13033
|
var init_runRecord = __esm({
|
|
12481
13034
|
"../../src/core/runRecord.ts"() {
|
|
12482
13035
|
"use strict";
|
|
@@ -12485,6 +13038,19 @@ var init_runRecord = __esm({
|
|
|
12485
13038
|
init_runFriction();
|
|
12486
13039
|
RUN_STATUSES = ["completed", "stopped_soft", "stopped_hard", "failed", "interrupted"];
|
|
12487
13040
|
RUN_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
13041
|
+
MACHINE_CLASSES_IN_RECORD = {
|
|
13042
|
+
none: true,
|
|
13043
|
+
blank: true,
|
|
13044
|
+
"repo-cold": true,
|
|
13045
|
+
"repo-resident": true
|
|
13046
|
+
};
|
|
13047
|
+
IDENTITIES_IN_RECORD = { none: true, read: true, write: true };
|
|
13048
|
+
BOUNDARY_SCOPES_IN_RECORD = {
|
|
13049
|
+
defaults: true,
|
|
13050
|
+
channel: true,
|
|
13051
|
+
user: true,
|
|
13052
|
+
directive: true
|
|
13053
|
+
};
|
|
12488
13054
|
RUN_LIST_DEFAULT_LIMIT = 50;
|
|
12489
13055
|
RUN_LIST_MAX_LIMIT = 200;
|
|
12490
13056
|
RUN_EVENTS_DEFAULT_PAGE = 1e3;
|
|
@@ -12515,7 +13081,7 @@ import { z as z7 } from "zod";
|
|
|
12515
13081
|
function registerDeliveryCommands(registry) {
|
|
12516
13082
|
for (const cmd of deliveryCommands) registry.register(cmd);
|
|
12517
13083
|
}
|
|
12518
|
-
var defineCommand4, REPO_SLUG2,
|
|
13084
|
+
var defineCommand4, REPO_SLUG2, ISO_DAY3, asJson, deliveryReport, deliveryCommands;
|
|
12519
13085
|
var init_delivery2 = __esm({
|
|
12520
13086
|
"../../src/core/commands/delivery.ts"() {
|
|
12521
13087
|
"use strict";
|
|
@@ -12525,21 +13091,22 @@ var init_delivery2 = __esm({
|
|
|
12525
13091
|
init_runRecord();
|
|
12526
13092
|
defineCommand4 = commandDefiner();
|
|
12527
13093
|
REPO_SLUG2 = /^(?!\.+\/)[\w.-]+\/(?!\.+$)[\w.-]+$/;
|
|
12528
|
-
|
|
13094
|
+
ISO_DAY3 = /^\d{4}-\d{2}-\d{2}$/;
|
|
12529
13095
|
asJson = (v) => v;
|
|
12530
13096
|
deliveryReport = defineCommand4({
|
|
12531
13097
|
id: "delivery.report",
|
|
12532
13098
|
options: z7.object({
|
|
12533
13099
|
repo: z7.string().regex(REPO_SLUG2).optional().describe("the repository (`owner/name`); default: the first under `delivery.repos`"),
|
|
12534
|
-
since: z7.string().regex(
|
|
13100
|
+
since: z7.string().regex(ISO_DAY3).optional().describe("the first day of the range (`YYYY-MM-DD`, UTC); the range ends today"),
|
|
12535
13101
|
weeks: z7.coerce.number().int().min(1).max(MAX_WEEKS).optional().describe(
|
|
12536
13102
|
`Monday-start weeks back from this one (default 4, at most ${MAX_WEEKS}); --since, when given, decides instead`
|
|
12537
|
-
)
|
|
13103
|
+
),
|
|
13104
|
+
fresh: flag.optional().describe("read GitHub now instead of the repository's snapshot, and refresh the snapshot")
|
|
12538
13105
|
}),
|
|
12539
13106
|
action: "delivery:read",
|
|
12540
13107
|
effect: "read",
|
|
12541
13108
|
enabledWhen: (caps) => caps.github,
|
|
12542
|
-
describe: "Delivery indicators per week and per unit \u2014 issue-to-merge time, first-pass CI, review rounds, findings and the share resolved with no human edit \u2014
|
|
13109
|
+
describe: "Delivery indicators per week and per unit \u2014 issue-to-merge time, first-pass CI, review rounds, findings and the share resolved with no human edit \u2014 from the repository's snapshot of GitHub's facts (--fresh reads GitHub now) and the run history; nothing written.",
|
|
12543
13110
|
render: (output) => renderDeliveryReport(output),
|
|
12544
13111
|
handler: async ({ options, caller, deps }) => {
|
|
12545
13112
|
const service = await deps.delivery.service();
|
|
@@ -12559,11 +13126,13 @@ var init_delivery2 = __esm({
|
|
|
12559
13126
|
return runFactsOf(page2.runs, repo);
|
|
12560
13127
|
};
|
|
12561
13128
|
try {
|
|
12562
|
-
return asJson(
|
|
13129
|
+
return asJson(
|
|
13130
|
+
await service.report(repo, { since: options.since, weeks: options.weeks, fresh: options.fresh, runs })
|
|
13131
|
+
);
|
|
12563
13132
|
} catch (err2) {
|
|
12564
|
-
const
|
|
12565
|
-
if (
|
|
12566
|
-
throw new CommandError("unavailable", `delivery indicators unavailable: ${
|
|
13133
|
+
const message2 = err2 instanceof Error ? err2.message : String(err2);
|
|
13134
|
+
if (message2 === DELIVERY_OFF_MESSAGE) throw new CommandError("unavailable", message2);
|
|
13135
|
+
throw new CommandError("unavailable", `delivery indicators unavailable: ${message2}`);
|
|
12567
13136
|
}
|
|
12568
13137
|
}
|
|
12569
13138
|
});
|
|
@@ -12693,7 +13262,7 @@ var init_deploy = __esm({
|
|
|
12693
13262
|
init_operatorRoot();
|
|
12694
13263
|
init_restart();
|
|
12695
13264
|
init_run();
|
|
12696
|
-
|
|
13265
|
+
init_profile2();
|
|
12697
13266
|
init_wranglerTemplate();
|
|
12698
13267
|
init_secrets();
|
|
12699
13268
|
init_commandRegistry();
|
|
@@ -14288,7 +14857,7 @@ var init_help = __esm({
|
|
|
14288
14857
|
init_commandRegistry();
|
|
14289
14858
|
init_commandSurface();
|
|
14290
14859
|
defineCommand8 = commandDefiner();
|
|
14291
|
-
DIRECTIVES_HELP = "`agent:review model:anthropic/claude-opus-5 effort:low look at PR 42` (effort: low | medium | high \u2014 lower = faster turns)";
|
|
14860
|
+
DIRECTIVES_HELP = "`agent:review model:anthropic/claude-opus-5 effort:low budget:20 look at PR 42` (effort: low | medium | high \u2014 lower = faster turns; budget: whole minutes, at least 2 \u2014 narrows this run's wall clock, never widens it)";
|
|
14292
14861
|
helpShow = defineCommand8({
|
|
14293
14862
|
id: "help.show",
|
|
14294
14863
|
action: "help:read",
|
|
@@ -14427,8 +14996,8 @@ var init_types2 = __esm({
|
|
|
14427
14996
|
"../../src/mcp/types.ts"() {
|
|
14428
14997
|
"use strict";
|
|
14429
14998
|
McpError = class extends Error {
|
|
14430
|
-
constructor(code,
|
|
14431
|
-
super(
|
|
14999
|
+
constructor(code, message2) {
|
|
15000
|
+
super(message2);
|
|
14432
15001
|
this.code = code;
|
|
14433
15002
|
this.name = "McpError";
|
|
14434
15003
|
}
|
|
@@ -14611,12 +15180,12 @@ var init_client = __esm({
|
|
|
14611
15180
|
const res = await this.post({ jsonrpc: "2.0", id, method, params }, signal, o);
|
|
14612
15181
|
const session = res.headers.get("mcp-session-id");
|
|
14613
15182
|
if (session && o?.initializing) this.sessionId = session;
|
|
14614
|
-
const
|
|
14615
|
-
if (
|
|
14616
|
-
const code = typeof
|
|
14617
|
-
throw new McpError(code, `${method}: ${String(
|
|
15183
|
+
const message2 = await this.readResponse(res, id, signal);
|
|
15184
|
+
if (message2.error) {
|
|
15185
|
+
const code = typeof message2.error.code === "number" ? message2.error.code : "protocol";
|
|
15186
|
+
throw new McpError(code, `${method}: ${String(message2.error.message ?? "error")}`);
|
|
14618
15187
|
}
|
|
14619
|
-
return
|
|
15188
|
+
return message2.result;
|
|
14620
15189
|
}
|
|
14621
15190
|
async post(body, signal, o) {
|
|
14622
15191
|
const headers = {
|
|
@@ -15023,8 +15592,8 @@ var init_oauth = __esm({
|
|
|
15023
15592
|
init_web();
|
|
15024
15593
|
init_client();
|
|
15025
15594
|
OAuthError = class extends Error {
|
|
15026
|
-
constructor(
|
|
15027
|
-
super(
|
|
15595
|
+
constructor(message2) {
|
|
15596
|
+
super(message2);
|
|
15028
15597
|
this.name = "OAuthError";
|
|
15029
15598
|
}
|
|
15030
15599
|
};
|
|
@@ -15167,9 +15736,9 @@ function bridgeMcpTools(server, client, tools, opts) {
|
|
|
15167
15736
|
try {
|
|
15168
15737
|
result = await client.callTool(t.name, input ?? {}, { signal: ctx.signal });
|
|
15169
15738
|
} catch (err2) {
|
|
15170
|
-
const
|
|
15739
|
+
const message2 = err2 instanceof McpError ? err2.message : err2 instanceof Error ? err2.message : String(err2);
|
|
15171
15740
|
const failed = classifyError(
|
|
15172
|
-
new Error(`MCP ${server.name}/${t.name} failed: ${
|
|
15741
|
+
new Error(`MCP ${server.name}/${t.name} failed: ${message2}`, { cause: err2 }),
|
|
15173
15742
|
mcpClass(err2)
|
|
15174
15743
|
);
|
|
15175
15744
|
span?.fail(failed);
|
|
@@ -15376,8 +15945,8 @@ var init_service = __esm({
|
|
|
15376
15945
|
init_source();
|
|
15377
15946
|
MCP_OFF_MESSAGE = "External MCP servers are not enabled in this deployment (no `mcp` block in config.yaml).";
|
|
15378
15947
|
McpServiceError = class extends Error {
|
|
15379
|
-
constructor(code,
|
|
15380
|
-
super(
|
|
15948
|
+
constructor(code, message2) {
|
|
15949
|
+
super(message2);
|
|
15381
15950
|
this.code = code;
|
|
15382
15951
|
this.name = "McpServiceError";
|
|
15383
15952
|
}
|
|
@@ -15985,12 +16554,12 @@ var init_service = __esm({
|
|
|
15985
16554
|
const tools = await this.opts.factory(spec).listTools();
|
|
15986
16555
|
return { kind: "ok", toolCount: tools.length };
|
|
15987
16556
|
} catch (err2) {
|
|
15988
|
-
const
|
|
15989
|
-
if (/HTTP 40[13]\b/.test(
|
|
15990
|
-
return { kind: "rejected", error: `the server rejected the token (${
|
|
16557
|
+
const message2 = err2 instanceof Error ? err2.message : String(err2);
|
|
16558
|
+
if (/HTTP 40[13]\b/.test(message2))
|
|
16559
|
+
return { kind: "rejected", error: `the server rejected the token (${message2})` };
|
|
15991
16560
|
return {
|
|
15992
16561
|
kind: "error",
|
|
15993
|
-
error: `stored, but the server could not be reached to verify it: ${
|
|
16562
|
+
error: `stored, but the server could not be reached to verify it: ${message2.slice(0, 200)}`
|
|
15994
16563
|
};
|
|
15995
16564
|
}
|
|
15996
16565
|
}
|
|
@@ -17880,8 +18449,8 @@ var init_githubApi = __esm({
|
|
|
17880
18449
|
MAX_FILE_CHARS = 2e5;
|
|
17881
18450
|
COMPARE_DIFF_MAX_CHARS = 12e5;
|
|
17882
18451
|
GithubApiError = class extends Error {
|
|
17883
|
-
constructor(status3,
|
|
17884
|
-
super(
|
|
18452
|
+
constructor(status3, message2) {
|
|
18453
|
+
super(message2);
|
|
17885
18454
|
this.status = status3;
|
|
17886
18455
|
this.name = "GithubApiError";
|
|
17887
18456
|
}
|
|
@@ -18203,8 +18772,8 @@ var init_reviewAbridge = __esm({
|
|
|
18203
18772
|
init_clock();
|
|
18204
18773
|
isReadingDiff = (e) => e.type === "review_artifact" && e.artifact === "reading_diff";
|
|
18205
18774
|
AbridgeRefusal = class extends Error {
|
|
18206
|
-
constructor(code,
|
|
18207
|
-
super(
|
|
18775
|
+
constructor(code, message2) {
|
|
18776
|
+
super(message2);
|
|
18208
18777
|
this.code = code;
|
|
18209
18778
|
this.name = "AbridgeRefusal";
|
|
18210
18779
|
}
|
|
@@ -19249,7 +19818,7 @@ var init_plan2 = __esm({
|
|
|
19249
19818
|
init_config();
|
|
19250
19819
|
init_capabilities();
|
|
19251
19820
|
init_secrets2();
|
|
19252
|
-
|
|
19821
|
+
init_profile2();
|
|
19253
19822
|
ENV_PATH = ".env";
|
|
19254
19823
|
CONFIG_PATH = "config/config.yaml";
|
|
19255
19824
|
PROFILE_PATH2 = "deploy/profile.json";
|
|
@@ -19262,7 +19831,7 @@ var init_plan2 = __esm({
|
|
|
19262
19831
|
];
|
|
19263
19832
|
OPENAI_PROVIDER = "openai";
|
|
19264
19833
|
OPENAI_KEY_ENV = "OPENAI_API_KEY";
|
|
19265
|
-
DEFAULT_MODEL_AGENTS = ["general", "coding", "review"];
|
|
19834
|
+
DEFAULT_MODEL_AGENTS = ["general", "coding", "review", "explore"];
|
|
19266
19835
|
ENV_LINE = /^(#\s*)?([A-Z][A-Z0-9_]*)=(.*)$/;
|
|
19267
19836
|
}
|
|
19268
19837
|
});
|
|
@@ -19753,7 +20322,12 @@ function buildCoreCommands(config, store, wiring) {
|
|
|
19753
20322
|
const delivery = once(async () => {
|
|
19754
20323
|
if (wiring.delivery) return wiring.delivery();
|
|
19755
20324
|
if (wiring.capabilities && !wiring.capabilities.github) return new NullDeliveryService();
|
|
19756
|
-
|
|
20325
|
+
const config2 = (await cfg()).config;
|
|
20326
|
+
const warn = (m) => wiring.warn(`[delivery] ${m}`);
|
|
20327
|
+
return deliveryFromConfig(parseDeliveryConfig(config2.delivery), {
|
|
20328
|
+
snapshots: buildDeliverySnapshotStore(config2, wiring.secrets, warn),
|
|
20329
|
+
warn
|
|
20330
|
+
}).service;
|
|
19757
20331
|
});
|
|
19758
20332
|
const deps = {
|
|
19759
20333
|
help: {
|
|
@@ -19818,13 +20392,19 @@ function buildCoreCommands(config, store, wiring) {
|
|
|
19818
20392
|
};
|
|
19819
20393
|
return bindCommands(registry, deps);
|
|
19820
20394
|
}
|
|
19821
|
-
function
|
|
19822
|
-
|
|
20395
|
+
function deliveryFromConfig(cfg, opts = {}) {
|
|
20396
|
+
const source2 = new SnapshottingDeliverySource(
|
|
20397
|
+
new GithubDeliverySource(),
|
|
20398
|
+
opts.snapshots ?? new InMemoryDeliverySnapshotStore(),
|
|
20399
|
+
{ ...opts.warn ? { warn: opts.warn } : {} }
|
|
20400
|
+
);
|
|
20401
|
+
const service = createDeliveryService(cfg, source2, {
|
|
19823
20402
|
identities: async () => {
|
|
19824
20403
|
const identity2 = await resolveGithubIdentity();
|
|
19825
20404
|
return identity2 ? { reviewers: [identity2.login] } : {};
|
|
19826
20405
|
}
|
|
19827
20406
|
});
|
|
20407
|
+
return { service, source: source2 };
|
|
19828
20408
|
}
|
|
19829
20409
|
var init_commandCatalogue = __esm({
|
|
19830
20410
|
"../../src/core/commandCatalogue.ts"() {
|
|
@@ -19843,6 +20423,8 @@ var init_commandCatalogue = __esm({
|
|
|
19843
20423
|
init_githubDelivery();
|
|
19844
20424
|
init_resident();
|
|
19845
20425
|
init_delivery();
|
|
20426
|
+
init_deliverySnapshot();
|
|
20427
|
+
init_deliverySnapshotStore();
|
|
19846
20428
|
init_commandRegistry();
|
|
19847
20429
|
init_secrets2();
|
|
19848
20430
|
init_all();
|
|
@@ -20442,10 +21024,10 @@ function safePredicate(isResident, slug) {
|
|
|
20442
21024
|
return false;
|
|
20443
21025
|
}
|
|
20444
21026
|
}
|
|
20445
|
-
async function safeProbe(
|
|
20446
|
-
if (!
|
|
21027
|
+
async function safeProbe(probe, slug) {
|
|
21028
|
+
if (!probe) return true;
|
|
20447
21029
|
try {
|
|
20448
|
-
const answer = await
|
|
21030
|
+
const answer = await probe(slug);
|
|
20449
21031
|
return answer === true || answer === "unreachable" ? answer : false;
|
|
20450
21032
|
} catch {
|
|
20451
21033
|
return "unreachable";
|
|
@@ -20454,7 +21036,7 @@ async function safeProbe(isResident, slug) {
|
|
|
20454
21036
|
function repoFromThread(history, isResident) {
|
|
20455
21037
|
return threadSignals(history, isResident).repo;
|
|
20456
21038
|
}
|
|
20457
|
-
async function resolveRepoContext(msg, history = [],
|
|
21039
|
+
async function resolveRepoContext(msg, history = [], probe, residentSlugs) {
|
|
20458
21040
|
const s = extractSignals(msg.text);
|
|
20459
21041
|
const thread = threadSignals(history);
|
|
20460
21042
|
let rejected;
|
|
@@ -20463,7 +21045,7 @@ async function resolveRepoContext(msg, history = [], isResident, residentSlugs)
|
|
|
20463
21045
|
const vet = async (cand) => {
|
|
20464
21046
|
let p = vetted.get(cand);
|
|
20465
21047
|
if (!p) {
|
|
20466
|
-
p = safeProbe(
|
|
21048
|
+
p = safeProbe(probe, cand);
|
|
20467
21049
|
vetted.set(cand, p);
|
|
20468
21050
|
}
|
|
20469
21051
|
const answer = await p;
|
|
@@ -20479,7 +21061,7 @@ async function resolveRepoContext(msg, history = [], isResident, residentSlugs)
|
|
|
20479
21061
|
return slugsOnce;
|
|
20480
21062
|
};
|
|
20481
21063
|
const resolveAddressed = async (a) => {
|
|
20482
|
-
if (a.slug !== void 0) return
|
|
21064
|
+
if (a.slug !== void 0) return probe && await vet(a.slug) ? a.slug : void 0;
|
|
20483
21065
|
const matches = (await listSlugs() ?? []).filter((slug) => slug.split("/")[1] === a.name);
|
|
20484
21066
|
return matches.length === 1 ? matches[0] : void 0;
|
|
20485
21067
|
};
|
|
@@ -22301,6 +22883,21 @@ ${raw.trim()}`;
|
|
|
22301
22883
|
* and URL reading, so a plain mention can answer from the repos and act on
|
|
22302
22884
|
* issues without being re-sent to another agent. */
|
|
22303
22885
|
assistant: [webFetchTool, updateStatusTool, ...GITHUB_READ_TOOLS, ...GITHUB_ISSUE_WRITE_TOOLS],
|
|
22886
|
+
/** The explore agent (docs/reference/specs/agent-explore.md): a shell and
|
|
22887
|
+
* file reads in a cold sandbox, the web with search, the skills and the
|
|
22888
|
+
* GitHub reads — and nothing that writes: no `write_file`, no `submit_*`,
|
|
22889
|
+
* no issue writes. Read-only is a toolset-and-prompt contract; the wall is
|
|
22890
|
+
* the read-scoped credential its machine holds. */
|
|
22891
|
+
explore: [
|
|
22892
|
+
bashTool,
|
|
22893
|
+
readFileTool,
|
|
22894
|
+
updateStatusTool,
|
|
22895
|
+
webFetchTool,
|
|
22896
|
+
webSearchTool,
|
|
22897
|
+
listSkillsTool,
|
|
22898
|
+
useSkillTool,
|
|
22899
|
+
...GITHUB_READ_TOOLS
|
|
22900
|
+
],
|
|
22304
22901
|
none: []
|
|
22305
22902
|
};
|
|
22306
22903
|
}
|
|
@@ -22505,9 +23102,9 @@ async function runLoop(opts, now, note, emit, agentSpan) {
|
|
|
22505
23102
|
);
|
|
22506
23103
|
throw err2;
|
|
22507
23104
|
}
|
|
22508
|
-
const
|
|
23105
|
+
const message2 = err2 instanceof Error ? err2.message : String(err2);
|
|
22509
23106
|
if (err2 instanceof ExecCapacityError) {
|
|
22510
|
-
const text2 = `\u23F3 Sandbox fleet busy \u2014 ${
|
|
23107
|
+
const text2 = `\u23F3 Sandbox fleet busy \u2014 ${message2}. Retry the command in a minute or finish with what you have.`;
|
|
22511
23108
|
emit({ type: "tool_result", tool: tu.name, ok: false, callId: tu.id, ...prepareToolResult(text2), ...spanId });
|
|
22512
23109
|
note("fleet_busy", text2);
|
|
22513
23110
|
settle2(false, { infra: true });
|
|
@@ -22519,7 +23116,7 @@ async function runLoop(opts, now, note, emit, agentSpan) {
|
|
|
22519
23116
|
tool: tu.name,
|
|
22520
23117
|
ok: false,
|
|
22521
23118
|
callId: tu.id,
|
|
22522
|
-
...prepareToolResult(
|
|
23119
|
+
...prepareToolResult(message2),
|
|
22523
23120
|
...infra ? { infra: true } : {},
|
|
22524
23121
|
...spanId
|
|
22525
23122
|
});
|
|
@@ -22528,7 +23125,7 @@ async function runLoop(opts, now, note, emit, agentSpan) {
|
|
|
22528
23125
|
return {
|
|
22529
23126
|
type: "tool_result",
|
|
22530
23127
|
toolUseId: tu.id,
|
|
22531
|
-
content: capToolResultContent(`Error: ${
|
|
23128
|
+
content: capToolResultContent(`Error: ${message2}`),
|
|
22532
23129
|
isError: true
|
|
22533
23130
|
};
|
|
22534
23131
|
}
|
|
@@ -22897,8 +23494,8 @@ function rereviewFollowUp(input) {
|
|
|
22897
23494
|
`Re-review at ${c}: focus on what changed since ${r} (\`git diff ${r} HEAD\` if ${r} is still present, otherwise diff against the base), re-check any finding above that the new commits address, and report the complete updated review \u2014 same format, verdict line first. Then call \`submit_verdict\` again with \`head\` = \`${input.current}\`; the earlier verdict is void.`
|
|
22898
23495
|
].join("\n");
|
|
22899
23496
|
}
|
|
22900
|
-
function subject(
|
|
22901
|
-
return
|
|
23497
|
+
function subject(message2) {
|
|
23498
|
+
return message2.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
22902
23499
|
}
|
|
22903
23500
|
function short3(sha) {
|
|
22904
23501
|
return sha.trim().toLowerCase().slice(0, 7);
|
|
@@ -23024,16 +23621,17 @@ var init_digestCoverage = __esm({
|
|
|
23024
23621
|
});
|
|
23025
23622
|
|
|
23026
23623
|
// ../../src/core/reviewRound.ts
|
|
23027
|
-
function releaseModeFor(
|
|
23028
|
-
return
|
|
23624
|
+
function releaseModeFor(identity2, opts) {
|
|
23625
|
+
return identity2 === "read" || opts.hardStopped ? "always" : "if-clean";
|
|
23029
23626
|
}
|
|
23030
23627
|
async function attachRoundWorkspace(input) {
|
|
23031
|
-
const { agent } = input.round;
|
|
23628
|
+
const { agent, profile } = input.round;
|
|
23032
23629
|
const selection = await makeExecutor(
|
|
23033
23630
|
input.factory,
|
|
23034
23631
|
{
|
|
23035
23632
|
threadKey: input.round.threadKey,
|
|
23036
23633
|
agent,
|
|
23634
|
+
profile,
|
|
23037
23635
|
repo: input.round.repo,
|
|
23038
23636
|
ref: input.round.ref,
|
|
23039
23637
|
headSha: input.round.headSha
|
|
@@ -23043,7 +23641,7 @@ async function attachRoundWorkspace(input) {
|
|
|
23043
23641
|
const release = async (opts) => {
|
|
23044
23642
|
const { executor } = selection;
|
|
23045
23643
|
if (!executor.release) return;
|
|
23046
|
-
const mode = releaseModeFor(
|
|
23644
|
+
const mode = releaseModeFor(profile.identity, opts);
|
|
23047
23645
|
try {
|
|
23048
23646
|
const r = await executor.release(mode, opts.span ? { span: opts.span } : void 0);
|
|
23049
23647
|
console.log(`[release] ${input.logKey} ${r.released ? "released" : "kept"}${r.reason ? ` (${r.reason})` : ""}`);
|
|
@@ -23757,6 +24355,9 @@ function reclaimedRunRecord(input) {
|
|
|
23757
24355
|
},
|
|
23758
24356
|
channelVisibility: row.meta.channelVisibility ?? "unknown",
|
|
23759
24357
|
repo: row.meta.repo,
|
|
24358
|
+
// The row carries the profile the run was admitted with (a clipped budget
|
|
24359
|
+
// included); a row from before profiles existed leaves the record without one.
|
|
24360
|
+
...row.meta.profile && row.meta.agent ? { profile: { preset: row.meta.agent, ...row.meta.profile } } : {},
|
|
23760
24361
|
finishedAt,
|
|
23761
24362
|
status: status3,
|
|
23762
24363
|
diagnosis: analyzeRunFriction(events, {
|
|
@@ -23815,12 +24416,16 @@ function assembleRunRecord(input) {
|
|
|
23815
24416
|
...activityOfEvents(events) !== void 0 ? { activity: activityOfEvents(events) } : {},
|
|
23816
24417
|
...msg.sourceUrl !== void 0 ? { sourceUrl: msg.sourceUrl } : {},
|
|
23817
24418
|
...msg.userName !== void 0 ? { userName: msg.userName } : {},
|
|
23818
|
-
...input.handoff !== void 0 ? { handoff: redactHandoff(input.handoff) } : {}
|
|
24419
|
+
...input.handoff !== void 0 ? { handoff: redactHandoff(input.handoff) } : {},
|
|
24420
|
+
...input.profile !== void 0 ? { profile: input.profile } : {}
|
|
23819
24421
|
});
|
|
23820
24422
|
return fitted.eventCount !== fitted.storedEventCount ? { ...fitted, truncated: true } : fitted;
|
|
23821
24423
|
}
|
|
24424
|
+
function profileRecordOf(agent, profile) {
|
|
24425
|
+
return { preset: agent.name, ...profile };
|
|
24426
|
+
}
|
|
23822
24427
|
function writeTombstone(deps, ctx) {
|
|
23823
|
-
const { msg, agent, resolved, repoCtx, channelVisibility, run: run2, registry, resume } = ctx;
|
|
24428
|
+
const { msg, agent, profile, resolved, repoCtx, channelVisibility, run: run2, registry, resume } = ctx;
|
|
23824
24429
|
if (!resume) {
|
|
23825
24430
|
const startSnap = registry.snapshot(run2.id, run2.token);
|
|
23826
24431
|
if (startSnap) {
|
|
@@ -23833,6 +24438,7 @@ function writeTombstone(deps, ctx) {
|
|
|
23833
24438
|
msg,
|
|
23834
24439
|
channelVisibility,
|
|
23835
24440
|
repo: repoCtx.repo,
|
|
24441
|
+
profile: profileRecordOf(agent, profile),
|
|
23836
24442
|
finishedAt: startSnap.startedAt,
|
|
23837
24443
|
status: "interrupted",
|
|
23838
24444
|
diagnosis: analyzeRunFriction(startSnap.events, {
|
|
@@ -23851,6 +24457,7 @@ function registerFinishRecord(deps, ctx) {
|
|
|
23851
24457
|
run: run2,
|
|
23852
24458
|
snap,
|
|
23853
24459
|
agent,
|
|
24460
|
+
profile,
|
|
23854
24461
|
resolved,
|
|
23855
24462
|
msg,
|
|
23856
24463
|
channelVisibility,
|
|
@@ -23874,6 +24481,7 @@ function registerFinishRecord(deps, ctx) {
|
|
|
23874
24481
|
msg,
|
|
23875
24482
|
channelVisibility,
|
|
23876
24483
|
repo: repoCtx.repo,
|
|
24484
|
+
profile: profileRecordOf(agent, profile),
|
|
23877
24485
|
finishedAt,
|
|
23878
24486
|
status: failedAfterFinish && status3 === "completed" ? "failed" : status3,
|
|
23879
24487
|
diagnosis,
|
|
@@ -24225,10 +24833,10 @@ ${chatCatalogueText(inGroup)}` };
|
|
|
24225
24833
|
const id = `${group}.${verb}`;
|
|
24226
24834
|
const cmd = exposed.find((c) => c.id === id);
|
|
24227
24835
|
if (!cmd) return null;
|
|
24228
|
-
const rejected = (
|
|
24836
|
+
const rejected = (message2) => ({
|
|
24229
24837
|
kind: "reply",
|
|
24230
24838
|
error: "invalid_input",
|
|
24231
|
-
text: `\u26A0\uFE0F \`${chatForm(id)}\`: ${
|
|
24839
|
+
text: `\u26A0\uFE0F \`${chatForm(id)}\`: ${message2}`
|
|
24232
24840
|
});
|
|
24233
24841
|
const tokens = tokenize(text);
|
|
24234
24842
|
if (!tokens.ok) return rejected(tokens.error);
|
|
@@ -24250,15 +24858,15 @@ function chatCallerFor(msg, config, resolveRepo) {
|
|
|
24250
24858
|
origin: { channelId: msg.channelId, threadKey: msg.threadKey, ...resolveRepo ? { repo: resolveRepo } : {} }
|
|
24251
24859
|
};
|
|
24252
24860
|
}
|
|
24253
|
-
function chatErrorLine(id, error,
|
|
24861
|
+
function chatErrorLine(id, error, message2, config, decidedBy = "registry") {
|
|
24254
24862
|
const name = chatForm(id);
|
|
24255
24863
|
switch (error) {
|
|
24256
24864
|
case "unauthorized":
|
|
24257
|
-
return decidedBy === "handler" ? `\u{1F6AB} \`${name}\`: ${
|
|
24865
|
+
return decidedBy === "handler" ? `\u{1F6AB} \`${name}\`: ${message2} Ask ${config.adminsHint()}.` : `\u{1F6AB} \`${name}\` is restricted. Ask ${config.adminsHint()}.`;
|
|
24258
24866
|
case "internal":
|
|
24259
|
-
return `\u26A0\uFE0F \`${name}\` failed: ${
|
|
24867
|
+
return `\u26A0\uFE0F \`${name}\` failed: ${message2}`;
|
|
24260
24868
|
default:
|
|
24261
|
-
return `\u26A0\uFE0F \`${name}\`: ${
|
|
24869
|
+
return `\u26A0\uFE0F \`${name}\`: ${message2}`;
|
|
24262
24870
|
}
|
|
24263
24871
|
}
|
|
24264
24872
|
async function invokeChatCommand({
|
|
@@ -25063,6 +25671,11 @@ var init_fastPath = __esm({
|
|
|
25063
25671
|
});
|
|
25064
25672
|
|
|
25065
25673
|
// ../../src/directives.ts
|
|
25674
|
+
function parseBudgetMinutes(value) {
|
|
25675
|
+
if (!/^\d+$/.test(value)) return void 0;
|
|
25676
|
+
const minutes = Number(value);
|
|
25677
|
+
return minutes >= MIN_BOUNDARY_MINUTES ? minutes : void 0;
|
|
25678
|
+
}
|
|
25066
25679
|
function lastThreadDirectives(history) {
|
|
25067
25680
|
const out = {};
|
|
25068
25681
|
for (const h of history) {
|
|
@@ -25095,6 +25708,14 @@ function parseDirectives(input) {
|
|
|
25095
25708
|
throw new Error(`Unknown effort "${f.value}". Valid: ${EFFORT_LEVELS_HINT}`);
|
|
25096
25709
|
}
|
|
25097
25710
|
out.effort = f.value;
|
|
25711
|
+
} else if (f.key === "budget") {
|
|
25712
|
+
const minutes = parseBudgetMinutes(f.value);
|
|
25713
|
+
if (minutes === void 0) {
|
|
25714
|
+
throw new Error(
|
|
25715
|
+
`Invalid budget "${f.value}": budget:<minutes> takes a whole number of minutes, at least ${MIN_BOUNDARY_MINUTES} (e.g. budget:30). It narrows this run's wall clock and never widens it.`
|
|
25716
|
+
);
|
|
25717
|
+
}
|
|
25718
|
+
out.budget = minutes;
|
|
25098
25719
|
}
|
|
25099
25720
|
text = text.replace(f.match, " ");
|
|
25100
25721
|
}
|
|
@@ -25106,8 +25727,47 @@ var init_directives = __esm({
|
|
|
25106
25727
|
"../../src/directives.ts"() {
|
|
25107
25728
|
"use strict";
|
|
25108
25729
|
init_registry();
|
|
25730
|
+
init_validate();
|
|
25109
25731
|
init_effort();
|
|
25110
|
-
DIRECTIVE_RE = /(?:^|\s)(agent|model|effort)[:=](\S+)/g;
|
|
25732
|
+
DIRECTIVE_RE = /(?:^|\s)(agent|model|effort|budget)[:=](\S+)/g;
|
|
25733
|
+
}
|
|
25734
|
+
});
|
|
25735
|
+
|
|
25736
|
+
// ../../src/execution/githubRepoProbe.ts
|
|
25737
|
+
function githubRepoProbe(opts) {
|
|
25738
|
+
const fetchImpl = opts.fetch ?? fetch;
|
|
25739
|
+
const token = opts.token ?? ((scope) => resolveGithubToken(scope));
|
|
25740
|
+
return async (slug) => {
|
|
25741
|
+
if (!SLUG.test(slug)) return false;
|
|
25742
|
+
let bearer;
|
|
25743
|
+
try {
|
|
25744
|
+
bearer = opts.scope === void 0 ? null : await token(opts.scope);
|
|
25745
|
+
} catch {
|
|
25746
|
+
return "unreachable";
|
|
25747
|
+
}
|
|
25748
|
+
const headers = { accept: "application/vnd.github+json", "user-agent": "switchboard" };
|
|
25749
|
+
if (bearer) headers.authorization = `Bearer ${bearer}`;
|
|
25750
|
+
let res;
|
|
25751
|
+
try {
|
|
25752
|
+
res = await fetchImpl(`https://api.github.com/repos/${slug}`, {
|
|
25753
|
+
headers,
|
|
25754
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS6)
|
|
25755
|
+
});
|
|
25756
|
+
} catch {
|
|
25757
|
+
return "unreachable";
|
|
25758
|
+
}
|
|
25759
|
+
if (res.ok) return true;
|
|
25760
|
+
if (res.status === 404) return false;
|
|
25761
|
+
return "unreachable";
|
|
25762
|
+
};
|
|
25763
|
+
}
|
|
25764
|
+
var REQUEST_TIMEOUT_MS6, SLUG;
|
|
25765
|
+
var init_githubRepoProbe = __esm({
|
|
25766
|
+
"../../src/execution/githubRepoProbe.ts"() {
|
|
25767
|
+
"use strict";
|
|
25768
|
+
init_githubApp();
|
|
25769
|
+
REQUEST_TIMEOUT_MS6 = 1e4;
|
|
25770
|
+
SLUG = /^[A-Za-z0-9][A-Za-z0-9-]*\/[A-Za-z0-9._-]+$/;
|
|
25111
25771
|
}
|
|
25112
25772
|
});
|
|
25113
25773
|
|
|
@@ -25132,32 +25792,48 @@ function resolveRun(deps, ctx) {
|
|
|
25132
25792
|
});
|
|
25133
25793
|
return { sticky, resolved };
|
|
25134
25794
|
}
|
|
25795
|
+
function resolveProfile(ctx) {
|
|
25796
|
+
const carried = ctx.resume?.row.meta.profile;
|
|
25797
|
+
const declared = carried ? { machine: carried.machine, identity: carried.identity, maxMinutes: carried.minutes } : ctx.agent;
|
|
25798
|
+
const resolution = effectiveProfile(
|
|
25799
|
+
declared,
|
|
25800
|
+
ctx.budget !== void 0 ? { budget: ctx.budget } : {},
|
|
25801
|
+
ctx.resolved.boundary
|
|
25802
|
+
);
|
|
25803
|
+
if (resolution.kind === "profile" && carried?.boundedBy && !resolution.profile.boundedBy) {
|
|
25804
|
+
return { kind: "profile", profile: { ...resolution.profile, boundedBy: carried.boundedBy } };
|
|
25805
|
+
}
|
|
25806
|
+
return resolution;
|
|
25807
|
+
}
|
|
25135
25808
|
function resolveTarget(deps, ctx) {
|
|
25136
|
-
const { msg, history,
|
|
25809
|
+
const { msg, history, profile, resolved, resume, root } = ctx;
|
|
25137
25810
|
const { provider: providerName, model } = parseModelRef(resolved.modelRef);
|
|
25138
25811
|
const provider = deps.providers.get(providerName);
|
|
25139
|
-
const needsRepo =
|
|
25812
|
+
const needsRepo = machineNeedsRepo(profile.machine);
|
|
25140
25813
|
const repoCtxP = root.span(
|
|
25141
25814
|
"dispatch.repo_context",
|
|
25142
25815
|
() => resume ? Promise.resolve(resume.repoCtx) : needsRepo ? Promise.resolve(
|
|
25143
|
-
deps.resolveRepoContext ? deps.resolveRepoContext(msg, history) : resolveRepoContext(
|
|
25144
|
-
msg,
|
|
25145
|
-
history,
|
|
25146
|
-
residentOnboardedProbe(deps.config.config.execution?.resident),
|
|
25147
|
-
residentSlugsLister(deps.config.config.execution?.resident)
|
|
25148
|
-
)
|
|
25816
|
+
deps.resolveRepoContext ? deps.resolveRepoContext(msg, history) : resolveRepoContext(msg, history, ...repoVetFor(profile, deps.config.config.execution?.resident))
|
|
25149
25817
|
).then((ctx2) => ctx2 ?? {}) : Promise.resolve({})
|
|
25150
25818
|
);
|
|
25151
25819
|
repoCtxP.catch(() => {
|
|
25152
25820
|
});
|
|
25153
25821
|
return { provider, model, needsRepo, repoCtxP };
|
|
25154
25822
|
}
|
|
25823
|
+
function repoVetFor(profile, resident) {
|
|
25824
|
+
if (profile.machine === "repo-cold")
|
|
25825
|
+
return [githubRepoProbe({ scope: githubTokenScopeFor(profile.identity) }), void 0];
|
|
25826
|
+
return [residentOnboardedProbe(resident), residentSlugsLister(resident)];
|
|
25827
|
+
}
|
|
25155
25828
|
var init_resolve = __esm({
|
|
25156
25829
|
"../../src/core/dispatch/resolve.ts"() {
|
|
25157
25830
|
"use strict";
|
|
25831
|
+
init_registry();
|
|
25832
|
+
init_profile();
|
|
25158
25833
|
init_directives();
|
|
25159
25834
|
init_types3();
|
|
25160
25835
|
init_factory();
|
|
25836
|
+
init_githubRepoProbe();
|
|
25161
25837
|
init_repoContext();
|
|
25162
25838
|
}
|
|
25163
25839
|
});
|
|
@@ -25176,8 +25852,97 @@ async function authorizeAgent(deps, ctx) {
|
|
|
25176
25852
|
}
|
|
25177
25853
|
return { kind: "allowed" };
|
|
25178
25854
|
}
|
|
25855
|
+
async function authorizeProfile(deps, ctx) {
|
|
25856
|
+
const { msg, io, refuse: refuse3, agent, resolution } = ctx;
|
|
25857
|
+
if (resolution.kind === "profile") return { kind: "allowed", profile: resolution.profile };
|
|
25858
|
+
const { refusal } = resolution;
|
|
25859
|
+
console.log(`[dispatch] ${msg.threadKey} not started: profile bounded (${agent.name}: ${refusalSummary(refusal)})`);
|
|
25860
|
+
await refuse3("profile_bounded", () => io.reply(profileRefusalReply(agent.name, refusal, deps.config.adminsHint())));
|
|
25861
|
+
return { kind: "refused", reason: "profile_bounded" };
|
|
25862
|
+
}
|
|
25863
|
+
function refusalSummary(refusal) {
|
|
25864
|
+
return refusal.axis === "identity" ? `identity ${refusal.needs} > ${refusal.cap} (${refusal.scope})` : `machine ${refusal.needs} not in ${refusal.allowed.join(",")} (${refusal.scopes.join(",")})`;
|
|
25865
|
+
}
|
|
25866
|
+
function boundaryOf(scope) {
|
|
25867
|
+
switch (scope) {
|
|
25868
|
+
case "channel":
|
|
25869
|
+
return "this channel's boundary";
|
|
25870
|
+
case "user":
|
|
25871
|
+
return "your own boundary";
|
|
25872
|
+
case "defaults":
|
|
25873
|
+
return "the installation's default boundary";
|
|
25874
|
+
case "directive":
|
|
25875
|
+
return "this message's own budget";
|
|
25876
|
+
}
|
|
25877
|
+
}
|
|
25878
|
+
function wayForward(scope, axis, needs, adminsHint) {
|
|
25879
|
+
switch (scope) {
|
|
25880
|
+
case "channel":
|
|
25881
|
+
return `run it in a channel that allows \`${needs}\`, or ask ${adminsHint} to raise this channel's boundary`;
|
|
25882
|
+
case "user":
|
|
25883
|
+
return `raise your own boundary with \`config set me --boundary.${axis} ${needs}\`, or drop your overrides with \`config clear me\``;
|
|
25884
|
+
case "defaults":
|
|
25885
|
+
return `ask ${adminsHint} to raise \`defaults.boundary\` in the configuration`;
|
|
25886
|
+
case "directive":
|
|
25887
|
+
return "send the message again without the budget directive";
|
|
25888
|
+
}
|
|
25889
|
+
}
|
|
25890
|
+
function profileRefusalReply(agentName, refusal, adminsHint) {
|
|
25891
|
+
const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
25892
|
+
if (refusal.axis === "identity") {
|
|
25893
|
+
const how2 = wayForward(refusal.scope, "maxIdentity", refusal.needs, adminsHint);
|
|
25894
|
+
return `\u{1F6AB} \`${agentName}\` needs a \`${refusal.needs}\` credential; ${boundaryOf(refusal.scope)} caps runs at \`${refusal.cap}\`. ${capitalize(how2)}.`;
|
|
25895
|
+
}
|
|
25896
|
+
const scopes = refusal.scopes.map(boundaryOf);
|
|
25897
|
+
const who2 = scopes.length > 1 ? `${scopes.join(" and ")} allow` : `${scopes[0] ?? "the boundary"} allows`;
|
|
25898
|
+
const allowed = refusal.allowed.map((m) => `\`${m}\``).join(", ");
|
|
25899
|
+
const how = refusal.scopes.map(
|
|
25900
|
+
(scope) => wayForward(
|
|
25901
|
+
scope,
|
|
25902
|
+
"machines",
|
|
25903
|
+
scope === "user" ? `<classes including ${refusal.needs}>` : refusal.needs,
|
|
25904
|
+
adminsHint
|
|
25905
|
+
)
|
|
25906
|
+
).join("; ");
|
|
25907
|
+
return `\u{1F6AB} \`${agentName}\` runs on a \`${refusal.needs}\` machine; ${who2} only ${allowed}. ${capitalize(how)}.`;
|
|
25908
|
+
}
|
|
25179
25909
|
async function authorizeRepo(deps, ctx) {
|
|
25180
|
-
const { msg, io, refuse: refuse3, card, shell, closeLines, clock: clock2, agent, needsRepo, repoCtx } = ctx;
|
|
25910
|
+
const { msg, io, refuse: refuse3, card, shell, closeLines, clock: clock2, agent, profile, needsRepo, repoCtx } = ctx;
|
|
25911
|
+
if (profile.machine === "repo-cold" && needsRepo && !repoCtx.repo) {
|
|
25912
|
+
if (repoCtx.rejectedRepo) {
|
|
25913
|
+
const slug = repoCtx.rejectedRepo;
|
|
25914
|
+
console.log(`[dispatch] ${msg.threadKey} not started: repo not visible (${slug}: GitHub answered 404)`);
|
|
25915
|
+
await refuse3("repo_not_visible", async () => {
|
|
25916
|
+
await card.done(
|
|
25917
|
+
shell.close({ kind: "not_started", icon: "\u{1F4E6}", reason: "repo not visible", ...closeLines(clock2(), false) })
|
|
25918
|
+
);
|
|
25919
|
+
await io.reply(
|
|
25920
|
+
`\u{1F4E6} \`${slug}\` is not a repository this installation can see \u2014 GitHub answered 404 \u2014 so I did not start ${aRun(agent.name)} for it. The repository is outside the Switchboard GitHub App installation (\`github_repos\` lists the reachable ones), or the name is wrong.`
|
|
25921
|
+
);
|
|
25922
|
+
});
|
|
25923
|
+
return { kind: "refused", reason: "repo_not_visible" };
|
|
25924
|
+
}
|
|
25925
|
+
if (repoCtx.unverifiedRepo) {
|
|
25926
|
+
const slug = repoCtx.unverifiedRepo;
|
|
25927
|
+
console.log(
|
|
25928
|
+
`[dispatch] ${msg.threadKey} not started: repo could not be verified (${slug}: GitHub did not answer)`
|
|
25929
|
+
);
|
|
25930
|
+
await refuse3("repo_unverified", async () => {
|
|
25931
|
+
await card.done(
|
|
25932
|
+
shell.close({
|
|
25933
|
+
kind: "not_started",
|
|
25934
|
+
icon: "\u{1F4E6}",
|
|
25935
|
+
reason: "repo could not be verified",
|
|
25936
|
+
...closeLines(clock2(), false)
|
|
25937
|
+
})
|
|
25938
|
+
);
|
|
25939
|
+
await io.reply(
|
|
25940
|
+
`\u26A0\uFE0F I couldn't verify \`${slug}\` against GitHub \u2014 it didn't answer \u2014 so I did not start ${aRun(agent.name)} rather than guess which repository you meant. Try again in a minute.`
|
|
25941
|
+
);
|
|
25942
|
+
});
|
|
25943
|
+
return { kind: "refused", reason: "repo_unverified" };
|
|
25944
|
+
}
|
|
25945
|
+
}
|
|
25181
25946
|
if (deps.capabilities.residents && needsRepo && !repoCtx.repo && repoCtx.rejectedRepo) {
|
|
25182
25947
|
const slug = repoCtx.rejectedRepo;
|
|
25183
25948
|
console.log(`[dispatch] ${msg.threadKey} not started: repo not onboarded (${slug})`);
|
|
@@ -25226,6 +25991,9 @@ async function authorizeRepo(deps, ctx) {
|
|
|
25226
25991
|
}
|
|
25227
25992
|
return { kind: "allowed" };
|
|
25228
25993
|
}
|
|
25994
|
+
function aRun(agentName) {
|
|
25995
|
+
return `${/^[aeiou]/i.test(agentName) ? "an" : "a"} *${agentName}* run`;
|
|
25996
|
+
}
|
|
25229
25997
|
async function authorizePrHead(ctx) {
|
|
25230
25998
|
const { msg, io, refuse: refuse3, card, shell, closeLines, clock: clock2, agent, directives, repoCtx } = ctx;
|
|
25231
25999
|
const preflight = checkPrHeadPreflight({ agent, requestText: directives.text, repoCtx });
|
|
@@ -25551,10 +26319,24 @@ function configAwarenessBlock(i) {
|
|
|
25551
26319
|
);
|
|
25552
26320
|
}
|
|
25553
26321
|
}
|
|
26322
|
+
if (i.boundary) {
|
|
26323
|
+
lines.push(
|
|
26324
|
+
`Boundary in force: ${fmtEffectiveBoundary(i.boundary)} \u2014 a boundary caps what any run in its scope may have and never grants; a preset above a cap is refused, a budget above it clipped. Users set their own with \`config set me --boundary.maxMinutes <n> --boundary.maxIdentity <none|read|write> --boundary.machines <a,b>\` (it can only tighten the channel's and the defaults'); \`config set channel --boundary.\u2026\` caps a channel.`
|
|
26325
|
+
);
|
|
26326
|
+
}
|
|
26327
|
+
if (i.budget?.boundedBy !== void 0) {
|
|
26328
|
+
lines.push(
|
|
26329
|
+
`Budget: ${i.budget.minutes} min (clipped by the ${clipSourceLabel(i.budget.boundedBy)}; the preset asks ${i.budget.presetMinutes}).`
|
|
26330
|
+
);
|
|
26331
|
+
}
|
|
26332
|
+
if (i.budget?.directive !== void 0 && i.budget.boundedBy !== "directive") {
|
|
26333
|
+
const stands = i.budget.boundedBy === void 0 ? `the preset's ${i.budget.presetMinutes} min` : `${i.budget.minutes} min`;
|
|
26334
|
+
lines.push(`This message's \`budget:${i.budget.directive}\` narrowed nothing: the run's budget is ${stands}.`);
|
|
26335
|
+
}
|
|
25554
26336
|
const channelGate = i.canEditChannelConfig ? "per-channel" : "per-channel; restricted for this user \u2014 ask an admin";
|
|
25555
26337
|
const levels = `<${EFFORT_LEVELS.join("|")}>`;
|
|
25556
26338
|
lines.push(
|
|
25557
|
-
`Users inspect and tune settings: \`config show\`, \`config set me --agent <name> --model <provider>/<model> --effort ${levels}\` (per-user; \`--models.<agent>\` / \`--efforts.<agent>\` per agent), \`config set channel \u2026\` (${channelGate}), \`config instructions me "<free text>"\` (custom instructions
|
|
26339
|
+
`Users inspect and tune settings: \`config show\`, \`config set me --agent <name> --model <provider>/<model> --effort ${levels}\` (per-user; \`--models.<agent>\` / \`--efforts.<agent>\` per agent), \`config set channel \u2026\` (${channelGate}), \`config instructions me|channel "<free text>"\` (custom instructions), \`config clear me|channel\`, and per-message \`agent:<name>\` / \`model:<provider>/<model>\` / \`effort:<level>\` / \`budget:<minutes>\` directives.`,
|
|
25558
26340
|
"When asked about your settings or tuning, answer from this block \u2014 you are not stateless or untunable."
|
|
25559
26341
|
);
|
|
25560
26342
|
return lines.join("\n");
|
|
@@ -25579,12 +26361,15 @@ function fmtDirective(d) {
|
|
|
25579
26361
|
if (d.agent) parts.push(`agent:${d.agent}`);
|
|
25580
26362
|
if (d.model) parts.push(`model:${d.model}`);
|
|
25581
26363
|
if (d.effort) parts.push(`effort:${d.effort}`);
|
|
26364
|
+
if (d.budget !== void 0) parts.push(`budget:${d.budget}`);
|
|
25582
26365
|
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
25583
26366
|
}
|
|
25584
26367
|
var CONFIG_AWARENESS_HEADER;
|
|
25585
26368
|
var init_configAwareness = __esm({
|
|
25586
26369
|
"../../src/core/configAwareness.ts"() {
|
|
25587
26370
|
"use strict";
|
|
26371
|
+
init_config();
|
|
26372
|
+
init_profile();
|
|
25588
26373
|
init_effort();
|
|
25589
26374
|
CONFIG_AWARENESS_HEADER = "Switchboard runtime config for this run:";
|
|
25590
26375
|
}
|
|
@@ -25795,6 +26580,15 @@ async function openAckCard(deps, ctx) {
|
|
|
25795
26580
|
const heartbeat = setInterval(() => card.update(shell.live()), 5e3);
|
|
25796
26581
|
return { shell, card, heartbeat };
|
|
25797
26582
|
}
|
|
26583
|
+
function budgetClipLabel(agent, profile, budgetDirective) {
|
|
26584
|
+
const idle = budgetDirective !== void 0 && profile.boundedBy !== "directive";
|
|
26585
|
+
if (profile.boundedBy === void 0) {
|
|
26586
|
+
return idle ? `budget:${budgetDirective} narrowed nothing (preset asks ${agent.maxMinutes})` : void 0;
|
|
26587
|
+
}
|
|
26588
|
+
const facts = [`${clipSourceLabel(profile.boundedBy)}; preset asks ${agent.maxMinutes}`];
|
|
26589
|
+
if (idle) facts.push(`budget:${budgetDirective} narrowed nothing`);
|
|
26590
|
+
return `budget ${profile.minutes} min (${facts.join("; ")})`;
|
|
26591
|
+
}
|
|
25798
26592
|
async function registerRun(deps, ctx) {
|
|
25799
26593
|
const {
|
|
25800
26594
|
msg,
|
|
@@ -25897,6 +26691,7 @@ async function reserveRun(deps, ctx) {
|
|
|
25897
26691
|
const {
|
|
25898
26692
|
msg,
|
|
25899
26693
|
agent,
|
|
26694
|
+
profile,
|
|
25900
26695
|
resolved,
|
|
25901
26696
|
repoCtx,
|
|
25902
26697
|
channelVisibility,
|
|
@@ -25932,7 +26727,8 @@ async function reserveRun(deps, ctx) {
|
|
|
25932
26727
|
...repoCtx.ref !== void 0 ? { ref: repoCtx.ref } : {},
|
|
25933
26728
|
...repoCtx.headSha !== void 0 ? { headSha: repoCtx.headSha } : {},
|
|
25934
26729
|
...repoCtx.pr !== void 0 ? { pr: repoCtx.pr } : {},
|
|
25935
|
-
readonly:
|
|
26730
|
+
readonly: profile.identity === "read",
|
|
26731
|
+
profile,
|
|
25936
26732
|
request: requestRow
|
|
25937
26733
|
},
|
|
25938
26734
|
card: card.handle ?? null,
|
|
@@ -25945,7 +26741,7 @@ async function reserveRun(deps, ctx) {
|
|
|
25945
26741
|
return void 0;
|
|
25946
26742
|
}
|
|
25947
26743
|
async function attachWorkspace(deps, ctx) {
|
|
25948
|
-
const { msg, io, refuse: refuse3, card, shell, closeLines, clock: clock2, agent, repoCtx, root } = ctx;
|
|
26744
|
+
const { msg, io, refuse: refuse3, card, shell, closeLines, clock: clock2, agent, profile, repoCtx, root } = ctx;
|
|
25949
26745
|
let round;
|
|
25950
26746
|
try {
|
|
25951
26747
|
round = await root.span("dispatch.workspace.attach", async (span) => {
|
|
@@ -25964,7 +26760,14 @@ async function attachWorkspace(deps, ctx) {
|
|
|
25964
26760
|
workspaceDir: deps.config.config.workspaceDir ?? "./workspaces",
|
|
25965
26761
|
dataDir: deps.dataDir ?? "./data"
|
|
25966
26762
|
},
|
|
25967
|
-
round: {
|
|
26763
|
+
round: {
|
|
26764
|
+
threadKey: msg.threadKey,
|
|
26765
|
+
agent,
|
|
26766
|
+
profile,
|
|
26767
|
+
repo: repoCtx.repo,
|
|
26768
|
+
ref: repoCtx.ref,
|
|
26769
|
+
headSha: repoCtx.headSha
|
|
26770
|
+
},
|
|
25968
26771
|
logKey: msg.threadKey,
|
|
25969
26772
|
span
|
|
25970
26773
|
});
|
|
@@ -25998,6 +26801,7 @@ async function composePrompt(deps, ctx) {
|
|
|
25998
26801
|
const {
|
|
25999
26802
|
msg,
|
|
26000
26803
|
agent,
|
|
26804
|
+
profile,
|
|
26001
26805
|
resolved,
|
|
26002
26806
|
directives,
|
|
26003
26807
|
sticky,
|
|
@@ -26023,9 +26827,23 @@ async function composePrompt(deps, ctx) {
|
|
|
26023
26827
|
effort: resolved.effort,
|
|
26024
26828
|
channel: scopes.channel,
|
|
26025
26829
|
user: scopes.user,
|
|
26026
|
-
messageDirective: {
|
|
26830
|
+
messageDirective: {
|
|
26831
|
+
agent: directives.agent,
|
|
26832
|
+
model: directives.model,
|
|
26833
|
+
effort: directives.effort,
|
|
26834
|
+
budget: directives.budget
|
|
26835
|
+
},
|
|
26027
26836
|
threadDirective: { agent: sticky.agent, model: sticky.model, effort: sticky.effort },
|
|
26028
26837
|
canEditChannelConfig: deps.config.canEditChannelConfig(msg.userId),
|
|
26838
|
+
// The boundary in force and the budget this run actually has — the same
|
|
26839
|
+
// values the gate judged, so "how long do you have?" is answered from fact.
|
|
26840
|
+
...resolved.boundary ? { boundary: resolved.boundary } : {},
|
|
26841
|
+
budget: {
|
|
26842
|
+
minutes: profile.minutes,
|
|
26843
|
+
presetMinutes: agent.maxMinutes,
|
|
26844
|
+
...profile.boundedBy !== void 0 ? { boundedBy: profile.boundedBy } : {},
|
|
26845
|
+
...directives.budget !== void 0 ? { directive: directives.budget } : {}
|
|
26846
|
+
},
|
|
26029
26847
|
mcp: {
|
|
26030
26848
|
registryOn: deps.capabilities.mcp,
|
|
26031
26849
|
served: mcpForRun.servers.filter((s) => s.toolCount !== void 0).map((s) => s.server),
|
|
@@ -26071,6 +26889,7 @@ var init_provision = __esm({
|
|
|
26071
26889
|
"../../src/core/dispatch/provision.ts"() {
|
|
26072
26890
|
"use strict";
|
|
26073
26891
|
init_registry();
|
|
26892
|
+
init_profile();
|
|
26074
26893
|
init_residentTrace();
|
|
26075
26894
|
init_resident();
|
|
26076
26895
|
init_memory();
|
|
@@ -26102,6 +26921,7 @@ async function claimRun(deps, ctx) {
|
|
|
26102
26921
|
channelVisibility,
|
|
26103
26922
|
run: run2,
|
|
26104
26923
|
registry,
|
|
26924
|
+
profile,
|
|
26105
26925
|
selection,
|
|
26106
26926
|
requestRow,
|
|
26107
26927
|
reserved,
|
|
@@ -26137,7 +26957,8 @@ async function claimRun(deps, ctx) {
|
|
|
26137
26957
|
...repoCtx.ref !== void 0 ? { ref: repoCtx.ref } : {},
|
|
26138
26958
|
...repoCtx.headSha !== void 0 ? { headSha: repoCtx.headSha } : {},
|
|
26139
26959
|
...repoCtx.pr !== void 0 ? { pr: repoCtx.pr } : {},
|
|
26140
|
-
readonly:
|
|
26960
|
+
readonly: profile.identity === "read",
|
|
26961
|
+
profile,
|
|
26141
26962
|
selection: resident === true ? "resident" : "sandbox",
|
|
26142
26963
|
...binding?.workspace !== void 0 ? { workspace: binding.workspace } : {},
|
|
26143
26964
|
...requestRow !== void 0 ? { request: requestRow } : {}
|
|
@@ -26150,7 +26971,9 @@ async function claimRun(deps, ctx) {
|
|
|
26150
26971
|
tools: mergeTools(TOOLSETS[agent.toolset] ?? [], mcpForRun?.tools).map(
|
|
26151
26972
|
({ name, description, inputSchema }) => ({ name, description, inputSchema })
|
|
26152
26973
|
),
|
|
26153
|
-
seed
|
|
26974
|
+
// The seed carries the EFFECTIVE budget, so a resume runs on what
|
|
26975
|
+
// this run was admitted with, not on the preset's own number.
|
|
26976
|
+
seed: { messages, budgetMs: profile.minutes * 6e4 },
|
|
26154
26977
|
// A stop asked of another container (`/runs/stop` there) reaches this
|
|
26155
26978
|
// run through its heartbeat and is honored like a local one; a fence
|
|
26156
26979
|
// (another generation took the run) is a hard stop — nothing more may
|
|
@@ -26642,7 +27465,7 @@ async function runLoop2(deps, ctx) {
|
|
|
26642
27465
|
const {
|
|
26643
27466
|
msg,
|
|
26644
27467
|
io,
|
|
26645
|
-
|
|
27468
|
+
profile,
|
|
26646
27469
|
resolved,
|
|
26647
27470
|
provider,
|
|
26648
27471
|
model,
|
|
@@ -26669,6 +27492,7 @@ async function runLoop2(deps, ctx) {
|
|
|
26669
27492
|
publishText,
|
|
26670
27493
|
ending
|
|
26671
27494
|
} = ctx;
|
|
27495
|
+
const agent = budgetedAgent(ctx.agent, profile);
|
|
26672
27496
|
const { executor, binding } = round.selection;
|
|
26673
27497
|
let reviewHead = ctx.reviewHead;
|
|
26674
27498
|
let lastActivityAt = ctx.loopStartedAt;
|
|
@@ -26996,6 +27820,7 @@ async function runLoop2(deps, ctx) {
|
|
|
26996
27820
|
run: run2,
|
|
26997
27821
|
snap,
|
|
26998
27822
|
agent,
|
|
27823
|
+
profile,
|
|
26999
27824
|
resolved,
|
|
27000
27825
|
msg,
|
|
27001
27826
|
channelVisibility,
|
|
@@ -27032,6 +27857,7 @@ async function runLoop2(deps, ctx) {
|
|
|
27032
27857
|
var init_runLoop = __esm({
|
|
27033
27858
|
"../../src/core/dispatch/runLoop.ts"() {
|
|
27034
27859
|
"use strict";
|
|
27860
|
+
init_profile();
|
|
27035
27861
|
init_runner();
|
|
27036
27862
|
init_githubPulls();
|
|
27037
27863
|
init_repoContext();
|
|
@@ -27087,6 +27913,7 @@ async function runShipCodingChild(input, ctx, opts, roundSpan) {
|
|
|
27087
27913
|
round: {
|
|
27088
27914
|
threadKey: input.threadKey,
|
|
27089
27915
|
agent: spec.agent,
|
|
27916
|
+
profile: declaredProfile(spec.agent),
|
|
27090
27917
|
repo: entry.repo,
|
|
27091
27918
|
ref: entry.branch,
|
|
27092
27919
|
headSha: opts.attachHeadSha
|
|
@@ -27275,6 +28102,7 @@ var init_codingChild = __esm({
|
|
|
27275
28102
|
"../../src/core/ship/codingChild.ts"() {
|
|
27276
28103
|
"use strict";
|
|
27277
28104
|
init_runner();
|
|
28105
|
+
init_profile();
|
|
27278
28106
|
init_descriptionTurn();
|
|
27279
28107
|
init_reviewVerdict();
|
|
27280
28108
|
init_codingPrPostStep();
|
|
@@ -27316,7 +28144,14 @@ async function runShipReviewChild(input, ctx, round, roundSpan) {
|
|
|
27316
28144
|
if (!pf.ok) return { refusal: pf.reply };
|
|
27317
28145
|
const ws = await attachRoundWorkspace({
|
|
27318
28146
|
factory: input.factory,
|
|
27319
|
-
round: {
|
|
28147
|
+
round: {
|
|
28148
|
+
threadKey: input.threadKey,
|
|
28149
|
+
agent: spec.agent,
|
|
28150
|
+
profile: declaredProfile(spec.agent),
|
|
28151
|
+
repo: entry.repo,
|
|
28152
|
+
ref: entry.branch,
|
|
28153
|
+
headSha: pinned
|
|
28154
|
+
},
|
|
27320
28155
|
logKey
|
|
27321
28156
|
});
|
|
27322
28157
|
const { executor, resident, binding, note } = ws.selection;
|
|
@@ -27450,6 +28285,7 @@ var init_reviewChild = __esm({
|
|
|
27450
28285
|
"../../src/core/ship/reviewChild.ts"() {
|
|
27451
28286
|
"use strict";
|
|
27452
28287
|
init_runner();
|
|
28288
|
+
init_profile();
|
|
27453
28289
|
init_reviewVerdict();
|
|
27454
28290
|
init_reviewedHead();
|
|
27455
28291
|
init_reviewRound();
|
|
@@ -27464,6 +28300,9 @@ function resolveShipCaps(cfg) {
|
|
|
27464
28300
|
maxMinutes: cfg?.maxMinutes ?? SHIP_DEFAULT_MAX_MINUTES
|
|
27465
28301
|
};
|
|
27466
28302
|
}
|
|
28303
|
+
function shipPresetFor(cfg) {
|
|
28304
|
+
return { ...AGENTS.ship, maxMinutes: resolveShipCaps(cfg).maxMinutes };
|
|
28305
|
+
}
|
|
27467
28306
|
function shipInterruptedNote(prUrl) {
|
|
27468
28307
|
const stands = prUrl ? `Its work stands on GitHub: ${prUrl}.` : "Whatever it pushed stands on its pipeline branch; no PR was opened yet.";
|
|
27469
28308
|
const reissue = prUrl ? `To continue the review loop, re-issue \`agent:ship\` in this thread with only the PR URL (${prUrl}).` : "To continue, re-issue `agent:ship` in this thread with the task \u2014 round 0 runs again on the same branch.";
|
|
@@ -27785,12 +28624,13 @@ var SHIP_DEFAULT_MAX_ROUNDS, SHIP_DEFAULT_MAX_MINUTES, SHIP_ROUND_RESERVE_MS;
|
|
|
27785
28624
|
var init_shipPipeline = __esm({
|
|
27786
28625
|
"../../src/core/shipPipeline.ts"() {
|
|
27787
28626
|
"use strict";
|
|
28627
|
+
init_registry();
|
|
27788
28628
|
init_reviewVerdict();
|
|
27789
28629
|
init_reviewedHead();
|
|
27790
28630
|
init_codingChild();
|
|
27791
28631
|
init_reviewChild();
|
|
27792
28632
|
SHIP_DEFAULT_MAX_ROUNDS = 3;
|
|
27793
|
-
SHIP_DEFAULT_MAX_MINUTES =
|
|
28633
|
+
SHIP_DEFAULT_MAX_MINUTES = AGENTS.ship.maxMinutes;
|
|
27794
28634
|
SHIP_ROUND_RESERVE_MS = 3 * 6e4;
|
|
27795
28635
|
}
|
|
27796
28636
|
});
|
|
@@ -27948,7 +28788,7 @@ var init_preflight = __esm({
|
|
|
27948
28788
|
|
|
27949
28789
|
// ../../src/core/dispatch/ship.ts
|
|
27950
28790
|
async function runShipBranch(deps, msg, io, ctx) {
|
|
27951
|
-
const { agent, card, directives, history, repoCtx, label, ending, trace, closeLines, refuse: refuse3, doneLines } = ctx;
|
|
28791
|
+
const { agent, profile, card, directives, history, repoCtx, label, ending, trace, closeLines, refuse: refuse3, doneLines } = ctx;
|
|
27952
28792
|
const root = trace.root;
|
|
27953
28793
|
const clock2 = deps.clock ?? systemClock;
|
|
27954
28794
|
const shell = createCardShell({ label, startedAt: ctx.startedAt, now: clock2 });
|
|
@@ -28050,7 +28890,8 @@ async function runShipBranch(deps, msg, io, ctx) {
|
|
|
28050
28890
|
diagnosis: analyzeRunFriction(startSnap.events, {
|
|
28051
28891
|
finished: false,
|
|
28052
28892
|
truncated: startSnap.truncated
|
|
28053
|
-
})
|
|
28893
|
+
}),
|
|
28894
|
+
profile: profileRecordOf(agent, profile)
|
|
28054
28895
|
}),
|
|
28055
28896
|
{ provisional: true }
|
|
28056
28897
|
);
|
|
@@ -28071,7 +28912,8 @@ async function runShipBranch(deps, msg, io, ctx) {
|
|
|
28071
28912
|
...repoCtx.repo !== void 0 ? { repo: repoCtx.repo } : {},
|
|
28072
28913
|
...msg.sourceUrl !== void 0 ? { sourceUrl: msg.sourceUrl } : {},
|
|
28073
28914
|
...msg.userName !== void 0 ? { userName: msg.userName } : {},
|
|
28074
|
-
...entry.resume !== void 0 ? { pr: entry.resume.pr } : {}
|
|
28915
|
+
...entry.resume !== void 0 ? { pr: entry.resume.pr } : {},
|
|
28916
|
+
profile
|
|
28075
28917
|
},
|
|
28076
28918
|
card: card.handle ?? null,
|
|
28077
28919
|
system: "",
|
|
@@ -28146,7 +28988,12 @@ async function runShipBranch(deps, msg, io, ctx) {
|
|
|
28146
28988
|
effort: spec.effort,
|
|
28147
28989
|
channel: scopes.channel,
|
|
28148
28990
|
user: scopes.user,
|
|
28149
|
-
messageDirective: {
|
|
28991
|
+
messageDirective: {
|
|
28992
|
+
agent: directives.agent,
|
|
28993
|
+
model: directives.model,
|
|
28994
|
+
effort: directives.effort,
|
|
28995
|
+
budget: directives.budget
|
|
28996
|
+
},
|
|
28150
28997
|
threadDirective: { agent: ctx.sticky.agent, model: ctx.sticky.model, effort: ctx.sticky.effort },
|
|
28151
28998
|
canEditChannelConfig: deps.config.canEditChannelConfig(msg.userId)
|
|
28152
28999
|
// No `mcp` here: ship rounds receive no MCP tools yet (docs/reference/specs/mcp-tools.md
|
|
@@ -28185,7 +29032,11 @@ async function runShipBranch(deps, msg, io, ctx) {
|
|
|
28185
29032
|
dataDir: deps.dataDir ?? "./data"
|
|
28186
29033
|
},
|
|
28187
29034
|
threadKey: msg.threadKey,
|
|
28188
|
-
|
|
29035
|
+
// The rounds cap is the config block's; the wall clock is the parent's
|
|
29036
|
+
// effective budget — the preset's declared `ship.maxMinutes` as a
|
|
29037
|
+
// boundary or a `budget:` directive clipped it (agent-ship.md item 8) —
|
|
29038
|
+
// so every child round is clipped to what remains of THAT.
|
|
29039
|
+
caps: { ...resolveShipCaps(deps.config.config.ship), maxMinutes: profile.minutes },
|
|
28189
29040
|
control: run2.control,
|
|
28190
29041
|
inbox: ctx.live.inbox,
|
|
28191
29042
|
// thread follow-ups steered into this run reach the child round in flight (thread-admission item 2)
|
|
@@ -28251,7 +29102,8 @@ async function runShipBranch(deps, msg, io, ctx) {
|
|
|
28251
29102
|
seal,
|
|
28252
29103
|
// The last coding round's handoff (agent-ship.md item 14) — the
|
|
28253
29104
|
// pipeline's, so the ship record carries what its child handed back.
|
|
28254
|
-
...outcome?.handoff !== void 0 ? { handoff: outcome.handoff } : {}
|
|
29105
|
+
...outcome?.handoff !== void 0 ? { handoff: outcome.handoff } : {},
|
|
29106
|
+
profile: profileRecordOf(agent, profile)
|
|
28255
29107
|
}),
|
|
28256
29108
|
{ span: root, ...ledgerRun ? { via: ledgerRun.sink } : {} }
|
|
28257
29109
|
)
|
|
@@ -28505,7 +29357,16 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28505
29357
|
if (await answerOperation(deps, { msg, io, ending, trace, directives, history })) return;
|
|
28506
29358
|
const { sticky, resolved } = resolveRun(deps, { msg, directives, history });
|
|
28507
29359
|
if ((await authorizeAgent(deps, { msg, io, refuse: refuse3, agentName: resolved.agentName })).kind === "refused") return;
|
|
28508
|
-
const agent = getAgent(resolved.agentName);
|
|
29360
|
+
const agent = resolved.agentName === "ship" ? shipPresetFor(deps.config.config.ship) : getAgent(resolved.agentName);
|
|
29361
|
+
const profileGate = await authorizeProfile(deps, {
|
|
29362
|
+
msg,
|
|
29363
|
+
io,
|
|
29364
|
+
refuse: refuse3,
|
|
29365
|
+
agent,
|
|
29366
|
+
resolution: resolveProfile({ agent, resolved, resume, budget: directives.budget })
|
|
29367
|
+
});
|
|
29368
|
+
if (profileGate.kind === "refused") return;
|
|
29369
|
+
const { profile } = profileGate;
|
|
28509
29370
|
const carriedRow = resume?.row ?? restart?.row;
|
|
28510
29371
|
const admissionCtx = {
|
|
28511
29372
|
msg,
|
|
@@ -28540,6 +29401,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28540
29401
|
msg,
|
|
28541
29402
|
history,
|
|
28542
29403
|
agent,
|
|
29404
|
+
profile,
|
|
28543
29405
|
resolved,
|
|
28544
29406
|
resume,
|
|
28545
29407
|
root
|
|
@@ -28561,15 +29423,19 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28561
29423
|
closeLines,
|
|
28562
29424
|
clock: clock2,
|
|
28563
29425
|
agent,
|
|
29426
|
+
profile,
|
|
28564
29427
|
needsRepo,
|
|
28565
29428
|
repoCtx
|
|
28566
29429
|
});
|
|
28567
29430
|
if (repoGate.kind === "refused") return;
|
|
29431
|
+
const clip3 = budgetClipLabel(agent, profile, directives.budget);
|
|
29432
|
+
if (clip3) shell.setLabel(`${shell.label} \xB7 ${clip3}`);
|
|
28568
29433
|
if (agent.name === "ship") {
|
|
28569
29434
|
setupCard = void 0;
|
|
28570
29435
|
clearInterval(setupHeartbeat);
|
|
28571
29436
|
await runShipBranch(deps, msg, io, {
|
|
28572
29437
|
agent,
|
|
29438
|
+
profile,
|
|
28573
29439
|
modelRef: resolved.modelRef,
|
|
28574
29440
|
label: shell.label,
|
|
28575
29441
|
startedAt,
|
|
@@ -28626,6 +29492,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28626
29492
|
const reservation = await reserveRun(deps, {
|
|
28627
29493
|
msg,
|
|
28628
29494
|
agent,
|
|
29495
|
+
profile,
|
|
28629
29496
|
resolved,
|
|
28630
29497
|
repoCtx,
|
|
28631
29498
|
channelVisibility,
|
|
@@ -28652,6 +29519,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28652
29519
|
closeLines,
|
|
28653
29520
|
clock: clock2,
|
|
28654
29521
|
agent,
|
|
29522
|
+
profile,
|
|
28655
29523
|
repoCtx,
|
|
28656
29524
|
root
|
|
28657
29525
|
});
|
|
@@ -28689,6 +29557,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28689
29557
|
const prompt = await composePrompt(deps, {
|
|
28690
29558
|
msg,
|
|
28691
29559
|
agent,
|
|
29560
|
+
profile,
|
|
28692
29561
|
resolved,
|
|
28693
29562
|
directives,
|
|
28694
29563
|
sticky,
|
|
@@ -28716,10 +29585,11 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28716
29585
|
`[resume] ${msg.threadKey} run ${run2.id} continues under ${deps.runLedger.gen}: from step ${resume.plan.step}, ${resume.plan.settlements.length} call(s) to settle, ${resume.events.length} event(s) replayed`
|
|
28717
29586
|
);
|
|
28718
29587
|
}
|
|
28719
|
-
writeTombstone(deps, { msg, agent, resolved, repoCtx, channelVisibility, run: run2, registry, resume });
|
|
29588
|
+
writeTombstone(deps, { msg, agent, profile, resolved, repoCtx, channelVisibility, run: run2, registry, resume });
|
|
28720
29589
|
ledgerRun = await claimRun(deps, {
|
|
28721
29590
|
msg,
|
|
28722
29591
|
agent,
|
|
29592
|
+
profile,
|
|
28723
29593
|
resolved,
|
|
28724
29594
|
repoCtx,
|
|
28725
29595
|
channelVisibility,
|
|
@@ -28741,6 +29611,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
28741
29611
|
msg,
|
|
28742
29612
|
io,
|
|
28743
29613
|
agent,
|
|
29614
|
+
profile,
|
|
28744
29615
|
resolved,
|
|
28745
29616
|
provider,
|
|
28746
29617
|
model,
|
|
@@ -28904,6 +29775,7 @@ var init_dispatcher = __esm({
|
|
|
28904
29775
|
init_reply();
|
|
28905
29776
|
init_record();
|
|
28906
29777
|
init_ship();
|
|
29778
|
+
init_shipPipeline();
|
|
28907
29779
|
init_settle();
|
|
28908
29780
|
init_runRegistry();
|
|
28909
29781
|
init_runEnding();
|
|
@@ -28911,22 +29783,6 @@ var init_dispatcher = __esm({
|
|
|
28911
29783
|
}
|
|
28912
29784
|
});
|
|
28913
29785
|
|
|
28914
|
-
// ../../src/core/workerError.ts
|
|
28915
|
-
async function errorSuffix(res) {
|
|
28916
|
-
const text = await res.text().catch(() => "");
|
|
28917
|
-
try {
|
|
28918
|
-
const parsed = JSON.parse(text);
|
|
28919
|
-
return parsed?.error ? `: ${String(parsed.error)}` : "";
|
|
28920
|
-
} catch {
|
|
28921
|
-
return "";
|
|
28922
|
-
}
|
|
28923
|
-
}
|
|
28924
|
-
var init_workerError = __esm({
|
|
28925
|
-
"../../src/core/workerError.ts"() {
|
|
28926
|
-
"use strict";
|
|
28927
|
-
}
|
|
28928
|
-
});
|
|
28929
|
-
|
|
28930
29786
|
// ../../src/core/runStoreWorker.ts
|
|
28931
29787
|
function describeError2(err2, depth = 0) {
|
|
28932
29788
|
if (!(err2 instanceof Error)) return String(err2);
|
|
@@ -29041,10 +29897,10 @@ var init_runStoreWorker = __esm({
|
|
|
29041
29897
|
throw new TransientStoreError(`run store ${path}: ${describeError2(err2)}`);
|
|
29042
29898
|
}
|
|
29043
29899
|
if (!res.ok) {
|
|
29044
|
-
const
|
|
29045
|
-
if (res.status === 404) throw new RouteMissingError(
|
|
29046
|
-
if (res.status >= 500 || res.status === 408 || res.status === 429) throw new TransientStoreError(
|
|
29047
|
-
throw new PermanentStoreError(
|
|
29900
|
+
const message2 = `run store ${path} HTTP ${res.status}${await errorSuffix(res)}`;
|
|
29901
|
+
if (res.status === 404) throw new RouteMissingError(message2);
|
|
29902
|
+
if (res.status >= 500 || res.status === 408 || res.status === 429) throw new TransientStoreError(message2);
|
|
29903
|
+
throw new PermanentStoreError(message2);
|
|
29048
29904
|
}
|
|
29049
29905
|
const data = await res.json().catch(() => null);
|
|
29050
29906
|
if (typeof data !== "object" || data === null)
|
|
@@ -29614,7 +30470,7 @@ function createLedgerWriteThrough(opts) {
|
|
|
29614
30470
|
* no record at all was killed before its conversation was stored and
|
|
29615
30471
|
* closes `interrupted`. */
|
|
29616
30472
|
async seed(messages, budgetMs) {
|
|
29617
|
-
const turns = messages.map((
|
|
30473
|
+
const turns = messages.map((message2, idx) => ({ idx, message: message2 }));
|
|
29618
30474
|
try {
|
|
29619
30475
|
const seeded = await ledger.seed(this.runId, gen, turns);
|
|
29620
30476
|
if (!seeded.ok) {
|
|
@@ -29644,7 +30500,7 @@ function createLedgerWriteThrough(opts) {
|
|
|
29644
30500
|
}
|
|
29645
30501
|
async step(report2) {
|
|
29646
30502
|
if (this.detached) return;
|
|
29647
|
-
const turns = report2.turns.map((
|
|
30503
|
+
const turns = report2.turns.map((message2, i) => ({ idx: report2.firstIdx + i, message: message2 }));
|
|
29648
30504
|
const record = {
|
|
29649
30505
|
step: ++this.stepNo,
|
|
29650
30506
|
seq: this.lastSeq,
|
|
@@ -29809,9 +30665,9 @@ function createLedgerWriteThrough(opts) {
|
|
|
29809
30665
|
return run2;
|
|
29810
30666
|
},
|
|
29811
30667
|
liveRuns: () => [...live],
|
|
29812
|
-
async pushInbox(runId3,
|
|
30668
|
+
async pushInbox(runId3, message2) {
|
|
29813
30669
|
try {
|
|
29814
|
-
const result = await ledger.pushInbox(runId3,
|
|
30670
|
+
const result = await ledger.pushInbox(runId3, message2);
|
|
29815
30671
|
if (result.ok && result.seq !== void 0) return result.seq;
|
|
29816
30672
|
warn(`[ledger] inbox push refused for run ${runId3}: no live row \u2014 the follow-up rides in memory only`);
|
|
29817
30673
|
return void 0;
|
|
@@ -31352,8 +32208,8 @@ function createSlackApp(deps) {
|
|
|
31352
32208
|
}
|
|
31353
32209
|
);
|
|
31354
32210
|
});
|
|
31355
|
-
app.message(async ({ message, client }) => {
|
|
31356
|
-
const m =
|
|
32211
|
+
app.message(async ({ message: message2, client }) => {
|
|
32212
|
+
const m = message2;
|
|
31357
32213
|
if (classifyMessage(m) === "skip") return;
|
|
31358
32214
|
botUserId ??= (await client.auth.test()).user_id ?? void 0;
|
|
31359
32215
|
const decision = classifyMessage(m, botUserId);
|
|
@@ -32042,8 +32898,8 @@ function toIncomingMessage2(identity2, args) {
|
|
|
32042
32898
|
function ok(id, result) {
|
|
32043
32899
|
return { jsonrpc: "2.0", id, result };
|
|
32044
32900
|
}
|
|
32045
|
-
function err(id, code,
|
|
32046
|
-
return { jsonrpc: "2.0", id, error: data ? { code, message, data } : { code, message } };
|
|
32901
|
+
function err(id, code, message2, data) {
|
|
32902
|
+
return { jsonrpc: "2.0", id, error: data ? { code, message: message2, data } : { code, message: message2 } };
|
|
32047
32903
|
}
|
|
32048
32904
|
function readId(msg) {
|
|
32049
32905
|
const id = msg.id;
|
|
@@ -32999,7 +33855,7 @@ function loadWebAssets(distDir) {
|
|
|
32999
33855
|
const full = join13(assetsDir, name);
|
|
33000
33856
|
if (statSync3(full).isFile()) files.set(`/assets/${name}`, readFileSync16(full));
|
|
33001
33857
|
}
|
|
33002
|
-
const
|
|
33858
|
+
const serve2 = (req, res) => {
|
|
33003
33859
|
const path = (req.url ?? "/").split("?")[0];
|
|
33004
33860
|
if (!path.startsWith("/assets/")) return false;
|
|
33005
33861
|
const method = (req.method ?? "GET").toUpperCase();
|
|
@@ -33023,7 +33879,7 @@ function loadWebAssets(distDir) {
|
|
|
33023
33879
|
else res.end(body);
|
|
33024
33880
|
return true;
|
|
33025
33881
|
};
|
|
33026
|
-
return { entry, serve };
|
|
33882
|
+
return { entry, serve: serve2 };
|
|
33027
33883
|
}
|
|
33028
33884
|
var CONTENT_TYPES, WEB_DIST_DIR;
|
|
33029
33885
|
var init_webAssets = __esm({
|
|
@@ -33227,6 +34083,7 @@ function createDeliveryViewHandler(deps, shell) {
|
|
|
33227
34083
|
}
|
|
33228
34084
|
const weeksParam = url.searchParams.get("weeks");
|
|
33229
34085
|
const sinceParam = url.searchParams.get("since");
|
|
34086
|
+
const fresh = url.searchParams.get("fresh") === "1";
|
|
33230
34087
|
const runs = async (range) => {
|
|
33231
34088
|
if (!deps.runs) return [];
|
|
33232
34089
|
const page2 = await deps.runs.listRuns({
|
|
@@ -33240,6 +34097,7 @@ function createDeliveryViewHandler(deps, shell) {
|
|
|
33240
34097
|
deps.service.report(repo, {
|
|
33241
34098
|
...weeksParam !== null ? { weeks: Number(weeksParam) } : {},
|
|
33242
34099
|
...sinceParam !== null ? { since: sinceParam } : {},
|
|
34100
|
+
...fresh ? { fresh } : {},
|
|
33243
34101
|
runs
|
|
33244
34102
|
}).then((report2) => {
|
|
33245
34103
|
if (route2.kind === "json") {
|
|
@@ -33623,14 +34481,14 @@ function createMcpConnectViewHandler(deps) {
|
|
|
33623
34481
|
async function complete(svc, nonce, identity2, token, res) {
|
|
33624
34482
|
const { decision, verified, toolCount, warning, server } = await svc.completeTicket(nonce, identity2, token);
|
|
33625
34483
|
if (!decision.ok) {
|
|
33626
|
-
const
|
|
34484
|
+
const message2 = refusalMessage(decision.refusal);
|
|
33627
34485
|
if (decision.refusal.kind === "bad_token" && server)
|
|
33628
|
-
return page(res, 400, "Token not accepted", `<p class="err">${esc(
|
|
34486
|
+
return page(res, 400, "Token not accepted", `<p class="err">${esc(message2)}</p>${entryForm(server, nonce)}`);
|
|
33629
34487
|
return page(
|
|
33630
34488
|
res,
|
|
33631
34489
|
statusFor(decision.refusal.kind),
|
|
33632
34490
|
"Connect link unavailable",
|
|
33633
|
-
`<p class="err">${esc(
|
|
34491
|
+
`<p class="err">${esc(message2)}</p>`
|
|
33634
34492
|
);
|
|
33635
34493
|
}
|
|
33636
34494
|
if (verified === false) {
|
|
@@ -33646,15 +34504,15 @@ async function complete(svc, nonce, identity2, token, res) {
|
|
|
33646
34504
|
async function start(svc, nonce, identity2, res) {
|
|
33647
34505
|
const result = await svc.startOAuth(nonce, identity2);
|
|
33648
34506
|
if (!result.ok) {
|
|
33649
|
-
const
|
|
34507
|
+
const message2 = refusalMessage(result.refusal);
|
|
33650
34508
|
if (result.refusal.kind === "oauth_failed" && result.server)
|
|
33651
34509
|
return page(
|
|
33652
34510
|
res,
|
|
33653
34511
|
502,
|
|
33654
34512
|
"Sign-in could not start",
|
|
33655
|
-
`<p class="err">${esc(
|
|
34513
|
+
`<p class="err">${esc(message2)}</p><p>Nothing was stored.</p>${entryForm(result.server, nonce)}`
|
|
33656
34514
|
);
|
|
33657
|
-
return page(res, statusFor(result.refusal.kind), "Connect link unavailable", `<p class="err">${esc(
|
|
34515
|
+
return page(res, statusFor(result.refusal.kind), "Connect link unavailable", `<p class="err">${esc(message2)}</p>`);
|
|
33658
34516
|
}
|
|
33659
34517
|
const host = hostOf(result.redirectUrl);
|
|
33660
34518
|
page(
|
|
@@ -33688,13 +34546,13 @@ function callback(svc, params, identity2, res) {
|
|
|
33688
34546
|
}).then((result) => {
|
|
33689
34547
|
if (!result.ok) {
|
|
33690
34548
|
const refusal = result.refusal ?? { kind: "not_found" };
|
|
33691
|
-
const
|
|
34549
|
+
const message2 = refusalMessage(refusal);
|
|
33692
34550
|
const retry = result.server && refusal.kind === "oauth_failed" ? `<p>Nothing was stored. Open the connect link again to retry.</p>` : "";
|
|
33693
34551
|
return page(
|
|
33694
34552
|
res,
|
|
33695
34553
|
refusal.kind === "oauth_failed" ? 502 : statusFor(refusal.kind),
|
|
33696
34554
|
"Sign-in did not complete",
|
|
33697
|
-
`<p class="err">${esc(
|
|
34555
|
+
`<p class="err">${esc(message2)}</p>${retry}`
|
|
33698
34556
|
);
|
|
33699
34557
|
}
|
|
33700
34558
|
return connected(res, result.server, result.toolCount, result.warning);
|
|
@@ -33893,19 +34751,19 @@ var init_processMetrics = __esm({
|
|
|
33893
34751
|
function hasData(part) {
|
|
33894
34752
|
return (part.type === "image" || part.type === "document") && typeof part.data === "string";
|
|
33895
34753
|
}
|
|
33896
|
-
function turnRows(idx,
|
|
34754
|
+
function turnRows(idx, message2, opts = {}) {
|
|
33897
34755
|
const partBytes = opts.partBytes ?? TRANSCRIPT_PART_BYTES;
|
|
33898
34756
|
const refBytes = opts.attachmentRefBytes ?? ATTACHMENT_REF_BYTES;
|
|
33899
34757
|
const rows = [];
|
|
33900
34758
|
const attachments = [];
|
|
33901
|
-
|
|
34759
|
+
message2.content.forEach((part, i) => {
|
|
33902
34760
|
let stored = part;
|
|
33903
34761
|
if (hasData(part) && part.data.length > refBytes) {
|
|
33904
34762
|
const ref = attachmentRef(idx, i);
|
|
33905
34763
|
attachments.push({ ref, mediaType: part.mediaType, data: part.data });
|
|
33906
34764
|
stored = { ...part, data: "", dataRef: ref };
|
|
33907
34765
|
}
|
|
33908
|
-
const json = JSON.stringify({ role:
|
|
34766
|
+
const json = JSON.stringify({ role: message2.role, part: stored });
|
|
33909
34767
|
const bytes = utf8ByteLength(json);
|
|
33910
34768
|
if (bytes > partBytes) {
|
|
33911
34769
|
throw new Error(`transcript: part ${i} of turn ${idx} is ${bytes} bytes, over the ${partBytes} row budget`);
|
|
@@ -34114,9 +34972,9 @@ var init_runLedgerWorker = __esm({
|
|
|
34114
34972
|
this.checkIds(runId3, gen);
|
|
34115
34973
|
return this.fenceResult(await this.post("/runs/state", { storeKey: this.opts.storeKey, runId: runId3, gen, state }));
|
|
34116
34974
|
}
|
|
34117
|
-
async pushInbox(runId3,
|
|
34975
|
+
async pushInbox(runId3, message2) {
|
|
34118
34976
|
this.checkIds(runId3);
|
|
34119
|
-
const r = await this.post("/runs/inbox", { storeKey: this.opts.storeKey, runId: runId3, message });
|
|
34977
|
+
const r = await this.post("/runs/inbox", { storeKey: this.opts.storeKey, runId: runId3, message: message2 });
|
|
34120
34978
|
return { ok: r.data.ok === true, ...typeof r.data.seq === "number" ? { seq: r.data.seq } : {} };
|
|
34121
34979
|
}
|
|
34122
34980
|
async readInbox(runId3, afterSeq) {
|
|
@@ -34503,7 +35361,7 @@ var init_resume = __esm({
|
|
|
34503
35361
|
"submit_handoff",
|
|
34504
35362
|
"submit_dispositions"
|
|
34505
35363
|
]);
|
|
34506
|
-
toolUsesOf = (
|
|
35364
|
+
toolUsesOf = (message2) => message2?.role === "assistant" ? message2.content.filter((p) => p.type === "tool_use") : [];
|
|
34507
35365
|
}
|
|
34508
35366
|
});
|
|
34509
35367
|
|
|
@@ -35196,7 +36054,16 @@ async function runBot() {
|
|
|
35196
36054
|
};
|
|
35197
36055
|
const runsService = createRunsService({ registry: defaultRunRegistry, store: runStore, ledger: ledgerClient });
|
|
35198
36056
|
const scheduleStore = buildScheduleStore(config.config.schedules, processSecrets, (m) => console.warn(`[schedules] ${m}`)) ?? new NullScheduleStore();
|
|
35199
|
-
const
|
|
36057
|
+
const deliveryWarn = (m) => console.warn(`[delivery] ${m}`);
|
|
36058
|
+
const deliveryConfig = parseDeliveryConfig(config.config.delivery);
|
|
36059
|
+
const delivery = capabilities.github ? deliveryFromConfig(deliveryConfig, {
|
|
36060
|
+
snapshots: buildDeliverySnapshotStore(config.config, processSecrets, deliveryWarn),
|
|
36061
|
+
warn: deliveryWarn
|
|
36062
|
+
}) : void 0;
|
|
36063
|
+
const deliveryService = delivery?.service ?? new NullDeliveryService();
|
|
36064
|
+
const deliveryEveryMinutes = deliveryConfig?.snapshot.everyMinutes ?? SNAPSHOT_EVERY_MINUTES.default;
|
|
36065
|
+
if (delivery && deliveryService.repos().length > 0)
|
|
36066
|
+
delivery.source.startRefreshLoop({ repos: deliveryService.repos(), everyMinutes: deliveryEveryMinutes });
|
|
35200
36067
|
const commands = buildCoreCommands(config, runStore, {
|
|
35201
36068
|
registry: defaultRunRegistry,
|
|
35202
36069
|
secrets: processSecrets,
|
|
@@ -35254,7 +36121,7 @@ async function runBot() {
|
|
|
35254
36121
|
const costsView = createCostsViewHandler(costsService, shell);
|
|
35255
36122
|
const costsState = capabilities.costs ? `GET /costs (${costsService.groups().join(",")}; LLM ${anthropicAdminKey ? "on" : "off"})` : costsCfg ? `GET /costs (503 \u2014 ${costsCfg.cloudflareTokenEnv} not set)` : "GET /costs (503 \u2014 no costs config)";
|
|
35256
36123
|
const deliveryView = createDeliveryViewHandler({ service: deliveryService, runs: runsService }, shell);
|
|
35257
|
-
const deliveryState = !capabilities.github ? "GET /delivery (503 \u2014 no GitHub credential)" : deliveryService.repos().length === 0 ? "GET /delivery (503 \u2014 no delivery.repos)" : `GET /delivery (${deliveryService.repos().join(",")})`;
|
|
36124
|
+
const deliveryState = !capabilities.github ? "GET /delivery (503 \u2014 no GitHub credential)" : deliveryService.repos().length === 0 ? "GET /delivery (503 \u2014 no delivery.repos)" : `GET /delivery (${deliveryService.repos().join(",")}; snapshot every ${deliveryEveryMinutes} min)`;
|
|
35258
36125
|
const tokenCount = Object.keys(auth.tokens).length;
|
|
35259
36126
|
const liveViewState = process.env.PUBLIC_BASE_URL ? "GET /runs (index) + /runs/:id (live view)" : "GET /runs (index) + live view (no PUBLIC_BASE_URL \u2014 per-run links omitted)";
|
|
35260
36127
|
const accessConfig = parseAccessConfig(publicEnv());
|
|
@@ -35580,6 +36447,7 @@ var init_index = __esm({
|
|
|
35580
36447
|
init_costsView();
|
|
35581
36448
|
init_deliveryView();
|
|
35582
36449
|
init_delivery();
|
|
36450
|
+
init_deliverySnapshotStore();
|
|
35583
36451
|
init_costs();
|
|
35584
36452
|
init_residentAdmin();
|
|
35585
36453
|
init_residentFleet();
|
|
@@ -35787,8 +36655,8 @@ function exitCodeFor(error) {
|
|
|
35787
36655
|
if (error === "busy") return 75;
|
|
35788
36656
|
return 1;
|
|
35789
36657
|
}
|
|
35790
|
-
function errorLine(code,
|
|
35791
|
-
return `error (${code}): ${
|
|
36658
|
+
function errorLine(code, message2) {
|
|
36659
|
+
return `error (${code}): ${message2}`;
|
|
35792
36660
|
}
|
|
35793
36661
|
async function runCommand(commands, parsed, caller, opts = {}) {
|
|
35794
36662
|
const cmd = commands.get(parsed.id);
|