chainlesschain 0.162.171 → 0.162.172

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 (177) hide show
  1. package/bin/chainlesschain.js +8 -0
  2. package/package.json +6 -1
  3. package/src/assets/web-panel/assets/{AIOps-Cf8yb18C.js → AIOps-oKCWU-LK.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CsFT6FMt.js → ActionButton-4CBfc5E4.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-DQe_hXMA.js → Analytics-BEmR-k_b.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-Cl9Pp7jk.js → AppLayout-D6a4ZnrC.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-CBEzLVjF.js → Artifacts-BRWIHCPl.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-BS2Un14C.js → Audit-CzGKlkTc.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-DmcDH8OK.js → BackgroundAgents-CmMYN10o.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-DvzjTkkn.js → Backup-CJ6e0ukD.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DnbpuyME.js → BaseInput-BpEvDrNt.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BJRRCm2P.js → Chat-wWuwwjKu.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bgpxyqd_.js → ChatBubbleRenderer-CJLyGo_u.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-DFOrWmvm.js → Checkbox-C6pW60Br.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-BIQ2kU6Q.js → Codegen-DF-nP22Y.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-BI3R-N4I.js → Col-BuueEwZW.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-CPiAwsHT.js → Community-DuE0Yzwr.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-Bv4cslSK.js → Compact-BrHim8EB.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-CSlDG1NZ.js → Compliance-DgAet8f_.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-CFcRumXf.js → Cowork-B9wY05lx.js} +4 -4
  21. package/src/assets/web-panel/assets/{Cron-DKYKMmOn.js → Cron-CvNBxfJX.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CxPMByp2.js → Crosschain-BnZRENa0.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DJqiYw1C.js → DID-DiqYLHTI.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-D2dLMxqy.js → Dashboard-t3SsRzZL.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BnJc384A.js → Dropdown-BCjMLam9.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-DctFvm-J.js → EmailListRenderer-D2v9-IHJ.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-J_xg-Qop.js → FamilyGuardDashboard-_iQu35qa.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BckL07Uw.js → Federation-Bkty8VqB.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-B8s5ccSO.js → FormItemContext-DdPW81BY.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-hPMBK2No.js → GenericCardRenderer-DrNYM4Zj.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-CfMpYLo7.js → Git-BjF-B2h0.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-Bt3OcrC7.js → Governance-DPhGdJ1v.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-BlKc336N.js → Inference--PPksOVj.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-B6p7og2c.js → KnowledgeGraph-y5WdV_JV.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-uv5Re6YR.js → Logs-B6_x7zba.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-Bg8zSyF8.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-CfNbntHt.js → Marketplace-CHpfMu1A.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-YRXt74Yk.js → McpTools-qqjtX3Cf.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-BfQQs-Jd.js → Memory-hASSgxbw.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-BuGC-4S2.js → MobileBridge-Dwh7Bhcf.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-Czieqw1m.js → MobileProjects-D09voh7W.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-DHWHOVCO.js → Mtc-9G1dXeId.js} +3 -3
  43. package/src/assets/web-panel/assets/{MtcAudit-DWSEbMW-.js → MtcAudit-CWtYXj6f.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-DrhEv1vq.js → Multisig-bDI0EnDk.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-D8wKCu7E.js → NLProgramming-CTanRaBP.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-AFeqq0I_.js → Notes-BdQENJFv.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-D6qenYUo.js → NotificationSettings-JvnQdStO.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-CF0X4fyB.js → OrderTableRenderer-BMGL9RPJ.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-DdfbNqf6.js → Organization-sBZnIb2D.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-BFEvnLfd.js → Overflow-CzOhNGE6.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-DtL6wbkz.js → P2P-D_D2yqda.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-CQPriTud.js → PdhVaultBrowser-D5lKd_Kx.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-Bj25ANmR.js → Permissions-L5s-wENg.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-BNj2Oux0.js → PersonalDataHub-iI49x6cH.js} +2 -2
  55. package/src/assets/web-panel/assets/{Pipeline-Dyj8UEaG.js → Pipeline-DPHqyk09.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-BBUrWRFz.js → Privacy-B-ZL9360.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-BdX7uQn6.js → ProjectInit-f05YzsN2.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-BghtW1zr.js → ProjectSettings-DZLKS6ex.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-9VTquZCz.js → Projects-ButF3DyM.js} +1 -1
  60. package/src/assets/web-panel/assets/{Providers-D-0K_Eza.js → Providers-CFDSXnkR.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-DDaN30_D.js → QrScannerModal-1N6Sdxdm.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-DfHlifOj.js → QuickAsk-tEqRwRSR.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-CgLIvYE2.js → Recommend-D4ZVHIwz.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DpOPrwE4.js → RemoteSession-Cqm32lhm.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-wMexlbCE.js → Reputation-BnjVsU_a.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-D9aD_nrc.js → Row-DzpHyTuz.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Drg7l6zu.js → RssFeed-Du5-ouwx.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-BKO1nrwN.js → Search-CYztyf2o.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-G3Kyk-TG.js → Security-C1hVxy8Z.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-xJReTOna.js → Services-BscEbAZ2.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-ldVDVTPG.js → Skeleton-B2sMLqKQ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-emwNYV0j.js → Skills-CoHKax06.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-CZYwGp1K.js → Sla-Bpie5KO6.js} +1 -1
  74. package/src/assets/web-panel/assets/SpeechSettings-BX63ijn5.js +1 -0
  75. package/src/assets/web-panel/assets/{SyncSettings-Dcs5Hhj6.js → SyncSettings-Bf72so5A.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-CerFAo26.js → Tasks-CVB2PZk4.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-BdZUbOg3.js → Templates-q0qyclJx.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-B4c_7Bsw.js → Tenant-CW-W-i0k.js} +1 -1
  79. package/src/assets/web-panel/assets/Terminal-D7QoPiXQ.js +3 -0
  80. package/src/assets/web-panel/assets/{TimelineRenderer-tc6sp0TV.js → TimelineRenderer-BaRDAbyA.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-Bw_vkMJq.js → Tokens-D6U4PRW8.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DkbJnpvz.js → Trigger-ClBDWdLo.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-CIf9kqN1.js → Trust-C_M6rWPq.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-Cjwllnea.js → UkeySign-bXHx8s4C.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-kgfkY7AN.js → VideoEditing-BcIt_ieI.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-CYWXt4u9.js → Wallet-Dd-4jcLs.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-QgPwyWCO.js → WebAuthn-B4F6yxQK.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-Co0lha18.js → WorkflowEditor-BEHkpfJq.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-CI__Ox-r.js → chat-D7hhRpIO.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-Csv0eYYd.js → colors-AMRhrRzS.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-e53UCdHy.js → compact-item-BYpsOET5.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-BMPGRDhV.js → createContext-CoUkR4LQ.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-BRylvxzY.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-Dz68qIAq.js → hasIn-CJKJMKki.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BT3CV4Nh.js → index-8pmZHnQU.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DyqcHiL1.js → index-BBJFiZ9Y.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-HbhQRrM2.js → index-BP69Ul3S.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CoGSbW5J.js → index-BTFHYauX.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DJqQL6so.js → index-BUJt2ar4.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CvLBQk_M.js → index-Bj30Aq6h.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-ygfUVVFv.js → index-BlpuqGt5.js} +1 -1
  102. package/src/assets/web-panel/assets/index-Bzvxvzlk.js +1 -0
  103. package/src/assets/web-panel/assets/{index-CYUxs6J1.js → index-C19xZKIP.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B1s1B8Iy.js → index-C6bg22vc.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C-NbcAbP.js → index-CH6XEWdj.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DctYrVMq.js → index-CK1Kknpl.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DVCd2aMX.js → index-CNyLbBGj.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-t6f80uqL.js → index-COg__P6M.js} +22 -22
  109. package/src/assets/web-panel/assets/{index-5iicv5af.js → index-CRlJOWsf.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BW2dImbg.js → index-CScG8TAY.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-K5E_wjut.js → index-CdL9cQIE.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Dk9Gi8xd.js → index-Ck35u_0v.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-_LmPlyeV.js → index-CkLZQtsh.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Dtjm1K1a.js → index-DFoujkWD.js} +1 -1
  115. package/src/assets/web-panel/assets/{index--7tHEadk.js → index-DFwh0R9h.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-C5hLtxVz.js → index-DStN9E7o.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D0bg74e1.js → index-DcozYrXV.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-wcCouSNq.js → index-De5mYp86.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CXuON9OG.js → index-DfEVOzNb.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CNtZMPKV.js → index-Dfna8sKa.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B4lKPJy1.js → index-DjbMaBLf.js} +1 -1
  122. package/src/assets/web-panel/assets/index-Dl6H3dxS.js +1 -0
  123. package/src/assets/web-panel/assets/{index-C53o-MdJ.js → index-Dpl_SJuk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-53ljQo_x.js → index-DyF9uYzB.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CpTzqJ0Z.js → index-HF3GvATm.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DCl4Xb4N.js → index-OJmXGn8n.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BOpz2qS1.js → index-ZPdNPhUq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BHkDRNA5.js → index-djikyGz3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CyLUaP2i.js → index-gQWWnP3_.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DnXm3Qsh.js → index-owVbLJnH.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-ajz0E0pK.js → index-tWEDZHzj.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-N9DkR1i7.js → index-ttTl376q.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-CrsoSnQF.js → index-z5rYvstM.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-DVCeQJrT.js → initDefaultProps-B_Uk-wzg.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-chBCR_8v.js → motion-ez7H8y8b.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-BziPlrh6.js → move-CKWUhhhX.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-Cenk0OD7.js → mtc-parser-DkNl7ocj.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-D-AiRsei.js → omit-C0uA2ytw.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CHw3Fvqt.js → pickAttrs-CySaWMPl.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-g8I-rCad.js → placementArrow-BWL3-3xo.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-BWffAr9k.js → responsiveObserve-BRy_wJog.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-BmUQqhkb.js → slide-DmmvSaBD.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-B89gCO-y.js → statusUtils-C_7SYY0K.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-x1bnCF73.js → styleChecker-DYgBJGDh.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-B-k1_Ggw.js → useFlexGapSupport-nPkoZkT6.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-Bc3PUqQk.js → useFs-CzpsfP4_.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-D8qFDX1I.js → usePersonalDataHub-Bo2vvMWl.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-UaL5-WGg.js → vnode-D-hXAnHb.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Dv7bsbLs.js → zoom-DW7seTGG.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/permissions.js +24 -1
  152. package/src/index.js +63 -845
  153. package/src/lib/agent-ipc-bus.js +331 -0
  154. package/src/lib/context-source-ledger.js +164 -0
  155. package/src/lib/execution-trace/index.js +10 -0
  156. package/src/lib/execution-trace/metrics-collector.js +218 -0
  157. package/src/lib/execution-trace/trace-context.js +182 -0
  158. package/src/lib/hook-manager.js +17 -0
  159. package/src/lib/hooks-v2-runtime.js +278 -0
  160. package/src/lib/metrics-collector.js +127 -0
  161. package/src/lib/observability/index.js +33 -0
  162. package/src/lib/observability/otlp-exporter.js +260 -0
  163. package/src/lib/otlp-exporter.js +45 -0
  164. package/src/lib/process-execution-broker/SPAWN_AUDIT_REPORT.md +117 -0
  165. package/src/lib/process-execution-broker/index.js +450 -0
  166. package/src/lib/process-execution-broker/patch-child-process.js +50 -0
  167. package/src/lib/process-execution-broker/spawn-audit.json +3814 -0
  168. package/src/lib/runtime-provenance-ledger.js +190 -0
  169. package/src/lib/session-hooks.js +41 -0
  170. package/src/program-base.js +4 -1
  171. package/src/repl/agent-repl.js +2 -0
  172. package/src/assets/web-panel/assets/MarkdownRenderer-CId5JWjX.js +0 -1
  173. package/src/assets/web-panel/assets/SpeechSettings-CyaPrzOF.js +0 -1
  174. package/src/assets/web-panel/assets/Terminal-VVFLS3Ol.js +0 -3
  175. package/src/assets/web-panel/assets/devWarning-BIulobq7.js +0 -1
  176. package/src/assets/web-panel/assets/index-BGkiYnET.js +0 -1
  177. package/src/assets/web-panel/assets/index-Eyhrr_3u.js +0 -1
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Agent IPC Bus — M2: 后台Agent实时交互总线
3
+ * 对应文档 §2.2
4
+ *
5
+ * 解决后台agent运行期间不能提问/confirm/elicit的问题:
6
+ * - child agent 通过 IPC 发送 interaction_request
7
+ * - parent 路由给 UI/REPL/headless resolver
8
+ * - 结果通过 interaction_response 返回child
9
+ * - 支持超时、取消、默认值
10
+ */
11
+
12
+ import { EventEmitter } from "node:events";
13
+ import crypto from "node:crypto";
14
+
15
+ /**
16
+ * @typedef {Object} InteractionRequest
17
+ * @property {string} requestId
18
+ * @property {string} agentId - child agent id
19
+ * @property {string} sessionId
20
+ * @property {string} turnId
21
+ * @property {'permission_prompt'|'human_input'|'question'|'confirm'|'elicit'|'mcp_elicit'} type
22
+ * @property {string} prompt
23
+ * @property {string[]} [choices]
24
+ * @property {any} [defaultValue]
25
+ * @property {number} [timeoutMs]
26
+ * @property {Object} [metadata]
27
+ */
28
+
29
+ class AgentIPCBus extends EventEmitter {
30
+ constructor() {
31
+ super();
32
+ /** @type {Map<string, {req: InteractionRequest, resolve: Function, reject: Function, timer?: NodeJS.Timeout}>} */
33
+ this._pendingRequests = new Map();
34
+ /** @type {Map<string, Function>} resolvers by agentId */
35
+ this._agentResolvers = new Map();
36
+ }
37
+
38
+ /**
39
+ * Register an agent worker's send function so bus can route responses back
40
+ * @param {string} agentId
41
+ * @param {(msg: any) => void} sendToWorker
42
+ */
43
+ registerAgent(agentId, sendToWorker) {
44
+ this._agentResolvers.set(agentId, sendToWorker);
45
+ this.emit("agent:registered", { agentId });
46
+ }
47
+
48
+ unregisterAgent(agentId) {
49
+ this._agentResolvers.delete(agentId);
50
+ // Reject all pending for this agent
51
+ for (const [reqId, entry] of this._pendingRequests.entries()) {
52
+ if (entry.req.agentId === agentId) {
53
+ if (entry.timer) clearTimeout(entry.timer);
54
+ entry.reject(new Error(`Agent ${agentId} disconnected while waiting for response`));
55
+ this._pendingRequests.delete(reqId);
56
+ }
57
+ }
58
+ this.emit("agent:unregistered", { agentId });
59
+ }
60
+
61
+ /**
62
+ * Child agent calls this to request human interaction
63
+ * @param {string} agentId
64
+ * @param {Partial<InteractionRequest>} req
65
+ * @returns {Promise<any>}
66
+ */
67
+ requestInteraction(agentId, req) {
68
+ const requestId = crypto.randomUUID();
69
+ const fullReq = {
70
+ requestId,
71
+ agentId,
72
+ sessionId: req.sessionId,
73
+ turnId: req.turnId,
74
+ type: req.type || "question",
75
+ prompt: req.prompt,
76
+ choices: req.choices,
77
+ defaultValue: req.defaultValue,
78
+ timeoutMs: req.timeoutMs || 300000, // 5min default
79
+ metadata: req.metadata || {},
80
+ };
81
+
82
+ return new Promise((resolve, reject) => {
83
+ const timer = setTimeout(() => {
84
+ this._pendingRequests.delete(requestId);
85
+ if (fullReq.defaultValue !== undefined) {
86
+ resolve(fullReq.defaultValue);
87
+ } else {
88
+ reject(new Error(`Interaction request ${requestId} timed out after ${fullReq.timeoutMs}ms`));
89
+ }
90
+ this.emit("request:timeout", fullReq);
91
+ }, fullReq.timeoutMs);
92
+
93
+ this._pendingRequests.set(requestId, { req: fullReq, resolve, reject, timer });
94
+ this.emit("request", fullReq);
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Parent/UI calls this to respond to a pending request
100
+ * @param {string} requestId
101
+ * @param {any} response
102
+ */
103
+ respond(requestId, response) {
104
+ const entry = this._pendingRequests.get(requestId);
105
+ if (!entry) return false;
106
+ if (entry.timer) clearTimeout(entry.timer);
107
+ this._pendingRequests.delete(requestId);
108
+ entry.resolve(response);
109
+ this.emit("request:resolved", { requestId, response });
110
+ return true;
111
+ }
112
+
113
+ /**
114
+ * Reject/cancel a pending request
115
+ * @param {string} requestId
116
+ * @param {Error} [err]
117
+ */
118
+ cancel(requestId, err) {
119
+ const entry = this._pendingRequests.get(requestId);
120
+ if (!entry) return false;
121
+ if (entry.timer) clearTimeout(entry.timer);
122
+ this._pendingRequests.delete(requestId);
123
+ entry.reject(err || new Error("Interaction cancelled by user"));
124
+ this.emit("request:cancelled", { requestId });
125
+ return true;
126
+ }
127
+
128
+ /** Get pending interaction requests for UI */
129
+ getPendingRequests() {
130
+ return Array.from(this._pendingRequests.values()).map(e => e.req);
131
+ }
132
+
133
+ /** Number of pending requests */
134
+ get pendingCount() {
135
+ return this._pendingRequests.size;
136
+ }
137
+
138
+ /**
139
+ * Spawn a child agent process with standardized JSON-RPC over stdio protocol
140
+ * Aligned with Claude Code sub-agent spawn specification
141
+ * @param {string} command - Agent executable/script path
142
+ * @param {string[]} args - Command arguments
143
+ * @param {object} options - Spawn options
144
+ * @returns {Promise<{process: ChildProcess, agentId: string}>}
145
+ */
146
+ async spawnAgentProcess(command, args = [], options = {}) {
147
+ const { spawn } = await import("node:child_process");
148
+ const agentId = options.agentId || crypto.randomUUID();
149
+ const heartbeatMs = options.heartbeatMs || 30000;
150
+
151
+ return new Promise((resolve, reject) => {
152
+ const child = spawn(command, args, {
153
+ stdio: ["pipe", "pipe", "pipe"],
154
+ env: {
155
+ ...process.env,
156
+ CHAINLESSCHAIN_AGENT_ID: agentId,
157
+ CHAINLESSCHAIN_AGENT_MODE: "subagent",
158
+ CHAINLESSCHAIN_IPC_PROTOCOL: "jsonrpc-stdio-v1",
159
+ ...options.env,
160
+ },
161
+ ...options.spawnOptions,
162
+ });
163
+
164
+ let buffer = "";
165
+ let initialized = false;
166
+ let heartbeatTimer = null;
167
+
168
+ // Handle stdout: line-delimited JSON-RPC
169
+ child.stdout.on("data", (chunk) => {
170
+ buffer += chunk.toString("utf8");
171
+ const lines = buffer.split("\n");
172
+ buffer = lines.pop() || ""; // Keep incomplete line in buffer
173
+
174
+ for (const line of lines) {
175
+ if (!line.trim()) continue;
176
+ try {
177
+ const msg = JSON.parse(line);
178
+ this._handleIncomingMessage(agentId, msg, child);
179
+ if (msg.method === "initialize" && !initialized) {
180
+ initialized = true;
181
+ this.registerAgent(agentId, (outMsg) => {
182
+ child.stdin.write(JSON.stringify(outMsg) + "\n");
183
+ });
184
+ // Send initialize response
185
+ child.stdin.write(JSON.stringify({
186
+ jsonrpc: "2.0",
187
+ id: msg.id,
188
+ result: {
189
+ protocolVersion: "1.0",
190
+ agentId,
191
+ capabilities: { interaction: true, tools: true },
192
+ },
193
+ }) + "\n");
194
+ // Setup heartbeat
195
+ heartbeatTimer = setInterval(() => {
196
+ if (child.exitCode !== null) {
197
+ clearInterval(heartbeatTimer);
198
+ return;
199
+ }
200
+ child.stdin.write(JSON.stringify({ jsonrpc: "2.0", method: "heartbeat" }) + "\n");
201
+ }, heartbeatMs);
202
+ resolve({ process: child, agentId });
203
+ }
204
+ } catch (e) {
205
+ this.emit("protocol:error", { agentId, error: e, raw: line });
206
+ }
207
+ }
208
+ });
209
+
210
+ // Handle stderr: pass through to logger
211
+ child.stderr.on("data", (chunk) => {
212
+ this.emit("agent:stderr", { agentId, data: chunk.toString("utf8") });
213
+ if (options.captureStderr !== false) {
214
+ process.stderr.write(`[agent:${agentId}] ${chunk}`);
215
+ }
216
+ });
217
+
218
+ child.on("error", (err) => {
219
+ if (heartbeatTimer) clearInterval(heartbeatTimer);
220
+ if (!initialized) reject(err);
221
+ this.emit("agent:error", { agentId, error: err });
222
+ });
223
+
224
+ child.on("exit", (code, signal) => {
225
+ if (heartbeatTimer) clearInterval(heartbeatTimer);
226
+ this.unregisterAgent(agentId);
227
+ this.emit("agent:exit", { agentId, code, signal });
228
+ });
229
+
230
+ // Timeout for initialization
231
+ setTimeout(() => {
232
+ if (!initialized) {
233
+ child.kill();
234
+ reject(new Error(`Agent ${agentId} initialization timed out`));
235
+ }
236
+ }, options.initTimeoutMs || 10000);
237
+ });
238
+ }
239
+
240
+ /**
241
+ * Handle incoming JSON-RPC message from child agent
242
+ * @private
243
+ */
244
+ _handleIncomingMessage(agentId, msg, child) {
245
+ if (!msg.jsonrpc || msg.jsonrpc !== "2.0") {
246
+ this.emit("protocol:warning", { agentId, msg, reason: "missing jsonrpc version" });
247
+ return;
248
+ }
249
+
250
+ // Handle requests (method + id)
251
+ if (msg.method && msg.id) {
252
+ if (msg.method === "interaction_request") {
253
+ this.requestInteraction(agentId, msg.params).then((result) => {
254
+ child.stdin.write(JSON.stringify({
255
+ jsonrpc: "2.0",
256
+ id: msg.id,
257
+ result,
258
+ }) + "\n");
259
+ }).catch((err) => {
260
+ child.stdin.write(JSON.stringify({
261
+ jsonrpc: "2.0",
262
+ id: msg.id,
263
+ error: { code: -32000, message: err.message },
264
+ }) + "\n");
265
+ });
266
+ } else if (msg.method === "log") {
267
+ this.emit("agent:log", { agentId, params: msg.params });
268
+ // Acknowledge log
269
+ child.stdin.write(JSON.stringify({ jsonrpc: "2.0", id: msg.id, result: true }) + "\n");
270
+ } else {
271
+ this.emit("agent:request", { agentId, msg });
272
+ }
273
+ }
274
+ // Handle notifications (method, no id)
275
+ else if (msg.method && !msg.id) {
276
+ if (msg.method === "heartbeat") {
277
+ this.emit("agent:heartbeat", { agentId });
278
+ } else if (msg.method === "progress") {
279
+ this.emit("agent:progress", { agentId, params: msg.params });
280
+ } else {
281
+ this.emit("agent:notification", { agentId, method: msg.method, params: msg.params });
282
+ }
283
+ }
284
+ // Handle responses (id + result/error)
285
+ else if (msg.id) {
286
+ this.emit("agent:response", { agentId, msg });
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Send a JSON-RPC request to a spawned agent via stdio
292
+ * @param {string} agentId
293
+ * @param {string} method
294
+ * @param {any} params
295
+ * @param {number} [timeoutMs=30000]
296
+ * @returns {Promise<any>}
297
+ */
298
+ sendRequest(agentId, method, params = {}, timeoutMs = 30000) {
299
+ const sendToWorker = this._agentResolvers.get(agentId);
300
+ if (!sendToWorker) {
301
+ return Promise.reject(new Error(`Agent ${agentId} not registered`));
302
+ }
303
+ const id = crypto.randomUUID();
304
+ return new Promise((resolve, reject) => {
305
+ const timer = setTimeout(() => {
306
+ this.removeAllListeners(`response:${id}`);
307
+ reject(new Error(`Request ${method} to agent ${agentId} timed out`));
308
+ }, timeoutMs);
309
+
310
+ const onResponse = (respMsg) => {
311
+ if (respMsg.msg.id === id) {
312
+ clearTimeout(timer);
313
+ this.off("agent:response", onResponse);
314
+ if (respMsg.msg.error) {
315
+ reject(new Error(respMsg.msg.error.message));
316
+ } else {
317
+ resolve(respMsg.msg.result);
318
+ }
319
+ }
320
+ };
321
+ this.on("agent:response", onResponse);
322
+
323
+ sendToWorker({ jsonrpc: "2.0", id, method, params });
324
+ });
325
+ }
326
+ }
327
+
328
+ // Singleton
329
+ const ipcBus = new AgentIPCBus();
330
+ export default ipcBus;
331
+ export { AgentIPCBus };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Context Source Ledger — M4-1: 上下文来源归因系统
3
+ * 对应文档 §2.5
4
+ *
5
+ * 统一追踪每段上下文的来源、工具调用、权限模式、置信度,
6
+ * 让"AI 为什么此刻知道这件事"完全可追溯
7
+ */
8
+
9
+ import crypto from "node:crypto";
10
+
11
+ /**
12
+ * @typedef {Object} ContextEntry
13
+ * @property {string} entryId
14
+ * @property {string} sessionId
15
+ * @property {string} turnId
16
+ * @property {string} sourceType - slash_command|mcp|tool|hook|skill|agent|file|memory|prompt|plugin
17
+ * @property {string} sourceId - tool name, mcp server name, hook id, etc.
18
+ * @property {'system'|'developer'|'plugin'|'user'|'agent'} permissionMode
19
+ * @property {number} confidence - 0-1
20
+ * @property {string} [summary]
21
+ * @property {any} [metadata]
22
+ * @property {number} tokenCount
23
+ * @property {Date} insertedAt
24
+ * @property {string[]} tags
25
+ */
26
+
27
+ class ContextSourceLedger {
28
+ constructor() {
29
+ /** @type {Map<string, ContextEntry>} */
30
+ this._entries = new Map();
31
+ /** @type {Map<string, ContextEntry[]>} turnIndex: turnId -> entries */
32
+ this._byTurn = new Map();
33
+ /** @type {Map<string, ContextEntry[]>} sessionIndex: sessionId -> entries */
34
+ this._bySession = new Map();
35
+ }
36
+
37
+ /**
38
+ * Record a context source entry
39
+ * @param {Partial<ContextEntry>} entry
40
+ * @returns {string} entryId
41
+ */
42
+ record(entry) {
43
+ const entryId = entry.entryId || crypto.randomUUID();
44
+ const full = {
45
+ entryId,
46
+ sessionId: entry.sessionId || "unknown",
47
+ turnId: entry.turnId || "unknown",
48
+ sourceType: entry.sourceType || "unknown",
49
+ sourceId: entry.sourceId || "unknown",
50
+ permissionMode: entry.permissionMode || "agent",
51
+ confidence: entry.confidence ?? 0.8,
52
+ summary: entry.summary,
53
+ metadata: entry.metadata,
54
+ tokenCount: entry.tokenCount || 0,
55
+ insertedAt: new Date(),
56
+ tags: entry.tags || [],
57
+ };
58
+
59
+ this._entries.set(entryId, full);
60
+
61
+ // Index by turn
62
+ if (!this._byTurn.has(full.turnId)) this._byTurn.set(full.turnId, []);
63
+ this._byTurn.get(full.turnId).push(full);
64
+
65
+ // Index by session
66
+ if (!this._bySession.has(full.sessionId)) this._bySession.set(full.sessionId, []);
67
+ this._bySession.get(full.sessionId).push(full);
68
+
69
+ return entryId;
70
+ }
71
+
72
+ /**
73
+ * Get all context entries for a given turn
74
+ * @param {string} turnId
75
+ * @returns {ContextEntry[]}
76
+ */
77
+ getTurnContext(turnId) {
78
+ return this._byTurn.get(turnId) || [];
79
+ }
80
+
81
+ /**
82
+ * Get all context entries for a session
83
+ * @param {string} sessionId
84
+ * @returns {ContextEntry[]}
85
+ */
86
+ getSessionContext(sessionId) {
87
+ return this._bySession.get(sessionId) || [];
88
+ }
89
+
90
+ /**
91
+ * Generate context provenance summary for a turn
92
+ * Shows exactly where each piece of context came from
93
+ * @param {string} turnId
94
+ * @returns {Object} provenance report
95
+ */
96
+ getTurnProvenance(turnId) {
97
+ const entries = this.getTurnContext(turnId);
98
+ const byType = {};
99
+ const byPermission = {};
100
+ const bySource = {};
101
+ let totalTokens = 0;
102
+ let avgConfidence = 0;
103
+
104
+ for (const e of entries) {
105
+ byType[e.sourceType] = (byType[e.sourceType] || 0) + 1;
106
+ byPermission[e.permissionMode] = (byPermission[e.permissionMode] || 0) + 1;
107
+ bySource[e.sourceId] = (bySource[e.sourceId] || 0) + 1;
108
+ totalTokens += e.tokenCount;
109
+ avgConfidence += e.confidence;
110
+ }
111
+
112
+ avgConfidence = entries.length > 0 ? avgConfidence / entries.length : 0;
113
+
114
+ return {
115
+ turnId,
116
+ totalEntries: entries.length,
117
+ totalTokens,
118
+ avgConfidence: Math.round(avgConfidence * 100) / 100,
119
+ byType,
120
+ byPermission,
121
+ bySource,
122
+ entries: entries.map(e => ({
123
+ sourceType: e.sourceType,
124
+ sourceId: e.sourceId,
125
+ permissionMode: e.permissionMode,
126
+ confidence: e.confidence,
127
+ tokenCount: e.tokenCount,
128
+ summary: e.summary,
129
+ tags: e.tags,
130
+ })),
131
+ };
132
+ }
133
+
134
+ /**
135
+ * Clear entries for a session
136
+ * @param {string} sessionId
137
+ */
138
+ clearSession(sessionId) {
139
+ const entries = this._bySession.get(sessionId) || [];
140
+ for (const e of entries) {
141
+ this._entries.delete(e.entryId);
142
+ const turnEntries = this._byTurn.get(e.turnId);
143
+ if (turnEntries) {
144
+ const idx = turnEntries.findIndex(x => x.entryId === e.entryId);
145
+ if (idx >= 0) turnEntries.splice(idx, 1);
146
+ }
147
+ }
148
+ this._bySession.delete(sessionId);
149
+ }
150
+
151
+ /** Get stats */
152
+ getStats() {
153
+ return {
154
+ totalEntries: this._entries.size,
155
+ sessionsTracked: this._bySession.size,
156
+ turnsTracked: this._byTurn.size,
157
+ };
158
+ }
159
+ }
160
+
161
+ // Singleton
162
+ const ledger = new ContextSourceLedger();
163
+ export default ledger;
164
+ export { ContextSourceLedger };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ExecutionTrace - M3 执行追踪统一导出
3
+ *
4
+ * 包含分布式追踪和指标收集功能:
5
+ * - TraceContext: W3C Trace Context 兼容的上下文传播
6
+ * - MetricsCollector: 轻量级性能指标收集
7
+ */
8
+
9
+ export * from "./trace-context.js";
10
+ export * from "./metrics-collector.js";