create-harness-vibe-coding 0.8.19 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/README-CN.md +4 -2
- package/README.md +23 -4
- package/package.json +17 -2
- package/src/generator.js +19 -6
- package/src/index.js +531 -38
- package/src/prompts.js +4 -4
- package/src/ui/dist/assets/AgentsRoute-BGGs90wH.js +7 -0
- package/src/ui/dist/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
- package/src/ui/dist/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
- package/src/ui/dist/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
- package/src/ui/dist/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
- package/src/ui/dist/assets/Combination-DhBLEmof.js +42 -0
- package/src/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/src/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/src/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/src/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/src/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/src/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/src/ui/dist/assets/RolesRoute-DnodCSz0.js +2 -0
- package/src/ui/dist/assets/RuntimePicker-CucD8TGn.js +7 -0
- package/src/ui/dist/assets/SettingsRoute-DquMWjac.js +2 -0
- package/src/ui/dist/assets/TaskList-Bxc0Uktx.js +7 -0
- package/src/ui/dist/assets/TerminalDrawer-CDusYltc.js +36 -0
- package/src/ui/dist/assets/WorkflowRoute-BN8yHmUs.css +1 -0
- package/src/ui/dist/assets/WorkflowRoute-D-0wVDpY.js +334 -0
- package/src/ui/dist/assets/abnfDiagram-VRR7QNED-zkRKkaxO.js +2 -0
- package/src/ui/dist/assets/apl-B4CMkyY2.js +2 -0
- package/src/ui/dist/assets/ar-SA-G6X2FPQ2-BiHaArx5.js +11 -0
- package/src/ui/dist/assets/arc-CBnLtOFO.js +2 -0
- package/src/ui/dist/assets/architectureDiagram-ZJ3FMSHR-DWXRXsh1.js +37 -0
- package/src/ui/dist/assets/asciiarmor-Df11BRmG.js +2 -0
- package/src/ui/dist/assets/asn1-EdZsLKOL.js +2 -0
- package/src/ui/dist/assets/asterisk-B-8jnY81.js +2 -0
- package/src/ui/dist/assets/az-AZ-76LH7QW2-CiT05voO.js +2 -0
- package/src/ui/dist/assets/bg-BG-XCXSNQG7-L-UM9tNf.js +6 -0
- package/src/ui/dist/assets/blockDiagram-677ZJIJ3-BIyh3Bry.js +133 -0
- package/src/ui/dist/assets/bn-BD-2XOGV67Q-NdgbA0bC.js +6 -0
- package/src/ui/dist/assets/brainfuck-C4LP7Hcl.js +2 -0
- package/src/ui/dist/assets/c4Diagram-LMCZKHZV-CA54vWWM.js +11 -0
- package/src/ui/dist/assets/ca-ES-6MX7JW3Y-BKZZsQ5J.js +9 -0
- package/src/ui/dist/assets/channel-Da_-zcAu.js +2 -0
- package/src/ui/dist/assets/chunk-2Q5K7J3B-DE4cxr1v.js +2 -0
- package/src/ui/dist/assets/chunk-32BRIVSS-i7FwbEU9.js +2 -0
- package/src/ui/dist/assets/chunk-5VM5RSS4-BhIcOYSu.js +16 -0
- package/src/ui/dist/assets/chunk-EX3LRPZG-Ci9zZRIs.js +232 -0
- package/src/ui/dist/assets/chunk-JWPE2WC7-BFdkcz-G.js +2 -0
- package/src/ui/dist/assets/chunk-MOJQB5TN-Dzmapl_S.js +89 -0
- package/src/ui/dist/assets/chunk-RYQCIY6F-RTmp7FOy.js +2 -0
- package/src/ui/dist/assets/chunk-V7JOEXUC-DInU3v3D.js +207 -0
- package/src/ui/dist/assets/chunk-VR4S4FIN-BHoyGBQO.js +2 -0
- package/src/ui/dist/assets/chunk-XXDRQBXY-DfeLZNZx.js +2 -0
- package/src/ui/dist/assets/classDiagram-OUVF2IWQ-FKbUS0bu.js +2 -0
- package/src/ui/dist/assets/classDiagram-v2-EOCWNBFH-FKbUS0bu.js +2 -0
- package/src/ui/dist/assets/clike-B9uivgTg.js +2 -0
- package/src/ui/dist/assets/clojure-BMjYHr_A.js +2 -0
- package/src/ui/dist/assets/cmake-BQqOBYOt.js +2 -0
- package/src/ui/dist/assets/cobol-CWcv1MsR.js +2 -0
- package/src/ui/dist/assets/coffeescript-S37ZYGWr.js +2 -0
- package/src/ui/dist/assets/commonlisp-DBKNyK5s.js +2 -0
- package/src/ui/dist/assets/cose-bilkent-JH36ORCC-_5PUJ615.js +2 -0
- package/src/ui/dist/assets/crystal-SjHAIU92.js +2 -0
- package/src/ui/dist/assets/cs-CZ-2BRQDIVT-DnkfnhDU.js +12 -0
- package/src/ui/dist/assets/css-BnMrqG3P.js +2 -0
- package/src/ui/dist/assets/cynefin-VYW2F7L2-CmkcFv-b.js +179 -0
- package/src/ui/dist/assets/cynefinDiagram-TSTJHNR4-D72VZn8H.js +63 -0
- package/src/ui/dist/assets/cypher-C_CwsFkJ.js +2 -0
- package/src/ui/dist/assets/cytoscape.esm-DTSO7Bv0.js +332 -0
- package/src/ui/dist/assets/d-pRatUO7H.js +2 -0
- package/src/ui/dist/assets/da-DK-5WZEPLOC-C54tQUgd.js +6 -0
- package/src/ui/dist/assets/dagre-VKFMJZFB-0BsAkrmo.js +5 -0
- package/src/ui/dist/assets/de-DE-XR44H4JA-DGfZlR10.js +9 -0
- package/src/ui/dist/assets/defaultLocale-DX6XiGOO.js +2 -0
- package/src/ui/dist/assets/diagram-FQU43EPY-C1ZJDOca.js +4 -0
- package/src/ui/dist/assets/diagram-G47NLZAW-D3pr3FSP.js +25 -0
- package/src/ui/dist/assets/diagram-NH7WQ7WH-Bwry0NV-.js +25 -0
- package/src/ui/dist/assets/diagram-OA4YK3LP-L6g09cmV.js +31 -0
- package/src/ui/dist/assets/diagram-WEI45ONY-Bh1puYVX.js +42 -0
- package/src/ui/dist/assets/diff-DbItnlRl.js +2 -0
- package/src/ui/dist/assets/directory-open-01563666-DWU9wJ6I.js +2 -0
- package/src/ui/dist/assets/directory-open-4ed118d0-CunoC1EB.js +2 -0
- package/src/ui/dist/assets/dockerfile-BKs6k2Af.js +2 -0
- package/src/ui/dist/assets/dtd-DF_7sFjM.js +2 -0
- package/src/ui/dist/assets/dylan-DwRh75JA.js +2 -0
- package/src/ui/dist/assets/ebnf-CDyGwa7X.js +2 -0
- package/src/ui/dist/assets/ebnfDiagram-CCIWWBDH-BC_mBRR5.js +2 -0
- package/src/ui/dist/assets/ecl-Cabwm37j.js +2 -0
- package/src/ui/dist/assets/eiffel-CnydiIhH.js +2 -0
- package/src/ui/dist/assets/el-GR-BZB4AONW-DsnwWweL.js +11 -0
- package/src/ui/dist/assets/elm-vLlmbW-K.js +2 -0
- package/src/ui/dist/assets/erDiagram-Q63AITRT-Bkxam36l.js +86 -0
- package/src/ui/dist/assets/erlang-BNw1qcRV.js +2 -0
- package/src/ui/dist/assets/es-ES-U4NZUMDT-CRxBcQgC.js +10 -0
- package/src/ui/dist/assets/eu-ES-A7QVB2H4-CTd_E7YR.js +12 -0
- package/src/ui/dist/assets/excalidraw-default-bMWIgNCy.svg +1 -0
- package/src/ui/dist/assets/fa-IR-HGAKTJCU-DO56k7eG.js +9 -0
- package/src/ui/dist/assets/factor-kuTfRLto.js +2 -0
- package/src/ui/dist/assets/fcl-Kvtd6kyn.js +2 -0
- package/src/ui/dist/assets/fi-FI-Z5N7JZ37-DEDCF9WB.js +7 -0
- package/src/ui/dist/assets/file-open-002ab408-DIuFHtCF.js +2 -0
- package/src/ui/dist/assets/file-open-7c801643-684qeFg4.js +2 -0
- package/src/ui/dist/assets/file-save-3189631c-C1wFhQhH.js +2 -0
- package/src/ui/dist/assets/file-save-745eba88-Bb9F9Kg7.js +2 -0
- package/src/ui/dist/assets/flowDiagram-23GEKE2U-C3SAEao7.js +157 -0
- package/src/ui/dist/assets/forth-Ffai-XNe.js +2 -0
- package/src/ui/dist/assets/fortran-DYz_wnZ1.js +2 -0
- package/src/ui/dist/assets/fr-FR-RHASNOE6-DE2nPyDt.js +10 -0
- package/src/ui/dist/assets/ganttDiagram-NO4QXBWP-U-J_Xi-_.js +293 -0
- package/src/ui/dist/assets/gas-Bneqetm1.js +2 -0
- package/src/ui/dist/assets/gherkin-heZmZLOM.js +2 -0
- package/src/ui/dist/assets/gitGraphDiagram-IHSO6WYX-BADVbD-a.js +107 -0
- package/src/ui/dist/assets/gl-ES-HMX3MZ6V-mCqVgQHC.js +11 -0
- package/src/ui/dist/assets/graph-C9eacEi8.js +2 -0
- package/src/ui/dist/assets/groovy-D9Dt4D0W.js +2 -0
- package/src/ui/dist/assets/haskell-Cw1EW3IL.js +2 -0
- package/src/ui/dist/assets/haxe-H-WmDvRZ.js +2 -0
- package/src/ui/dist/assets/he-IL-6SHJWFNN-KnaLrCzw.js +11 -0
- package/src/ui/dist/assets/hi-IN-IWLTKZ5I-wuqiaaWt.js +5 -0
- package/src/ui/dist/assets/http-DBlCnlav.js +2 -0
- package/src/ui/dist/assets/hu-HU-A5ZG7DT2-DLg_zm22.js +8 -0
- package/src/ui/dist/assets/id-ID-SAP4L64H-MB2mXqcR.js +11 -0
- package/src/ui/dist/assets/idl-BEugSyMb.js +2 -0
- package/src/ui/dist/assets/image-blob-reduce.esm-HwCm7IZ0.js +8 -0
- package/src/ui/dist/assets/index-39SJtrt0.js +2 -0
- package/src/ui/dist/assets/index-BQ0LIrW-.js +2 -0
- package/src/ui/dist/assets/index-BcAUh2Nm.css +1 -0
- package/src/ui/dist/assets/index-BcThOK-i.js +331 -0
- package/src/ui/dist/assets/index-BnxV3k_S.js +3 -0
- package/src/ui/dist/assets/index-C7MZBHbT.js +117 -0
- package/src/ui/dist/assets/index-CCvKI2rM.js +2 -0
- package/src/ui/dist/assets/index-CZvmcCab.js +8 -0
- package/src/ui/dist/assets/index-Cp3hLKNl.js +2 -0
- package/src/ui/dist/assets/index-D7ayFxcx.js +2 -0
- package/src/ui/dist/assets/index-DAYxSQGU.js +2 -0
- package/src/ui/dist/assets/index-DD-HeMV0.css +1 -0
- package/src/ui/dist/assets/index-DPMxd3Qn.js +2 -0
- package/src/ui/dist/assets/index-DSe2jx3k.js +4 -0
- package/src/ui/dist/assets/index-DUirCkgW.js +2 -0
- package/src/ui/dist/assets/index-DaKPQ2hN.js +159 -0
- package/src/ui/dist/assets/index-DzpuR0Jg.js +2 -0
- package/src/ui/dist/assets/index-POndwsCI.js +2 -0
- package/src/ui/dist/assets/index-R8NM9I_9.js +2 -0
- package/src/ui/dist/assets/index-TCDuDhBj.js +2 -0
- package/src/ui/dist/assets/index-TckzASdM.js +2 -0
- package/src/ui/dist/assets/index-Yi5ytFFr.js +2 -0
- package/src/ui/dist/assets/infoDiagram-FWYZ7A6U-CiGBlFqH.js +3 -0
- package/src/ui/dist/assets/init-Gi6I4Gst.js +2 -0
- package/src/ui/dist/assets/ishikawaDiagram-FXEZZL3T-B1aheRbz.js +71 -0
- package/src/ui/dist/assets/it-IT-JPQ66NNP-DT3HSU7X.js +12 -0
- package/src/ui/dist/assets/ja-JP-DBVTYXUO-CsfJjjWt.js +9 -0
- package/src/ui/dist/assets/javascript-iXu5QeM3.js +2 -0
- package/src/ui/dist/assets/journeyDiagram-5HDEW3XC-DtnJPxub.js +140 -0
- package/src/ui/dist/assets/julia-DuME0IfC.js +2 -0
- package/src/ui/dist/assets/kaa-6HZHGXH3-DQz-1-Gn.js +2 -0
- package/src/ui/dist/assets/kab-KAB-ZGHBKWFO-CaH-LSoK.js +9 -0
- package/src/ui/dist/assets/kanban-definition-HUTT4EX6-CZatSm3e.js +90 -0
- package/src/ui/dist/assets/katex-C5jXJg4s.js +258 -0
- package/src/ui/dist/assets/kk-KZ-P5N5QNE5-BMXmcm55.js +2 -0
- package/src/ui/dist/assets/km-KH-HSX4SM5Z-ZeoJNBpN.js +12 -0
- package/src/ui/dist/assets/ko-KR-MTYHY66A-BeaLRKph.js +10 -0
- package/src/ui/dist/assets/ku-TR-6OUDTVRD-B_28KrkR.js +10 -0
- package/src/ui/dist/assets/layout-DEXfKzaS.js +2 -0
- package/src/ui/dist/assets/linear-CpEDnQRC.js +2 -0
- package/src/ui/dist/assets/livescript-BwQOo05w.js +2 -0
- package/src/ui/dist/assets/lt-LT-XHIRWOB4-BxDcnUhp.js +4 -0
- package/src/ui/dist/assets/lua-VAEuO923.js +2 -0
- package/src/ui/dist/assets/lv-LV-5QDEKY6T-DpKDl1_y.js +8 -0
- package/src/ui/dist/assets/map-Czzmt4hB.js +2 -0
- package/src/ui/dist/assets/mathematica-DTrFuWx2.js +2 -0
- package/src/ui/dist/assets/mbox-CNhZ1qSd.js +2 -0
- package/src/ui/dist/assets/mermaidLoader-CBO31t0J.js +305 -0
- package/src/ui/dist/assets/mermaidLoader-CEK31ho9.css +1 -0
- package/src/ui/dist/assets/mindmap-definition-LN4V7U3C-CQ0TccEr.js +97 -0
- package/src/ui/dist/assets/mirc-CjQqDB4T.js +2 -0
- package/src/ui/dist/assets/mllike-CXdrOF99.js +2 -0
- package/src/ui/dist/assets/modelica-Dc1JOy9r.js +2 -0
- package/src/ui/dist/assets/mr-IN-CRQNXWMA-BKCZT58p.js +14 -0
- package/src/ui/dist/assets/mscgen-BA5vi2Kp.js +2 -0
- package/src/ui/dist/assets/mumps-BT43cFF4.js +2 -0
- package/src/ui/dist/assets/my-MM-5M5IBNSE-D34k0G9T.js +2 -0
- package/src/ui/dist/assets/nb-NO-T6EIAALU-DXr_KW8J.js +11 -0
- package/src/ui/dist/assets/nginx-DdIZxoE0.js +2 -0
- package/src/ui/dist/assets/nl-NL-IS3SIHDZ-C1L0aVDR.js +9 -0
- package/src/ui/dist/assets/nn-NO-6E72VCQL-CLWVSxbZ.js +9 -0
- package/src/ui/dist/assets/nsis-LdVXkNf5.js +2 -0
- package/src/ui/dist/assets/ntriples-BfvgReVJ.js +2 -0
- package/src/ui/dist/assets/oc-FR-POXYY2M6-nf8_J3eR.js +9 -0
- package/src/ui/dist/assets/octave-Ck1zUtKM.js +2 -0
- package/src/ui/dist/assets/ordinal-Cboi1Yqb.js +2 -0
- package/src/ui/dist/assets/oz-BzwKVEFT.js +2 -0
- package/src/ui/dist/assets/pa-IN-N4M65BXN-CAMJ-xd6.js +5 -0
- package/src/ui/dist/assets/pascal--L3eBynH.js +2 -0
- package/src/ui/dist/assets/pegDiagram-2B236MQR-Bj2RcmRd.js +2 -0
- package/src/ui/dist/assets/percentages-BXMCSKIN-s9yWFdr6.js +160 -0
- package/src/ui/dist/assets/perl-CdXCOZ3F.js +2 -0
- package/src/ui/dist/assets/pica-BGv_AhAB.js +8 -0
- package/src/ui/dist/assets/pieDiagram-ENE6RG2P-obpzz8dC.js +40 -0
- package/src/ui/dist/assets/pig-CevX1Tat.js +2 -0
- package/src/ui/dist/assets/pl-PL-T2D74RX3-DKJ5H85v.js +10 -0
- package/src/ui/dist/assets/powershell-CFHJl5sT.js +2 -0
- package/src/ui/dist/assets/properties-C78fOPTZ.js +2 -0
- package/src/ui/dist/assets/protobuf-ChK-085T.js +2 -0
- package/src/ui/dist/assets/{proxy-D0vUbds5.js → proxy-BSmwef4H.js} +2 -2
- package/src/ui/dist/assets/pt-BR-5N22H2LF-B5kow-kN.js +10 -0
- package/src/ui/dist/assets/pt-PT-UZXXM6DQ-B2G34fso.js +10 -0
- package/src/ui/dist/assets/pug-DeIclll2.js +2 -0
- package/src/ui/dist/assets/puppet-DMA9R1ak.js +2 -0
- package/src/ui/dist/assets/python-BuPzkPfP.js +2 -0
- package/src/ui/dist/assets/q-pXgVlZs6.js +2 -0
- package/src/ui/dist/assets/quadrantDiagram-ABIIQ3AL-Cl-T7NkJ.js +8 -0
- package/src/ui/dist/assets/r-B6wPVr8A.js +2 -0
- package/src/ui/dist/assets/railroadDiagram-RFXS5EU6-DMq82RHg.js +2 -0
- package/src/ui/dist/assets/{refresh-cw-JNmExijd.js → refresh-cw-CbFd7guV.js} +2 -2
- package/src/ui/dist/assets/requirementDiagram-TGXJPOKE-tGInMDgU.js +85 -0
- package/src/ui/dist/assets/ro-RO-JPDTUUEW-BwLdZW91.js +12 -0
- package/src/ui/dist/assets/roundRect-0PYZxl1G.js +2 -0
- package/src/ui/dist/assets/rpm-CTu-6PCP.js +2 -0
- package/src/ui/dist/assets/ru-RU-B4JR7IUQ-DpdAgIJc.js +10 -0
- package/src/ui/dist/assets/ruby-B2Rjki9n.js +2 -0
- package/src/ui/dist/assets/runtimeBrand-BoKPimsz.js +2 -0
- package/src/ui/dist/assets/sankeyDiagram-HTMAVEWB-C7X-ET4m.js +41 -0
- package/src/ui/dist/assets/sas-B4kiWyti.js +2 -0
- package/src/ui/dist/assets/save-D1CXHwBw.js +12 -0
- package/src/ui/dist/assets/scheme-C41bIUwD.js +2 -0
- package/src/ui/dist/assets/sequenceDiagram-DBY2YBRQ-Bn24i_nY.js +163 -0
- package/src/ui/dist/assets/settings-2-DtSNAAcU.js +22 -0
- package/src/ui/dist/assets/shell-CjFT_Tl9.js +2 -0
- package/src/ui/dist/assets/shield-check-BVbJ8T_N.js +7 -0
- package/src/ui/dist/assets/si-LK-N5RQ5JYF-naJaUy5u.js +2 -0
- package/src/ui/dist/assets/sieve-C3Gn_uJK.js +2 -0
- package/src/ui/dist/assets/simple-mode-GW_nhZxv.js +2 -0
- package/src/ui/dist/assets/sizeCapture-X5ZJPWSS-DAQHfm82.js +2 -0
- package/src/ui/dist/assets/sk-SK-C5VTKIMK-1NPz1J_d.js +7 -0
- package/src/ui/dist/assets/sl-SI-NN7IZMDC-D8RfmNQw.js +7 -0
- package/src/ui/dist/assets/smalltalk-CnHTOXQT.js +2 -0
- package/src/ui/dist/assets/solr-DehyRSwq.js +2 -0
- package/src/ui/dist/assets/sparql-DkYu6x3z.js +2 -0
- package/src/ui/dist/assets/spreadsheet-BCZA_wO0.js +2 -0
- package/src/ui/dist/assets/sql-D0XecflT.js +2 -0
- package/src/ui/dist/assets/stateDiagram-2N3HPSRC-Ck48D1ck.js +2 -0
- package/src/ui/dist/assets/stateDiagram-v2-6OUMAXLB-CdfRCJAJ.js +2 -0
- package/src/ui/dist/assets/stex-C3f8Ysf7.js +2 -0
- package/src/ui/dist/assets/style-C3QI7VPf.css +1 -0
- package/src/ui/dist/assets/stylus-B533Al4x.js +2 -0
- package/src/ui/dist/assets/subset-shared.chunk-eAtLHmbi.js +85 -0
- package/src/ui/dist/assets/subset-worker.chunk-DeHCTnTk.js +2 -0
- package/src/ui/dist/assets/sv-SE-XGPEYMSR-BeOYCU-8.js +11 -0
- package/src/ui/dist/assets/swift-BzpIVaGY.js +2 -0
- package/src/ui/dist/assets/swimlanes-5IMT3BWC-DOy22UjP.js +3 -0
- package/src/ui/dist/assets/swimlanesDiagram-G3AALYLV-sicPbVOg.js +9 -0
- package/src/ui/dist/assets/ta-IN-2NMHFXQM-CtS68WDd.js +10 -0
- package/src/ui/dist/assets/tcl-DVfN8rqt.js +2 -0
- package/src/ui/dist/assets/{terminal-BBQvnOAK.js → terminal-DEby5Y_P.js} +2 -2
- package/src/ui/dist/assets/terminalControl-BkFeDVXo.js +134 -0
- package/src/ui/dist/assets/textile-CnDTJFAw.js +2 -0
- package/src/ui/dist/assets/th-TH-HPSO5L25-DCHY9-Co.js +3 -0
- package/src/ui/dist/assets/tiddlywiki-DO-Gjzrf.js +2 -0
- package/src/ui/dist/assets/tiki-DGYXhP31.js +2 -0
- package/src/ui/dist/assets/timeline-definition-FHXFAJF6-DVkG72qO.js +121 -0
- package/src/ui/dist/assets/toml-Bm5Em-hy.js +2 -0
- package/src/ui/dist/assets/tr-TR-DEFEU3FU-y5-vjTv8.js +8 -0
- package/src/ui/dist/assets/troff-wAsdV37c.js +2 -0
- package/src/ui/dist/assets/ttcn-CfJYG6tj.js +2 -0
- package/src/ui/dist/assets/ttcn-cfg-B9xdYoR4.js +2 -0
- package/src/ui/dist/assets/turtle-B1tBg_DP.js +2 -0
- package/src/ui/dist/assets/uk-UA-QMV73CPH-BRbR5It6.js +7 -0
- package/src/ui/dist/assets/useReducedMotion-D07XP52Q.js +12 -0
- package/src/ui/dist/assets/vb-CmGdzxic.js +2 -0
- package/src/ui/dist/assets/vbscript-BuJXcnF6.js +2 -0
- package/src/ui/dist/assets/velocity-D8B20fx6.js +2 -0
- package/src/ui/dist/assets/vennDiagram-L72KCM5P-DwMwBlf-.js +35 -0
- package/src/ui/dist/assets/verilog-C6RDOZhf.js +2 -0
- package/src/ui/dist/assets/vhdl-lSbBsy5d.js +2 -0
- package/src/ui/dist/assets/vi-VN-M7AON7JQ-s6wSBv2s.js +6 -0
- package/src/ui/dist/assets/wardleyDiagram-EHGQE667-CNuuvzEg.js +79 -0
- package/src/ui/dist/assets/webidl-ZXfAyPTL.js +2 -0
- package/src/ui/dist/assets/{x-DoIOGAJz.js → x-B84wq78k.js} +2 -2
- package/src/ui/dist/assets/xquery-DzFWVndE.js +2 -0
- package/src/ui/dist/assets/xychartDiagram-FW5EYKEG-dUpZxmn6.js +8 -0
- package/src/ui/dist/assets/yacas-BJ4BC0dw.js +2 -0
- package/src/ui/dist/assets/z80-Hz9HOZM7.js +2 -0
- package/src/ui/dist/assets/zh-CN-LNUGB5OW-Cu_-POQN.js +11 -0
- package/src/ui/dist/assets/zh-HK-E62DVLB3-BCx4W4qZ.js +2 -0
- package/src/ui/dist/assets/zh-TW-RAJ6MFWO-02wx_Mrj.js +10 -0
- package/src/ui/dist/icons/excalidraw.svg +1 -0
- package/src/ui/dist/icons/markdown.svg +1 -0
- package/src/ui/dist/index.html +2 -2
- package/src/ui/package.json +10 -0
- package/src/ui/playwright.config.ts +36 -0
- package/src/ui/pnpm-workspace.yaml +2 -0
- package/src/ui/public/icons/excalidraw.svg +1 -0
- package/src/ui/public/icons/markdown.svg +1 -0
- package/src/ui/tsconfig.json +2 -1
- package/src/ui/vite.config.ts +1 -0
- package/src/wf-ui-server/__tests__/a2a-store.test.mjs +432 -15
- package/src/wf-ui-server/__tests__/action-registry-loader.test.mjs +156 -0
- package/src/wf-ui-server/__tests__/claude-stream-json.test.mjs +397 -0
- package/src/wf-ui-server/__tests__/codex-appserver.test.mjs +392 -0
- package/src/wf-ui-server/__tests__/component-node-api.test.mjs +881 -0
- package/src/wf-ui-server/__tests__/component-node-store.test.mjs +401 -0
- package/src/wf-ui-server/__tests__/control-plane-acceptance.test.mjs +2027 -0
- package/src/wf-ui-server/__tests__/control-plane-cli-smoke.test.mjs +1014 -0
- package/src/wf-ui-server/__tests__/dispatch-lifecycle.test.mjs +330 -0
- package/src/wf-ui-server/__tests__/effort-compatibility-red-092.test.mjs +151 -0
- package/src/wf-ui-server/__tests__/graph-layout-agent-tree.test.mjs +254 -0
- package/src/wf-ui-server/__tests__/graph-layout-tidy.test.mjs +260 -0
- package/src/wf-ui-server/__tests__/graph-layout.test.mjs +84 -0
- package/src/wf-ui-server/__tests__/node-config-api.test.mjs +384 -0
- package/src/wf-ui-server/__tests__/opencode-server.test.mjs +526 -0
- package/src/wf-ui-server/__tests__/peer-capsule.test.mjs +2 -2
- package/src/wf-ui-server/__tests__/pty-adapter.test.mjs +71 -1
- package/src/wf-ui-server/__tests__/runtime-config.test.mjs +3 -3
- package/src/wf-ui-server/__tests__/runtime-detector.test.mjs +21 -0
- package/src/wf-ui-server/__tests__/runtime-review.test.mjs +828 -0
- package/src/wf-ui-server/__tests__/server.integration.test.mjs +1463 -11
- package/src/wf-ui-server/__tests__/session-cleanup.test.mjs +159 -0
- package/src/wf-ui-server/__tests__/session-registry.test.mjs +52 -3
- package/src/wf-ui-server/__tests__/settings.test.mjs +12 -2
- package/src/wf-ui-server/__tests__/spawn-gate.test.mjs +78 -0
- package/src/wf-ui-server/__tests__/task-group-parser.test.mjs +120 -0
- package/src/wf-ui-server/__tests__/task-group-tag.test.mjs +264 -0
- package/src/wf-ui-server/__tests__/task-parser.test.mjs +49 -3
- package/src/wf-ui-server/__tests__/terminal-context-hardening.test.mjs +122 -0
- package/src/wf-ui-server/__tests__/terminal-context.test.mjs +164 -0
- package/src/wf-ui-server/__tests__/terminal-store.test.mjs +4 -4
- package/src/wf-ui-server/__tests__/wf-browser-api.test.mjs +599 -0
- package/src/wf-ui-server/__tests__/wf-browser-store.test.mjs +184 -0
- package/src/wf-ui-server/__tests__/workflow-action-registry.test.mjs +282 -0
- package/src/wf-ui-server/__tests__/workflow-agent-communication.test.mjs +411 -0
- package/src/wf-ui-server/__tests__/workflow-agent-context.test.mjs +323 -0
- package/src/wf-ui-server/__tests__/workflow-agent-cooperation-permissions.test.mjs +318 -0
- package/src/wf-ui-server/__tests__/workflow-agent-messages-structured.test.mjs +458 -0
- package/src/wf-ui-server/__tests__/workflow-agent-routing.test.mjs +434 -0
- package/src/wf-ui-server/__tests__/workflow-agent-runtime.test.mjs +324 -0
- package/src/wf-ui-server/__tests__/workflow-api-integration.test.mjs +263 -0
- package/src/wf-ui-server/__tests__/workflow-api-phase3.test.mjs +1213 -0
- package/src/wf-ui-server/__tests__/workflow-claude-materialize.test.mjs +209 -0
- package/src/wf-ui-server/__tests__/workflow-cli-registry-manuals.test.mjs +173 -0
- package/src/wf-ui-server/__tests__/workflow-cli-surface.test.mjs +176 -0
- package/src/wf-ui-server/__tests__/workflow-codex-resume-id.test.mjs +556 -0
- package/src/wf-ui-server/__tests__/workflow-cooperation-enforcement.test.mjs +553 -0
- package/src/wf-ui-server/__tests__/workflow-depth-resume-dock.test.mjs +846 -0
- package/src/wf-ui-server/__tests__/workflow-display-node.test.mjs +150 -0
- package/src/wf-ui-server/__tests__/workflow-edge-update.test.mjs +296 -0
- package/src/wf-ui-server/__tests__/workflow-file-cache-lock-watch.test.mjs +380 -0
- package/src/wf-ui-server/__tests__/workflow-file-formats.test.mjs +994 -0
- package/src/wf-ui-server/__tests__/workflow-file-node-actions.test.mjs +294 -0
- package/src/wf-ui-server/__tests__/workflow-goal-actions.test.mjs +357 -0
- package/src/wf-ui-server/__tests__/workflow-goal-task-autoclose.test.mjs +256 -0
- package/src/wf-ui-server/__tests__/workflow-graceful-stop.test.mjs +108 -0
- package/src/wf-ui-server/__tests__/workflow-graph-undo.test.mjs +524 -0
- package/src/wf-ui-server/__tests__/workflow-layout.test.mjs +732 -0
- package/src/wf-ui-server/__tests__/workflow-magnetic-topology.test.mjs +222 -0
- package/src/wf-ui-server/__tests__/workflow-markdown-lock.test.mjs +359 -0
- package/src/wf-ui-server/__tests__/workflow-mcp-hub.test.mjs +174 -0
- package/src/wf-ui-server/__tests__/workflow-node-manual-schema.test.mjs +241 -0
- package/src/wf-ui-server/__tests__/workflow-node-runtime.test.mjs +1991 -0
- package/src/wf-ui-server/__tests__/workflow-node-store-utils.test.mjs +125 -0
- package/src/wf-ui-server/__tests__/workflow-registry-drift.test.mjs +296 -0
- package/src/wf-ui-server/__tests__/workflow-resource-handle-four-side.test.mjs +217 -0
- package/src/wf-ui-server/__tests__/workflow-role-profile.test.mjs +234 -0
- package/src/wf-ui-server/__tests__/workflow-set-model.test.mjs +261 -0
- package/src/wf-ui-server/__tests__/workflow-skill-group-context-enabled.test.mjs +131 -0
- package/src/wf-ui-server/__tests__/workflow-skill-group-enable-disable.test.mjs +186 -0
- package/src/wf-ui-server/__tests__/workflow-skills-hub.test.mjs +125 -0
- package/src/wf-ui-server/__tests__/workflow-state-reconcile.test.mjs +139 -0
- package/src/wf-ui-server/__tests__/workflow-subagent-strategy-matrix.test.mjs +529 -0
- package/src/wf-ui-server/__tests__/workflow-team-flow.test.mjs +278 -0
- package/src/wf-ui-server/__tests__/workflow-terminal-control-live.test.mjs +294 -0
- package/src/wf-ui-server/__tests__/workflow-terminal-control.test.mjs +631 -0
- package/src/wf-ui-server/__tests__/workflow-timer-wakeup.test.mjs +318 -0
- package/src/wf-ui-server/__tests__/workflow-unified-resume.test.mjs +537 -0
- package/src/wf-ui-server/__tests__/workspace-api-hardening.test.mjs +187 -0
- package/src/wf-ui-server/__tests__/workspace-api.test.mjs +382 -0
- package/src/wf-ui-server/__tests__/workspace-reveal.test.mjs +138 -0
- package/src/wf-ui-server/__tests__/workspace-store-hardening.test.mjs +255 -0
- package/src/wf-ui-server/__tests__/workspace-store.test.mjs +208 -0
- package/src/wf-ui-server/__tests__/ws-events.integration.test.mjs +52 -25
- package/src/wf-ui-server/__tests__/ws-terminal.integration.test.mjs +12 -6
- package/src/wf-ui-server/__tests__/ws-wf-browser.integration.test.mjs +488 -0
- package/src/wf-ui-server/a2a-store.mjs +3007 -89
- package/src/wf-ui-server/action-registry.mjs +277 -0
- package/src/wf-ui-server/bridge-store.mjs +276 -0
- package/src/wf-ui-server/chat-driver.mjs +220 -0
- package/src/wf-ui-server/chat-store.mjs +109 -0
- package/src/wf-ui-server/claude-transcript-materializer.mjs +235 -0
- package/src/wf-ui-server/codex-update-prompt.mjs +53 -0
- package/src/wf-ui-server/component-node-store.mjs +689 -0
- package/src/wf-ui-server/composition-api.mjs +436 -0
- package/src/wf-ui-server/control-plane-token.mjs +17 -0
- package/src/wf-ui-server/dispatch-contract.mjs +150 -0
- package/src/wf-ui-server/drivers/claude-stream-json.mjs +371 -0
- package/src/wf-ui-server/drivers/codex-appserver.mjs +513 -0
- package/src/wf-ui-server/drivers/opencode-server.mjs +486 -0
- package/src/wf-ui-server/excalidraw-svg.mjs +141 -0
- package/src/wf-ui-server/file-format-adapters.mjs +511 -0
- package/src/wf-ui-server/file-watcher.mjs +215 -0
- package/src/wf-ui-server/graph-layout.mjs +778 -0
- package/src/wf-ui-server/harness-env.mjs +46 -0
- package/src/wf-ui-server/json-store-utils.mjs +48 -0
- package/src/wf-ui-server/model-capability.mjs +773 -0
- package/src/wf-ui-server/node-config-store.mjs +233 -0
- package/src/wf-ui-server/node-store-utils.mjs +88 -0
- package/src/wf-ui-server/peer-capsule.mjs +56 -1
- package/src/wf-ui-server/pty-adapter.mjs +513 -11
- package/src/wf-ui-server/reveal-foreground.mjs +69 -0
- package/src/wf-ui-server/runtime-detector.mjs +52 -6
- package/src/wf-ui-server/server.mjs +5613 -403
- package/src/wf-ui-server/session-cleanup.mjs +363 -0
- package/src/wf-ui-server/session-registry.mjs +179 -3
- package/src/wf-ui-server/settings.mjs +25 -0
- package/src/wf-ui-server/spawn-gate.mjs +46 -0
- package/src/wf-ui-server/task-parser.mjs +88 -3
- package/src/wf-ui-server/terminal-store.mjs +225 -11
- package/src/wf-ui-server/timer-wakeup-scheduler.mjs +226 -0
- package/src/wf-ui-server/wf-browser-store.mjs +733 -0
- package/src/wf-ui-server/workflow-agent-context.mjs +1731 -0
- package/src/wf-ui-server/workflow-capability-node-store.mjs +676 -0
- package/src/wf-ui-server/workflow-event-node-store.mjs +623 -0
- package/src/wf-ui-server/workflow-goal-node-store.mjs +328 -0
- package/src/wf-ui-server/workflow-graph-store.mjs +623 -0
- package/src/wf-ui-server/workflow-mcp-hub.mjs +286 -0
- package/src/wf-ui-server/workflow-node-runtime.mjs +1767 -0
- package/src/wf-ui-server/workflow-node-settings-store.mjs +339 -0
- package/src/wf-ui-server/workflow-node-types/agent-node.mjs +920 -0
- package/src/wf-ui-server/workflow-node-types/display-node.mjs +151 -0
- package/src/wf-ui-server/workflow-node-types/excalidraw-node.mjs +145 -0
- package/src/wf-ui-server/workflow-node-types/file-node.mjs +484 -0
- package/src/wf-ui-server/workflow-node-types/github-trigger-node.mjs +207 -0
- package/src/wf-ui-server/workflow-node-types/goal-node.mjs +491 -0
- package/src/wf-ui-server/workflow-node-types/markdown-node.mjs +225 -0
- package/src/wf-ui-server/workflow-node-types/mcp-connector-node.mjs +71 -0
- package/src/wf-ui-server/workflow-node-types/role-profile-store.mjs +191 -0
- package/src/wf-ui-server/workflow-node-types/skill-group-node.mjs +98 -0
- package/src/wf-ui-server/workflow-node-types/timer-node.mjs +607 -0
- package/src/wf-ui-server/workflow-ontology.mjs +681 -0
- package/src/wf-ui-server/workflow-operation-store.mjs +115 -0
- package/src/wf-ui-server/workflow-skills-hub.mjs +366 -0
- package/src/wf-ui-server/workflow-skills-market.mjs +723 -0
- package/src/wf-ui-server/workspace-store.mjs +951 -0
- package/src/wf-ui-server/ws-chat.mjs +299 -0
- package/src/wf-ui-server/ws-events.mjs +45 -20
- package/src/wf-ui-server/ws-terminal.mjs +165 -22
- package/src/wf-ui-server/ws-wf-browser.mjs +419 -0
- package/templates/common/.claude/agents/review-manager.md +33 -29
- package/templates/common/.claude/commands/wf-browser.md +1 -1
- package/templates/common/.claude/commands/wf-help.md +5 -3
- package/templates/common/.claude/commands/wf-init.md +44 -0
- package/templates/common/.claude/commands/wf-learn.md +34 -8
- package/templates/common/.claude/commands/wf-max.md +19 -9
- package/templates/common/.claude/commands/wf-review.md +3 -3
- package/templates/common/.claude/commands/wf-search.md +55 -0
- package/templates/common/.claude/commands/wf-task-archive.md +5 -4
- package/templates/common/.claude/commands/wf-task-list.md +6 -3
- package/templates/common/.claude/commands/wf-task-record.md +10 -2
- package/templates/common/.claude/commands/wf-ui.md +12 -5
- package/templates/common/.claude/commands/wf-update.md +4 -0
- package/templates/common/.claude/commands/wf.md +12 -1
- package/templates/common/.claude/rules/ecc/common.md +10 -1
- package/templates/common/.claude/skills/wf/SKILL.md +36 -0
- package/templates/common/.claude/skills/wf-browser/SKILL.md +427 -122
- package/templates/common/.claude/skills/wf-browser/references/BROWSER_CONTROL_PATTERNS.md +43 -0
- package/templates/common/.claude/skills/wf-init/SKILL.md +33 -0
- package/templates/common/.claude/skills/wf-learn/SKILL.md +106 -26
- package/templates/common/.claude/skills/wf-max/SKILL.md +45 -11
- package/templates/common/.claude/skills/wf-review/SKILL.md +26 -54
- package/templates/common/.claude/skills/wf-search/SKILL.md +122 -0
- package/templates/common/.claude/skills/wf-search/references/evidence-contract.md +77 -0
- package/templates/common/.claude/skills/wf-search/references/policies/compare.md +38 -0
- package/templates/common/.claude/skills/wf-search/references/policies/fact.md +39 -0
- package/templates/common/.claude/skills/wf-search/references/policies/troubleshoot.md +39 -0
- package/templates/common/.claude/skills/wf-search/references/policies/verify.md +44 -0
- package/templates/common/.claude/skills/wf-search/references/source-routing.md +40 -0
- package/templates/common/.claude/skills/wf-search/references/tool-adapters.md +38 -0
- package/templates/common/.claude/skills/wf-ui/SKILL.md +146 -12
- package/templates/common/.claude/skills/wf-update/SKILL.md +5 -1
- package/templates/common/.harness-version +188 -85
- package/templates/common/.opencode/agents/review-manager.md +31 -27
- package/templates/common/.opencode/commands/wf-browser.md +1 -1
- package/templates/common/.opencode/commands/wf-help.md +5 -3
- package/templates/common/.opencode/commands/wf-init.md +44 -0
- package/templates/common/.opencode/commands/wf-learn.md +34 -8
- package/templates/common/.opencode/commands/wf-max.md +19 -9
- package/templates/common/.opencode/commands/wf-review.md +3 -3
- package/templates/common/.opencode/commands/wf-search.md +55 -0
- package/templates/common/.opencode/commands/wf-task-archive.md +5 -7
- package/templates/common/.opencode/commands/wf-task-list.md +6 -6
- package/templates/common/.opencode/commands/wf-task-record.md +10 -5
- package/templates/common/.opencode/commands/wf-ui.md +12 -5
- package/templates/common/.opencode/commands/wf-update.md +4 -0
- package/templates/common/.opencode/commands/wf.md +12 -1
- package/templates/common/CLAUDE.md +61 -3
- package/templates/common/Harness/MEMORY.md +8 -5
- package/templates/common/Harness/README.md +14 -10
- package/templates/common/Harness/a2a/action-registry.json +4397 -0
- package/templates/common/Harness/a2a/role-graph.json +16 -3
- package/templates/common/Harness/a2a/skills/terminal-control.json +45 -1
- package/templates/common/Harness/a2a/skills/wf-ui-map.json +50 -0
- package/templates/common/Harness/a2a/skills/workflow-agent-node.json +143 -0
- package/templates/common/Harness/a2a/skills/workflow-context.json +95 -0
- package/templates/common/Harness/a2a/skills/workflow-diagram-node.json +60 -0
- package/templates/common/Harness/a2a/skills/workflow-display-node.json +69 -0
- package/templates/common/Harness/a2a/skills/workflow-file-node.json +92 -0
- package/templates/common/Harness/a2a/skills/workflow-goal-node.json +76 -0
- package/templates/common/Harness/a2a/skills/workflow-markdown-node.json +79 -0
- package/templates/common/Harness/a2a/skills/workflow-mcp-connector-node.json +59 -0
- package/templates/common/Harness/a2a/skills/workflow-node-actions.json +105 -0
- package/templates/common/Harness/a2a/skills/workflow-node-map.json +71 -0
- package/templates/common/Harness/a2a/skills/workflow-ontology.json +54 -0
- package/templates/common/Harness/a2a/skills/workflow-resource-node.json +68 -0
- package/templates/common/Harness/a2a/skills/workflow-skill-group-node.json +56 -0
- package/templates/common/Harness/a2a/skills/workflow-timer-node.json +81 -0
- package/templates/common/Harness/a2a/workflows.json +33 -0
- package/templates/common/Harness/ownership.manifest.json +263 -2
- package/templates/common/Harness/project/architecture.md +499 -0
- package/templates/common/Harness/research/README.md +20 -0
- package/templates/common/Harness/scripts/README.md +70 -6
- package/templates/common/Harness/scripts/a2a-terminal.mjs +12 -4
- package/templates/common/Harness/scripts/context-budget.mjs +7 -3
- package/templates/common/Harness/scripts/lib/memory-context.mjs +400 -0
- package/templates/common/Harness/scripts/lib/path-scope.mjs +77 -0
- package/templates/common/Harness/scripts/lib/research-policy.mjs +99 -0
- package/templates/common/Harness/scripts/lib/wf-search.mjs +189 -0
- package/templates/common/Harness/scripts/memory-context.mjs +63 -0
- package/templates/common/Harness/scripts/research-policy.mjs +27 -0
- package/templates/common/Harness/scripts/task-context.mjs +547 -0
- package/templates/common/Harness/scripts/task-group-index.mjs +242 -0
- package/templates/common/Harness/scripts/task-state.mjs +659 -95
- package/templates/common/Harness/scripts/validate-harness.mjs +70 -28
- package/templates/common/Harness/scripts/wf-auto-update-prompt.mjs +24 -0
- package/templates/common/Harness/scripts/wf-remove.mjs +10 -0
- package/templates/common/Harness/scripts/wf-search.mjs +10 -0
- package/templates/common/Harness/scripts/wf-ui-control.mjs +3144 -0
- package/templates/common/Harness/scripts/wf-update-check.mjs +274 -51
- package/templates/common/Harness/scripts/wf-update-runner.mjs +53 -16
- package/templates/common/Harness/settings.json +10 -0
- package/templates/common/Harness/specs/guides/SETUP.md +4 -3
- package/templates/common/Harness/specs/protocols/HARNESS_BRIDGE.md +429 -48
- package/templates/common/Harness/specs/protocols/MEMORY_PROTOCOL.md +24 -0
- package/templates/common/Harness/specs/protocols/TASK_ARCHIVE.md +14 -11
- package/templates/common/Harness/specs/runtime/command-surface.json +28 -0
- package/templates/common/Harness/specs/runtime/context-loading.md +6 -0
- package/templates/common/Harness/specs/runtime/dispatch.md +9 -1
- package/templates/common/Harness/specs/runtime/subagents.md +20 -5
- package/templates/common/Harness/specs/workflows/WF-AUTO-SPARK.md +19 -0
- package/templates/common/Harness/specs/workflows/WF-AUTO.md +21 -0
- package/templates/common/Harness/specs/workflows/WF-KERNEL.md +4 -2
- package/templates/common/Harness/specs/workflows/WF-MAX.md +39 -12
- package/templates/common/Harness/specs/workflows/WF-STATE.md +62 -14
- package/templates/common/Harness/specs/workflows/WF.md +32 -0
- package/templates/common/Harness/tasks/INDEX.json +7 -0
- package/templates/common/Harness/tasks/INDEX.md +12 -0
- package/templates/common/Harness/tasks/_template/PLAN.md +6 -0
- package/templates/common/Harness/tasks/_template/PROGRESS.md +5 -0
- package/templates/common/Harness/tasks/_template/STATE.json +22 -0
- package/templates/common/Harness/templates/TEST_PLAN.template.md +5 -4
- package/templates/common/Harness/templates/UI_CONTRACT.template.md +7 -5
- package/templates/common/Harness/wf-browser/README.md +69 -0
- package/templates/common/README.md +17 -0
- package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js +0 -17
- package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js.map +0 -1
- package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js +0 -7
- package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js.map +0 -1
- package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js +0 -12
- package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js.map +0 -1
- package/src/ui/dist/assets/TaskList-BN4r8s1i.js +0 -50
- package/src/ui/dist/assets/TaskList-BN4r8s1i.js.map +0 -1
- package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js +0 -74
- package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js.map +0 -1
- package/src/ui/dist/assets/WorkflowRoute-BnuhLJ6X.css +0 -1
- package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js +0 -39
- package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js.map +0 -1
- package/src/ui/dist/assets/index-BOVYWntB.js +0 -117
- package/src/ui/dist/assets/index-BOVYWntB.js.map +0 -1
- package/src/ui/dist/assets/index-DaUObq0H.css +0 -1
- package/src/ui/dist/assets/maximize-2-LNrr_rKr.js +0 -7
- package/src/ui/dist/assets/maximize-2-LNrr_rKr.js.map +0 -1
- package/src/ui/dist/assets/plus-QuTJyoT3.js +0 -7
- package/src/ui/dist/assets/plus-QuTJyoT3.js.map +0 -1
- package/src/ui/dist/assets/proxy-D0vUbds5.js.map +0 -1
- package/src/ui/dist/assets/refresh-cw-JNmExijd.js.map +0 -1
- package/src/ui/dist/assets/terminal-BBQvnOAK.js.map +0 -1
- package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js +0 -7
- package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js.map +0 -1
- package/src/ui/dist/assets/x-DoIOGAJz.js.map +0 -1
- package/src/ui/pnpm-lock.yaml +0 -1582
- package/src/ui/src/App.tsx +0 -86
- package/src/ui/src/api.ts +0 -93
- package/src/ui/src/components/AgentsRoute.tsx +0 -503
- package/src/ui/src/components/Footer.tsx +0 -69
- package/src/ui/src/components/Header.tsx +0 -175
- package/src/ui/src/components/LoadingView.tsx +0 -22
- package/src/ui/src/components/RolesRoute.tsx +0 -169
- package/src/ui/src/components/SettingsRoute.tsx +0 -166
- package/src/ui/src/components/TaskList.tsx +0 -388
- package/src/ui/src/components/TerminalDrawer.tsx +0 -611
- package/src/ui/src/components/WorkflowRoute.tsx +0 -670
- package/src/ui/src/hooks/useReducedMotion.ts +0 -17
- package/src/ui/src/hooks/useServerConnection.ts +0 -114
- package/src/ui/src/index.css +0 -281
- package/src/ui/src/main.tsx +0 -11
- package/src/ui/src/types.ts +0 -108
- /package/src/ui/dist/assets/{TerminalDrawer-6GBZ9nXN.css → terminalControl-6GBZ9nXN.css} +0 -0
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
2
|
+
import { getRuntimeDefinition, resolveExecutable } from './runtime-detector.mjs';
|
|
3
|
+
import { readRuntimeConfig } from './runtime-config.mjs';
|
|
4
|
+
import { loadSettings } from './settings.mjs';
|
|
5
|
+
|
|
6
|
+
// Model selection is a dispatch preflight, not a best-effort launch hint. A
|
|
7
|
+
// probe may only return supported when it has a trusted source for the exact
|
|
8
|
+
// model (and, when requested, the exact effort). In particular, this module
|
|
9
|
+
// never turns a model string from the HTTP envelope into a catalog entry.
|
|
10
|
+
export const MODEL_CAPABILITY_CODES = Object.freeze({
|
|
11
|
+
UNSUPPORTED: 'UNSUPPORTED',
|
|
12
|
+
UNAVAILABLE: 'UNAVAILABLE',
|
|
13
|
+
UNVERIFIED: 'UNVERIFIED',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const PROBE_TIMEOUT_MS = 5000;
|
|
17
|
+
const MAX_PROBE_OUTPUT_BYTES = 1024 * 1024;
|
|
18
|
+
const MAX_CODEX_PAGES = 32;
|
|
19
|
+
|
|
20
|
+
function text(value) {
|
|
21
|
+
return String(value ?? '').trim();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function safeReason(reason, fallbackCode, fallbackMessage) {
|
|
25
|
+
if (!reason || typeof reason !== 'object') {
|
|
26
|
+
return { code: fallbackCode, message: fallbackMessage };
|
|
27
|
+
}
|
|
28
|
+
const code = text(reason.code).replace(/[^A-Za-z0-9_.:-]/g, '').slice(0, 100) || fallbackCode;
|
|
29
|
+
const message = text(reason.message).replace(/[\r\n]/g, ' ').slice(0, 240) || fallbackMessage;
|
|
30
|
+
return { code, message };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function modelError(code, message, details = {}) {
|
|
34
|
+
const error = new Error(message);
|
|
35
|
+
error.statusCode = 422;
|
|
36
|
+
error.code = code;
|
|
37
|
+
error.details = {
|
|
38
|
+
sourceKind: text(details.sourceKind) || 'none',
|
|
39
|
+
verificationLevel: text(details.verificationLevel) || code.toLowerCase(),
|
|
40
|
+
...(details.reason ? { reason: safeReason(details.reason, `MODEL_${code}`, message) } : {}),
|
|
41
|
+
};
|
|
42
|
+
return error;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function unsupported(message, details = {}) {
|
|
46
|
+
return modelError(MODEL_CAPABILITY_CODES.UNSUPPORTED, message, details);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function unavailable(message, details = {}) {
|
|
50
|
+
return modelError(MODEL_CAPABILITY_CODES.UNAVAILABLE, message, details);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function unverified(message, details = {}) {
|
|
54
|
+
return modelError(MODEL_CAPABILITY_CODES.UNVERIFIED, message, details);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function cleanSupportedEfforts(value) {
|
|
58
|
+
if (!Array.isArray(value)) return undefined;
|
|
59
|
+
const efforts = value.map(item => {
|
|
60
|
+
if (typeof item === 'string' || typeof item === 'number') return text(item).toLowerCase();
|
|
61
|
+
if (!item || typeof item !== 'object') return '';
|
|
62
|
+
return text(item.reasoningEffort || item.effort || item.id || item.name).toLowerCase();
|
|
63
|
+
}).filter(Boolean);
|
|
64
|
+
return [...new Set(efforts)];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function effortFromVariantMetadata(value) {
|
|
68
|
+
if (typeof value === 'string' || typeof value === 'number') return text(value).toLowerCase();
|
|
69
|
+
if (!value || typeof value !== 'object') return '';
|
|
70
|
+
return text(value.effort || value.reasoningEffort || value.reasoning_effort).toLowerCase();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function parseJsonBlock(lines, start) {
|
|
74
|
+
let candidate = '';
|
|
75
|
+
let depth = 0;
|
|
76
|
+
let sawOpening = false;
|
|
77
|
+
let inString = false;
|
|
78
|
+
let escaped = false;
|
|
79
|
+
for (let index = start; index < lines.length; index += 1) {
|
|
80
|
+
const line = lines[index];
|
|
81
|
+
candidate += `${candidate ? '\n' : ''}${line}`;
|
|
82
|
+
for (const character of line) {
|
|
83
|
+
if (escaped) {
|
|
84
|
+
escaped = false;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (character === '\\' && inString) {
|
|
88
|
+
escaped = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (character === '"') {
|
|
92
|
+
inString = !inString;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (inString) continue;
|
|
96
|
+
if (character === '{') {
|
|
97
|
+
sawOpening = true;
|
|
98
|
+
depth += 1;
|
|
99
|
+
} else if (character === '}') {
|
|
100
|
+
depth -= 1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!sawOpening || depth !== 0) continue;
|
|
104
|
+
try {
|
|
105
|
+
const value = JSON.parse(candidate);
|
|
106
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) return { value, end: index };
|
|
107
|
+
} catch {
|
|
108
|
+
// A balanced but invalid block is retained as a name-only row and must
|
|
109
|
+
// not consume the next model's metadata.
|
|
110
|
+
}
|
|
111
|
+
return { value: null, end: index };
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function normalizeOpenCodeEntry(header, metadata = null) {
|
|
117
|
+
const catalogId = text(header);
|
|
118
|
+
const providerId = text(metadata?.providerID || metadata?.providerId);
|
|
119
|
+
const modelId = text(metadata?.id || metadata?.model || (catalogId.includes('/') ? catalogId.slice(catalogId.lastIndexOf('/') + 1) : catalogId));
|
|
120
|
+
const variantsValue = metadata && Object.hasOwn(metadata, 'variants') && metadata.variants && typeof metadata.variants === 'object'
|
|
121
|
+
? metadata.variants
|
|
122
|
+
: undefined;
|
|
123
|
+
const variantMap = {};
|
|
124
|
+
const ambiguousEfforts = new Set();
|
|
125
|
+
if (variantsValue) {
|
|
126
|
+
for (const [variantId, variantMetadata] of Object.entries(variantsValue)) {
|
|
127
|
+
const effort = effortFromVariantMetadata(variantMetadata);
|
|
128
|
+
if (!effort || ambiguousEfforts.has(effort)) continue;
|
|
129
|
+
if (!Object.hasOwn(variantMap, effort)) variantMap[effort] = text(variantId);
|
|
130
|
+
// If two provider variants claim the same effort, remove the mapping;
|
|
131
|
+
// selecting one by object order would silently choose an unverified
|
|
132
|
+
// provider-specific variant.
|
|
133
|
+
else if (variantMap[effort] !== text(variantId)) {
|
|
134
|
+
delete variantMap[effort];
|
|
135
|
+
ambiguousEfforts.add(effort);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const supportedEfforts = variantsValue
|
|
140
|
+
? [...new Set(Object.keys(variantMap))]
|
|
141
|
+
: undefined;
|
|
142
|
+
return {
|
|
143
|
+
catalogId,
|
|
144
|
+
providerId,
|
|
145
|
+
modelId,
|
|
146
|
+
...(variantsValue ? { variants: Object.keys(variantsValue) } : {}),
|
|
147
|
+
...(supportedEfforts ? { supportedEfforts } : {}),
|
|
148
|
+
...(Object.keys(variantMap).length ? { effortVariants: variantMap } : {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Parse the first-party `opencode models --verbose` output. Each model is
|
|
154
|
+
* printed as a qualified id followed by its JSON metadata. A name-only row is
|
|
155
|
+
* retained, but deliberately has no effort metadata.
|
|
156
|
+
*/
|
|
157
|
+
export function parseOpenCodeVerboseCatalog(output) {
|
|
158
|
+
const lines = String(output || '').split(/\r?\n/);
|
|
159
|
+
const entries = [];
|
|
160
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
161
|
+
const header = text(lines[index]);
|
|
162
|
+
if (!header || header.startsWith('{') || header.startsWith('[')) continue;
|
|
163
|
+
const next = index + 1;
|
|
164
|
+
if (next < lines.length && text(lines[next]).startsWith('{')) {
|
|
165
|
+
const parsed = parseJsonBlock(lines, next);
|
|
166
|
+
if (parsed?.value) {
|
|
167
|
+
entries.push(normalizeOpenCodeEntry(header, parsed.value));
|
|
168
|
+
index = parsed.end;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// `--pure` without verbose metadata is a complete model-name catalog, not
|
|
173
|
+
// an effort catalog. Keep it discoverable so requested effort remains
|
|
174
|
+
// explicitly UNVERIFIED instead of being guessed from the model name.
|
|
175
|
+
entries.push(normalizeOpenCodeEntry(header));
|
|
176
|
+
}
|
|
177
|
+
return entries;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function openCodeEntryMatches(entry, requestedModel) {
|
|
181
|
+
const requested = text(requestedModel);
|
|
182
|
+
if (!requested) return false;
|
|
183
|
+
const catalogId = text(entry?.catalogId);
|
|
184
|
+
const modelId = text(entry?.modelId);
|
|
185
|
+
const qualified = entry?.providerId && modelId ? `${entry.providerId}/${modelId}` : '';
|
|
186
|
+
if (catalogId === requested || qualified === requested || modelId === requested) return true;
|
|
187
|
+
return !requested.includes('/') && catalogId.endsWith(`/${requested}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Resolve one OpenCode model and its own exact variant mapping. Variant data
|
|
192
|
+
* never comes from a neighboring model entry or from the requested string.
|
|
193
|
+
*/
|
|
194
|
+
export function resolveOpenCodeModelCapability(catalog, requestedModel, effort = '') {
|
|
195
|
+
const model = text(requestedModel);
|
|
196
|
+
const entries = Array.isArray(catalog)
|
|
197
|
+
? catalog.filter(candidate => openCodeEntryMatches(candidate, model))
|
|
198
|
+
: [];
|
|
199
|
+
// OpenCode's launch contract is provider/model. A bare model id is unsafe
|
|
200
|
+
// even when today's catalog happens to contain only one provider: a later
|
|
201
|
+
// provider addition would silently change the runtime selected by an old
|
|
202
|
+
// dispatch request. Keep the rejection tied to the complete native catalog
|
|
203
|
+
// so callers receive an explicit, actionable 422 rather than a guess.
|
|
204
|
+
if (!model.includes('/')) {
|
|
205
|
+
return {
|
|
206
|
+
status: 'unsupported',
|
|
207
|
+
sourceKind: 'opencode-models',
|
|
208
|
+
verificationLevel: 'authoritative',
|
|
209
|
+
complete: true,
|
|
210
|
+
model,
|
|
211
|
+
reason: {
|
|
212
|
+
code: 'MODEL_PROVIDER_REQUIRED',
|
|
213
|
+
message: 'OpenCode dispatch requires an exact provider/model id; specify the provider explicitly.',
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (entries.length > 1) {
|
|
218
|
+
return {
|
|
219
|
+
status: 'unsupported',
|
|
220
|
+
sourceKind: 'opencode-models',
|
|
221
|
+
verificationLevel: 'authoritative',
|
|
222
|
+
complete: true,
|
|
223
|
+
model,
|
|
224
|
+
reason: {
|
|
225
|
+
code: 'MODEL_CATALOG_AMBIGUOUS',
|
|
226
|
+
message: 'The OpenCode catalog contains multiple entries for this provider/model id; choose one exact catalog id.',
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const entry = entries[0];
|
|
231
|
+
if (!entry) {
|
|
232
|
+
return {
|
|
233
|
+
status: 'unsupported',
|
|
234
|
+
sourceKind: 'opencode-models',
|
|
235
|
+
verificationLevel: 'authoritative',
|
|
236
|
+
complete: true,
|
|
237
|
+
model,
|
|
238
|
+
reason: { code: 'MODEL_NOT_IN_AUTHORITATIVE_CATALOG', message: 'The model is absent from the complete OpenCode models catalog.' },
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const result = supportedFromEntry(model, 'opencode-models', 'authoritative', entry, entry.supportedEfforts);
|
|
242
|
+
const requestedEffort = text(effort).toLowerCase();
|
|
243
|
+
if (!requestedEffort) return result;
|
|
244
|
+
if (!entry.supportedEfforts) return result;
|
|
245
|
+
if (!entry.supportedEfforts.includes(requestedEffort)) {
|
|
246
|
+
return {
|
|
247
|
+
status: 'unsupported',
|
|
248
|
+
sourceKind: 'opencode-models',
|
|
249
|
+
verificationLevel: 'authoritative',
|
|
250
|
+
complete: true,
|
|
251
|
+
model,
|
|
252
|
+
reason: { code: 'MODEL_EFFORT_NOT_SUPPORTED', message: `The authoritative OpenCode model metadata excludes effort '${requestedEffort}'.` },
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
const effortVariant = entry.effortVariants?.[requestedEffort];
|
|
256
|
+
if (!effortVariant) {
|
|
257
|
+
return {
|
|
258
|
+
status: 'unverified',
|
|
259
|
+
sourceKind: 'opencode-models',
|
|
260
|
+
verificationLevel: 'authoritative',
|
|
261
|
+
complete: true,
|
|
262
|
+
model,
|
|
263
|
+
reason: { code: 'MODEL_EFFORT_VARIANT_UNVERIFIED', message: 'The model metadata names the effort but does not identify one exact launch variant.' },
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return { ...result, effortVariant, catalogModelId: entry.catalogId };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Read only the Harness-owned operator model declarations from project settings. */
|
|
270
|
+
export function readHarnessRuntimeCapabilities(projectRoot, runtime) {
|
|
271
|
+
const configured = loadSettings(projectRoot)?.runtimeCapabilities;
|
|
272
|
+
const runtimeConfig = configured && typeof configured === 'object'
|
|
273
|
+
? (configured[runtime] || (runtime === 'cc' ? configured.claude : null))
|
|
274
|
+
: null;
|
|
275
|
+
const models = runtimeConfig?.models && typeof runtimeConfig.models === 'object' && !Array.isArray(runtimeConfig.models)
|
|
276
|
+
? runtimeConfig.models
|
|
277
|
+
: {};
|
|
278
|
+
const normalized = {};
|
|
279
|
+
for (const [model, value] of Object.entries(models)) {
|
|
280
|
+
const exactModel = text(model);
|
|
281
|
+
if (!exactModel || !value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
282
|
+
const supportedEfforts = cleanSupportedEfforts(value.supportedEfforts);
|
|
283
|
+
normalized[exactModel] = {
|
|
284
|
+
...(supportedEfforts ? { supportedEfforts } : {}),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
sourceKind: 'harness-operator-runtime-capabilities',
|
|
289
|
+
verificationLevel: 'operator-configured',
|
|
290
|
+
models: normalized,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Validate a probe result against the canonical dispatch request. This is
|
|
296
|
+
* deliberately exported as a pure helper so construction seams can exercise
|
|
297
|
+
* it without starting a runtime or making a provider request.
|
|
298
|
+
*/
|
|
299
|
+
export function assertModelCapability(result, { runtime, model, effort } = {}) {
|
|
300
|
+
const requestedModel = text(model);
|
|
301
|
+
const requestedEffort = text(effort).toLowerCase();
|
|
302
|
+
if (!result || typeof result !== 'object' || Array.isArray(result)) {
|
|
303
|
+
throw unverified('Model capability could not be verified: probe returned no result', {
|
|
304
|
+
reason: { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'No trusted model capability result was returned.' },
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const status = text(result.status).toLowerCase();
|
|
309
|
+
const sourceKind = text(result.sourceKind);
|
|
310
|
+
const verificationLevel = text(result.verificationLevel).toLowerCase();
|
|
311
|
+
const reason = result.reason;
|
|
312
|
+
if (text(runtime).toLowerCase() === 'opencode' && !requestedModel.includes('/')) {
|
|
313
|
+
// OpenCode's CLI requires provider/model. Enforce that launch identity at
|
|
314
|
+
// the server seam too: a trusted construction probe may be backed by a
|
|
315
|
+
// catalog with two providers, but it must not authorize a bare id that
|
|
316
|
+
// the CLI would resolve implicitly or differently over time.
|
|
317
|
+
throw unsupported('OpenCode dispatch requires an exact provider/model id; specify the provider explicitly.', {
|
|
318
|
+
sourceKind,
|
|
319
|
+
verificationLevel,
|
|
320
|
+
reason: {
|
|
321
|
+
code: 'MODEL_PROVIDER_REQUIRED',
|
|
322
|
+
message: 'The OpenCode model must include its provider (provider/model).',
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (status === 'unavailable') {
|
|
328
|
+
throw unavailable('Model capability probe is unavailable', { sourceKind, verificationLevel, reason });
|
|
329
|
+
}
|
|
330
|
+
if (status === 'unverified' || status === '') {
|
|
331
|
+
throw unverified('Model capability is not backed by a trusted catalog', { sourceKind, verificationLevel, reason });
|
|
332
|
+
}
|
|
333
|
+
if (status === 'unsupported') {
|
|
334
|
+
// An unsupported answer is meaningful only from a complete authoritative
|
|
335
|
+
// list. Partial, inferred, or operator-unknown answers are unverified.
|
|
336
|
+
if (result.complete !== true
|
|
337
|
+
|| !['authoritative', 'operator-configured'].includes(verificationLevel)
|
|
338
|
+
|| !sourceKind) {
|
|
339
|
+
throw unverified('Model capability cannot establish that the model is unsupported', {
|
|
340
|
+
sourceKind,
|
|
341
|
+
verificationLevel,
|
|
342
|
+
reason: reason || { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'The source is not a complete authoritative catalog.' },
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
throw unsupported(`Unsupported model '${requestedModel}'`, { sourceKind, verificationLevel, reason });
|
|
346
|
+
}
|
|
347
|
+
if (status !== 'supported') {
|
|
348
|
+
throw unverified('Model capability returned an unknown status', {
|
|
349
|
+
sourceKind,
|
|
350
|
+
verificationLevel,
|
|
351
|
+
reason: { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'The probe status was not recognized.' },
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (!sourceKind || !verificationLevel || result.complete !== true) {
|
|
356
|
+
throw unverified('Model capability is not complete and trusted', {
|
|
357
|
+
sourceKind,
|
|
358
|
+
verificationLevel,
|
|
359
|
+
reason: reason || { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'The supported result is missing trusted provenance.' },
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
const returnedModel = text(result.model);
|
|
363
|
+
if (!returnedModel || returnedModel !== requestedModel) {
|
|
364
|
+
throw unsupported(`Model capability did not verify requested model '${requestedModel}'`, {
|
|
365
|
+
sourceKind,
|
|
366
|
+
verificationLevel,
|
|
367
|
+
reason: { code: 'MODEL_CAPABILITY_MODEL_MISMATCH', message: 'The provider result did not identify the requested model exactly.' },
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const supportedEfforts = cleanSupportedEfforts(result.supportedEfforts);
|
|
372
|
+
if (requestedEffort) {
|
|
373
|
+
// Do not infer an effort from a model being present. If the provider
|
|
374
|
+
// omitted effort metadata we cannot claim xhigh (or any other effort).
|
|
375
|
+
if (!supportedEfforts) {
|
|
376
|
+
throw unverified('Model effort capability is not verified', {
|
|
377
|
+
sourceKind,
|
|
378
|
+
verificationLevel,
|
|
379
|
+
reason: { code: 'MODEL_EFFORT_METADATA_UNAVAILABLE', message: 'The trusted model source did not publish supported efforts.' },
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
if (!supportedEfforts.includes(requestedEffort)) {
|
|
383
|
+
throw unsupported(`Unsupported effort '${requestedEffort}' for model '${requestedModel}'`, {
|
|
384
|
+
sourceKind,
|
|
385
|
+
verificationLevel,
|
|
386
|
+
reason: { code: 'MODEL_EFFORT_NOT_SUPPORTED', message: 'The authoritative model source excludes the requested effort.' },
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
status: 'supported',
|
|
393
|
+
sourceKind,
|
|
394
|
+
verificationLevel,
|
|
395
|
+
complete: true,
|
|
396
|
+
model: returnedModel,
|
|
397
|
+
...(supportedEfforts ? { supportedEfforts } : {}),
|
|
398
|
+
...(result.effortVariant ? { effortVariant: text(result.effortVariant) } : {}),
|
|
399
|
+
...(result.catalogModelId ? { catalogModelId: text(result.catalogModelId) } : {}),
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function probeDeadline(deadlineAt) {
|
|
404
|
+
const supplied = Number(deadlineAt);
|
|
405
|
+
if (Number.isFinite(supplied)) return supplied;
|
|
406
|
+
return Date.now() + PROBE_TIMEOUT_MS;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function spawnOptions(projectRoot, deadlineAt) {
|
|
410
|
+
return {
|
|
411
|
+
cwd: projectRoot,
|
|
412
|
+
windowsHide: true,
|
|
413
|
+
shell: process.platform === 'win32',
|
|
414
|
+
env: process.env,
|
|
415
|
+
deadlineAt,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function killOwnedProcess(child) {
|
|
420
|
+
if (!child || child.killed || child.exitCode !== null) return;
|
|
421
|
+
try {
|
|
422
|
+
if (process.platform === 'win32' && Number.isInteger(child.pid) && child.pid > 0) {
|
|
423
|
+
// `where.exe` commonly resolves .CMD launchers on Windows. The shell
|
|
424
|
+
// wrapper and its launcher are both owned by this probe, so terminate
|
|
425
|
+
// exactly that process tree on timeout/response completion.
|
|
426
|
+
spawnSync('taskkill', ['/PID', String(child.pid), '/T', '/F'], {
|
|
427
|
+
windowsHide: true,
|
|
428
|
+
timeout: 1000,
|
|
429
|
+
stdio: 'ignore',
|
|
430
|
+
});
|
|
431
|
+
} else {
|
|
432
|
+
child.kill('SIGTERM');
|
|
433
|
+
}
|
|
434
|
+
} catch { /* the child may have exited */ }
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function runCapture(command, args, { projectRoot, deadlineAt }) {
|
|
438
|
+
return new Promise((resolve, reject) => {
|
|
439
|
+
const child = spawn(command, args, spawnOptions(projectRoot, deadlineAt));
|
|
440
|
+
let stdout = '';
|
|
441
|
+
let stderr = '';
|
|
442
|
+
let settled = false;
|
|
443
|
+
const finish = (fn, value) => {
|
|
444
|
+
if (settled) return;
|
|
445
|
+
settled = true;
|
|
446
|
+
clearTimeout(timer);
|
|
447
|
+
killOwnedProcess(child);
|
|
448
|
+
fn(value);
|
|
449
|
+
};
|
|
450
|
+
const remaining = Math.max(1, deadlineAt - Date.now());
|
|
451
|
+
const timer = setTimeout(() => finish(reject, unavailable('Model capability probe deadline elapsed', {
|
|
452
|
+
reason: { code: 'MODEL_CAPABILITY_TIMEOUT', message: 'The native model catalog probe exceeded its deadline.' },
|
|
453
|
+
})), remaining);
|
|
454
|
+
timer.unref?.();
|
|
455
|
+
child.stdout?.on('data', chunk => {
|
|
456
|
+
if (stdout.length < MAX_PROBE_OUTPUT_BYTES) stdout += String(chunk).slice(0, MAX_PROBE_OUTPUT_BYTES - stdout.length);
|
|
457
|
+
});
|
|
458
|
+
child.stderr?.on('data', chunk => {
|
|
459
|
+
if (stderr.length < 4096) stderr += String(chunk).slice(0, 4096 - stderr.length);
|
|
460
|
+
});
|
|
461
|
+
child.once('error', () => finish(reject, unavailable('Native model catalog probe could not start', {
|
|
462
|
+
reason: { code: 'MODEL_CAPABILITY_PROCESS_ERROR', message: 'The runtime model catalog process could not be started.' },
|
|
463
|
+
})));
|
|
464
|
+
child.once('close', code => {
|
|
465
|
+
if (code !== 0) {
|
|
466
|
+
finish(reject, unavailable('Native model catalog probe failed', {
|
|
467
|
+
reason: { code: 'MODEL_CAPABILITY_PROCESS_ERROR', message: 'The runtime model catalog process exited unsuccessfully.' },
|
|
468
|
+
}));
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
finish(resolve, { stdout, stderr });
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function codexModelsFromResult(result) {
|
|
477
|
+
const data = result?.data ?? result?.models ?? result?.items ?? result;
|
|
478
|
+
return Array.isArray(data) ? data : [];
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function codexModelId(entry) {
|
|
482
|
+
if (typeof entry === 'string') return text(entry);
|
|
483
|
+
if (!entry || typeof entry !== 'object') return '';
|
|
484
|
+
return text(entry.id || entry.model || entry.name);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function codexEfforts(entry) {
|
|
488
|
+
if (!entry || typeof entry !== 'object') return undefined;
|
|
489
|
+
return cleanSupportedEfforts(
|
|
490
|
+
entry.supportedReasoningEfforts
|
|
491
|
+
|| entry.supportedEfforts
|
|
492
|
+
|| entry.reasoningEfforts
|
|
493
|
+
|| entry.reasoning_efforts,
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function runCodexModelList(command, { projectRoot, deadlineAt }) {
|
|
498
|
+
return new Promise((resolve, reject) => {
|
|
499
|
+
const child = spawn(command, ['app-server', '--listen', 'stdio://'], spawnOptions(projectRoot, deadlineAt));
|
|
500
|
+
let buffer = '';
|
|
501
|
+
let settled = false;
|
|
502
|
+
let nextId = 1;
|
|
503
|
+
let modelListId = null;
|
|
504
|
+
let pages = 0;
|
|
505
|
+
let entries = [];
|
|
506
|
+
let complete = false;
|
|
507
|
+
const finish = (fn, value) => {
|
|
508
|
+
if (settled) return;
|
|
509
|
+
settled = true;
|
|
510
|
+
clearTimeout(timer);
|
|
511
|
+
killOwnedProcess(child);
|
|
512
|
+
fn(value);
|
|
513
|
+
};
|
|
514
|
+
const remaining = Math.max(1, deadlineAt - Date.now());
|
|
515
|
+
const timer = setTimeout(() => finish(reject, unavailable('Codex model catalog probe deadline elapsed', {
|
|
516
|
+
sourceKind: 'codex-app-server-model-list',
|
|
517
|
+
verificationLevel: 'unavailable',
|
|
518
|
+
reason: { code: 'MODEL_CAPABILITY_TIMEOUT', message: 'The Codex model/list probe exceeded its deadline.' },
|
|
519
|
+
})), remaining);
|
|
520
|
+
timer.unref?.();
|
|
521
|
+
|
|
522
|
+
const write = message => {
|
|
523
|
+
try { child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', ...message })}\n`); } catch {
|
|
524
|
+
finish(reject, unavailable('Codex model catalog probe could not write request', {
|
|
525
|
+
sourceKind: 'codex-app-server-model-list',
|
|
526
|
+
reason: { code: 'MODEL_CAPABILITY_PROCESS_ERROR', message: 'The Codex model catalog process did not accept the request.' },
|
|
527
|
+
}));
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
const requestModels = cursor => {
|
|
531
|
+
modelListId = nextId++;
|
|
532
|
+
write({ id: modelListId, method: 'model/list', params: { includeHidden: true, ...(cursor ? { cursor } : {}) } });
|
|
533
|
+
};
|
|
534
|
+
const onMessage = message => {
|
|
535
|
+
if (!message || typeof message !== 'object') return;
|
|
536
|
+
if (message.id === 1) {
|
|
537
|
+
if (message.error) {
|
|
538
|
+
finish(reject, unavailable('Codex model catalog initialization failed', {
|
|
539
|
+
sourceKind: 'codex-app-server-model-list',
|
|
540
|
+
reason: { code: 'MODEL_CAPABILITY_PROVIDER_ERROR', message: 'Codex did not initialize its model catalog.' },
|
|
541
|
+
}));
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
write({ method: 'initialized' });
|
|
545
|
+
requestModels('');
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (message.id !== modelListId) return;
|
|
549
|
+
if (message.error) {
|
|
550
|
+
finish(reject, unavailable('Codex model catalog request failed', {
|
|
551
|
+
sourceKind: 'codex-app-server-model-list',
|
|
552
|
+
reason: { code: 'MODEL_CAPABILITY_PROVIDER_ERROR', message: 'Codex did not return its model catalog.' },
|
|
553
|
+
}));
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const result = message.result || {};
|
|
557
|
+
entries = entries.concat(codexModelsFromResult(result));
|
|
558
|
+
pages += 1;
|
|
559
|
+
const cursor = text(result.nextCursor || result.next_cursor || '');
|
|
560
|
+
if (cursor && pages < MAX_CODEX_PAGES) {
|
|
561
|
+
requestModels(cursor);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (cursor) {
|
|
565
|
+
finish(reject, unavailable('Codex model catalog was not fully enumerated', {
|
|
566
|
+
sourceKind: 'codex-app-server-model-list',
|
|
567
|
+
reason: { code: 'MODEL_CAPABILITY_PARTIAL_CATALOG', message: 'The Codex model catalog pagination limit was reached.' },
|
|
568
|
+
}));
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
complete = true;
|
|
572
|
+
finish(resolve, { entries, complete });
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
child.stdout?.on('data', chunk => {
|
|
576
|
+
buffer += String(chunk);
|
|
577
|
+
if (buffer.length > MAX_PROBE_OUTPUT_BYTES) {
|
|
578
|
+
finish(reject, unavailable('Codex model catalog output exceeded the probe limit', {
|
|
579
|
+
sourceKind: 'codex-app-server-model-list',
|
|
580
|
+
reason: { code: 'MODEL_CAPABILITY_OUTPUT_LIMIT', message: 'The Codex model catalog response was too large.' },
|
|
581
|
+
}));
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const lines = buffer.split(/\r?\n/);
|
|
585
|
+
buffer = lines.pop() || '';
|
|
586
|
+
for (const line of lines) {
|
|
587
|
+
try { onMessage(JSON.parse(line)); } catch { /* non-protocol diagnostics are ignored */ }
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
child.once('error', () => finish(reject, unavailable('Codex model catalog process could not start', {
|
|
591
|
+
sourceKind: 'codex-app-server-model-list',
|
|
592
|
+
reason: { code: 'MODEL_CAPABILITY_PROCESS_ERROR', message: 'The Codex model catalog process could not be started.' },
|
|
593
|
+
})));
|
|
594
|
+
child.once('close', code => {
|
|
595
|
+
if (!settled) finish(reject, unavailable('Codex model catalog process exited before returning a model catalog', {
|
|
596
|
+
sourceKind: 'codex-app-server-model-list',
|
|
597
|
+
reason: { code: code === 0 ? 'MODEL_CAPABILITY_EMPTY_RESULT' : 'MODEL_CAPABILITY_PROCESS_ERROR', message: 'Codex did not return a complete model catalog.' },
|
|
598
|
+
}));
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
write({
|
|
602
|
+
id: 1,
|
|
603
|
+
method: 'initialize',
|
|
604
|
+
params: {
|
|
605
|
+
clientInfo: { name: 'harness-model-capability-probe', title: 'Harness model capability probe', version: '0.0.0' },
|
|
606
|
+
capabilities: {},
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function operatorConfiguredModels(projectRoot, runtime) {
|
|
613
|
+
let config;
|
|
614
|
+
try { config = readRuntimeConfig(projectRoot, runtime); } catch { return []; }
|
|
615
|
+
const models = [];
|
|
616
|
+
for (const file of config.files || []) {
|
|
617
|
+
const value = file.values?.availableModels;
|
|
618
|
+
if (Array.isArray(value)) {
|
|
619
|
+
for (const item of value) {
|
|
620
|
+
if (typeof item === 'string' && text(item)) models.push(text(item));
|
|
621
|
+
else if (item && typeof item === 'object' && text(item.id || item.model || item.name)) models.push(text(item.id || item.model || item.name));
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return [...new Set(models)];
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
function operatorCapabilityResult(projectRoot, runtime, requestedModel, effort) {
|
|
629
|
+
const declarations = readHarnessRuntimeCapabilities(projectRoot, runtime);
|
|
630
|
+
const declared = declarations.models[requestedModel];
|
|
631
|
+
if (!declared) return null;
|
|
632
|
+
// The compact operator schema declares model + effort names only. OpenCode
|
|
633
|
+
// additionally needs an exact provider variant id, which this declaration
|
|
634
|
+
// intentionally does not invent; native verbose metadata remains the only
|
|
635
|
+
// source that can authorize an OpenCode effort launch.
|
|
636
|
+
if (runtime === 'opencode' && text(effort)) {
|
|
637
|
+
return {
|
|
638
|
+
status: 'unverified',
|
|
639
|
+
sourceKind: declarations.sourceKind,
|
|
640
|
+
verificationLevel: declarations.verificationLevel,
|
|
641
|
+
complete: true,
|
|
642
|
+
model: requestedModel,
|
|
643
|
+
reason: { code: 'MODEL_EFFORT_VARIANT_UNVERIFIED', message: 'An operator effort declaration cannot identify an exact OpenCode variant.' },
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
return supportedFromEntry(
|
|
647
|
+
requestedModel,
|
|
648
|
+
declarations.sourceKind,
|
|
649
|
+
declarations.verificationLevel,
|
|
650
|
+
declared,
|
|
651
|
+
declared.supportedEfforts,
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function supportedFromEntry(model, sourceKind, verificationLevel, entry, supportedEfforts) {
|
|
656
|
+
return {
|
|
657
|
+
status: 'supported',
|
|
658
|
+
sourceKind,
|
|
659
|
+
verificationLevel,
|
|
660
|
+
complete: true,
|
|
661
|
+
model,
|
|
662
|
+
...(supportedEfforts ? { supportedEfforts } : {}),
|
|
663
|
+
...(entry && typeof entry === 'object' && entry.supportedEfforts ? { supportedEfforts: cleanSupportedEfforts(entry.supportedEfforts) } : {}),
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Native-first model capability probe. It performs only catalog discovery:
|
|
669
|
+
* Codex app-server initialize/model-list and OpenCode models. No prompt,
|
|
670
|
+
* thread, turn, or inference request is sent.
|
|
671
|
+
*/
|
|
672
|
+
export async function probeModelCapability({ runtime, model, effort = '', projectRoot, deadlineAt } = {}) {
|
|
673
|
+
const runtimeId = text(runtime);
|
|
674
|
+
const requestedModel = text(model);
|
|
675
|
+
const deadline = probeDeadline(deadlineAt);
|
|
676
|
+
if (!runtimeId || !requestedModel) {
|
|
677
|
+
return {
|
|
678
|
+
status: 'unverified', sourceKind: 'none', verificationLevel: 'unverified', complete: false, model: requestedModel,
|
|
679
|
+
reason: { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'Runtime and model are required for capability discovery.' },
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (runtimeId === 'claude' || runtimeId === 'cc') {
|
|
684
|
+
const operatorResult = operatorCapabilityResult(projectRoot, runtimeId, requestedModel, effort);
|
|
685
|
+
if (operatorResult) return operatorResult;
|
|
686
|
+
const operatorDeclarations = readHarnessRuntimeCapabilities(projectRoot, runtimeId);
|
|
687
|
+
if (Object.keys(operatorDeclarations.models).length) {
|
|
688
|
+
return {
|
|
689
|
+
status: 'unsupported',
|
|
690
|
+
sourceKind: operatorDeclarations.sourceKind,
|
|
691
|
+
verificationLevel: operatorDeclarations.verificationLevel,
|
|
692
|
+
complete: true,
|
|
693
|
+
model: requestedModel,
|
|
694
|
+
reason: { code: 'MODEL_NOT_IN_OPERATOR_ALLOWLIST', message: 'The model is absent from the Harness operator model declaration.' },
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
const configured = operatorConfiguredModels(projectRoot, runtimeId);
|
|
698
|
+
if (!configured.length) {
|
|
699
|
+
return {
|
|
700
|
+
status: 'unverified', sourceKind: 'none', verificationLevel: 'unverified', complete: false, model: requestedModel,
|
|
701
|
+
reason: { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'Claude has no trusted operator model allowlist configured.' },
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
return configured.includes(requestedModel)
|
|
705
|
+
? supportedFromEntry(requestedModel, 'claude-operator-config', 'operator-configured')
|
|
706
|
+
: {
|
|
707
|
+
status: 'unsupported', sourceKind: 'claude-operator-config', verificationLevel: 'operator-configured', complete: true, model: requestedModel,
|
|
708
|
+
reason: { code: 'MODEL_NOT_IN_OPERATOR_ALLOWLIST', message: 'The model is absent from the operator model allowlist.' },
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
const definition = getRuntimeDefinition(runtimeId);
|
|
713
|
+
const commandName = definition?.commands?.[0];
|
|
714
|
+
const executable = commandName ? resolveExecutable(commandName) : null;
|
|
715
|
+
if (!executable) {
|
|
716
|
+
return {
|
|
717
|
+
status: 'unavailable', sourceKind: `${runtimeId || 'runtime'}-model-catalog`, verificationLevel: 'unavailable', complete: false, model: requestedModel,
|
|
718
|
+
reason: { code: 'MODEL_CAPABILITY_UNAVAILABLE', message: 'The runtime executable is not available for model discovery.' },
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (runtimeId === 'codex') {
|
|
723
|
+
try {
|
|
724
|
+
const catalog = await runCodexModelList(executable, { projectRoot, deadlineAt: deadline });
|
|
725
|
+
const entry = catalog.entries.find(candidate => codexModelId(candidate) === requestedModel);
|
|
726
|
+
if (entry) return supportedFromEntry(requestedModel, 'codex-app-server-model-list', 'authoritative', entry, codexEfforts(entry));
|
|
727
|
+
const operatorResult = operatorCapabilityResult(projectRoot, runtimeId, requestedModel, effort);
|
|
728
|
+
if (operatorResult) return operatorResult;
|
|
729
|
+
return {
|
|
730
|
+
status: 'unsupported', sourceKind: 'codex-app-server-model-list', verificationLevel: 'authoritative', complete: catalog.complete, model: requestedModel,
|
|
731
|
+
reason: { code: 'MODEL_NOT_IN_AUTHORITATIVE_CATALOG', message: 'The model is absent from the complete Codex model/list catalog.' },
|
|
732
|
+
};
|
|
733
|
+
} catch (error) {
|
|
734
|
+
if (error?.code === MODEL_CAPABILITY_CODES.UNAVAILABLE) throw error;
|
|
735
|
+
const operatorResult = operatorCapabilityResult(projectRoot, runtimeId, requestedModel, effort);
|
|
736
|
+
if (operatorResult) return operatorResult;
|
|
737
|
+
return {
|
|
738
|
+
status: 'unavailable', sourceKind: 'codex-app-server-model-list', verificationLevel: 'unavailable', complete: false, model: requestedModel,
|
|
739
|
+
reason: { code: 'MODEL_CAPABILITY_UNAVAILABLE', message: 'Codex model discovery did not complete.' },
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (runtimeId === 'opencode') {
|
|
745
|
+
try {
|
|
746
|
+
const result = await runCapture(executable, ['models', '--pure', '--log-level', 'ERROR', '--verbose'], { projectRoot, deadlineAt: deadline });
|
|
747
|
+
const capability = resolveOpenCodeModelCapability(parseOpenCodeVerboseCatalog(result.stdout), requestedModel, effort);
|
|
748
|
+
if (capability.status === 'supported' || capability.status === 'unverified') return capability;
|
|
749
|
+
if (capability.reason?.code === 'MODEL_NOT_IN_AUTHORITATIVE_CATALOG') {
|
|
750
|
+
const operatorResult = operatorCapabilityResult(projectRoot, runtimeId, requestedModel, effort);
|
|
751
|
+
if (operatorResult) return operatorResult;
|
|
752
|
+
}
|
|
753
|
+
return capability;
|
|
754
|
+
} catch (error) {
|
|
755
|
+
if (error?.code === MODEL_CAPABILITY_CODES.UNAVAILABLE) throw error;
|
|
756
|
+
const operatorResult = operatorCapabilityResult(projectRoot, runtimeId, requestedModel, effort);
|
|
757
|
+
if (operatorResult) return operatorResult;
|
|
758
|
+
return {
|
|
759
|
+
status: 'unavailable', sourceKind: 'opencode-models', verificationLevel: 'unavailable', complete: false, model: requestedModel,
|
|
760
|
+
reason: { code: 'MODEL_CAPABILITY_UNAVAILABLE', message: 'OpenCode model discovery did not complete.' },
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return {
|
|
766
|
+
status: 'unverified', sourceKind: 'none', verificationLevel: 'unverified', complete: false, model: requestedModel,
|
|
767
|
+
reason: { code: 'MODEL_CAPABILITY_UNVERIFIED', message: 'This runtime has no trusted native model catalog integration.' },
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
export function capabilityErrorFromProbe(result, request) {
|
|
772
|
+
return assertModelCapability(result, request);
|
|
773
|
+
}
|