chainlesschain 0.165.8 → 0.165.9

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.
Files changed (169) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-B3gWmXjo.js → AIOps-DxwjrnEA.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-G9pdT-0e.js → ActionButton-JdbYowzn.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Ca30J7m2.js → Analytics-C06GCahv.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BtVTm8PU.js → AppLayout-BUVEEyi1.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-BhViNa6u.js → Artifacts-D_ORzkJd.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-DhKq-FnY.js → Audit-8o_Y5ejG.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BL0SVbnE.js → BackgroundAgents-DrkHd5VU.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-BWkblnFi.js → Backup-CKBZCX11.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-ClaRNrF8.js → BaseInput-C8HkI399.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-sZE2Z77o.js → Chat-zb2H2Wux.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BAfKOnRe.js → ChatBubbleRenderer-BDcNpU_F.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-Cvhay5WM.js → Checkbox-MwPtQmNz.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BpejL-4N.js → Codegen-3p5QCkFK.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-g2Ki6g_1.js → Col-BPLlhn52.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-D2xKbNo9.js → Community-C-3dBNOM.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-DbL1Pds3.js → Compact-BUcy-F_b.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DGtZCV4c.js → Compliance-CI8NxT8m.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-4kQpoNsI.js → Cowork-DaDEBS-Q.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-BxTYXXAN.js → Cron-BSv9HXu5.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-k0J0LT2N.js → Crosschain-yuiKlJmv.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-BaqhoPgN.js → DID-D6LfldB0.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-T4RVPIM1.js → Dashboard-CBhLqG61.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-DszOToWq.js → Dropdown-BG8pIl3O.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-C9KJU7HF.js → EmailListRenderer-CY92VIE6.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Cmr0JnsA.js → FamilyGuardDashboard-1Q_ehauM.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BI-_2xZX.js → Federation-D3XirJIU.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-DsnDEPsl.js → FormItemContext-DfI9UuGZ.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-BLncAKKK.js → GenericCardRenderer-IeCZk2m7.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-BPQhGXDn.js → Git-DzK4IJAZ.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CyElbUQW.js → Governance-BHf5KfmQ.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CcSntBQD.js → Inference-BmaxSALS.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-p6e7HZ2r.js → KnowledgeGraph-BgePFLA9.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-CNEtr-wz.js → Logs-nqgxpOc4.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-xkX6izBt.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-Dd2notAJ.js → Marketplace-Bu8to-86.js} +1 -1
  38. package/src/assets/web-panel/assets/McpTools-BFWTzEk0.js +4 -0
  39. package/src/assets/web-panel/assets/{Memory-Dg2uTvwx.js → Memory-B026G2GA.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-r1YMRiJV.js → MobileBridge-CM2Eeg6I.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-C-89kSm4.js → MobileProjects-B79Ob3hy.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-CrPZcVgf.js → Mtc-CxevSZuV.js} +5 -5
  43. package/src/assets/web-panel/assets/{MtcAudit-sxi7hqJb.js → MtcAudit-X396cPEX.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-CAgOMfF1.js → Multisig-HWIB_aZ1.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-DafaPts3.js → NLProgramming-gnYD1Xwy.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-CJM-xUW_.js → Notes-Dn2Gf_J1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-L0ZjfAh_.js → NotificationSettings-BRKBQ5rq.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-BB1CvCK0.js → OrderTableRenderer-Dy___Cgo.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-DeLtgAD8.js → Organization-cqfccxnt.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-CKC2b10z.js → Overflow-CSX4FHN3.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-eyf2rzY1.js → P2P-Bwa4aghp.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-5upNIOW8.js → PdhVaultBrowser-Dhszyjig.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-B8p3W6JK.js → Permissions-CXzTyk6e.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-BnRMxTq3.js → PersonalDataHub-CFCAAJbb.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-DjCNI1li.js → Pipeline-BPJbx6xt.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-u6gXLbWT.js → Privacy-BbiXvEHz.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BZAw4tkM.js → ProjectInit-B-s7-wSD.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-B1Tr72q7.js → ProjectSettings-Dyug206y.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-DO7HFuBQ.js → Projects-BtAI5Fwo.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-BjCztyhj.js → Providers-JpIPmz6N.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-ZWyCUbR1.js → QrScannerModal-CZdoN64A.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-DhDjeW4G.js → QuickAsk-BwvnoRIT.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-R_CN2MuU.js → Recommend-ASMlMQrD.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-uxFcujeu.js → RemoteSession-BiJzKFKi.js} +3 -3
  65. package/src/assets/web-panel/assets/{Reputation-DX8D7rks.js → Reputation-C80TWLIO.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-BYahQILD.js → Row-C1VNmjmX.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CUSQ2tm-.js → RssFeed-T2MyGUlG.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-CnN_S8Cs.js → Search-DXM6O83L.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-DcZlh-O4.js → Security-nv69kU7W.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-ZhBOjzIX.js → Services-AyHWe7Qj.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-D5Qnq_lI.js → Skeleton-D6PWLxFI.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-BC9cZ3Be.js → Skills-BqVeOmNQ.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-DauJ3E8_.js → Sla-BegIPl9M.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-CKJn3xk-.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-DUvJbSct.js → SyncSettings-Th4cnAMl.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-BXa-5noQ.js → Tasks-BuKfBroh.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-JxaiUt_3.js → Templates-CMuWN8Ac.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-BW4ERQN8.js → Tenant-C4je8E8Q.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-DltUbdtv.js → Terminal-agJESOcO.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-CMoZz0Tc.js → TimelineRenderer-D2qDuVZ_.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-D_VEV60K.js → Tokens-Cvmn99rH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CCXTCs0R.js → Trigger-D_QYIHH8.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-lkGRIPcG.js → Trust-BmzvQLnX.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-BfGeQ9HX.js → UkeySign-D_LopHwH.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BEC7pYvc.js → VideoEditing-DoWl3PhQ.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BZdG24o0.js → Wallet-5NYcAkxe.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-yoEddedp.js → WebAuthn-B-_Q3ewp.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BXZEprOW.js → WorkflowEditor-CHET-gi2.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-gg0bzZal.js → chat-C6nvb-n6.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-DjRVRuin.js → colors-CTDE9LTX.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-su-dieAc.js → compact-item-KnemdF8D.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-Ci3S8oKF.js → createContext-DUJR3Uek.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-1DqLH1KX.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-D8F10heH.js → hasIn-CFNTaby8.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CusgZPtc.js → index-65HO56Bv.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BbF1IHof.js → index-B8RtbSkV.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CEmXRhAE.js → index-BHqSqnW7.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DIJ2qFOC.js → index-BTetEUWd.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CUmDhC4j.js → index-BXWg1crv.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DBAETXft.js → index-BdiC4LOs.js} +1 -1
  101. package/src/assets/web-panel/assets/index-BhJtcPWo.js +1 -0
  102. package/src/assets/web-panel/assets/{index-Tu8eWqh-.js → index-BuizJo2E.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BzPB6kGZ.js → index-BwZM1rod.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DkMEF5VT.js → index-C96N9xeL.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BTFpdBtt.js → index-CHfUdnJH.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DkfQR3hM.js → index-CKvBF3Ov.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-T6_6ygJZ.js → index-CSD9_I2_.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CR0h6seT.js → index-Cc7dbl_p.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dbq4NMET.js → index-CcF0D7UZ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C6ygzplr.js → index-Ceu92a8D.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-11wtYQiF.js → index-CnLpuTAU.js} +1 -1
  112. package/src/assets/web-panel/assets/index-Cq8MWPDT.js +1 -0
  113. package/src/assets/web-panel/assets/{index-1IgxgALJ.js → index-CquKnw5r.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CMPqd5Cv.js → index-CyEtHvEE.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BMMOVoLD.js → index-DF-fcTvQ.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-W7XUgdVL.js → index-DF1Y0Vuw.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DyLUarhZ.js → index-DJyPeBBk.js} +3 -3
  118. package/src/assets/web-panel/assets/{index-BDJntYmJ.js → index-DP-PbO11.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-COWd8uGx.js → index-DZgCRMxk.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-8Z-8BIlN.js → index-DfJzS3Qa.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-dHZinfko.js → index-DqPpJkte.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BCI5v0yB.js → index-DzReoLyh.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CPIYSp4H.js → index-JGTiDeOW.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-jyNgp5FI.js → index-NUR0If7O.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-6Tniqk1s.js → index-NtAcnJYW.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BgT9su_e.js → index-OmuhFYKE.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DugB_aKa.js → index-Wlc7o_C8.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Ba_HyPnE.js → index-bxTPfdri.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CC3ZDjzY.js → index-k6uorYmf.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-5JqhujnR.js → index-ox6mIwE2.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-1agckWSq.js → index-rVDD7AAR.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BGzixOGZ.js → index-u0h6QqVV.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DnLucOn9.js → index-v-mtxmWH.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-Cv4p8e4w.js → initDefaultProps-qEt8dI-t.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-B8EwmMOw.js → motion-DetKPWy-.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-B8R9F8TK.js → move-BeNYeDV2.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DoFYz5Bp.js → mtc-parser-C0q0MK_T.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-CHWYLBjI.js → omit-DLKkrKpE.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CXuPDO77.js → pickAttrs-Bw1tWsY8.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BaAtUUon.js → placementArrow-DeesBLbd.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-DCc4zcDD.js → responsiveObserve-bqLhxHhn.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-B_lx89oZ.js → slide-DGCXRoQm.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-DE8DPmR0.js → statusUtils-H-re3Egl.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-1ktXOsL_.js → styleChecker-BXg4qGX_.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-xH89-wjh.js → useFlexGapSupport-CKLb2KA6.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DscvfW5p.js → useFs-CTAhHeyw.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-RdMKQta7.js → usePersonalDataHub-BQ4pDh5g.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-Z3wTni2T.js → vnode-jrSK6j4j.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-B0iChCsm.js → zoom-fOQE24pw.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/data/changelog.json +13 -0
  152. package/src/gateways/ws/mcp-topic-handlers.js +167 -0
  153. package/src/lib/agent-network.js +166 -29
  154. package/src/lib/agent-router.js +62 -6
  155. package/src/lib/agent-sandbox.js +7 -1
  156. package/src/lib/claude-code-bridge.js +159 -54
  157. package/src/lib/cowork-workflow.js +69 -6
  158. package/src/lib/external-agent-adapters.js +269 -0
  159. package/src/lib/ipfs-storage.js +127 -25
  160. package/src/lib/orchestrator.js +47 -0
  161. package/src/lib/shell-approval.js +7 -5
  162. package/src/lib/workflow-engine.js +42 -11
  163. package/src/runtime/agent-runtime.js +12 -1
  164. package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +0 -1
  165. package/src/assets/web-panel/assets/McpTools-BBsN2CSW.js +0 -7
  166. package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +0 -1
  167. package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +0 -1
  168. package/src/assets/web-panel/assets/index-CJGOlduY.js +0 -1
  169. package/src/assets/web-panel/assets/index-CkBCN5yH.js +0 -1
@@ -14,7 +14,44 @@
14
14
  */
15
15
 
16
16
  import { EventEmitter } from "events";
17
+ import crypto from "crypto";
18
+ import runtimeClaimsContract from "@chainlesschain/session-core/runtime-claims";
17
19
  import executionBroker from "./process-execution-broker/index.js";
20
+ import {
21
+ createExternalAgentAdapter,
22
+ EXTERNAL_AGENT_ERROR,
23
+ } from "./external-agent-adapters.js";
24
+
25
+ const {
26
+ RUNTIME_MODE,
27
+ TERMINAL_EVIDENCE_KIND,
28
+ createRuntimeClaims,
29
+ hasTerminalSuccessEvidence,
30
+ } = runtimeClaimsContract;
31
+
32
+ const REAL_EXECUTION_CLAIMS = createRuntimeClaims({
33
+ mode: RUNTIME_MODE.REAL_EXECUTION,
34
+ durable: false,
35
+ crashSafe: false,
36
+ isolatedWrites: false,
37
+ });
38
+
39
+ const VALIDATION_ONLY_CLAIMS = createRuntimeClaims({
40
+ mode: RUNTIME_MODE.VALIDATE_ONLY,
41
+ });
42
+
43
+ function transcriptReceipt(rawOutput) {
44
+ return `sha256:${crypto.createHash("sha256").update(rawOutput).digest("hex")}`;
45
+ }
46
+
47
+ export {
48
+ ExternalAgentAdapter,
49
+ ClaudeAdapter,
50
+ CodexAdapter,
51
+ createExternalAgentAdapter,
52
+ EXTERNAL_AGENT_ERROR,
53
+ EXTERNAL_AGENT_PROTOCOL,
54
+ } from "./external-agent-adapters.js";
18
55
 
19
56
  /* ---------- _deps injection (Vitest CJS mock pattern) ---------- */
20
57
  export const _deps = {
@@ -30,6 +67,7 @@ export const AGENT_STATUS = {
30
67
  COMPLETED: "completed",
31
68
  FAILED: "failed",
32
69
  TIMEOUT: "timeout",
70
+ CANCELLED: "cancelled",
33
71
  };
34
72
 
35
73
  // Bound how much of a child's stdout/stderr we retain in memory. A verbose or
@@ -68,7 +106,7 @@ export function detectClaudeCode() {
68
106
  }
69
107
 
70
108
  /**
71
- * Check if the `codex` CLI (GitHub Copilot Coding Agent) is installed.
109
+ * Check if the OpenAI Codex CLI is installed.
72
110
  * Returns { found: boolean, version?: string }.
73
111
  */
74
112
  export function detectCodex() {
@@ -83,8 +121,9 @@ export function detectCodex() {
83
121
  // ─── Single Agent ─────────────────────────────────────────────────
84
122
 
85
123
  /**
86
- * A single Claude Code CLI execution agent.
87
- * Wraps `claude -p "<task>" --output-format stream-json` as a child process.
124
+ * A single external coding-agent CLI process. The historical class name is
125
+ * retained for API compatibility; provider-specific argv and JSONL parsing are
126
+ * delegated to ClaudeAdapter or CodexAdapter.
88
127
  */
89
128
  export class ClaudeCodeAgent extends EventEmitter {
90
129
  constructor(options = {}) {
@@ -94,9 +133,18 @@ export class ClaudeCodeAgent extends EventEmitter {
94
133
  `cc-agent-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
95
134
  this.cliCommand = options.cliCommand || "claude"; // "claude" or "codex"
96
135
  this.model = options.model || null;
136
+ this.sandbox = options.sandbox || null;
137
+ this.adapter =
138
+ options.adapter ||
139
+ createExternalAgentAdapter({
140
+ cliCommand: this.cliCommand,
141
+ model: this.model,
142
+ sandbox: this.sandbox,
143
+ });
97
144
  this.status = AGENT_STATUS.IDLE;
98
145
  this.currentTask = null;
99
146
  this._proc = null;
147
+ this._cancelRequested = false;
100
148
  }
101
149
 
102
150
  /**
@@ -128,14 +176,33 @@ export class ClaudeCodeAgent extends EventEmitter {
128
176
  this.currentTask = taskDescription;
129
177
  this.emit("task:start", { agentId: this.id, task: taskDescription });
130
178
 
131
- const args = ["-p", fullPrompt, "--output-format", "stream-json"];
132
- if (this.model) {
133
- args.push("--model", this.model);
134
- }
135
- if (allowedTools) {
136
- args.push("--allowedTools", allowedTools);
179
+ let args;
180
+ try {
181
+ args = this.adapter.buildArgs({ prompt: fullPrompt, allowedTools });
182
+ } catch (err) {
183
+ this.status = AGENT_STATUS.FAILED;
184
+ this.currentTask = null;
185
+ const result = {
186
+ success: false,
187
+ status: "validation-failed",
188
+ output: "",
189
+ exitCode: -1,
190
+ duration: 0,
191
+ timedOut: false,
192
+ cancelled: false,
193
+ agentId: this.id,
194
+ error: err.message,
195
+ errorCode: err.code || EXTERNAL_AGENT_ERROR.UNSUPPORTED_OPTION,
196
+ protocol: this.adapter.capabilities().protocol,
197
+ runtimeClaims: VALIDATION_ONLY_CLAIMS,
198
+ terminalEvidence: [],
199
+ };
200
+ this.emit("task:complete", result);
201
+ return result;
137
202
  }
138
203
 
204
+ this._cancelRequested = false;
205
+
139
206
  return new Promise((resolve) => {
140
207
  const startTime = Date.now();
141
208
  const outputChunks = [];
@@ -160,7 +227,7 @@ export class ClaudeCodeAgent extends EventEmitter {
160
227
  return bytes;
161
228
  };
162
229
 
163
- const proc = _deps.spawn(this.cliCommand, args, {
230
+ const proc = _deps.spawn(this.adapter.command, args, {
164
231
  cwd,
165
232
  env: { ...process.env },
166
233
  windowsHide: true,
@@ -220,28 +287,93 @@ export class ClaudeCodeAgent extends EventEmitter {
220
287
  this._proc = null;
221
288
  const duration = Date.now() - startTime;
222
289
  const rawOutput = outputChunks.join("");
290
+ const cancelled = this._cancelRequested && !timedOut;
291
+ const projection = this.adapter.parseTranscript(rawOutput);
292
+ const missingTerminal =
293
+ this.adapter.capabilities().requiresTerminalEvent &&
294
+ projection.terminal === null;
295
+ const protocolFailed =
296
+ projection.terminal === "failed" || missingTerminal;
223
297
  const status = timedOut
224
298
  ? AGENT_STATUS.TIMEOUT
225
- : code === 0
226
- ? AGENT_STATUS.COMPLETED
227
- : AGENT_STATUS.FAILED;
299
+ : cancelled
300
+ ? AGENT_STATUS.CANCELLED
301
+ : protocolFailed
302
+ ? AGENT_STATUS.FAILED
303
+ : code === 0
304
+ ? AGENT_STATUS.COMPLETED
305
+ : AGENT_STATUS.FAILED;
228
306
 
229
307
  this.status = status;
230
308
  this.currentTask = null;
231
309
 
232
- // Parse stream-json output: last assistant message is the result
233
- const parsedOutput = _parseStreamJson(rawOutput);
310
+ const terminalEvidence = [
311
+ ...(projection.terminal
312
+ ? [
313
+ {
314
+ kind: TERMINAL_EVIDENCE_KIND.RUNTIME_EVENT,
315
+ outcome: projection.terminal,
316
+ source: this.adapter.capabilities().protocol,
317
+ },
318
+ ]
319
+ : []),
320
+ ...(rawOutput
321
+ ? [
322
+ {
323
+ kind: TERMINAL_EVIDENCE_KIND.OUTPUT_RECEIPT,
324
+ digest: transcriptReceipt(rawOutput),
325
+ },
326
+ ]
327
+ : []),
328
+ ];
329
+ const success =
330
+ code === 0 &&
331
+ !timedOut &&
332
+ !cancelled &&
333
+ !protocolFailed &&
334
+ hasTerminalSuccessEvidence(REAL_EXECUTION_CLAIMS, terminalEvidence);
335
+ const errorCode = timedOut
336
+ ? EXTERNAL_AGENT_ERROR.TIMEOUT
337
+ : cancelled
338
+ ? EXTERNAL_AGENT_ERROR.CANCELLED
339
+ : code !== 0
340
+ ? EXTERNAL_AGENT_ERROR.EXIT_NONZERO
341
+ : protocolFailed
342
+ ? EXTERNAL_AGENT_ERROR.PROTOCOL_FAILED
343
+ : null;
234
344
 
235
345
  const result = {
236
- success: code === 0 && !timedOut,
237
- output: parsedOutput || rawOutput.slice(-4000), // last 4K chars fallback
346
+ success,
347
+ status: success ? "completed" : status,
348
+ output: projection.output || rawOutput.slice(-4000),
238
349
  rawOutput,
239
350
  outputTruncated, // true when the child exceeded maxOutputBytes
240
351
  exitCode: code,
241
352
  duration,
242
353
  timedOut,
354
+ cancelled,
243
355
  agentId: this.id,
244
356
  stderr: errorChunks.join("").slice(-2000),
357
+ error: success
358
+ ? undefined
359
+ : projection.error ||
360
+ (missingTerminal
361
+ ? "External agent JSONL stream ended without a terminal event"
362
+ : null) ||
363
+ (timedOut
364
+ ? "External agent timed out"
365
+ : cancelled
366
+ ? "External agent was cancelled"
367
+ : `External agent exited with code ${code}`),
368
+ errorCode,
369
+ protocol: this.adapter.capabilities().protocol,
370
+ terminalEvent: projection.terminal,
371
+ usage: projection.usage,
372
+ unknownEventTypes: projection.unknownEventTypes,
373
+ unknownItemTypes: projection.unknownItemTypes,
374
+ malformedLineCount: projection.malformedLineCount,
375
+ runtimeClaims: REAL_EXECUTION_CLAIMS,
376
+ terminalEvidence,
245
377
  };
246
378
 
247
379
  this.emit("task:complete", result);
@@ -256,12 +388,18 @@ export class ClaudeCodeAgent extends EventEmitter {
256
388
  this.currentTask = null;
257
389
  const result = {
258
390
  success: false,
391
+ status: "failed",
259
392
  output: "",
260
393
  exitCode: -1,
261
394
  duration: Date.now() - startTime,
262
395
  timedOut: false,
396
+ cancelled: false,
263
397
  agentId: this.id,
264
398
  error: err.message,
399
+ errorCode: EXTERNAL_AGENT_ERROR.SPAWN_FAILED,
400
+ protocol: this.adapter.capabilities().protocol,
401
+ runtimeClaims: REAL_EXECUTION_CLAIMS,
402
+ terminalEvidence: [],
265
403
  };
266
404
  this.emit("task:complete", result);
267
405
  resolve(result);
@@ -272,6 +410,7 @@ export class ClaudeCodeAgent extends EventEmitter {
272
410
  /** Abort the currently running task. */
273
411
  abort() {
274
412
  if (this._proc) {
413
+ this._cancelRequested = true;
275
414
  this._proc.kill("SIGTERM");
276
415
  }
277
416
  }
@@ -281,6 +420,7 @@ export class ClaudeCodeAgent extends EventEmitter {
281
420
  id: this.id,
282
421
  status: this.status,
283
422
  cliCommand: this.cliCommand,
423
+ protocol: this.adapter.capabilities().protocol,
284
424
  currentTask: this.currentTask,
285
425
  };
286
426
  }
@@ -304,6 +444,7 @@ export class ClaudeCodePool extends EventEmitter {
304
444
  this.maxParallel = options.maxParallel || 3;
305
445
  this.cliCommand = options.cliCommand || "claude";
306
446
  this.model = options.model || null;
447
+ this.sandbox = options.sandbox || null;
307
448
  this.agentTimeout = options.agentTimeout || 300_000;
308
449
 
309
450
  // Bound retained completion history. dispatch() returns results directly,
@@ -359,6 +500,7 @@ export class ClaudeCodePool extends EventEmitter {
359
500
  id: `agent-${task.id}`,
360
501
  cliCommand: this.cliCommand,
361
502
  model: this.model,
503
+ sandbox: this.sandbox,
362
504
  });
363
505
 
364
506
  this._agents.set(agent.id, agent);
@@ -400,43 +542,6 @@ export class ClaudeCodePool extends EventEmitter {
400
542
  }
401
543
  }
402
544
 
403
- // ─── Helpers ──────────────────────────────────────────────────────
404
-
405
- /**
406
- * Parse Claude Code stream-json output and extract the last assistant text.
407
- * Stream-json lines look like: {"type":"assistant","message":{...}}
408
- */
409
- function _parseStreamJson(raw) {
410
- if (!raw) return "";
411
- const lines = raw.split("\n").filter(Boolean);
412
- let lastText = "";
413
-
414
- for (const line of lines) {
415
- try {
416
- const obj = JSON.parse(line);
417
- // stream-json: result message has type "result"
418
- if (obj.type === "result" && obj.result) {
419
- return typeof obj.result === "string"
420
- ? obj.result
421
- : JSON.stringify(obj.result);
422
- }
423
- // assistant message blocks
424
- if (obj.type === "assistant" && obj.message?.content) {
425
- const blocks = obj.message.content;
426
- const textBlocks = blocks
427
- .filter((b) => b.type === "text")
428
- .map((b) => b.text)
429
- .join("\n");
430
- if (textBlocks) lastText = textBlocks;
431
- }
432
- } catch (_err) {
433
- // Non-JSON line (progress text) — ignore
434
- }
435
- }
436
-
437
- return lastText;
438
- }
439
-
440
545
  // =====================================================================
441
546
  // claude-code-bridge V2 governance overlay (iter17)
442
547
  // =====================================================================
@@ -131,6 +131,9 @@ const ADMITTED_STEP_STATUSES = new Set([
131
131
  "failed",
132
132
  "partial",
133
133
  "skipped",
134
+ "exhausted",
135
+ "upstream_failed",
136
+ "cancelled",
134
137
  ]);
135
138
  const MAX_ADMITTED_RUN_STEPS = 64;
136
139
  const MAX_ADMITTED_SNAPSHOT_NODES = 25_000;
@@ -948,6 +951,23 @@ export function validateWorkflow(wf) {
948
951
  errors.push(`steps[${i}].maxIterations must be a positive integer`);
949
952
  }
950
953
  }
954
+ // forEach expands `stepId` into concrete runtime ids such as
955
+ // `stepId[0]`. A declarative step with the same id would overwrite the
956
+ // child result and make dependency/evidence accounting ambiguous.
957
+ for (const parent of wf.steps) {
958
+ if (parent?.forEach === undefined || typeof parent.id !== "string") {
959
+ continue;
960
+ }
961
+ const escapedParentId = parent.id.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
962
+ const childIdPattern = new RegExp(`^${escapedParentId}\\[\\d+\\]$`, "u");
963
+ for (const id of ids) {
964
+ if (childIdPattern.test(id)) {
965
+ errors.push(
966
+ `step id '${id}' collides with dynamic children of '${parent.id}'`,
967
+ );
968
+ }
969
+ }
970
+ }
951
971
  // Check dependsOn references exist
952
972
  for (const s of wf.steps) {
953
973
  for (const dep of s.dependsOn || []) {
@@ -1682,7 +1702,7 @@ export async function runLoopStep({
1682
1702
  }
1683
1703
  const outcome = {
1684
1704
  id: recordId,
1685
- status: last ? last.status : "skipped",
1705
+ status: stopReason === "cap" ? "exhausted" : last ? last.status : "skipped",
1686
1706
  taskId: last?.taskId ?? null,
1687
1707
  result: {
1688
1708
  ...(last?.result || {}),
@@ -1694,6 +1714,35 @@ export async function runLoopStep({
1694
1714
  return admitted ? normalizeAdmittedOutcome(outcome) : outcome;
1695
1715
  }
1696
1716
 
1717
+ function dependencyBlock(step, resultsById) {
1718
+ const blocked = (step.dependsOn || [])
1719
+ .map((id) => resultsById.get(id))
1720
+ .filter((outcome) => outcome && outcome.status !== "completed");
1721
+ if (blocked.length === 0) return null;
1722
+
1723
+ const blockedRootCut = [
1724
+ ...new Set(
1725
+ blocked.flatMap((outcome) =>
1726
+ Array.isArray(outcome.result?.blockedRootCut)
1727
+ ? outcome.result.blockedRootCut
1728
+ : [outcome.id],
1729
+ ),
1730
+ ),
1731
+ ];
1732
+ const allSkipped = blocked.every((outcome) => outcome.status === "skipped");
1733
+ return {
1734
+ id: step.id,
1735
+ status: allSkipped ? "skipped" : "upstream_failed",
1736
+ taskId: null,
1737
+ result: {
1738
+ summary: allSkipped
1739
+ ? "skipped because an upstream dependency was skipped"
1740
+ : "blocked by an unsuccessful upstream dependency",
1741
+ blockedRootCut,
1742
+ },
1743
+ };
1744
+ }
1745
+
1697
1746
  // ─── Step node + no-barrier pipeline ──────────────────────────────────────────
1698
1747
 
1699
1748
  /**
@@ -1726,6 +1775,12 @@ export async function runStepNode(step, ctx) {
1726
1775
  };
1727
1776
  };
1728
1777
 
1778
+ const blocked = dependencyBlock(step, resultsById);
1779
+ if (blocked) {
1780
+ resultsById.set(recordId, blocked);
1781
+ return { outcomes: [blocked], failed: blocked.status !== "skipped" };
1782
+ }
1783
+
1729
1784
  let runThis;
1730
1785
  try {
1731
1786
  runThis = shouldRunStep(step, resultsById);
@@ -1834,9 +1889,10 @@ export async function runStepNode(step, ctx) {
1834
1889
  * No-barrier pipeline scheduler: start each step the instant *its own*
1835
1890
  * dependencies finish, rather than waiting for the whole dependency level.
1836
1891
  * Up to `maxParallel` step nodes run concurrently. On failure with
1837
- * `continueOnError` off, no new steps are scheduled (in-flight ones finish) and
1838
- * the rest are marked skipped. Produces the same outcome set as the batch
1839
- * executor — only the wall-clock idle between levels is removed.
1892
+ * `continueOnError` off, no new steps are scheduled (in-flight ones finish).
1893
+ * Unscheduled descendants receive the same dependency-derived terminal state
1894
+ * as the batch executor; unrelated work is marked skipped. Only the wall-clock
1895
+ * idle between levels differs.
1840
1896
  */
1841
1897
  export async function runPipeline({
1842
1898
  steps,
@@ -1886,9 +1942,9 @@ export async function runPipeline({
1886
1942
  reject(fatalError);
1887
1943
  return;
1888
1944
  }
1889
- for (const s of steps) {
1945
+ for (const s of topoSort(steps)) {
1890
1946
  if (scheduled.has(s.id)) continue;
1891
- const o = {
1947
+ const o = dependencyBlock(s, resultsById) || {
1892
1948
  id: s.id,
1893
1949
  status: "skipped",
1894
1950
  taskId: null,
@@ -2196,6 +2252,13 @@ export async function executeWorkflow(options = {}) {
2196
2252
  const runnable = []; // { step, message, recordId, parentId }
2197
2253
  const preOutcomes = []; // outcomes produced synchronously (skipped)
2198
2254
  for (const step of chunk) {
2255
+ const blocked = dependencyBlock(step, resultsById);
2256
+ if (blocked) {
2257
+ if (blocked.status !== "skipped") anyFailure = true;
2258
+ resultsById.set(step.id, blocked);
2259
+ preOutcomes.push(blocked);
2260
+ continue;
2261
+ }
2199
2262
  if (anyFailure && !continueOnError) {
2200
2263
  const outcome = {
2201
2264
  id: step.id,