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
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Provider-specific contracts for non-interactive coding-agent CLIs.
3
+ *
4
+ * Keep argv construction and JSONL parsing here instead of assuming that two
5
+ * CLIs with similar product goals expose the same wire protocol.
6
+ */
7
+
8
+ export const EXTERNAL_AGENT_PROTOCOL = Object.freeze({
9
+ CLAUDE_STREAM_JSON: "claude-stream-json-v1",
10
+ CODEX_EXEC_JSONL: "codex-exec-jsonl-v1",
11
+ });
12
+
13
+ export const EXTERNAL_AGENT_ERROR = Object.freeze({
14
+ CANCELLED: "EXTERNAL_AGENT_CANCELLED",
15
+ TIMEOUT: "EXTERNAL_AGENT_TIMEOUT",
16
+ EXIT_NONZERO: "EXTERNAL_AGENT_EXIT_NONZERO",
17
+ SPAWN_FAILED: "EXTERNAL_AGENT_SPAWN_FAILED",
18
+ PROTOCOL_FAILED: "EXTERNAL_AGENT_PROTOCOL_FAILED",
19
+ UNSUPPORTED_OPTION: "EXTERNAL_AGENT_UNSUPPORTED_OPTION",
20
+ });
21
+
22
+ const KNOWN_CODEX_ITEM_TYPES = new Set([
23
+ "agent_message",
24
+ "reasoning",
25
+ "command_execution",
26
+ "file_change",
27
+ "mcp_tool_call",
28
+ "web_search",
29
+ "plan_update",
30
+ ]);
31
+
32
+ function stringifyValue(value) {
33
+ return typeof value === "string" ? value : JSON.stringify(value);
34
+ }
35
+
36
+ function errorMessage(value, fallback) {
37
+ if (typeof value === "string" && value) return value;
38
+ if (value && typeof value.message === "string" && value.message) {
39
+ return value.message;
40
+ }
41
+ return fallback;
42
+ }
43
+
44
+ /**
45
+ * Common adapter surface. Subclasses provide buildArgs() and parseEvent().
46
+ */
47
+ export class ExternalAgentAdapter {
48
+ constructor(options = {}) {
49
+ this.command = options.command;
50
+ this.model = options.model || null;
51
+ }
52
+
53
+ capabilities() {
54
+ return Object.freeze({
55
+ protocol: "unknown",
56
+ jsonl: false,
57
+ modelOverride: false,
58
+ allowedTools: false,
59
+ requiresTerminalEvent: false,
60
+ });
61
+ }
62
+
63
+ buildArgs() {
64
+ throw new Error("ExternalAgentAdapter.buildArgs() must be implemented");
65
+ }
66
+
67
+ parseEvent() {
68
+ throw new Error("ExternalAgentAdapter.parseEvent() must be implemented");
69
+ }
70
+
71
+ /**
72
+ * Reduce a JSONL transcript into a provider-neutral terminal projection.
73
+ * Unknown additive events are retained for diagnostics but do not make a
74
+ * successful run fail.
75
+ */
76
+ parseTranscript(raw) {
77
+ const lines = String(raw || "")
78
+ .split(/\r?\n/)
79
+ .filter((line) => line.trim().length > 0);
80
+ const projection = {
81
+ output: "",
82
+ terminal: null,
83
+ error: null,
84
+ parsedEventCount: 0,
85
+ malformedLineCount: 0,
86
+ unknownEventTypes: [],
87
+ unknownItemTypes: [],
88
+ usage: null,
89
+ };
90
+ const unknownEvents = new Set();
91
+ const unknownItems = new Set();
92
+
93
+ for (const line of lines) {
94
+ let event;
95
+ try {
96
+ event = JSON.parse(line);
97
+ projection.parsedEventCount += 1;
98
+ } catch (_err) {
99
+ projection.malformedLineCount += 1;
100
+ continue;
101
+ }
102
+
103
+ const normalized = this.parseEvent(event);
104
+ if (normalized.output) projection.output = normalized.output;
105
+ if (normalized.terminal) projection.terminal = normalized.terminal;
106
+ if (normalized.error) projection.error = normalized.error;
107
+ if (normalized.usage) projection.usage = normalized.usage;
108
+ if (normalized.unknownEventType) {
109
+ unknownEvents.add(normalized.unknownEventType);
110
+ }
111
+ if (normalized.unknownItemType) {
112
+ unknownItems.add(normalized.unknownItemType);
113
+ }
114
+ }
115
+
116
+ projection.unknownEventTypes = [...unknownEvents];
117
+ projection.unknownItemTypes = [...unknownItems];
118
+ return projection;
119
+ }
120
+ }
121
+
122
+ export class ClaudeAdapter extends ExternalAgentAdapter {
123
+ constructor(options = {}) {
124
+ super({ ...options, command: options.command || "claude" });
125
+ }
126
+
127
+ capabilities() {
128
+ return Object.freeze({
129
+ protocol: EXTERNAL_AGENT_PROTOCOL.CLAUDE_STREAM_JSON,
130
+ jsonl: true,
131
+ modelOverride: true,
132
+ allowedTools: true,
133
+ requiresTerminalEvent: true,
134
+ });
135
+ }
136
+
137
+ buildArgs({ prompt, allowedTools = null } = {}) {
138
+ const args = ["-p", String(prompt || ""), "--output-format", "stream-json"];
139
+ if (this.model) args.push("--model", this.model);
140
+ if (allowedTools) args.push("--allowedTools", allowedTools);
141
+ return args;
142
+ }
143
+
144
+ parseEvent(event) {
145
+ if (!event || typeof event !== "object") {
146
+ return { unknownEventType: "<non-object>" };
147
+ }
148
+
149
+ if (event.type === "result") {
150
+ const failed = event.is_error === true || event.subtype === "error";
151
+ return {
152
+ output: event.result ? stringifyValue(event.result) : "",
153
+ terminal: failed ? "failed" : "completed",
154
+ error: failed
155
+ ? errorMessage(event.error || event.result, "Claude Code turn failed")
156
+ : null,
157
+ usage: event.usage || null,
158
+ };
159
+ }
160
+
161
+ if (event.type === "assistant" && Array.isArray(event.message?.content)) {
162
+ const output = event.message.content
163
+ .filter((block) => block?.type === "text")
164
+ .map((block) => block.text)
165
+ .filter(Boolean)
166
+ .join("\n");
167
+ return { output };
168
+ }
169
+
170
+ // These are progress/input events in Claude Code stream-json.
171
+ if (["system", "user", "rate_limit_event"].includes(event.type)) {
172
+ return {};
173
+ }
174
+ return { unknownEventType: String(event.type || "<missing>") };
175
+ }
176
+ }
177
+
178
+ export class CodexAdapter extends ExternalAgentAdapter {
179
+ constructor(options = {}) {
180
+ super({ ...options, command: options.command || "codex" });
181
+ this.sandbox = options.sandbox || null;
182
+ }
183
+
184
+ capabilities() {
185
+ return Object.freeze({
186
+ protocol: EXTERNAL_AGENT_PROTOCOL.CODEX_EXEC_JSONL,
187
+ jsonl: true,
188
+ modelOverride: true,
189
+ allowedTools: false,
190
+ requiresTerminalEvent: true,
191
+ sandboxModes: ["read-only", "workspace-write", "danger-full-access"],
192
+ });
193
+ }
194
+
195
+ buildArgs({ prompt, allowedTools = null } = {}) {
196
+ if (allowedTools) {
197
+ const err = new Error(
198
+ "Codex CLI does not expose Claude Code's --allowedTools option",
199
+ );
200
+ err.code = EXTERNAL_AGENT_ERROR.UNSUPPORTED_OPTION;
201
+ throw err;
202
+ }
203
+
204
+ const args = ["exec", "--json"];
205
+ if (this.model) args.push("--model", this.model);
206
+ if (this.sandbox) args.push("--sandbox", this.sandbox);
207
+ args.push(String(prompt || ""));
208
+ return args;
209
+ }
210
+
211
+ parseEvent(event) {
212
+ if (!event || typeof event !== "object") {
213
+ return { unknownEventType: "<non-object>" };
214
+ }
215
+
216
+ switch (event.type) {
217
+ case "thread.started":
218
+ case "turn.started":
219
+ return {};
220
+ case "turn.completed":
221
+ return {
222
+ terminal: "completed",
223
+ usage: event.usage || null,
224
+ };
225
+ case "turn.failed":
226
+ return {
227
+ terminal: "failed",
228
+ error: errorMessage(event.error, "Codex turn failed"),
229
+ };
230
+ case "error":
231
+ return {
232
+ terminal: "failed",
233
+ error: errorMessage(event.error || event, "Codex emitted an error"),
234
+ };
235
+ case "item.started":
236
+ case "item.updated":
237
+ case "item.completed": {
238
+ const itemType = event.item?.type;
239
+ const unknownItemType =
240
+ itemType && !KNOWN_CODEX_ITEM_TYPES.has(itemType)
241
+ ? String(itemType)
242
+ : null;
243
+ const output =
244
+ event.type === "item.completed" &&
245
+ itemType === "agent_message" &&
246
+ typeof event.item?.text === "string"
247
+ ? event.item.text
248
+ : "";
249
+ return { output, unknownItemType };
250
+ }
251
+ default:
252
+ return { unknownEventType: String(event.type || "<missing>") };
253
+ }
254
+ }
255
+ }
256
+
257
+ export function createExternalAgentAdapter(options = {}) {
258
+ const command = options.command || options.cliCommand || "claude";
259
+ if (command === "codex" || /(^|[\\/])codex(?:\.cmd|\.exe)?$/i.test(command)) {
260
+ return new CodexAdapter({ ...options, command });
261
+ }
262
+ if (
263
+ command === "claude" ||
264
+ /(^|[\\/])claude(?:\.cmd|\.exe)?$/i.test(command)
265
+ ) {
266
+ return new ClaudeAdapter({ ...options, command });
267
+ }
268
+ throw new Error(`Unsupported external agent CLI: ${command}`);
269
+ }
@@ -21,6 +21,35 @@
21
21
  */
22
22
 
23
23
  import crypto from "crypto";
24
+ import { createSecretStore } from "./secret-store.js";
25
+
26
+ let configuredIpfsSecretStore = null;
27
+
28
+ export function setIpfsSecretStore(secretStore) {
29
+ if (
30
+ !secretStore ||
31
+ typeof secretStore.set !== "function" ||
32
+ typeof secretStore.get !== "function" ||
33
+ typeof secretStore.delete !== "function"
34
+ ) {
35
+ throw new TypeError("IPFS storage requires a SecretStore");
36
+ }
37
+ configuredIpfsSecretStore = secretStore;
38
+ }
39
+
40
+ function getIpfsSecretStore() {
41
+ if (!configuredIpfsSecretStore) {
42
+ configuredIpfsSecretStore = createSecretStore({
43
+ service: "chainlesschain-ipfs-dek",
44
+ });
45
+ }
46
+ return configuredIpfsSecretStore;
47
+ }
48
+
49
+ function _encryptionKeyRef(cid) {
50
+ const digest = crypto.createHash("sha256").update(cid).digest("hex");
51
+ return `ipfs/dek/${digest}`;
52
+ }
24
53
 
25
54
  /* ── Constants ──────────────────────────────────────────── */
26
55
 
@@ -91,7 +120,8 @@ export function ensureIpfsTables(db) {
91
120
  mime_type TEXT,
92
121
  pinned INTEGER DEFAULT 0,
93
122
  encrypted INTEGER DEFAULT 0,
94
- encryption_key TEXT,
123
+ encryption_key TEXT DEFAULT '',
124
+ encryption_key_ref TEXT,
95
125
  knowledge_id TEXT,
96
126
  metadata TEXT,
97
127
  payload TEXT,
@@ -105,9 +135,63 @@ export function ensureIpfsTables(db) {
105
135
  updated_at INTEGER NOT NULL
106
136
  )`);
107
137
 
138
+ const columns = db.prepare("PRAGMA table_info(ipfs_content)").all();
139
+ if (
140
+ columns.length > 0 &&
141
+ !columns.some((entry) => entry.name === "encryption_key_ref")
142
+ ) {
143
+ db.exec("ALTER TABLE ipfs_content ADD COLUMN encryption_key_ref TEXT");
144
+ }
145
+
146
+ migrateIpfsEncryptionKeys(db);
147
+
108
148
  _loadAll(db);
109
149
  }
110
150
 
151
+ export function migrateIpfsEncryptionKeys(db, { dryRun = false } = {}) {
152
+ db.exec("PRAGMA secure_delete = ON");
153
+ const rows = db
154
+ .prepare("SELECT cid, encryption_key, encryption_key_ref FROM ipfs_content")
155
+ .all()
156
+ .filter((row) => row.encryption_key && !row.encryption_key_ref);
157
+ if (dryRun) {
158
+ return { pending: rows.length, migrated: 0, dryRun: true };
159
+ }
160
+
161
+ if (rows.length > 0 && typeof db.transaction !== "function") {
162
+ throw new Error(
163
+ "IPFS data-key migration requires transactional database support",
164
+ );
165
+ }
166
+
167
+ const secretStore = rows.length > 0 ? getIpfsSecretStore() : null;
168
+ const stagedKeyRefs = [];
169
+ try {
170
+ for (const row of rows) {
171
+ const keyRef = _encryptionKeyRef(row.cid);
172
+ secretStore.set(keyRef, row.encryption_key);
173
+ stagedKeyRefs.push(keyRef);
174
+ }
175
+ const applyMigration = db.transaction(() => {
176
+ for (const row of rows) {
177
+ const keyRef = _encryptionKeyRef(row.cid);
178
+ db.prepare(
179
+ "UPDATE ipfs_content SET encryption_key = ?, encryption_key_ref = ? WHERE cid = ?",
180
+ ).run("", keyRef, row.cid);
181
+ }
182
+ });
183
+ applyMigration();
184
+ } catch (error) {
185
+ for (const keyRef of stagedKeyRefs) secretStore.delete(keyRef);
186
+ throw error;
187
+ }
188
+ return {
189
+ pending: rows.length,
190
+ migrated: rows.length,
191
+ dryRun: false,
192
+ };
193
+ }
194
+
111
195
  function _loadAll(db) {
112
196
  _content.clear();
113
197
  _knowledgeLinks.clear();
@@ -263,6 +347,7 @@ export function addContent(
263
347
  }
264
348
 
265
349
  const cid = _computeCid(payload);
350
+ const encryptionKeyRef = encryptionKey ? _encryptionKeyRef(cid) : null;
266
351
 
267
352
  // Idempotent: if CID exists, just update flags
268
353
  const existing = _content.get(cid);
@@ -301,7 +386,8 @@ export function addContent(
301
386
  mime_type: mimeType || null,
302
387
  pinned: pin ? 1 : 0,
303
388
  encrypted: encrypt ? 1 : 0,
304
- encryption_key: encryptionKey,
389
+ encryption_key: "",
390
+ encryption_key_ref: encryptionKeyRef,
305
391
  knowledge_id: knowledgeId || null,
306
392
  metadata: metadataJson,
307
393
  payload: payloadBase64,
@@ -309,24 +395,33 @@ export function addContent(
309
395
  updated_at: now,
310
396
  };
311
397
 
312
- db.prepare(
313
- `INSERT INTO ipfs_content (id, cid, filename, size, mime_type, pinned, encrypted, encryption_key, knowledge_id, metadata, payload, created_at, updated_at)
314
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
315
- ).run(
316
- id,
317
- cid,
318
- entry.filename,
319
- size,
320
- entry.mime_type,
321
- entry.pinned,
322
- entry.encrypted,
323
- entry.encryption_key,
324
- entry.knowledge_id,
325
- entry.metadata,
326
- entry.payload,
327
- now,
328
- now,
329
- );
398
+ if (encryptionKeyRef) {
399
+ getIpfsSecretStore().set(encryptionKeyRef, encryptionKey);
400
+ }
401
+ try {
402
+ db.prepare(
403
+ `INSERT INTO ipfs_content (id, cid, filename, size, mime_type, pinned, encrypted, encryption_key, encryption_key_ref, knowledge_id, metadata, payload, created_at, updated_at)
404
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
405
+ ).run(
406
+ id,
407
+ cid,
408
+ entry.filename,
409
+ size,
410
+ entry.mime_type,
411
+ entry.pinned,
412
+ entry.encrypted,
413
+ entry.encryption_key,
414
+ entry.encryption_key_ref,
415
+ entry.knowledge_id,
416
+ entry.metadata,
417
+ entry.payload,
418
+ now,
419
+ now,
420
+ );
421
+ } catch (error) {
422
+ if (encryptionKeyRef) getIpfsSecretStore().delete(encryptionKeyRef);
423
+ throw error;
424
+ }
330
425
 
331
426
  _content.set(cid, entry);
332
427
  if (knowledgeId) {
@@ -350,9 +445,12 @@ export function getContent(db, cid, { asString } = {}) {
350
445
  if (!entry) return null;
351
446
 
352
447
  let buffer = Buffer.from(entry.payload, "base64");
353
- if (entry.encrypted && entry.encryption_key) {
448
+ if (entry.encrypted) {
354
449
  try {
355
- buffer = _decrypt(buffer, entry.encryption_key);
450
+ if (!entry.encryption_key_ref) return null;
451
+ const encryptionKey = getIpfsSecretStore().get(entry.encryption_key_ref);
452
+ if (!encryptionKey) return null;
453
+ buffer = _decrypt(buffer, encryptionKey);
356
454
  } catch (_e) {
357
455
  return null;
358
456
  }
@@ -395,7 +493,7 @@ export function listContent(db, { pinned, knowledgeId, limit = 50 } = {}) {
395
493
  .sort((a, b) => b.created_at - a.created_at)
396
494
  .slice(0, limit)
397
495
  .map((c) => {
398
- const { payload, encryption_key, ...rest } = c;
496
+ const { payload, encryption_key, encryption_key_ref, ...rest } = c;
399
497
  return rest;
400
498
  });
401
499
  }
@@ -446,7 +544,7 @@ export function listPins(db, { limit = 50, sortBy = "created_at" } = {}) {
446
544
  .sort(sorter)
447
545
  .slice(0, limit)
448
546
  .map((c) => {
449
- const { payload, encryption_key, ...rest } = c;
547
+ const { payload, encryption_key, encryption_key_ref, ...rest } = c;
450
548
  return rest;
451
549
  });
452
550
  }
@@ -501,8 +599,12 @@ export function garbageCollect(db) {
501
599
  }
502
600
  }
503
601
  for (const cid of toRemove) {
602
+ const entry = _content.get(cid);
504
603
  _content.delete(cid);
505
604
  db.prepare("DELETE FROM ipfs_content WHERE cid = ?").run(cid);
605
+ if (entry?.encryption_key_ref) {
606
+ getIpfsSecretStore().delete(entry.encryption_key_ref);
607
+ }
506
608
  }
507
609
  // Clean up knowledge links pointing to removed CIDs
508
610
  for (const [kid, set] of _knowledgeLinks) {
@@ -555,7 +657,7 @@ export function getKnowledgeAttachments(db, knowledgeId) {
555
657
  .map((cid) => _content.get(cid))
556
658
  .filter(Boolean)
557
659
  .map((c) => {
558
- const { payload, encryption_key, ...rest } = c;
660
+ const { payload, encryption_key, encryption_key_ref, ...rest } = c;
559
661
  return rest;
560
662
  });
561
663
  }
@@ -28,6 +28,17 @@ import { NotificationManager } from "./notifiers/index.js";
28
28
  import { createChatFn } from "./cowork-adapter.js";
29
29
  import { firstBalancedJson } from "./json-schema-output.js";
30
30
  import executionBroker from "./process-execution-broker/index.js";
31
+ import runtimeClaimsContract from "@chainlesschain/session-core/runtime-claims";
32
+
33
+ const { RUNTIME_MODE, createRuntimeClaims, hasTerminalSuccessEvidence } =
34
+ runtimeClaimsContract;
35
+
36
+ const ORCHESTRATOR_RUNTIME_CLAIMS = createRuntimeClaims({
37
+ mode: RUNTIME_MODE.REAL_EXECUTION,
38
+ durable: false,
39
+ crashSafe: false,
40
+ isolatedWrites: false,
41
+ });
31
42
 
32
43
  /* ---------- _deps injection (Vitest CJS mock pattern) ---------- */
33
44
  export const _deps = {
@@ -160,6 +171,8 @@ export class Orchestrator extends EventEmitter {
160
171
  ciErrors: [],
161
172
  createdAt: new Date().toISOString(),
162
173
  completedAt: null,
174
+ runtimeClaims: ORCHESTRATOR_RUNTIME_CLAIMS,
175
+ terminalEvidence: [],
163
176
  };
164
177
 
165
178
  this._tasks.set(task.id, task);
@@ -192,6 +205,8 @@ export class Orchestrator extends EventEmitter {
192
205
  source: t.source,
193
206
  retries: t.retries,
194
207
  createdAt: t.createdAt,
208
+ runtimeClaims: t.runtimeClaims,
209
+ terminalEvidence: t.terminalEvidence,
195
210
  }));
196
211
  return {
197
212
  tasks,
@@ -228,6 +243,7 @@ export class Orchestrator extends EventEmitter {
228
243
 
229
244
  // Step 2: Dispatch to Claude Code agents
230
245
  task.agentResults = await this._dispatch(task);
246
+ this._assertSuccessfulAgentResults(task);
231
247
 
232
248
  // Step 3: CI/CD check
233
249
  if (task.runCI) {
@@ -368,6 +384,7 @@ export class Orchestrator extends EventEmitter {
368
384
  task.agentResults = await this._router.dispatch(fixSubtasks, {
369
385
  cwd: task.cwd,
370
386
  });
387
+ this._assertSuccessfulAgentResults(task);
371
388
  this.emit("agents:complete", { task, results: task.agentResults });
372
389
  }
373
390
 
@@ -409,6 +426,36 @@ export class Orchestrator extends EventEmitter {
409
426
  }
410
427
  }
411
428
 
429
+ _assertSuccessfulAgentResults(task) {
430
+ if (!Array.isArray(task.agentResults) || task.agentResults.length === 0) {
431
+ throw new Error("Agent dispatch produced no terminal results");
432
+ }
433
+
434
+ const failed = [];
435
+ const evidence = [];
436
+ for (let index = 0; index < task.agentResults.length; index += 1) {
437
+ const result = task.agentResults[index];
438
+ const valid =
439
+ result?.success === true &&
440
+ hasTerminalSuccessEvidence(
441
+ result.runtimeClaims,
442
+ result.terminalEvidence,
443
+ );
444
+ if (!valid) {
445
+ failed.push(
446
+ `${result?.taskId || `result-${index}`}: ${result?.error || result?.status || "missing terminal evidence"}`,
447
+ );
448
+ } else {
449
+ evidence.push(...result.terminalEvidence);
450
+ }
451
+ }
452
+
453
+ if (failed.length > 0) {
454
+ throw new Error(`Agent execution did not succeed: ${failed.join("; ")}`);
455
+ }
456
+ task.terminalEvidence = evidence;
457
+ }
458
+
412
459
  /**
413
460
  * Bound retained task history to maxTasks. Evicts the oldest TERMINAL tasks
414
461
  * first (Map preserves insertion order = FIFO); an in-flight task is never
@@ -238,13 +238,15 @@ export async function evaluateShellCommandWithApproval({
238
238
  };
239
239
  }
240
240
 
241
- // No ApprovalGate wired? Preserve legacy behavior (shell policy decides).
241
+ // A missing gate is an unavailable security boundary, not an implicit
242
+ // authorization. Explicit bypass modes must provide their own auditable
243
+ // gate implementation instead of omitting the gate.
242
244
  if (!approvalGate || typeof approvalGate.decide !== "function") {
243
245
  return {
244
- allowed: true,
245
- decision: DECISION.ALLOW,
246
- via: "shell-policy",
247
- reason: shellPolicy.reason,
246
+ allowed: false,
247
+ decision: DECISION.DENY,
248
+ via: "approval-gate-unavailable",
249
+ reason: "Approval gate is unavailable",
248
250
  shellPolicy,
249
251
  riskLevel,
250
252
  policy: null,