@iowarp/clio-coder 0.4.4 → 0.4.6
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 +116 -2
- package/CONTRIBUTING.md +39 -24
- package/NOTICE +16 -0
- package/README.md +343 -403
- package/dist/{acp-WNAYYF4F.js → acp-UVEVWSDL.js} +25 -24
- package/dist/{agents-3OKXHLOI.js → agents-VWY37DTK.js} +78 -77
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-VKNNMGPU.js → auth-PCV2XQDV.js} +38 -38
- package/dist/builtins-PD652MTK.js +22 -0
- package/dist/{chunk-TQAHXW6Y.js → chunk-22PQ4TX4.js} +4 -4
- package/dist/{chunk-NRO2BJRH.js → chunk-24T2YZ7A.js} +10686 -4464
- package/dist/{chunk-Y55JBDO5.js → chunk-2AKYFREM.js} +38 -23
- package/dist/{chunk-NEDJ26B5.js → chunk-2GPGAE5W.js} +6 -51
- package/dist/{chunk-IKCO5N3L.js → chunk-2QPI3TR3.js} +3 -3
- package/dist/{chunk-HRQMFLJP.js → chunk-32KJPXAM.js} +6 -6
- package/dist/{chunk-65DEGPJ6.js → chunk-3A3CUMKA.js} +6 -4
- package/dist/{chunk-UXCU4E3T.js → chunk-3BJGMT2D.js} +35 -14
- package/dist/{chunk-5ICU3EUH.js → chunk-3HQVBIKD.js} +5 -5
- package/dist/{chunk-GWZNEVM2.js → chunk-3JLFK5MW.js} +9 -9
- package/dist/{chunk-XXYSBZIQ.js → chunk-3O2ZAUGQ.js} +4 -4
- package/dist/{chunk-GX5WYQO4.js → chunk-3QKXHCGS.js} +8 -8
- package/dist/{chunk-JCI2ROMZ.js → chunk-3T4DXWP6.js} +7 -7
- package/dist/{chunk-DR52UMZW.js → chunk-3UW3KU4A.js} +2 -2
- package/dist/{chunk-OEJSLEPW.js → chunk-3WBALRQH.js} +337 -337
- package/dist/{chunk-ELWDPP3Y.js → chunk-4DU2TVI4.js} +8 -8
- package/dist/{chunk-JSD46VO2.js → chunk-4U4TKZFR.js} +43 -36
- package/dist/{chunk-FEAXX7B6.js → chunk-4VMV6OS6.js} +4 -4
- package/dist/{chunk-2ZSONWVL.js → chunk-536HXRFE.js} +13 -13
- package/dist/{chunk-W54I7H25.js → chunk-5A6XR3RJ.js} +44 -19
- package/dist/{chunk-YPC6ZR5L.js → chunk-5CMARGPF.js} +119 -5
- package/dist/{chunk-KXDSS5WJ.js → chunk-5CY4Q6QI.js} +4 -4
- package/dist/{chunk-D4CJV46V.js → chunk-5GZICIYO.js} +3 -3
- package/dist/{chunk-4IUZQIJ3.js → chunk-5PHVPU4G.js} +2 -2
- package/dist/{chunk-Q4WO54TA.js → chunk-5QRX7SLS.js} +11 -11
- package/dist/{chunk-3ODX73FK.js → chunk-5VTJP36Q.js} +4 -4
- package/dist/chunk-5ZSZEYJK.js +119 -0
- package/dist/{chunk-EBY63B7G.js → chunk-6EXUUOSN.js} +2 -2
- package/dist/{chunk-DT3LWJOB.js → chunk-6HAO6X5B.js} +24 -6
- package/dist/{chunk-SVNXH4L2.js → chunk-6ICZKDUC.js} +2 -2
- package/dist/{chunk-K6T2ZAMZ.js → chunk-6OII3LOK.js} +6 -6
- package/dist/{chunk-36CT5VVL.js → chunk-6RYDAVQT.js} +138 -89
- package/dist/{chunk-I7XBWTYH.js → chunk-6VRRJT7L.js} +5 -5
- package/dist/{chunk-DQOVN6KV.js → chunk-6YA46L5A.js} +4 -4
- package/dist/{chunk-NZMNUPZZ.js → chunk-77CZRFTE.js} +3 -3
- package/dist/{chunk-NAI6ZFCY.js → chunk-7JSSKXG2.js} +122 -11
- package/dist/{chunk-2VTFPG5O.js → chunk-7WLRF2U5.js} +2 -2
- package/dist/chunk-7WUZEB2M.js +165 -0
- package/dist/{chunk-3UUXNFEX.js → chunk-7YJWEF2L.js} +61 -34
- package/dist/{chunk-3EBYEESD.js → chunk-A46ILRS2.js} +5 -5
- package/dist/{chunk-IXIY2H4R.js → chunk-ACCKVSHU.js} +5 -5
- package/dist/{chunk-UOIZ7DA4.js → chunk-AP7HDJOP.js} +2 -2
- package/dist/{chunk-JEIYHLOR.js → chunk-B3MOMLJ4.js} +12 -12
- package/dist/{chunk-APJ265NV.js → chunk-B5GGDIHT.js} +146 -146
- package/dist/{chunk-PMZVFWSR.js → chunk-B5ZTR6KZ.js} +2 -2
- package/dist/{chunk-I5FWO7L5.js → chunk-B6UM3OZC.js} +2 -2
- package/dist/{chunk-2CU2H6KE.js → chunk-BBV5TKE6.js} +5 -5
- package/dist/{chunk-23L32XTI.js → chunk-BLTEAUCB.js} +68 -39
- package/dist/{chunk-4O6MANBS.js → chunk-BS4GAMUB.js} +14 -10
- package/dist/{chunk-XULDXHTN.js → chunk-BT7HGDOX.js} +105 -53
- package/dist/{chunk-S66XZJOF.js → chunk-C27U2TYG.js} +2 -2
- package/dist/{chunk-QZWQA4DE.js → chunk-CBSKDFWL.js} +3 -3
- package/dist/{chunk-2LEAKD4C.js → chunk-CKK25WN3.js} +3 -3
- package/dist/{chunk-BYP5D4HI.js → chunk-CTTI7G3T.js} +2 -2
- package/dist/{chunk-XAKHZX5N.js → chunk-CVDAFGPW.js} +4 -4
- package/dist/{chunk-RKKLTLYB.js → chunk-CXQ37WJH.js} +3 -3
- package/dist/{chunk-GTUD2WMY.js → chunk-DBREN25X.js} +44 -9
- package/dist/{chunk-NDDGJUXD.js → chunk-DNCE23JJ.js} +2 -2
- package/dist/{chunk-HVDIIIQW.js → chunk-DNHVRBH4.js} +3 -3
- package/dist/{chunk-D7E7WCDF.js → chunk-DVNAPPXU.js} +2 -2
- package/dist/{chunk-6UINWWS6.js → chunk-DXLUVUD4.js} +16 -16
- package/dist/{chunk-YXLYO42X.js → chunk-DXVMLM3Z.js} +3 -2
- package/dist/{chunk-5MEZN6CB.js → chunk-DZK63TZJ.js} +6 -6
- package/dist/{chunk-IWHMRKLL.js → chunk-E3LEPLQ2.js} +2 -2
- package/dist/{chunk-JT2RFCC5.js → chunk-E7RF4KBO.js} +5 -5
- package/dist/{chunk-3R73A4XB.js → chunk-ECBHH7LU.js} +3 -3
- package/dist/chunk-ECOMVOHP.js +139 -0
- package/dist/chunk-EFSEIZE6.js +56 -0
- package/dist/{chunk-4NSRCOYP.js → chunk-EHOSNVVM.js} +3 -2
- package/dist/chunk-EM2WNQS2.js +93 -0
- package/dist/{chunk-57XXR6DR.js → chunk-F5Z7EWMN.js} +967 -246
- package/dist/{chunk-HAXOFFRH.js → chunk-FQOOGXBH.js} +7 -7
- package/dist/{chunk-ZTJUVLTU.js → chunk-FXFVDPWY.js} +2 -2
- package/dist/{chunk-XPLRXC72.js → chunk-GD55RTIW.js} +3 -3
- package/dist/{chunk-5B2AEOW5.js → chunk-GH5ZR6JP.js} +472 -472
- package/dist/{chunk-TOIVGRUX.js → chunk-GJ24ODAX.js} +5 -5
- package/dist/{chunk-EXLD33WO.js → chunk-GLYBJ4RQ.js} +24 -9
- package/dist/{chunk-26QSH3EJ.js → chunk-HHVJNVUJ.js} +5 -5
- package/dist/{chunk-F4EKGO4N.js → chunk-HL26ADLH.js} +4 -2
- package/dist/{chunk-FFUPXJC4.js → chunk-HPTJF6DG.js} +32 -56
- package/dist/{chunk-ID64D7PE.js → chunk-HXHFDHB6.js} +24 -24
- package/dist/{chunk-CUSRQKPU.js → chunk-HZ2T2YED.js} +299 -89
- package/dist/{chunk-YD5GIKET.js → chunk-HZFBVU5X.js} +49 -580
- package/dist/{chunk-6QOTUPRG.js → chunk-I2K2NCZQ.js} +65 -17
- package/dist/{chunk-SZAA6XDG.js → chunk-IFDRAD6F.js} +2 -2
- package/dist/{chunk-I2DWJ4GM.js → chunk-IGLVVNEG.js} +54 -42
- package/dist/{chunk-6Q3CYFD3.js → chunk-IKRWLEDA.js} +186 -35
- package/dist/{chunk-2JH2WHGE.js → chunk-J2FYEQ5L.js} +4 -4
- package/dist/{chunk-BMS5RKQY.js → chunk-JABWPKFY.js} +3 -3
- package/dist/{chunk-2DSOYNFC.js → chunk-JMPL7NUB.js} +7 -7
- package/dist/{chunk-QDC3K2U3.js → chunk-K2BLQC5E.js} +3 -3
- package/dist/{chunk-AUPNRN7C.js → chunk-K2HL3GBL.js} +4 -4
- package/dist/{chunk-54X7T7DK.js → chunk-KAFMW7WM.js} +72 -81
- package/dist/{chunk-OZNBF4L3.js → chunk-KECNXMDE.js} +2 -2
- package/dist/{chunk-BTK3SSSK.js → chunk-KMF54VH3.js} +2 -2
- package/dist/chunk-KPRLAMP4.js +32 -0
- package/dist/{chunk-ECH6PKUQ.js → chunk-KQ6IDQIB.js} +2 -2
- package/dist/{chunk-3UNOLWNZ.js → chunk-KTFSFCVN.js} +20 -9
- package/dist/{chunk-IRXAATOX.js → chunk-L4N3DWNW.js} +3 -3
- package/dist/{chunk-JQLNNIKT.js → chunk-LIN2K3EL.js} +6 -6
- package/dist/{chunk-2STGEDFV.js → chunk-LK2FN5JY.js} +2 -2
- package/dist/{chunk-LCGCVYZ4.js → chunk-LQTKDAUO.js} +2 -2
- package/dist/{chunk-U6TMQNSI.js → chunk-LTR5QCLS.js} +4 -4
- package/dist/chunk-LUL5Z66S.js +221 -0
- package/dist/{chunk-ELZVTCGV.js → chunk-LVFANMOH.js} +151 -327
- package/dist/{chunk-H7IXIC72.js → chunk-LY4N4TTL.js} +17 -3
- package/dist/{chunk-VKPAQYEB.js → chunk-LZBMXNLP.js} +5 -5
- package/dist/{chunk-UL3WSD3F.js → chunk-M4KFUXS7.js} +2 -2
- package/dist/{chunk-NXYCB2VD.js → chunk-M6TAYK66.js} +6 -6
- package/dist/{chunk-CFGTUFWB.js → chunk-MCJKEGHO.js} +2 -2
- package/dist/{chunk-6XLNIQDB.js → chunk-MYI32N4R.js} +2 -2
- package/dist/{chunk-4WR7VSYB.js → chunk-N2OKBREN.js} +23 -9
- package/dist/{chunk-3GY4F45V.js → chunk-NC4KV7EL.js} +6 -6
- package/dist/{chunk-LLXSDWXS.js → chunk-NF3BK5WR.js} +5 -5
- package/dist/{chunk-4M6Z5QVF.js → chunk-NNWJYUNO.js} +11 -11
- package/dist/chunk-NTK3WTHM.js +141 -0
- package/dist/{chunk-GYV6VZOC.js → chunk-NTTS3O53.js} +2 -2
- package/dist/{chunk-4BJ5BYCE.js → chunk-O3VV6IVK.js} +2 -2
- package/dist/{chunk-W6GROXXM.js → chunk-O5F25NIE.js} +2 -2
- package/dist/{chunk-NXIMQY5W.js → chunk-ODUTYZIU.js} +5 -5
- package/dist/{chunk-KFV5L5SK.js → chunk-OQM5IVJY.js} +118 -232
- package/dist/{chunk-75W7L2E2.js → chunk-P5JMBPDJ.js} +1052 -171
- package/dist/{chunk-XRZT5WY5.js → chunk-P5SC4DLJ.js} +4 -4
- package/dist/{chunk-S6PYF2XF.js → chunk-P6M7RKMI.js} +4 -4
- package/dist/{chunk-R6Q67RJH.js → chunk-PECBKCDK.js} +34 -6
- package/dist/{chunk-33YXPOE3.js → chunk-PPEZJWUG.js} +2 -2
- package/dist/{chunk-RXTN6AKH.js → chunk-PWWSIB2A.js} +5 -5
- package/dist/{chunk-DXKJURES.js → chunk-PZN2LQY6.js} +14 -11
- package/dist/{chunk-N56KALIC.js → chunk-Q7NNUHQV.js} +62 -35
- package/dist/{chunk-RQCKCSRL.js → chunk-QCOV5DFY.js} +22 -22
- package/dist/{chunk-3DPEIQKN.js → chunk-QH3ZTUOA.js} +2 -2
- package/dist/{chunk-NEKRRTYW.js → chunk-QJMRYTCX.js} +8 -8
- package/dist/{chunk-YNFKXPEC.js → chunk-QNWRHOMF.js} +35 -66
- package/dist/{chunk-YAKGTXEV.js → chunk-QRFXEO6Y.js} +2 -2
- package/dist/{chunk-35MSIRKH.js → chunk-QUIJZSDW.js} +2 -2
- package/dist/{chunk-72YIHOZQ.js → chunk-QXFBABFJ.js} +10 -10
- package/dist/chunk-R2CT5YDO.js +66 -0
- package/dist/{chunk-HHV2GANA.js → chunk-R2P2U3ZS.js} +2 -2
- package/dist/{chunk-IGLP3ODT.js → chunk-RGZNQ5CT.js} +15 -15
- package/dist/chunk-SD7SHNDW.js +15 -0
- package/dist/chunk-SL2RDHKO.js +19 -0
- package/dist/{chunk-NUGM5KR6.js → chunk-SRCEQKQS.js} +2 -2
- package/dist/{chunk-OMQNJVKW.js → chunk-SRZOW5L2.js} +43 -13
- package/dist/{chunk-UEPWCCTY.js → chunk-SXQKNKRA.js} +12 -12
- package/dist/{chunk-3M6DQK6S.js → chunk-T334FW2H.js} +7 -7
- package/dist/{chunk-V76WTFTW.js → chunk-T52TPHYC.js} +6 -6
- package/dist/{chunk-5636DCO5.js → chunk-TJFDL26W.js} +59 -12
- package/dist/{chunk-3I7MS7N2.js → chunk-TK2BMCBZ.js} +2 -2
- package/dist/{chunk-5OIVVPHF.js → chunk-TN5FW4XY.js} +13 -6
- package/dist/{chunk-LL4KHSZI.js → chunk-U2MSJ57E.js} +2 -2
- package/dist/{chunk-FTMGRKEF.js → chunk-U44YYLVV.js} +4 -4
- package/dist/{chunk-YECAMM3D.js → chunk-U7H5WRG5.js} +5 -5
- package/dist/{chunk-5TUB6SLS.js → chunk-UFYNOQK4.js} +7 -7
- package/dist/{chunk-R346GLFC.js → chunk-UHW5V7HC.js} +2 -2
- package/dist/{chunk-VIA6RFQZ.js → chunk-UQIVHSE4.js} +4 -4
- package/dist/{chunk-RAY4OVGZ.js → chunk-URBGEOH3.js} +5 -5
- package/dist/chunk-USZA7GWL.js +341 -0
- package/dist/{chunk-ZA4VCIGV.js → chunk-UUQ5G6EZ.js} +60 -41
- package/dist/{chunk-VG7TBQIY.js → chunk-V552WL53.js} +68 -4
- package/dist/{chunk-7UGL4MB5.js → chunk-VAHLPXPY.js} +10 -10
- package/dist/{chunk-25QBEXRS.js → chunk-VANN3GDP.js} +7 -26
- package/dist/{chunk-BWH6N36D.js → chunk-VHKTOLEW.js} +272 -42
- package/dist/{chunk-QUFRYSWI.js → chunk-VHMX7SXF.js} +129 -48
- package/dist/{chunk-336NSSKI.js → chunk-VNBICSS2.js} +2 -2
- package/dist/{chunk-VAVR4IJY.js → chunk-VQD7NH7Z.js} +3 -3
- package/dist/{chunk-LBMZMYH2.js → chunk-W2RJEH6Q.js} +3 -3
- package/dist/{chunk-7CR24IG7.js → chunk-WDV62RKY.js} +2 -2
- package/dist/{chunk-BJVFZO5U.js → chunk-WJIMKGD6.js} +7 -7
- package/dist/{chunk-USR47QNF.js → chunk-WKUYQBCG.js} +14 -14
- package/dist/{chunk-GHS5EBTQ.js → chunk-WNGF5AJX.js} +36 -22
- package/dist/{chunk-MXHC5QYU.js → chunk-WTQGRBHV.js} +5 -144
- package/dist/{chunk-6OSVSQL5.js → chunk-WV6TDAPN.js} +41 -23
- package/dist/chunk-WXA2CFJO.js +23 -0
- package/dist/{chunk-2ASED4PZ.js → chunk-X3BI7HTV.js} +26 -26
- package/dist/{chunk-QSNYB6ZV.js → chunk-XCUDZQLX.js} +3 -3
- package/dist/{chunk-RZDWV63N.js → chunk-XWMSPJYN.js} +6 -6
- package/dist/chunk-YGDMBK7O.js +567 -0
- package/dist/{chunk-6PAZTBPA.js → chunk-YPRSNUTC.js} +15 -6
- package/dist/{chunk-2IR2NMPA.js → chunk-ZIDFQJRB.js} +2 -2
- package/dist/{chunk-LTIKRKFL.js → chunk-ZS43Y2FT.js} +4 -4
- package/dist/{chunk-6EJMN2Y3.js → chunk-ZTNFYMIO.js} +2 -2
- package/dist/{chunk-WEPFGWHJ.js → chunk-ZZFWWYLX.js} +2 -2
- package/dist/cli/index.js +44 -44
- package/dist/clio-QQCMTUZE.js +26 -0
- package/dist/{code-nav-IJR2DBPR.js → code-nav-GUPM6766.js} +48 -32
- package/dist/codewiki/build-worker.js +76 -29
- package/dist/{compile-cache-OQAVB7Y5.js → compile-cache-WJEPUZEJ.js} +4 -4
- package/dist/{components-2TGAI2RC.js → components-TNIKXCBH.js} +13 -13
- package/dist/{config-IUA6OYNS.js → config-IIM7YOD3.js} +211 -124
- package/dist/configure-4ZM5HWJX.js +73 -0
- package/dist/{context-BOYF5EJM.js → context-44BZLJ3J.js} +62 -31
- package/dist/{context-4MPR7WKB.js → context-AIDVQKMW.js} +126 -121
- package/dist/{context-2DKHWH2T.js → context-OL5P3HEP.js} +92 -62
- package/dist/context-clear-OQV76MYP.js +184 -0
- package/dist/{context-index-HNG3MOME.js → context-index-HP2JFUWA.js} +13 -11
- package/dist/{context-map-COB37XXN.js → context-map-INTXD54D.js} +71 -21
- package/dist/{context-working-set-3I3FYX6Y.js → context-working-set-ZUW3EGLS.js} +32 -31
- package/dist/detail-UXPWRANG.js +115 -0
- package/dist/{dispatch-runner-RJ5I2F2O.js → dispatch-runner-P3ZW6G77.js} +192 -116
- package/dist/{docs-SPOV3BAN.js → docs-BL7ROUFN.js} +4 -4
- package/dist/{doctor-DKICC2SN.js → doctor-JJVGPZWT.js} +59 -58
- package/dist/{eval-OQOQUDHK.js → eval-V2RTN3UH.js} +476 -170
- package/dist/{eval-inventory-Y6QRFOH5.js → eval-inventory-QOYZERXJ.js} +7 -7
- package/dist/evidence-35PYWGSO.js +225 -0
- package/dist/{evidence-4DQ25GUQ.js → evidence-CIGGKI6J.js} +111 -94
- package/dist/{evolve-GSS52E5J.js → evolve-33SM3NJP.js} +108 -91
- package/dist/{extensions-G7MFLYHT.js → extensions-YVRHX6ZI.js} +16 -16
- package/dist/{fleet-Q37YHHAQ.js → fleet-LFO7SIPC.js} +147 -146
- package/dist/{fleet-commands-G7E4N7SM.js → fleet-commands-RLK72GU3.js} +27 -26
- package/dist/{fleet-decisions-O7M6QBA2.js → fleet-decisions-3SBSCTCW.js} +16 -15
- package/dist/{fleet-graph-TOUBW6OW.js → fleet-graph-JZIBCGMW.js} +39 -38
- package/dist/{fleet-inspect-SW33JJNI.js → fleet-inspect-2L5YGGZJ.js} +108 -91
- package/dist/{fleet-new-RDVJLHHH.js → fleet-new-RCKGSRDV.js} +3 -3
- package/dist/{fleet-preflight-CV2655TW.js → fleet-preflight-QRSHIIDE.js} +10 -9
- package/dist/{fleet-validate-KESZX2YH.js → fleet-validate-LIAVKDUU.js} +46 -42
- package/dist/{fleet-verify-UQPMTVE3.js → fleet-verify-JIK3OQZR.js} +106 -89
- package/dist/fleet-view-IWHYGQKK.js +118 -0
- package/dist/{init-PXEXQSBF.js → init-NJEDOTQW.js} +124 -123
- package/dist/{install-NKNG7KD4.js → install-3RZDDP23.js} +5 -5
- package/dist/{interop-ZG5T62U3.js → interop-RVCAYECG.js} +25 -25
- package/dist/inventory-74UL7UHU.js +118 -0
- package/dist/{library-B2W4N74O.js → library-CTKZA7K3.js} +45 -44
- package/dist/{memory-YCANYS5A.js → memory-I76I5VUH.js} +108 -93
- package/dist/{models-GERTU3YI.js → models-D4YDIQZQ.js} +64 -62
- package/dist/{monitor-CPNIUULB.js → monitor-NKVD55HX.js} +137 -107
- package/dist/{orchestrator-J4BSH4WQ.js → orchestrator-I6OATVPK.js} +1715 -1687
- package/dist/{panes-BOHAEGYC.js → panes-7BTYH3XQ.js} +8 -8
- package/dist/{panes-NXSLDQZ2.js → panes-WPOMEMRH.js} +22 -22
- package/dist/{paths-VSUWNC22.js → paths-J3KN7UAO.js} +12 -12
- package/dist/preload-EJAWJEIO.js +116 -0
- package/dist/{registry-LG64LTF4.js → registry-DESGAXWK.js} +3 -3
- package/dist/{reset-TNWTB5LU.js → reset-4XMQKDNZ.js} +22 -20
- package/dist/{resources-4PXNMD5G.js → resources-TVYVXK3Q.js} +41 -40
- package/dist/{run-D6XJ34CN.js → run-OWQNNSJU.js} +164 -157
- package/dist/{share-2NWMJJEE.js → share-NPZZMUXG.js} +43 -42
- package/dist/{skills-KR7WON5G.js → skills-OXFEAWMT.js} +47 -46
- package/dist/{skills-eval-O2ZNOLDS.js → skills-eval-J5TCKSJA.js} +128 -107
- package/dist/{skills-inventory-ZZOUBK7O.js → skills-inventory-7II4DM57.js} +41 -40
- package/dist/slash-commands-MDSDSWYF.js +92 -0
- package/dist/{steer-XA25PSCS.js → steer-S7D7IKPU.js} +7 -7
- package/dist/{support-7EMVWYG2.js → support-5VAEC32W.js} +14 -14
- package/dist/{targets-OMH2XCSN.js → targets-KILZEOCE.js} +161 -94
- package/dist/tasks-R6P6OV22.js +36 -0
- package/dist/{terminal-lease-C2J3JYRE.js → terminal-lease-LZCG2KN3.js} +12 -11
- package/dist/tools-6OCQ6SVB.js +28 -0
- package/dist/{trace-FXMXUZUF.js → trace-JHLXWUMN.js} +18 -17
- package/dist/{tree-sitter-HGKH6LG4.js → tree-sitter-AQUUOSYM.js} +6 -6
- package/dist/{tui-primitives-K5PASC3O.js → tui-primitives-RCY2HN7G.js} +3 -3
- package/dist/{uninstall-HALS6BLF.js → uninstall-FXYMFFRT.js} +17 -17
- package/dist/{upgrade-MS72RJEP.js → upgrade-D2OZH6IQ.js} +42 -41
- package/dist/{usage-NHG6MCJM.js → usage-PIASNUS4.js} +137 -105
- package/dist/{verifiers-7AUNVXDY.js → verifiers-LTHUY2PX.js} +28 -27
- package/dist/verify-HYF7KBVE.js +30 -0
- package/dist/{version-KGEG7EPO.js → version-RFPKO6T7.js} +4 -4
- package/dist/{web-fetch-V4FKSDAV.js → web-fetch-MQN4FH3X.js} +169 -18
- package/dist/wiki-generate-RK7JQ5NP.js +615 -0
- package/dist/{with-panes-BDQEWBRT.js → with-panes-OFTNAR4Y.js} +34 -20
- package/dist/worker/entry.js +108 -95
- package/dist/{workspace-ZJ6BFM3Q.js → workspace-DZ7JADBG.js} +6 -6
- package/docs/README.md +7 -6
- package/docs/architecture/acp.md +10 -0
- package/docs/architecture/architecture.md +5 -5
- package/docs/architecture/context-engine.md +45 -60
- package/docs/architecture/context-working-set.md +7 -9
- package/docs/architecture/dispatch-architecture-rationale.md +1 -1
- package/docs/architecture/evidence-and-memory.md +10 -0
- package/docs/architecture/pi-boundary.md +37 -7
- package/docs/architecture/prompt-envelope-and-tools.md +7 -7
- package/docs/architecture/session-lifecycle.md +4 -4
- package/docs/architecture/tui-design.md +45 -30
- package/docs/architecture/worker-dispatch-mechanics.md +4 -0
- package/docs/guide/commands-and-modes.md +75 -61
- package/docs/guide/configuration-and-targets.md +126 -26
- package/docs/guide/configuration-reference.md +22 -7
- package/docs/guide/environment-variables.md +6 -2
- package/docs/guide/fleet-dispatch.md +13 -6
- package/docs/guide/glossary.md +1 -1
- package/docs/guide/installation-and-lifecycle.md +79 -20
- package/docs/guide/proactive-memory.md +1 -1
- package/docs/guide/skills-marketplace.md +11 -3
- package/docs/guide/tool-usage.md +9 -2
- package/docs/process/development-pipeline.md +11 -11
- package/docs/process/documentation-coverage.md +1 -1
- package/docs/process/documentation-guide.md +2 -2
- package/docs/process/eval-runner.md +15 -0
- package/docs/process/evals-internal.md +1 -1
- package/docs/process/release-cut-checklist.md +24 -12
- package/evals/README.md +4 -0
- package/evals/behavioral-corpus-grader.mjs +147 -14
- package/evals/behavioral-model-negative-control.yaml +1 -0
- package/evals/behavioral-model.yaml +266 -1
- package/evals/fixtures/docs-retrieval.json +102 -0
- package/evals/fixtures/scalar-decision.json +17 -0
- package/evals/fixtures/scout-citation-pipeline.json +55 -0
- package/evals/fixtures/source-explanation.json +74 -0
- package/evals/fixtures/tool-arguments.json +18 -0
- package/evals/fixtures/tool-surface/read.txt +4 -0
- package/evals/fixtures/tool-surface/subdir/keep.txt +1 -0
- package/evals/no-edit-memory-grader.mjs +149 -0
- package/evals/scalar-decision-grader.py +41 -0
- package/evals/scalar-decision-machinery.ts +145 -0
- package/evals/source-explanation-grader.mjs +118 -0
- package/evals/tool-surface-grader.mjs +53 -0
- package/evals/tool-surface-model.yaml +274 -0
- package/package.json +14 -14
- package/skills/README.md +6 -6
- package/skills/registry.yaml +1 -1
- package/skills/skill-marketplace.json +1 -1
- package/src/cli/ask.ts +10 -10
- package/src/cli/bootstrap-generate.ts +6 -0
- package/src/cli/config-inspect.ts +24 -7
- package/src/cli/config-trust.ts +62 -0
- package/src/cli/config.ts +8 -0
- package/src/cli/configure-editor.ts +51 -0
- package/src/cli/configure-interop.ts +1 -1
- package/src/cli/configure-oauth.ts +1 -1
- package/src/cli/configure-onboarding.ts +232 -96
- package/src/cli/configure-prompts.ts +76 -0
- package/src/cli/configure-quick.ts +274 -0
- package/src/cli/configure-target.ts +14 -2
- package/src/cli/configure.ts +413 -174
- package/src/cli/context-map.ts +75 -14
- package/src/cli/context.ts +46 -17
- package/src/cli/eval.ts +17 -3
- package/src/cli/modes/print.ts +32 -4
- package/src/cli/oauth-manual-input.ts +1 -1
- package/src/cli/reset.ts +2 -0
- package/src/cli/run.ts +16 -14
- package/src/cli/select.ts +35 -4
- package/src/cli/skills-eval.ts +10 -8
- package/src/cli/steer-channel.ts +31 -18
- package/src/cli/targets.ts +83 -31
- package/src/cli/tasks.ts +10 -1
- package/src/cli/upgrade.ts +11 -8
- package/src/cli/usage.ts +24 -0
- package/src/cli/wiki-generate.ts +239 -96
- package/src/core/bash-exec.ts +43 -15
- package/src/core/bus-events.ts +15 -0
- package/src/core/config.ts +39 -15
- package/src/core/defaults.ts +38 -15
- package/src/{interactive → core}/external-editor.ts +4 -4
- package/src/core/file-references.ts +11 -1
- package/src/core/incomplete-installation.ts +3 -1
- package/src/core/settings-layers.ts +21 -5
- package/src/core/termination.ts +26 -9
- package/src/core/untrusted-content.ts +16 -0
- package/src/core/workspace-trust.ts +179 -0
- package/src/domains/agents/builtins/coder.md +4 -2
- package/src/domains/agents/builtins/context-bootstrap.md +3 -1
- package/src/domains/agents/builtins/documenter.md +7 -4
- package/src/domains/agents/builtins/researcher.md +1 -0
- package/src/domains/agents/builtins/scout.md +7 -1
- package/src/domains/agents/result-contract.ts +199 -26
- package/src/domains/config/classify.ts +1 -1
- package/src/domains/config/keybindings.ts +3 -31
- package/src/domains/context/bootstrap-prompt.ts +11 -9
- package/src/domains/context/bootstrap.ts +74 -39
- package/src/domains/context/clio-md.ts +88 -26
- package/src/domains/context/codewiki/build-operation.ts +121 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +37 -3
- package/src/domains/context/codewiki/build-worker.ts +3 -35
- package/src/domains/context/codewiki/coordinator.ts +36 -6
- package/src/domains/context/codewiki/indexer.ts +59 -19
- package/src/domains/context/contract.ts +6 -2
- package/src/domains/context/extension.ts +72 -10
- package/src/domains/context/fingerprint.ts +39 -34
- package/src/domains/context/index.ts +7 -1
- package/src/domains/context/prompt-context.ts +55 -14
- package/src/domains/context/refresh.ts +9 -57
- package/src/domains/context/wiki/assemble.ts +14 -10
- package/src/domains/context/wiki/evidence.ts +209 -0
- package/src/domains/context/wiki/generate.ts +201 -67
- package/src/domains/context/wiki/meta.ts +10 -2
- package/src/domains/context/wiki/plan-store.ts +70 -14
- package/src/domains/context/wiki/plan.ts +71 -14
- package/src/domains/context/wiki/prompts.ts +42 -1
- package/src/domains/context/wiki/source-content.ts +106 -0
- package/src/domains/context/wiki/staleness.ts +33 -22
- package/src/domains/context/working-set/contract.ts +8 -2
- package/src/domains/context/working-set/engine.ts +17 -4
- package/src/domains/context/working-set/fold.ts +15 -2
- package/src/domains/context/working-set/marker.ts +2 -1
- package/src/domains/context/working-set/project.ts +18 -7
- package/src/domains/context/working-set/recall.ts +82 -56
- package/src/domains/dispatch/active-route-planner.ts +6 -3
- package/src/domains/dispatch/admission-queue.ts +19 -7
- package/src/domains/dispatch/admission.ts +3 -3
- package/src/domains/dispatch/budget-envelope.ts +47 -82
- package/src/domains/dispatch/capacity-lease.ts +57 -19
- package/src/domains/dispatch/contract.ts +10 -2
- package/src/domains/dispatch/event-pump.ts +28 -7
- package/src/domains/dispatch/execution-role.ts +49 -2
- package/src/domains/dispatch/execution-scheduler.ts +2 -0
- package/src/domains/dispatch/extension.ts +190 -105
- package/src/domains/dispatch/fleet-run.ts +20 -0
- package/src/domains/dispatch/gate-role-prompts.ts +4 -2
- package/src/domains/dispatch/parallel-writers.ts +34 -0
- package/src/domains/dispatch/reservation-store.ts +8 -34
- package/src/domains/dispatch/route-approval.ts +3 -3
- package/src/domains/dispatch/route-observer.ts +4 -2
- package/src/domains/dispatch/route-quality.ts +6 -1
- package/src/domains/dispatch/types.ts +4 -3
- package/src/domains/dispatch/worker-spawn.ts +58 -21
- package/src/domains/dispatch/workspace-checkpoint.ts +57 -0
- package/src/domains/eval/compare/behavioral.ts +81 -14
- package/src/domains/eval/compare/compare.ts +15 -5
- package/src/domains/eval/compare/envelope.ts +12 -5
- package/src/domains/eval/metrics/context.ts +24 -1
- package/src/domains/eval/metrics/tracked.ts +4 -28
- package/src/domains/eval/reports/comparison.ts +9 -9
- package/src/domains/eval/runners/clio-run.ts +5 -1
- package/src/domains/eval/schema/suite.ts +2 -0
- package/src/domains/eval/schema/validate.ts +1 -0
- package/src/domains/eval/suites/run.ts +189 -13
- package/src/domains/eval/verifiers/integrity.ts +39 -0
- package/src/domains/eval/verifiers/patch.ts +58 -2
- package/src/domains/eval/workspaces/temp-copy.ts +3 -0
- package/src/domains/evidence/build.ts +4 -2
- package/src/domains/interop/registry.ts +2 -2
- package/src/domains/middleware/hooks-io.ts +45 -26
- package/src/domains/middleware/hooks.ts +6 -0
- package/src/domains/middleware/injection-screen.ts +23 -0
- package/src/domains/middleware/rules.ts +5 -1
- package/src/domains/middleware/stalled-turn.ts +18 -3
- package/src/domains/middleware/task-board-reminder.ts +4 -2
- package/src/domains/middleware/task-nudge.ts +4 -1
- package/src/domains/mux/contract.ts +34 -1
- package/src/domains/mux/dock-controller.ts +8 -1
- package/src/domains/mux/index.ts +1 -0
- package/src/domains/mux/socket-client.ts +13 -3
- package/src/domains/observability/contract.ts +2 -2
- package/src/domains/observability/projection.ts +30 -9
- package/src/domains/prompts/compiler.ts +10 -2
- package/src/domains/prompts/contract.ts +7 -4
- package/src/domains/prompts/extension.ts +28 -64
- package/src/domains/prompts/fragments/identity/clio.md +23 -0
- package/src/domains/prompts/fragments/operating/contract.md +10 -0
- package/src/domains/prompts/fragments/operating/delegation.md +5 -0
- package/src/domains/prompts/fragments/wiki/page.md +28 -15
- package/src/domains/prompts/fragments/wiki/plan.md +4 -4
- package/src/domains/prompts/preload-prefix.ts +31 -0
- package/src/domains/prompts/preload.ts +135 -61
- package/src/domains/providers/auth/backend-file.ts +15 -11
- package/src/domains/providers/auth/storage.ts +3 -5
- package/src/domains/providers/catalog.ts +18 -3
- package/src/domains/providers/probe/fingerprint.ts +13 -6
- package/src/domains/providers/probe/reasoning.ts +2 -0
- package/src/domains/providers/runtime-resolution.ts +11 -9
- package/src/domains/providers/runtimes/cloud/openrouter.ts +2 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +23 -7
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +7 -2
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +10 -4
- package/src/domains/resources/skills/promotion.ts +8 -1
- package/src/domains/safety/action-classifier.ts +9 -0
- package/src/domains/safety/autonomy.ts +10 -1
- package/src/domains/safety/contract.ts +5 -1
- package/src/domains/safety/default-path-policy.ts +11 -0
- package/src/domains/safety/extension.ts +11 -2
- package/src/domains/safety/policy-engine.ts +189 -32
- package/src/domains/safety/project-policy.ts +7 -2
- package/src/domains/safety/workspace-trust.ts +43 -0
- package/src/domains/session/compaction/compact.ts +384 -21
- package/src/domains/session/compaction/cut-point.ts +42 -5
- package/src/domains/session/compaction/tokens.ts +9 -1
- package/src/domains/session/decision-board.ts +43 -33
- package/src/domains/session/entries.ts +169 -4
- package/src/domains/session/prompt-manifest.ts +47 -8
- package/src/domains/session/task-board.ts +21 -3
- package/src/domains/user-tasks/handoff.ts +16 -0
- package/src/engine/acp/adapter.ts +44 -12
- package/src/engine/acp/server.ts +1 -0
- package/src/engine/acp/transport.ts +2 -1
- package/src/engine/acp/types.ts +6 -1
- package/src/engine/antigravity/subprocess-runtime.ts +20 -4
- package/src/engine/api-registry.ts +19 -2
- package/src/engine/apis/openai-completions.ts +13 -6
- package/src/engine/apis/output-budget.ts +26 -10
- package/src/engine/claude/sdk-runtime.ts +4 -3
- package/src/engine/env-api-keys.ts +2 -1
- package/src/engine/external-subprocess.ts +14 -3
- package/src/engine/loop-guard.ts +19 -2
- package/src/engine/provider-diagnostics.ts +129 -0
- package/src/engine/provider-payload.ts +3 -1
- package/src/engine/worker-runtime.ts +13 -2
- package/src/engine/worker-tools.ts +5 -1
- package/src/entry/extension-reload.ts +1 -0
- package/src/entry/orchestrator.ts +53 -15
- package/src/interactive/application-controller.ts +1 -31
- package/src/interactive/chat-loop-messages.ts +12 -4
- package/src/interactive/chat-loop.ts +115 -45
- package/src/interactive/chat-panel.ts +163 -637
- package/src/interactive/chat-renderer.ts +73 -30
- package/src/interactive/context-recall-command.ts +2 -1
- package/src/interactive/dispatch-board.ts +18 -5
- package/src/interactive/editor-submit.ts +21 -31
- package/src/interactive/footer/dashboard.ts +8 -3
- package/src/interactive/footer/widgets.ts +50 -91
- package/src/interactive/interactive-application.ts +24 -44
- package/src/interactive/interactive-event-projection.ts +9 -45
- package/src/interactive/interactive-input-runtime.ts +3 -28
- package/src/interactive/interactive-presentation.ts +45 -16
- package/src/interactive/interactive-slash-runtime.ts +5 -40
- package/src/interactive/layout.ts +31 -5
- package/src/interactive/model-session-replay.ts +2 -2
- package/src/interactive/overlay-frame.ts +1 -0
- package/src/interactive/overlay-general-openers.ts +5 -1
- package/src/interactive/overlay-lifecycle.ts +1 -0
- package/src/interactive/overlay-session-lifecycle.ts +7 -1
- package/src/interactive/overlays/ask-user.ts +1 -0
- package/src/interactive/overlays/message-picker.ts +1 -1
- package/src/interactive/overlays/settings.ts +9 -8
- package/src/interactive/renderers/preview.ts +16 -0
- package/src/interactive/renderers/tool-execution.ts +84 -161
- package/src/interactive/renderers/worker-entry.ts +74 -43
- package/src/interactive/slash-autocomplete.ts +1 -6
- package/src/interactive/slash-commands.ts +16 -46
- package/src/interactive/status/controller.ts +0 -5
- package/src/interactive/status/state-machine.ts +44 -26
- package/src/interactive/status/types.ts +3 -0
- package/src/interactive/status/verbs.ts +13 -12
- package/src/interactive/transcript-detail.ts +50 -112
- package/src/interactive/turn-context.ts +221 -53
- package/src/interactive/turn-middleware.ts +3 -1
- package/src/interactive/turn-persistence.ts +3 -0
- package/src/interactive/turn-runtime.ts +11 -2
- package/src/interactive/turn-state.ts +10 -9
- package/src/interactive/view/artifacts.ts +4 -0
- package/src/interactive/view/view-overlay.ts +44 -34
- package/src/interactive/watch-pane.ts +18 -4
- package/src/interactive/worker-stream.ts +7 -7
- package/src/tools/agent-tools.ts +6 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/builtin-tool-catalog.ts +9 -2
- package/src/tools/codewiki/code-nav.ts +4 -10
- package/src/tools/compete-judge-task.ts +71 -0
- package/src/tools/compete-worktrees.ts +34 -0
- package/src/tools/context/index.ts +32 -7
- package/src/tools/context/surface.ts +15 -4
- package/src/tools/decide.ts +1 -1
- package/src/tools/dispatch-admission.ts +12 -1
- package/src/tools/dispatch-arguments.ts +38 -1
- package/src/tools/dispatch-plan.ts +7 -7
- package/src/tools/dispatch-runner.ts +48 -32
- package/src/tools/dispatch-schema.ts +30 -23
- package/src/tools/dispatch-scout-admission.ts +10 -44
- package/src/tools/dispatch-scout.ts +2 -3
- package/src/tools/find.ts +13 -4
- package/src/tools/grep.ts +13 -1
- package/src/tools/ls.ts +7 -1
- package/src/tools/monitor.ts +26 -11
- package/src/tools/network-policy.ts +11 -24
- package/src/tools/observation.ts +39 -2
- package/src/tools/presentation.ts +1 -1
- package/src/tools/read.ts +112 -15
- package/src/tools/registry.ts +55 -18
- package/src/tools/result-shaping.ts +110 -2
- package/src/tools/tasks.ts +33 -7
- package/src/tools/verify/frontend.ts +67 -30
- package/src/tools/verify/numeric.ts +10 -5
- package/src/tools/web-fetch-network.ts +179 -0
- package/src/tools/web-fetch-surface.ts +2 -1
- package/src/tools/web-fetch.ts +15 -13
- package/src/tools/worker-evidence.ts +27 -0
- package/src/worker/spec-contract.ts +12 -8
- package/dist/builtins-WGALA46I.js +0 -22
- package/dist/chunk-2WZ546HR.js +0 -792
- package/dist/chunk-5PSMVOLM.js +0 -56
- package/dist/chunk-EL24TAU4.js +0 -1560
- package/dist/chunk-IZXGRF7P.js +0 -4048
- package/dist/chunk-JVCV3ICN.js +0 -47
- package/dist/chunk-MNJGS2IN.js +0 -33
- package/dist/chunk-O5CVSAG5.js +0 -122
- package/dist/chunk-ODGTEFFI.js +0 -50
- package/dist/chunk-OQE5J4C6.js +0 -73
- package/dist/chunk-UUVG37B4.js +0 -244
- package/dist/chunk-V6HJFQZE.js +0 -228
- package/dist/clio-QLICPCF5.js +0 -25
- package/dist/configure-VEPX4NMX.js +0 -55
- package/dist/context-clear-S4ZJCQUX.js +0 -182
- package/dist/detail-A7JAVSIG.js +0 -98
- package/dist/evidence-4F5USFKH.js +0 -208
- package/dist/fleet-view-MN2VG4MR.js +0 -101
- package/dist/inventory-C26CFDRR.js +0 -101
- package/dist/preload-P6DGH2PZ.js +0 -13
- package/dist/slash-commands-ZXPJD64J.js +0 -92
- package/dist/tasks-IPAGMEIX.js +0 -36
- package/dist/tools-EFFEAIDP.js +0 -28
- package/dist/verify-FWYGPKMR.js +0 -29
- package/dist/wiki-generate-743CIGJW.js +0 -476
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
import { performance } from "node:perf_hooks";
|
|
2
|
-
import type {
|
|
2
|
+
import type { OutputStyle } from "../core/defaults.js";
|
|
3
3
|
import { SKILL_SUGGESTION_PREFIX } from "../core/skill-activation.js";
|
|
4
4
|
import { rawDurationMs } from "../core/timers.js";
|
|
5
|
+
import { redactSecretString } from "../domains/safety/redaction.js";
|
|
5
6
|
import { type Component, Markdown, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../engine/tui.js";
|
|
6
7
|
import type { AgentMessage } from "../engine/types.js";
|
|
7
|
-
import { toolPresentationPolicy } from "../tools/presentation.js";
|
|
8
|
-
import { toolResultPresentationPolicy } from "../tools/result-disposition.js";
|
|
9
8
|
import type { ChatLoopEvent, RetryStatusPayload } from "./chat-loop.js";
|
|
10
9
|
import { extractText, isSelfExplainingAbort } from "./chat-loop-messages.js";
|
|
11
10
|
import type { ApprovalRequestView } from "./permission-overlay.js";
|
|
12
11
|
import { codeInk } from "./renderers/code-ink.js";
|
|
13
12
|
import { createMermaidMarkdownTransform } from "./renderers/mermaid.js";
|
|
14
13
|
import { styleTaggedNotice } from "./renderers/notice.js";
|
|
14
|
+
import { previewBudget, previewRows } from "./renderers/preview.js";
|
|
15
15
|
import { formatRetryStatus } from "./renderers/retry-status.js";
|
|
16
16
|
import {
|
|
17
|
+
canGroupObservation,
|
|
17
18
|
renderToolAwaitingApproval,
|
|
18
|
-
renderToolCallHeader,
|
|
19
19
|
renderToolExecution,
|
|
20
|
-
|
|
21
|
-
renderToolStreamingExecution,
|
|
22
|
-
renderToolSubline,
|
|
20
|
+
renderToolPreview,
|
|
23
21
|
} from "./renderers/tool-execution.js";
|
|
24
22
|
import { renderWorkerEntryLines } from "./renderers/worker-entry.js";
|
|
25
23
|
import {
|
|
@@ -28,28 +26,15 @@ import {
|
|
|
28
26
|
foldMessageIntoRunTally,
|
|
29
27
|
formatReasoningChip,
|
|
30
28
|
formatReasoningLabel,
|
|
31
|
-
INLINE_STATUS_INDENT_COLS,
|
|
32
29
|
type ReasoningTokenProvenance,
|
|
33
30
|
type ReasoningUsageView,
|
|
34
31
|
reasoningFromTally,
|
|
35
|
-
type StatusPhase,
|
|
36
32
|
UNMEASURED_REASONING,
|
|
37
|
-
type VerbRender,
|
|
38
33
|
} from "./status/index.js";
|
|
39
34
|
import { clioTheme, fgSequence, GLYPH, markdownTheme, SGR_DIM, SGR_RESET } from "./theme/index.js";
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
policyRunningToolFold,
|
|
44
|
-
policyThinkingFold,
|
|
45
|
-
policyToolFold,
|
|
46
|
-
policyWorkerFold,
|
|
47
|
-
resolveFold,
|
|
48
|
-
type TranscriptDetailPolicy,
|
|
49
|
-
toggledFold,
|
|
50
|
-
transcriptDetail,
|
|
51
|
-
} from "./transcript-detail.js";
|
|
52
|
-
import { type WorkerEntryState, workerAskedByModel } from "./worker-stream.js";
|
|
35
|
+
import { type TranscriptDetailPolicy, transcriptDetail } from "./transcript-detail.js";
|
|
36
|
+
import type { ViewArtifact } from "./view/artifacts.js";
|
|
37
|
+
import type { WorkerEntryState } from "./worker-stream.js";
|
|
53
38
|
|
|
54
39
|
// Fenced code reaches the screen through pi-tui's Markdown component, which
|
|
55
40
|
// exposes the MarkdownTheme.highlightCode hook: it hands over the raw fence
|
|
@@ -73,8 +58,6 @@ const RESET = SGR_RESET;
|
|
|
73
58
|
const DIM = SGR_DIM;
|
|
74
59
|
const TEAL = fgSequence("accent");
|
|
75
60
|
const BLUE_REASON = fgSequence("reason");
|
|
76
|
-
const GREEN_OK = fgSequence("success");
|
|
77
|
-
const AMBER = fgSequence("warning");
|
|
78
61
|
const RED_CRIT = fgSequence("error");
|
|
79
62
|
const AGENT_GLYPH = GLYPH.agent;
|
|
80
63
|
const USER_GLYPH = GLYPH.user;
|
|
@@ -97,6 +80,8 @@ const USER_GLYPH = GLYPH.user;
|
|
|
97
80
|
export type { ReasoningTokenProvenance } from "./status/index.js";
|
|
98
81
|
|
|
99
82
|
export interface ChatPanelTurnUsage {
|
|
83
|
+
elapsedMs?: number;
|
|
84
|
+
outcome?: string;
|
|
100
85
|
inputTokens: number;
|
|
101
86
|
outputTokens: number;
|
|
102
87
|
cacheReadTokens: number;
|
|
@@ -164,13 +149,6 @@ type ToolSegment = {
|
|
|
164
149
|
settledWithoutResult?: boolean | undefined;
|
|
165
150
|
/** True when the finished result was an error. Meaningful only after `finished`. */
|
|
166
151
|
isError: boolean;
|
|
167
|
-
/**
|
|
168
|
-
* The operator's explicit fold for this block, or none. The effective state
|
|
169
|
-
* is this override when set, else what the transcript detail policy gives
|
|
170
|
-
* the call (through the tool's presentation once it has finished). Cleared
|
|
171
|
-
* when `/output` changes and when a session is switched in.
|
|
172
|
-
*/
|
|
173
|
-
fold?: FoldOverride;
|
|
174
152
|
/** Wall-clock start time captured by the chat panel for live duration display. */
|
|
175
153
|
startedAtMs?: number;
|
|
176
154
|
/** Completed call duration in milliseconds (event-supplied or measured locally). */
|
|
@@ -239,17 +217,13 @@ type ThinkingSegment = {
|
|
|
239
217
|
finalized: boolean;
|
|
240
218
|
/** Panel clock when the first delta of this stretch arrived. */
|
|
241
219
|
startedAtMs?: number;
|
|
242
|
-
/** The operator's explicit fold for this stretch, or none. */
|
|
243
|
-
fold?: FoldOverride;
|
|
244
220
|
};
|
|
245
221
|
type AssistantSegment = TextSegment | ToolSegment | ErrorSegment | ThinkingSegment;
|
|
246
222
|
/**
|
|
247
223
|
* A caller-rendered block receives the frame's transcript detail policy so a
|
|
248
|
-
* block
|
|
249
|
-
* way the panel resolves a model call. Blocks that ignore it are unaffected.
|
|
224
|
+
* block such as the operator's `!` bash row follows the same preset as the panel. Blocks that ignore it are unaffected.
|
|
250
225
|
*/
|
|
251
|
-
type ReplayBlockRenderer = (width: number, detail: TranscriptDetailPolicy) => string[];
|
|
252
|
-
type AssistantStatusLine = { phase: StatusPhase; verb: string; toneHint: VerbRender["toneHint"] };
|
|
226
|
+
type ReplayBlockRenderer = (width: number, detail: TranscriptDetailPolicy, unbounded?: boolean) => string[];
|
|
253
227
|
|
|
254
228
|
type TranscriptEntry =
|
|
255
229
|
| { role: "user"; text: string; status?: () => UserTurnStatus }
|
|
@@ -266,17 +240,15 @@ type TranscriptEntry =
|
|
|
266
240
|
*/
|
|
267
241
|
messageStartSegmentIndex?: number | undefined;
|
|
268
242
|
pending: boolean;
|
|
269
|
-
statusLine?: AssistantStatusLine | null | undefined;
|
|
270
243
|
isError: boolean;
|
|
271
244
|
turnUsage?: ChatPanelTurnUsage;
|
|
272
245
|
}
|
|
273
246
|
/**
|
|
274
|
-
* A dispatched worker's attributed block.
|
|
275
|
-
* override; `state` is the live object the worker-stream reducer mutates, so
|
|
247
|
+
* A dispatched worker's attributed block. `state` is the live object the worker-stream reducer mutates, so
|
|
276
248
|
* a streaming delta reaches the screen without copying the entry per frame.
|
|
277
249
|
* The panel is told when that happened through `applyWorkerState`.
|
|
278
250
|
*/
|
|
279
|
-
| { role: "worker"; state: WorkerEntryState
|
|
251
|
+
| { role: "worker"; state: WorkerEntryState }
|
|
280
252
|
/**
|
|
281
253
|
* A block the caller renders itself. Most are settled the moment they are
|
|
282
254
|
* appended, but a few (the operator's `!` bash row) keep mutating the state
|
|
@@ -288,26 +260,10 @@ type TranscriptEntry =
|
|
|
288
260
|
role: "replayBlock";
|
|
289
261
|
renderBlock: ReplayBlockRenderer;
|
|
290
262
|
isLive?: (() => boolean) | undefined;
|
|
291
|
-
fold?: ReplayBlockFoldControl | undefined;
|
|
292
263
|
};
|
|
293
264
|
|
|
294
265
|
type WorkerTranscriptEntry = Extract<TranscriptEntry, { role: "worker" }>;
|
|
295
266
|
|
|
296
|
-
/**
|
|
297
|
-
* Fold state a caller-rendered block owns. The panel never stores it: the
|
|
298
|
-
* block's closure reads it when rendering, so the panel only needs to resolve
|
|
299
|
-
* and flip it when the operator uses an expand/collapse key, and to clear it
|
|
300
|
-
* when `/output` changes. Same tri-state as a tool segment: an override, or
|
|
301
|
-
* none, over the fold the policy gives the block.
|
|
302
|
-
*/
|
|
303
|
-
export interface ReplayBlockFoldControl {
|
|
304
|
-
/** The fold the policy gives this block when no override is set. */
|
|
305
|
-
policyFold(detail: TranscriptDetailPolicy): Fold;
|
|
306
|
-
/** The operator's override, or none. */
|
|
307
|
-
fold(): FoldOverride;
|
|
308
|
-
setFold(fold: FoldOverride): void;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
267
|
/**
|
|
312
268
|
* Whether a painted operator turn exists in the ledger yet. `pending` is the
|
|
313
269
|
* window between the editor being consumed and admission; `refused` is a
|
|
@@ -327,7 +283,7 @@ export interface ChatPanel extends Component {
|
|
|
327
283
|
* that keeps changing after the append, so the panel keeps re-rendering it
|
|
328
284
|
* instead of treating the first frame as final.
|
|
329
285
|
*/
|
|
330
|
-
appendReplayBlock(renderBlock: ReplayBlockRenderer, isLive?: () => boolean
|
|
286
|
+
appendReplayBlock(renderBlock: ReplayBlockRenderer, isLive?: () => boolean): void;
|
|
331
287
|
applyEvent(event: ChatLoopEvent): void;
|
|
332
288
|
/** Mark a just-rehydrated tool segment so its mutation diff remains plain. */
|
|
333
289
|
markToolReplayed?(toolCallId: string): void;
|
|
@@ -344,57 +300,17 @@ export interface ChatPanel extends Component {
|
|
|
344
300
|
* so what the operator can share is exactly what the operator can see.
|
|
345
301
|
*/
|
|
346
302
|
workerStates(): ReadonlyArray<WorkerEntryState>;
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Publish the live run tally's reasoning projection. The pending entry's
|
|
350
|
-
* tail line reads this; passing null returns it to unmeasured, which is what
|
|
351
|
-
* an idle or just-started turn is.
|
|
352
|
-
*/
|
|
353
|
-
setLiveReasoning(view: ReasoningUsageView | null): void;
|
|
354
|
-
/**
|
|
355
|
-
* Flip the newest foldable block (tool call, worker card, or fold-owning
|
|
356
|
-
* replay block) away from its effective state. The flip is an override
|
|
357
|
-
* over the transcript detail policy: under `/output verbose` it folds an
|
|
358
|
-
* open block, under `/output minimal` it opens a folded one.
|
|
359
|
-
*/
|
|
360
|
-
toggleLastToolExpanded(): boolean;
|
|
361
|
-
/** Set an explicit override on every tool, worker, and fold-owning block at once. */
|
|
362
|
-
toggleAllToolsExpanded(): boolean;
|
|
363
|
-
/**
|
|
364
|
-
* Drop every operator override so each block returns to what the transcript
|
|
365
|
-
* detail policy gives it. `/output` changes and session switches do this:
|
|
366
|
-
* the operator asked for a new baseline, and what they had opened belonged
|
|
367
|
-
* to the transcript they left. Idempotent.
|
|
368
|
-
*/
|
|
369
|
-
clearFoldOverrides(): void;
|
|
370
|
-
/**
|
|
371
|
-
* Flip the newest thinking stretch between the one-line dim marker
|
|
372
|
-
* and the full rail-prefixed body, as an override over the policy. A turn
|
|
373
|
-
* with no thinking yet is left alone; a new stretch inherits the policy.
|
|
374
|
-
*/
|
|
375
|
-
toggleLastThinking(): boolean;
|
|
376
|
-
toggleAllThinking(): boolean;
|
|
377
|
-
/** Whether live thinking would render open this frame, which presentation pacing consults. */
|
|
303
|
+
inspectionArtifacts(): ViewArtifact[];
|
|
304
|
+
/** Whether the current preset shows supplied reasoning, for stream pacing. */
|
|
378
305
|
isThinkingExpanded(): boolean;
|
|
379
|
-
/** Toggle whether expanded live tool bodies include cumulative partial output. */
|
|
380
|
-
toggleLiveToolOutput(): boolean;
|
|
381
306
|
/** Clears the visible transcript. /new uses this after rotating the session. */
|
|
382
307
|
reset(): void;
|
|
383
308
|
}
|
|
384
309
|
|
|
385
310
|
export interface ChatPanelOptions {
|
|
386
|
-
|
|
387
|
-
* Resolves the user-visible key string for the `clio-coder.tool.expand`
|
|
388
|
-
* action, which folds and unfolds the newest tool call or worker block.
|
|
389
|
-
* Returning a non-empty string surfaces a dim ` (<key>)` hint on the one
|
|
390
|
-
* surface the key would act on: the latest finished collapsed tool subline,
|
|
391
|
-
* or the newest folded worker card. Returning undefined or an empty string
|
|
392
|
-
* suppresses the hint. Called per render so live keybinding changes flow
|
|
393
|
-
* through.
|
|
394
|
-
*/
|
|
395
|
-
getToolExpandKey?: () => string | undefined;
|
|
311
|
+
getTerminalRows?: () => number;
|
|
396
312
|
/** Live transcript detail mode. Settings changes take effect on the next frame. */
|
|
397
|
-
|
|
313
|
+
getOutputStyle?: () => OutputStyle;
|
|
398
314
|
/** Receives measured panel render cost; no FPS claim is made by the panel. */
|
|
399
315
|
onRenderMetrics?: (metrics: ChatPanelRenderMetrics) => void;
|
|
400
316
|
/** Clock injection for deterministic duration tests. Defaults to Date.now. */
|
|
@@ -556,10 +472,6 @@ function scopeTerminalErrorAfterSuccessfulTool(
|
|
|
556
472
|
return `[error] ${modelFailure}${detachedDispatchSucceeded ? "; detached runs continue" : ""}`;
|
|
557
473
|
}
|
|
558
474
|
|
|
559
|
-
function hasThinking(entry: Extract<TranscriptEntry, { role: "assistant" }>): boolean {
|
|
560
|
-
return entry.segments.some((seg) => seg.kind === "thinking" && seg.text.length > 0);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
475
|
/** The thinking segment still receiving deltas, which is always the tail. */
|
|
564
476
|
function openThinkingSegment(entry: Extract<TranscriptEntry, { role: "assistant" }>): ThinkingSegment | null {
|
|
565
477
|
const tail = entry.segments[entry.segments.length - 1];
|
|
@@ -597,11 +509,6 @@ function lastAssistantIndex(
|
|
|
597
509
|
return null;
|
|
598
510
|
}
|
|
599
511
|
|
|
600
|
-
function hasStreamingText(entry: Extract<TranscriptEntry, { role: "assistant" }>): boolean {
|
|
601
|
-
const tail = entry.segments[entry.segments.length - 1];
|
|
602
|
-
return tail?.kind === "text" && !tail.finalized && tail.text.trim().length > 0;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
512
|
/**
|
|
606
513
|
* Locate the skill-suggestion protocol line inside a reply.
|
|
607
514
|
*
|
|
@@ -765,9 +672,7 @@ function appendUserRowTail(rendered: string[], tail: string, width: number): voi
|
|
|
765
672
|
* Static marker used when thinking is folded. This matches pi-coding-agent's
|
|
766
673
|
* hidden-thinking presentation and avoids previewing reasoning content.
|
|
767
674
|
*/
|
|
768
|
-
const THINKING_HIDDEN_LABEL =
|
|
769
|
-
const THINKING_LINE_LIMIT = 12;
|
|
770
|
-
|
|
675
|
+
const THINKING_HIDDEN_LABEL = "Thinking · /view";
|
|
771
676
|
function dimLine(text: string, width: number): string {
|
|
772
677
|
return `${DIM}${truncateToWidth(text, Math.max(1, width), GLYPH.ellipsis, false)}${RESET}`;
|
|
773
678
|
}
|
|
@@ -786,62 +691,12 @@ function renderSettledThinkingMarker(view: ReasoningUsageView, width: number): s
|
|
|
786
691
|
);
|
|
787
692
|
}
|
|
788
693
|
|
|
789
|
-
/**
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
* after the model had already moved on, so the transcript read out of order.
|
|
796
|
-
*
|
|
797
|
-
* The count is whatever the run tally has folded so far, so between model calls
|
|
798
|
-
* the line states elapsed and nothing else. Visible thinking text is never
|
|
799
|
-
* counted: that number moved with how much reasoning the provider chose to
|
|
800
|
-
* display, not with what the turn spent.
|
|
801
|
-
*/
|
|
802
|
-
function renderLiveReasoningLine(view: ReasoningUsageView, elapsedMs: number | undefined, width: number): string {
|
|
803
|
-
const chip = formatReasoningChip(view, compactReasoningTokens);
|
|
804
|
-
const head = chip === null ? THINKING_HIDDEN_LABEL : `Thinking · ${chip} ${formatReasoningLabel(view)}`;
|
|
805
|
-
const seconds = elapsedMs === undefined ? 0 : Math.floor(Math.max(0, elapsedMs) / 1000);
|
|
806
|
-
return dimLine(seconds > 0 ? `${head} · ${seconds}s` : head, width);
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
/**
|
|
810
|
-
* Render the expanded thinking body: the text dimmed behind a dim `│ ` rail,
|
|
811
|
-
* capped at `THINKING_LINE_LIMIT` lines. A streaming turn keeps the tail (the
|
|
812
|
-
* reasoning still arriving); a settled one keeps the head with a
|
|
813
|
-
* `... N more lines hidden` overflow message. Mirrors the tool toggle's
|
|
814
|
-
* lab-notebook minimalism: no colored glyphs, no boxes.
|
|
815
|
-
*/
|
|
816
|
-
function renderThinkingRail(thinking: string, width: number, streaming: boolean, unbounded = false): string[] {
|
|
817
|
-
if (thinking.length === 0) return [];
|
|
818
|
-
const splitLines = thinking.split("\n");
|
|
819
|
-
let visible: string[];
|
|
820
|
-
if (unbounded) {
|
|
821
|
-
// /export reproduces the whole transcript; the live cap is a screen budget.
|
|
822
|
-
visible = splitLines;
|
|
823
|
-
} else if (streaming) {
|
|
824
|
-
if (splitLines.length > THINKING_LINE_LIMIT) {
|
|
825
|
-
const hiddenCount = splitLines.length - THINKING_LINE_LIMIT;
|
|
826
|
-
visible = [`… ${hiddenCount} earlier lines hidden`, ...splitLines.slice(-THINKING_LINE_LIMIT)];
|
|
827
|
-
} else {
|
|
828
|
-
visible = splitLines;
|
|
829
|
-
}
|
|
830
|
-
} else {
|
|
831
|
-
visible =
|
|
832
|
-
splitLines.length > THINKING_LINE_LIMIT
|
|
833
|
-
? [...splitLines.slice(0, THINKING_LINE_LIMIT), `... ${splitLines.length - THINKING_LINE_LIMIT} more lines hidden`]
|
|
834
|
-
: splitLines;
|
|
835
|
-
}
|
|
836
|
-
const out: string[] = [];
|
|
837
|
-
const bodyWidth = Math.max(1, width - 2);
|
|
838
|
-
for (const raw of visible) {
|
|
839
|
-
const wrappedLines = raw.length === 0 ? [""] : wrapTextWithAnsi(raw, bodyWidth);
|
|
840
|
-
for (const wrapped of wrappedLines) {
|
|
841
|
-
out.push(`${BLUE_REASON}│ ${RESET}${DIM}${wrapped}${RESET}`);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
return out;
|
|
694
|
+
/** Wrap first, then keep the same tail both while streaming and after settlement. */
|
|
695
|
+
function renderThinkingRail(thinking: string, width: number, limit: number, unbounded = false): string[] {
|
|
696
|
+
const rows = wrapTextWithAnsi(redactSecretString(thinking), Math.max(1, width - 2)).map(
|
|
697
|
+
(row) => `${BLUE_REASON}│ ${RESET}${DIM}${row}${RESET}`,
|
|
698
|
+
);
|
|
699
|
+
return unbounded ? rows : previewRows(rows, limit, width, true);
|
|
845
700
|
}
|
|
846
701
|
|
|
847
702
|
/**
|
|
@@ -860,7 +715,7 @@ function renderTurnUsageLine(
|
|
|
860
715
|
if (receipt === "none") return [];
|
|
861
716
|
if (receipt === "compact") {
|
|
862
717
|
const receipt = truncateToWidth(
|
|
863
|
-
`
|
|
718
|
+
` ${usage.outcome ?? "Done"}${usage.elapsedMs === undefined ? "" : ` · ${Math.round(usage.elapsedMs / 1000)}s`}`,
|
|
864
719
|
width,
|
|
865
720
|
GLYPH.ellipsis,
|
|
866
721
|
false,
|
|
@@ -897,138 +752,65 @@ function renderTurnUsageLine(
|
|
|
897
752
|
);
|
|
898
753
|
}
|
|
899
754
|
|
|
900
|
-
/** The indent resolveInlineVerb budgets against when it fits the verb to the terminal. */
|
|
901
|
-
const STATUS_INDENT = " ".repeat(INLINE_STATUS_INDENT_COLS);
|
|
902
|
-
|
|
903
|
-
function styleStatusVerb(text: string, toneHint: VerbRender["toneHint"]): string {
|
|
904
|
-
if (toneHint === "error") return `${RED_CRIT}${text}${RESET}`;
|
|
905
|
-
if (toneHint === "warn") return `${AMBER}${text}${RESET}`;
|
|
906
|
-
if (toneHint === "ok") return `${GREEN_OK}${text}${RESET}`;
|
|
907
|
-
return `${DIM}${text}${RESET}`;
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
/**
|
|
911
|
-
* The fold the policy gives a tool segment this frame: the running-tool rule
|
|
912
|
-
* while in flight, the tool body rule (through the tool's own presentation)
|
|
913
|
-
* once finished, and the error rule for a finished failure.
|
|
914
|
-
*/
|
|
915
|
-
function policySegmentFold(seg: ToolSegment, detail: TranscriptDetailPolicy): Fold {
|
|
916
|
-
if (!seg.finished) return policyRunningToolFold(detail);
|
|
917
|
-
if (seg.isError && detail.errors === "body") return "expanded";
|
|
918
|
-
return policyToolFold(detail, toolResultPresentationPolicy(seg.result) ?? toolPresentationPolicy(seg.name, seg.args));
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
/** Effective state of a tool segment: the operator's override, else the policy. */
|
|
922
|
-
function toolSegmentExpanded(seg: ToolSegment, detail: TranscriptDetailPolicy): boolean {
|
|
923
|
-
return resolveFold(seg.fold, policySegmentFold(seg, detail)) === "expanded";
|
|
924
|
-
}
|
|
925
|
-
|
|
926
755
|
function renderToolSegmentLines(
|
|
927
756
|
seg: ToolSegment,
|
|
928
757
|
width: number,
|
|
929
|
-
expandKey: string | undefined,
|
|
930
|
-
latestHintToolId: string | null,
|
|
931
758
|
nowMs: number,
|
|
932
|
-
|
|
759
|
+
unbounded: boolean,
|
|
933
760
|
detail: TranscriptDetailPolicy,
|
|
934
|
-
|
|
761
|
+
terminalRows: number,
|
|
935
762
|
): string[] {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
?
|
|
941
|
-
: seg.argsComplete
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
//
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
durationMs: seg.durationMs,
|
|
964
|
-
resultSummary: seg.resultSummary,
|
|
965
|
-
outcome: seg.settlement,
|
|
966
|
-
blockReason: seg.blockReason,
|
|
967
|
-
evictedReason: seg.evictedReason,
|
|
968
|
-
}
|
|
969
|
-
: { toolCallId: seg.id, toolName: seg.name, args: seg.args, elapsedMs, phase },
|
|
970
|
-
width,
|
|
971
|
-
hintKey,
|
|
972
|
-
{
|
|
973
|
-
diffStyle: seg.replayed === true ? "plain" : "color",
|
|
974
|
-
foldedExtras: detail.toolBody === "folded" ? "none" : "per-tool",
|
|
975
|
-
},
|
|
976
|
-
);
|
|
977
|
-
}
|
|
978
|
-
if (!seg.finished) {
|
|
979
|
-
if (liveToolOutput && seg.partialResult !== undefined) {
|
|
980
|
-
return renderToolStreamingExecution(
|
|
981
|
-
{ toolCallId: seg.id, toolName: seg.name, args: seg.args, elapsedMs, phase },
|
|
982
|
-
width,
|
|
983
|
-
seg.partialResult,
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
const call = { toolCallId: seg.id, toolName: seg.name, args: seg.args, elapsedMs, phase };
|
|
987
|
-
return liveToolOutput ? renderToolCallHeader(call, width) : renderToolRunningStatus(call, width);
|
|
988
|
-
}
|
|
989
|
-
return renderToolExecution(
|
|
990
|
-
{
|
|
991
|
-
toolCallId: seg.id,
|
|
992
|
-
toolName: seg.name,
|
|
993
|
-
args: seg.args,
|
|
994
|
-
result: seg.result,
|
|
995
|
-
isError: seg.isError,
|
|
996
|
-
durationMs: seg.durationMs,
|
|
997
|
-
resultSummary: seg.resultSummary,
|
|
998
|
-
outcome: seg.settlement,
|
|
999
|
-
blockReason: seg.blockReason,
|
|
1000
|
-
evictedReason: seg.evictedReason,
|
|
1001
|
-
},
|
|
1002
|
-
width,
|
|
1003
|
-
{ unbounded: unboundedToolBodies, diffStyle: seg.replayed === true ? "plain" : "color" },
|
|
1004
|
-
);
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
/**
|
|
1008
|
-
* Whether a worker block draws its one-line card this frame: the operator's
|
|
1009
|
-
* override when set, else the policy's worker rule, which under the balanced
|
|
1010
|
-
* level is the origin default (a run the model asked for folds).
|
|
1011
|
-
*/
|
|
1012
|
-
function workerEntryFolded(entry: WorkerTranscriptEntry, detail: TranscriptDetailPolicy): boolean {
|
|
1013
|
-
return resolveFold(entry.fold, policyWorkerFold(detail, workerAskedByModel(entry.state))) === "folded";
|
|
763
|
+
const call = {
|
|
764
|
+
toolCallId: seg.id,
|
|
765
|
+
toolName: seg.name,
|
|
766
|
+
args: seg.args,
|
|
767
|
+
elapsedMs: seg.startedAtMs === undefined ? undefined : Math.max(0, rawDurationMs(seg.startedAtMs, nowMs)),
|
|
768
|
+
phase: seg.executionStarted ? ("running" as const) : seg.argsComplete ? ("ready" as const) : ("forming" as const),
|
|
769
|
+
};
|
|
770
|
+
if (!seg.finished && seg.awaitingApproval) return renderToolAwaitingApproval(call, width, seg.approvalView);
|
|
771
|
+
// Argument fragments are not separate actions. Reveal the row once the call is formed.
|
|
772
|
+
if (!seg.finished && !seg.argsComplete && !seg.executionStarted) return [];
|
|
773
|
+
const finished = {
|
|
774
|
+
...call,
|
|
775
|
+
result: seg.result,
|
|
776
|
+
isError: seg.isError,
|
|
777
|
+
durationMs: seg.durationMs,
|
|
778
|
+
resultSummary: seg.resultSummary,
|
|
779
|
+
outcome: seg.settlement,
|
|
780
|
+
blockReason: seg.blockReason,
|
|
781
|
+
evictedReason: seg.evictedReason,
|
|
782
|
+
};
|
|
783
|
+
const options = { unbounded, diffStyle: seg.replayed ? ("plain" as const) : ("color" as const) };
|
|
784
|
+
if (unbounded && seg.finished) return renderToolExecution(finished, width, options);
|
|
785
|
+
return renderToolPreview(seg.finished ? finished : call, width, detail, {
|
|
786
|
+
...options,
|
|
787
|
+
terminalRows,
|
|
788
|
+
partialResult: seg.partialResult,
|
|
789
|
+
});
|
|
1014
790
|
}
|
|
1015
791
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
return
|
|
792
|
+
function observation(seg: AssistantSegment | undefined): string | null {
|
|
793
|
+
if (seg?.kind !== "tool" || !seg.finished) return null;
|
|
794
|
+
return canGroupObservation({
|
|
795
|
+
toolCallId: seg.id,
|
|
796
|
+
toolName: seg.name,
|
|
797
|
+
result: seg.result,
|
|
798
|
+
isError: seg.isError,
|
|
799
|
+
outcome: seg.settlement,
|
|
800
|
+
evictedReason: seg.evictedReason,
|
|
801
|
+
resultSummary: seg.resultSummary,
|
|
802
|
+
})
|
|
803
|
+
? seg.name
|
|
804
|
+
: null;
|
|
1019
805
|
}
|
|
1020
806
|
|
|
1021
807
|
function renderEntryLines(
|
|
1022
808
|
entry: TranscriptEntry,
|
|
1023
809
|
width: number,
|
|
1024
|
-
expandKey: string | undefined,
|
|
1025
|
-
latestHintToolId: string | null,
|
|
1026
|
-
latestFoldedWorkerId: string | null,
|
|
1027
810
|
nowMs: number,
|
|
1028
811
|
unboundedToolBodies: boolean,
|
|
1029
812
|
detail: TranscriptDetailPolicy,
|
|
1030
|
-
|
|
1031
|
-
liveReasoning: ReasoningUsageView,
|
|
813
|
+
terminalRows: number,
|
|
1032
814
|
): string[] {
|
|
1033
815
|
if (entry.role === "replayBlock") {
|
|
1034
816
|
return entry.renderBlock(width, detail);
|
|
@@ -1048,11 +830,7 @@ function renderEntryLines(
|
|
|
1048
830
|
return wrapTextWithAnsi(formatRetryStatus(entry.status), width);
|
|
1049
831
|
}
|
|
1050
832
|
if (entry.role === "worker") {
|
|
1051
|
-
return renderWorkerEntryLines(entry.state, width, {
|
|
1052
|
-
folded: workerEntryFolded(entry, detail),
|
|
1053
|
-
...(expandKey !== undefined && entry.state.assignmentId === latestFoldedWorkerId ? { expandKey } : {}),
|
|
1054
|
-
unbounded: unboundedToolBodies,
|
|
1055
|
-
});
|
|
833
|
+
return renderWorkerEntryLines(entry.state, width, { detail, terminalRows, unbounded: unboundedToolBodies });
|
|
1056
834
|
}
|
|
1057
835
|
// A settled assistant entry that rendered nothing at all contributes nothing.
|
|
1058
836
|
// A mid-turn notice splits the transcript, so the events after it open a
|
|
@@ -1062,59 +840,36 @@ function renderEntryLines(
|
|
|
1062
840
|
return [];
|
|
1063
841
|
}
|
|
1064
842
|
const lines: string[] = [];
|
|
1065
|
-
// Reasoning
|
|
1066
|
-
// came between. A closed stretch is a folded marker (or a head-anchored rail
|
|
1067
|
-
// when expanded); the stretch still open while the turn is pending is the
|
|
1068
|
-
// live indicator, with the tally's count and its own elapsed. The turn's
|
|
1069
|
-
// settled count chip rides on the last marker once the turn has settled.
|
|
843
|
+
// Reasoning stays between the prose and actions that surround it.
|
|
1070
844
|
const chipIndex = entry.pending ? -1 : lastThinkingIndex(entry);
|
|
1071
845
|
const clioPrefix = entry.isError ? CLIO_PREFIX_ERROR : CLIO_PREFIX;
|
|
1072
846
|
const proseWidth = Math.max(1, width - PROSE_GUTTER_WIDTH);
|
|
1073
847
|
let labeled = false;
|
|
1074
|
-
let liveIndicatorShown = false;
|
|
1075
|
-
let latestThinkingExpanded = policyThinkingFold(detail) === "expanded";
|
|
1076
848
|
for (let segIndex = 0; segIndex < entry.segments.length; segIndex += 1) {
|
|
1077
849
|
const seg = entry.segments[segIndex];
|
|
1078
850
|
if (seg === undefined) continue;
|
|
1079
851
|
if (seg.kind === "thinking") {
|
|
1080
852
|
if (seg.text.length === 0) continue;
|
|
1081
|
-
|
|
1082
|
-
latestThinkingExpanded = thinkingExpandedNow;
|
|
1083
|
-
const live = entry.pending && !seg.finalized;
|
|
1084
|
-
if (thinkingExpandedNow) lines.push(...renderThinkingRail(seg.text, width, live, unboundedToolBodies));
|
|
1085
|
-
if (live) {
|
|
1086
|
-
liveIndicatorShown = true;
|
|
1087
|
-
// The bare marker level states that the model is thinking and
|
|
1088
|
-
// nothing else: no count, no elapsed. An operator who opened the
|
|
1089
|
-
// stretch anyway gets the progress line under the rail.
|
|
853
|
+
if (detail.reasoningRows > 0 || unboundedToolBodies) {
|
|
1090
854
|
lines.push(
|
|
1091
|
-
|
|
1092
|
-
? dimLine(THINKING_HIDDEN_LABEL, width)
|
|
1093
|
-
: renderLiveReasoningLine(
|
|
1094
|
-
liveReasoning,
|
|
1095
|
-
seg.startedAtMs === undefined ? undefined : Math.max(0, nowMs - seg.startedAtMs),
|
|
1096
|
-
width,
|
|
1097
|
-
),
|
|
855
|
+
...renderThinkingRail(seg.text, width, previewBudget(detail.reasoningRows, terminalRows), unboundedToolBodies),
|
|
1098
856
|
);
|
|
1099
|
-
} else
|
|
857
|
+
} else {
|
|
1100
858
|
const view = segIndex === chipIndex ? reasoningFromTurnUsage(entry.turnUsage) : UNMEASURED_REASONING;
|
|
1101
859
|
lines.push(renderSettledThinkingMarker(view, width));
|
|
1102
860
|
}
|
|
1103
861
|
continue;
|
|
1104
862
|
}
|
|
1105
863
|
if (seg.kind === "tool") {
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
liveToolOutput,
|
|
1116
|
-
),
|
|
1117
|
-
);
|
|
864
|
+
const kind = detail.style === "compact" && !unboundedToolBodies ? observation(seg) : null;
|
|
865
|
+
let count = 1;
|
|
866
|
+
if (kind) {
|
|
867
|
+
while (entry.segments[segIndex + count] && observation(entry.segments[segIndex + count]) === kind) count++;
|
|
868
|
+
}
|
|
869
|
+
if (count > 1) {
|
|
870
|
+
lines.push(dimLine(`✓ ${kind === "read" ? `Read ${count} files` : `${count} ${kind} actions`} · /view`, width));
|
|
871
|
+
segIndex += count - 1;
|
|
872
|
+
} else lines.push(...renderToolSegmentLines(seg, width, nowMs, unboundedToolBodies, detail, terminalRows));
|
|
1118
873
|
continue;
|
|
1119
874
|
}
|
|
1120
875
|
// Text and error segments share the reply-prefix bookkeeping: the first
|
|
@@ -1144,32 +899,7 @@ function renderEntryLines(
|
|
|
1144
899
|
lines.push(...hangProseLines(rendered));
|
|
1145
900
|
}
|
|
1146
901
|
}
|
|
1147
|
-
// A thinking stretch closes when text or a tool follows it so the historical
|
|
1148
|
-
// marker stays in stream order. The turn-level reasoning projection is still
|
|
1149
|
-
// live, though, and must remain beside the current tail instead of scrolling
|
|
1150
|
-
// away with that marker. An open tail stretch already rendered this line.
|
|
1151
|
-
if (entry.pending && hasThinking(entry) && !liveIndicatorShown) {
|
|
1152
|
-
lines.push(
|
|
1153
|
-
detail.thinking === "marker" && !latestThinkingExpanded
|
|
1154
|
-
? dimLine(THINKING_HIDDEN_LABEL, width)
|
|
1155
|
-
: renderLiveReasoningLine(liveReasoning, undefined, width),
|
|
1156
|
-
);
|
|
1157
|
-
liveIndicatorShown = true;
|
|
1158
|
-
}
|
|
1159
902
|
if (entry.turnUsage && !entry.pending) lines.push(...renderTurnUsageLine(entry.turnUsage, width, detail.receipt));
|
|
1160
|
-
// The open thinking segment's line is the one that speaks for reasoning while
|
|
1161
|
-
// the turn runs. The generic thinking verb is suppressed while it shows so
|
|
1162
|
-
// the entry never carries two indicators for the same thing.
|
|
1163
|
-
const shouldRenderStatus =
|
|
1164
|
-
entry.pending &&
|
|
1165
|
-
entry.statusLine !== null &&
|
|
1166
|
-
entry.statusLine !== undefined &&
|
|
1167
|
-
!(entry.statusLine.phase === "writing" && hasStreamingText(entry)) &&
|
|
1168
|
-
!(entry.statusLine.phase === "thinking" && liveIndicatorShown);
|
|
1169
|
-
if (!labeled && !hasVisibleOutput(entry)) lines.push(clioPrefix.trimEnd());
|
|
1170
|
-
if (shouldRenderStatus) {
|
|
1171
|
-
lines.push(`${STATUS_INDENT}${styleStatusVerb(entry.statusLine?.verb ?? "", entry.statusLine?.toneHint ?? "muted")}`);
|
|
1172
|
-
}
|
|
1173
903
|
return lines;
|
|
1174
904
|
}
|
|
1175
905
|
|
|
@@ -1178,18 +908,12 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1178
908
|
/** Assignment to its placed block, in placement order, so a streaming delta is O(1) to route. */
|
|
1179
909
|
const workerEntries = new Map<string, WorkerTranscriptEntry>();
|
|
1180
910
|
let dirty = true;
|
|
911
|
+
let runStartedAt: number | undefined;
|
|
1181
912
|
let cachedWidth: number | undefined;
|
|
1182
913
|
let cachedLines: string[] = [];
|
|
1183
|
-
let cachedExpandKey: string | undefined;
|
|
1184
914
|
let cachedDetail: TranscriptDetailPolicy | undefined;
|
|
1185
|
-
let cachedLiveToolOutput: boolean | undefined;
|
|
1186
|
-
/**
|
|
1187
|
-
* The verbosity the last frame rendered under, or null before any frame.
|
|
1188
|
-
* A change between frames is the operator asking for a new baseline
|
|
1189
|
-
* (`/output`, or Settings → Terminal), and every override goes with it.
|
|
1190
|
-
*/
|
|
1191
|
-
let lastVerbosity: OutputVerbosity | undefined | null = null;
|
|
1192
915
|
let cachedTick = 0;
|
|
916
|
+
let cachedTerminalRows = 0;
|
|
1193
917
|
/**
|
|
1194
918
|
* Did the last executed render put a counting elapsed line on screen? It is
|
|
1195
919
|
* what decides whether the render key carries a time tick at all, so a
|
|
@@ -1202,7 +926,7 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1202
926
|
* entries, which re-rendered everything past the cap on every dirty frame
|
|
1203
927
|
* (10 ms/frame at 800 entries). The ceiling bounds worst-case memory at
|
|
1204
928
|
* roughly 4096 rendered entries; past it, the excess only re-renders on
|
|
1205
|
-
* full-rebuild events (width change
|
|
929
|
+
* full-rebuild events (width or style change), which the frozen prefix
|
|
1206
930
|
* below makes rare rather than per-frame.
|
|
1207
931
|
*/
|
|
1208
932
|
const MIN_ENTRY_RENDER_CACHE = 256;
|
|
@@ -1220,13 +944,6 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1220
944
|
* the render key changes.
|
|
1221
945
|
*/
|
|
1222
946
|
let frozen: { lines: string[]; through: number; key: string } | null = null;
|
|
1223
|
-
let liveToolOutput = true;
|
|
1224
|
-
/**
|
|
1225
|
-
* The run tally's reasoning, projected. It is panel-level rather than
|
|
1226
|
-
* per-entry because only the pending tail entry ever renders it, and that
|
|
1227
|
-
* entry is by definition unfrozen and uncached.
|
|
1228
|
-
*/
|
|
1229
|
-
let liveReasoning: ReasoningUsageView = UNMEASURED_REASONING;
|
|
1230
947
|
const unboundedToolBodies = options.unboundedToolBodies === true;
|
|
1231
948
|
|
|
1232
949
|
const markDirty = (): void => {
|
|
@@ -1250,39 +967,8 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1250
967
|
if (frozen !== null && frozen.through >= transcript.length) frozen = null;
|
|
1251
968
|
};
|
|
1252
969
|
|
|
1253
|
-
const resolveExpandKey = (): string | undefined => {
|
|
1254
|
-
const key = options.getToolExpandKey?.();
|
|
1255
|
-
if (typeof key !== "string" || key.length === 0) return undefined;
|
|
1256
|
-
return key;
|
|
1257
|
-
};
|
|
1258
|
-
|
|
1259
970
|
const now = (): number => options.now?.() ?? Date.now();
|
|
1260
|
-
|
|
1261
|
-
/** The policy for a frame or a keypress, from whatever the settings say right now. */
|
|
1262
|
-
const currentDetail = (): TranscriptDetailPolicy => transcriptDetail(options.getOutputVerbosity?.());
|
|
1263
|
-
|
|
1264
|
-
/**
|
|
1265
|
-
* Drop every operator override. Shared by the panel method and the
|
|
1266
|
-
* verbosity-change path in render, so both leave the same state behind.
|
|
1267
|
-
*/
|
|
1268
|
-
const dropFoldOverrides = (): void => {
|
|
1269
|
-
for (const entry of transcript) {
|
|
1270
|
-
if (entry.role === "replayBlock") {
|
|
1271
|
-
entry.fold?.setFold(undefined);
|
|
1272
|
-
continue;
|
|
1273
|
-
}
|
|
1274
|
-
if (entry.role === "worker") {
|
|
1275
|
-
entry.fold = undefined;
|
|
1276
|
-
continue;
|
|
1277
|
-
}
|
|
1278
|
-
if (entry.role !== "assistant") continue;
|
|
1279
|
-
for (const seg of entry.segments) {
|
|
1280
|
-
if (seg.kind === "tool" || seg.kind === "thinking") seg.fold = undefined;
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
clearRenderCaches();
|
|
1284
|
-
markDirty();
|
|
1285
|
-
};
|
|
971
|
+
const currentDetail = (): TranscriptDetailPolicy => transcriptDetail(options.getOutputStyle?.());
|
|
1286
972
|
|
|
1287
973
|
/**
|
|
1288
974
|
* Force an in-flight tool segment to a settled error line. A call blocked at
|
|
@@ -1460,37 +1146,6 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1460
1146
|
entry.segments.push({ kind: "error", text });
|
|
1461
1147
|
};
|
|
1462
1148
|
|
|
1463
|
-
/**
|
|
1464
|
-
* Who advertises the fold key this frame: the newest worker card whose
|
|
1465
|
-
* effective state is folded, or the newest finished tool subline whose
|
|
1466
|
-
* effective state is folded with no worker card behind it. Effective means
|
|
1467
|
-
* override-or-policy, so the hint follows the block whatever the verbosity.
|
|
1468
|
-
* One surface at most, because the key reaches the newest foldable thing of
|
|
1469
|
-
* either kind, and a chord shown anywhere else would open something the
|
|
1470
|
-
* operator was not looking at. An already-open newest card advertises
|
|
1471
|
-
* nothing, since folding it again needs no invitation.
|
|
1472
|
-
*/
|
|
1473
|
-
const expandHintOwner = (detail: TranscriptDetailPolicy): { toolId: string | null; workerId: string | null } => {
|
|
1474
|
-
let workerMayOwn = true;
|
|
1475
|
-
for (let entryIndex = transcript.length - 1; entryIndex >= 0; entryIndex -= 1) {
|
|
1476
|
-
const entry = transcript[entryIndex];
|
|
1477
|
-
if (entry?.role === "worker") {
|
|
1478
|
-
return {
|
|
1479
|
-
toolId: null,
|
|
1480
|
-
workerId: workerMayOwn && workerEntryFolded(entry, detail) ? entry.state.assignmentId : null,
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1483
|
-
if (entry?.role !== "assistant") continue;
|
|
1484
|
-
for (let segIndex = entry.segments.length - 1; segIndex >= 0; segIndex -= 1) {
|
|
1485
|
-
const seg = entry.segments[segIndex];
|
|
1486
|
-
if (seg?.kind !== "tool") continue;
|
|
1487
|
-
if (seg.finished && !toolSegmentExpanded(seg, detail)) return { toolId: seg.id, workerId: null };
|
|
1488
|
-
workerMayOwn = false;
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
return { toolId: null, workerId: null };
|
|
1492
|
-
};
|
|
1493
|
-
|
|
1494
1149
|
/**
|
|
1495
1150
|
* Where a newly seen worker block belongs. An agent-origin run nests under
|
|
1496
1151
|
* the assistant entry holding the tool call that spawned it, behind any
|
|
@@ -1511,12 +1166,6 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1511
1166
|
return index >= transcript.length ? null : index;
|
|
1512
1167
|
};
|
|
1513
1168
|
|
|
1514
|
-
/** True when the entry owns the tool the expand hint currently points at. */
|
|
1515
|
-
const entryContainsHint = (entry: TranscriptEntry, latestHintToolId: string | null): boolean =>
|
|
1516
|
-
latestHintToolId !== null &&
|
|
1517
|
-
entry.role === "assistant" &&
|
|
1518
|
-
entry.segments.some((segment) => segment.kind === "tool" && segment.id === latestHintToolId);
|
|
1519
|
-
|
|
1520
1169
|
/** True when the entry renders at least one counting elapsed line this frame. */
|
|
1521
1170
|
const entryHasRunningTool = (entry: TranscriptEntry): boolean =>
|
|
1522
1171
|
(entry.role === "assistant" &&
|
|
@@ -1546,13 +1195,8 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1546
1195
|
|
|
1547
1196
|
const render = (width: number): string[] => {
|
|
1548
1197
|
const startedAt = performance.now();
|
|
1549
|
-
const
|
|
1550
|
-
const
|
|
1551
|
-
// A new verbosity is a new baseline: the operator's per-block overrides
|
|
1552
|
-
// were answers to the old one, so they go before the frame is built.
|
|
1553
|
-
if (lastVerbosity !== null && verbosity !== lastVerbosity) dropFoldOverrides();
|
|
1554
|
-
lastVerbosity = verbosity;
|
|
1555
|
-
const detail = transcriptDetail(verbosity);
|
|
1198
|
+
const detail = currentDetail();
|
|
1199
|
+
const terminalRows = options.getTerminalRows?.() ?? 40;
|
|
1556
1200
|
const nowMs = now();
|
|
1557
1201
|
// `dirty` is set on mutation and never on a tick, so without time in the
|
|
1558
1202
|
// key a running tool's elapsed counter advanced only when something
|
|
@@ -1562,36 +1206,23 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1562
1206
|
// pinned to 0 whenever nothing is counting so a settled transcript
|
|
1563
1207
|
// re-renders no more often than it did before.
|
|
1564
1208
|
const tick = renderedRunningTool ? Math.floor(nowMs / 100) : 0;
|
|
1565
|
-
// The hit guard runs before any transcript scan. expandHintOwner
|
|
1566
|
-
// walks the whole transcript when the newest tool is expanded or absent, and
|
|
1567
|
-
// it is not part of the panel-level key, so computing it above the guard cost
|
|
1568
|
-
// a full scan per frame for a value the early return discards.
|
|
1569
1209
|
if (
|
|
1570
1210
|
!dirty &&
|
|
1571
1211
|
cachedWidth === width &&
|
|
1572
|
-
|
|
1212
|
+
cachedTerminalRows === terminalRows &&
|
|
1573
1213
|
cachedDetail === detail &&
|
|
1574
|
-
cachedLiveToolOutput === liveToolOutput &&
|
|
1575
1214
|
cachedTick === tick
|
|
1576
1215
|
) {
|
|
1577
1216
|
options.onRenderMetrics?.({ durationMs: performance.now() - startedAt, cacheHit: true, entriesRendered: 0 });
|
|
1578
1217
|
return cachedLines;
|
|
1579
1218
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
// every finished collapsed tool, and keying every entry on it re-rendered
|
|
1583
|
-
// the entire transcript per tool completion. Only the entry that contains
|
|
1584
|
-
// the hint tool renders differently, so only that entry's key carries it.
|
|
1585
|
-
// The tick stays out of the entry key: a settled entry renders the same
|
|
1586
|
-
// bytes at every tick, and keying it on time would drop the entry cache
|
|
1587
|
-
// and the frozen prefix ten times a second. Only the panel-level guard
|
|
1588
|
-
// above is time-keyed, so a tick re-renders the live tail and nothing else.
|
|
1589
|
-
const baseKey = `${width}|${expandKey ?? ""}|${detail.toolBody}:${detail.runningTool}:${detail.thinking}:${detail.worker}:${detail.receipt}:${detail.errors}|${liveToolOutput}`;
|
|
1219
|
+
// Stable entries cache by width, height budget, and preset.
|
|
1220
|
+
const baseKey = `${width}|${terminalRows}|${detail.style}`;
|
|
1590
1221
|
const capacity = entryCacheCapacity();
|
|
1591
1222
|
if (frozen !== null && frozen.key !== baseKey) frozen = null;
|
|
1592
1223
|
const out: string[] = frozen === null ? [] : frozen.lines.slice();
|
|
1593
1224
|
const startIndex = frozen === null ? 0 : frozen.through;
|
|
1594
|
-
// The freeze extends over the contiguous run of stable
|
|
1225
|
+
// The freeze extends over the contiguous run of stable leading
|
|
1595
1226
|
// entries; it is captured after the loop from what this frame rendered.
|
|
1596
1227
|
let freezeThrough = startIndex;
|
|
1597
1228
|
let freezeLineCount = out.length;
|
|
@@ -1609,16 +1240,9 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1609
1240
|
// five scouts costs five rows, which is what makes the folded default
|
|
1610
1241
|
// worth having. Anything else keeps the blank line between entries.
|
|
1611
1242
|
const previous = i > 0 ? transcript[i - 1] : undefined;
|
|
1612
|
-
const stacksOnPrevious =
|
|
1613
|
-
entry.role === "worker" &&
|
|
1614
|
-
previous?.role === "worker" &&
|
|
1615
|
-
workerEntryFolded(entry, detail) &&
|
|
1616
|
-
workerEntryFolded(previous, detail);
|
|
1243
|
+
const stacksOnPrevious = entry.role === "worker" && previous?.role === "worker" && detail.style === "compact";
|
|
1617
1244
|
if (i > 0 && !stacksOnPrevious) out.push("");
|
|
1618
|
-
const
|
|
1619
|
-
entryContainsHint(entry, latestHintToolId) ||
|
|
1620
|
-
(entry.role === "worker" && entry.state.assignmentId === latestFoldedWorkerId);
|
|
1621
|
-
const entryKey = containsHint ? `${baseKey}|hint:${latestHintToolId}|${latestFoldedWorkerId}` : baseKey;
|
|
1245
|
+
const entryKey = baseKey;
|
|
1622
1246
|
const cached = entryRenderCache.get(entry);
|
|
1623
1247
|
const cacheable = i >= transcript.length - capacity && entry.role !== "replayBlock" && entryIsStable(entry);
|
|
1624
1248
|
if (cacheable && cached?.key === entryKey) {
|
|
@@ -1627,18 +1251,7 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1627
1251
|
for (const line of cached.lines) out.push(line);
|
|
1628
1252
|
} else {
|
|
1629
1253
|
entriesRendered += 1;
|
|
1630
|
-
const renderedEntry = renderEntryLines(
|
|
1631
|
-
entry,
|
|
1632
|
-
width,
|
|
1633
|
-
expandKey,
|
|
1634
|
-
latestHintToolId,
|
|
1635
|
-
latestFoldedWorkerId,
|
|
1636
|
-
nowMs,
|
|
1637
|
-
unboundedToolBodies,
|
|
1638
|
-
detail,
|
|
1639
|
-
liveToolOutput,
|
|
1640
|
-
liveReasoning,
|
|
1641
|
-
);
|
|
1254
|
+
const renderedEntry = renderEntryLines(entry, width, nowMs, unboundedToolBodies, detail, terminalRows);
|
|
1642
1255
|
for (const line of renderedEntry) out.push(line);
|
|
1643
1256
|
if (cacheable) {
|
|
1644
1257
|
entryRenderCache.set(entry, { key: entryKey, lines: renderedEntry });
|
|
@@ -1649,7 +1262,7 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1649
1262
|
}
|
|
1650
1263
|
}
|
|
1651
1264
|
}
|
|
1652
|
-
if (freezeOpen && i === freezeThrough && entryIsStable(entry)
|
|
1265
|
+
if (freezeOpen && i === freezeThrough && entryIsStable(entry)) {
|
|
1653
1266
|
freezeThrough = i + 1;
|
|
1654
1267
|
freezeLineCount = out.length;
|
|
1655
1268
|
} else {
|
|
@@ -1659,9 +1272,8 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1659
1272
|
frozen = freezeThrough > 0 ? { lines: out.slice(0, freezeLineCount), through: freezeThrough, key: baseKey } : null;
|
|
1660
1273
|
cachedLines = out;
|
|
1661
1274
|
cachedWidth = width;
|
|
1662
|
-
cachedExpandKey = expandKey;
|
|
1663
1275
|
cachedDetail = detail;
|
|
1664
|
-
|
|
1276
|
+
cachedTerminalRows = terminalRows;
|
|
1665
1277
|
cachedTick = tick;
|
|
1666
1278
|
renderedRunningTool = sawRunningTool;
|
|
1667
1279
|
dirty = false;
|
|
@@ -1674,8 +1286,8 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1674
1286
|
transcript.push({ role: "user", text, ...(status ? { status } : {}) });
|
|
1675
1287
|
markDirty();
|
|
1676
1288
|
},
|
|
1677
|
-
appendReplayBlock(renderBlock: ReplayBlockRenderer, isLive?: () => boolean
|
|
1678
|
-
transcript.push({ role: "replayBlock", renderBlock, isLive
|
|
1289
|
+
appendReplayBlock(renderBlock: ReplayBlockRenderer, isLive?: () => boolean): void {
|
|
1290
|
+
transcript.push({ role: "replayBlock", renderBlock, isLive });
|
|
1679
1291
|
markDirty();
|
|
1680
1292
|
},
|
|
1681
1293
|
applyWorkerState(state: WorkerEntryState): void {
|
|
@@ -1703,135 +1315,58 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1703
1315
|
workerStates(): ReadonlyArray<WorkerEntryState> {
|
|
1704
1316
|
return [...workerEntries.values()].map((entry) => entry.state);
|
|
1705
1317
|
},
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
if (entry?.role === "replayBlock" && entry.fold !== undefined) {
|
|
1720
|
-
entry.fold.setFold(toggledFold(resolveFold(entry.fold.fold(), entry.fold.policyFold(detail))));
|
|
1721
|
-
clearRenderCaches();
|
|
1722
|
-
markDirty();
|
|
1723
|
-
return true;
|
|
1724
|
-
}
|
|
1725
|
-
if (entry?.role === "worker") {
|
|
1726
|
-
entry.fold = workerEntryFolded(entry, detail) ? "expanded" : "folded";
|
|
1727
|
-
clearRenderCaches();
|
|
1728
|
-
markDirty();
|
|
1729
|
-
return true;
|
|
1730
|
-
}
|
|
1731
|
-
if (entry?.role !== "assistant") continue;
|
|
1732
|
-
for (let segIndex = entry.segments.length - 1; segIndex >= 0; segIndex -= 1) {
|
|
1733
|
-
const seg = entry.segments[segIndex];
|
|
1734
|
-
if (seg?.kind !== "tool") continue;
|
|
1735
|
-
seg.fold = toolSegmentExpanded(seg, detail) ? "folded" : "expanded";
|
|
1736
|
-
clearRenderCaches();
|
|
1737
|
-
markDirty();
|
|
1738
|
-
return true;
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
return false;
|
|
1742
|
-
},
|
|
1743
|
-
toggleAllToolsExpanded(): boolean {
|
|
1744
|
-
const detail = currentDetail();
|
|
1745
|
-
const tools: ToolSegment[] = [];
|
|
1746
|
-
const workers: WorkerTranscriptEntry[] = [];
|
|
1747
|
-
const blocks: ReplayBlockFoldControl[] = [];
|
|
1748
|
-
for (const entry of transcript) {
|
|
1749
|
-
if (entry.role === "replayBlock") {
|
|
1750
|
-
if (entry.fold !== undefined) blocks.push(entry.fold);
|
|
1751
|
-
continue;
|
|
1752
|
-
}
|
|
1753
|
-
if (entry.role === "worker") {
|
|
1754
|
-
workers.push(entry);
|
|
1755
|
-
continue;
|
|
1756
|
-
}
|
|
1757
|
-
if (entry.role !== "assistant") continue;
|
|
1758
|
-
for (const seg of entry.segments) {
|
|
1759
|
-
if (seg.kind === "tool") tools.push(seg);
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
if (tools.length === 0 && workers.length === 0 && blocks.length === 0) return false;
|
|
1763
|
-
// One folded block anywhere means "open everything"; otherwise fold
|
|
1764
|
-
// everything. Either way every block gets an explicit override.
|
|
1765
|
-
const expand =
|
|
1766
|
-
tools.some((seg) => !toolSegmentExpanded(seg, detail)) ||
|
|
1767
|
-
workers.some((entry) => workerEntryFolded(entry, detail)) ||
|
|
1768
|
-
blocks.some((fold) => resolveFold(fold.fold(), fold.policyFold(detail)) === "folded");
|
|
1769
|
-
const next: Fold = expand ? "expanded" : "folded";
|
|
1770
|
-
for (const seg of tools) seg.fold = next;
|
|
1771
|
-
for (const entry of workers) entry.fold = next;
|
|
1772
|
-
for (const fold of blocks) fold.setFold(next);
|
|
1773
|
-
clearRenderCaches();
|
|
1774
|
-
markDirty();
|
|
1775
|
-
return true;
|
|
1776
|
-
},
|
|
1777
|
-
clearFoldOverrides(): void {
|
|
1778
|
-
dropFoldOverrides();
|
|
1779
|
-
},
|
|
1780
|
-
toggleLastThinking(): boolean {
|
|
1781
|
-
const detail = currentDetail();
|
|
1782
|
-
for (let entryIndex = transcript.length - 1; entryIndex >= 0; entryIndex -= 1) {
|
|
1783
|
-
const entry = transcript[entryIndex];
|
|
1784
|
-
if (entry?.role !== "assistant") continue;
|
|
1785
|
-
for (let segIndex = entry.segments.length - 1; segIndex >= 0; segIndex -= 1) {
|
|
1786
|
-
const segment = entry.segments[segIndex];
|
|
1787
|
-
if (segment?.kind !== "thinking" || segment.text.length === 0) continue;
|
|
1788
|
-
segment.fold = thinkingExpanded(segment, detail) ? "folded" : "expanded";
|
|
1789
|
-
clearRenderCaches();
|
|
1790
|
-
markDirty();
|
|
1791
|
-
return true;
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
return false;
|
|
1795
|
-
},
|
|
1796
|
-
toggleAllThinking(): boolean {
|
|
1797
|
-
const detail = currentDetail();
|
|
1798
|
-
const segments: ThinkingSegment[] = [];
|
|
1318
|
+
inspectionArtifacts(): ViewArtifact[] {
|
|
1319
|
+
const artifacts: ViewArtifact[] = [];
|
|
1320
|
+
const add = (title: string, render: () => string[]) => {
|
|
1321
|
+
const index = artifacts.length;
|
|
1322
|
+
artifacts.push({
|
|
1323
|
+
id: `transcript:${index + 1}`,
|
|
1324
|
+
category: "transcript",
|
|
1325
|
+
title,
|
|
1326
|
+
timestamp: now() + index,
|
|
1327
|
+
searchText: [title],
|
|
1328
|
+
load: async () => ({ format: "text", lines: render().map(redactSecretString) }),
|
|
1329
|
+
});
|
|
1330
|
+
};
|
|
1799
1331
|
for (const entry of transcript) {
|
|
1800
|
-
if (entry.role
|
|
1801
|
-
|
|
1802
|
-
|
|
1332
|
+
if (entry.role === "assistant") {
|
|
1333
|
+
for (const seg of entry.segments) {
|
|
1334
|
+
if (seg.kind === "thinking" && seg.text) add("Thinking · supplied reasoning", () => seg.text.split("\n"));
|
|
1335
|
+
if (seg.kind === "tool")
|
|
1336
|
+
add(`${seg.name} · ${seg.id}`, () =>
|
|
1337
|
+
renderToolExecution(
|
|
1338
|
+
{
|
|
1339
|
+
toolCallId: seg.id,
|
|
1340
|
+
toolName: seg.name,
|
|
1341
|
+
args: seg.args,
|
|
1342
|
+
result: seg.result ?? seg.partialResult,
|
|
1343
|
+
isError: seg.isError,
|
|
1344
|
+
outcome: seg.settlement,
|
|
1345
|
+
blockReason: seg.blockReason,
|
|
1346
|
+
resultSummary: seg.resultSummary,
|
|
1347
|
+
},
|
|
1348
|
+
120,
|
|
1349
|
+
{ unbounded: true, diffStyle: "plain" },
|
|
1350
|
+
),
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
} else if (entry.role === "worker") {
|
|
1354
|
+
add(`${entry.state.agentId} · worker ${entry.state.runId}`, () =>
|
|
1355
|
+
renderWorkerEntryLines(entry.state, 120, { unbounded: true }),
|
|
1356
|
+
);
|
|
1357
|
+
} else if (entry.role === "replayBlock") {
|
|
1358
|
+
add("Session action", () => entry.renderBlock(120, transcriptDetail("detailed"), true));
|
|
1803
1359
|
}
|
|
1804
1360
|
}
|
|
1805
|
-
|
|
1806
|
-
const expand = segments.some((segment) => !thinkingExpanded(segment, detail));
|
|
1807
|
-
for (const segment of segments) segment.fold = expand ? "expanded" : "folded";
|
|
1808
|
-
clearRenderCaches();
|
|
1809
|
-
markDirty();
|
|
1810
|
-
return true;
|
|
1361
|
+
return artifacts;
|
|
1811
1362
|
},
|
|
1812
1363
|
isThinkingExpanded(): boolean {
|
|
1813
|
-
|
|
1814
|
-
// if any, is the one that applies. Before a stretch arrives, the policy answers.
|
|
1815
|
-
const detail = currentDetail();
|
|
1816
|
-
const index = lastAssistantIndex(transcript);
|
|
1817
|
-
const entry = index === null ? undefined : transcript[index];
|
|
1818
|
-
if (entry?.role === "assistant") {
|
|
1819
|
-
for (let segIndex = entry.segments.length - 1; segIndex >= 0; segIndex -= 1) {
|
|
1820
|
-
const segment = entry.segments[segIndex];
|
|
1821
|
-
if (segment?.kind === "thinking" && segment.text.length > 0) return thinkingExpanded(segment, detail);
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
return policyThinkingFold(detail) === "expanded";
|
|
1825
|
-
},
|
|
1826
|
-
toggleLiveToolOutput(): boolean {
|
|
1827
|
-
liveToolOutput = !liveToolOutput;
|
|
1828
|
-
markDirty();
|
|
1829
|
-
return liveToolOutput;
|
|
1364
|
+
return currentDetail().reasoningRows > 0;
|
|
1830
1365
|
},
|
|
1831
1366
|
reset(): void {
|
|
1832
1367
|
transcript.length = 0;
|
|
1368
|
+
runStartedAt = undefined;
|
|
1833
1369
|
workerEntries.clear();
|
|
1834
|
-
liveReasoning = UNMEASURED_REASONING;
|
|
1835
1370
|
clearRenderCaches();
|
|
1836
1371
|
markDirty();
|
|
1837
1372
|
},
|
|
@@ -1843,6 +1378,10 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
1843
1378
|
markDirty();
|
|
1844
1379
|
},
|
|
1845
1380
|
applyEvent(event: ChatLoopEvent): void {
|
|
1381
|
+
if (event.type === "agent_start") {
|
|
1382
|
+
runStartedAt = now();
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1846
1385
|
if (event.type === "agent_status") {
|
|
1847
1386
|
return;
|
|
1848
1387
|
}
|
|
@@ -2149,7 +1688,21 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
2149
1688
|
const target = index === null ? undefined : transcript[index];
|
|
2150
1689
|
if (target?.role === "assistant") {
|
|
2151
1690
|
invalidateEntryCache(target);
|
|
2152
|
-
|
|
1691
|
+
const stop = event.messages.filter((message) => message.role === "assistant").at(-1) as
|
|
1692
|
+
| { stopReason?: string }
|
|
1693
|
+
| undefined;
|
|
1694
|
+
target.turnUsage = {
|
|
1695
|
+
...runUsage,
|
|
1696
|
+
...(runStartedAt === undefined ? {} : { elapsedMs: Math.max(0, now() - runStartedAt) }),
|
|
1697
|
+
outcome:
|
|
1698
|
+
stop?.stopReason === "error"
|
|
1699
|
+
? "Failed"
|
|
1700
|
+
: stop?.stopReason === "aborted"
|
|
1701
|
+
? "Cancelled"
|
|
1702
|
+
: stop?.stopReason === "length"
|
|
1703
|
+
? "Output limit"
|
|
1704
|
+
: "Done",
|
|
1705
|
+
};
|
|
2153
1706
|
}
|
|
2154
1707
|
for (let after = (index ?? -1) + 1; after < transcript.length; after += 1) {
|
|
2155
1708
|
const later = transcript[after];
|
|
@@ -2183,39 +1736,12 @@ export function createChatPanel(options: ChatPanelOptions = {}): ChatPanel {
|
|
|
2183
1736
|
invalidateEntryCache(entry);
|
|
2184
1737
|
closeOpenThinking(entry);
|
|
2185
1738
|
entry.pending = false;
|
|
2186
|
-
entry.statusLine = null;
|
|
2187
1739
|
entry.messageStartSegmentIndex = undefined;
|
|
2188
1740
|
}
|
|
2189
1741
|
}
|
|
2190
1742
|
markDirty();
|
|
2191
1743
|
}
|
|
2192
1744
|
},
|
|
2193
|
-
setLiveReasoning(view: ReasoningUsageView | null): void {
|
|
2194
|
-
const next = view ?? UNMEASURED_REASONING;
|
|
2195
|
-
if (next.tokens === liveReasoning.tokens && next.provenance === liveReasoning.provenance) return;
|
|
2196
|
-
liveReasoning = next;
|
|
2197
|
-
// The line lives on the pending tail entry, which the freeze may already
|
|
2198
|
-
// cover if nothing has mutated since the last settle.
|
|
2199
|
-
unfreezeTail();
|
|
2200
|
-
const last = transcript[transcript.length - 1];
|
|
2201
|
-
if (last !== undefined) invalidateEntryCache(last);
|
|
2202
|
-
markDirty();
|
|
2203
|
-
},
|
|
2204
|
-
setStatusLine(line): void {
|
|
2205
|
-
if (line) {
|
|
2206
|
-
const assistant = ensureAssistant();
|
|
2207
|
-
assistant.pending = true;
|
|
2208
|
-
assistant.statusLine = line;
|
|
2209
|
-
markDirty();
|
|
2210
|
-
return;
|
|
2211
|
-
}
|
|
2212
|
-
const last = transcript[transcript.length - 1];
|
|
2213
|
-
if (last && last.role === "assistant") {
|
|
2214
|
-
unfreezeTail();
|
|
2215
|
-
last.statusLine = null;
|
|
2216
|
-
markDirty();
|
|
2217
|
-
}
|
|
2218
|
-
},
|
|
2219
1745
|
render,
|
|
2220
1746
|
invalidate(): void {
|
|
2221
1747
|
markDirty();
|