@cleocode/cleo 2026.10.4 → 2026.10.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/README.md +7 -0
- package/dist/cli/{adapter-LVXHFBC4.js → adapter-OUQRSFZL.js} +10 -9
- package/dist/cli/{add-WUAV7LDT.js → add-4SRRJL4U.js} +18 -18
- package/dist/cli/{add-batch-U2DLKAQC.js → add-batch-TSWICA5J.js} +12 -11
- package/dist/cli/admin-L3F6CDYH.js +1428 -0
- package/dist/cli/{admin-I7BQYVZD.js → admin-YMU55YCU.js} +10 -9
- package/dist/cli/{adr-K2THMQBS.js → adr-XESRMFMP.js} +10 -9
- package/dist/cli/{agent-WQ6XY2DW.js → agent-TAFPIYUU.js} +66 -28
- package/dist/cli/{agent-outputs-BJIYLVTU.js → agent-outputs-HVJJIPS4.js} +3 -3
- package/dist/cli/{analyze-PGQZWGOC.js → analyze-YQ22QVGW.js} +10 -9
- package/dist/cli/{archive-5LZPF7C3.js → archive-W5XX6AH7.js} +10 -9
- package/dist/cli/{archive-stats-U6CYC6JM.js → archive-stats-HP2KPAJU.js} +10 -9
- package/dist/cli/attention-7JBDCRZX.js +124 -0
- package/dist/cli/{attention-SOURWCNI.js → attention-ZXZANHKC.js} +13 -12
- package/dist/cli/{audit-FO2Y4LH2.js → audit-ICA2SEFN.js} +2 -2
- package/dist/cli/{auth-ED7TAIXI.js → auth-DXIG5OG7.js} +5 -5
- package/dist/cli/{backfill-32TRAYRD.js → backfill-LBSYBWLR.js} +2 -2
- package/dist/cli/{backup-LEJMZJKL.js → backup-NUGBZ7NA.js} +17 -16
- package/dist/cli/{backup-inspect-6HPLUEI2.js → backup-inspect-PDRXI45A.js} +3 -3
- package/dist/cli/{backup-recover-2BTYBZU2.js → backup-recover-TVKAPERB.js} +3 -3
- package/dist/cli/{blockers-5JULUJTV.js → blockers-ZOPCGHDW.js} +10 -9
- package/dist/cli/{brain-273N3FW4.js → brain-EJOBKL4A.js} +9 -12
- package/dist/cli/{briefing-7H6OLECX.js → briefing-RDQJ6WHS.js} +11 -10
- package/dist/cli/{caamp-MFQVN6VU.js → caamp-Z3XPKEHB.js} +2 -2
- package/dist/cli/{cancel-SCMJTXZB.js → cancel-S7EHLCJN.js} +10 -9
- package/dist/cli/{cant-46XCUP4P.js → cant-CHNN6O57.js} +2 -2
- package/dist/cli/{changeset-32NMBGG2.js → changeset-RYPHPN2B.js} +4 -6
- package/dist/cli/check-C67YAU7W.js +759 -0
- package/dist/cli/{check-RWJLBCI2.js → check-DHMURGHC.js} +30 -13
- package/dist/cli/{checkpoint-37HMMKD7.js → checkpoint-UWDFOGYQ.js} +3 -3
- package/dist/cli/{chunk-NRKWJLMS.js → chunk-22YPFZYB.js} +2 -2
- package/dist/cli/{chunk-I3CRQQAD.js → chunk-2MGFDMDF.js} +84 -37
- package/dist/cli/{chunk-BCEXRFA2.js → chunk-4JYHPP4C.js} +2 -2
- package/dist/cli/{chunk-A2IUEIM5.js → chunk-4PEODTHY.js} +2 -2
- package/dist/cli/{chunk-3ZO3M37V.js → chunk-4RGSNUUP.js} +118 -170
- package/dist/cli/{chunk-AWCQH2W5.js → chunk-4VASFLUW.js} +2 -2
- package/dist/cli/{chunk-BPEVD37G.js → chunk-5PNI276X.js} +2 -2
- package/dist/cli/{chunk-OGV57L4J.js → chunk-6N6WGLXE.js} +6 -2
- package/dist/cli/{chunk-KHB52JNB.js → chunk-75UH3BLS.js} +4 -3
- package/dist/cli/{chunk-5ZFFUFH7.js → chunk-7ACK4EIN.js} +2 -2
- package/dist/cli/{chunk-MNJRLSEQ.js → chunk-7NMKLVMI.js} +2 -2
- package/dist/cli/{chunk-GFGLLDXX.js → chunk-7SINJXB6.js} +2 -2
- package/dist/cli/{chunk-KJDWWQFY.js → chunk-7UARFJYS.js} +3 -3
- package/dist/cli/{chunk-JNZJPIPJ.js → chunk-7ZYPQV4N.js} +3 -3
- package/dist/cli/{chunk-DVTPIZJM.js → chunk-AQCYT3L4.js} +2 -2
- package/dist/cli/{chunk-EGOTK2HA.js → chunk-BQK6XTOH.js} +2 -2
- package/dist/cli/{chunk-DYABOIHB.js → chunk-CAPAGD5E.js} +6 -4
- package/dist/cli/{chunk-ZZTHTMQP.js → chunk-CHGEDCKG.js} +3 -3
- package/dist/cli/{chunk-QPUY2HQZ.js → chunk-COXFJ3PT.js} +2 -2
- package/dist/cli/chunk-D7BAQNV2.js +55 -0
- package/dist/cli/{chunk-OPTEQKBB.js → chunk-EIUXVHNF.js} +3 -3
- package/dist/cli/{chunk-3PGH67MT.js → chunk-EUGB6P5V.js} +4 -6
- package/dist/cli/chunk-EW2CKNNZ.js +304 -0
- package/dist/cli/{chunk-2JIJD2I7.js → chunk-FSKN4DWC.js} +2 -2
- package/dist/cli/{chunk-NSHV2JNM.js → chunk-FVKLULL7.js} +2 -2
- package/dist/cli/{chunk-GH37QXW5.js → chunk-GAGUBU4Z.js} +2 -2
- package/dist/cli/{chunk-37NU2XDP.js → chunk-GKRFH2YG.js} +2 -2
- package/dist/cli/{chunk-ULN4OKQQ.js → chunk-GRU74UE4.js} +21 -10
- package/dist/cli/{chunk-LKNUA3SB.js → chunk-HFLLZE6A.js} +2 -2
- package/dist/cli/{chunk-YGKEECTI.js → chunk-HXRXT3XU.js} +2 -2
- package/dist/cli/{chunk-REUTEW3O.js → chunk-IIOGUY3B.js} +6 -6
- package/dist/cli/chunk-ILWWL462.js +60 -0
- package/dist/cli/{chunk-XRAX6XFP.js → chunk-J5USPJKZ.js} +2 -2
- package/dist/cli/{chunk-S24YI723.js → chunk-KEQS36GD.js} +4 -4
- package/dist/cli/chunk-L7ONYSV6.js +2497 -0
- package/dist/cli/chunk-NEFMQYLE.js +656 -0
- package/dist/cli/{chunk-QFFQSKRC.js → chunk-NU6CQQVB.js} +6 -2
- package/dist/cli/{chunk-5J2VH3BC.js → chunk-PN4WW5VX.js} +3 -3
- package/dist/cli/{chunk-AYA6F4ZT.js → chunk-PSJ33WVO.js} +3 -3
- package/dist/cli/{chunk-FORFDPP5.js → chunk-QJJWWCIC.js} +3 -3
- package/dist/cli/{chunk-ZBISIPCK.js → chunk-QKMBWYAS.js} +16 -1
- package/dist/cli/chunk-QWNKLLLG.js +84 -0
- package/dist/cli/{chunk-7INMKEAD.js → chunk-QWUFFDL3.js} +2 -2
- package/dist/cli/chunk-QY76BRUZ.js +35 -0
- package/dist/cli/chunk-R45KVF5Y.js +117 -0
- package/dist/cli/{chunk-W33Q3FBH.js → chunk-RRKP7HLU.js} +3 -3
- package/dist/cli/{chunk-YUZJI67I.js → chunk-T6GZJYL3.js} +2 -2
- package/dist/cli/{chunk-LWQBJQSE.js → chunk-TLQ37HRE.js} +3 -3
- package/dist/cli/chunk-TPTNEJZJ.js +52 -0
- package/dist/cli/chunk-TYC7G5LF.js +100 -0
- package/dist/cli/{chunk-J3ZFM3UQ.js → chunk-UWCZY52R.js} +25 -13
- package/dist/cli/{chunk-V5GBGOGM.js → chunk-VB3LDPL5.js} +2 -2
- package/dist/cli/chunk-WWCYZYSN.js +56 -0
- package/dist/cli/{chunk-EBRZ76HS.js → chunk-XA5WISNV.js} +4 -3
- package/dist/cli/chunk-XHRZ7OYZ.js +132 -0
- package/dist/cli/{chunk-EOPQFCSR.js → chunk-XLPMIGJJ.js} +6 -6
- package/dist/cli/{chunk-NWTATTEQ.js → chunk-ZMGDZMSJ.js} +2 -2
- package/dist/cli/{claim-KPENYHIQ.js → claim-IGOG2QOC.js} +10 -9
- package/dist/cli/{classify-DRVMCFQU.js → classify-MG4N7GMQ.js} +2 -2
- package/dist/cli/{cli-T3CR7J57.js → cli-A23Q335V.js} +10 -7
- package/dist/cli/{cloud-PPQ4O5TX.js → cloud-SILYJVKO.js} +194 -28
- package/dist/cli/{code-Z5CTMVTD.js → code-H2FQCVMW.js} +2 -2
- package/dist/cli/{complete-UBOCOBRB.js → complete-JLX7NBI4.js} +9 -8
- package/dist/cli/{complexity-BV2AGQRZ.js → complexity-OKV7PVZH.js} +10 -9
- package/dist/cli/{compliance-32PD5Y47.js → compliance-QMGZHJNQ.js} +10 -9
- package/dist/cli/{conduit-VDKCH33F.js → conduit-4H32UYEA.js} +10 -9
- package/dist/cli/conduit-EY54WTZA.js +535 -0
- package/dist/cli/{config-I72JAXK4.js → config-TDYOC7XO.js} +21 -18
- package/dist/cli/{consensus-LFILLSTK.js → consensus-4XCOFPPT.js} +10 -9
- package/dist/cli/{context-XUUVFVTP.js → context-FN4YTGHD.js} +12 -11
- package/dist/cli/{contribution-37NQ4N5R.js → contribution-7RWFBJLC.js} +10 -9
- package/dist/cli/{curator-TFDXU2EX.js → curator-HKZJCVRL.js} +2 -2
- package/dist/cli/{current-C4SN5BWV.js → current-B2NU7V3G.js} +10 -9
- package/dist/cli/{daemon-DV25JQ62.js → daemon-GBD4TVCD.js} +11 -10
- package/dist/cli/{dash-TFU4RLQW.js → dash-IGDANIE5.js} +10 -9
- package/dist/cli/{decide-5VPMNTSI.js → decide-26SXC2V6.js} +5 -8
- package/dist/cli/{decompose-KOYEZNJL.js → decompose-LQ76TEZG.js} +11 -10
- package/dist/cli/{decomposition-7OHUFIQN.js → decomposition-WFRWNUSJ.js} +10 -9
- package/dist/cli/{delete-Q7YCAFY5.js → delete-T5DUQHOX.js} +11 -10
- package/dist/cli/{deps-6UZKLDGJ.js → deps-UTPZJBXL.js} +17 -18
- package/dist/cli/{detect-FERY35UL.js → detect-FFZSMVDT.js} +10 -9
- package/dist/cli/{detect-drift-UL2JTPUK.js → detect-drift-TVCJOFYJ.js} +7 -7
- package/dist/cli/diagnostics-GN5CVD3N.js +93 -0
- package/dist/cli/{diagnostics-TI5QAZXR.js → diagnostics-ZNBKH6GX.js} +10 -9
- package/dist/cli/docs-CLQKEEUK.js +1710 -0
- package/dist/cli/{docs-QI2PRN3T.js → docs-DPPDFTWR.js} +45 -42
- package/dist/cli/{doctor-AX5TICQO.js → doctor-GPENOP4N.js} +79 -62
- package/dist/cli/{doctor-ac-bindings-YPMYHU2G.js → doctor-ac-bindings-S3IOEFP4.js} +3 -3
- package/dist/cli/{doctor-acceptance-drift-PYNFGMKB.js → doctor-acceptance-drift-VNFKPBSQ.js} +3 -3
- package/dist/cli/{doctor-credentials-UZRIADKM.js → doctor-credentials-A5H4JMTF.js} +3 -3
- package/dist/cli/{doctor-db-substrate-Q2TOYM2S.js → doctor-db-substrate-FGCISE4Z.js} +3 -3
- package/dist/cli/{doctor-dep-cycles-GCVYZY6F.js → doctor-dep-cycles-BKKKHHYG.js} +3 -3
- package/dist/cli/{doctor-exodus-RO5SUTC2.js → doctor-exodus-ND2DH2KP.js} +3 -3
- package/dist/cli/{doctor-exodus-residue-EM2AWQXP.js → doctor-exodus-residue-4EMRYMEQ.js} +3 -3
- package/dist/cli/{doctor-fk-check-Q3FOLECE.js → doctor-fk-check-VY3RIQV3.js} +3 -3
- package/dist/cli/{doctor-global-delivery-TNOAQ3NP.js → doctor-global-delivery-JN6IGHUL.js} +3 -3
- package/dist/cli/{doctor-heavy-command-hook-IO3QAQLG.js → doctor-heavy-command-hook-XSN44WXU.js} +3 -3
- package/dist/cli/{doctor-legacy-backups-O2YH5VLS.js → doctor-legacy-backups-QAG5NHYP.js} +3 -3
- package/dist/cli/{doctor-legacy-reaper-VSEJEIFA.js → doctor-legacy-reaper-CIRGFE6R.js} +3 -3
- package/dist/cli/{doctor-malformed-ids-LQ766V5K.js → doctor-malformed-ids-WL7HT4TB.js} +3 -3
- package/dist/cli/{doctor-manifest-rows-6FQDNHLH.js → doctor-manifest-rows-SMQCKJ2T.js} +3 -3
- package/dist/cli/{doctor-memory-guard-J4PSEKB5.js → doctor-memory-guard-LJDOJG76.js} +3 -3
- package/dist/cli/{doctor-migrations-ONOH56YM.js → doctor-migrations-ETQPFNUP.js} +3 -3
- package/dist/cli/{doctor-nexus-residency-FUQAX7PV.js → doctor-nexus-residency-A4JMKBEJ.js} +3 -3
- package/dist/cli/{doctor-project-identity-GUDK3HYX.js → doctor-project-identity-FFQJ5LNX.js} +3 -3
- package/dist/cli/{doctor-projects-7L3BNL4O.js → doctor-projects-MFUTKRHP.js} +3 -3
- package/dist/cli/{doctor-projects-registry-TEAVHFQU.js → doctor-projects-registry-76X6VTGM.js} +3 -3
- package/dist/cli/{doctor-release-readiness-IEGHX6SL.js → doctor-release-readiness-QJCOPFTK.js} +3 -3
- package/dist/cli/{doctor-repair-NBONOSZU.js → doctor-repair-AU76FIKY.js} +3 -3
- package/dist/cli/doctor-row-identity-KW6JYZQE.js +26 -0
- package/dist/cli/{doctor-skill-fixtures-7Y6L34A3.js → doctor-skill-fixtures-G3T7JUHS.js} +3 -3
- package/dist/cli/{doctor-split-brain-TUKIGVHF.js → doctor-split-brain-FUW6L7FS.js} +3 -3
- package/dist/cli/{doctor-superseded-store-BHZY2B2L.js → doctor-superseded-store-DUHGSBLC.js} +3 -3
- package/dist/cli/doctor-sync-journal-SXMUIKF7.js +26 -0
- package/dist/cli/doctor-sync-triggers-6WNJZFRM.js +26 -0
- package/dist/cli/{doctor-tool-locks-REQMIVYK.js → doctor-tool-locks-66LSLUBN.js} +3 -3
- package/dist/cli/{doctor-twin-collapse-222GOSPE.js → doctor-twin-collapse-AYBYBFC4.js} +3 -3
- package/dist/cli/{doctor-worktree-stores-J7TCRVJ3.js → doctor-worktree-stores-C5XEH5OG.js} +3 -3
- package/dist/cli/{done-V3AOO65B.js → done-R64XRZ32.js} +11 -10
- package/dist/cli/entities-3JIHDIOK.js +361 -0
- package/dist/cli/{event-EGNPGE5A.js → event-45KEWV5H.js} +2 -2
- package/dist/cli/{exists-H4SDCBPL.js → exists-BEDZS5RI.js} +3 -3
- package/dist/cli/{exodus-KALO3B3X.js → exodus-DUX62344.js} +3 -3
- package/dist/cli/{export-ROFOCG4M.js → export-C5PQIQ5O.js} +11 -10
- package/dist/cli/{export-tasks-US3WBIEQ.js → export-tasks-CUXDZPJB.js} +11 -10
- package/dist/cli/{federation-SUIB5QWT.js → federation-ESM35EGG.js} +3 -3
- package/dist/cli/{find-YICG4BG6.js → find-5EUZHHQJ.js} +13 -12
- package/dist/cli/focus-6AH4KLRO.js +368 -0
- package/dist/cli/{focus-TKCZPKOM.js → focus-ANKAIRO5.js} +10 -9
- package/dist/cli/{gateway-H4HFDC3E.js → gateway-2GW2KTK3.js} +2 -2
- package/dist/cli/{gc-5R2TUY5T.js → gc-CTOQLUSA.js} +2 -2
- package/dist/cli/{go-PRQFK5YG.js → go-YJPNHHYT.js} +6 -6
- package/dist/cli/{goal-7CZRMLHC.js → goal-4GW4G77D.js} +4 -3
- package/dist/cli/{grade-PY2YRPUS.js → grade-25WSZH4X.js} +10 -9
- package/dist/cli/{graph-XIXMCFKG.js → graph-JUO3TMF3.js} +11 -10
- package/dist/cli/{history-EIXADPAD.js → history-NACNUQTC.js} +10 -9
- package/dist/cli/{import-R73SO444.js → import-7ESGL5SS.js} +10 -9
- package/dist/cli/{import-tasks-O22FZJ4U.js → import-tasks-FLE2RPBR.js} +10 -9
- package/dist/cli/index.js +395 -238
- package/dist/cli/{init-IHEJDQWU.js → init-AN4DZ2XO.js} +5 -5
- package/dist/cli/{inject-LSRVWNCP.js → inject-HQWA5GWY.js} +10 -9
- package/dist/cli/{install-global-4AZUCH6U.js → install-global-YQV4W5OG.js} +2 -2
- package/dist/cli/intelligence-OFFNQGHE.js +238 -0
- package/dist/cli/{intelligence-2OSFOGD2.js → intelligence-QIC4SN4X.js} +10 -9
- package/dist/cli/{issue-IIWEDNFC.js → issue-P5RNMRDG.js} +10 -9
- package/dist/cli/{janitor-GPMC7VOR.js → janitor-ZNCFQ7E3.js} +2 -2
- package/dist/cli/{labels-5NPOIQXN.js → labels-ORBM3T57.js} +10 -9
- package/dist/cli/{lifecycle-4FFS2K2T.js → lifecycle-MHR22TVI.js} +13 -12
- package/dist/cli/{list-47KEUGPQ.js → list-LB6GCYYU.js} +14 -13
- package/dist/cli/llm-H7LZWQKX.js +130 -0
- package/dist/cli/{llm-G5B3I6GD.js → llm-OTJWPMGI.js} +14 -13
- package/dist/cli/{llm-cost-S7RS6BVA.js → llm-cost-MLMXEAR4.js} +3 -3
- package/dist/cli/{llm-stream-24A45NTS.js → llm-stream-AAEUNKRP.js} +3 -3
- package/dist/cli/{log-XF6H2XSD.js → log-W2A5M2NA.js} +10 -9
- package/dist/cli/{login-LBPLGHYG.js → login-SIXFFZSP.js} +6 -4
- package/dist/cli/{logout-SX4JSJIV.js → logout-G3KVLQQM.js} +5 -5
- package/dist/cli/{manifest-NMCW4PIW.js → manifest-G4T6EBSI.js} +10 -9
- package/dist/cli/{map-BU72KMGF.js → map-VU5M72TK.js} +10 -9
- package/dist/cli/{memory-UHYIVGVM.js → memory-2E27G2G5.js} +17 -21
- package/dist/cli/memory-IAEYKXG6.js +1895 -0
- package/dist/cli/{migrate-agents-v2-OO7OILZK.js → migrate-agents-v2-A52QIYNJ.js} +3 -3
- package/dist/cli/{migrate-claude-mem-EDNYUY3K.js → migrate-claude-mem-TPDW3R4Z.js} +17 -12
- package/dist/cli/{next-RZFRG5X7.js → next-SVH4LIDY.js} +10 -9
- package/dist/cli/nexus-FPQV2EAF.js +1059 -0
- package/dist/cli/{nexus-4S4Z5EVU.js → nexus-XSFXN5E6.js} +14 -13
- package/dist/cli/{ops-KR7AWCG3.js → ops-K6LHY5J6.js} +10 -9
- package/dist/cli/orchestrate-CZ2J6W3L.js +1650 -0
- package/dist/cli/{orchestrate-HOYZY3VX.js → orchestrate-HURUCQFT.js} +13 -11
- package/dist/cli/{otel-U7IIRBCT.js → otel-JCNPVJLZ.js} +2 -2
- package/dist/cli/{phase-NYZFHUE5.js → phase-VDFRASSO.js} +10 -9
- package/dist/cli/pipeline-TCZPOEDR.js +697 -0
- package/dist/cli/{pivot-FF2CVUZL.js → pivot-V5MSQZ7L.js} +10 -9
- package/dist/cli/{plan-3SL2NTRV.js → plan-SQUGCKSM.js} +10 -9
- package/dist/cli/{playbook-2FCBV7N3.js → playbook-L47GLDQD.js} +10 -9
- package/dist/cli/playbook-NJVO4R6P.js +33 -0
- package/dist/cli/{project-WDX2TGMC.js → project-YZEC7GYF.js} +6 -5
- package/dist/cli/{promote-YINYFBZY.js → promote-FINF4HVK.js} +10 -9
- package/dist/cli/provenance-3TUWVBFR.js +141 -0
- package/dist/cli/{provenance-C7AYD7WG.js → provenance-YZG33JGM.js} +10 -9
- package/dist/cli/{provider-QLJEDQBR.js → provider-23JVLLG3.js} +10 -9
- package/dist/cli/{reason-JF5BHBM5.js → reason-FHN54O7O.js} +10 -9
- package/dist/cli/{reconcile-NMISHDGX.js → reconcile-MOM5T4AX.js} +11 -10
- package/dist/cli/{refresh-memory-EY5YNICV.js → refresh-memory-3OSTRAVK.js} +2 -2
- package/dist/cli/{relates-R3ZPICAY.js → relates-6FWUFUS2.js} +10 -9
- package/dist/cli/release-G2DPSG5M.js +347 -0
- package/dist/cli/{release-4ZJTMUUT.js → release-URX6JHZ2.js} +10 -9
- package/dist/cli/{remote-QSONJDIK.js → remote-VIULU2T5.js} +3 -3
- package/dist/cli/{renderers-64OR3IWX.js → renderers-TGSW77J4.js} +2 -2
- package/dist/cli/{reorder-J3DOE7ST.js → reorder-UIPN6TQY.js} +10 -9
- package/dist/cli/{reparent-2OUMKEZX.js → reparent-ALOWWUIU.js} +10 -9
- package/dist/cli/{req-TZB7OFKO.js → req-RH2Y3H7A.js} +10 -9
- package/dist/cli/{research-MTD7EX45.js → research-G2Y72HRC.js} +10 -9
- package/dist/cli/{restore-VEUOX7NF.js → restore-VBR5XNML.js} +62 -15
- package/dist/cli/{revert-3YF2IL5G.js → revert-32LDNSGP.js} +2 -2
- package/dist/cli/{roadmap-7OOQLXKG.js → roadmap-LFU3AG7D.js} +10 -9
- package/dist/cli/{run-2U5NZV5Z.js → run-HXRILSR7.js} +40 -6
- package/dist/cli/{safestop-VR4VK56D.js → safestop-Z5UC7NGQ.js} +10 -9
- package/dist/cli/{saga-SEWPIOX2.js → saga-Y6FZS6AM.js} +12 -11
- package/dist/cli/{schema-C52WZ35V.js → schema-OOOKLWUE.js} +5 -5
- package/dist/cli/{self-update-GQIGUDPS.js → self-update-26SOTJMH.js} +3 -3
- package/dist/cli/{selfimprove-3Y5L4ECT.js → selfimprove-4SMOCLUV.js} +10 -9
- package/dist/cli/selfimprove-EB4RQLP4.js +139 -0
- package/dist/cli/sentient-QPETVE53.js +254 -0
- package/dist/cli/{sentient-M4YMAVGV.js → sentient-RGMWR4XJ.js} +2 -2
- package/dist/cli/{sequence-6UBMA4IF.js → sequence-H7DSAJPF.js} +10 -9
- package/dist/cli/{service-5R7SILZ7.js → service-EK5MGB2D.js} +10 -9
- package/dist/cli/service-GLOMZWPQ.js +437 -0
- package/dist/cli/{session-3C6AAC4Y.js → session-HYUXAQGC.js} +12 -11
- package/dist/cli/session-N5ISU56W.js +568 -0
- package/dist/cli/{setup-BTUBW5PU.js → setup-L3YYV53D.js} +4 -4
- package/dist/cli/{show-MXT2V7TF.js → show-364V3KY2.js} +12 -11
- package/dist/cli/{skill-GFUZOU2C.js → skill-F2KR6HW5.js} +2 -2
- package/dist/cli/{skills-EDWLKAF3.js → skills-FS3DCP6E.js} +13 -12
- package/dist/cli/{snapshot-GUWMURCM.js → snapshot-EGXEQ5PR.js} +12 -11
- package/dist/cli/{src-66GAKPXR.js → src-LYLXHXHH.js} +2 -2
- package/dist/cli/{start-QFG56RGN.js → start-6DXOCCKL.js} +10 -9
- package/dist/cli/{stats-GW55P7RR.js → stats-UVUQEGYC.js} +10 -9
- package/dist/cli/{status-46HTKNRR.js → status-XLKYLN42.js} +3 -3
- package/dist/cli/sticky-VSTQ2I2O.js +264 -0
- package/dist/cli/{sticky-2DUZOUGI.js → sticky-XZXZDCFW.js} +12 -11
- package/dist/cli/{stop-J2QEUKHX.js → stop-VNOAFWNB.js} +10 -9
- package/dist/cli/{sync-GJP2QYT5.js → sync-YYPARW3A.js} +11 -10
- package/dist/cli/tasks-C24KHTFF.js +1118 -0
- package/dist/cli/{tasks-BNXTM7PB.js → tasks-LBJC7CZV.js} +10 -9
- package/dist/cli/{telemetry-55Z2XJWL.js → telemetry-CU7W5WAY.js} +2 -2
- package/dist/cli/{templates-7O77TKPV.js → templates-G42JBUY4.js} +9 -11
- package/dist/cli/{testing-37YTBNKP.js → testing-HSRITHEY.js} +10 -9
- package/dist/cli/{token-UAVJMNUI.js → token-J74E7TSU.js} +10 -9
- package/dist/cli/tools-BI74W7VE.js +652 -0
- package/dist/cli/{transcript-LORQTV5Z.js → transcript-RGK7RSGQ.js} +2 -2
- package/dist/cli/{update-NVCYV2FT.js → update-2KQWA27S.js} +19 -17
- package/dist/cli/update-check-entry.js +124 -0
- package/dist/cli/update-notice-6SQ6WPQG.js +68 -0
- package/dist/cli/upgrade-E2MJAPC7.js +136 -0
- package/dist/cli/{upgrade-OXJXOGEF.js → upgrade-XRSQ4RWH.js} +5 -5
- package/dist/cli/{verify-LYLDHPT2.js → verify-WASRGDBA.js} +10 -9
- package/dist/cli/{web-QP2RP266.js → web-NJ3P67EU.js} +4 -4
- package/dist/cli/{workgraph-FXBSZDQE.js → workgraph-OHJ2VKJD.js} +6 -6
- package/dist/cli/{worktree-6RXAJIST.js → worktree-FVQLORFY.js} +10 -9
- package/dist/cli/worktree-ZJ6JTQNG.js +287 -0
- package/package.json +13 -13
- package/studio-dist/client/_app/immutable/chunks/{Btgeq_wq.js → AH7dIemv.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{DgEKqO6r.js → BDgH40i3.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/BXDCSJ7U.js +1 -0
- package/studio-dist/client/_app/immutable/chunks/{CgBjxmu6.js → Gg4iYl59.js} +1 -1
- package/studio-dist/client/_app/immutable/entry/{app.a02HWaRB.js → app.DUDNK-37.js} +2 -2
- package/studio-dist/client/_app/immutable/entry/start.DNmZ0pA4.js +1 -0
- package/studio-dist/client/_app/immutable/nodes/{0.nTXyRfc-.js → 0.DWqP3ail.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{1.4zrWeHtl.js → 1.CZGVUP5B.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{15.D9mk4JyY.js → 15.DGaflZRS.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{16._-wt-sQf.js → 16.uYlarGXl.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{17.CUu6LQDj.js → 17.CZMR0E47.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{18.Dz4QRTkX.js → 18.CBC-AKH_.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{20.CJ2_EB0U.js → 20.BGi43MvQ.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{24.Igj2FS7k.js → 24.Dv8ftCyR.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/25.DQPVlTDQ.js +39 -0
- package/studio-dist/client/_app/immutable/nodes/{26.6iPyjT44.js → 26.Cl800304.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{3.AA5GwNgP.js → 3.D_fQKj9f.js} +1 -1
- package/studio-dist/client/_app/version.json +1 -1
- package/studio-dist/server/chunks/{0-DGmsoBYm.js → 0-BpOagOst.js} +3 -3
- package/studio-dist/server/chunks/1-D0oRGR-C.js +9 -0
- package/studio-dist/server/chunks/{15-Bg6YTndh.js → 15-BcjHz7Tv.js} +3 -3
- package/studio-dist/server/chunks/{16-BObLwgyD.js → 16-CXm8TUk7.js} +3 -3
- package/studio-dist/server/chunks/{17-BNXGyAHX.js → 17-mSgUK-cp.js} +3 -3
- package/studio-dist/server/chunks/{18-UqQFRIID.js → 18-BtfnIw1d.js} +3 -3
- package/studio-dist/server/chunks/{20-CMn8a_yP.js → 20-By1e4QDS.js} +3 -3
- package/studio-dist/server/chunks/{24-BuOTDzib.js → 24-0i2YLVxG.js} +3 -3
- package/studio-dist/server/chunks/{dist-B8xbIrdB.js → 25-DPsrqbrh.js} +795 -10736
- package/studio-dist/server/chunks/{26-DWGObn2T.js → 26-P0XkOibm.js} +3 -3
- package/studio-dist/server/chunks/{3-CyiffdJZ.js → 3-WudjUK7e.js} +3 -3
- package/studio-dist/server/chunks/{_layout.svelte-DYtClaIk.js → _layout.svelte-D9m81Rle.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-CEATWp_5.js → _page.svelte-2PDLOF83.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-Bip079LT.js → _page.svelte-BjE3jm2K.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-CV3xiD1y.js → _page.svelte-Clc0vmiZ.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-DSSy6LuK.js → _page.svelte-DABdRT3h.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-1h9E6s_f.js → _page.svelte-DG3PjiHj.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-BT1EUadj.js → _page.svelte-Edy9CaE8.js} +20 -7
- package/studio-dist/server/chunks/{_page.svelte-BNNF62Nm.js → _page.svelte-Hrf3-ZR8.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-TF795TAS.js → _page.svelte-VB4O4Nl5.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-Cv_KVJDV.js → _page.svelte-d3jEgjsI.js} +3 -3
- package/studio-dist/server/chunks/{_server.ts-CzrwbhkQ.js → _server.ts-BcRFsyo3.js} +4 -5
- package/studio-dist/server/chunks/{_server.ts-C4w6UdU0.js → _server.ts-CEWpIFrj.js} +6 -5
- package/studio-dist/server/chunks/{_server.ts-BlhRFLY3.js → _server.ts-CLVdVIF9.js} +2 -2
- package/studio-dist/server/chunks/{_server.ts-Db6mEile.js → _server.ts-D_j7aSy5.js} +6 -5
- package/studio-dist/server/chunks/{_server.ts-DWt8Dziu.js → _server.ts-QEZF8h2q.js} +4 -5
- package/studio-dist/server/chunks/{client-D8f2k-H_.js → client-Kp1dP1od.js} +2 -2
- package/studio-dist/server/chunks/{error.svelte-DbbOwIme.js → error.svelte-WOCioJVX.js} +3 -3
- package/studio-dist/server/chunks/{hooks.server-D2qbf3Zp.js → hooks.server-DH9zkIrJ.js} +3 -1
- package/studio-dist/server/chunks/{http-1ftNGTs5.js → http-DT5kxaWk.js} +5 -4
- package/studio-dist/server/chunks/{internal-CTULuLPB.js → internal-z0vqd5_u.js} +3 -3
- package/studio-dist/server/chunks/operations-registry-DdzmYzqX.js +10584 -0
- package/studio-dist/server/chunks/{stores-CS5XOReX.js → stores-s2kaL315.js} +2 -2
- package/studio-dist/server/index.js +1 -1
- package/studio-dist/server/manifest.js +17 -17
- package/dist/cli/chunk-3IOQVUO7.js +0 -17308
- package/dist/cli/chunk-OAPN46TC.js +0 -89
- package/studio-dist/client/_app/immutable/chunks/t81h7afa.js +0 -1
- package/studio-dist/client/_app/immutable/entry/start.BreMSngo.js +0 -1
- package/studio-dist/client/_app/immutable/nodes/25.BnATjVGN.js +0 -39
- package/studio-dist/server/chunks/1-8PfxPvlK.js +0 -9
- package/studio-dist/server/chunks/25-CIMSmjVx.js +0 -366
|
@@ -0,0 +1,2497 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const _installed = Symbol.for('cleocode.cli.sqliteWarningFilter');
|
|
3
|
+
if (globalThis[_installed]) return;
|
|
4
|
+
globalThis[_installed] = true;
|
|
5
|
+
const _origEmitWarning = process.emitWarning;
|
|
6
|
+
process.emitWarning = function(warning, type, code, ctor) {
|
|
7
|
+
if (typeof warning === 'object' && warning.name === 'ExperimentalWarning' && typeof warning.message === 'string' && /SQLite is an experimental feature/i.test(warning.message)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (typeof warning === 'string' && /SQLite is an experimental feature/i.test(warning)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
return _origEmitWarning.call(process, warning, type, code, ctor);
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
import {
|
|
17
|
+
CLEO_DIR_NAME,
|
|
18
|
+
CONFIG_JSON
|
|
19
|
+
} from "./chunk-6N6WGLXE.js";
|
|
20
|
+
import {
|
|
21
|
+
resolve
|
|
22
|
+
} from "./chunk-4VASFLUW.js";
|
|
23
|
+
import {
|
|
24
|
+
getIdempotencyKeyContext,
|
|
25
|
+
getProjectionOptOut,
|
|
26
|
+
isDescribeMode,
|
|
27
|
+
settleThenExit
|
|
28
|
+
} from "./chunk-QKMBWYAS.js";
|
|
29
|
+
import {
|
|
30
|
+
cliError,
|
|
31
|
+
cliOutput,
|
|
32
|
+
loadEsmSync
|
|
33
|
+
} from "./chunk-4RGSNUUP.js";
|
|
34
|
+
import {
|
|
35
|
+
getFieldContext,
|
|
36
|
+
getFormatContext
|
|
37
|
+
} from "./chunk-6JSJNYH2.js";
|
|
38
|
+
import {
|
|
39
|
+
getBoundSession
|
|
40
|
+
} from "./chunk-D7BAQNV2.js";
|
|
41
|
+
import {
|
|
42
|
+
createLazyDomainHandlers
|
|
43
|
+
} from "./chunk-TYC7G5LF.js";
|
|
44
|
+
|
|
45
|
+
// packages/cleo/src/dispatch/adapters/cli.ts
|
|
46
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
47
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
48
|
+
import { createRequire } from "node:module";
|
|
49
|
+
import { dirname, join as join2 } from "node:path";
|
|
50
|
+
import { fileURLToPath } from "node:url";
|
|
51
|
+
import { hooks } from "@cleocode/core/hooks/registry";
|
|
52
|
+
import { getProjectRoot } from "@cleocode/core/project-scope";
|
|
53
|
+
import { trackBackgroundOp } from "@cleocode/core/store/background-ops";
|
|
54
|
+
|
|
55
|
+
// packages/animations/src/animate-context.ts
|
|
56
|
+
function createAnimateContext(input) {
|
|
57
|
+
const format = input.flagResolution.format;
|
|
58
|
+
const quiet = input.flagResolution.quiet;
|
|
59
|
+
const isTTY = input.isTTY ?? Boolean(process.stdout.isTTY);
|
|
60
|
+
const noColor = input.noColor ?? process.env.NO_COLOR != null;
|
|
61
|
+
const inputs = { format, quiet, isTTY, noColor };
|
|
62
|
+
if (format !== "human") {
|
|
63
|
+
return { enabled: false, reason: "format-json", inputs };
|
|
64
|
+
}
|
|
65
|
+
if (quiet) {
|
|
66
|
+
return { enabled: false, reason: "quiet", inputs };
|
|
67
|
+
}
|
|
68
|
+
if (!isTTY) {
|
|
69
|
+
return { enabled: false, reason: "no-tty", inputs };
|
|
70
|
+
}
|
|
71
|
+
if (noColor) {
|
|
72
|
+
return { enabled: false, reason: "no-color", inputs };
|
|
73
|
+
}
|
|
74
|
+
return { enabled: true, reason: "enabled", inputs };
|
|
75
|
+
}
|
|
76
|
+
var SILENT_CONTEXT = Object.freeze({
|
|
77
|
+
enabled: false,
|
|
78
|
+
reason: "format-json",
|
|
79
|
+
inputs: Object.freeze({
|
|
80
|
+
format: "json",
|
|
81
|
+
quiet: false,
|
|
82
|
+
isTTY: false,
|
|
83
|
+
noColor: false
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// packages/animations/src/braille.ts
|
|
88
|
+
var BRAILLE_DOT_MAP = [
|
|
89
|
+
[1, 8],
|
|
90
|
+
// row 0
|
|
91
|
+
[2, 16],
|
|
92
|
+
// row 1
|
|
93
|
+
[4, 32],
|
|
94
|
+
// row 2
|
|
95
|
+
[64, 128]
|
|
96
|
+
// row 3
|
|
97
|
+
];
|
|
98
|
+
function gridToBraille(grid) {
|
|
99
|
+
const rows = grid.length;
|
|
100
|
+
const cols = grid[0] ? grid[0].length : 0;
|
|
101
|
+
const charCount = Math.ceil(cols / 2);
|
|
102
|
+
let result = "";
|
|
103
|
+
for (let c = 0; c < charCount; c++) {
|
|
104
|
+
let code = 10240;
|
|
105
|
+
for (let r = 0; r < 4 && r < rows; r++) {
|
|
106
|
+
for (let d = 0; d < 2; d++) {
|
|
107
|
+
const col = c * 2 + d;
|
|
108
|
+
if (col < cols && grid[r] && grid[r][col]) {
|
|
109
|
+
code |= BRAILLE_DOT_MAP[r][d];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
result += String.fromCodePoint(code);
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
function makeGrid(rows, cols) {
|
|
118
|
+
if (rows <= 0 || cols <= 0) return [];
|
|
119
|
+
return Array.from({ length: rows }, () => Array(cols).fill(false));
|
|
120
|
+
}
|
|
121
|
+
function genScan() {
|
|
122
|
+
const W = 8, H = 4, frames = [];
|
|
123
|
+
for (let pos = -1; pos < W + 1; pos++) {
|
|
124
|
+
const g = makeGrid(H, W);
|
|
125
|
+
for (let r = 0; r < H; r++) {
|
|
126
|
+
for (let c = 0; c < W; c++) {
|
|
127
|
+
if (c === pos || c === pos - 1) g[r][c] = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
frames.push(gridToBraille(g));
|
|
131
|
+
}
|
|
132
|
+
return frames;
|
|
133
|
+
}
|
|
134
|
+
function genRain() {
|
|
135
|
+
const W = 8, H = 4, totalFrames = 12, frames = [];
|
|
136
|
+
const offsets = [0, 3, 1, 5, 2, 7, 4, 6];
|
|
137
|
+
for (let f = 0; f < totalFrames; f++) {
|
|
138
|
+
const g = makeGrid(H, W);
|
|
139
|
+
for (let c = 0; c < W; c++) {
|
|
140
|
+
const row = (f + offsets[c]) % (H + 2);
|
|
141
|
+
if (row < H) g[row][c] = true;
|
|
142
|
+
}
|
|
143
|
+
frames.push(gridToBraille(g));
|
|
144
|
+
}
|
|
145
|
+
return frames;
|
|
146
|
+
}
|
|
147
|
+
function genScanLine() {
|
|
148
|
+
const W = 6, H = 4, frames = [];
|
|
149
|
+
const positions = [0, 1, 2, 3, 2, 1];
|
|
150
|
+
for (const row of positions) {
|
|
151
|
+
const g = makeGrid(H, W);
|
|
152
|
+
for (let c = 0; c < W; c++) {
|
|
153
|
+
g[row][c] = true;
|
|
154
|
+
if (row > 0) g[row - 1][c] = c % 2 === 0;
|
|
155
|
+
}
|
|
156
|
+
frames.push(gridToBraille(g));
|
|
157
|
+
}
|
|
158
|
+
return frames;
|
|
159
|
+
}
|
|
160
|
+
function genPulse() {
|
|
161
|
+
const W = 6, H = 4, frames = [];
|
|
162
|
+
const cx = W / 2 - 0.5, cy = H / 2 - 0.5;
|
|
163
|
+
const radii = [0.5, 1.2, 2, 3, 3.5];
|
|
164
|
+
for (const r of radii) {
|
|
165
|
+
const g = makeGrid(H, W);
|
|
166
|
+
for (let row = 0; row < H; row++) {
|
|
167
|
+
for (let col = 0; col < W; col++) {
|
|
168
|
+
const dist = Math.sqrt((col - cx) ** 2 + (row - cy) ** 2);
|
|
169
|
+
if (Math.abs(dist - r) < 0.9) g[row][col] = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
frames.push(gridToBraille(g));
|
|
173
|
+
}
|
|
174
|
+
return frames;
|
|
175
|
+
}
|
|
176
|
+
function genSnake() {
|
|
177
|
+
const W = 4, H = 4;
|
|
178
|
+
const path = [];
|
|
179
|
+
for (let r = 0; r < H; r++) {
|
|
180
|
+
if (r % 2 === 0) {
|
|
181
|
+
for (let c = 0; c < W; c++) path.push([r, c]);
|
|
182
|
+
} else {
|
|
183
|
+
for (let c = W - 1; c >= 0; c--) path.push([r, c]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const frames = [];
|
|
187
|
+
for (let i = 0; i < path.length; i++) {
|
|
188
|
+
const g = makeGrid(H, W);
|
|
189
|
+
for (let t = 0; t < 4; t++) {
|
|
190
|
+
const idx = (i - t + path.length) % path.length;
|
|
191
|
+
g[path[idx][0]][path[idx][1]] = true;
|
|
192
|
+
}
|
|
193
|
+
frames.push(gridToBraille(g));
|
|
194
|
+
}
|
|
195
|
+
return frames;
|
|
196
|
+
}
|
|
197
|
+
function genSparkle() {
|
|
198
|
+
const patterns = [
|
|
199
|
+
[
|
|
200
|
+
1,
|
|
201
|
+
0,
|
|
202
|
+
0,
|
|
203
|
+
1,
|
|
204
|
+
0,
|
|
205
|
+
0,
|
|
206
|
+
1,
|
|
207
|
+
0,
|
|
208
|
+
0,
|
|
209
|
+
0,
|
|
210
|
+
1,
|
|
211
|
+
0,
|
|
212
|
+
0,
|
|
213
|
+
1,
|
|
214
|
+
0,
|
|
215
|
+
0,
|
|
216
|
+
0,
|
|
217
|
+
1,
|
|
218
|
+
0,
|
|
219
|
+
0,
|
|
220
|
+
1,
|
|
221
|
+
0,
|
|
222
|
+
0,
|
|
223
|
+
1,
|
|
224
|
+
1,
|
|
225
|
+
0,
|
|
226
|
+
0,
|
|
227
|
+
0,
|
|
228
|
+
0,
|
|
229
|
+
1,
|
|
230
|
+
0,
|
|
231
|
+
0
|
|
232
|
+
],
|
|
233
|
+
[
|
|
234
|
+
0,
|
|
235
|
+
1,
|
|
236
|
+
0,
|
|
237
|
+
0,
|
|
238
|
+
1,
|
|
239
|
+
0,
|
|
240
|
+
0,
|
|
241
|
+
1,
|
|
242
|
+
1,
|
|
243
|
+
0,
|
|
244
|
+
0,
|
|
245
|
+
1,
|
|
246
|
+
0,
|
|
247
|
+
0,
|
|
248
|
+
0,
|
|
249
|
+
1,
|
|
250
|
+
0,
|
|
251
|
+
0,
|
|
252
|
+
0,
|
|
253
|
+
1,
|
|
254
|
+
0,
|
|
255
|
+
1,
|
|
256
|
+
0,
|
|
257
|
+
0,
|
|
258
|
+
0,
|
|
259
|
+
0,
|
|
260
|
+
1,
|
|
261
|
+
0,
|
|
262
|
+
1,
|
|
263
|
+
0,
|
|
264
|
+
1,
|
|
265
|
+
0
|
|
266
|
+
],
|
|
267
|
+
[
|
|
268
|
+
0,
|
|
269
|
+
0,
|
|
270
|
+
1,
|
|
271
|
+
0,
|
|
272
|
+
0,
|
|
273
|
+
1,
|
|
274
|
+
0,
|
|
275
|
+
0,
|
|
276
|
+
0,
|
|
277
|
+
1,
|
|
278
|
+
0,
|
|
279
|
+
0,
|
|
280
|
+
0,
|
|
281
|
+
0,
|
|
282
|
+
1,
|
|
283
|
+
0,
|
|
284
|
+
1,
|
|
285
|
+
0,
|
|
286
|
+
1,
|
|
287
|
+
0,
|
|
288
|
+
0,
|
|
289
|
+
0,
|
|
290
|
+
0,
|
|
291
|
+
1,
|
|
292
|
+
0,
|
|
293
|
+
1,
|
|
294
|
+
0,
|
|
295
|
+
1,
|
|
296
|
+
0,
|
|
297
|
+
0,
|
|
298
|
+
0,
|
|
299
|
+
1
|
|
300
|
+
],
|
|
301
|
+
[
|
|
302
|
+
1,
|
|
303
|
+
0,
|
|
304
|
+
0,
|
|
305
|
+
0,
|
|
306
|
+
0,
|
|
307
|
+
0,
|
|
308
|
+
1,
|
|
309
|
+
1,
|
|
310
|
+
0,
|
|
311
|
+
0,
|
|
312
|
+
1,
|
|
313
|
+
0,
|
|
314
|
+
1,
|
|
315
|
+
0,
|
|
316
|
+
0,
|
|
317
|
+
0,
|
|
318
|
+
0,
|
|
319
|
+
0,
|
|
320
|
+
0,
|
|
321
|
+
0,
|
|
322
|
+
1,
|
|
323
|
+
0,
|
|
324
|
+
1,
|
|
325
|
+
0,
|
|
326
|
+
1,
|
|
327
|
+
0,
|
|
328
|
+
0,
|
|
329
|
+
1,
|
|
330
|
+
0,
|
|
331
|
+
0,
|
|
332
|
+
1,
|
|
333
|
+
0
|
|
334
|
+
],
|
|
335
|
+
[
|
|
336
|
+
0,
|
|
337
|
+
0,
|
|
338
|
+
0,
|
|
339
|
+
1,
|
|
340
|
+
1,
|
|
341
|
+
0,
|
|
342
|
+
0,
|
|
343
|
+
0,
|
|
344
|
+
0,
|
|
345
|
+
1,
|
|
346
|
+
0,
|
|
347
|
+
0,
|
|
348
|
+
0,
|
|
349
|
+
1,
|
|
350
|
+
0,
|
|
351
|
+
1,
|
|
352
|
+
1,
|
|
353
|
+
0,
|
|
354
|
+
0,
|
|
355
|
+
1,
|
|
356
|
+
0,
|
|
357
|
+
0,
|
|
358
|
+
0,
|
|
359
|
+
0,
|
|
360
|
+
0,
|
|
361
|
+
1,
|
|
362
|
+
0,
|
|
363
|
+
0,
|
|
364
|
+
0,
|
|
365
|
+
1,
|
|
366
|
+
0,
|
|
367
|
+
1
|
|
368
|
+
],
|
|
369
|
+
[
|
|
370
|
+
0,
|
|
371
|
+
1,
|
|
372
|
+
1,
|
|
373
|
+
0,
|
|
374
|
+
0,
|
|
375
|
+
0,
|
|
376
|
+
0,
|
|
377
|
+
1,
|
|
378
|
+
0,
|
|
379
|
+
0,
|
|
380
|
+
0,
|
|
381
|
+
1,
|
|
382
|
+
0,
|
|
383
|
+
0,
|
|
384
|
+
1,
|
|
385
|
+
0,
|
|
386
|
+
0,
|
|
387
|
+
1,
|
|
388
|
+
0,
|
|
389
|
+
0,
|
|
390
|
+
0,
|
|
391
|
+
1,
|
|
392
|
+
0,
|
|
393
|
+
0,
|
|
394
|
+
0,
|
|
395
|
+
0,
|
|
396
|
+
1,
|
|
397
|
+
0,
|
|
398
|
+
1,
|
|
399
|
+
0,
|
|
400
|
+
0,
|
|
401
|
+
0
|
|
402
|
+
]
|
|
403
|
+
];
|
|
404
|
+
const W = 8, H = 4, frames = [];
|
|
405
|
+
for (const pat of patterns) {
|
|
406
|
+
const g = makeGrid(H, W);
|
|
407
|
+
for (let r = 0; r < H; r++) {
|
|
408
|
+
for (let c = 0; c < W; c++) {
|
|
409
|
+
g[r][c] = !!pat[r * W + c];
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
frames.push(gridToBraille(g));
|
|
413
|
+
}
|
|
414
|
+
return frames;
|
|
415
|
+
}
|
|
416
|
+
function genCascade() {
|
|
417
|
+
const W = 8, H = 4, frames = [];
|
|
418
|
+
for (let offset = -2; offset < W + H; offset++) {
|
|
419
|
+
const g = makeGrid(H, W);
|
|
420
|
+
for (let r = 0; r < H; r++) {
|
|
421
|
+
for (let c = 0; c < W; c++) {
|
|
422
|
+
const diag = c + r;
|
|
423
|
+
if (diag === offset || diag === offset - 1) g[r][c] = true;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
frames.push(gridToBraille(g));
|
|
427
|
+
}
|
|
428
|
+
return frames;
|
|
429
|
+
}
|
|
430
|
+
function genColumns() {
|
|
431
|
+
const W = 6, H = 4, frames = [];
|
|
432
|
+
for (let col = 0; col < W; col++) {
|
|
433
|
+
for (let fillTo = H - 1; fillTo >= 0; fillTo--) {
|
|
434
|
+
const g = makeGrid(H, W);
|
|
435
|
+
for (let pc = 0; pc < col; pc++) {
|
|
436
|
+
for (let r = 0; r < H; r++) g[r][pc] = true;
|
|
437
|
+
}
|
|
438
|
+
for (let r = fillTo; r < H; r++) g[r][col] = true;
|
|
439
|
+
frames.push(gridToBraille(g));
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const full = makeGrid(H, W);
|
|
443
|
+
for (let r = 0; r < H; r++) for (let c = 0; c < W; c++) full[r][c] = true;
|
|
444
|
+
frames.push(gridToBraille(full));
|
|
445
|
+
frames.push(gridToBraille(makeGrid(H, W)));
|
|
446
|
+
return frames;
|
|
447
|
+
}
|
|
448
|
+
function genOrbit() {
|
|
449
|
+
const W = 2, H = 4;
|
|
450
|
+
const path = [
|
|
451
|
+
[0, 0],
|
|
452
|
+
[0, 1],
|
|
453
|
+
[1, 1],
|
|
454
|
+
[2, 1],
|
|
455
|
+
[3, 1],
|
|
456
|
+
[3, 0],
|
|
457
|
+
[2, 0],
|
|
458
|
+
[1, 0]
|
|
459
|
+
];
|
|
460
|
+
const frames = [];
|
|
461
|
+
for (let i = 0; i < path.length; i++) {
|
|
462
|
+
const g = makeGrid(H, W);
|
|
463
|
+
g[path[i][0]][path[i][1]] = true;
|
|
464
|
+
const t1 = (i - 1 + path.length) % path.length;
|
|
465
|
+
g[path[t1][0]][path[t1][1]] = true;
|
|
466
|
+
frames.push(gridToBraille(g));
|
|
467
|
+
}
|
|
468
|
+
return frames;
|
|
469
|
+
}
|
|
470
|
+
function genBreathe() {
|
|
471
|
+
const stages = [
|
|
472
|
+
[],
|
|
473
|
+
[[1, 0]],
|
|
474
|
+
[
|
|
475
|
+
[0, 1],
|
|
476
|
+
[2, 0]
|
|
477
|
+
],
|
|
478
|
+
[
|
|
479
|
+
[0, 0],
|
|
480
|
+
[1, 1],
|
|
481
|
+
[3, 0]
|
|
482
|
+
],
|
|
483
|
+
[
|
|
484
|
+
[0, 0],
|
|
485
|
+
[1, 1],
|
|
486
|
+
[2, 0],
|
|
487
|
+
[3, 1]
|
|
488
|
+
],
|
|
489
|
+
[
|
|
490
|
+
[0, 0],
|
|
491
|
+
[0, 1],
|
|
492
|
+
[1, 1],
|
|
493
|
+
[2, 0],
|
|
494
|
+
[3, 1]
|
|
495
|
+
],
|
|
496
|
+
[
|
|
497
|
+
[0, 0],
|
|
498
|
+
[0, 1],
|
|
499
|
+
[1, 0],
|
|
500
|
+
[2, 1],
|
|
501
|
+
[3, 0],
|
|
502
|
+
[3, 1]
|
|
503
|
+
],
|
|
504
|
+
[
|
|
505
|
+
[0, 0],
|
|
506
|
+
[0, 1],
|
|
507
|
+
[1, 0],
|
|
508
|
+
[1, 1],
|
|
509
|
+
[2, 0],
|
|
510
|
+
[3, 0],
|
|
511
|
+
[3, 1]
|
|
512
|
+
],
|
|
513
|
+
[
|
|
514
|
+
[0, 0],
|
|
515
|
+
[0, 1],
|
|
516
|
+
[1, 0],
|
|
517
|
+
[1, 1],
|
|
518
|
+
[2, 0],
|
|
519
|
+
[2, 1],
|
|
520
|
+
[3, 0],
|
|
521
|
+
[3, 1]
|
|
522
|
+
]
|
|
523
|
+
];
|
|
524
|
+
const frames = [];
|
|
525
|
+
const sequence = [...stages, ...stages.slice().reverse().slice(1)];
|
|
526
|
+
for (const dots of sequence) {
|
|
527
|
+
const g = makeGrid(4, 2);
|
|
528
|
+
for (const [r, c] of dots) g[r][c] = true;
|
|
529
|
+
frames.push(gridToBraille(g));
|
|
530
|
+
}
|
|
531
|
+
return frames;
|
|
532
|
+
}
|
|
533
|
+
function genWaveRows() {
|
|
534
|
+
const W = 8, H = 4, totalFrames = 16, frames = [];
|
|
535
|
+
for (let f = 0; f < totalFrames; f++) {
|
|
536
|
+
const g = makeGrid(H, W);
|
|
537
|
+
for (let c = 0; c < W; c++) {
|
|
538
|
+
const phase = f - c * 0.5;
|
|
539
|
+
const row = Math.round((Math.sin(phase * 0.8) + 1) / 2 * (H - 1));
|
|
540
|
+
g[row][c] = true;
|
|
541
|
+
if (row > 0) g[row - 1][c] = (f + c) % 3 === 0;
|
|
542
|
+
}
|
|
543
|
+
frames.push(gridToBraille(g));
|
|
544
|
+
}
|
|
545
|
+
return frames;
|
|
546
|
+
}
|
|
547
|
+
function genCheckerboard() {
|
|
548
|
+
const W = 6, H = 4, frames = [];
|
|
549
|
+
for (let phase = 0; phase < 4; phase++) {
|
|
550
|
+
const g = makeGrid(H, W);
|
|
551
|
+
for (let r = 0; r < H; r++) {
|
|
552
|
+
for (let c = 0; c < W; c++) {
|
|
553
|
+
if (phase < 2) {
|
|
554
|
+
g[r][c] = (r + c + phase) % 2 === 0;
|
|
555
|
+
} else {
|
|
556
|
+
g[r][c] = (r + c + phase) % 3 === 0;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
frames.push(gridToBraille(g));
|
|
561
|
+
}
|
|
562
|
+
return frames;
|
|
563
|
+
}
|
|
564
|
+
function genHelix() {
|
|
565
|
+
const W = 8, H = 4, totalFrames = 16, frames = [];
|
|
566
|
+
for (let f = 0; f < totalFrames; f++) {
|
|
567
|
+
const g = makeGrid(H, W);
|
|
568
|
+
for (let c = 0; c < W; c++) {
|
|
569
|
+
const phase = (f + c) * (Math.PI / 4);
|
|
570
|
+
const y1 = Math.round((Math.sin(phase) + 1) / 2 * (H - 1));
|
|
571
|
+
const y2 = Math.round((Math.sin(phase + Math.PI) + 1) / 2 * (H - 1));
|
|
572
|
+
g[y1][c] = true;
|
|
573
|
+
g[y2][c] = true;
|
|
574
|
+
}
|
|
575
|
+
frames.push(gridToBraille(g));
|
|
576
|
+
}
|
|
577
|
+
return frames;
|
|
578
|
+
}
|
|
579
|
+
function genFillSweep() {
|
|
580
|
+
const W = 4, H = 4, frames = [];
|
|
581
|
+
for (let row = H - 1; row >= 0; row--) {
|
|
582
|
+
const g = makeGrid(H, W);
|
|
583
|
+
for (let r = row; r < H; r++) {
|
|
584
|
+
for (let c = 0; c < W; c++) g[r][c] = true;
|
|
585
|
+
}
|
|
586
|
+
frames.push(gridToBraille(g));
|
|
587
|
+
}
|
|
588
|
+
const full = makeGrid(H, W);
|
|
589
|
+
for (let r = 0; r < H; r++) for (let c = 0; c < W; c++) full[r][c] = true;
|
|
590
|
+
frames.push(gridToBraille(full));
|
|
591
|
+
frames.push(gridToBraille(full));
|
|
592
|
+
for (let row = 0; row < H; row++) {
|
|
593
|
+
const g = makeGrid(H, W);
|
|
594
|
+
for (let r = row + 1; r < H; r++) {
|
|
595
|
+
for (let c = 0; c < W; c++) g[r][c] = true;
|
|
596
|
+
}
|
|
597
|
+
frames.push(gridToBraille(g));
|
|
598
|
+
}
|
|
599
|
+
frames.push(gridToBraille(makeGrid(H, W)));
|
|
600
|
+
return frames;
|
|
601
|
+
}
|
|
602
|
+
function genDiagonalSwipe() {
|
|
603
|
+
const W = 4, H = 4, frames = [];
|
|
604
|
+
const maxDiag = W + H - 2;
|
|
605
|
+
for (let d = 0; d <= maxDiag; d++) {
|
|
606
|
+
const g = makeGrid(H, W);
|
|
607
|
+
for (let r = 0; r < H; r++) {
|
|
608
|
+
for (let c = 0; c < W; c++) {
|
|
609
|
+
if (r + c <= d) g[r][c] = true;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
frames.push(gridToBraille(g));
|
|
613
|
+
}
|
|
614
|
+
const full = makeGrid(H, W);
|
|
615
|
+
for (let r = 0; r < H; r++) for (let c = 0; c < W; c++) full[r][c] = true;
|
|
616
|
+
frames.push(gridToBraille(full));
|
|
617
|
+
for (let d = 0; d <= maxDiag; d++) {
|
|
618
|
+
const g = makeGrid(H, W);
|
|
619
|
+
for (let r = 0; r < H; r++) {
|
|
620
|
+
for (let c = 0; c < W; c++) {
|
|
621
|
+
if (r + c > d) g[r][c] = true;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
frames.push(gridToBraille(g));
|
|
625
|
+
}
|
|
626
|
+
frames.push(gridToBraille(makeGrid(H, W)));
|
|
627
|
+
return frames;
|
|
628
|
+
}
|
|
629
|
+
var spinners = {
|
|
630
|
+
// === Classic braille single-char ===
|
|
631
|
+
braille: {
|
|
632
|
+
frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
|
|
633
|
+
interval: 80
|
|
634
|
+
},
|
|
635
|
+
braillewave: {
|
|
636
|
+
frames: ["\u2801\u2802\u2804\u2840", "\u2802\u2804\u2840\u2880", "\u2804\u2840\u2880\u2820", "\u2840\u2880\u2820\u2810", "\u2880\u2820\u2810\u2808", "\u2820\u2810\u2808\u2801", "\u2810\u2808\u2801\u2802", "\u2808\u2801\u2802\u2804"],
|
|
637
|
+
interval: 100
|
|
638
|
+
},
|
|
639
|
+
dna: {
|
|
640
|
+
frames: [
|
|
641
|
+
"\u280B\u2809\u2819\u281A",
|
|
642
|
+
"\u2809\u2819\u281A\u2812",
|
|
643
|
+
"\u2819\u281A\u2812\u2802",
|
|
644
|
+
"\u281A\u2812\u2802\u2802",
|
|
645
|
+
"\u2812\u2802\u2802\u2812",
|
|
646
|
+
"\u2802\u2802\u2812\u2832",
|
|
647
|
+
"\u2802\u2812\u2832\u2834",
|
|
648
|
+
"\u2812\u2832\u2834\u2824",
|
|
649
|
+
"\u2832\u2834\u2824\u2804",
|
|
650
|
+
"\u2834\u2824\u2804\u280B",
|
|
651
|
+
"\u2824\u2804\u280B\u2809",
|
|
652
|
+
"\u2804\u280B\u2809\u2819"
|
|
653
|
+
],
|
|
654
|
+
interval: 80
|
|
655
|
+
},
|
|
656
|
+
// === Generated braille grid animations ===
|
|
657
|
+
scan: { frames: genScan(), interval: 70 },
|
|
658
|
+
rain: { frames: genRain(), interval: 100 },
|
|
659
|
+
scanline: { frames: genScanLine(), interval: 120 },
|
|
660
|
+
pulse: { frames: genPulse(), interval: 180 },
|
|
661
|
+
snake: { frames: genSnake(), interval: 80 },
|
|
662
|
+
sparkle: { frames: genSparkle(), interval: 150 },
|
|
663
|
+
cascade: { frames: genCascade(), interval: 60 },
|
|
664
|
+
columns: { frames: genColumns(), interval: 60 },
|
|
665
|
+
orbit: { frames: genOrbit(), interval: 100 },
|
|
666
|
+
breathe: { frames: genBreathe(), interval: 100 },
|
|
667
|
+
waverows: { frames: genWaveRows(), interval: 90 },
|
|
668
|
+
checkerboard: { frames: genCheckerboard(), interval: 250 },
|
|
669
|
+
helix: { frames: genHelix(), interval: 80 },
|
|
670
|
+
fillsweep: { frames: genFillSweep(), interval: 100 },
|
|
671
|
+
diagswipe: { frames: genDiagonalSwipe(), interval: 60 }
|
|
672
|
+
};
|
|
673
|
+
var CANON_TO_GENERIC = {
|
|
674
|
+
looming: "helix",
|
|
675
|
+
weaving: "braillewave",
|
|
676
|
+
heartbeat: "breathe",
|
|
677
|
+
awakening: "pulse",
|
|
678
|
+
sweeping: "scan",
|
|
679
|
+
watching: "orbit",
|
|
680
|
+
cascade: "cascade",
|
|
681
|
+
tapestry: "waverows",
|
|
682
|
+
refinery: "columns"
|
|
683
|
+
};
|
|
684
|
+
var canonSpinners = {
|
|
685
|
+
looming: spinners[CANON_TO_GENERIC.looming],
|
|
686
|
+
weaving: spinners[CANON_TO_GENERIC.weaving],
|
|
687
|
+
heartbeat: spinners[CANON_TO_GENERIC.heartbeat],
|
|
688
|
+
awakening: spinners[CANON_TO_GENERIC.awakening],
|
|
689
|
+
sweeping: spinners[CANON_TO_GENERIC.sweeping],
|
|
690
|
+
watching: spinners[CANON_TO_GENERIC.watching],
|
|
691
|
+
cascade: spinners[CANON_TO_GENERIC.cascade],
|
|
692
|
+
tapestry: spinners[CANON_TO_GENERIC.tapestry],
|
|
693
|
+
refinery: spinners[CANON_TO_GENERIC.refinery]
|
|
694
|
+
};
|
|
695
|
+
function resolveSpinner(name) {
|
|
696
|
+
if (name in spinners) {
|
|
697
|
+
return spinners[name];
|
|
698
|
+
}
|
|
699
|
+
if (name in canonSpinners) {
|
|
700
|
+
return canonSpinners[name];
|
|
701
|
+
}
|
|
702
|
+
return void 0;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// packages/animations/src/render/legend.ts
|
|
706
|
+
var DEFAULT_MULTILINE_THRESHOLD = 8;
|
|
707
|
+
var SUMMARY_SEPARATOR = " \xB7 ";
|
|
708
|
+
var SUMMARY_SEPARATOR_ASCII = " | ";
|
|
709
|
+
function renderLegend(input) {
|
|
710
|
+
if (!input.ctx.enabled) return "";
|
|
711
|
+
if (input.items.length === 0) return "";
|
|
712
|
+
const threshold = input.multiLineThreshold ?? DEFAULT_MULTILINE_THRESHOLD;
|
|
713
|
+
const formatted = input.items.map((item) => `${item.icon} ${item.label}`);
|
|
714
|
+
if (input.items.length <= threshold) {
|
|
715
|
+
return formatted.join(" ");
|
|
716
|
+
}
|
|
717
|
+
return formatted.join("\n");
|
|
718
|
+
}
|
|
719
|
+
function renderSummary(input) {
|
|
720
|
+
if (!input.ctx.enabled) return "";
|
|
721
|
+
if (input.counts.length === 0) return "";
|
|
722
|
+
const separator = input.ctx.inputs.noColor ? SUMMARY_SEPARATOR_ASCII : SUMMARY_SEPARATOR;
|
|
723
|
+
return input.counts.map((c) => `${c.n} ${c.label}`).join(separator);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// packages/animations/src/render/tree.ts
|
|
727
|
+
import { ascii, KindIcon, StatusIcon } from "@cleocode/contracts/render/icon.js";
|
|
728
|
+
var DEFAULT_FOLD_AT = 50;
|
|
729
|
+
var CONNECTOR_UNICODE = Object.freeze({
|
|
730
|
+
branch: "\u251C\u2500 ",
|
|
731
|
+
leaf: "\u2514\u2500 ",
|
|
732
|
+
vertical: "\u2502 ",
|
|
733
|
+
blank: " "
|
|
734
|
+
});
|
|
735
|
+
var CONNECTOR_ASCII = Object.freeze({
|
|
736
|
+
branch: "+- ",
|
|
737
|
+
leaf: "+- ",
|
|
738
|
+
vertical: "| ",
|
|
739
|
+
blank: " "
|
|
740
|
+
});
|
|
741
|
+
var KIND_LABEL = {
|
|
742
|
+
saga: "sagas",
|
|
743
|
+
epic: "epics",
|
|
744
|
+
task: "tasks",
|
|
745
|
+
subtask: "subtasks"
|
|
746
|
+
};
|
|
747
|
+
function renderTree(resp, opts) {
|
|
748
|
+
if (!opts.ctx.enabled) return "";
|
|
749
|
+
if (resp.tree.length === 0) return "";
|
|
750
|
+
const useAscii = opts.asciiBoxDrawing ?? opts.ctx.inputs.noColor;
|
|
751
|
+
const connectors = useAscii ? CONNECTOR_ASCII : CONNECTOR_UNICODE;
|
|
752
|
+
const foldAt = opts.foldAt ?? DEFAULT_FOLD_AT;
|
|
753
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
754
|
+
let rootNode;
|
|
755
|
+
for (const node of resp.tree) {
|
|
756
|
+
if (node.parentId === null) {
|
|
757
|
+
if (node.id === resp.root) rootNode = node;
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
const bucket = childrenByParent.get(node.parentId);
|
|
761
|
+
if (bucket) bucket.push(node);
|
|
762
|
+
else childrenByParent.set(node.parentId, [node]);
|
|
763
|
+
}
|
|
764
|
+
if (rootNode === void 0) return "";
|
|
765
|
+
const lines = [];
|
|
766
|
+
lines.push(formatRow(rootNode, "", useAscii));
|
|
767
|
+
emitChildren(rootNode.id, [], childrenByParent, connectors, foldAt, useAscii, lines);
|
|
768
|
+
return lines.join("\n");
|
|
769
|
+
}
|
|
770
|
+
function emitChildren(parentId, ancestorIsLast, childrenByParent, connectors, foldAt, useAscii, out) {
|
|
771
|
+
const children = childrenByParent.get(parentId);
|
|
772
|
+
if (children === void 0 || children.length === 0) return;
|
|
773
|
+
const ancestorPrefix = ancestorIsLast.map((isLast) => isLast ? connectors.blank : connectors.vertical).join("");
|
|
774
|
+
const shouldFold = children.length > foldAt;
|
|
775
|
+
const visibleCount = shouldFold ? foldAt - 1 : children.length;
|
|
776
|
+
const visible = children.slice(0, visibleCount);
|
|
777
|
+
for (let i = 0; i < visible.length; i++) {
|
|
778
|
+
const child = visible[i];
|
|
779
|
+
if (child === void 0) continue;
|
|
780
|
+
const isLastInBatch = !shouldFold && i === children.length - 1;
|
|
781
|
+
const connector = isLastInBatch ? connectors.leaf : connectors.branch;
|
|
782
|
+
out.push(formatRow(child, `${ancestorPrefix}${connector}`, useAscii));
|
|
783
|
+
emitChildren(
|
|
784
|
+
child.id,
|
|
785
|
+
[...ancestorIsLast, isLastInBatch],
|
|
786
|
+
childrenByParent,
|
|
787
|
+
connectors,
|
|
788
|
+
foldAt,
|
|
789
|
+
useAscii,
|
|
790
|
+
out
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
if (shouldFold) {
|
|
794
|
+
const hidden = children.length - visibleCount;
|
|
795
|
+
const sampleKind = children[0]?.kind ?? "task";
|
|
796
|
+
const label = KIND_LABEL[sampleKind];
|
|
797
|
+
out.push(
|
|
798
|
+
`${ancestorPrefix}${connectors.leaf}\u2026 and ${hidden} more ${label} (run cleo tree ${parentId} to expand)`
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function formatRow(node, prefix, useAscii) {
|
|
803
|
+
const kindIcon = resolveKindIcon(node.kind, useAscii);
|
|
804
|
+
const statusIcon = resolveStatusIcon(node.status, useAscii);
|
|
805
|
+
return `${prefix}${kindIcon} ${node.title} ${statusIcon}`.trimEnd();
|
|
806
|
+
}
|
|
807
|
+
function resolveKindIcon(kind, useAscii) {
|
|
808
|
+
const icon = KIND_BY_NODE_KIND[kind];
|
|
809
|
+
return useAscii ? ascii(icon) : icon;
|
|
810
|
+
}
|
|
811
|
+
function resolveStatusIcon(status, useAscii) {
|
|
812
|
+
const icon = STATUS_BY_NODE_STATUS[status];
|
|
813
|
+
return useAscii ? ascii(icon) : icon;
|
|
814
|
+
}
|
|
815
|
+
var KIND_BY_NODE_KIND = {
|
|
816
|
+
saga: KindIcon.SAGA,
|
|
817
|
+
epic: KindIcon.EPIC,
|
|
818
|
+
task: KindIcon.TASK,
|
|
819
|
+
subtask: KindIcon.SUBTASK
|
|
820
|
+
};
|
|
821
|
+
var STATUS_BY_NODE_STATUS = {
|
|
822
|
+
pending: StatusIcon.PENDING,
|
|
823
|
+
in_progress: StatusIcon.ACTIVE,
|
|
824
|
+
done: StatusIcon.DONE,
|
|
825
|
+
blocked: StatusIcon.BLOCKED,
|
|
826
|
+
cancelled: StatusIcon.CANCELLED,
|
|
827
|
+
archived: StatusIcon.ARCHIVED
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// packages/animations/src/spinner-handle.ts
|
|
831
|
+
var HIDE_CURSOR = "\x1B[?25l";
|
|
832
|
+
var SHOW_CURSOR = "\x1B[?25h";
|
|
833
|
+
var CLEAR_LINE = "\r\x1B[2K";
|
|
834
|
+
var NOOP_HANDLE = Object.freeze({
|
|
835
|
+
start() {
|
|
836
|
+
},
|
|
837
|
+
stop() {
|
|
838
|
+
},
|
|
839
|
+
update() {
|
|
840
|
+
},
|
|
841
|
+
enabled: false
|
|
842
|
+
});
|
|
843
|
+
var activeRestores = /* @__PURE__ */ new Set();
|
|
844
|
+
var exitListenersInstalled = false;
|
|
845
|
+
function ensureProcessExitListeners() {
|
|
846
|
+
if (exitListenersInstalled) return;
|
|
847
|
+
exitListenersInstalled = true;
|
|
848
|
+
const restoreAll = () => {
|
|
849
|
+
for (const fn of activeRestores) {
|
|
850
|
+
try {
|
|
851
|
+
fn();
|
|
852
|
+
} catch {
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
activeRestores.clear();
|
|
856
|
+
};
|
|
857
|
+
process.once("exit", restoreAll);
|
|
858
|
+
process.once("SIGINT", () => {
|
|
859
|
+
restoreAll();
|
|
860
|
+
process.exit(130);
|
|
861
|
+
});
|
|
862
|
+
process.once("SIGTERM", () => {
|
|
863
|
+
restoreAll();
|
|
864
|
+
process.exit(143);
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
function createSpinnerHandle(context, name, label, options) {
|
|
868
|
+
if (!context.enabled) return NOOP_HANDLE;
|
|
869
|
+
const spinner = resolveSpinner(name);
|
|
870
|
+
if (!spinner) return NOOP_HANDLE;
|
|
871
|
+
const delayMs = options?.delayMs ?? 150;
|
|
872
|
+
let timer = null;
|
|
873
|
+
let delayTimer = null;
|
|
874
|
+
let frameIndex = 0;
|
|
875
|
+
let currentLabel = label;
|
|
876
|
+
let visible = false;
|
|
877
|
+
let registeredRestore = null;
|
|
878
|
+
function render() {
|
|
879
|
+
const frame = spinner.frames[frameIndex++ % spinner.frames.length];
|
|
880
|
+
process.stdout.write(`${CLEAR_LINE} ${frame} ${currentLabel}`);
|
|
881
|
+
}
|
|
882
|
+
function clear() {
|
|
883
|
+
if (visible) {
|
|
884
|
+
process.stdout.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
|
|
885
|
+
visible = false;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function deregister() {
|
|
889
|
+
if (registeredRestore) {
|
|
890
|
+
activeRestores.delete(registeredRestore);
|
|
891
|
+
registeredRestore = null;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
return {
|
|
895
|
+
enabled: true,
|
|
896
|
+
start() {
|
|
897
|
+
if (timer || delayTimer) return;
|
|
898
|
+
ensureProcessExitListeners();
|
|
899
|
+
registeredRestore = clear;
|
|
900
|
+
activeRestores.add(registeredRestore);
|
|
901
|
+
delayTimer = setTimeout(() => {
|
|
902
|
+
delayTimer = null;
|
|
903
|
+
process.stdout.write(HIDE_CURSOR);
|
|
904
|
+
visible = true;
|
|
905
|
+
render();
|
|
906
|
+
timer = setInterval(render, spinner.interval);
|
|
907
|
+
}, delayMs);
|
|
908
|
+
},
|
|
909
|
+
stop(finalLine) {
|
|
910
|
+
if (delayTimer) {
|
|
911
|
+
clearTimeout(delayTimer);
|
|
912
|
+
delayTimer = null;
|
|
913
|
+
}
|
|
914
|
+
if (timer) {
|
|
915
|
+
clearInterval(timer);
|
|
916
|
+
timer = null;
|
|
917
|
+
}
|
|
918
|
+
clear();
|
|
919
|
+
deregister();
|
|
920
|
+
if (finalLine !== void 0 && finalLine.length > 0) {
|
|
921
|
+
process.stdout.write(`${finalLine}
|
|
922
|
+
`);
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
update(newLabel) {
|
|
926
|
+
currentLabel = newLabel;
|
|
927
|
+
}
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// packages/cleo/src/cli/animation-bridge.ts
|
|
932
|
+
function deriveSpinnerLabel(domain, operation) {
|
|
933
|
+
const key = `${domain}.${operation}`;
|
|
934
|
+
switch (key) {
|
|
935
|
+
case "tasks.list":
|
|
936
|
+
case "tasks.find":
|
|
937
|
+
case "tasks.search":
|
|
938
|
+
return { label: "Searching tasks\u2026", spinner: "sweeping" };
|
|
939
|
+
case "tasks.show":
|
|
940
|
+
case "tasks.depends":
|
|
941
|
+
return { label: "Loading task\u2026", spinner: "weaving" };
|
|
942
|
+
case "tasks.tree":
|
|
943
|
+
case "tasks.deps.tree":
|
|
944
|
+
case "tasks.deps.validate":
|
|
945
|
+
return { label: "Building dep graph\u2026", spinner: "looming" };
|
|
946
|
+
case "orchestrate.waves":
|
|
947
|
+
case "orchestrate.ready":
|
|
948
|
+
return { label: "Computing waves\u2026", spinner: "tapestry" };
|
|
949
|
+
case "session.briefing.show":
|
|
950
|
+
case "session.status":
|
|
951
|
+
return { label: "Resolving session\u2026", spinner: "awakening" };
|
|
952
|
+
case "memory.find":
|
|
953
|
+
case "brain.find":
|
|
954
|
+
case "brain.digest":
|
|
955
|
+
return { label: "Querying BRAIN\u2026", spinner: "refinery" };
|
|
956
|
+
case "nexus.query":
|
|
957
|
+
case "nexus.context":
|
|
958
|
+
case "nexus.impact":
|
|
959
|
+
return { label: "Walking the graph\u2026", spinner: "looming" };
|
|
960
|
+
default:
|
|
961
|
+
return { label: "Working\u2026", spinner: "weaving" };
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
function createDispatchSpinner(domain, operation) {
|
|
965
|
+
const flagResolution = getFormatContext();
|
|
966
|
+
const animCtx = createAnimateContext({ flagResolution });
|
|
967
|
+
const { label, spinner } = deriveSpinnerLabel(domain, operation);
|
|
968
|
+
return createSpinnerHandle(animCtx, spinner, label);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// packages/cleo/src/dispatch/dispatcher.ts
|
|
972
|
+
import { createGatewayHandler, Dispatcher } from "@cleocode/runtime/gateway/dispatch";
|
|
973
|
+
|
|
974
|
+
// packages/cleo/src/dispatch/middleware/audit.ts
|
|
975
|
+
import { getLogger } from "@cleocode/core/logger";
|
|
976
|
+
import { getProjectInfoSync } from "@cleocode/core/project-info";
|
|
977
|
+
import { resolveSessionIdFromEnv } from "@cleocode/core/sessions/session-id";
|
|
978
|
+
import { resolveBoundSession } from "@cleocode/core/store/session-store";
|
|
979
|
+
|
|
980
|
+
// packages/cleo/src/dispatch/lib/config-loader.ts
|
|
981
|
+
import { existsSync, readFileSync } from "fs";
|
|
982
|
+
import { join } from "path";
|
|
983
|
+
|
|
984
|
+
// packages/cleo/src/dispatch/middleware/rate-limiter.ts
|
|
985
|
+
var DEFAULT_RATE_LIMITING = {
|
|
986
|
+
enabled: true,
|
|
987
|
+
query: { maxRequests: 100, windowMs: 6e4 },
|
|
988
|
+
mutate: { maxRequests: 30, windowMs: 6e4 },
|
|
989
|
+
spawn: { maxRequests: 10, windowMs: 6e4 }
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
// packages/cleo/src/dispatch/lib/defaults.ts
|
|
993
|
+
var DEFAULT_LIFECYCLE_ENFORCEMENT = {
|
|
994
|
+
mode: "strict",
|
|
995
|
+
allowSkip: ["consensus"],
|
|
996
|
+
emergencyBypass: false
|
|
997
|
+
};
|
|
998
|
+
var DEFAULT_PROTOCOL_VALIDATION = {
|
|
999
|
+
strictMode: true,
|
|
1000
|
+
blockOnViolation: true,
|
|
1001
|
+
logViolations: true
|
|
1002
|
+
};
|
|
1003
|
+
var DEFAULT_CONFIG = {
|
|
1004
|
+
cliPath: "cleo",
|
|
1005
|
+
timeout: 3e4,
|
|
1006
|
+
// 30 seconds
|
|
1007
|
+
logLevel: "info",
|
|
1008
|
+
enableMetrics: false,
|
|
1009
|
+
maxRetries: 3,
|
|
1010
|
+
queryCache: true,
|
|
1011
|
+
queryCacheTtl: 3e4,
|
|
1012
|
+
// 30 seconds
|
|
1013
|
+
auditLog: true,
|
|
1014
|
+
strictValidation: true,
|
|
1015
|
+
lifecycleEnforcement: { ...DEFAULT_LIFECYCLE_ENFORCEMENT },
|
|
1016
|
+
protocolValidation: { ...DEFAULT_PROTOCOL_VALIDATION },
|
|
1017
|
+
rateLimiting: { ...DEFAULT_RATE_LIMITING }
|
|
1018
|
+
};
|
|
1019
|
+
var ENV_PREFIX = "CLEO_";
|
|
1020
|
+
var CONFIG_SCHEMA = {
|
|
1021
|
+
cliPath: { type: "string", required: true },
|
|
1022
|
+
timeout: { type: "number", min: 1e3, max: 3e5 },
|
|
1023
|
+
logLevel: { type: "string", enum: ["debug", "info", "warn", "error"] },
|
|
1024
|
+
enableMetrics: { type: "boolean" },
|
|
1025
|
+
maxRetries: { type: "number", min: 0, max: 10 },
|
|
1026
|
+
queryCache: { type: "boolean" },
|
|
1027
|
+
queryCacheTtl: { type: "number", min: 0, max: 6e5 },
|
|
1028
|
+
auditLog: { type: "boolean" },
|
|
1029
|
+
strictValidation: { type: "boolean" }
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
// packages/cleo/src/dispatch/lib/config-loader.ts
|
|
1033
|
+
var ConfigValidationError = class extends Error {
|
|
1034
|
+
constructor(field, value, constraint) {
|
|
1035
|
+
super(`Invalid config field '${field}': ${constraint} (got ${value})`);
|
|
1036
|
+
this.field = field;
|
|
1037
|
+
this.value = value;
|
|
1038
|
+
this.constraint = constraint;
|
|
1039
|
+
this.name = "ConfigValidationError";
|
|
1040
|
+
}
|
|
1041
|
+
field;
|
|
1042
|
+
value;
|
|
1043
|
+
constraint;
|
|
1044
|
+
};
|
|
1045
|
+
function loadFromEnv(key) {
|
|
1046
|
+
const envKey = `${ENV_PREFIX}${key.toUpperCase()}`;
|
|
1047
|
+
return process.env[envKey];
|
|
1048
|
+
}
|
|
1049
|
+
function parseEnvValue(key, value) {
|
|
1050
|
+
const schema = CONFIG_SCHEMA[key];
|
|
1051
|
+
if (schema.type === "boolean") {
|
|
1052
|
+
return value.toLowerCase() === "true" || value === "1";
|
|
1053
|
+
}
|
|
1054
|
+
if (schema.type === "number") {
|
|
1055
|
+
const num = parseInt(value, 10);
|
|
1056
|
+
if (Number.isNaN(num)) {
|
|
1057
|
+
throw new ConfigValidationError(key, value, "must be a number");
|
|
1058
|
+
}
|
|
1059
|
+
return num;
|
|
1060
|
+
}
|
|
1061
|
+
return value;
|
|
1062
|
+
}
|
|
1063
|
+
function loadFromFile(projectRoot) {
|
|
1064
|
+
const root = projectRoot || process.cwd();
|
|
1065
|
+
const configPath = join(root, CLEO_DIR_NAME, CONFIG_JSON);
|
|
1066
|
+
if (!existsSync(configPath)) {
|
|
1067
|
+
return {};
|
|
1068
|
+
}
|
|
1069
|
+
try {
|
|
1070
|
+
const content = readFileSync(configPath, "utf-8");
|
|
1071
|
+
const config = JSON.parse(content);
|
|
1072
|
+
const result = {};
|
|
1073
|
+
if (config.lifecycleEnforcement) {
|
|
1074
|
+
result.lifecycleEnforcement = {
|
|
1075
|
+
...DEFAULT_LIFECYCLE_ENFORCEMENT,
|
|
1076
|
+
...config.lifecycleEnforcement
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
if (config.protocolValidation) {
|
|
1080
|
+
result.protocolValidation = {
|
|
1081
|
+
...DEFAULT_PROTOCOL_VALIDATION,
|
|
1082
|
+
...config.protocolValidation
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
if (config.rateLimiting) {
|
|
1086
|
+
const rlConfig = config.rateLimiting;
|
|
1087
|
+
result.rateLimiting = {
|
|
1088
|
+
...DEFAULT_RATE_LIMITING,
|
|
1089
|
+
...rlConfig,
|
|
1090
|
+
query: { ...DEFAULT_RATE_LIMITING.query, ...rlConfig?.query },
|
|
1091
|
+
mutate: { ...DEFAULT_RATE_LIMITING.mutate, ...rlConfig?.mutate },
|
|
1092
|
+
spawn: { ...DEFAULT_RATE_LIMITING.spawn, ...rlConfig?.spawn }
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
return result;
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
console.error(`Warning: Failed to load config file: ${error}`);
|
|
1098
|
+
return {};
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
function validateField(key, value) {
|
|
1102
|
+
const schema = CONFIG_SCHEMA[key];
|
|
1103
|
+
if (!schema) {
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
const actualType = typeof value;
|
|
1107
|
+
if (actualType !== schema.type) {
|
|
1108
|
+
throw new ConfigValidationError(key, value, `must be of type ${schema.type}`);
|
|
1109
|
+
}
|
|
1110
|
+
if ("enum" in schema && schema.enum && !schema.enum.includes(value)) {
|
|
1111
|
+
throw new ConfigValidationError(key, value, `must be one of: ${schema.enum.join(", ")}`);
|
|
1112
|
+
}
|
|
1113
|
+
if (schema.type === "number") {
|
|
1114
|
+
const numValue = value;
|
|
1115
|
+
if ("min" in schema && numValue < schema.min) {
|
|
1116
|
+
throw new ConfigValidationError(key, value, `must be >= ${schema.min}`);
|
|
1117
|
+
}
|
|
1118
|
+
if ("max" in schema && numValue > schema.max) {
|
|
1119
|
+
throw new ConfigValidationError(key, value, `must be <= ${schema.max}`);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
function validateConfig(config) {
|
|
1124
|
+
for (const [key, value] of Object.entries(config)) {
|
|
1125
|
+
validateField(key, value);
|
|
1126
|
+
}
|
|
1127
|
+
for (const [key, schema] of Object.entries(CONFIG_SCHEMA)) {
|
|
1128
|
+
if ("required" in schema && schema.required) {
|
|
1129
|
+
if (config[key] === void 0) {
|
|
1130
|
+
throw new ConfigValidationError(key, void 0, "is required");
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
function loadConfig(projectRoot) {
|
|
1136
|
+
const config = {
|
|
1137
|
+
...DEFAULT_CONFIG,
|
|
1138
|
+
lifecycleEnforcement: { ...DEFAULT_LIFECYCLE_ENFORCEMENT },
|
|
1139
|
+
protocolValidation: { ...DEFAULT_PROTOCOL_VALIDATION },
|
|
1140
|
+
rateLimiting: {
|
|
1141
|
+
...DEFAULT_RATE_LIMITING,
|
|
1142
|
+
query: { ...DEFAULT_RATE_LIMITING.query },
|
|
1143
|
+
mutate: { ...DEFAULT_RATE_LIMITING.mutate },
|
|
1144
|
+
spawn: { ...DEFAULT_RATE_LIMITING.spawn }
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
const fileConfig = loadFromFile(projectRoot);
|
|
1148
|
+
const {
|
|
1149
|
+
lifecycleEnforcement: fileLc,
|
|
1150
|
+
protocolValidation: filePv,
|
|
1151
|
+
rateLimiting: fileRl,
|
|
1152
|
+
...restFileConfig
|
|
1153
|
+
} = fileConfig;
|
|
1154
|
+
if (fileLc) {
|
|
1155
|
+
config.lifecycleEnforcement = { ...config.lifecycleEnforcement, ...fileLc };
|
|
1156
|
+
}
|
|
1157
|
+
if (filePv) {
|
|
1158
|
+
config.protocolValidation = { ...config.protocolValidation, ...filePv };
|
|
1159
|
+
}
|
|
1160
|
+
if (fileRl) {
|
|
1161
|
+
config.rateLimiting = {
|
|
1162
|
+
...config.rateLimiting,
|
|
1163
|
+
...fileRl,
|
|
1164
|
+
query: { ...config.rateLimiting.query, ...fileRl.query },
|
|
1165
|
+
mutate: { ...config.rateLimiting.mutate, ...fileRl.mutate },
|
|
1166
|
+
spawn: { ...config.rateLimiting.spawn, ...fileRl.spawn }
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
Object.assign(config, restFileConfig);
|
|
1170
|
+
for (const key of Object.keys(DEFAULT_CONFIG)) {
|
|
1171
|
+
const envValue = loadFromEnv(key);
|
|
1172
|
+
if (envValue !== void 0) {
|
|
1173
|
+
config[key] = parseEnvValue(key, envValue);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
validateConfig(config);
|
|
1177
|
+
return config;
|
|
1178
|
+
}
|
|
1179
|
+
var globalConfig = null;
|
|
1180
|
+
function getConfig() {
|
|
1181
|
+
if (globalConfig === null) {
|
|
1182
|
+
globalConfig = loadConfig();
|
|
1183
|
+
}
|
|
1184
|
+
return globalConfig;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// packages/cleo/src/dispatch/middleware/audit.ts
|
|
1188
|
+
import { queryAudit } from "@cleocode/core/audit";
|
|
1189
|
+
var log = getLogger("audit");
|
|
1190
|
+
var cachedProjectHash;
|
|
1191
|
+
function resolveProjectHash() {
|
|
1192
|
+
if (cachedProjectHash !== void 0) return cachedProjectHash;
|
|
1193
|
+
try {
|
|
1194
|
+
const info = getProjectInfoSync();
|
|
1195
|
+
cachedProjectHash = info?.projectHash ?? null;
|
|
1196
|
+
} catch {
|
|
1197
|
+
cachedProjectHash = null;
|
|
1198
|
+
}
|
|
1199
|
+
return cachedProjectHash ?? null;
|
|
1200
|
+
}
|
|
1201
|
+
async function isGradeMode() {
|
|
1202
|
+
if (process.env.CLEO_SESSION_GRADE === "true") return true;
|
|
1203
|
+
try {
|
|
1204
|
+
const session = (await resolveBoundSession())?.session;
|
|
1205
|
+
if (session?.gradeMode) return true;
|
|
1206
|
+
} catch {
|
|
1207
|
+
}
|
|
1208
|
+
return false;
|
|
1209
|
+
}
|
|
1210
|
+
async function getActiveSessionInfo() {
|
|
1211
|
+
const gradeId = process.env.CLEO_SESSION_GRADE_ID;
|
|
1212
|
+
if (gradeId && process.env.CLEO_SESSION_GRADE === "true") {
|
|
1213
|
+
return { id: gradeId, gradeMode: true };
|
|
1214
|
+
}
|
|
1215
|
+
const envId = resolveSessionIdFromEnv();
|
|
1216
|
+
if (envId) {
|
|
1217
|
+
return { id: envId, gradeMode: false };
|
|
1218
|
+
}
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1221
|
+
async function writeToSqlite(entry, requestId, response) {
|
|
1222
|
+
try {
|
|
1223
|
+
const { getDb } = await import("@cleocode/core/store/sqlite");
|
|
1224
|
+
const { auditLog } = await import("@cleocode/core/store/schema/audit");
|
|
1225
|
+
const { AuditLogInsertSchema } = await import("@cleocode/core/store/audit-log-schema");
|
|
1226
|
+
const { randomUUID: randomUUID3 } = await import("node:crypto");
|
|
1227
|
+
const payload = {
|
|
1228
|
+
id: randomUUID3(),
|
|
1229
|
+
timestamp: entry.timestamp,
|
|
1230
|
+
action: entry.operation,
|
|
1231
|
+
taskId: entry.metadata.taskId ?? "system",
|
|
1232
|
+
actor: entry.metadata.userId ?? "agent",
|
|
1233
|
+
detailsJson: JSON.stringify(entry.params),
|
|
1234
|
+
// Dispatch-level columns (ADR-019)
|
|
1235
|
+
domain: entry.domain,
|
|
1236
|
+
operation: entry.operation,
|
|
1237
|
+
sessionId: entry.sessionId,
|
|
1238
|
+
requestId: requestId ?? null,
|
|
1239
|
+
idempotencyKey: typeof entry.params["idempotencyKey"] === "string" ? entry.params["idempotencyKey"] : null,
|
|
1240
|
+
durationMs: entry.result.duration,
|
|
1241
|
+
success: entry.result.success ? 1 : 0,
|
|
1242
|
+
source: entry.metadata.source,
|
|
1243
|
+
gateway: entry.metadata.gateway ?? null,
|
|
1244
|
+
errorMessage: entry.error ?? null,
|
|
1245
|
+
afterJson: typeof entry.params["idempotencyKey"] === "string" && response ? JSON.stringify({
|
|
1246
|
+
success: response.success,
|
|
1247
|
+
...response.data !== void 0 ? { data: response.data } : {},
|
|
1248
|
+
...response.page !== void 0 ? { page: response.page } : {},
|
|
1249
|
+
...response.partial !== void 0 ? { partial: response.partial } : {},
|
|
1250
|
+
...response.error !== void 0 ? { error: response.error } : {}
|
|
1251
|
+
}) : null,
|
|
1252
|
+
// Project correlation (T5337)
|
|
1253
|
+
projectHash: resolveProjectHash()
|
|
1254
|
+
};
|
|
1255
|
+
const parsed = AuditLogInsertSchema.safeParse(payload);
|
|
1256
|
+
if (!parsed.success) {
|
|
1257
|
+
log.warn(
|
|
1258
|
+
{ issues: parsed.error.issues },
|
|
1259
|
+
"Audit payload failed Zod validation; skipping insert"
|
|
1260
|
+
);
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
const db = await getDb(process.cwd());
|
|
1264
|
+
await db.insert(auditLog).values(parsed.data).run();
|
|
1265
|
+
} catch (err) {
|
|
1266
|
+
log.warn({ err }, "Failed to write audit entry to SQLite");
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
function createAudit() {
|
|
1270
|
+
return async (req, next) => {
|
|
1271
|
+
const startTime = Date.now();
|
|
1272
|
+
const currentSessionId = req.sessionId ?? (await getActiveSessionInfo())?.id ?? null;
|
|
1273
|
+
const isGradeSession = await isGradeMode();
|
|
1274
|
+
const response = await next();
|
|
1275
|
+
const shouldAudit = req.gateway === "mutate" || req.gateway === "query" && isGradeSession;
|
|
1276
|
+
if (!shouldAudit) return response;
|
|
1277
|
+
const config = getConfig();
|
|
1278
|
+
if (!config.auditLog) return response;
|
|
1279
|
+
const entry = {
|
|
1280
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1281
|
+
sessionId: currentSessionId,
|
|
1282
|
+
domain: req.domain,
|
|
1283
|
+
operation: req.operation,
|
|
1284
|
+
params: req.params || {},
|
|
1285
|
+
result: {
|
|
1286
|
+
success: response.success,
|
|
1287
|
+
exitCode: response.error?.exitCode || 0,
|
|
1288
|
+
duration: Date.now() - startTime
|
|
1289
|
+
},
|
|
1290
|
+
metadata: {
|
|
1291
|
+
taskId: req.params?.taskId || req.params?.parent,
|
|
1292
|
+
source: req.source,
|
|
1293
|
+
gateway: req.gateway
|
|
1294
|
+
},
|
|
1295
|
+
error: response.error?.message
|
|
1296
|
+
};
|
|
1297
|
+
log.info(
|
|
1298
|
+
{
|
|
1299
|
+
domain: entry.domain,
|
|
1300
|
+
operation: entry.operation,
|
|
1301
|
+
sessionId: entry.sessionId,
|
|
1302
|
+
taskId: entry.metadata.taskId,
|
|
1303
|
+
gateway: entry.metadata.gateway,
|
|
1304
|
+
success: entry.result.success,
|
|
1305
|
+
exitCode: entry.result.exitCode,
|
|
1306
|
+
durationMs: entry.result.duration,
|
|
1307
|
+
idempotencyKey: typeof entry.params["idempotencyKey"] === "string" ? entry.params["idempotencyKey"] : void 0
|
|
1308
|
+
},
|
|
1309
|
+
`${entry.metadata.gateway ?? "dispatch"} ${entry.domain}.${entry.operation}`
|
|
1310
|
+
);
|
|
1311
|
+
await writeToSqlite(entry, req.requestId, response);
|
|
1312
|
+
return response;
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// packages/cleo/src/dispatch/middleware/budget-enforcement.ts
|
|
1317
|
+
import { ExitCode } from "@cleocode/contracts/exit-codes.js";
|
|
1318
|
+
|
|
1319
|
+
// packages/cleo/src/dispatch/lib/budget.ts
|
|
1320
|
+
import { MVI_TRUTH_FIELDS } from "@cleocode/core/dispatch/mvi-projection";
|
|
1321
|
+
import { applyBudgetEnforcement, BUDGET_EXCEEDED_CODE, checkBudget } from "@cleocode/lafs";
|
|
1322
|
+
var DEFAULT_BUDGET = 4e3;
|
|
1323
|
+
function toProtoEnvelope(response) {
|
|
1324
|
+
const protoMeta = response["meta"] ?? {};
|
|
1325
|
+
return {
|
|
1326
|
+
$schema: "https://lafs.dev/schemas/v1/envelope.schema.json",
|
|
1327
|
+
_meta: Object.keys(protoMeta).length > 0 ? protoMeta : {
|
|
1328
|
+
specVersion: "1.2.3",
|
|
1329
|
+
schemaVersion: "2026.2.1",
|
|
1330
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1331
|
+
operation: "dispatch.response",
|
|
1332
|
+
requestId: "budget-check",
|
|
1333
|
+
transport: "sdk",
|
|
1334
|
+
strict: true,
|
|
1335
|
+
mvi: "standard",
|
|
1336
|
+
contextVersion: 1
|
|
1337
|
+
},
|
|
1338
|
+
success: response["success"] ?? true,
|
|
1339
|
+
result: response["data"] ?? null,
|
|
1340
|
+
...response["error"] ? { error: response["error"] } : {}
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
function enforceBudget(response, budgetOrOptions) {
|
|
1344
|
+
const options = typeof budgetOrOptions === "number" ? { budget: budgetOrOptions } : budgetOrOptions ?? {};
|
|
1345
|
+
const effectiveBudget = options.budget ?? DEFAULT_BUDGET;
|
|
1346
|
+
const mode = options.mode ?? "truncate";
|
|
1347
|
+
const envelope = toProtoEnvelope(response);
|
|
1348
|
+
const enforcement = applyBudgetEnforcement(
|
|
1349
|
+
envelope,
|
|
1350
|
+
effectiveBudget,
|
|
1351
|
+
// In 'truncate' mode the engine attempts to shrink the payload; in 'error'
|
|
1352
|
+
// mode we skip truncation so the overflow surfaces as an error envelope.
|
|
1353
|
+
{ truncateOnExceed: mode === "truncate", requiredFields: MVI_TRUTH_FIELDS }
|
|
1354
|
+
);
|
|
1355
|
+
const exceeded = !enforcement.withinBudget;
|
|
1356
|
+
const meta = response["meta"] ?? {};
|
|
1357
|
+
meta["_budgetEnforcement"] = {
|
|
1358
|
+
budget: effectiveBudget,
|
|
1359
|
+
estimatedTokens: enforcement.estimatedTokens,
|
|
1360
|
+
withinBudget: enforcement.withinBudget,
|
|
1361
|
+
truncated: enforcement.truncated,
|
|
1362
|
+
mode
|
|
1363
|
+
};
|
|
1364
|
+
return {
|
|
1365
|
+
response: {
|
|
1366
|
+
...response,
|
|
1367
|
+
meta,
|
|
1368
|
+
// Replace data with the (possibly truncated) result when truncation
|
|
1369
|
+
// actually occurred.
|
|
1370
|
+
...enforcement.truncated && enforcement.envelope.result !== void 0 && {
|
|
1371
|
+
data: enforcement.envelope.result
|
|
1372
|
+
}
|
|
1373
|
+
},
|
|
1374
|
+
enforcement,
|
|
1375
|
+
exceeded
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// packages/cleo/src/dispatch/lib/budget-ceilings.ts
|
|
1380
|
+
var FOCUS_TOKEN_CEILING = 1500;
|
|
1381
|
+
var BRIEFING_TOKEN_CEILING = 4e3;
|
|
1382
|
+
var BUDGET_POLICIES = {
|
|
1383
|
+
"focus.show": { budget: FOCUS_TOKEN_CEILING, mode: "truncate" },
|
|
1384
|
+
"session.briefing.show": { budget: BRIEFING_TOKEN_CEILING, mode: "truncate" }
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
// packages/cleo/src/dispatch/middleware/budget-enforcement.ts
|
|
1388
|
+
function resolvePolicy(req) {
|
|
1389
|
+
const override = req.params?.["_budget"];
|
|
1390
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
1391
|
+
const modeOverride = req.params?.["_budgetMode"];
|
|
1392
|
+
const mode = modeOverride === "error" || modeOverride === "truncate" ? modeOverride : "truncate";
|
|
1393
|
+
return { budget: override, mode };
|
|
1394
|
+
}
|
|
1395
|
+
const opKey = `${req.domain}.${req.operation}`;
|
|
1396
|
+
return BUDGET_POLICIES[opKey];
|
|
1397
|
+
}
|
|
1398
|
+
function budgetExceededError(details) {
|
|
1399
|
+
const estimated = typeof details["estimatedTokens"] === "number" ? details["estimatedTokens"] : 0;
|
|
1400
|
+
const budget = typeof details["budget"] === "number" ? details["budget"] : 0;
|
|
1401
|
+
return {
|
|
1402
|
+
code: BUDGET_EXCEEDED_CODE,
|
|
1403
|
+
exitCode: ExitCode.VALIDATION_ERROR,
|
|
1404
|
+
message: `Response exceeds declared MVI budget: estimated ${estimated} tokens, budget ${budget} tokens`,
|
|
1405
|
+
details,
|
|
1406
|
+
fix: "Request a narrower view (e.g. add --limit, --field, or a tighter --mvi level) or raise the budget."
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
function createBudgetEnforcement() {
|
|
1410
|
+
return async (req, next) => {
|
|
1411
|
+
const policy = resolvePolicy(req);
|
|
1412
|
+
if (req.params) {
|
|
1413
|
+
if ("_budget" in req.params) delete req.params["_budget"];
|
|
1414
|
+
if ("_budgetMode" in req.params) delete req.params["_budgetMode"];
|
|
1415
|
+
}
|
|
1416
|
+
if (policy && req.gateway === "mutate") {
|
|
1417
|
+
const meta = {
|
|
1418
|
+
gateway: req.gateway,
|
|
1419
|
+
domain: req.domain,
|
|
1420
|
+
operation: req.operation,
|
|
1421
|
+
source: req.source,
|
|
1422
|
+
requestId: req.requestId,
|
|
1423
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1424
|
+
duration_ms: 0
|
|
1425
|
+
};
|
|
1426
|
+
const minimum = enforceBudget(
|
|
1427
|
+
{ success: true, meta, data: {} },
|
|
1428
|
+
{ budget: policy.budget, mode: "error" }
|
|
1429
|
+
);
|
|
1430
|
+
if (minimum.exceeded) {
|
|
1431
|
+
return {
|
|
1432
|
+
success: false,
|
|
1433
|
+
meta,
|
|
1434
|
+
data: null,
|
|
1435
|
+
error: budgetExceededError({
|
|
1436
|
+
budget: policy.budget,
|
|
1437
|
+
estimatedTokens: minimum.enforcement.estimatedTokens
|
|
1438
|
+
})
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
const response = await next();
|
|
1443
|
+
if (!policy || !response.success || response.data === void 0) {
|
|
1444
|
+
return response;
|
|
1445
|
+
}
|
|
1446
|
+
const options = {
|
|
1447
|
+
budget: policy.budget,
|
|
1448
|
+
mode: req.gateway === "mutate" ? "error" : policy.mode
|
|
1449
|
+
};
|
|
1450
|
+
const { response: enforced, exceeded } = enforceBudget(
|
|
1451
|
+
// Bridge the canonical DispatchResponse into the Record shape enforceBudget
|
|
1452
|
+
// consumes. Field names (meta/data/success) match 1:1.
|
|
1453
|
+
{ meta: response.meta, data: response.data, success: response.success },
|
|
1454
|
+
options
|
|
1455
|
+
);
|
|
1456
|
+
const enforcedData = enforced["data"];
|
|
1457
|
+
const enforcedMeta = enforced["meta"] ?? response.meta;
|
|
1458
|
+
if (exceeded && req.gateway === "mutate") {
|
|
1459
|
+
return { ...response, meta: enforcedMeta };
|
|
1460
|
+
}
|
|
1461
|
+
if (exceeded) {
|
|
1462
|
+
const beDetails = enforcedMeta["_budgetEnforcement"] ?? {};
|
|
1463
|
+
return {
|
|
1464
|
+
...response,
|
|
1465
|
+
meta: enforcedMeta,
|
|
1466
|
+
success: false,
|
|
1467
|
+
data: null,
|
|
1468
|
+
error: budgetExceededError(beDetails)
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
response.meta = enforcedMeta;
|
|
1472
|
+
if (enforcedData !== void 0) {
|
|
1473
|
+
response.data = enforcedData;
|
|
1474
|
+
}
|
|
1475
|
+
return response;
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
// packages/cleo/src/dispatch/middleware/claim-heartbeat.ts
|
|
1480
|
+
var CLAIM_HEARTBEAT_BUDGET_MS = 250;
|
|
1481
|
+
function createClaimHeartbeat(renew, budgetMs = CLAIM_HEARTBEAT_BUDGET_MS) {
|
|
1482
|
+
return async (req, next) => {
|
|
1483
|
+
const response = await next();
|
|
1484
|
+
const sessionId = req.sessionId;
|
|
1485
|
+
if (req.gateway === "mutate" && response.success && sessionId) {
|
|
1486
|
+
const renewal = renew(req, sessionId).catch(() => void 0);
|
|
1487
|
+
let timer;
|
|
1488
|
+
const budget = new Promise((resolve2) => {
|
|
1489
|
+
timer = setTimeout(resolve2, budgetMs);
|
|
1490
|
+
timer.unref?.();
|
|
1491
|
+
});
|
|
1492
|
+
await Promise.race([renewal, budget]);
|
|
1493
|
+
if (timer) clearTimeout(timer);
|
|
1494
|
+
}
|
|
1495
|
+
return response;
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// packages/cleo/src/dispatch/middleware/field-filter.ts
|
|
1500
|
+
import { isMVILevel, applyFieldFilter as sdkApplyFieldFilter } from "@cleocode/lafs";
|
|
1501
|
+
function createFieldFilter() {
|
|
1502
|
+
return async (req, next) => {
|
|
1503
|
+
const _fields = req._fields ?? req.params?._fields;
|
|
1504
|
+
const rawMvi = req._mvi ?? req.params?._mvi;
|
|
1505
|
+
const _mvi = isMVILevel(rawMvi) ? rawMvi : void 0;
|
|
1506
|
+
if (req.params) {
|
|
1507
|
+
delete req.params["_fields"];
|
|
1508
|
+
delete req.params["_mvi"];
|
|
1509
|
+
}
|
|
1510
|
+
if (_fields) req._fields = _fields;
|
|
1511
|
+
if (_mvi) req._mvi = _mvi;
|
|
1512
|
+
const response = await next();
|
|
1513
|
+
if (_fields?.length && response.success && response.data !== void 0) {
|
|
1514
|
+
const stub = {
|
|
1515
|
+
$schema: "https://lafs.dev/schemas/v1/envelope.schema.json",
|
|
1516
|
+
_meta: {
|
|
1517
|
+
specVersion: "",
|
|
1518
|
+
schemaVersion: "",
|
|
1519
|
+
timestamp: response.meta.timestamp,
|
|
1520
|
+
operation: response.meta.operation,
|
|
1521
|
+
requestId: response.meta.requestId,
|
|
1522
|
+
transport: "sdk",
|
|
1523
|
+
strict: true,
|
|
1524
|
+
mvi: "minimal",
|
|
1525
|
+
contextVersion: 0
|
|
1526
|
+
},
|
|
1527
|
+
success: true,
|
|
1528
|
+
result: response.data
|
|
1529
|
+
};
|
|
1530
|
+
const filtered = sdkApplyFieldFilter(
|
|
1531
|
+
stub,
|
|
1532
|
+
_fields
|
|
1533
|
+
);
|
|
1534
|
+
response.data = filtered.result ?? void 0;
|
|
1535
|
+
}
|
|
1536
|
+
return response;
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
// packages/cleo/src/dispatch/middleware/idempotency.ts
|
|
1541
|
+
function getIdempotencyKey(params) {
|
|
1542
|
+
const value = params?.["idempotencyKey"];
|
|
1543
|
+
if (typeof value !== "string") return void 0;
|
|
1544
|
+
const trimmed = value.trim();
|
|
1545
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
1546
|
+
}
|
|
1547
|
+
function asStoredResponse(value) {
|
|
1548
|
+
if (!value || typeof value !== "object") return null;
|
|
1549
|
+
const candidate = value;
|
|
1550
|
+
if (typeof candidate.success !== "boolean") return null;
|
|
1551
|
+
return value;
|
|
1552
|
+
}
|
|
1553
|
+
function stripIdempotencyKey(params) {
|
|
1554
|
+
if (!params || typeof params !== "object" || Array.isArray(params)) return params;
|
|
1555
|
+
const clone = { ...params };
|
|
1556
|
+
delete clone["idempotencyKey"];
|
|
1557
|
+
return clone;
|
|
1558
|
+
}
|
|
1559
|
+
function stableJson(value) {
|
|
1560
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableJson(item)).join(",")}]`;
|
|
1561
|
+
if (value && typeof value === "object") {
|
|
1562
|
+
const entries = Object.entries(value).sort(
|
|
1563
|
+
([a], [b]) => a.localeCompare(b)
|
|
1564
|
+
);
|
|
1565
|
+
return `{${entries.map(([key, val]) => `${JSON.stringify(key)}:${stableJson(val)}`).join(",")}}`;
|
|
1566
|
+
}
|
|
1567
|
+
return JSON.stringify(value);
|
|
1568
|
+
}
|
|
1569
|
+
function sameRequestParams(currentParams, persistedJson) {
|
|
1570
|
+
try {
|
|
1571
|
+
const persisted = JSON.parse(persistedJson);
|
|
1572
|
+
return stableJson(stripIdempotencyKey(currentParams ?? {})) === stableJson(stripIdempotencyKey(persisted));
|
|
1573
|
+
} catch {
|
|
1574
|
+
return false;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
async function findPersistedResponse(req, idempotencyKey) {
|
|
1578
|
+
try {
|
|
1579
|
+
const { getDb, getNativeDb, getProjectInfoSync: getProjectInfoSync2 } = await import("@cleocode/core/internal");
|
|
1580
|
+
let projectHash = null;
|
|
1581
|
+
try {
|
|
1582
|
+
projectHash = getProjectInfoSync2()?.projectHash ?? null;
|
|
1583
|
+
} catch {
|
|
1584
|
+
projectHash = null;
|
|
1585
|
+
}
|
|
1586
|
+
if (!projectHash) return { kind: "miss" };
|
|
1587
|
+
await getDb(process.cwd());
|
|
1588
|
+
const db = getNativeDb();
|
|
1589
|
+
if (!db) return { kind: "miss" };
|
|
1590
|
+
const values = [req.domain, req.operation, idempotencyKey, projectHash];
|
|
1591
|
+
const rows = db.prepare(
|
|
1592
|
+
`SELECT after_json AS afterJson, details_json AS detailsJson
|
|
1593
|
+
FROM audit_log
|
|
1594
|
+
WHERE domain = ?
|
|
1595
|
+
AND operation = ?
|
|
1596
|
+
AND idempotency_key = ?
|
|
1597
|
+
AND success = 1
|
|
1598
|
+
AND project_hash = ?
|
|
1599
|
+
ORDER BY timestamp DESC
|
|
1600
|
+
LIMIT 1`
|
|
1601
|
+
).all(...values);
|
|
1602
|
+
const row = rows[0];
|
|
1603
|
+
if (!row?.afterJson) return { kind: "miss" };
|
|
1604
|
+
if (!row.detailsJson || !sameRequestParams(req.params, row.detailsJson)) {
|
|
1605
|
+
return { kind: "conflict" };
|
|
1606
|
+
}
|
|
1607
|
+
const response = asStoredResponse(JSON.parse(row.afterJson));
|
|
1608
|
+
return response ? { kind: "hit", response } : { kind: "miss" };
|
|
1609
|
+
} catch {
|
|
1610
|
+
return { kind: "miss" };
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
function createIdempotency() {
|
|
1614
|
+
return async (req, next) => {
|
|
1615
|
+
if (req.gateway !== "mutate") return next();
|
|
1616
|
+
const resolved = resolve(req.gateway, req.domain, req.operation);
|
|
1617
|
+
const idempotencyKey = getIdempotencyKey(req.params);
|
|
1618
|
+
if (!resolved?.def.idempotent) {
|
|
1619
|
+
if (idempotencyKey) {
|
|
1620
|
+
return {
|
|
1621
|
+
meta: {
|
|
1622
|
+
gateway: req.gateway,
|
|
1623
|
+
domain: req.domain,
|
|
1624
|
+
operation: req.operation,
|
|
1625
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1626
|
+
duration_ms: 0,
|
|
1627
|
+
source: req.source,
|
|
1628
|
+
requestId: req.requestId,
|
|
1629
|
+
...req.sessionId ? { sessionId: req.sessionId } : {},
|
|
1630
|
+
idempotencyKey
|
|
1631
|
+
},
|
|
1632
|
+
success: false,
|
|
1633
|
+
error: {
|
|
1634
|
+
code: "E_IDEMPOTENCY_UNSUPPORTED",
|
|
1635
|
+
message: `${req.domain}.${req.operation} does not support --idempotency-key, so the key was NOT applied. Do not retry this command blindly: query first with \`cleo find\` or \`cleo show <id> --full\` to establish whether the previous attempt committed.`,
|
|
1636
|
+
details: {
|
|
1637
|
+
domain: req.domain,
|
|
1638
|
+
operation: req.operation,
|
|
1639
|
+
idempotencySupported: false
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
return next();
|
|
1645
|
+
}
|
|
1646
|
+
if (!idempotencyKey) return next();
|
|
1647
|
+
const lookup = await findPersistedResponse(req, idempotencyKey);
|
|
1648
|
+
if (lookup.kind === "miss") return next();
|
|
1649
|
+
if (lookup.kind === "conflict") {
|
|
1650
|
+
return {
|
|
1651
|
+
meta: {
|
|
1652
|
+
gateway: req.gateway,
|
|
1653
|
+
domain: req.domain,
|
|
1654
|
+
operation: req.operation,
|
|
1655
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1656
|
+
duration_ms: 0,
|
|
1657
|
+
source: req.source,
|
|
1658
|
+
requestId: req.requestId,
|
|
1659
|
+
...req.sessionId ? { sessionId: req.sessionId } : {},
|
|
1660
|
+
idempotencyKey
|
|
1661
|
+
},
|
|
1662
|
+
success: false,
|
|
1663
|
+
error: {
|
|
1664
|
+
code: "E_IDEMPOTENCY_KEY_CONFLICT",
|
|
1665
|
+
message: "Idempotency key was already used with different parameters",
|
|
1666
|
+
details: { domain: req.domain, operation: req.operation }
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
const persisted = lookup.response;
|
|
1671
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1672
|
+
return {
|
|
1673
|
+
meta: {
|
|
1674
|
+
gateway: req.gateway,
|
|
1675
|
+
domain: req.domain,
|
|
1676
|
+
operation: req.operation,
|
|
1677
|
+
timestamp: now,
|
|
1678
|
+
duration_ms: 0,
|
|
1679
|
+
source: req.source,
|
|
1680
|
+
requestId: req.requestId,
|
|
1681
|
+
...req.sessionId ? { sessionId: req.sessionId } : {},
|
|
1682
|
+
idempotencyKey,
|
|
1683
|
+
idempotentReplay: true
|
|
1684
|
+
},
|
|
1685
|
+
success: persisted.success,
|
|
1686
|
+
...persisted.data !== void 0 ? { data: persisted.data } : {},
|
|
1687
|
+
...persisted.page !== void 0 ? { page: persisted.page } : {},
|
|
1688
|
+
...persisted.partial !== void 0 ? { partial: persisted.partial } : {},
|
|
1689
|
+
...persisted.error !== void 0 ? { error: persisted.error } : {}
|
|
1690
|
+
};
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// packages/cleo/src/dispatch/middleware/mutate-minimal-envelope.ts
|
|
1695
|
+
import {
|
|
1696
|
+
applyMutateProjection,
|
|
1697
|
+
MUTATE_PROJECTION_PLANS
|
|
1698
|
+
} from "@cleocode/core/dispatch/mutate-projection";
|
|
1699
|
+
import { resolveProjectionMode } from "@cleocode/core/dispatch/mvi-projection";
|
|
1700
|
+
import { isJsonPointer } from "@cleocode/core/dispatch/projection";
|
|
1701
|
+
function resolveModeFor(req) {
|
|
1702
|
+
const override = req.params?.["_projection"];
|
|
1703
|
+
if (override === "full" || override === "mvi") return override;
|
|
1704
|
+
return resolveProjectionMode(getProjectionOptOut() || void 0);
|
|
1705
|
+
}
|
|
1706
|
+
var OPERATION_BUCKETS = {
|
|
1707
|
+
"tasks.add": "created",
|
|
1708
|
+
"tasks.add-batch": "created",
|
|
1709
|
+
// T11482 (DHQ-036): saga.create now projects the created saga ID into the
|
|
1710
|
+
// `created` bucket so `--field /data/created/0` resolves a parseable saga ID.
|
|
1711
|
+
"tasks.saga.create": "created",
|
|
1712
|
+
"tasks.update": "updated",
|
|
1713
|
+
"tasks.complete": "updated",
|
|
1714
|
+
"tasks.delete": "deleted"
|
|
1715
|
+
};
|
|
1716
|
+
var BASE_DATA_FIELDS = /* @__PURE__ */ new Set([
|
|
1717
|
+
"count",
|
|
1718
|
+
"created",
|
|
1719
|
+
"updated",
|
|
1720
|
+
"deleted",
|
|
1721
|
+
"ids",
|
|
1722
|
+
"fieldPathHints",
|
|
1723
|
+
"status",
|
|
1724
|
+
"completedAt",
|
|
1725
|
+
"changes",
|
|
1726
|
+
"dryRun",
|
|
1727
|
+
"duplicate",
|
|
1728
|
+
"acceptanceCriteriaIds",
|
|
1729
|
+
"autoCompleted",
|
|
1730
|
+
// T12660: `cleo complete` reports a cleared focus pointer + next ready task.
|
|
1731
|
+
"focusCleared",
|
|
1732
|
+
"nextSuggested",
|
|
1733
|
+
"cascadeDeleted",
|
|
1734
|
+
// T10599 add-batch dry-run semantics exposed by the projected mutate
|
|
1735
|
+
// envelope. Keep these pointer-addressable for --field consumers.
|
|
1736
|
+
"wouldCreate",
|
|
1737
|
+
"wouldAffect",
|
|
1738
|
+
"insertedCount",
|
|
1739
|
+
"validatedCount",
|
|
1740
|
+
"validationFindings",
|
|
1741
|
+
"knowledgeCoverage"
|
|
1742
|
+
]);
|
|
1743
|
+
function decodePointerToken(token) {
|
|
1744
|
+
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
1745
|
+
}
|
|
1746
|
+
function prevalidateMutateProjectionPointer(operation, pointer) {
|
|
1747
|
+
if (pointer === "" || pointer === "/") return null;
|
|
1748
|
+
if (!pointer.startsWith("/data/")) return null;
|
|
1749
|
+
const [, root, field, index] = pointer.split("/").map(decodePointerToken);
|
|
1750
|
+
if (root !== "data" || !field || !BASE_DATA_FIELDS.has(field)) {
|
|
1751
|
+
return `Pointer "${pointer}" is not available on the projected mutation envelope. Use /data/created/0, /data/updated/0, /data/deleted/0, or legacy /data/ids/0.`;
|
|
1752
|
+
}
|
|
1753
|
+
const bucket = OPERATION_BUCKETS[operation];
|
|
1754
|
+
if (index !== void 0 && ["created", "updated", "deleted"].includes(field) && field !== bucket) {
|
|
1755
|
+
return `Pointer "${pointer}" cannot resolve for ${operation}; use /data/${bucket}/0.`;
|
|
1756
|
+
}
|
|
1757
|
+
return null;
|
|
1758
|
+
}
|
|
1759
|
+
function fieldNotFoundResponse(req, message) {
|
|
1760
|
+
return {
|
|
1761
|
+
meta: {
|
|
1762
|
+
gateway: req.gateway,
|
|
1763
|
+
domain: req.domain,
|
|
1764
|
+
operation: req.operation,
|
|
1765
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1766
|
+
duration_ms: 0,
|
|
1767
|
+
source: req.source,
|
|
1768
|
+
requestId: req.requestId,
|
|
1769
|
+
mutateProjection: "mvi"
|
|
1770
|
+
},
|
|
1771
|
+
success: false,
|
|
1772
|
+
error: {
|
|
1773
|
+
code: "E_FIELD_NOT_FOUND",
|
|
1774
|
+
exitCode: 4,
|
|
1775
|
+
message,
|
|
1776
|
+
details: { phase: "prewrite-field-projection-validation" }
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
function isRecord(value) {
|
|
1781
|
+
return value !== null && typeof value === "object";
|
|
1782
|
+
}
|
|
1783
|
+
function safeRead(value, key) {
|
|
1784
|
+
try {
|
|
1785
|
+
return value[key];
|
|
1786
|
+
} catch {
|
|
1787
|
+
return void 0;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
function safeStringArray(value) {
|
|
1791
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
1792
|
+
}
|
|
1793
|
+
function addUnique(target, values) {
|
|
1794
|
+
for (const value of values) {
|
|
1795
|
+
if (!target.includes(value)) target.push(value);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
function collectCreatedIds(data) {
|
|
1799
|
+
if (!isRecord(data)) return { created: [], acceptanceCriteriaIds: [] };
|
|
1800
|
+
const created = [];
|
|
1801
|
+
const acceptanceCriteriaIds = [];
|
|
1802
|
+
const task = safeRead(data, "task");
|
|
1803
|
+
if (isRecord(task)) {
|
|
1804
|
+
const id = safeRead(task, "id");
|
|
1805
|
+
if (typeof id === "string") created.push(id);
|
|
1806
|
+
}
|
|
1807
|
+
const createdIds = safeRead(data, "createdIds");
|
|
1808
|
+
if (isRecord(createdIds)) {
|
|
1809
|
+
addUnique(created, safeStringArray(safeRead(createdIds, "tasks")));
|
|
1810
|
+
addUnique(acceptanceCriteriaIds, safeStringArray(safeRead(createdIds, "acceptanceCriteria")));
|
|
1811
|
+
}
|
|
1812
|
+
const tasks = safeRead(data, "tasks");
|
|
1813
|
+
if (Array.isArray(tasks)) {
|
|
1814
|
+
for (const entry of tasks) {
|
|
1815
|
+
if (!isRecord(entry)) continue;
|
|
1816
|
+
const nestedTask = safeRead(entry, "task");
|
|
1817
|
+
const id = isRecord(nestedTask) ? safeRead(nestedTask, "id") : safeRead(entry, "id");
|
|
1818
|
+
if (typeof id === "string" && !created.includes(id)) created.push(id);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return { created, acceptanceCriteriaIds };
|
|
1822
|
+
}
|
|
1823
|
+
function buildProjectionFailureWarning(data, error) {
|
|
1824
|
+
const { created, acceptanceCriteriaIds } = collectCreatedIds(data);
|
|
1825
|
+
const createdSuffix = created.length > 0 ? ` Created task IDs: ${created.join(", ")}.` : "";
|
|
1826
|
+
const acSuffix = acceptanceCriteriaIds.length > 0 ? ` Acceptance criteria IDs: ${acceptanceCriteriaIds.join(", ")}.` : "";
|
|
1827
|
+
const warning = {
|
|
1828
|
+
code: "W_MUTATE_PROJECTION_FAILED",
|
|
1829
|
+
message: `Mutation succeeded, but the response projection failed.${createdSuffix}${acSuffix} Do not retry creation; inspect the IDs above or rerun with --full if you need the unprojected payload.`,
|
|
1830
|
+
created,
|
|
1831
|
+
acceptanceCriteriaIds,
|
|
1832
|
+
retryHazard: true,
|
|
1833
|
+
recoveryHint: "Do not retry creation. Use the emitted IDs with cleo show, or rerun the command with --full only for inspection."
|
|
1834
|
+
};
|
|
1835
|
+
if (error instanceof Error && error.message.length > 0) warning.cause = error.message;
|
|
1836
|
+
return warning;
|
|
1837
|
+
}
|
|
1838
|
+
function createMutateMinimalEnvelope() {
|
|
1839
|
+
return async (req, next) => {
|
|
1840
|
+
const mode = resolveModeFor(req);
|
|
1841
|
+
const opKey = `${req.domain}.${req.operation}`;
|
|
1842
|
+
const hasPlan = MUTATE_PROJECTION_PLANS[opKey] !== void 0;
|
|
1843
|
+
const field = getFieldContext().field;
|
|
1844
|
+
if (hasPlan && mode === "mvi" && field && isJsonPointer(field)) {
|
|
1845
|
+
const validationError = prevalidateMutateProjectionPointer(opKey, field);
|
|
1846
|
+
if (validationError) return fieldNotFoundResponse(req, validationError);
|
|
1847
|
+
}
|
|
1848
|
+
const response = await next();
|
|
1849
|
+
if (!hasPlan) return response;
|
|
1850
|
+
if (response.success && response.data !== void 0) {
|
|
1851
|
+
try {
|
|
1852
|
+
response.data = applyMutateProjection(response.data, opKey, mode);
|
|
1853
|
+
} catch (error) {
|
|
1854
|
+
response.partial = true;
|
|
1855
|
+
response.meta.mutateProjection = "projection-failed";
|
|
1856
|
+
response.meta.warning = buildProjectionFailureWarning(response.data, error);
|
|
1857
|
+
return response;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
response.meta.mutateProjection = mode;
|
|
1861
|
+
return response;
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// packages/cleo/src/dispatch/middleware/mvi-record-projection.ts
|
|
1866
|
+
import {
|
|
1867
|
+
applyProjectionPlan,
|
|
1868
|
+
PROJECTION_PLANS,
|
|
1869
|
+
resolveProjectionMode as resolveProjectionMode2
|
|
1870
|
+
} from "@cleocode/core/dispatch/mvi-projection";
|
|
1871
|
+
import { extractByJsonPointer, isJsonPointer as isJsonPointer2 } from "@cleocode/core/dispatch/projection";
|
|
1872
|
+
function resolveModeFor2(req) {
|
|
1873
|
+
const override = req.params?.["_projection"];
|
|
1874
|
+
if (override === "full" || override === "mvi") return override;
|
|
1875
|
+
return resolveProjectionMode2(getProjectionOptOut() || void 0);
|
|
1876
|
+
}
|
|
1877
|
+
function fieldPointerNeedsFullData(fullData, projectedData) {
|
|
1878
|
+
const field = getFieldContext().field;
|
|
1879
|
+
if (!field || !isJsonPointer2(field) || !field.startsWith("/data/")) return false;
|
|
1880
|
+
const pointer = field.slice("/data".length);
|
|
1881
|
+
return extractByJsonPointer(projectedData, pointer) === void 0 && extractByJsonPointer(fullData, pointer) !== void 0;
|
|
1882
|
+
}
|
|
1883
|
+
function createMviRecordProjection() {
|
|
1884
|
+
return async (req, next) => {
|
|
1885
|
+
const mode = resolveModeFor2(req);
|
|
1886
|
+
if (req.params && "_projection" in req.params) {
|
|
1887
|
+
delete req.params["_projection"];
|
|
1888
|
+
}
|
|
1889
|
+
const opKey = `${req.domain}.${req.operation}`;
|
|
1890
|
+
const hasPlan = PROJECTION_PLANS[opKey] !== void 0;
|
|
1891
|
+
const response = await next();
|
|
1892
|
+
if (!hasPlan) return response;
|
|
1893
|
+
let appliedMode = mode;
|
|
1894
|
+
if (response.success && response.data !== void 0) {
|
|
1895
|
+
const projected = applyProjectionPlan(response.data, opKey, mode);
|
|
1896
|
+
if (mode === "mvi" && opKey === "tasks.show" && fieldPointerNeedsFullData(response.data, projected)) {
|
|
1897
|
+
appliedMode = "full";
|
|
1898
|
+
} else {
|
|
1899
|
+
response.data = projected;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
response.meta.projection = appliedMode;
|
|
1903
|
+
return response;
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
// packages/cleo/src/dispatch/lib/security.ts
|
|
1908
|
+
import {
|
|
1909
|
+
ALL_VALID_STATUSES,
|
|
1910
|
+
DEFAULT_RATE_LIMITS,
|
|
1911
|
+
ensureArray,
|
|
1912
|
+
RateLimiter,
|
|
1913
|
+
SecurityError,
|
|
1914
|
+
sanitizeContent,
|
|
1915
|
+
sanitizeParams,
|
|
1916
|
+
sanitizePath,
|
|
1917
|
+
sanitizeTaskId,
|
|
1918
|
+
VALID_DOMAINS,
|
|
1919
|
+
VALID_GATEWAYS,
|
|
1920
|
+
VALID_LIFECYCLE_STAGE_STATUSES,
|
|
1921
|
+
VALID_MANIFEST_STATUSES,
|
|
1922
|
+
VALID_PRIORITIES,
|
|
1923
|
+
validateEnum
|
|
1924
|
+
} from "@cleocode/core/security/input-sanitization";
|
|
1925
|
+
|
|
1926
|
+
// packages/cleo/src/dispatch/middleware/sanitizer.ts
|
|
1927
|
+
function createSanitizer(getProjectRoot2) {
|
|
1928
|
+
return async (req, next) => {
|
|
1929
|
+
if (req.params) {
|
|
1930
|
+
try {
|
|
1931
|
+
const root = getProjectRoot2 ? getProjectRoot2() : void 0;
|
|
1932
|
+
req.params = sanitizeParams(req.params, root, {
|
|
1933
|
+
domain: req.domain,
|
|
1934
|
+
operation: req.operation
|
|
1935
|
+
});
|
|
1936
|
+
} catch (error) {
|
|
1937
|
+
return {
|
|
1938
|
+
meta: {
|
|
1939
|
+
gateway: req.gateway,
|
|
1940
|
+
domain: req.domain,
|
|
1941
|
+
operation: req.operation,
|
|
1942
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1943
|
+
duration_ms: 0,
|
|
1944
|
+
source: req.source,
|
|
1945
|
+
requestId: req.requestId
|
|
1946
|
+
},
|
|
1947
|
+
success: false,
|
|
1948
|
+
error: {
|
|
1949
|
+
code: "E_VALIDATION_FAILED",
|
|
1950
|
+
exitCode: 6,
|
|
1951
|
+
// VALIDATION_ERROR
|
|
1952
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1953
|
+
}
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
return next();
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
// packages/cleo/src/dispatch/middleware/session-resolver.ts
|
|
1962
|
+
import { randomUUID } from "node:crypto";
|
|
1963
|
+
import { resolveSessionIdFromEnv as resolveSessionIdFromEnv2 } from "@cleocode/core/sessions/session-id";
|
|
1964
|
+
function resolveOriginSessionId(sessionId, executionSessionId) {
|
|
1965
|
+
return process.env.CLEO_ORIGIN_SESSION_ID ?? process.env.CLEO_SESSION_ORIGIN_ID ?? sessionId ?? executionSessionId;
|
|
1966
|
+
}
|
|
1967
|
+
function resolveExecutionSessionId() {
|
|
1968
|
+
return process.env.CLEO_EXECUTION_SESSION_ID ?? process.env.CLEO_SESSION_EXECUTION_ID ?? randomUUID();
|
|
1969
|
+
}
|
|
1970
|
+
function createSessionResolver(cliSessionLookup, onUnboundMutation) {
|
|
1971
|
+
return async (req, next) => {
|
|
1972
|
+
if (!req.executionSessionId) {
|
|
1973
|
+
req.executionSessionId = resolveExecutionSessionId();
|
|
1974
|
+
}
|
|
1975
|
+
if (req.sessionId) {
|
|
1976
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
1977
|
+
return next();
|
|
1978
|
+
}
|
|
1979
|
+
const bound = getBoundSession();
|
|
1980
|
+
if (bound) {
|
|
1981
|
+
req.sessionId = bound.sessionId;
|
|
1982
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
1983
|
+
return next();
|
|
1984
|
+
}
|
|
1985
|
+
if (cliSessionLookup && req.source === "cli") {
|
|
1986
|
+
try {
|
|
1987
|
+
const activeId = await cliSessionLookup();
|
|
1988
|
+
if (activeId) {
|
|
1989
|
+
req.sessionId = activeId;
|
|
1990
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
1991
|
+
return next();
|
|
1992
|
+
}
|
|
1993
|
+
} catch {
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
const envGradeId = process.env.CLEO_SESSION_GRADE_ID;
|
|
1997
|
+
if (envGradeId && process.env.CLEO_SESSION_GRADE === "true") {
|
|
1998
|
+
req.sessionId = envGradeId;
|
|
1999
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
2000
|
+
return next();
|
|
2001
|
+
}
|
|
2002
|
+
const cliResolved = cliSessionLookup !== void 0 && req.source === "cli";
|
|
2003
|
+
const envId = cliResolved ? null : resolveSessionIdFromEnv2();
|
|
2004
|
+
if (envId) {
|
|
2005
|
+
req.sessionId = envId;
|
|
2006
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
2007
|
+
return next();
|
|
2008
|
+
}
|
|
2009
|
+
req.originSessionId ??= resolveOriginSessionId(req.sessionId, req.executionSessionId);
|
|
2010
|
+
if (onUnboundMutation && req.source === "cli" && req.gateway === "mutate" && req.domain !== "session") {
|
|
2011
|
+
try {
|
|
2012
|
+
await onUnboundMutation(req);
|
|
2013
|
+
} catch {
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
return next();
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
// packages/cleo/src/dispatch/middleware/store-write-guard.ts
|
|
2021
|
+
var ALLOWED_WHILE_READ_ONLY = /* @__PURE__ */ new Set(["admin.backup"]);
|
|
2022
|
+
function createStoreWriteGuard(getProjectRoot2) {
|
|
2023
|
+
return async (req, next) => {
|
|
2024
|
+
if (req.gateway !== "mutate" || ALLOWED_WHILE_READ_ONLY.has(`${req.domain}.${req.operation}`)) {
|
|
2025
|
+
return next();
|
|
2026
|
+
}
|
|
2027
|
+
let projectRoot;
|
|
2028
|
+
try {
|
|
2029
|
+
projectRoot = getProjectRoot2();
|
|
2030
|
+
} catch {
|
|
2031
|
+
return next();
|
|
2032
|
+
}
|
|
2033
|
+
const { storeWriteBlock } = await import("@cleocode/core/store/store-write-guard.js");
|
|
2034
|
+
const blocked = await storeWriteBlock(projectRoot, {
|
|
2035
|
+
domain: req.domain,
|
|
2036
|
+
operation: req.operation
|
|
2037
|
+
});
|
|
2038
|
+
if (blocked === null) return next();
|
|
2039
|
+
return {
|
|
2040
|
+
success: false,
|
|
2041
|
+
meta: {
|
|
2042
|
+
gateway: req.gateway,
|
|
2043
|
+
domain: req.domain,
|
|
2044
|
+
operation: req.operation,
|
|
2045
|
+
source: req.source,
|
|
2046
|
+
requestId: req.requestId,
|
|
2047
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2048
|
+
duration_ms: 0
|
|
2049
|
+
},
|
|
2050
|
+
data: null,
|
|
2051
|
+
error: {
|
|
2052
|
+
code: "E_TWIN_COLLAPSE_FAILED",
|
|
2053
|
+
exitCode: blocked.code,
|
|
2054
|
+
message: blocked.message,
|
|
2055
|
+
...blocked.details ? { details: blocked.details } : {},
|
|
2056
|
+
...blocked.fix ? { fix: blocked.fix } : {}
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
// packages/cleo/src/dispatch/middleware/telemetry.ts
|
|
2063
|
+
import { isTelemetryEnabled, recordTelemetryEvent } from "@cleocode/core/telemetry/index";
|
|
2064
|
+
function createTelemetry() {
|
|
2065
|
+
return async (req, next) => {
|
|
2066
|
+
const startTime = Date.now();
|
|
2067
|
+
const response = await next();
|
|
2068
|
+
try {
|
|
2069
|
+
if (isTelemetryEnabled()) {
|
|
2070
|
+
const durationMs = response.meta.duration_ms ?? Date.now() - startTime;
|
|
2071
|
+
const exitCode = response.success ? 0 : response.error?.exitCode ?? 1;
|
|
2072
|
+
const errorCode = response.error?.code ?? null;
|
|
2073
|
+
recordTelemetryEvent({
|
|
2074
|
+
domain: req.domain,
|
|
2075
|
+
gateway: req.gateway,
|
|
2076
|
+
operation: req.operation,
|
|
2077
|
+
durationMs,
|
|
2078
|
+
exitCode,
|
|
2079
|
+
errorCode
|
|
2080
|
+
}).catch(() => {
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2083
|
+
} catch {
|
|
2084
|
+
}
|
|
2085
|
+
return response;
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// packages/cleo/src/dispatch/middleware/write-actor.ts
|
|
2090
|
+
import { runWithWriteActor } from "@cleocode/core/store/sync/write-actor";
|
|
2091
|
+
function createWriteActor() {
|
|
2092
|
+
return async (req, next) => {
|
|
2093
|
+
if (req.gateway !== "mutate") return next();
|
|
2094
|
+
return runWithWriteActor(
|
|
2095
|
+
{
|
|
2096
|
+
op: `${req.domain}.${req.operation}`,
|
|
2097
|
+
...req.sessionId ? { session: req.sessionId } : {}
|
|
2098
|
+
},
|
|
2099
|
+
next
|
|
2100
|
+
);
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
// packages/cleo/src/dispatch/adapters/cli.ts
|
|
2105
|
+
var ERROR_CODE_TO_EXIT = {
|
|
2106
|
+
E_NOT_FOUND: 4,
|
|
2107
|
+
E_INVALID_INPUT: 2,
|
|
2108
|
+
E_FILE_ERROR: 3,
|
|
2109
|
+
E_DEPENDENCY: 5,
|
|
2110
|
+
E_VALIDATION: 6,
|
|
2111
|
+
E_RETRYABLE: 7,
|
|
2112
|
+
E_CONFIG_ERROR: 8,
|
|
2113
|
+
E_PROJECT_MOVED: 9,
|
|
2114
|
+
E_PARENT_NOT_FOUND: 10,
|
|
2115
|
+
E_DEPTH_EXCEEDED: 11,
|
|
2116
|
+
E_SIBLING_LIMIT: 12,
|
|
2117
|
+
E_CIRCULAR_DEP: 14,
|
|
2118
|
+
E_INVALID_PARENT_TYPE: 13,
|
|
2119
|
+
E_ORPHAN_DETECTED: 15,
|
|
2120
|
+
E_HAS_CHILDREN: 16,
|
|
2121
|
+
E_TASK_COMPLETED: 17,
|
|
2122
|
+
// ExitCode.TASK_COMPLETED — canonical value from @cleocode/contracts
|
|
2123
|
+
E_HAS_DEPENDENTS: 19,
|
|
2124
|
+
E_CHECKSUM_MISMATCH: 20,
|
|
2125
|
+
E_CONFLICT: 23,
|
|
2126
|
+
E_SESSION_UNBOUND: 24,
|
|
2127
|
+
E_WORKTREE_LOCKED: 25,
|
|
2128
|
+
E_TASK_RENAMED: 26,
|
|
2129
|
+
E_TWIN_COLLAPSE_FAILED: 55,
|
|
2130
|
+
E_SESSION_EXISTS: 30,
|
|
2131
|
+
E_SESSION_NOT_FOUND: 31,
|
|
2132
|
+
E_SCOPE_CONFLICT: 32,
|
|
2133
|
+
E_ACTIVE_TASK_REQUIRED: 38,
|
|
2134
|
+
E_INVALID_OPERATION: 2,
|
|
2135
|
+
E_MISSING_PARAMS: 2,
|
|
2136
|
+
E_NO_HANDLER: 1,
|
|
2137
|
+
E_INTERNAL: 1,
|
|
2138
|
+
// T9796 — docs canon CI gate: violation = fail-build, invalid = tool-error.
|
|
2139
|
+
E_CANON_VIOLATION: 1,
|
|
2140
|
+
E_CANON_INVALID: 2
|
|
2141
|
+
};
|
|
2142
|
+
var caampLibraryReady = null;
|
|
2143
|
+
function ensureCaampLibrary() {
|
|
2144
|
+
caampLibraryReady ??= registerCaampLibrary();
|
|
2145
|
+
return caampLibraryReady;
|
|
2146
|
+
}
|
|
2147
|
+
async function registerCaampLibrary() {
|
|
2148
|
+
let caamp;
|
|
2149
|
+
try {
|
|
2150
|
+
caamp = await import("@cleocode/caamp");
|
|
2151
|
+
} catch {
|
|
2152
|
+
return;
|
|
2153
|
+
}
|
|
2154
|
+
const { catalog, registerSkillLibraryFromPath } = caamp;
|
|
2155
|
+
if (catalog.isCatalogAvailable()) return;
|
|
2156
|
+
try {
|
|
2157
|
+
let skillsRoot = null;
|
|
2158
|
+
try {
|
|
2159
|
+
const req = createRequire(import.meta.url);
|
|
2160
|
+
const skillsPkgJson = req.resolve("@cleocode/skills/package.json");
|
|
2161
|
+
const candidate = dirname(skillsPkgJson);
|
|
2162
|
+
if (existsSync2(join2(candidate, "skills", "manifest.json"))) {
|
|
2163
|
+
skillsRoot = candidate;
|
|
2164
|
+
}
|
|
2165
|
+
} catch {
|
|
2166
|
+
}
|
|
2167
|
+
if (!skillsRoot) {
|
|
2168
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
2169
|
+
const packageRoot = join2(dirname(thisFile), "..", "..", "..", "..", "..");
|
|
2170
|
+
const candidate = join2(packageRoot, "packages", "skills");
|
|
2171
|
+
if (existsSync2(join2(candidate, "skills", "manifest.json"))) {
|
|
2172
|
+
skillsRoot = candidate;
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
if (skillsRoot) {
|
|
2176
|
+
registerSkillLibraryFromPath(skillsRoot);
|
|
2177
|
+
}
|
|
2178
|
+
} catch {
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
var BARREL_FREE_OPERATIONS = /* @__PURE__ */ new Set([
|
|
2182
|
+
"query:tasks.show",
|
|
2183
|
+
"query:tasks.find",
|
|
2184
|
+
"query:tasks.list",
|
|
2185
|
+
"query:tasks.current",
|
|
2186
|
+
"query:session.status",
|
|
2187
|
+
"query:session.briefing.show"
|
|
2188
|
+
]);
|
|
2189
|
+
async function prepareCoreFor(gateway, domain, operation) {
|
|
2190
|
+
if (BARREL_FREE_OPERATIONS.has(`${gateway}:${domain}.${operation}`)) return;
|
|
2191
|
+
await import("@cleocode/core/registrations");
|
|
2192
|
+
await ensureCaampLibrary();
|
|
2193
|
+
}
|
|
2194
|
+
var _dispatcher = null;
|
|
2195
|
+
function getCliDispatcher() {
|
|
2196
|
+
if (!_dispatcher) {
|
|
2197
|
+
_dispatcher = createCliDispatcher();
|
|
2198
|
+
}
|
|
2199
|
+
return _dispatcher;
|
|
2200
|
+
}
|
|
2201
|
+
function createCliGatewayHandler() {
|
|
2202
|
+
const dispatcher = getCliDispatcher();
|
|
2203
|
+
return {
|
|
2204
|
+
// A daemon serves every operation, so it prepares CORE the way the CLI
|
|
2205
|
+
// does for an operation outside BARREL_FREE_OPERATIONS (T13126).
|
|
2206
|
+
handle: async (req) => {
|
|
2207
|
+
await import("@cleocode/core/internal");
|
|
2208
|
+
await ensureCaampLibrary();
|
|
2209
|
+
return dispatcher.dispatch(req);
|
|
2210
|
+
}
|
|
2211
|
+
};
|
|
2212
|
+
}
|
|
2213
|
+
async function lookupCliSession() {
|
|
2214
|
+
try {
|
|
2215
|
+
const { resolveBoundSessionId } = await import("@cleocode/core/store/session-store");
|
|
2216
|
+
return await resolveBoundSessionId();
|
|
2217
|
+
} catch {
|
|
2218
|
+
return null;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
async function heartbeatCliSession(_req, sessionId) {
|
|
2222
|
+
const { heartbeatProjectSession } = await import("@cleocode/core/task-work/claims");
|
|
2223
|
+
await heartbeatProjectSession(getProjectRoot(), sessionId);
|
|
2224
|
+
}
|
|
2225
|
+
async function warnUnboundMutation(req) {
|
|
2226
|
+
if (getFormatContext().quiet) return;
|
|
2227
|
+
const { hasActiveSession } = await import("@cleocode/core/store/session-store");
|
|
2228
|
+
if (!await hasActiveSession()) return;
|
|
2229
|
+
process.stderr.write(
|
|
2230
|
+
`[cleo] warning: no session is bound to this terminal; ${req.domain}.${req.operation} is not attributed to any session (bind: 'cleo session start' | 'cleo session resume <id>' | CLEO_SESSION_ID=<id>)
|
|
2231
|
+
`
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
function createCliDispatcher() {
|
|
2235
|
+
const handlers = createLazyDomainHandlers();
|
|
2236
|
+
return new Dispatcher({
|
|
2237
|
+
handlers,
|
|
2238
|
+
middlewares: [
|
|
2239
|
+
// T12535: refuse mutating ops while the store's twin collapse is failed
|
|
2240
|
+
// (reads stay available, served from the merged TEMP shadows).
|
|
2241
|
+
createStoreWriteGuard(() => getProjectRoot()),
|
|
2242
|
+
createSessionResolver(lookupCliSession, warnUnboundMutation),
|
|
2243
|
+
// T4959: session identity first; T12500: warn when unbound
|
|
2244
|
+
createWriteActor(),
|
|
2245
|
+
// T13229: local write frames record the command as actor.op
|
|
2246
|
+
createClaimHeartbeat(heartbeatCliSession),
|
|
2247
|
+
// T12502 · T12540: a bound session's mutation refreshes lastActivity + renews its leases
|
|
2248
|
+
createSanitizer(() => getProjectRoot()),
|
|
2249
|
+
createFieldFilter(),
|
|
2250
|
+
// T9922 (Saga T9855 / E8.3): MVI record projection default for read ops.
|
|
2251
|
+
// Runs AFTER the domain handler returns so it can trim the data payload
|
|
2252
|
+
// before audit + telemetry record byte sizes. Sits before audit so the
|
|
2253
|
+
// audit trail captures the projected (final) bytes.
|
|
2254
|
+
createMviRecordProjection(),
|
|
2255
|
+
// T9931 (Saga T9855 / E9.4): minimal envelopes for mutate ops. Mirror
|
|
2256
|
+
// policy to the read-side projection — sits in the same pre-audit slot
|
|
2257
|
+
// so audit/telemetry record the trimmed bytes.
|
|
2258
|
+
createMutateMinimalEnvelope(),
|
|
2259
|
+
// T11350 (Epic T11285 EP-MVI-PRIMITIVE): LIVE MVI token-budget chokepoint.
|
|
2260
|
+
// Runs AFTER projection/minimal-envelope (measures the trimmed payload)
|
|
2261
|
+
// and BEFORE audit/telemetry (so they record the final budget-enforced
|
|
2262
|
+
// bytes). Enforces per-op ceilings from BUDGET_POLICIES (e.g. focus ≤1500).
|
|
2263
|
+
createBudgetEnforcement(),
|
|
2264
|
+
createAudit(),
|
|
2265
|
+
// T4959: CLI now gets audit trail
|
|
2266
|
+
createIdempotency(),
|
|
2267
|
+
// T10600: duplicate retry protection after audit wraps the response
|
|
2268
|
+
createTelemetry()
|
|
2269
|
+
// T624: opt-in self-improvement telemetry
|
|
2270
|
+
]
|
|
2271
|
+
});
|
|
2272
|
+
}
|
|
2273
|
+
function resetCliDispatcher() {
|
|
2274
|
+
_dispatcher = null;
|
|
2275
|
+
}
|
|
2276
|
+
function maybeEmitDescribe(gateway, domain, operation, outputOpts) {
|
|
2277
|
+
if (!isDescribeMode()) return false;
|
|
2278
|
+
const key = `${domain}.${operation}`;
|
|
2279
|
+
const { describeOperation } = loadEsmSync(
|
|
2280
|
+
"@cleocode/core/dispatch/describe-operation"
|
|
2281
|
+
);
|
|
2282
|
+
const descriptor = describeOperation(key);
|
|
2283
|
+
const command = outputOpts?.command ?? operation;
|
|
2284
|
+
if (descriptor === null) {
|
|
2285
|
+
cliOutput(
|
|
2286
|
+
{ operation: key, gateway, inputContract: null, outputContract: null },
|
|
2287
|
+
{
|
|
2288
|
+
command,
|
|
2289
|
+
operation: `describe.${key}`,
|
|
2290
|
+
message: `No registered operation found for "${key}".`
|
|
2291
|
+
}
|
|
2292
|
+
);
|
|
2293
|
+
return true;
|
|
2294
|
+
}
|
|
2295
|
+
cliOutput(descriptor, {
|
|
2296
|
+
command,
|
|
2297
|
+
operation: `describe.${key}`,
|
|
2298
|
+
message: `Schema for ${key} (input + output). Use the outputContract.fieldPointers for --field.`
|
|
2299
|
+
});
|
|
2300
|
+
return true;
|
|
2301
|
+
}
|
|
2302
|
+
async function dispatchFromCli(gateway, domain, operation, params, outputOpts) {
|
|
2303
|
+
if (maybeEmitDescribe(gateway, domain, operation, outputOpts)) return;
|
|
2304
|
+
await prepareCoreFor(gateway, domain, operation);
|
|
2305
|
+
const dispatcher = getCliDispatcher();
|
|
2306
|
+
const projectRoot = getProjectRoot();
|
|
2307
|
+
const dispatchStart = Date.now();
|
|
2308
|
+
void trackBackgroundOp(
|
|
2309
|
+
hooks.dispatch("PromptSubmit", projectRoot, {
|
|
2310
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2311
|
+
gateway,
|
|
2312
|
+
domain,
|
|
2313
|
+
operation,
|
|
2314
|
+
source: "cli"
|
|
2315
|
+
}).catch(() => {
|
|
2316
|
+
})
|
|
2317
|
+
);
|
|
2318
|
+
const spinner = createDispatchSpinner(domain, operation);
|
|
2319
|
+
spinner.start();
|
|
2320
|
+
let response;
|
|
2321
|
+
const mergedParams = mergeIdempotencyParam(gateway, params);
|
|
2322
|
+
try {
|
|
2323
|
+
response = await dispatcher.dispatch({
|
|
2324
|
+
gateway,
|
|
2325
|
+
domain,
|
|
2326
|
+
operation,
|
|
2327
|
+
params: mergedParams,
|
|
2328
|
+
source: "cli",
|
|
2329
|
+
requestId: randomUUID2()
|
|
2330
|
+
});
|
|
2331
|
+
} finally {
|
|
2332
|
+
spinner.stop();
|
|
2333
|
+
}
|
|
2334
|
+
void trackBackgroundOp(
|
|
2335
|
+
hooks.dispatch("ResponseComplete", projectRoot, {
|
|
2336
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2337
|
+
gateway,
|
|
2338
|
+
domain,
|
|
2339
|
+
operation,
|
|
2340
|
+
success: response.success,
|
|
2341
|
+
durationMs: Date.now() - dispatchStart,
|
|
2342
|
+
errorCode: response.error?.code
|
|
2343
|
+
}).catch(() => {
|
|
2344
|
+
})
|
|
2345
|
+
);
|
|
2346
|
+
if (response.success) {
|
|
2347
|
+
if (gateway === "mutate") {
|
|
2348
|
+
const { autoRecordDispatchTokenUsage } = await import("@cleocode/core/metrics/token-service");
|
|
2349
|
+
await autoRecordDispatchTokenUsage({
|
|
2350
|
+
requestPayload: mergedParams,
|
|
2351
|
+
responsePayload: { data: response.data, page: response.page },
|
|
2352
|
+
transport: "cli",
|
|
2353
|
+
gateway,
|
|
2354
|
+
domain,
|
|
2355
|
+
operation,
|
|
2356
|
+
sessionId: response.meta.sessionId,
|
|
2357
|
+
requestId: response.meta.requestId,
|
|
2358
|
+
cwd: getProjectRoot()
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
const opts = {
|
|
2362
|
+
command: outputOpts?.command ?? operation,
|
|
2363
|
+
operation: outputOpts?.operation ?? `${domain}.${operation}`,
|
|
2364
|
+
...outputOpts
|
|
2365
|
+
};
|
|
2366
|
+
if (opts.page === void 0 && response.page !== void 0) {
|
|
2367
|
+
opts.page = response.page;
|
|
2368
|
+
}
|
|
2369
|
+
if (opts.responseMeta === void 0) {
|
|
2370
|
+
opts.responseMeta = response.meta;
|
|
2371
|
+
}
|
|
2372
|
+
cliOutput(response.data, opts);
|
|
2373
|
+
} else {
|
|
2374
|
+
const errorCode = response.error?.code ?? "E_GENERAL";
|
|
2375
|
+
const exitCode = response.error?.exitCode ?? ERROR_CODE_TO_EXIT[errorCode] ?? 1;
|
|
2376
|
+
cliError(
|
|
2377
|
+
response.error?.message ?? "Unknown error",
|
|
2378
|
+
exitCode,
|
|
2379
|
+
{
|
|
2380
|
+
name: errorCode,
|
|
2381
|
+
details: response.error?.details,
|
|
2382
|
+
fix: response.error?.fix,
|
|
2383
|
+
alternatives: response.error?.alternatives
|
|
2384
|
+
},
|
|
2385
|
+
{
|
|
2386
|
+
operation: `${domain}.${operation}`,
|
|
2387
|
+
requestId: response.meta.requestId,
|
|
2388
|
+
duration_ms: response.meta.duration_ms,
|
|
2389
|
+
timestamp: response.meta.timestamp,
|
|
2390
|
+
...response.meta.sessionId ? { sessionId: response.meta.sessionId } : {},
|
|
2391
|
+
...response.meta.originSessionId ? { originSessionId: response.meta.originSessionId } : {},
|
|
2392
|
+
...response.meta.executionSessionId ? { executionSessionId: response.meta.executionSessionId } : {}
|
|
2393
|
+
}
|
|
2394
|
+
);
|
|
2395
|
+
await settleThenExit(exitCode);
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
function handleRawError(response, _opts) {
|
|
2399
|
+
if (response.success) return;
|
|
2400
|
+
const errorCode = response.error?.code ?? "E_GENERAL";
|
|
2401
|
+
const exitCode = response.error?.exitCode ?? ERROR_CODE_TO_EXIT[errorCode] ?? 1;
|
|
2402
|
+
cliError(
|
|
2403
|
+
response.error?.message ?? "Unknown error",
|
|
2404
|
+
exitCode,
|
|
2405
|
+
{
|
|
2406
|
+
name: errorCode,
|
|
2407
|
+
details: response.error?.details,
|
|
2408
|
+
fix: response.error?.fix,
|
|
2409
|
+
alternatives: response.error?.alternatives
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
operation: _opts.operation,
|
|
2413
|
+
requestId: response.meta.requestId,
|
|
2414
|
+
duration_ms: response.meta.duration_ms,
|
|
2415
|
+
timestamp: response.meta.timestamp,
|
|
2416
|
+
...response.meta.sessionId ? { sessionId: response.meta.sessionId } : {},
|
|
2417
|
+
...response.meta.originSessionId ? { originSessionId: response.meta.originSessionId } : {},
|
|
2418
|
+
...response.meta.executionSessionId ? { executionSessionId: response.meta.executionSessionId } : {}
|
|
2419
|
+
}
|
|
2420
|
+
);
|
|
2421
|
+
process.exit(exitCode);
|
|
2422
|
+
}
|
|
2423
|
+
async function dispatchRaw(gateway, domain, operation, params) {
|
|
2424
|
+
await prepareCoreFor(gateway, domain, operation);
|
|
2425
|
+
const dispatcher = getCliDispatcher();
|
|
2426
|
+
const projectRoot = getProjectRoot();
|
|
2427
|
+
const dispatchStart = Date.now();
|
|
2428
|
+
void trackBackgroundOp(
|
|
2429
|
+
hooks.dispatch("PromptSubmit", projectRoot, {
|
|
2430
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2431
|
+
gateway,
|
|
2432
|
+
domain,
|
|
2433
|
+
operation,
|
|
2434
|
+
source: "cli"
|
|
2435
|
+
}).catch(() => {
|
|
2436
|
+
})
|
|
2437
|
+
);
|
|
2438
|
+
const spinner = createDispatchSpinner(domain, operation);
|
|
2439
|
+
spinner.start();
|
|
2440
|
+
let response;
|
|
2441
|
+
const mergedParams = mergeIdempotencyParam(gateway, params);
|
|
2442
|
+
try {
|
|
2443
|
+
response = await dispatcher.dispatch({
|
|
2444
|
+
gateway,
|
|
2445
|
+
domain,
|
|
2446
|
+
operation,
|
|
2447
|
+
params: mergedParams,
|
|
2448
|
+
source: "cli",
|
|
2449
|
+
requestId: randomUUID2()
|
|
2450
|
+
});
|
|
2451
|
+
} finally {
|
|
2452
|
+
spinner.stop();
|
|
2453
|
+
}
|
|
2454
|
+
void trackBackgroundOp(
|
|
2455
|
+
hooks.dispatch("ResponseComplete", projectRoot, {
|
|
2456
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2457
|
+
gateway,
|
|
2458
|
+
domain,
|
|
2459
|
+
operation,
|
|
2460
|
+
success: response.success,
|
|
2461
|
+
durationMs: Date.now() - dispatchStart,
|
|
2462
|
+
errorCode: response.error?.code
|
|
2463
|
+
}).catch(() => {
|
|
2464
|
+
})
|
|
2465
|
+
);
|
|
2466
|
+
if (!response.success) {
|
|
2467
|
+
const { settleBeforeExit } = await import("@cleocode/core/shutdown");
|
|
2468
|
+
await settleBeforeExit();
|
|
2469
|
+
}
|
|
2470
|
+
return response;
|
|
2471
|
+
}
|
|
2472
|
+
function mergeIdempotencyParam(gateway, params) {
|
|
2473
|
+
if (gateway !== "mutate") return params;
|
|
2474
|
+
const idempotencyKey = getIdempotencyKeyContext();
|
|
2475
|
+
if (!idempotencyKey || params?.["idempotencyKey"] !== void 0) return params;
|
|
2476
|
+
return { ...params ?? {}, idempotencyKey };
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
export {
|
|
2480
|
+
createAnimateContext,
|
|
2481
|
+
renderLegend,
|
|
2482
|
+
renderSummary,
|
|
2483
|
+
renderTree,
|
|
2484
|
+
prepareCoreFor,
|
|
2485
|
+
getCliDispatcher,
|
|
2486
|
+
createCliGatewayHandler,
|
|
2487
|
+
lookupCliSession,
|
|
2488
|
+
heartbeatCliSession,
|
|
2489
|
+
warnUnboundMutation,
|
|
2490
|
+
createCliDispatcher,
|
|
2491
|
+
resetCliDispatcher,
|
|
2492
|
+
maybeEmitDescribe,
|
|
2493
|
+
dispatchFromCli,
|
|
2494
|
+
handleRawError,
|
|
2495
|
+
dispatchRaw
|
|
2496
|
+
};
|
|
2497
|
+
//# sourceMappingURL=chunk-L7ONYSV6.js.map
|