@iowarp/clio-coder 0.4.4 → 0.4.5
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 +92 -2
- package/CONTRIBUTING.md +25 -15
- package/README.md +340 -27
- package/dist/{acp-WNAYYF4F.js → acp-H3CU2HBQ.js} +25 -24
- package/dist/{agents-3OKXHLOI.js → agents-IXQQZ7BD.js} +77 -77
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-VKNNMGPU.js → auth-R7KYF7N3.js} +38 -38
- package/dist/builtins-CRFDQUVP.js +22 -0
- package/dist/{chunk-TQAHXW6Y.js → chunk-22PQ4TX4.js} +4 -4
- 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-JCI2ROMZ.js → chunk-3T4DXWP6.js} +7 -7
- package/dist/{chunk-DR52UMZW.js → chunk-3UW3KU4A.js} +2 -2
- package/dist/{chunk-6Q3CYFD3.js → chunk-4SVIVOMC.js} +184 -33
- 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-I2DWJ4GM.js → chunk-5DDOTTG4.js} +54 -42
- package/dist/{chunk-D4CJV46V.js → chunk-5GZICIYO.js} +3 -3
- package/dist/{chunk-4IUZQIJ3.js → chunk-5PHVPU4G.js} +2 -2
- package/dist/{chunk-3ODX73FK.js → chunk-5VTJP36Q.js} +4 -4
- package/dist/{chunk-54X7T7DK.js → chunk-5ZMXGW7P.js} +79 -7
- package/dist/chunk-5ZSZEYJK.js +119 -0
- package/dist/{chunk-IXIY2H4R.js → chunk-633EXGZA.js} +5 -5
- package/dist/{chunk-CUSRQKPU.js → chunk-6CDNRHWH.js} +299 -89
- package/dist/{chunk-EBY63B7G.js → chunk-6EXUUOSN.js} +2 -2
- package/dist/{chunk-SVNXH4L2.js → chunk-6ICZKDUC.js} +2 -2
- package/dist/{chunk-JEIYHLOR.js → chunk-6SYEGZI3.js} +12 -12
- package/dist/{chunk-DQOVN6KV.js → chunk-6YA46L5A.js} +4 -4
- package/dist/{chunk-NZMNUPZZ.js → chunk-77CZRFTE.js} +3 -3
- package/dist/{chunk-6PAZTBPA.js → chunk-7HBHHVCK.js} +15 -6
- package/dist/{chunk-25QBEXRS.js → chunk-7TKWWPD7.js} +5 -4
- 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-UOIZ7DA4.js → chunk-AP7HDJOP.js} +2 -2
- 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-4O6MANBS.js → chunk-BS4GAMUB.js} +14 -10
- 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-YNFKXPEC.js → chunk-DIMRLNIC.js} +35 -66
- package/dist/{chunk-NDDGJUXD.js → chunk-DNCE23JJ.js} +2 -2
- package/dist/{chunk-HVDIIIQW.js → chunk-DNHVRBH4.js} +3 -3
- package/dist/{chunk-XULDXHTN.js → chunk-DRD2A54W.js} +102 -50
- package/dist/{chunk-D7E7WCDF.js → chunk-DVNAPPXU.js} +2 -2
- package/dist/{chunk-YXLYO42X.js → chunk-DXVMLM3Z.js} +3 -2
- package/dist/{chunk-5MEZN6CB.js → chunk-DZK63TZJ.js} +6 -6
- package/dist/{chunk-IGLP3ODT.js → chunk-E3BQTQUP.js} +15 -15
- package/dist/{chunk-IWHMRKLL.js → chunk-E3LEPLQ2.js} +2 -2
- 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-FEAXX7B6.js → chunk-EHCPSZJF.js} +4 -4
- package/dist/{chunk-4NSRCOYP.js → chunk-EHOSNVVM.js} +3 -2
- package/dist/{chunk-7UGL4MB5.js → chunk-EQEJJ53P.js} +10 -10
- package/dist/{chunk-GWZNEVM2.js → chunk-EWD5P3GK.js} +9 -9
- package/dist/{chunk-6UINWWS6.js → chunk-F34AR6O3.js} +14 -14
- package/dist/{chunk-GHS5EBTQ.js → chunk-FKIOX6DS.js} +29 -20
- package/dist/{chunk-HAXOFFRH.js → chunk-FQOOGXBH.js} +7 -7
- package/dist/{chunk-Y55JBDO5.js → chunk-FSTIBAGM.js} +38 -23
- 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-QUFRYSWI.js → chunk-GNQRWTMY.js} +129 -48
- package/dist/{chunk-5ICU3EUH.js → chunk-GVYWZNRK.js} +5 -5
- package/dist/{chunk-GX5WYQO4.js → chunk-GXCCHKN6.js} +6 -6
- package/dist/{chunk-K6T2ZAMZ.js → chunk-HGSLRG33.js} +6 -6
- package/dist/{chunk-26QSH3EJ.js → chunk-HHVJNVUJ.js} +5 -5
- package/dist/{chunk-F4EKGO4N.js → chunk-HL26ADLH.js} +4 -2
- package/dist/{chunk-JT2RFCC5.js → chunk-HR3HPQ76.js} +5 -5
- package/dist/{chunk-ID64D7PE.js → chunk-HXHFDHB6.js} +24 -24
- package/dist/{chunk-ELWDPP3Y.js → chunk-I7VLWRK2.js} +8 -8
- package/dist/{chunk-6OSVSQL5.js → chunk-ICO4TQ2F.js} +7 -5
- package/dist/{chunk-SZAA6XDG.js → chunk-IFDRAD6F.js} +2 -2
- package/dist/{chunk-72YIHOZQ.js → chunk-ILJ7DWGE.js} +9 -9
- package/dist/{chunk-2JH2WHGE.js → chunk-J2FYEQ5L.js} +4 -4
- package/dist/{chunk-BMS5RKQY.js → chunk-JABWPKFY.js} +3 -3
- package/dist/{chunk-QDC3K2U3.js → chunk-K2BLQC5E.js} +3 -3
- package/dist/{chunk-AUPNRN7C.js → chunk-K2HL3GBL.js} +4 -4
- package/dist/{chunk-2ASED4PZ.js → chunk-K6RDB7IA.js} +26 -26
- package/dist/{chunk-FFUPXJC4.js → chunk-KDWLXVMN.js} +23 -24
- package/dist/{chunk-OZNBF4L3.js → chunk-KECNXMDE.js} +2 -2
- package/dist/{chunk-6QOTUPRG.js → chunk-KF6GFW6O.js} +66 -18
- 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-57XXR6DR.js → chunk-KYKNBD4Y.js} +24 -23
- package/dist/{chunk-IRXAATOX.js → chunk-L4N3DWNW.js} +3 -3
- 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-NEKRRTYW.js → chunk-MC3JSVR6.js} +2 -2
- package/dist/{chunk-CFGTUFWB.js → chunk-MCJKEGHO.js} +2 -2
- package/dist/{chunk-DXKJURES.js → chunk-MDU3C27C.js} +10 -7
- package/dist/{chunk-6XLNIQDB.js → chunk-MYI32N4R.js} +2 -2
- package/dist/{chunk-3GY4F45V.js → chunk-NC4KV7EL.js} +6 -6
- package/dist/{chunk-LLXSDWXS.js → chunk-NF3BK5WR.js} +5 -5
- package/dist/chunk-NTK3WTHM.js +141 -0
- package/dist/{chunk-GYV6VZOC.js → chunk-NTTS3O53.js} +2 -2
- package/dist/{chunk-RZDWV63N.js → chunk-NY6IWDVU.js} +6 -6
- package/dist/{chunk-XXYSBZIQ.js → chunk-O2RQ7LCK.js} +4 -4
- 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-LTIKRKFL.js → chunk-ONRTXOZY.js} +4 -4
- package/dist/{chunk-KFV5L5SK.js → chunk-OQM5IVJY.js} +118 -232
- package/dist/{chunk-XRZT5WY5.js → chunk-P5SC4DLJ.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-2STGEDFV.js → chunk-QEQISF75.js} +2 -2
- package/dist/{chunk-3DPEIQKN.js → chunk-QH3ZTUOA.js} +2 -2
- package/dist/{chunk-YAKGTXEV.js → chunk-QRFXEO6Y.js} +2 -2
- package/dist/{chunk-35MSIRKH.js → chunk-QUIJZSDW.js} +2 -2
- package/dist/{chunk-HHV2GANA.js → chunk-R2P2U3ZS.js} +2 -2
- package/dist/{chunk-2DSOYNFC.js → chunk-R6MAYTMS.js} +7 -7
- package/dist/{chunk-JQLNNIKT.js → chunk-R6MICQYU.js} +6 -6
- package/dist/{chunk-NAI6ZFCY.js → chunk-RLTT5GVY.js} +122 -11
- package/dist/{chunk-DT3LWJOB.js → chunk-RXIOCVBZ.js} +24 -6
- package/dist/{chunk-N56KALIC.js → chunk-S32UQ5GL.js} +61 -34
- package/dist/{chunk-UEPWCCTY.js → chunk-SBZX6ARC.js} +12 -12
- package/dist/chunk-SD7SHNDW.js +15 -0
- package/dist/{chunk-NRO2BJRH.js → chunk-SDWNDICN.js} +10235 -4015
- package/dist/{chunk-UXCU4E3T.js → chunk-SE4ZKILO.js} +6 -6
- 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-3M6DQK6S.js → chunk-T334FW2H.js} +7 -7
- package/dist/{chunk-V76WTFTW.js → chunk-T52TPHYC.js} +6 -6
- package/dist/{chunk-I7XBWTYH.js → chunk-T53XI6I7.js} +5 -5
- package/dist/{chunk-2ZSONWVL.js → chunk-T7FDXNRU.js} +13 -13
- package/dist/{chunk-JSD46VO2.js → chunk-TEG3RYVZ.js} +43 -36
- package/dist/{chunk-3I7MS7N2.js → chunk-TK2BMCBZ.js} +2 -2
- package/dist/{chunk-5OIVVPHF.js → chunk-TN5FW4XY.js} +13 -6
- package/dist/{chunk-75W7L2E2.js → chunk-TZ7MFRG4.js} +1041 -162
- package/dist/{chunk-36CT5VVL.js → chunk-U2JOLB7O.js} +126 -77
- 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-RQCKCSRL.js → chunk-U7VQ4NI4.js} +22 -22
- package/dist/{chunk-5TUB6SLS.js → chunk-UFYNOQK4.js} +7 -7
- package/dist/{chunk-R346GLFC.js → chunk-UHW5V7HC.js} +2 -2
- package/dist/{chunk-USR47QNF.js → chunk-UL36QJX6.js} +14 -14
- 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-YD5GIKET.js → chunk-UTUNT5QL.js} +48 -579
- package/dist/{chunk-ZA4VCIGV.js → chunk-UUQ5G6EZ.js} +60 -41
- package/dist/{chunk-23L32XTI.js → chunk-UXAC2FX4.js} +68 -39
- package/dist/{chunk-VG7TBQIY.js → chunk-V552WL53.js} +68 -4
- package/dist/{chunk-BWH6N36D.js → chunk-VHKTOLEW.js} +272 -42
- package/dist/{chunk-EXLD33WO.js → chunk-VLPTKCKT.js} +24 -9
- 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-S6PYF2XF.js → chunk-WFKDPU7U.js} +4 -4
- package/dist/{chunk-BJVFZO5U.js → chunk-WJIMKGD6.js} +7 -7
- package/dist/{chunk-5636DCO5.js → chunk-WLMSOT73.js} +59 -12
- package/dist/{chunk-MXHC5QYU.js → chunk-WTQGRBHV.js} +5 -144
- package/dist/chunk-WXA2CFJO.js +23 -0
- package/dist/{chunk-QSNYB6ZV.js → chunk-XCUDZQLX.js} +3 -3
- package/dist/{chunk-4M6Z5QVF.js → chunk-XXBQKW32.js} +11 -11
- package/dist/{chunk-OEJSLEPW.js → chunk-YEJIG7LN.js} +332 -332
- package/dist/chunk-YGDMBK7O.js +567 -0
- package/dist/{chunk-4WR7VSYB.js → chunk-YYB3MC65.js} +23 -9
- package/dist/{chunk-2IR2NMPA.js → chunk-ZIDFQJRB.js} +2 -2
- package/dist/{chunk-Q4WO54TA.js → chunk-ZMZQEBKI.js} +14 -14
- 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-5I2IBFYL.js +26 -0
- package/dist/{code-nav-IJR2DBPR.js → code-nav-YXIAEZVS.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-Y2JDJ3JJ.js} +210 -124
- package/dist/configure-SML6UBZ5.js +55 -0
- package/dist/{context-4MPR7WKB.js → context-P5YSEO55.js} +125 -121
- package/dist/{context-2DKHWH2T.js → context-QQ53HSGJ.js} +91 -62
- package/dist/{context-BOYF5EJM.js → context-S2EEC3EJ.js} +62 -31
- package/dist/context-clear-TMEQCOTH.js +183 -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-CNLSQN5K.js} +31 -31
- package/dist/detail-5572VLBO.js +114 -0
- package/dist/{dispatch-runner-RJ5I2F2O.js → dispatch-runner-FRHD6P2O.js} +191 -116
- package/dist/{docs-SPOV3BAN.js → docs-BL7ROUFN.js} +4 -4
- package/dist/{doctor-DKICC2SN.js → doctor-N3LCM2LG.js} +58 -58
- package/dist/{eval-OQOQUDHK.js → eval-BUU3ZOUZ.js} +473 -168
- package/dist/{eval-inventory-Y6QRFOH5.js → eval-inventory-QOYZERXJ.js} +7 -7
- package/dist/evidence-DTGEN456.js +224 -0
- package/dist/{evidence-4DQ25GUQ.js → evidence-SQ5DNFEN.js} +110 -94
- package/dist/{evolve-GSS52E5J.js → evolve-IJNUFZDS.js} +107 -91
- package/dist/{extensions-G7MFLYHT.js → extensions-YVRHX6ZI.js} +16 -16
- package/dist/{fleet-Q37YHHAQ.js → fleet-ZNNVSYFO.js} +147 -147
- package/dist/{fleet-commands-G7E4N7SM.js → fleet-commands-5YE7NPJL.js} +27 -26
- package/dist/{fleet-decisions-O7M6QBA2.js → fleet-decisions-3SBSCTCW.js} +16 -15
- package/dist/{fleet-graph-TOUBW6OW.js → fleet-graph-6HHPWF5T.js} +39 -38
- package/dist/{fleet-inspect-SW33JJNI.js → fleet-inspect-JEYMGCGC.js} +107 -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-4PM4GDDL.js} +46 -42
- package/dist/{fleet-verify-UQPMTVE3.js → fleet-verify-NJDTHTO3.js} +105 -89
- package/dist/fleet-view-UP2BWQQY.js +117 -0
- package/dist/{init-PXEXQSBF.js → init-S3GZQ5ZF.js} +123 -123
- package/dist/{install-NKNG7KD4.js → install-3RZDDP23.js} +5 -5
- package/dist/{interop-ZG5T62U3.js → interop-YOTGXFJM.js} +25 -25
- package/dist/inventory-K2OZ36YJ.js +117 -0
- package/dist/{library-B2W4N74O.js → library-GJI6W6OK.js} +45 -44
- package/dist/{memory-YCANYS5A.js → memory-OQOXQGYD.js} +107 -93
- package/dist/{models-GERTU3YI.js → models-3IK2Y5WE.js} +63 -62
- package/dist/{monitor-CPNIUULB.js → monitor-FTJLTKCQ.js} +136 -107
- package/dist/{orchestrator-J4BSH4WQ.js → orchestrator-N47O7SFD.js} +1159 -697
- 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-65U34NG6.js +115 -0
- package/dist/{registry-LG64LTF4.js → registry-DESGAXWK.js} +3 -3
- package/dist/{reset-TNWTB5LU.js → reset-MUVQDLNL.js} +20 -20
- package/dist/{resources-4PXNMD5G.js → resources-LM76COAO.js} +41 -40
- package/dist/{run-D6XJ34CN.js → run-3VFZQ33N.js} +162 -156
- package/dist/{share-2NWMJJEE.js → share-4JUB4BL7.js} +43 -42
- package/dist/{skills-KR7WON5G.js → skills-S36AAJHU.js} +47 -46
- package/dist/{skills-eval-O2ZNOLDS.js → skills-eval-G6T57L7M.js} +127 -107
- package/dist/{skills-inventory-ZZOUBK7O.js → skills-inventory-WLM46PJH.js} +41 -40
- package/dist/slash-commands-GBARG3Y7.js +91 -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-N5REUETU.js} +145 -94
- package/dist/tasks-6BVY5YZF.js +36 -0
- package/dist/{terminal-lease-C2J3JYRE.js → terminal-lease-57UEOJKS.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-4HD5HAIV.js} +40 -39
- package/dist/{usage-NHG6MCJM.js → usage-4GWM2WWP.js} +136 -105
- package/dist/{verifiers-7AUNVXDY.js → verifiers-GSKWKWVG.js} +28 -27
- package/dist/verify-3AS3ULCY.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-7BV7XWIY.js +614 -0
- package/dist/{with-panes-BDQEWBRT.js → with-panes-OFTNAR4Y.js} +34 -20
- package/dist/worker/entry.js +99 -88
- 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 +44 -59
- 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/worker-dispatch-mechanics.md +4 -0
- package/docs/guide/commands-and-modes.md +49 -36
- package/docs/guide/configuration-and-targets.md +7 -2
- package/docs/guide/configuration-reference.md +13 -3
- package/docs/guide/environment-variables.md +6 -2
- package/docs/guide/fleet-dispatch.md +12 -0
- package/docs/guide/installation-and-lifecycle.md +35 -9
- 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 +10 -10
- 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 +6 -6
- 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/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/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/run.ts +16 -14
- 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 +9 -6
- 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 +33 -14
- package/src/core/defaults.ts +5 -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/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/runtime-resolution.ts +11 -9
- package/src/domains/providers/runtimes/cloud/openrouter.ts +2 -0
- 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/chat-loop-messages.ts +12 -4
- package/src/interactive/chat-loop.ts +115 -45
- package/src/interactive/chat-renderer.ts +60 -0
- package/src/interactive/context-recall-command.ts +2 -1
- package/src/interactive/dispatch-board.ts +17 -2
- package/src/interactive/editor-submit.ts +13 -0
- package/src/interactive/interactive-application.ts +8 -2
- package/src/interactive/interactive-event-projection.ts +7 -1
- package/src/interactive/interactive-presentation.ts +15 -7
- package/src/interactive/interactive-slash-runtime.ts +2 -0
- package/src/interactive/layout.ts +2 -1
- package/src/interactive/model-session-replay.ts +2 -2
- package/src/interactive/overlay-frame.ts +1 -0
- package/src/interactive/overlay-general-openers.ts +3 -1
- package/src/interactive/overlay-session-lifecycle.ts +6 -0
- package/src/interactive/overlays/ask-user.ts +1 -0
- package/src/interactive/overlays/message-picker.ts +1 -1
- package/src/interactive/renderers/tool-execution.ts +17 -1
- package/src/interactive/renderers/worker-entry.ts +25 -10
- package/src/interactive/slash-commands.ts +9 -7
- 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/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/read.ts +112 -15
- package/src/tools/registry.ts +54 -17
- 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 +6 -1
- 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
|
@@ -12,10 +12,21 @@
|
|
|
12
12
|
|
|
13
13
|
import { streamSimple } from "../../../engine/ai.js";
|
|
14
14
|
import type { EngineModel, Usage } from "../../../engine/types.js";
|
|
15
|
+
import type { WorkingSetView } from "../../context/working-set/contract.js";
|
|
15
16
|
import { foldWorkingSet } from "../../context/working-set/fold.js";
|
|
17
|
+
import { projectWorkingSet } from "../../context/working-set/project.js";
|
|
16
18
|
import { recallableRefListing } from "../../context/working-set/recall.js";
|
|
17
|
-
import { extractReasoningTokens } from "../context-accounting.js";
|
|
18
|
-
import
|
|
19
|
+
import { estimateAgentContextTokens, extractReasoningTokens } from "../context-accounting.js";
|
|
20
|
+
import {
|
|
21
|
+
type CompactionUsage,
|
|
22
|
+
latestSkillContextState,
|
|
23
|
+
type PreservedUserContext,
|
|
24
|
+
type SessionEntry,
|
|
25
|
+
type SkillContextCheckpoint,
|
|
26
|
+
type SkillContextState,
|
|
27
|
+
skillContextContentHash,
|
|
28
|
+
verifiedSkillContextCheckpoint,
|
|
29
|
+
} from "../entries.js";
|
|
19
30
|
import { serializeConversation } from "./branch-summary.js";
|
|
20
31
|
import { findCutPoint } from "./cut-point.js";
|
|
21
32
|
import { DEFAULT_KEEP_RECENT_TOKENS, DEFAULT_RESERVE_TOKENS } from "./defaults.js";
|
|
@@ -87,6 +98,43 @@ In addition to that carried-forward context, summarize ONLY the active-turn deta
|
|
|
87
98
|
|
|
88
99
|
Do NOT answer the user. Do NOT summarize unrelated older history.`;
|
|
89
100
|
|
|
101
|
+
/** Validate the history checkpoint, never the intentionally different split-turn prompt. */
|
|
102
|
+
function validateHistorySummary(text: string): void {
|
|
103
|
+
const required = [
|
|
104
|
+
"## Goal",
|
|
105
|
+
"## Constraints & Preferences",
|
|
106
|
+
"## Progress",
|
|
107
|
+
"### Done",
|
|
108
|
+
"### In Progress",
|
|
109
|
+
"### Blocked",
|
|
110
|
+
"## Key Decisions",
|
|
111
|
+
"## Next Steps",
|
|
112
|
+
"## Critical Context",
|
|
113
|
+
];
|
|
114
|
+
const headings: string[] = [];
|
|
115
|
+
let fence: { character: string; length: number } | undefined;
|
|
116
|
+
for (const line of text.split(/\r?\n/)) {
|
|
117
|
+
const fenceMatch = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
|
|
118
|
+
if (fenceMatch) {
|
|
119
|
+
const marker = fenceMatch[1] ?? "";
|
|
120
|
+
if (!fence) fence = { character: marker[0] ?? "", length: marker.length };
|
|
121
|
+
else if (marker[0] === fence.character && marker.length >= fence.length && !fenceMatch[2]?.trim()) fence = undefined;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (fence) continue;
|
|
125
|
+
const heading = /^ {0,3}(#{2,3})[ \t]+(.+?)(?:[ \t]+#+)?[ \t]*$/.exec(line);
|
|
126
|
+
if (heading) {
|
|
127
|
+
const normalized = `${heading[1]} ${heading[2]}`;
|
|
128
|
+
if (required.includes(normalized)) headings.push(normalized);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (fence || headings.length !== required.length || headings.some((heading, index) => heading !== required[index])) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"compaction returned an incomplete history checkpoint: required headings must appear in order outside code fences; checkpoint was not saved",
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
90
138
|
/** One invoked summary stream, including failed calls that produce no checkpoint. */
|
|
91
139
|
export interface CompactionCallObservation {
|
|
92
140
|
outcome: "success" | "error" | "aborted";
|
|
@@ -96,8 +144,17 @@ export interface CompactionCallObservation {
|
|
|
96
144
|
}
|
|
97
145
|
|
|
98
146
|
export interface CompactInput {
|
|
99
|
-
/** Ordered session entries to compact
|
|
147
|
+
/** Ordered active-path session entries to compact; returned cut indexes address this same array. */
|
|
100
148
|
entries: ReadonlyArray<SessionEntry>;
|
|
149
|
+
/** Authoritative main-agent selection; omitted for unknown legacy state. */
|
|
150
|
+
skillContextState?: SkillContextState | null;
|
|
151
|
+
/** Pure source-test seam. Production uses the existing summary stream. */
|
|
152
|
+
summarize?: (request: {
|
|
153
|
+
systemPrompt: string;
|
|
154
|
+
userText: string;
|
|
155
|
+
maxTokens: number;
|
|
156
|
+
}) => Promise<{ text: string; usage?: unknown }>;
|
|
157
|
+
|
|
101
158
|
/** Resolved orchestrator or compaction-override model. */
|
|
102
159
|
model: EngineModel;
|
|
103
160
|
/** API key for the model. Optional because local engines accept a fallback handled upstream. */
|
|
@@ -114,11 +171,15 @@ export interface CompactInput {
|
|
|
114
171
|
reserveTokens?: number;
|
|
115
172
|
/** Override the built-in keep-recent default (DEFAULT_KEEP_RECENT_TOKENS). */
|
|
116
173
|
keepRecentTokens?: number;
|
|
174
|
+
/** Carry this user message verbatim if removed; defaults to the latest operator turn for manual compaction. */
|
|
175
|
+
preserveUserTurnId?: string;
|
|
117
176
|
/** Accounting observer; called once per invoked stream, including failures. */
|
|
118
177
|
onCall?: (call: CompactionCallObservation) => void;
|
|
119
178
|
}
|
|
120
179
|
|
|
121
180
|
export interface CompactResult {
|
|
181
|
+
skillContext?: SkillContextCheckpoint;
|
|
182
|
+
userContext?: PreservedUserContext;
|
|
122
183
|
/** Generated summary text. Empty when there was nothing to summarize. */
|
|
123
184
|
summary: string;
|
|
124
185
|
/**
|
|
@@ -191,6 +252,157 @@ function findTurnStartForProtection(
|
|
|
191
252
|
return -1;
|
|
192
253
|
}
|
|
193
254
|
|
|
255
|
+
/** Recover only complete, uniquely paired historical main-agent loads. Never consult current disk. */
|
|
256
|
+
export function captureSkillContext(
|
|
257
|
+
entries: ReadonlyArray<SessionEntry>,
|
|
258
|
+
selection: SkillContextState | undefined,
|
|
259
|
+
): SkillContextCheckpoint | undefined {
|
|
260
|
+
if (!selection || selection.unknown) return undefined;
|
|
261
|
+
const newestSelected = Math.max(
|
|
262
|
+
-1,
|
|
263
|
+
...selection.activationRefs.map((ref) => entries.findIndex((entry) => entry.turnId === ref)),
|
|
264
|
+
);
|
|
265
|
+
if (
|
|
266
|
+
selection.activationRefs.length > 0 &&
|
|
267
|
+
entries
|
|
268
|
+
.slice(newestSelected + 1)
|
|
269
|
+
.some((entry) => entry.kind === "skillActivation" && entry.activation.runId === undefined)
|
|
270
|
+
)
|
|
271
|
+
return undefined;
|
|
272
|
+
const skills: SkillContextCheckpoint["skills"] = [];
|
|
273
|
+
for (const ref of selection.activationRefs) {
|
|
274
|
+
const matches = entries.filter((entry) => entry.turnId === ref);
|
|
275
|
+
const entry = matches[0];
|
|
276
|
+
if (matches.length !== 1 || entry?.kind !== "skillActivation") return undefined;
|
|
277
|
+
const activation = entry.activation;
|
|
278
|
+
if (
|
|
279
|
+
activation.runId !== undefined ||
|
|
280
|
+
activation.triggeredBy !== "tool" ||
|
|
281
|
+
!activation.turnId ||
|
|
282
|
+
activation.drift === "mismatch"
|
|
283
|
+
)
|
|
284
|
+
return undefined;
|
|
285
|
+
// A later load with the same name supersedes this receipt, even if the later evidence is incomplete.
|
|
286
|
+
if (
|
|
287
|
+
entries
|
|
288
|
+
.slice(entries.indexOf(entry) + 1)
|
|
289
|
+
.some(
|
|
290
|
+
(later) =>
|
|
291
|
+
later.kind === "skillActivation" &&
|
|
292
|
+
later.activation.runId === undefined &&
|
|
293
|
+
later.activation.name === activation.name,
|
|
294
|
+
)
|
|
295
|
+
)
|
|
296
|
+
return undefined;
|
|
297
|
+
const request = entries.find((candidate) => candidate.turnId === activation.turnId);
|
|
298
|
+
if (request?.kind !== "message" || request.role !== "user") return undefined;
|
|
299
|
+
const start = entries.indexOf(request);
|
|
300
|
+
const next = entries.findIndex(
|
|
301
|
+
(candidate, index) => index > start && candidate.kind === "message" && candidate.role === "user",
|
|
302
|
+
);
|
|
303
|
+
const turn = entries.slice(start, next < 0 ? undefined : next);
|
|
304
|
+
if (!turn.includes(entry)) return undefined;
|
|
305
|
+
const calls = turn.filter((candidate) => {
|
|
306
|
+
if (candidate.kind !== "message" || candidate.role !== "tool_call") return false;
|
|
307
|
+
const payload = payloadObject(candidate.payload);
|
|
308
|
+
const args = payloadObject(payload?.args);
|
|
309
|
+
return payload?.name === "context" && args?.scope === "skills" && args.name === activation.name;
|
|
310
|
+
});
|
|
311
|
+
if (calls.length !== 1) return undefined;
|
|
312
|
+
const call = calls[0];
|
|
313
|
+
if (call?.kind !== "message") return undefined;
|
|
314
|
+
const callId = payloadObject(call.payload)?.toolCallId;
|
|
315
|
+
if (typeof callId !== "string" || !callId) return undefined;
|
|
316
|
+
const assistant = turn.find((candidate) => candidate.turnId === call.parentTurnId);
|
|
317
|
+
if (
|
|
318
|
+
assistant?.kind !== "message" ||
|
|
319
|
+
assistant.role !== "assistant" ||
|
|
320
|
+
!contentBlocks(assistant.payload).some(
|
|
321
|
+
(block) =>
|
|
322
|
+
block.type === "toolCall" &&
|
|
323
|
+
block.id === callId &&
|
|
324
|
+
block.name === "context" &&
|
|
325
|
+
JSON.stringify(block.arguments) === JSON.stringify(payloadObject(call.payload)?.args),
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
return undefined;
|
|
329
|
+
const results = entries.filter(
|
|
330
|
+
(candidate) =>
|
|
331
|
+
candidate.kind === "message" &&
|
|
332
|
+
candidate.role === "tool_result" &&
|
|
333
|
+
payloadObject(candidate.payload)?.toolCallId === callId,
|
|
334
|
+
);
|
|
335
|
+
const resultEntry = results[0];
|
|
336
|
+
if (
|
|
337
|
+
results.length !== 1 ||
|
|
338
|
+
resultEntry?.kind !== "message" ||
|
|
339
|
+
!turn.includes(resultEntry) ||
|
|
340
|
+
resultEntry.parentTurnId !== call.turnId ||
|
|
341
|
+
entry.parentTurnId !== request.turnId
|
|
342
|
+
)
|
|
343
|
+
return undefined;
|
|
344
|
+
const payload = payloadObject(resultEntry.payload);
|
|
345
|
+
const result = payloadObject(payload?.result);
|
|
346
|
+
const details = payloadObject(result?.details);
|
|
347
|
+
const observation = payloadObject(details?.observation);
|
|
348
|
+
const resultSummary = payloadObject(payload?.resultSummary);
|
|
349
|
+
const summaryObservation = payloadObject(resultSummary?.observation);
|
|
350
|
+
const sourceInfo = payloadObject(details?.sourceInfo);
|
|
351
|
+
if (
|
|
352
|
+
payload?.toolName !== "context" ||
|
|
353
|
+
payload.isError !== false ||
|
|
354
|
+
payload.outcome !== "ok" ||
|
|
355
|
+
details?.kind !== "ok" ||
|
|
356
|
+
observation?.truncated !== false ||
|
|
357
|
+
details.workingSet !== undefined ||
|
|
358
|
+
details.contextCompaction !== undefined ||
|
|
359
|
+
resultSummary?.truncated !== false ||
|
|
360
|
+
summaryObservation?.truncated === true ||
|
|
361
|
+
details.name !== activation.name ||
|
|
362
|
+
details.path !== activation.filePath ||
|
|
363
|
+
details.hash !== activation.hash ||
|
|
364
|
+
details.source !== activation.source ||
|
|
365
|
+
details.sourceOrigin !== activation.sourceOrigin ||
|
|
366
|
+
sourceInfo?.path !== activation.filePath ||
|
|
367
|
+
sourceInfo.scope !== details.scope ||
|
|
368
|
+
sourceInfo.source !== activation.sourceOrigin ||
|
|
369
|
+
(details.drift !== undefined && details.drift !== "match") ||
|
|
370
|
+
details.drift !== activation.drift ||
|
|
371
|
+
!Array.isArray(result?.content) ||
|
|
372
|
+
!result.content.every((block: unknown) => {
|
|
373
|
+
const obj = payloadObject(block);
|
|
374
|
+
return obj?.type === "text" && typeof obj.text === "string";
|
|
375
|
+
})
|
|
376
|
+
)
|
|
377
|
+
return undefined;
|
|
378
|
+
const content = result.content as Array<{ type: "text"; text: string }>;
|
|
379
|
+
const text = content.map((block) => block.text).join("\n");
|
|
380
|
+
if (
|
|
381
|
+
observation.shownBytes !== Buffer.byteLength(text, "utf8") ||
|
|
382
|
+
observation.totalBytes !== observation.shownBytes ||
|
|
383
|
+
resultSummary?.bytes !== observation.shownBytes
|
|
384
|
+
)
|
|
385
|
+
return undefined;
|
|
386
|
+
const requestPayload = payloadObject(request.payload);
|
|
387
|
+
const operatorText = requestPayload?.operatorText;
|
|
388
|
+
const requestText =
|
|
389
|
+
typeof operatorText === "string" && operatorText.trim().length > 0 ? operatorText : requestPayload?.text;
|
|
390
|
+
if (typeof requestText !== "string") return undefined;
|
|
391
|
+
skills.push({
|
|
392
|
+
activationRef: ref,
|
|
393
|
+
requestRef: request.turnId,
|
|
394
|
+
callRef: call.turnId,
|
|
395
|
+
resultRef: resultEntry.turnId,
|
|
396
|
+
activation: structuredClone(activation),
|
|
397
|
+
requestText,
|
|
398
|
+
content: structuredClone(content),
|
|
399
|
+
contentHash: skillContextContentHash(content),
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
const checkpoint = { version: 1 as const, skills };
|
|
403
|
+
return verifiedSkillContextCheckpoint(checkpoint) ? checkpoint : undefined;
|
|
404
|
+
}
|
|
405
|
+
|
|
194
406
|
function buildPreviousContextPrefix(previousContextText: string): string {
|
|
195
407
|
const trimmed = previousContextText.trim();
|
|
196
408
|
return trimmed.length > 0 ? `<previous-context>\n${trimmed}\n</previous-context>\n\n` : "";
|
|
@@ -320,20 +532,30 @@ function formatFileOperations(fileOps: FileOperations): string {
|
|
|
320
532
|
return sections.length > 0 ? `\n\n${sections.join("\n\n")}` : "";
|
|
321
533
|
}
|
|
322
534
|
|
|
323
|
-
function formatRecallableRefs(
|
|
535
|
+
function formatRecallableRefs(
|
|
536
|
+
entries: ReadonlyArray<SessionEntry>,
|
|
537
|
+
firstKeptEntryIndex: number,
|
|
538
|
+
view: WorkingSetView,
|
|
539
|
+
): string {
|
|
324
540
|
const entryIndexes = new Map<string, number>();
|
|
325
541
|
for (let index = 0; index < entries.length; index += 1) {
|
|
326
542
|
const entry = entries[index];
|
|
327
543
|
if (entry) entryIndexes.set(entry.turnId, index);
|
|
328
544
|
}
|
|
329
|
-
const view = foldWorkingSet(entries);
|
|
330
545
|
const evictedBeforeCut = new Map(
|
|
331
546
|
[...view.evicted].filter(([ref]) => (entryIndexes.get(ref) ?? Number.POSITIVE_INFINITY) < firstKeptEntryIndex),
|
|
332
547
|
);
|
|
333
548
|
const listing = recallableRefListing(entries, { ...view, evicted: evictedBeforeCut });
|
|
334
|
-
if (
|
|
549
|
+
if (
|
|
550
|
+
listing.refs.length === 0 &&
|
|
551
|
+
!entries.slice(0, firstKeptEntryIndex).some((entry) => entry.kind === "message" && entry.role === "tool_result")
|
|
552
|
+
)
|
|
553
|
+
return "";
|
|
335
554
|
const rows = [...listing.refs];
|
|
336
555
|
if (listing.remaining > 0) rows.push(`and ${listing.remaining} more`);
|
|
556
|
+
rows.push(
|
|
557
|
+
'Preview only. Persisted original tool results removed by this summary are also recallable. Discover all active-path results with context(scope="recall", limit=8, offset=0), omitting ref; query filters path/tool/ref terms. Follow nextOffset, then recall the selected ref.',
|
|
558
|
+
);
|
|
337
559
|
return `\n\n<recallable-refs>\n${rows.join("\n")}\n</recallable-refs>`;
|
|
338
560
|
}
|
|
339
561
|
|
|
@@ -411,13 +633,36 @@ async function runSummaryStream(
|
|
|
411
633
|
systemPrompt,
|
|
412
634
|
messages: [buildUserMessage(userText)],
|
|
413
635
|
};
|
|
636
|
+
// Price the complete serialized request, including templates, previous
|
|
637
|
+
// context, custom instructions and message overhead. This is the shared
|
|
638
|
+
// estimate, not provider-exact tokenization; never truncate constraints to
|
|
639
|
+
// make an oversized projected conversation fit.
|
|
640
|
+
const estimatedInput = estimateAgentContextTokens(context);
|
|
641
|
+
const contextWindow = input.model.contextWindow;
|
|
642
|
+
if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
643
|
+
throw new Error("compaction requires a positive finite model context window");
|
|
644
|
+
}
|
|
645
|
+
if (estimatedInput + maxTokens > contextWindow) {
|
|
646
|
+
throw new Error(
|
|
647
|
+
`compaction estimated input ${estimatedInput} tokens plus output ${maxTokens} tokens exceeds model context window ${contextWindow}; use a larger compaction model or reduce the working set`,
|
|
648
|
+
);
|
|
649
|
+
}
|
|
414
650
|
|
|
651
|
+
input.signal?.throwIfAborted();
|
|
415
652
|
const timestamp = new Date().toISOString();
|
|
416
653
|
const started = performance.now();
|
|
417
654
|
let usage: unknown;
|
|
418
655
|
let reported: Record<string, unknown> = {};
|
|
419
656
|
let outcome: CompactionCallObservation["outcome"] = "error";
|
|
420
657
|
try {
|
|
658
|
+
if (input.summarize) {
|
|
659
|
+
const response = await input.summarize({ systemPrompt, userText, maxTokens });
|
|
660
|
+
usage = response.usage;
|
|
661
|
+
reported = retainReportedUsage(reported, usage);
|
|
662
|
+
input.signal?.throwIfAborted();
|
|
663
|
+
outcome = "success";
|
|
664
|
+
return { text: response.text.trim(), usage };
|
|
665
|
+
}
|
|
421
666
|
// Summarization requests thinking off, as its resolver does. Bare stream
|
|
422
667
|
// infers an active level from model.reasoning and would undo that choice.
|
|
423
668
|
const events = streamSimple(
|
|
@@ -434,6 +679,11 @@ async function runSummaryStream(
|
|
|
434
679
|
}
|
|
435
680
|
if (event.type === "done") {
|
|
436
681
|
usage = event.message.usage ?? usage;
|
|
682
|
+
reported = retainReportedUsage(reported, usage);
|
|
683
|
+
input.signal?.throwIfAborted();
|
|
684
|
+
if (event.reason === "length" || event.message.stopReason === "length") {
|
|
685
|
+
throw new Error("compaction summary reached the model output limit; incomplete checkpoint was not saved");
|
|
686
|
+
}
|
|
437
687
|
outcome = "success";
|
|
438
688
|
return { text: textFromAssistant(event.message).trim(), usage };
|
|
439
689
|
}
|
|
@@ -465,6 +715,12 @@ async function runSummaryStream(
|
|
|
465
715
|
export async function compact(input: CompactInput): Promise<CompactResult> {
|
|
466
716
|
const reserveTokens = input.reserveTokens ?? DEFAULT_RESERVE_TOKENS;
|
|
467
717
|
const keepRecentTokens = input.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS;
|
|
718
|
+
// Apply the same ledger decisions as live replay before pricing or
|
|
719
|
+
// serializing any slice, including the prior checkpoint's retained suffix.
|
|
720
|
+
// Projection preserves positions and turn IDs; cuts still address the raw
|
|
721
|
+
// input, which remains untouched and available for exact recall.
|
|
722
|
+
const workingSet = foldWorkingSet(input.entries);
|
|
723
|
+
const entries = projectWorkingSet(input.entries, workingSet);
|
|
468
724
|
// Iterative compaction: when a prior `compactionSummary` exists, the
|
|
469
725
|
// summary is canonical history. Restrict the cut search and the new-history
|
|
470
726
|
// slice to entries strictly after that boundary; the canonical summary and
|
|
@@ -472,29 +728,89 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
|
|
|
472
728
|
// than rediscovering already-compacted raw history. Mirrors pi-coding-agent's
|
|
473
729
|
// `boundaryStart = prevCompactionIndex + 1` and `usageStart = prevCompactionIndex`
|
|
474
730
|
// in compaction.ts:619-628.
|
|
475
|
-
const prevCompactionIndex = findLatestCompactionIndex(
|
|
731
|
+
const prevCompactionIndex = findLatestCompactionIndex(entries);
|
|
476
732
|
const boundaryStart = prevCompactionIndex + 1;
|
|
477
|
-
const
|
|
733
|
+
const selection =
|
|
734
|
+
input.skillContextState === null ? undefined : (input.skillContextState ?? latestSkillContextState(input.entries));
|
|
735
|
+
let skillContext = captureSkillContext(input.entries, selection);
|
|
736
|
+
const priorCheckpoint = entries[prevCompactionIndex];
|
|
737
|
+
// An explicit-off checkpoint carries an empty skill list: nothing was
|
|
738
|
+
// retained, so nothing needs re-verification and later unknown state must
|
|
739
|
+
// not block compaction forever.
|
|
740
|
+
const priorSkillContext =
|
|
741
|
+
priorCheckpoint?.kind === "compactionSummary" &&
|
|
742
|
+
priorCheckpoint.skillContext !== undefined &&
|
|
743
|
+
priorCheckpoint.skillContext.skills.length > 0
|
|
744
|
+
? priorCheckpoint.skillContext
|
|
745
|
+
: undefined;
|
|
746
|
+
// A typed checkpoint is not regenerated from summary prose. Failure to verify
|
|
747
|
+
// its original receipts prevents another destructive pass.
|
|
748
|
+
if (priorSkillContext !== undefined && !skillContext) {
|
|
749
|
+
throw new Error("cannot verify preserved skill context; retaining the existing checkpoint");
|
|
750
|
+
}
|
|
751
|
+
if (priorSkillContext !== undefined) {
|
|
752
|
+
if (!verifiedSkillContextCheckpoint(priorSkillContext)) throw new Error("invalid preserved skill checkpoint");
|
|
753
|
+
for (const previous of priorSkillContext.skills) {
|
|
754
|
+
const current = skillContext?.skills.find((skill) => skill.activationRef === previous.activationRef);
|
|
755
|
+
if (current && JSON.stringify(current) !== JSON.stringify(previous)) {
|
|
756
|
+
throw new Error("preserved skill context no longer matches its captured receipt");
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (skillContext && priorSkillContext !== undefined) {
|
|
761
|
+
skillContext = {
|
|
762
|
+
version: 1,
|
|
763
|
+
skills: skillContext.skills.map((skill) =>
|
|
764
|
+
structuredClone(
|
|
765
|
+
priorSkillContext.skills.find((previous) => previous.activationRef === skill.activationRef) ?? skill,
|
|
766
|
+
),
|
|
767
|
+
),
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
// A legacy checkpoint (no typed field) never adjudicated older activations,
|
|
771
|
+
// so the fallback clamp stays fail-closed across its boundary. A typed
|
|
772
|
+
// checkpoint already retained or explicitly dropped everything before it.
|
|
773
|
+
const legacyPriorCheckpoint =
|
|
774
|
+
priorCheckpoint?.kind === "compactionSummary" && priorCheckpoint.skillContext === undefined;
|
|
775
|
+
const protectedStart = skillContext
|
|
776
|
+
? null
|
|
777
|
+
: findLatestSkillActivationProtectionStart(entries, legacyPriorCheckpoint ? 0 : boundaryStart);
|
|
478
778
|
const usageStart = prevCompactionIndex >= 0 ? prevCompactionIndex : 0;
|
|
479
|
-
const usageEntries =
|
|
779
|
+
const usageEntries = entries.slice(usageStart);
|
|
480
780
|
const lastUsage = getLastAssistantUsage(usageEntries);
|
|
481
781
|
const tokensBefore = calculateContextTokens(usageEntries, lastUsage);
|
|
482
|
-
const rawCut = findCutPoint(
|
|
782
|
+
const rawCut = findCutPoint(entries, keepRecentTokens, { startIndex: boundaryStart });
|
|
483
783
|
const cut =
|
|
484
784
|
protectedStart !== null && rawCut.firstKeptEntryIndex > protectedStart
|
|
485
785
|
? { firstKeptEntryIndex: protectedStart, turnStartIndex: -1, isSplitTurn: false }
|
|
486
786
|
: rawCut;
|
|
487
787
|
const historyEnd = cut.isSplitTurn ? cut.turnStartIndex : cut.firstKeptEntryIndex;
|
|
488
|
-
const pre =
|
|
788
|
+
const pre = entries.slice(boundaryStart, Math.max(boundaryStart, historyEnd));
|
|
489
789
|
const turnPrefix = cut.isSplitTurn
|
|
490
|
-
?
|
|
790
|
+
? entries.slice(Math.max(boundaryStart, cut.turnStartIndex), cut.firstKeptEntryIndex)
|
|
491
791
|
: [];
|
|
492
|
-
const previousContextEntries = priorCompactionContextEntries(
|
|
792
|
+
const previousContextEntries = priorCompactionContextEntries(entries, prevCompactionIndex);
|
|
493
793
|
const previousContextText = serializeConversation(previousContextEntries);
|
|
494
|
-
const fileOps = extractFileOps([
|
|
794
|
+
const fileOps = extractFileOps([
|
|
795
|
+
...priorCompactionContextEntries(input.entries, prevCompactionIndex),
|
|
796
|
+
...input.entries.slice(boundaryStart, cut.firstKeptEntryIndex),
|
|
797
|
+
]);
|
|
495
798
|
const firstKept = input.entries[cut.firstKeptEntryIndex] ?? null;
|
|
496
|
-
|
|
497
|
-
|
|
799
|
+
// The newest complete exchange can begin immediately after the checkpoint.
|
|
800
|
+
// Its earlier retained suffix is still live context, even though it sits
|
|
801
|
+
// before boundaryStart in the append-only ledger. Summarize that suffix
|
|
802
|
+
// with the canonical prior summary instead of declaring nothing to compact.
|
|
803
|
+
// Never use this path to cross a protected cut or to re-summarize a bare
|
|
804
|
+
// checkpoint with no retained work; the caller still enforces request fit.
|
|
805
|
+
const priorSuffix = previousContextEntries.slice(1);
|
|
806
|
+
const summarizePriorSuffix =
|
|
807
|
+
pre.length === 0 &&
|
|
808
|
+
turnPrefix.length === 0 &&
|
|
809
|
+
firstKept !== null &&
|
|
810
|
+
cut.firstKeptEntryIndex >= boundaryStart &&
|
|
811
|
+
priorSuffix.some((entry) => entry.kind === "message" || entry.kind === "bashExecution");
|
|
812
|
+
|
|
813
|
+
if (pre.length === 0 && turnPrefix.length === 0 && !summarizePriorSuffix) {
|
|
498
814
|
return {
|
|
499
815
|
summary: "",
|
|
500
816
|
firstKeptEntryIndex: cut.firstKeptEntryIndex,
|
|
@@ -506,15 +822,25 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
|
|
|
506
822
|
}
|
|
507
823
|
|
|
508
824
|
const systemPrompt = input.systemPrompt ?? COMPACTION_SYSTEM_PROMPT;
|
|
509
|
-
|
|
825
|
+
if (!Number.isFinite(reserveTokens) || reserveTokens <= 0) {
|
|
826
|
+
throw new Error("compaction requires a positive finite reserve token budget");
|
|
827
|
+
}
|
|
828
|
+
if (!Number.isFinite(input.model.maxTokens) || input.model.maxTokens < 1) {
|
|
829
|
+
throw new Error("compaction requires a positive finite model output token limit");
|
|
830
|
+
}
|
|
831
|
+
const maxTokens = Math.min(Math.floor(input.model.maxTokens), Math.max(1024, Math.floor(reserveTokens * 0.8)));
|
|
510
832
|
const summaryParts: string[] = [];
|
|
511
833
|
let usage: CompactionUsage | undefined;
|
|
512
|
-
if (pre.length > 0) {
|
|
513
|
-
const conversationText = serializeConversation(pre);
|
|
514
|
-
const
|
|
834
|
+
if (pre.length > 0 || summarizePriorSuffix) {
|
|
835
|
+
const conversationText = serializeConversation(summarizePriorSuffix ? priorSuffix : pre);
|
|
836
|
+
const previousText = summarizePriorSuffix
|
|
837
|
+
? serializeConversation(previousContextEntries.slice(0, 1))
|
|
838
|
+
: previousContextText;
|
|
839
|
+
const userText = buildUserText(conversationText, input.instructions, previousText);
|
|
515
840
|
const historySummary = await runSummaryStream(input, userText, systemPrompt, maxTokens);
|
|
516
841
|
usage = addCompactionUsage(usage, historySummary.usage);
|
|
517
842
|
if (historySummary.text.length === 0) throw new Error("compaction returned an empty history summary");
|
|
843
|
+
validateHistorySummary(historySummary.text);
|
|
518
844
|
summaryParts.push(historySummary.text);
|
|
519
845
|
}
|
|
520
846
|
if (turnPrefix.length > 0) {
|
|
@@ -526,9 +852,44 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
|
|
|
526
852
|
summaryParts.push(`**Turn Context (split turn):**\n\n${prefixSummary.text}`);
|
|
527
853
|
}
|
|
528
854
|
|
|
855
|
+
// A generated split summary is not a reliable copy of the active request.
|
|
856
|
+
// Keep it in the canonical checkpoint so live replay and resume agree.
|
|
857
|
+
let userContext: PreservedUserContext | undefined =
|
|
858
|
+
priorCheckpoint?.kind === "compactionSummary" ? priorCheckpoint.userContext : undefined;
|
|
859
|
+
// Manual compaction has no live active-turn hint after a turn settles.
|
|
860
|
+
// Preserve the latest operator request if the split removes it as well.
|
|
861
|
+
let activeUserIndex = -1;
|
|
862
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
863
|
+
const entry = entries[index];
|
|
864
|
+
if (
|
|
865
|
+
entry?.kind === "message" &&
|
|
866
|
+
entry.role === "user" &&
|
|
867
|
+
(input.preserveUserTurnId === undefined || entry.turnId === input.preserveUserTurnId)
|
|
868
|
+
) {
|
|
869
|
+
activeUserIndex = index;
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
const activeUser =
|
|
874
|
+
activeUserIndex >= 0 && activeUserIndex < cut.firstKeptEntryIndex ? entries[activeUserIndex] : undefined;
|
|
875
|
+
if (activeUser?.kind === "message" && activeUser.payload && typeof activeUser.payload === "object") {
|
|
876
|
+
const payload = activeUser.payload;
|
|
877
|
+
// Composed text can contain transient reminders. Reassert only the
|
|
878
|
+
// operator's canonical words when present, without normalizing them.
|
|
879
|
+
const operatorText = "operatorText" in payload ? payload.operatorText : undefined;
|
|
880
|
+
const text =
|
|
881
|
+
typeof operatorText === "string" && operatorText.trim().length > 0
|
|
882
|
+
? operatorText
|
|
883
|
+
: "text" in payload && typeof payload.text === "string"
|
|
884
|
+
? payload.text
|
|
885
|
+
: null;
|
|
886
|
+
if (text !== null) userContext = { turnId: activeUser.turnId, text };
|
|
887
|
+
}
|
|
888
|
+
|
|
529
889
|
const summary = `${summaryParts.join("\n\n---\n\n").trim()}${formatFileOperations(fileOps)}${formatRecallableRefs(
|
|
530
890
|
input.entries,
|
|
531
891
|
cut.firstKeptEntryIndex,
|
|
892
|
+
workingSet,
|
|
532
893
|
)}`.trim();
|
|
533
894
|
|
|
534
895
|
return {
|
|
@@ -536,9 +897,11 @@ export async function compact(input: CompactInput): Promise<CompactResult> {
|
|
|
536
897
|
firstKeptEntryIndex: cut.firstKeptEntryIndex,
|
|
537
898
|
firstKeptTurnId: firstKept?.turnId ?? null,
|
|
538
899
|
tokensBefore,
|
|
539
|
-
messagesSummarized: pre.length + turnPrefix.length,
|
|
900
|
+
messagesSummarized: pre.length + turnPrefix.length + (summarizePriorSuffix ? priorSuffix.length : 0),
|
|
540
901
|
isSplitTurn: cut.isSplitTurn,
|
|
541
902
|
...(usage !== undefined ? { usage } : {}),
|
|
903
|
+
...(skillContext !== undefined ? { skillContext } : {}),
|
|
904
|
+
...(userContext !== undefined ? { userContext } : {}),
|
|
542
905
|
};
|
|
543
906
|
}
|
|
544
907
|
|
|
@@ -52,11 +52,11 @@ function findTurnStartIndex(entries: ReadonlyArray<SessionEntry>, entryIndex: nu
|
|
|
52
52
|
return -1;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
/** Entries we can cut at.
|
|
55
|
+
/** Entries we can cut at. Tool rows must stay with their assistant declaration. */
|
|
56
56
|
function isValidCutPoint(entry: SessionEntry): boolean {
|
|
57
57
|
switch (entry.kind) {
|
|
58
58
|
case "message":
|
|
59
|
-
return entry.role !== "tool_result";
|
|
59
|
+
return entry.role !== "tool_result" && entry.role !== "tool_call";
|
|
60
60
|
case "bashExecution":
|
|
61
61
|
case "custom":
|
|
62
62
|
case "skillActivation":
|
|
@@ -88,6 +88,36 @@ function findValidCutPoints(entries: ReadonlyArray<SessionEntry>, startIndex: nu
|
|
|
88
88
|
return cuts;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/** Retain the assistant declaration and its entire tool batch when the tail alone exceeds the budget. */
|
|
92
|
+
function findToolBatchStart(
|
|
93
|
+
entries: ReadonlyArray<SessionEntry>,
|
|
94
|
+
resultIndex: number,
|
|
95
|
+
startIndex: number,
|
|
96
|
+
endIndex: number,
|
|
97
|
+
): number {
|
|
98
|
+
for (let index = resultIndex - 1; index >= startIndex; index--) {
|
|
99
|
+
const entry = entries[index];
|
|
100
|
+
if (entry?.kind !== "message") continue;
|
|
101
|
+
if (entry.role === "user") break;
|
|
102
|
+
if (entry.role !== "assistant") continue;
|
|
103
|
+
const payload = entry.payload as { content?: unknown } | null;
|
|
104
|
+
if (!Array.isArray(payload?.content)) break;
|
|
105
|
+
const callIds = new Set<string>();
|
|
106
|
+
for (const block of payload.content) {
|
|
107
|
+
if (block?.type === "toolCall" && typeof block.id === "string") callIds.add(block.id);
|
|
108
|
+
}
|
|
109
|
+
if (callIds.size === 0) break;
|
|
110
|
+
for (let tail = index + 1; tail < endIndex; tail++) {
|
|
111
|
+
const result = entries[tail];
|
|
112
|
+
if (result?.kind !== "message" || result.role !== "tool_result") continue;
|
|
113
|
+
const id = (result.payload as { toolCallId?: unknown } | null)?.toolCallId;
|
|
114
|
+
if (typeof id !== "string" || !callIds.has(id)) return -1;
|
|
115
|
+
}
|
|
116
|
+
return index;
|
|
117
|
+
}
|
|
118
|
+
return -1;
|
|
119
|
+
}
|
|
120
|
+
|
|
91
121
|
/**
|
|
92
122
|
* Find the cut point that keeps at least `keepRecentTokens` tokens in the
|
|
93
123
|
* retained suffix. Never cuts at a `tool_result`. When walking forward from
|
|
@@ -131,14 +161,21 @@ export function findCutPoint(
|
|
|
131
161
|
break;
|
|
132
162
|
}
|
|
133
163
|
}
|
|
164
|
+
// No newer cut exists inside a final tool-result batch. Snap back to
|
|
165
|
+
// its assistant, not the whole user turn or an individual call row.
|
|
166
|
+
// The suffix may exceed the target; the continuation guard still
|
|
167
|
+
// checks whether summarizing older work actually made the request fit.
|
|
168
|
+
if (cutIndex === -1 && entry.kind === "message" && (entry.role === "tool_result" || entry.role === "tool_call")) {
|
|
169
|
+
cutIndex = findToolBatchStart(entries, i, startIndex, endIndex);
|
|
170
|
+
}
|
|
134
171
|
break;
|
|
135
172
|
}
|
|
136
173
|
}
|
|
137
174
|
|
|
138
175
|
if (cutIndex === -1) {
|
|
139
|
-
// Walker never crossed keepRecentTokens, or
|
|
140
|
-
//
|
|
141
|
-
//
|
|
176
|
+
// Walker never crossed keepRecentTokens, or found neither a newer cut
|
|
177
|
+
// nor a verifiable assistant declaration for the final result batch.
|
|
178
|
+
// Prefer the newest turn start so older turns still feed the
|
|
142
179
|
// summary prompt. Absent any turn start, fall back to the oldest valid
|
|
143
180
|
// cut. That matches the pre-fix behavior, so pre stays empty and the
|
|
144
181
|
// orchestrator reports nothing to compact.
|
|
@@ -62,7 +62,15 @@ function estimateCustom(entry: CustomEntry): number {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function estimateSummary(entry: BranchSummaryEntry | CompactionSummaryEntry): number {
|
|
65
|
-
|
|
65
|
+
let tokens = ceilChars(entry.summary.length);
|
|
66
|
+
if (entry.kind !== "compactionSummary") return tokens;
|
|
67
|
+
if (entry.userContext) tokens += ceilChars(entry.userContext.text.length + 40) + 4;
|
|
68
|
+
for (const skill of entry.skillContext?.skills ?? []) {
|
|
69
|
+
tokens += ceilChars(skill.requestText.length + 40) + 4;
|
|
70
|
+
tokens += ceilChars(JSON.stringify(skill.activation).length + 32) + 4;
|
|
71
|
+
for (const block of skill.content) tokens += ceilChars(block.text.length) + 4;
|
|
72
|
+
}
|
|
73
|
+
return tokens;
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
/**
|