@iowarp/clio-coder 0.4.1 → 0.4.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 +127 -0
- package/CONTRIBUTING.md +142 -52
- package/README.md +434 -473
- package/SECURITY.md +2 -1
- package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
- package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
- package/dist/builtins-IA7V7FUC.js +22 -0
- package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
- package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
- package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
- package/dist/chunk-3EBYEESD.js +314 -0
- package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
- package/dist/chunk-4UVU7BJ5.js +39 -0
- package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
- package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/chunk-5MEZN6CB.js +1334 -0
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
- package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
- package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
- package/dist/chunk-7DRAWPTZ.js +360 -0
- package/dist/chunk-7E7I3WLS.js +3762 -0
- package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
- package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
- package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
- package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
- package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
- package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
- package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
- package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
- package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
- package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
- package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
- package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
- package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
- package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
- package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
- package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
- package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
- package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
- package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
- package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
- package/dist/chunk-IJNZMHLA.js +101 -0
- package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
- package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
- package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
- package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
- package/dist/chunk-JEQ3XTHC.js +42 -0
- package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
- package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
- package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
- package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
- package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
- package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
- package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
- package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
- package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
- package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
- package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
- package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
- package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
- package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
- package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
- package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
- package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
- package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
- package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
- package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
- package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
- package/dist/chunk-SKHCAU7K.js +385 -0
- package/dist/chunk-SZAA6XDG.js +30 -0
- package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
- package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
- package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
- package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
- package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
- package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
- package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
- package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
- package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
- package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
- package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
- package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
- package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
- package/dist/chunk-XRZT5WY5.js +47 -0
- package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
- package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
- package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
- package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
- package/dist/cli/index.js +41 -39
- package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
- package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
- package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
- package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
- package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
- package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
- package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
- package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
- package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
- package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
- package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
- package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
- package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
- package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
- package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
- package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
- package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
- package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
- package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
- package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
- package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
- package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
- package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
- package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
- package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
- package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
- package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
- package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
- package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
- package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
- package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
- package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
- package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
- package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
- package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
- package/dist/reset-EAJFFJVB.js +344 -0
- package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
- package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
- package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
- package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
- package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
- package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
- package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
- package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
- package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
- package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
- package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
- package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
- package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
- package/dist/uninstall-5PEVOE5B.js +408 -0
- package/dist/upgrade-M4WXY6KN.js +303 -0
- package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
- package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
- package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
- package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
- package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
- package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
- package/dist/worker/entry.js +90 -74
- package/docs/README.md +176 -81
- package/docs/{acp.md → architecture/acp.md} +36 -20
- package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
- package/docs/{architecture.md → architecture/architecture.md} +43 -22
- package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
- package/docs/architecture/artifact-versions.md +90 -0
- package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
- package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
- package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
- package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
- package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
- package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
- package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
- package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
- package/docs/{observability.md → architecture/observability.md} +38 -14
- package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
- package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
- package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
- package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
- package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
- package/docs/architecture/time-conventions.md +125 -0
- package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
- package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
- package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
- package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
- package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
- package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
- package/docs/guide/configuration-reference.md +1163 -0
- package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
- package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
- package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
- package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
- package/docs/{glossary.md → guide/glossary.md} +14 -11
- package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
- package/docs/guide/panes-and-files.md +290 -0
- package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
- package/docs/{resource-library.md → guide/resource-library.md} +13 -4
- package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
- package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
- package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
- package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
- package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
- package/docs/process/development-pipeline.md +152 -0
- package/docs/process/documentation-coverage.md +100 -0
- package/docs/process/documentation-guide.md +187 -0
- package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
- package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
- package/docs/{evolution.md → process/evolution.md} +2 -2
- package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
- package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
- package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
- package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
- package/evals/README.md +2 -2
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +10 -8
- package/skills/README.md +52 -41
- package/skills/coding/ast-grep/SKILL.md +102 -31
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +41 -6
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +88 -29
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +81 -54
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +44 -3
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +46 -16
- package/skills/context/context-prime/evals.md +45 -0
- package/skills/git/branch-closeout/SKILL.md +132 -0
- package/skills/git/branch-closeout/evals.md +133 -0
- package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
- package/skills/git/file-ticket/SKILL.md +78 -64
- package/skills/git/file-ticket/assets/issue-template.md +22 -0
- package/skills/git/file-ticket/evals.md +31 -26
- package/skills/git/file-ticket/references/issue-discovery.md +49 -0
- package/skills/git/fix-issue/SKILL.md +88 -65
- package/skills/git/fix-issue/evals.md +35 -31
- package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
- package/skills/git/resolve-merge-conflicts/SKILL.md +101 -52
- package/skills/git/resolve-merge-conflicts/evals.md +52 -25
- package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
- package/skills/git/ship/SKILL.md +103 -67
- package/skills/git/ship/assets/pr-template.md +21 -0
- package/skills/git/ship/evals.md +44 -28
- package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
- package/skills/git/worktree-create/SKILL.md +80 -50
- package/skills/git/worktree-create/evals.md +40 -33
- package/skills/git/worktree-create/references/worktree-setup.md +62 -66
- package/skills/git/worktree-merge/SKILL.md +112 -65
- package/skills/git/worktree-merge/evals.md +42 -34
- package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
- package/skills/meta/clio-coder-dev/SKILL.md +9 -5
- package/skills/meta/clio-coder-dev/evals.md +3 -2
- package/skills/meta/clio-coder-test/SKILL.md +102 -95
- package/skills/meta/clio-coder-test/evals.md +9 -4
- package/skills/meta/clio-coder-test/references/harness.md +100 -124
- package/skills/meta/clio-coder-test/references/test-map.md +77 -50
- package/skills/meta/credentials/SKILL.md +2 -2
- package/skills/meta/find-skills/SKILL.md +2 -2
- package/skills/meta/herdr/SKILL.md +2 -2
- package/skills/meta/skill-craft/SKILL.md +22 -16
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +62 -13
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +131 -15
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +47 -7
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +58 -3
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +54 -3
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +70 -62
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +77 -19
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +21 -2
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +24 -2
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +27 -2
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +97 -62
- package/skills/workflow/cut-it/SKILL.md +66 -6
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +118 -28
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +87 -11
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +77 -18
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/args.ts +2 -2
- package/src/cli/bootstrap-generate.ts +1 -1
- package/src/cli/config-inspect.ts +65 -12
- package/src/cli/configure-interop.ts +105 -13
- package/src/cli/configure-oauth.ts +57 -0
- package/src/cli/configure-onboarding.ts +980 -0
- package/src/cli/configure-target.ts +594 -0
- package/src/cli/configure.ts +1082 -532
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/docs.ts +22 -14
- package/src/cli/doctor-naming.ts +5 -5
- package/src/cli/doctor-toolchain.ts +3 -3
- package/src/cli/eval.ts +1 -2
- package/src/cli/extensions.ts +2 -1
- package/src/cli/fleet.ts +1 -1
- package/src/cli/index.ts +3 -1
- package/src/cli/internal-dispatch.ts +3 -4
- package/src/cli/lifecycle-presenter.ts +436 -0
- package/src/cli/models.ts +10 -2
- package/src/cli/modes/print.ts +5 -1
- package/src/cli/panes.ts +19 -5
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +9 -4
- package/src/cli/select.ts +664 -0
- package/src/cli/share.ts +5 -1
- package/src/cli/skills-eval.ts +3 -3
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +5 -6
- package/src/cli/trace.ts +55 -4
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +204 -149
- package/src/cli/usage.ts +86 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/cli/wiki-generate.ts +1 -1
- package/src/core/artifact-paths.ts +1 -1
- package/src/core/bash-exec.ts +131 -86
- package/src/core/bus-events.ts +51 -6
- package/src/core/config.ts +61 -1
- package/src/core/defaults.ts +7 -4
- package/src/core/dispatch-outcome.ts +16 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/guardrails.ts +10 -49
- package/src/core/prompt-hint.ts +9 -0
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +89 -2
- package/src/domains/agents/builtins/architect.md +2 -3
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +2 -2
- package/src/domains/agents/builtins/documenter.md +2 -2
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/oracle.md +1 -1
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +2 -2
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +13 -15
- package/src/domains/agents/contract.ts +2 -0
- package/src/domains/agents/extension.ts +23 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/config/keybindings.ts +8 -0
- package/src/domains/context/extension.ts +0 -3
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/context/working-set/path-index.ts +1 -0
- package/src/domains/dispatch/admission.ts +29 -0
- package/src/domains/dispatch/agent-candidates.ts +10 -0
- package/src/domains/dispatch/budget-envelope.ts +86 -1
- package/src/domains/dispatch/capability-match.ts +11 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/contract.ts +11 -1
- package/src/domains/dispatch/extension.ts +237 -49
- package/src/domains/dispatch/host-verification.ts +435 -39
- package/src/domains/dispatch/intent-requirements.ts +10 -0
- package/src/domains/dispatch/intent.ts +18 -1
- package/src/domains/dispatch/path-scope.ts +235 -24
- package/src/domains/dispatch/run-event-journal.ts +4 -15
- package/src/domains/dispatch/state.ts +2 -3
- package/src/domains/dispatch/transport.ts +45 -21
- package/src/domains/dispatch/types.ts +58 -3
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/artifacts/store.ts +5 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
- package/src/domains/eval/metrics/token-stream.ts +201 -31
- package/src/domains/eval/metrics/tracked.ts +40 -4
- package/src/domains/eval/runners/clio-run.ts +5 -2
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/store.ts +8 -1
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/evidence/trust-status.ts +10 -1
- package/src/domains/extensions/contract.ts +15 -1
- package/src/domains/extensions/discovery.ts +238 -41
- package/src/domains/extensions/extension.ts +105 -6
- package/src/domains/extensions/index.ts +24 -0
- package/src/domains/extensions/integrity.ts +189 -0
- package/src/domains/extensions/manager.ts +17 -1
- package/src/domains/extensions/resource-path.ts +27 -0
- package/src/domains/extensions/resources.ts +18 -38
- package/src/domains/extensions/snapshot-store.ts +39 -0
- package/src/domains/extensions/snapshot.ts +180 -0
- package/src/domains/extensions/state.ts +385 -57
- package/src/domains/extensions/types.ts +118 -1
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
- package/src/domains/lifecycle/migrations/index.ts +6 -0
- package/src/domains/lifecycle/naming-resources.ts +19 -4
- package/src/domains/lifecycle/naming-yazi.ts +10 -5
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/contract.ts +26 -0
- package/src/domains/middleware/extension.ts +24 -24
- package/src/domains/middleware/hook-receipts.ts +27 -4
- package/src/domains/middleware/hooks-io.ts +65 -32
- package/src/domains/middleware/hooks.ts +64 -0
- package/src/domains/middleware/index.ts +28 -5
- package/src/domains/middleware/marketplace-offer.ts +3 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/registrations.ts +326 -0
- package/src/domains/middleware/runtime.ts +28 -0
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/middleware/snapshot.ts +20 -7
- package/src/domains/mux/contract.ts +38 -0
- package/src/domains/mux/detect.ts +6 -13
- package/src/domains/mux/index.ts +1 -1
- package/src/domains/mux/operations.ts +44 -5
- package/src/domains/mux/yazi/assets/yazi.toml +2 -2
- package/src/domains/mux/yazi/session.ts +53 -4
- package/src/domains/mux/yazi/theme.ts +117 -17
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/contract.ts +10 -11
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/extension.ts +17 -4
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/observability/projection.ts +14 -90
- package/src/domains/observability/trace-store.ts +43 -7
- package/src/domains/prompts/compiler.ts +73 -53
- package/src/domains/prompts/contract.ts +15 -3
- package/src/domains/prompts/extension.ts +97 -9
- package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
- package/src/domains/prompts/fragments/identity/clio.md +6 -12
- package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
- package/src/domains/prompts/fragments/operating/contract.md +7 -15
- package/src/domains/prompts/fragments/operating/delegation.md +32 -34
- package/src/domains/prompts/fragments/operating/skills.md +10 -24
- package/src/domains/prompts/fragments/operating/worker.md +1 -8
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/index.ts +1 -1
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +2 -0
- package/src/domains/providers/model-runtime-capabilities.ts +99 -25
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
- package/src/domains/providers/runtime-resolution.ts +31 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
- package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +7 -2
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
- package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
- package/src/domains/providers/support.ts +11 -5
- package/src/domains/providers/target-model-cache.ts +25 -2
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/cost-provenance.ts +19 -0
- package/src/domains/providers/types/local-model-quirks.ts +85 -37
- package/src/domains/providers/types/runtime-descriptor.ts +20 -1
- package/src/domains/providers/types/target-descriptor.ts +19 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/install.ts +72 -7
- package/src/domains/resources/skills/loader.ts +23 -19
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/call-target.ts +1 -1
- package/src/domains/safety/index.ts +1 -0
- package/src/domains/safety/loop-detector.ts +7 -4
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +34 -11
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/entries.ts +6 -0
- package/src/domains/session/task-board.ts +10 -9
- package/src/domains/session/usage.ts +3 -3
- package/src/domains/share/archive.ts +164 -7
- package/src/engine/acp/server.ts +62 -9
- package/src/engine/agent.ts +13 -3
- package/src/engine/ai.ts +26 -8
- package/src/engine/antigravity/subprocess-runtime.ts +386 -120
- package/src/engine/api-registry.ts +3 -0
- package/src/engine/apis/llamacpp-residency.ts +3 -4
- package/src/engine/apis/lmstudio.ts +3 -3
- package/src/engine/apis/ollama-native.ts +6 -6
- package/src/engine/apis/openai-completions.ts +145 -39
- package/src/engine/apis/output-budget.ts +8 -18
- package/src/engine/apis/residency.ts +8 -27
- package/src/engine/external-subprocess.ts +114 -6
- package/src/engine/gemma-channel-filter.ts +19 -0
- package/src/engine/loop-guard.ts +92 -12
- package/src/engine/worker-runtime.ts +40 -11
- package/src/engine/worker-tools.ts +3 -1
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/extension-hook-sources.ts +28 -0
- package/src/entry/extension-reload.ts +309 -0
- package/src/entry/orchestrator.ts +464 -251
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/application-controller.ts +2 -1
- package/src/interactive/bus-notices.ts +8 -1
- package/src/interactive/chat-loop-messages.ts +16 -17
- package/src/interactive/chat-loop.ts +75 -3
- package/src/interactive/chat-panel.ts +36 -13
- package/src/interactive/chat-renderer.ts +72 -7
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/dispatch-board.ts +6 -11
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +39 -4
- package/src/interactive/interactive-input-runtime.ts +4 -0
- package/src/interactive/interactive-presentation.ts +2 -2
- package/src/interactive/interactive-slash-runtime.ts +4 -1
- package/src/interactive/overlays/extensions.ts +9 -1
- package/src/interactive/overlays/help-reference.ts +13 -0
- package/src/interactive/overlays/settings.ts +27 -16
- package/src/interactive/panes-runtime.ts +111 -35
- package/src/interactive/prompt-cache-identity.ts +88 -0
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-commands.ts +153 -20
- package/src/interactive/stream-pacing-policy.ts +0 -23
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +39 -20
- package/src/interactive/turn-recovery.ts +8 -0
- package/src/interactive/turn-runtime.ts +27 -11
- package/src/interactive/turn-state.ts +7 -0
- package/src/interactive/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +6 -1
- package/src/interactive/yazi-bridge.ts +60 -6
- package/src/tools/agent-tools.ts +30 -1
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +3 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +52 -22
- package/src/tools/codewiki/code-nav-surface.ts +6 -0
- package/src/tools/codewiki/code-nav.ts +99 -13
- package/src/tools/context/docs-engine.ts +20 -7
- package/src/tools/context/index.ts +59 -21
- package/src/tools/core-bootstrap.ts +28 -6
- package/src/tools/credential-present.ts +1 -2
- package/src/tools/dispatch-arguments.ts +6 -1
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +49 -4
- package/src/tools/dispatch-run-events.ts +1 -1
- package/src/tools/dispatch-runner.ts +12 -0
- package/src/tools/dispatch-schema.ts +338 -0
- package/src/tools/dispatch-types.ts +3 -0
- package/src/tools/dispatch.ts +9 -254
- package/src/tools/ledger.ts +3 -5
- package/src/tools/monitor-surface.ts +5 -13
- package/src/tools/observation.ts +4 -5
- package/src/tools/panes-surface.ts +4 -11
- package/src/tools/panes.ts +4 -2
- package/src/tools/policy.ts +15 -2
- package/src/tools/read.ts +5 -6
- package/src/tools/registry.ts +41 -12
- package/src/tools/result-shaping.ts +18 -14
- package/src/tools/steer-surface.ts +1 -1
- package/src/tools/tasks.ts +1 -1
- package/src/tools/truncate.ts +6 -5
- package/src/tools/verify/surface.ts +6 -12
- package/src/tools/web-fetch-surface.ts +1 -3
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/builtins-UJLMOVOV.js +0 -17
- package/dist/chunk-5QIAJV2D.js +0 -48
- package/dist/chunk-JZWT5J3Y.js +0 -814
- package/dist/chunk-K7VKOLQQ.js +0 -15
- package/dist/chunk-PMZCIOCJ.js +0 -25
- package/dist/chunk-SUW5DORT.js +0 -819
- package/dist/chunk-UOV2BYIW.js +0 -107
- package/dist/chunk-WR6U3OVP.js +0 -45
- package/dist/chunk-Y45G3AXC.js +0 -1558
- package/dist/reset-EOLM7GVE.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-H7TOM7YL.js +0 -323
- package/docs/artifact-versions.md +0 -67
- package/docs/development-pipeline.md +0 -121
- package/docs/documentation-coverage.md +0 -46
- package/docs/documentation-guide.md +0 -167
- package/docs/time-conventions.md +0 -101
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The arrow-key prompts for `clio-coder configure`: a one-of-many picker, a
|
|
3
|
+
* many-of-many picker, and a single-line text field.
|
|
4
|
+
*
|
|
5
|
+
* Every other prompt in this CLI is a readline line-prompt from `./ask.ts`, and
|
|
6
|
+
* that is still the fallback: raw mode needs a terminal on both ends, and a
|
|
7
|
+
* scripted run, a pipe, or a dumb terminal has neither. `canSelect()` answers
|
|
8
|
+
* whether the interactive path is available, and callers keep the numbered
|
|
9
|
+
* prompt for when it is not, so no invocation loses a way to answer.
|
|
10
|
+
*
|
|
11
|
+
* The escape key is the whole point. A readline menu can only be left by typing
|
|
12
|
+
* the token that means "back", which the screen has to teach; Escape is the key
|
|
13
|
+
* a person already presses. It arrives as a plain keypress here because raw mode
|
|
14
|
+
* turns off the terminal's own line discipline, which is also why Ctrl-C has to
|
|
15
|
+
* be handled by hand: with `setRawMode(true)` no SIGINT is raised and an
|
|
16
|
+
* unhandled Ctrl-C would simply do nothing.
|
|
17
|
+
*
|
|
18
|
+
* The text field exists for the same reason. A wizard whose list steps go back
|
|
19
|
+
* on Escape and whose typed steps do not is worse than one that never offered
|
|
20
|
+
* Escape at all, and readline cannot report the key: it is the start of every
|
|
21
|
+
* arrow sequence, so readline waits half a second and then discards it.
|
|
22
|
+
*/
|
|
23
|
+
import { emitKeypressEvents } from "node:readline";
|
|
24
|
+
import chalk from "chalk";
|
|
25
|
+
|
|
26
|
+
import { column, terminalColumns, truncate } from "./text-layout.js";
|
|
27
|
+
|
|
28
|
+
export interface SelectChoice<T> {
|
|
29
|
+
value: T;
|
|
30
|
+
label: string;
|
|
31
|
+
/** Dim text after the label, for what the entry covers. */
|
|
32
|
+
hint?: string;
|
|
33
|
+
/** Ticked when a multi-select opens. Ignored by the one-of-many picker. */
|
|
34
|
+
checked?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Lines above a prompt, already styled by the caller. An empty string is a bare rail. */
|
|
38
|
+
export type PromptHeading = string | ReadonlyArray<string>;
|
|
39
|
+
|
|
40
|
+
export interface SelectOptions<T> {
|
|
41
|
+
heading?: PromptHeading;
|
|
42
|
+
choices: ReadonlyArray<SelectChoice<T>>;
|
|
43
|
+
/** Index the cursor opens on, clamped into range. */
|
|
44
|
+
initialIndex?: number;
|
|
45
|
+
/** Prefix on every rendered line, so the picker sits on the presenter's rail. */
|
|
46
|
+
railPrefix?: string;
|
|
47
|
+
/** Word for leaving the menu, shown in the key legend. Omit to hide it. */
|
|
48
|
+
backLabel?: string;
|
|
49
|
+
/** Rows to show at once. Defaults to what the terminal has room for. */
|
|
50
|
+
maxVisible?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Erase the menu once it is answered, leaving the caller's transcript to say
|
|
53
|
+
* what was chosen. A wizard that redraws its own answer rows needs this; a
|
|
54
|
+
* settings menu that returns to the same screen does not.
|
|
55
|
+
*/
|
|
56
|
+
clearOnExit?: boolean;
|
|
57
|
+
input?: NodeJS.ReadStream;
|
|
58
|
+
output?: NodeJS.WriteStream;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type SelectResult<T> = { kind: "selected"; value: T } | { kind: "back" } | { kind: "quit" };
|
|
62
|
+
|
|
63
|
+
export interface MultiSelectOptions<T> extends Omit<SelectOptions<T>, "initialIndex"> {
|
|
64
|
+
/** Word for accepting the ticked set, shown in the key legend. */
|
|
65
|
+
confirmLabel?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type MultiSelectResult<T> = { kind: "selected"; values: T[] } | { kind: "back" } | { kind: "quit" };
|
|
69
|
+
|
|
70
|
+
export interface TextPromptOptions {
|
|
71
|
+
heading?: PromptHeading;
|
|
72
|
+
/** Pre-filled and editable. Pressing enter on it returns it unchanged. */
|
|
73
|
+
initial?: string;
|
|
74
|
+
/** Dim line under the field, for what a good answer looks like. */
|
|
75
|
+
hint?: string;
|
|
76
|
+
/** Show dots instead of the characters, for a credential. */
|
|
77
|
+
mask?: boolean;
|
|
78
|
+
/** Reason to refuse the answer and stay on the field, or null to accept it. */
|
|
79
|
+
validate?: (value: string) => string | null;
|
|
80
|
+
railPrefix?: string;
|
|
81
|
+
backLabel?: string;
|
|
82
|
+
clearOnExit?: boolean;
|
|
83
|
+
input?: NodeJS.ReadStream;
|
|
84
|
+
output?: NodeJS.WriteStream;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type TextResult = { kind: "value"; value: string } | { kind: "back" } | { kind: "quit" };
|
|
88
|
+
|
|
89
|
+
/** Whether the arrow-key prompts can run: both ends must be a real terminal. */
|
|
90
|
+
export function canSelect(
|
|
91
|
+
input: NodeJS.ReadStream = process.stdin,
|
|
92
|
+
output: NodeJS.WriteStream = process.stdout,
|
|
93
|
+
): boolean {
|
|
94
|
+
return Boolean(input.isTTY && output.isTTY && typeof input.setRawMode === "function" && process.env.TERM !== "dumb");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const ESC = "\u001B";
|
|
98
|
+
const CURSOR_HIDE = `${ESC}[?25l`;
|
|
99
|
+
const CURSOR_SHOW = `${ESC}[?25h`;
|
|
100
|
+
const ANSI_PATTERN = new RegExp(`${ESC}\\[[0-9;?]*[A-Za-z]`, "gu");
|
|
101
|
+
|
|
102
|
+
/** Printed width of a styled string, which is not its length once it carries color. */
|
|
103
|
+
function printedWidth(text: string): number {
|
|
104
|
+
return text.replace(ANSI_PATTERN, "").length;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface Keypress {
|
|
108
|
+
name?: string;
|
|
109
|
+
ctrl?: boolean;
|
|
110
|
+
meta?: boolean;
|
|
111
|
+
shift?: boolean;
|
|
112
|
+
sequence?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Lines above the list that are not choices, so the viewport can be sized to what is left. */
|
|
116
|
+
function headingLines(heading: PromptHeading | undefined): string[] {
|
|
117
|
+
if (heading === undefined) return [];
|
|
118
|
+
return typeof heading === "string" ? [heading] : [...heading];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Hold the terminal in raw mode for one prompt, resolving on whatever the key
|
|
123
|
+
* handler decides.
|
|
124
|
+
*
|
|
125
|
+
* An input that stops talking is not an answer. Without the `end`/`close` arms
|
|
126
|
+
* a prompt sits on a closed stdin forever, which is what a recorded terminal
|
|
127
|
+
* session and a `script` capture both produce at the end of their key file.
|
|
128
|
+
*/
|
|
129
|
+
async function readKeys<R>(
|
|
130
|
+
input: NodeJS.ReadStream,
|
|
131
|
+
output: NodeJS.WriteStream,
|
|
132
|
+
hideCursor: boolean,
|
|
133
|
+
onStart: () => void,
|
|
134
|
+
onKey: (str: string, key: Keypress, finish: (result: R) => void) => void,
|
|
135
|
+
onEnd: () => R,
|
|
136
|
+
): Promise<R> {
|
|
137
|
+
const wasRaw = input.isRaw === true;
|
|
138
|
+
emitKeypressEvents(input);
|
|
139
|
+
input.setRawMode(true);
|
|
140
|
+
input.resume();
|
|
141
|
+
if (hideCursor) output.write(CURSOR_HIDE);
|
|
142
|
+
onStart();
|
|
143
|
+
try {
|
|
144
|
+
return await new Promise<R>((resolve) => {
|
|
145
|
+
const finish = (result: R): void => {
|
|
146
|
+
input.off("keypress", handleKey);
|
|
147
|
+
input.off("end", handleEnd);
|
|
148
|
+
input.off("close", handleEnd);
|
|
149
|
+
resolve(result);
|
|
150
|
+
};
|
|
151
|
+
function handleEnd(): void {
|
|
152
|
+
finish(onEnd());
|
|
153
|
+
}
|
|
154
|
+
function handleKey(str: string, key: Keypress): void {
|
|
155
|
+
onKey(str, key ?? {}, finish);
|
|
156
|
+
}
|
|
157
|
+
input.on("keypress", handleKey);
|
|
158
|
+
input.once("end", handleEnd);
|
|
159
|
+
input.once("close", handleEnd);
|
|
160
|
+
});
|
|
161
|
+
} finally {
|
|
162
|
+
if (hideCursor) output.write(CURSOR_SHOW);
|
|
163
|
+
if (!wasRaw) input.setRawMode(false);
|
|
164
|
+
input.pause();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Draw one frame in place: up over what was drawn, then clear to the end of the
|
|
170
|
+
* screen. A full clear would take the transcript above the prompt with it.
|
|
171
|
+
*/
|
|
172
|
+
function makeFrame(output: NodeJS.WriteStream): {
|
|
173
|
+
draw: (lines: ReadonlyArray<string>) => void;
|
|
174
|
+
erase: () => void;
|
|
175
|
+
drawn: () => number;
|
|
176
|
+
} {
|
|
177
|
+
let drawn = 0;
|
|
178
|
+
return {
|
|
179
|
+
draw(lines) {
|
|
180
|
+
if (drawn > 0) output.write(`${ESC}[${drawn}A${ESC}[0J`);
|
|
181
|
+
output.write(`${lines.join("\n")}\n`);
|
|
182
|
+
drawn = lines.length;
|
|
183
|
+
},
|
|
184
|
+
erase() {
|
|
185
|
+
if (drawn > 0) output.write(`${ESC}[${drawn}A${ESC}[0J`);
|
|
186
|
+
drawn = 0;
|
|
187
|
+
},
|
|
188
|
+
drawn: () => drawn,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
interface ChoiceRowSpec<T> {
|
|
193
|
+
choices: ReadonlyArray<SelectChoice<T>>;
|
|
194
|
+
rail: string;
|
|
195
|
+
railWidth: number;
|
|
196
|
+
output: NodeJS.WriteStream;
|
|
197
|
+
/** Printed width of everything drawn before the label, cursor included. */
|
|
198
|
+
markerWidth: number;
|
|
199
|
+
marker: (index: number) => string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The choice rows for one frame, windowed to what the terminal can hold. */
|
|
203
|
+
function choiceRows<T>(spec: ChoiceRowSpec<T>, index: number, windowStart: number, viewport: number): string[] {
|
|
204
|
+
const { choices, rail, railWidth, output, markerWidth, marker } = spec;
|
|
205
|
+
// Measured every frame, so a window resized mid-menu lays out correctly on
|
|
206
|
+
// the next keypress rather than at the width the menu opened on.
|
|
207
|
+
const room = terminalColumns(output) - railWidth;
|
|
208
|
+
const hasHints = choices.some((choice) => choice.hint !== undefined);
|
|
209
|
+
const labelWidth = Math.min(30, Math.max(...choices.map((choice) => choice.label.length)));
|
|
210
|
+
const hintRoom = room - markerWidth - labelWidth - 2;
|
|
211
|
+
const end = Math.min(choices.length, windowStart + viewport);
|
|
212
|
+
const lines: string[] = [];
|
|
213
|
+
if (windowStart > 0) lines.push(`${rail}${chalk.dim(` ↑ ${windowStart} more`)}`);
|
|
214
|
+
for (let position = windowStart; position < end; position++) {
|
|
215
|
+
const choice = choices[position];
|
|
216
|
+
if (choice === undefined) continue;
|
|
217
|
+
const active = position === index;
|
|
218
|
+
// Widths are computed on the unstyled text and the color applied
|
|
219
|
+
// afterwards. Truncating the styled string counted escape bytes as
|
|
220
|
+
// columns, so the highlighted row, which carries the most escapes, was
|
|
221
|
+
// cut several characters shorter than every other row.
|
|
222
|
+
const aligned = hasHints && hintRoom >= 12;
|
|
223
|
+
const label = aligned ? column(choice.label, labelWidth) : truncate(choice.label, room - markerWidth);
|
|
224
|
+
const hint = aligned && choice.hint !== undefined ? truncate(choice.hint, hintRoom) : "";
|
|
225
|
+
const styledLabel = active ? chalk.cyan.bold(label) : label;
|
|
226
|
+
lines.push(`${rail}${marker(position)}${styledLabel}${hint.length > 0 ? ` ${chalk.dim(hint)}` : ""}`.trimEnd());
|
|
227
|
+
}
|
|
228
|
+
if (end < choices.length) lines.push(`${rail}${chalk.dim(` ↓ ${choices.length - end} more`)}`);
|
|
229
|
+
return lines;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Rows to show at once. The list scrolls rather than overflowing, because a
|
|
234
|
+
* frame taller than the terminal cannot be redrawn in place: the cursor-up that
|
|
235
|
+
* opens the next frame lands in the middle of the previous one.
|
|
236
|
+
*/
|
|
237
|
+
function viewportFor(output: NodeJS.WriteStream, overhead: number, total: number, requested?: number): number {
|
|
238
|
+
if (requested !== undefined) return Math.max(1, Math.min(total, requested));
|
|
239
|
+
const rows = typeof output.rows === "number" && output.rows > 0 ? output.rows : 24;
|
|
240
|
+
return Math.max(3, Math.min(total, rows - overhead));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export async function promptSelect<T>(options: SelectOptions<T>): Promise<SelectResult<T>> {
|
|
244
|
+
const input = options.input ?? process.stdin;
|
|
245
|
+
const output = options.output ?? process.stdout;
|
|
246
|
+
const choices = options.choices;
|
|
247
|
+
if (choices.length === 0) return { kind: "back" };
|
|
248
|
+
|
|
249
|
+
const rail = options.railPrefix ?? "";
|
|
250
|
+
// The rail prefix carries color, so its printed length is not its string
|
|
251
|
+
// length; the caller's indentation is two spaces plus one glyph either way.
|
|
252
|
+
const railWidth = 3;
|
|
253
|
+
const head = headingLines(options.heading);
|
|
254
|
+
const frame = makeFrame(output);
|
|
255
|
+
|
|
256
|
+
let index = Math.min(Math.max(options.initialIndex ?? 0, 0), choices.length - 1);
|
|
257
|
+
let windowStart = 0;
|
|
258
|
+
|
|
259
|
+
const render = (): void => {
|
|
260
|
+
const viewport = viewportFor(output, head.length + 5, choices.length, options.maxVisible);
|
|
261
|
+
if (index < windowStart) windowStart = index;
|
|
262
|
+
else if (index >= windowStart + viewport) windowStart = index - viewport + 1;
|
|
263
|
+
windowStart = Math.max(0, Math.min(windowStart, choices.length - viewport));
|
|
264
|
+
const lines: string[] = [];
|
|
265
|
+
for (const line of head) lines.push(`${rail}${line}`.trimEnd());
|
|
266
|
+
if (head.length > 0) lines.push(rail.trimEnd());
|
|
267
|
+
lines.push(
|
|
268
|
+
...choiceRows(
|
|
269
|
+
{
|
|
270
|
+
choices,
|
|
271
|
+
rail,
|
|
272
|
+
railWidth,
|
|
273
|
+
output,
|
|
274
|
+
markerWidth: 2,
|
|
275
|
+
marker: (position) => `${position === index ? chalk.cyan("❯") : " "} `,
|
|
276
|
+
},
|
|
277
|
+
index,
|
|
278
|
+
windowStart,
|
|
279
|
+
viewport,
|
|
280
|
+
),
|
|
281
|
+
);
|
|
282
|
+
lines.push(rail.trimEnd());
|
|
283
|
+
// On the top screen escape and q do the same thing, and listing both as
|
|
284
|
+
// "quit" reads as two different exits.
|
|
285
|
+
const legend = ["↑/↓ move", "enter select"];
|
|
286
|
+
if (options.backLabel !== undefined && options.backLabel !== "quit") legend.push(`esc ${options.backLabel}`);
|
|
287
|
+
legend.push(options.backLabel === "quit" ? "esc or q quit" : "q quit");
|
|
288
|
+
lines.push(`${rail}${chalk.dim(legend.join(" · "))}`);
|
|
289
|
+
frame.draw(lines);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const result = await readKeys<SelectResult<T>>(
|
|
293
|
+
input,
|
|
294
|
+
output,
|
|
295
|
+
true,
|
|
296
|
+
render,
|
|
297
|
+
(_str, key, finish) => {
|
|
298
|
+
if (key.ctrl && (key.name === "c" || key.name === "d")) {
|
|
299
|
+
finish({ kind: "quit" });
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
switch (key.name) {
|
|
303
|
+
case "up":
|
|
304
|
+
case "k":
|
|
305
|
+
index = (index - 1 + choices.length) % choices.length;
|
|
306
|
+
render();
|
|
307
|
+
return;
|
|
308
|
+
case "down":
|
|
309
|
+
case "j":
|
|
310
|
+
case "tab":
|
|
311
|
+
index = (index + 1) % choices.length;
|
|
312
|
+
render();
|
|
313
|
+
return;
|
|
314
|
+
case "pageup":
|
|
315
|
+
index = Math.max(0, index - 5);
|
|
316
|
+
render();
|
|
317
|
+
return;
|
|
318
|
+
case "pagedown":
|
|
319
|
+
index = Math.min(choices.length - 1, index + 5);
|
|
320
|
+
render();
|
|
321
|
+
return;
|
|
322
|
+
case "home":
|
|
323
|
+
index = 0;
|
|
324
|
+
render();
|
|
325
|
+
return;
|
|
326
|
+
case "end":
|
|
327
|
+
index = choices.length - 1;
|
|
328
|
+
render();
|
|
329
|
+
return;
|
|
330
|
+
case "return":
|
|
331
|
+
case "enter":
|
|
332
|
+
case "space": {
|
|
333
|
+
const choice = choices[index];
|
|
334
|
+
finish(choice === undefined ? { kind: "back" } : { kind: "selected", value: choice.value });
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
case "escape":
|
|
338
|
+
case "left":
|
|
339
|
+
case "backspace":
|
|
340
|
+
finish({ kind: "back" });
|
|
341
|
+
return;
|
|
342
|
+
case "q":
|
|
343
|
+
finish({ kind: "quit" });
|
|
344
|
+
return;
|
|
345
|
+
default: {
|
|
346
|
+
// A digit picks that row directly, so the muscle memory the
|
|
347
|
+
// numbered menu built still works.
|
|
348
|
+
const digit = Number.parseInt(key.name ?? "", 10);
|
|
349
|
+
if (Number.isInteger(digit) && digit >= 1 && digit <= choices.length) {
|
|
350
|
+
index = digit - 1;
|
|
351
|
+
render();
|
|
352
|
+
const choice = choices[index];
|
|
353
|
+
if (choice !== undefined) finish({ kind: "selected", value: choice.value });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
() => ({ kind: "quit" }),
|
|
359
|
+
);
|
|
360
|
+
if (options.clearOnExit) frame.erase();
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Tick any number of entries and confirm once.
|
|
366
|
+
*
|
|
367
|
+
* This is what replaces a run of `[y/N]` questions, one per detected thing. The
|
|
368
|
+
* questions were identical apart from a name, and asking them in sequence hid
|
|
369
|
+
* how many there were and gave no way to change the first answer after seeing
|
|
370
|
+
* the last.
|
|
371
|
+
*/
|
|
372
|
+
export async function promptMultiSelect<T>(options: MultiSelectOptions<T>): Promise<MultiSelectResult<T>> {
|
|
373
|
+
const input = options.input ?? process.stdin;
|
|
374
|
+
const output = options.output ?? process.stdout;
|
|
375
|
+
const choices = options.choices;
|
|
376
|
+
if (choices.length === 0) return { kind: "selected", values: [] };
|
|
377
|
+
|
|
378
|
+
const rail = options.railPrefix ?? "";
|
|
379
|
+
const railWidth = 3;
|
|
380
|
+
const head = headingLines(options.heading);
|
|
381
|
+
const frame = makeFrame(output);
|
|
382
|
+
const checked = choices.map((choice) => choice.checked === true);
|
|
383
|
+
|
|
384
|
+
let index = 0;
|
|
385
|
+
let windowStart = 0;
|
|
386
|
+
|
|
387
|
+
const render = (): void => {
|
|
388
|
+
const viewport = viewportFor(output, head.length + 5, choices.length, options.maxVisible);
|
|
389
|
+
if (index < windowStart) windowStart = index;
|
|
390
|
+
else if (index >= windowStart + viewport) windowStart = index - viewport + 1;
|
|
391
|
+
windowStart = Math.max(0, Math.min(windowStart, choices.length - viewport));
|
|
392
|
+
const lines: string[] = [];
|
|
393
|
+
for (const line of head) lines.push(`${rail}${line}`.trimEnd());
|
|
394
|
+
if (head.length > 0) lines.push(rail.trimEnd());
|
|
395
|
+
lines.push(
|
|
396
|
+
...choiceRows(
|
|
397
|
+
{
|
|
398
|
+
choices,
|
|
399
|
+
rail,
|
|
400
|
+
railWidth,
|
|
401
|
+
output,
|
|
402
|
+
markerWidth: 4,
|
|
403
|
+
marker: (position) => {
|
|
404
|
+
const cursor = position === index ? chalk.cyan("❯") : " ";
|
|
405
|
+
const box = checked[position] === true ? chalk.green("◉") : chalk.dim("○");
|
|
406
|
+
return `${cursor} ${box} `;
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
index,
|
|
410
|
+
windowStart,
|
|
411
|
+
viewport,
|
|
412
|
+
),
|
|
413
|
+
);
|
|
414
|
+
lines.push(rail.trimEnd());
|
|
415
|
+
const legend = ["↑/↓ move", "space toggle", `enter ${options.confirmLabel ?? "confirm"}`];
|
|
416
|
+
if (options.backLabel !== undefined) legend.push(`esc ${options.backLabel}`);
|
|
417
|
+
lines.push(`${rail}${chalk.dim(legend.join(" · "))}`);
|
|
418
|
+
frame.draw(lines);
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const result = await readKeys<MultiSelectResult<T>>(
|
|
422
|
+
input,
|
|
423
|
+
output,
|
|
424
|
+
true,
|
|
425
|
+
render,
|
|
426
|
+
(_str, key, finish) => {
|
|
427
|
+
if (key.ctrl && (key.name === "c" || key.name === "d")) {
|
|
428
|
+
finish({ kind: "quit" });
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
switch (key.name) {
|
|
432
|
+
case "up":
|
|
433
|
+
case "k":
|
|
434
|
+
index = (index - 1 + choices.length) % choices.length;
|
|
435
|
+
render();
|
|
436
|
+
return;
|
|
437
|
+
case "down":
|
|
438
|
+
case "j":
|
|
439
|
+
case "tab":
|
|
440
|
+
index = (index + 1) % choices.length;
|
|
441
|
+
render();
|
|
442
|
+
return;
|
|
443
|
+
case "home":
|
|
444
|
+
index = 0;
|
|
445
|
+
render();
|
|
446
|
+
return;
|
|
447
|
+
case "end":
|
|
448
|
+
index = choices.length - 1;
|
|
449
|
+
render();
|
|
450
|
+
return;
|
|
451
|
+
case "space":
|
|
452
|
+
checked[index] = checked[index] !== true;
|
|
453
|
+
render();
|
|
454
|
+
return;
|
|
455
|
+
case "a":
|
|
456
|
+
// One key for "all of them", because the alternative on a list of
|
|
457
|
+
// six is six presses of space with nothing telling you that.
|
|
458
|
+
{
|
|
459
|
+
const turnOn = checked.some((value) => !value);
|
|
460
|
+
checked.fill(turnOn);
|
|
461
|
+
}
|
|
462
|
+
render();
|
|
463
|
+
return;
|
|
464
|
+
case "return":
|
|
465
|
+
case "enter":
|
|
466
|
+
finish({
|
|
467
|
+
kind: "selected",
|
|
468
|
+
values: choices.filter((_choice, position) => checked[position] === true).map((choice) => choice.value),
|
|
469
|
+
});
|
|
470
|
+
return;
|
|
471
|
+
case "escape":
|
|
472
|
+
case "left":
|
|
473
|
+
finish({ kind: "back" });
|
|
474
|
+
return;
|
|
475
|
+
default: {
|
|
476
|
+
const digit = Number.parseInt(key.name ?? "", 10);
|
|
477
|
+
if (Number.isInteger(digit) && digit >= 1 && digit <= choices.length) {
|
|
478
|
+
index = digit - 1;
|
|
479
|
+
checked[index] = checked[index] !== true;
|
|
480
|
+
render();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
() => ({ kind: "quit" }),
|
|
486
|
+
);
|
|
487
|
+
if (options.clearOnExit) frame.erase();
|
|
488
|
+
return result;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** Printable text from one keypress, including a paste that arrives whole. */
|
|
492
|
+
function typedText(str: string, key: Keypress): string | null {
|
|
493
|
+
if (key.ctrl === true || key.meta === true) return null;
|
|
494
|
+
if (typeof str !== "string" || str.length === 0) return null;
|
|
495
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: the point is to reject them
|
|
496
|
+
if (/[\u0000-\u001F\u007F]/u.test(str)) return null;
|
|
497
|
+
return str;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* One line of text with a default already in the field, Escape to go back.
|
|
502
|
+
*
|
|
503
|
+
* The terminal cursor is left visible and moved onto the field rather than
|
|
504
|
+
* drawn as an inverted cell: under NO_COLOR an inverted cell renders as nothing
|
|
505
|
+
* at all, and a text field with no cursor is a field you cannot tell is
|
|
506
|
+
* focused.
|
|
507
|
+
*/
|
|
508
|
+
export async function promptText(options: TextPromptOptions): Promise<TextResult> {
|
|
509
|
+
const input = options.input ?? process.stdin;
|
|
510
|
+
const output = options.output ?? process.stdout;
|
|
511
|
+
const rail = options.railPrefix ?? "";
|
|
512
|
+
const railWidth = printedWidth(rail);
|
|
513
|
+
const head = headingLines(options.heading);
|
|
514
|
+
const frame = makeFrame(output);
|
|
515
|
+
|
|
516
|
+
let value = options.initial ?? "";
|
|
517
|
+
let caret = value.length;
|
|
518
|
+
let error: string | null = null;
|
|
519
|
+
/** Lines drawn below the field, so the cursor can be put back on it. */
|
|
520
|
+
let below = 0;
|
|
521
|
+
/** Whether the cursor is currently parked on the field rather than after the frame. */
|
|
522
|
+
let parked = false;
|
|
523
|
+
|
|
524
|
+
const render = (): void => {
|
|
525
|
+
if (parked) {
|
|
526
|
+
output.write(`\r${below > 0 ? `${ESC}[${below}B` : ""}`);
|
|
527
|
+
parked = false;
|
|
528
|
+
}
|
|
529
|
+
const room = Math.max(8, terminalColumns(output) - railWidth - 2);
|
|
530
|
+
const shown = options.mask === true ? "•".repeat(value.length) : value;
|
|
531
|
+
const lines: string[] = [];
|
|
532
|
+
for (const line of head) lines.push(`${rail}${line}`.trimEnd());
|
|
533
|
+
if (head.length > 0) lines.push(rail.trimEnd());
|
|
534
|
+
const fieldIndex = lines.length;
|
|
535
|
+
lines.push(`${rail}${chalk.cyan("❯")} ${truncate(shown, room)}`);
|
|
536
|
+
if (error !== null) lines.push(`${rail}${chalk.yellow(truncate(error, room))}`);
|
|
537
|
+
else if (options.hint !== undefined) lines.push(`${rail}${chalk.dim(truncate(options.hint, room))}`);
|
|
538
|
+
lines.push(rail.trimEnd());
|
|
539
|
+
const legend = ["enter accept"];
|
|
540
|
+
if (options.backLabel !== undefined) legend.push(`esc ${options.backLabel}`);
|
|
541
|
+
legend.push("ctrl-c quit");
|
|
542
|
+
lines.push(`${rail}${chalk.dim(legend.join(" · "))}`);
|
|
543
|
+
frame.draw(lines);
|
|
544
|
+
below = lines.length - fieldIndex;
|
|
545
|
+
// Park the terminal's own cursor on the field, at the edit position.
|
|
546
|
+
const columnOffset = railWidth + 2 + Math.min(caret, room);
|
|
547
|
+
output.write(`${ESC}[${below}A\r${columnOffset > 0 ? `${ESC}[${columnOffset}C` : ""}`);
|
|
548
|
+
parked = true;
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
const unpark = (): void => {
|
|
552
|
+
if (!parked) return;
|
|
553
|
+
output.write(`\r${below > 0 ? `${ESC}[${below}B` : ""}`);
|
|
554
|
+
parked = false;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const result = await readKeys<TextResult>(
|
|
558
|
+
input,
|
|
559
|
+
output,
|
|
560
|
+
false,
|
|
561
|
+
render,
|
|
562
|
+
(str, key, finish) => {
|
|
563
|
+
if (key.ctrl === true) {
|
|
564
|
+
switch (key.name) {
|
|
565
|
+
case "c":
|
|
566
|
+
case "d":
|
|
567
|
+
unpark();
|
|
568
|
+
finish({ kind: "quit" });
|
|
569
|
+
return;
|
|
570
|
+
case "a":
|
|
571
|
+
caret = 0;
|
|
572
|
+
render();
|
|
573
|
+
return;
|
|
574
|
+
case "e":
|
|
575
|
+
caret = value.length;
|
|
576
|
+
render();
|
|
577
|
+
return;
|
|
578
|
+
case "u":
|
|
579
|
+
value = value.slice(caret);
|
|
580
|
+
caret = 0;
|
|
581
|
+
render();
|
|
582
|
+
return;
|
|
583
|
+
case "k":
|
|
584
|
+
value = value.slice(0, caret);
|
|
585
|
+
render();
|
|
586
|
+
return;
|
|
587
|
+
case "w": {
|
|
588
|
+
const head_ = value.slice(0, caret).replace(/\S+\s*$/u, "");
|
|
589
|
+
value = head_ + value.slice(caret);
|
|
590
|
+
caret = head_.length;
|
|
591
|
+
render();
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
default:
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
switch (key.name) {
|
|
599
|
+
case "escape":
|
|
600
|
+
unpark();
|
|
601
|
+
finish({ kind: "back" });
|
|
602
|
+
return;
|
|
603
|
+
case "return":
|
|
604
|
+
case "enter": {
|
|
605
|
+
const answer = value.trim();
|
|
606
|
+
const reason = options.validate?.(answer) ?? null;
|
|
607
|
+
if (reason !== null) {
|
|
608
|
+
error = reason;
|
|
609
|
+
render();
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
unpark();
|
|
613
|
+
finish({ kind: "value", value: answer });
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
case "backspace":
|
|
617
|
+
if (caret > 0) {
|
|
618
|
+
value = value.slice(0, caret - 1) + value.slice(caret);
|
|
619
|
+
caret -= 1;
|
|
620
|
+
error = null;
|
|
621
|
+
render();
|
|
622
|
+
}
|
|
623
|
+
return;
|
|
624
|
+
case "delete":
|
|
625
|
+
if (caret < value.length) {
|
|
626
|
+
value = value.slice(0, caret) + value.slice(caret + 1);
|
|
627
|
+
error = null;
|
|
628
|
+
render();
|
|
629
|
+
}
|
|
630
|
+
return;
|
|
631
|
+
case "left":
|
|
632
|
+
caret = Math.max(0, caret - 1);
|
|
633
|
+
render();
|
|
634
|
+
return;
|
|
635
|
+
case "right":
|
|
636
|
+
caret = Math.min(value.length, caret + 1);
|
|
637
|
+
render();
|
|
638
|
+
return;
|
|
639
|
+
case "home":
|
|
640
|
+
caret = 0;
|
|
641
|
+
render();
|
|
642
|
+
return;
|
|
643
|
+
case "end":
|
|
644
|
+
caret = value.length;
|
|
645
|
+
render();
|
|
646
|
+
return;
|
|
647
|
+
default: {
|
|
648
|
+
const typed = typedText(str, key);
|
|
649
|
+
if (typed === null) return;
|
|
650
|
+
value = value.slice(0, caret) + typed + value.slice(caret);
|
|
651
|
+
caret += typed.length;
|
|
652
|
+
error = null;
|
|
653
|
+
render();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
() => {
|
|
658
|
+
unpark();
|
|
659
|
+
return { kind: "quit" };
|
|
660
|
+
},
|
|
661
|
+
);
|
|
662
|
+
if (options.clearOnExit) frame.erase();
|
|
663
|
+
return result;
|
|
664
|
+
}
|
package/src/cli/share.ts
CHANGED
|
@@ -142,7 +142,11 @@ function printDiagnostics(diagnostics: ReadonlyArray<ShareDiagnostic>): void {
|
|
|
142
142
|
|
|
143
143
|
function printRecovery(plan: ShareImportPlan): void {
|
|
144
144
|
if (!plan.recovery) return;
|
|
145
|
-
process.stderr.write(
|
|
145
|
+
process.stderr.write(
|
|
146
|
+
plan.recovery.failed
|
|
147
|
+
? "recovery: import stopped after a write failure\n"
|
|
148
|
+
: "recovery: import completed with preserved backups\n",
|
|
149
|
+
);
|
|
146
150
|
process.stderr.write("written files:\n");
|
|
147
151
|
if (plan.recovery.written.length === 0) process.stderr.write(" none\n");
|
|
148
152
|
else {
|
package/src/cli/skills-eval.ts
CHANGED
|
@@ -51,9 +51,9 @@ const DEFAULT_RUN_TIMEOUT_MS = 600_000;
|
|
|
51
51
|
*
|
|
52
52
|
* A headless `clio-coder run` has no operator to answer a permission ask, so below
|
|
53
53
|
* full-auto every exec-class call in an arm dies with the harness's own denial
|
|
54
|
-
* and the judge scores a skill that was never allowed to act.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* and the judge scores a skill that was never allowed to act. The 2026-08-13
|
|
55
|
+
* harness decision is that eval arms run full-auto because their workspaces
|
|
56
|
+
* are per-run copies created under a
|
|
57
57
|
* private temp root and removed when the scenario ends. The judge arm is
|
|
58
58
|
* excluded: it scores text and is instructed to call no tools, so granting it
|
|
59
59
|
* unattended write and exec buys nothing.
|