chainlesschain 0.166.46 → 0.166.48

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 (232) hide show
  1. package/README.md +6 -4
  2. package/package.json +4 -2
  3. package/src/assets/web-panel/assets/{AIOps-Cp8KiMmv.js → AIOps-BLGEffkh.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-B4d9BGsm.js → ActionButton-Cz1z2VGD.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Cf9yXTkv.js → Analytics-C3j9cf6q.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-40UkmxtP.js → AppLayout-BR9ERuCA.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-Ckkb4oOA.js → Artifacts-CozJCm4y.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-Dnf569k5.js → Audit-DC5g9Ra2.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-CA6bLem4.js → BackgroundAgents-B1zrQ0dW.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-ChQU0I_Q.js → Backup-ChVnfjpm.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-BHeZXnNN.js → BaseInput-8_vLQsLf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-DcFVYB2E.js → Chat-Dct9bm6L.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-BvoSsCKh.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-2PDbejv2.js → Checkbox-DZQIsCIC.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-DJBn1RAu.js → Codegen-CdzHxmnq.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CPRq7n6y.js → Col-DdAN8LeW.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-axvINFMi.js → Community-CNgjT9MA.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-_OX4Qbe0.js → Compact-BtQiX6G-.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DWAkvzRL.js → Compliance-OGX5ma3j.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-CUIJ25oj.js → Cowork-CgugQnGM.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-nR0m7H3_.js → Cron-Bpg7cPFD.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CgTLXzh_.js → Crosschain-D1hsuswf.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-BllzRB6Q.js → DID-miDRsMBw.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-C9f0IIBN.js → Dashboard-CGcl8htP.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BkahetiO.js → Dropdown-BFaxTdVE.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-rartVC-k.js → EmailListRenderer-BQdGLZIO.js} +1 -1
  27. package/src/assets/web-panel/assets/{EvolutionSettings-BqpG3XHV.js → EvolutionSettings-bMvgBk6r.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgUdFvw1.js → FamilyGuardDashboard-c1WVC_--.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-oFpIQU6g.js → Federation-DyAcFrQY.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-BUH5xlyP.js → FormItemContext-CfwpfD2B.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-ilRa-ueg.js → GenericCardRenderer-DkJcbBpS.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DlHHSF8j.js → Git-DgYIrPJh.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-yQiiXIWe.js → Governance-BF1tYPJ6.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-BUDRVGOP.js → Inference-BFkwRIrU.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-BaGyIoN1.js → KnowledgeGraph-DpCoqhBa.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-C1cO6zE0.js → Logs-DU2qAJmD.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-_z_Iaoes.js → MarkdownRenderer-QWv7UJLq.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-CM8cGL0K.js → Marketplace-Dz9NUrfo.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-CDqAMU0U.js → McpTools-B67I3d5v.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-CfB0-Ofv.js → Memory-crkElJSy.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BL18ytvB.js → MobileBridge-BO20VbdX.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-PIyyxbuJ.js → MobileProjects-Ba-3gZZd.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-BTTrFCol.js → Mtc-BAHZM084.js} +4 -4
  44. package/src/assets/web-panel/assets/{MtcAudit-JHZn037c.js → MtcAudit-CL3DzajL.js} +4 -4
  45. package/src/assets/web-panel/assets/{Multisig-CMf9NEdB.js → Multisig-BSWWzvWH.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-Dhk3qaus.js → NLProgramming-fnxqXM_3.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-6F8EarNN.js → Notes-qUZPIQXT.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-gxdaVEit.js → NotificationSettings-x9Xrixqu.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-gVgXQWdc.js → OrderTableRenderer-BtMtQUt7.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-CzvHcDNO.js → Organization-C946Hzna.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-Dclx30Vv.js → Overflow-BYf8KIts.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-CM0Wm9vZ.js → P2P-Cbqf5dnv.js} +2 -2
  53. package/src/assets/web-panel/assets/PdhVaultBrowser-rmxp0cuF.js +7 -0
  54. package/src/assets/web-panel/assets/{Permissions-B_oATenG.js → Permissions-CZBw45EW.js} +3 -3
  55. package/src/assets/web-panel/assets/{PersonalDataHub-CptiVBh5.js → PersonalDataHub-BKwUAt43.js} +4 -4
  56. package/src/assets/web-panel/assets/{Pipeline-DkHzgyyI.js → Pipeline-DmFD2QW4.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-DzZvwcKh.js → Privacy-KpuwWvt5.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-CzkCs-5G.js → ProjectInit-Bt8UheX6.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-BB8dcxRD.js → ProjectSettings-2ZeAn9CP.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-B7PW9CFY.js → Projects-zBuet8Zs.js} +1 -1
  61. package/src/assets/web-panel/assets/{Providers-Tfx-ti1V.js → Providers-DcEAnw6L.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-EvWlNhfX.js → QrScannerModal-qF7liYG9.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-CUspgbNC.js → QuickAsk-qiESlVBJ.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-COY2g77J.js → Recommend-Bk-cQyi9.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-BzMBU6E6.js → RemoteSession-CwrekErS.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-RtYRF4YP.js → Reputation-Bmw_UQtW.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-Bva3l9Lc.js → Row-CPdqZIUX.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-BhjzLvW3.js → RssFeed-D_W-xxvS.js} +2 -2
  69. package/src/assets/web-panel/assets/{Search-BYzT2PTR.js → Search-Hu0oDFj_.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-Bcl4-KTv.js → Security-DeRxUwmq.js} +3 -3
  71. package/src/assets/web-panel/assets/{Services-BRRa4A0f.js → Services-CsNmHFkf.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DYQ016qy.js → Skeleton-gv_Vz0tN.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-CAUKL9JA.js → Skills-Dgg-_rCB.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-BTyUqfuD.js → Sla-Bpu-bsEJ.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-CUjMihrs.js → SpeechSettings-CrhleHuF.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-CvfOSupr.js → SyncSettings-JHjUN6I9.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-EvjNXrWH.js → Tasks-DKRWKkl9.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-wPAp0EoM.js → Templates-leiWntLq.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-CP0D-q9Q.js → Tenant--1bYulvn.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-CQ0f2iFg.js → Terminal-C0y6FvSS.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-D3JrGSPb.js → TimelineRenderer-CQK4PVv4.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-yXf2PPp9.js → Tokens-DbIvF-DV.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-DfmMOoZ2.js → Trigger-CkXJ2vuq.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-BTCyMgf1.js → Trust-B02WXJPw.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-DKCwIBHi.js → UkeySign-VPMkfzmw.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-CQpDSzLO.js → VideoEditing-C5ezUnah.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-CyFrzC3K.js → Wallet-CYfvYRrY.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-D6Nr_1kd.js → WebAuthn-DtKl-kpr.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-CgR9tNrB.js → WorkflowEditor-DACITF-u.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-CRG_IeyP.js → chat-qnygfnLi.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-MdE3TStI.js → colors-D4mISLBD.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-B0LRuiNV.js → compact-item-BBPfxYGL.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-B_V5fjcX.js → createContext-Byx4ndHp.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-DBy6gsuI.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DSL-c_hr.js → hasIn-CGjLkkn3.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DE7bSYmW.js → index-B8UpadHC.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BD0w-888.js → index-B9jH-h4X.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BbZZ7P_c.js → index-BN7_TSgU.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BIDCNwy6.js → index-BNe2lCk6.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CkN53KiJ.js → index-B_fHPZ8E.js} +1 -1
  101. package/src/assets/web-panel/assets/index-BfEDXk_E.js +1 -0
  102. package/src/assets/web-panel/assets/{index-BsAEd-Do.js → index-BklGH3YI.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CS3bOhV7.js → index-BmKYaaGP.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B3iW-mhn.js → index-BxQF1wCU.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-SmQfEHjp.js → index-ByA1NyFP.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-0200QxC4.js → index-BzeBBAl5.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-c8OqO3rq.js → index-C3abGsSW.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C-aKWR2v.js → index-C9tcHs46.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BNhWoD6d.js → index-CD5Btq6p.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CVDi4rS9.js → index-CFMWjuav.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CEOAZm5j.js → index-CMj8qmpX.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C67dPW0L.js → index-CVUJjQAT.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-D3pJBTvo.js → index-CWhI8G14.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DtOTppk8.js → index-CZjNamSU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DRRY44XP.js → index-CmHE-lY_.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Tg3yl8wc.js → index-CoA8WsVr.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CXMeisJK.js → index-Cpg3AWRy.js} +1 -1
  118. package/src/assets/web-panel/assets/index-CrxUwNM8.js +1 -0
  119. package/src/assets/web-panel/assets/{index-Bq8-2Ibv.js → index-CsVuQsY1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BHp1nSur.js → index-CydHMjwc.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CPYshcic.js → index-DH6iC5b2.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DBwBZwio.js → index-DZXhKAk9.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Didyuq2Z.js → index-D_g9mA1N.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CdHMc9LQ.js → index-DboTeuPF.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C5dqieYX.js → index-DfgpKd64.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CdplnAS9.js → index-Dmfe0L2Z.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-KaSejHjf.js → index-Dzni_5Qw.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BpwGsAA-.js → index-J5JkStvY.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-OBhlHSMN.js → index-Ne8UGllV.js} +3 -3
  130. package/src/assets/web-panel/assets/{index-CZICtYJ0.js → index-O09jXbir.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DVgTf7CZ.js → index-Y7el_3WS.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BQAsL19t.js → index-c_tBkIlU.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BMm8tO2X.js → index-lKJWAmd4.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CNytQuFq.js → index-xzRKTy0R.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-P8SBN6Di.js → initDefaultProps-XuhfEIhB.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-BubbjUT_.js → motion-Cbxh6AxO.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-Chcykv0I.js → move-C7IEnFly.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-DyiYuGDu.js → mtc-parser-lLADx4LL.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-Rdwb_Neb.js → omit-mIbic_k-.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-CCr0MYHl.js → pickAttrs-_xIYEqu3.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-B1ZXz3bb.js → placementArrow-ClB-E0ny.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-BGEdwej6.js → responsiveObserve-D36Bg2ut.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-CpnsUMaT.js → slide-CUuO08Bl.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-C7x-TVp_.js → statusUtils-BKahwLbv.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-CC5k_791.js → styleChecker-2pT-T8vy.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-BpZFKsJW.js → useFlexGapSupport-DyH5g7Rg.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-CVq5HySy.js → useFs-CTOauB3X.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-BGkdLryu.js → usePersonalDataHub-B02JYIMe.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-uLtOUEK-.js → vnode-Do22wQrc.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-BfVC9iUs.js → zoom-BfnL7rit.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +3 -3
  153. package/src/commands/agent.js +8 -0
  154. package/src/commands/background-session.js +31 -3
  155. package/src/commands/chat.js +5 -1
  156. package/src/commands/eval.js +86 -28
  157. package/src/commands/llm.js +104 -1
  158. package/src/commands/plugin.js +161 -1
  159. package/src/commands/sandbox.js +121 -2
  160. package/src/commands/serve.js +11 -2
  161. package/src/commands/skill.js +29 -0
  162. package/src/data/changelog.json +26 -0
  163. package/src/gateways/ws/session-protocol.js +13 -0
  164. package/src/gateways/ws/ws-agent-handler.js +17 -0
  165. package/src/gateways/ws/ws-server.js +3 -0
  166. package/src/gateways/ws/ws-session-state.js +131 -0
  167. package/src/generated/cc-agent-protocol.schema.json +48 -1
  168. package/src/lazy-dispatch.js +8 -1
  169. package/src/lib/agent-sandbox.js +337 -53
  170. package/src/lib/app-server/cli-agent-kernel-adapter.js +28 -0
  171. package/src/lib/app-server/server.js +93 -0
  172. package/src/lib/background-agent-keeper-client.js +2 -0
  173. package/src/lib/background-agent-keeper-protocol.js +7 -0
  174. package/src/lib/background-agent-list-index.js +222 -0
  175. package/src/lib/background-agent-supervisor.js +232 -47
  176. package/src/lib/codex-app-server-adapter.js +82 -27
  177. package/src/lib/context-memory-kernel/durable-memory-port.js +31 -8
  178. package/src/lib/context-memory-kernel/provider-context.js +118 -19
  179. package/src/lib/deferred-question-context.js +278 -0
  180. package/src/lib/eval/evidence.js +202 -64
  181. package/src/lib/eval/plugin-suite.js +1181 -0
  182. package/src/lib/eval/runner.js +10 -3
  183. package/src/lib/evolution/agent-evolution-runtime-composition.js +236 -1
  184. package/src/lib/evolution/agent-model-projection.js +97 -1
  185. package/src/lib/evolution/evidence-backed-wiki-maintainer.js +154 -1
  186. package/src/lib/evolution/evolution-artifact-ports.js +6 -0
  187. package/src/lib/evolution/evolution-deployment-loader.js +87 -3
  188. package/src/lib/evolution/evolution-eval-gate.js +8 -0
  189. package/src/lib/evolution/evolution-eval-runtime-composition.js +255 -0
  190. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +58 -2
  191. package/src/lib/evolution/evolution-ledger-file-backend.js +23 -2
  192. package/src/lib/evolution/evolution-ledger-manifest-chain.js +223 -7
  193. package/src/lib/evolution/evolution-ledger-v2-journal.js +525 -0
  194. package/src/lib/evolution/evolution-ledger-v2-manifest-backend.js +46 -2
  195. package/src/lib/evolution/evolution-ledger.js +57 -1
  196. package/src/lib/evolution/evolution-run-ledger-adapter.js +93 -0
  197. package/src/lib/evolution/evolution-run-wiki-evidence-resolver.js +259 -0
  198. package/src/lib/evolution/governed-hub-llm.js +238 -5
  199. package/src/lib/evolution/governed-hub-resolver.js +82 -4
  200. package/src/lib/evolution/governed-hub-skill.js +11 -5
  201. package/src/lib/evolution/governed-skill-synthesis-provider-chat.js +10 -1
  202. package/src/lib/evolution/skill-runtime-revalidation-ledger-adapter.js +254 -0
  203. package/src/lib/evolution/skill-runtime-revalidation.js +530 -0
  204. package/src/lib/evolution/skill-target-matrix-eval.js +4 -4
  205. package/src/lib/evolution/wiki-evidence-commit-guard.js +366 -0
  206. package/src/lib/evolution/wiki-informed-skill-proposer.js +13 -1
  207. package/src/lib/goal-context.js +14 -5
  208. package/src/lib/interaction-adapter.js +166 -1
  209. package/src/lib/model-capabilities.js +271 -0
  210. package/src/lib/model-context-catalog.js +105 -0
  211. package/src/lib/model-context-window.js +4 -49
  212. package/src/lib/openai-responses.js +428 -0
  213. package/src/lib/plugin-runtime/scopes.js +7 -1
  214. package/src/lib/remote-read-loop-guard.js +2 -2
  215. package/src/lib/runtime-usage-ledger.js +16 -0
  216. package/src/lib/session-host-snapshot.js +16 -0
  217. package/src/lib/skill-loader.js +12 -0
  218. package/src/lib/with-file-lock.js +3 -1
  219. package/src/repl/agent-repl.js +5 -1
  220. package/src/runtime/agent-core.js +348 -23
  221. package/src/runtime/agent-runtime.js +7 -0
  222. package/src/runtime/coding-agent-contract-shared.cjs +13 -1
  223. package/src/runtime/headless-runner.js +4 -1
  224. package/src/runtime/headless-stream.js +283 -45
  225. package/src/runtime/runtime-factory.js +26 -2
  226. package/src/workers/background-agent-keeper.js +23 -13
  227. package/src/workers/background-agent-worker.js +27 -13
  228. package/src/assets/web-panel/assets/ChatBubbleRenderer-Bi2SY9E_.js +0 -1
  229. package/src/assets/web-panel/assets/PdhVaultBrowser-fYmQzmTA.js +0 -7
  230. package/src/assets/web-panel/assets/devWarning-BtFLt3qI.js +0 -1
  231. package/src/assets/web-panel/assets/index-BhuWQHeG.js +0 -1
  232. package/src/assets/web-panel/assets/index-D-4tFek3.js +0 -1
@@ -1,5 +1,6 @@
1
1
  /** OS-isolated shell execution for the coding agent. */
2
2
  import fs from "node:fs";
3
+ import os from "node:os";
3
4
  import path from "node:path";
4
5
  import { proxyEnv } from "./sandbox-egress-proxy.js";
5
6
  import executionBroker from "./process-execution-broker/index.js";
@@ -10,8 +11,15 @@ export const AGENT_SANDBOX_MODES = Object.freeze([
10
11
  "workspace-write",
11
12
  "strict",
12
13
  ]);
14
+ export const AGENT_SANDBOX_CAPABILITY_SCHEMA =
15
+ "chainlesschain.agent-sandbox-capabilities/v1";
13
16
  export const _deps = {
14
17
  spawnSync: (...args) => executionBroker.spawnSync(...args),
18
+ host: () => ({
19
+ platform: process.platform,
20
+ release: os.release(),
21
+ arch: process.arch,
22
+ }),
15
23
  };
16
24
 
17
25
  function stringList(value) {
@@ -322,46 +330,298 @@ export function enforceSandboxFailClosed(sandbox, reason = "safe") {
322
330
  };
323
331
  }
324
332
 
333
+ function capability(id, details = {}) {
334
+ return { id, ...details };
335
+ }
336
+
337
+ function addUniqueCapability(target, entry) {
338
+ if (!target.some((candidate) => candidate.id === entry.id)) {
339
+ target.push(entry);
340
+ }
341
+ }
342
+
343
+ /**
344
+ * Describe the exact legacy agent-shell sandbox request without claiming that
345
+ * a command has run. `enforceable` is backend capability; `applied` is only
346
+ * populated after a child was successfully started through that backend.
347
+ */
348
+ export function assessAgentSandboxCapabilities(sandbox, options = {}) {
349
+ const host = options.host || {
350
+ platform: process.platform,
351
+ release: os.release(),
352
+ arch: process.arch,
353
+ };
354
+ const execution = options.execution || null;
355
+ const availability = options.availability || null;
356
+ const requested = [];
357
+ const enforceable = [];
358
+ const unsupported = [];
359
+
360
+ if (!sandbox) {
361
+ return {
362
+ schema: AGENT_SANDBOX_CAPABILITY_SCHEMA,
363
+ host: {
364
+ platform: String(host.platform),
365
+ release: String(host.release),
366
+ arch: String(host.arch),
367
+ },
368
+ backend: {
369
+ engine: null,
370
+ isolationLevel: "policy-only",
371
+ availabilityChecked: false,
372
+ available: null,
373
+ reason: null,
374
+ },
375
+ status: "disabled",
376
+ execution: {
377
+ observed: false,
378
+ attempted: false,
379
+ started: false,
380
+ },
381
+ requested,
382
+ enforceable,
383
+ applied: [],
384
+ unsupported,
385
+ };
386
+ }
387
+
388
+ const engine = String(sandbox.engine || "");
389
+ const policy = sandbox.policy || normalizeSandboxPolicy({}, sandbox.cwd);
390
+ const supportedEngine = engine === "docker" || engine === "bubblewrap";
391
+ const supportedPlatform =
392
+ engine !== "bubblewrap" || host.platform === "linux";
393
+ const isolationCapability =
394
+ engine === "docker"
395
+ ? "isolation.container"
396
+ : engine === "bubblewrap"
397
+ ? "isolation.linux-namespace"
398
+ : "isolation.unknown";
399
+ const networkCapability = sandbox.network
400
+ ? "network.unrestricted"
401
+ : "network.none";
402
+
403
+ addUniqueCapability(requested, capability(isolationCapability));
404
+ addUniqueCapability(requested, capability("filesystem.workspace-read-write"));
405
+ addUniqueCapability(requested, capability(networkCapability));
406
+
407
+ const filesystemRequests = [
408
+ ["filesystem.additional-read", policy.allowRead],
409
+ ["filesystem.deny-read", policy.denyRead],
410
+ ["filesystem.additional-write", policy.allowWrite],
411
+ ["filesystem.deny-write", policy.denyWrite],
412
+ ];
413
+ for (const [id, values] of filesystemRequests) {
414
+ if (values?.length) {
415
+ addUniqueCapability(
416
+ requested,
417
+ capability(id, { entries: values.length }),
418
+ );
419
+ }
420
+ }
421
+ const domainRuleCount =
422
+ (policy.allowedDomains?.length || 0) + (policy.deniedDomains?.length || 0);
423
+ if (domainRuleCount > 0) {
424
+ addUniqueCapability(
425
+ requested,
426
+ capability("network.domain-policy", { entries: domainRuleCount }),
427
+ );
428
+ }
429
+
430
+ if (!supportedEngine) {
431
+ unsupported.push(
432
+ capability("backend.engine", {
433
+ reason: "unsupported_engine",
434
+ message: `Unsupported agent sandbox engine: ${engine || "<empty>"}`,
435
+ remediation: "Use engine=docker or engine=bubblewrap.",
436
+ }),
437
+ );
438
+ } else if (!supportedPlatform) {
439
+ unsupported.push(
440
+ capability("backend.platform", {
441
+ reason: "bubblewrap_requires_linux",
442
+ message: `bubblewrap is only supported on Linux; host platform is ${host.platform}`,
443
+ remediation: "Use Docker on this host or run bubblewrap on Linux.",
444
+ }),
445
+ );
446
+ } else {
447
+ addUniqueCapability(
448
+ enforceable,
449
+ capability(isolationCapability, {
450
+ enforcement:
451
+ engine === "docker" ? "docker-container" : "bubblewrap-namespaces",
452
+ }),
453
+ );
454
+ addUniqueCapability(
455
+ enforceable,
456
+ capability("filesystem.workspace-read-write", {
457
+ enforcement:
458
+ engine === "docker" ? "docker-bind-mount" : "bubblewrap-bind-mount",
459
+ }),
460
+ );
461
+ addUniqueCapability(
462
+ enforceable,
463
+ capability(networkCapability, {
464
+ enforcement:
465
+ engine === "docker"
466
+ ? sandbox.network
467
+ ? "docker-default-network"
468
+ : "docker-network-none"
469
+ : sandbox.network
470
+ ? "bubblewrap-share-net"
471
+ : "bubblewrap-unshared-network-namespace",
472
+ }),
473
+ );
474
+
475
+ for (const [id, values] of filesystemRequests) {
476
+ if (!values?.length) continue;
477
+ if (engine === "docker") {
478
+ unsupported.push(
479
+ capability(id, {
480
+ reason: "docker_fine_grained_filesystem_unsupported",
481
+ message:
482
+ "The Docker sandbox backend cannot enforce fine-grained filesystem policy; use engine=bubblewrap",
483
+ remediation:
484
+ "Use engine=bubblewrap on Linux or remove the fine-grained rule.",
485
+ }),
486
+ );
487
+ } else if (id === "filesystem.additional-read") {
488
+ unsupported.push(
489
+ capability(id, {
490
+ reason: "bubblewrap_additional_read_not_isolated",
491
+ message:
492
+ "The bubblewrap agent-shell backend exposes the host root read-only and cannot make allowRead an exclusive read boundary",
493
+ remediation:
494
+ "Remove allowRead or use the attested ProcessExecutionBroker sandbox for a supported execution contract.",
495
+ }),
496
+ );
497
+ } else {
498
+ addUniqueCapability(
499
+ enforceable,
500
+ capability(id, {
501
+ entries: values.length,
502
+ enforcement: `bubblewrap-${id.replace("filesystem.", "")}-mount`,
503
+ }),
504
+ );
505
+ }
506
+ }
507
+
508
+ if (domainRuleCount > 0) {
509
+ unsupported.push(
510
+ capability("network.domain-policy", {
511
+ reason: "domain_policy_has_no_non_bypassable_backend",
512
+ message:
513
+ "Domain-restricted sandbox networking has no non-bypassable backend enforcement; refusing unrestricted network access",
514
+ remediation:
515
+ "Disable sandbox networking or use a separately attested dependency-fetch service.",
516
+ }),
517
+ );
518
+ }
519
+ }
520
+
521
+ const executionObserved = execution !== null;
522
+ const executionAttempted = execution?.attempted === true;
523
+ const executionStarted = execution?.started === true;
524
+ const availabilityChecked = availability !== null || executionStarted;
525
+ const available = executionStarted
526
+ ? true
527
+ : availability === null
528
+ ? null
529
+ : availability.available === true;
530
+ const availabilityReason = executionStarted
531
+ ? null
532
+ : availability?.reason || null;
533
+ let status = "ready";
534
+ if (unsupported.length > 0) status = "unsupported";
535
+ else if (executionStarted) status = "applied";
536
+ else if (executionAttempted) status = "failed-to-start";
537
+ else if (availabilityChecked && !available) status = "unavailable";
538
+
539
+ return {
540
+ schema: AGENT_SANDBOX_CAPABILITY_SCHEMA,
541
+ host: {
542
+ platform: String(host.platform),
543
+ release: String(host.release),
544
+ arch: String(host.arch),
545
+ },
546
+ backend: {
547
+ engine,
548
+ isolationLevel: isolationLevel(sandbox),
549
+ availabilityChecked,
550
+ available,
551
+ reason: availabilityReason,
552
+ },
553
+ status,
554
+ execution: {
555
+ observed: executionObserved,
556
+ attempted: executionAttempted,
557
+ started: executionStarted,
558
+ },
559
+ requested,
560
+ enforceable,
561
+ applied: executionStarted ? enforceable.map((entry) => ({ ...entry })) : [],
562
+ unsupported,
563
+ };
564
+ }
565
+
566
+ export function assertSandboxCapabilities(sandbox, options = {}) {
567
+ const report = assessAgentSandboxCapabilities(sandbox, options);
568
+ if (report.unsupported.length === 0) return report;
569
+ const error = new Error(
570
+ `Unsupported sandbox capability request: ${report.unsupported
571
+ .map((entry) => `${entry.id} (${entry.message})`)
572
+ .join("; ")}`,
573
+ );
574
+ error.code = "CONFIG_SANDBOX_CAPABILITY_UNSUPPORTED";
575
+ error.capabilityReport = report;
576
+ throw error;
577
+ }
578
+
579
+ function attachSandboxCapabilityReport(
580
+ result,
581
+ sandbox,
582
+ execution,
583
+ availability,
584
+ host,
585
+ ) {
586
+ return {
587
+ ...result,
588
+ sandboxCapabilities: assessAgentSandboxCapabilities(sandbox, {
589
+ execution,
590
+ availability,
591
+ host,
592
+ }),
593
+ };
594
+ }
595
+
325
596
  export function executeSandboxedShell(command, sandbox, options = {}) {
326
597
  if (!sandbox || !["docker", "bubblewrap"].includes(sandbox.engine)) {
327
598
  throw new Error("A supported agent sandbox configuration is required");
328
599
  }
329
600
  const hostCwd = path.resolve(options.cwd || sandbox.cwd);
330
601
  const policy = sandbox.policy || normalizeSandboxPolicy({}, hostCwd);
331
- // Proxy environment variables are advisory: a child can clear them or open a
332
- // raw socket. Until a backend can enforce egress below the process layer,
333
- // domain-restricted networking must fail closed instead of granting the
334
- // sandbox an unrestricted network namespace.
335
- const egress = options.egressProxy || null;
336
- if (
337
- (policy.allowedDomains.length || policy.deniedDomains.length) &&
338
- sandbox.network
339
- ) {
602
+ const capabilityHost = _deps.host();
603
+ const capabilityReport = assessAgentSandboxCapabilities(sandbox, {
604
+ host: capabilityHost,
605
+ });
606
+ if (capabilityReport.unsupported.length > 0) {
340
607
  return {
341
608
  stdout: "",
342
- stderr:
343
- "Domain-restricted sandbox networking has no non-bypassable backend enforcement; refusing unrestricted network access",
609
+ stderr: capabilityReport.unsupported
610
+ .map((entry) => entry.message)
611
+ .join("; "),
344
612
  exitCode: 1,
345
613
  failedToStart: true,
614
+ sandboxCapabilities: capabilityReport,
346
615
  };
347
616
  }
617
+ // Proxy environment variables are advisory: a child can clear them or open a
618
+ // raw socket. Until a backend can enforce egress below the process layer,
619
+ // domain-restricted networking must fail closed instead of granting the
620
+ // sandbox an unrestricted network namespace.
621
+ const egress = options.egressProxy || null;
348
622
  if (sandbox.engine === "bubblewrap") {
349
623
  return executeBubblewrapShell(command, sandbox, options, hostCwd, policy);
350
624
  }
351
- if (
352
- policy.allowRead.length ||
353
- policy.denyRead.length ||
354
- policy.allowWrite.length ||
355
- policy.denyWrite.length
356
- ) {
357
- return {
358
- stdout: "",
359
- stderr:
360
- "The Docker sandbox backend cannot enforce fine-grained filesystem policy; use engine=bubblewrap",
361
- exitCode: 1,
362
- failedToStart: true,
363
- };
364
- }
365
625
  const args = ["run", "--rm", "--init"];
366
626
  if (!sandbox.network) args.push("--network", "none");
367
627
  args.push("--mount", `type=bind,source=${hostCwd},target=/workspace`);
@@ -397,22 +657,34 @@ export function executeSandboxedShell(command, sandbox, options = {}) {
397
657
  auditContext: options.auditContext,
398
658
  });
399
659
  if (result.error) {
400
- return {
660
+ return attachSandboxCapabilityReport(
661
+ {
662
+ stdout: result.stdout || "",
663
+ stderr:
664
+ result.error.code === "ENOENT"
665
+ ? "Docker is not installed"
666
+ : result.error.message,
667
+ exitCode: typeof result.status === "number" ? result.status : 1,
668
+ failedToStart: true,
669
+ },
670
+ sandbox,
671
+ { attempted: true, started: false },
672
+ { available: false, reason: result.error.message },
673
+ capabilityHost,
674
+ );
675
+ }
676
+ return attachSandboxCapabilityReport(
677
+ {
401
678
  stdout: result.stdout || "",
402
- stderr:
403
- result.error.code === "ENOENT"
404
- ? "Docker is not installed"
405
- : result.error.message,
679
+ stderr: result.stderr || "",
406
680
  exitCode: typeof result.status === "number" ? result.status : 1,
407
- failedToStart: true,
408
- };
409
- }
410
- return {
411
- stdout: result.stdout || "",
412
- stderr: result.stderr || "",
413
- exitCode: typeof result.status === "number" ? result.status : 1,
414
- signal: result.signal || null,
415
- };
681
+ signal: result.signal || null,
682
+ },
683
+ sandbox,
684
+ { attempted: true, started: true },
685
+ { available: true, reason: null },
686
+ capabilityHost,
687
+ );
416
688
  }
417
689
 
418
690
  function executeBubblewrapShell(command, sandbox, options, hostCwd, policy) {
@@ -469,22 +741,34 @@ function executeBubblewrapShell(command, sandbox, options, hostCwd, policy) {
469
741
  auditContext: options.auditContext,
470
742
  });
471
743
  if (result.error) {
472
- return {
744
+ return attachSandboxCapabilityReport(
745
+ {
746
+ stdout: result.stdout || "",
747
+ stderr:
748
+ result.error.code === "ENOENT"
749
+ ? "bubblewrap is not installed"
750
+ : result.error.message,
751
+ exitCode: typeof result.status === "number" ? result.status : 1,
752
+ failedToStart: true,
753
+ },
754
+ sandbox,
755
+ { attempted: true, started: false },
756
+ { available: false, reason: result.error.message },
757
+ _deps.host(),
758
+ );
759
+ }
760
+ return attachSandboxCapabilityReport(
761
+ {
473
762
  stdout: result.stdout || "",
474
- stderr:
475
- result.error.code === "ENOENT"
476
- ? "bubblewrap is not installed"
477
- : result.error.message,
763
+ stderr: result.stderr || "",
478
764
  exitCode: typeof result.status === "number" ? result.status : 1,
479
- failedToStart: true,
480
- };
481
- }
482
- return {
483
- stdout: result.stdout || "",
484
- stderr: result.stderr || "",
485
- exitCode: typeof result.status === "number" ? result.status : 1,
486
- signal: result.signal || null,
487
- };
765
+ signal: result.signal || null,
766
+ },
767
+ sandbox,
768
+ { attempted: true, started: true },
769
+ { available: true, reason: null },
770
+ _deps.host(),
771
+ );
488
772
  }
489
773
 
490
774
  /**
@@ -2,6 +2,7 @@ import { PassThrough } from "node:stream";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import {
4
4
  assertSandboxAvailable,
5
+ assertSandboxCapabilities,
5
6
  normalizeAgentSandboxMode,
6
7
  } from "../agent-sandbox.js";
7
8
 
@@ -127,6 +128,7 @@ export class CliAgentKernelAdapter {
127
128
  },
128
129
  },
129
130
  );
131
+ assertSandboxCapabilities(sandbox);
130
132
  assertSandboxAvailable(sandbox);
131
133
 
132
134
  const input = new PassThrough();
@@ -166,6 +168,26 @@ export class CliAgentKernelAdapter {
166
168
  binding: event.binding,
167
169
  });
168
170
  }
171
+ if (event.type === "question_request") {
172
+ const answerQuestion = async () => {
173
+ let answer = null;
174
+ try {
175
+ answer = await current.requestQuestion(event);
176
+ } catch {
177
+ // A missing/rejecting host is cancellation, never implicit consent.
178
+ }
179
+ writeLine(input, {
180
+ type: "answer",
181
+ id: event.id,
182
+ answer,
183
+ binding: event.binding,
184
+ });
185
+ };
186
+ // The Headless runtime owns blocking semantics and its timeout. Keep
187
+ // the transport event chain free so a timed-out question can emit
188
+ // question_resolved/result even while a slow host request is pending.
189
+ void answerQuestion().catch(() => {});
190
+ }
169
191
  if (event.type === "result") {
170
192
  session.current = null;
171
193
  current.resolve(event);
@@ -194,6 +216,7 @@ export class CliAgentKernelAdapter {
194
216
  permissionMode,
195
217
  sandbox,
196
218
  interactiveApprovals: true,
219
+ interactiveQuestions: turnOptions.interactiveQuestions === true,
197
220
  includePartialMessages: true,
198
221
  ephemeral: false,
199
222
  evolutionIngress:
@@ -263,6 +286,7 @@ export class CliAgentKernelAdapter {
263
286
  options = {},
264
287
  emit,
265
288
  requestApproval,
289
+ requestQuestion,
266
290
  }) {
267
291
  const session = await this._session(threadId, options);
268
292
  if (session.current) {
@@ -283,6 +307,10 @@ export class CliAgentKernelAdapter {
283
307
  turnId,
284
308
  emit,
285
309
  requestApproval,
310
+ requestQuestion:
311
+ typeof requestQuestion === "function"
312
+ ? requestQuestion
313
+ : async () => null,
286
314
  resolve,
287
315
  reject,
288
316
  };
@@ -10,6 +10,7 @@ import { AppServerGraphRuntime } from "./graph-runtime.js";
10
10
  import { captureAgentSkillOutcomeIndex } from "../evolution/agent-evolution-runtime-composition-brand.js";
11
11
  import { captureSkillVectorAuthority } from "../skill-vector-authority.js";
12
12
  import { captureSkillRetrievalRevocationReader } from "../evolution/skill-retrieval-revocation-authority.js";
13
+ import { sameInteractionBinding } from "../interaction-binding.js";
13
14
  import { compileGraphDefinition } from "../graph-kernel/compiler.js";
14
15
  import { createCliContextMemoryRuntime } from "../context-memory-kernel/runtime.js";
15
16
  import { isEvolutionWorkbenchCliHost } from "../evolution/evolution-workbench-cli-host.js";
@@ -882,6 +883,10 @@ export class CcAppServer {
882
883
  turnOptions.skillRetrievalRevocationReader =
883
884
  skillRetrievalRevocationReader;
884
885
  }
886
+ if (this.negotiated) {
887
+ turnOptions.interactiveQuestions =
888
+ this.negotiated.features.includes("deferred_questions");
889
+ }
885
890
  const result = await this.kernel.startTurn({
886
891
  threadId,
887
892
  turnId: attempt.id,
@@ -896,6 +901,7 @@ export class CcAppServer {
896
901
  event,
897
902
  }),
898
903
  requestApproval: (event) => this._requestApproval(turn, event),
904
+ requestQuestion: (event) => this._requestQuestion(turn, event),
899
905
  });
900
906
  const failed = result?.is_error === true || result?.subtype === "error";
901
907
  const output = typeof result?.result === "string" ? result.result : "";
@@ -1137,6 +1143,8 @@ export class CcAppServer {
1137
1143
  turnOptions.skillRetrievalRevocationReader =
1138
1144
  this.skillRetrievalRevocationReader;
1139
1145
  }
1146
+ turnOptions.interactiveQuestions =
1147
+ this.negotiated?.features.includes("deferred_questions") === true;
1140
1148
  const result = await this.kernel.startTurn({
1141
1149
  threadId: turn.threadId,
1142
1150
  turnId: turn.id,
@@ -1144,6 +1152,7 @@ export class CcAppServer {
1144
1152
  options: turnOptions,
1145
1153
  emit: (event) => this._emitKernelEvent(turn, event),
1146
1154
  requestApproval: (event) => this._requestApproval(turn, event),
1155
+ requestQuestion: (event) => this._requestQuestion(turn, event),
1147
1156
  });
1148
1157
  if (turn.interruptRequested) {
1149
1158
  await this._completeTurn(turn, "interrupted", result);
@@ -1321,6 +1330,48 @@ export class CcAppServer {
1321
1330
  );
1322
1331
  return;
1323
1332
  }
1333
+ if (event?.type === "question_request") {
1334
+ if (!this.negotiated?.features.includes("deferred_questions")) return;
1335
+ const blocking = event.blocking !== false && event.mode !== "deferred";
1336
+ if (blocking) turn.status = "waiting_input";
1337
+ turn.revision += 1;
1338
+ await this._notify(
1339
+ "question/requested",
1340
+ { request: this._questionRequest(turn, event) },
1341
+ {
1342
+ threadId: turn.threadId,
1343
+ turnId: turn.id,
1344
+ itemId: `${turn.id}:question:${safeId(event.id, "question")}`,
1345
+ traceId,
1346
+ idempotencyKey: `question-requested:${turn.id}:${event.id}`,
1347
+ },
1348
+ );
1349
+ return;
1350
+ }
1351
+ if (event?.type === "question_resolved") {
1352
+ if (!this.negotiated?.features.includes("deferred_questions")) return;
1353
+ if (event.blocking !== false && event.mode !== "deferred") {
1354
+ turn.status = "running";
1355
+ }
1356
+ turn.revision += 1;
1357
+ await this._notify(
1358
+ "question/resolved",
1359
+ {
1360
+ threadId: turn.threadId,
1361
+ turnId: turn.id,
1362
+ questionId: safeId(event.id, `${turn.id}:question`),
1363
+ mode: event.mode === "deferred" ? "deferred" : "blocking",
1364
+ via: event.via || "unknown",
1365
+ },
1366
+ {
1367
+ threadId: turn.threadId,
1368
+ turnId: turn.id,
1369
+ traceId,
1370
+ idempotencyKey: `question-resolved:${turn.id}:${event.id}:${event.via}`,
1371
+ },
1372
+ );
1373
+ return;
1374
+ }
1324
1375
  if (event?.type === "plan_update") {
1325
1376
  await this._notify(
1326
1377
  "item/completed",
@@ -1394,6 +1445,48 @@ export class CcAppServer {
1394
1445
  return result;
1395
1446
  }
1396
1447
 
1448
+ _questionRequest(turn, event) {
1449
+ const id = safeId(event.id, `${turn.id}:question`);
1450
+ return {
1451
+ id,
1452
+ threadId: turn.threadId,
1453
+ turnId: turn.id,
1454
+ binding: event.binding || null,
1455
+ question: String(event.question || "").slice(0, 16_384),
1456
+ options: Array.isArray(event.options)
1457
+ ? event.options.slice(0, 128)
1458
+ : null,
1459
+ multiSelect: event.multiSelect === true,
1460
+ mode: event.mode === "deferred" ? "deferred" : "blocking",
1461
+ blocking: event.blocking !== false && event.mode !== "deferred",
1462
+ purpose: event.purpose || "decision",
1463
+ contextRevision: Number.isSafeInteger(event.context_revision)
1464
+ ? event.context_revision
1465
+ : null,
1466
+ expiresAt: new Date(this.now() + this.requestTimeoutMs).toISOString(),
1467
+ };
1468
+ }
1469
+
1470
+ async _requestQuestion(turn, event) {
1471
+ if (!this.negotiated?.features.includes("deferred_questions")) return null;
1472
+ const request = this._questionRequest(turn, event);
1473
+ const result = requireObject(
1474
+ await this._requestClient("question/answer", { request }),
1475
+ "question answer",
1476
+ );
1477
+ if (
1478
+ result.questionId !== request.id ||
1479
+ !request.binding ||
1480
+ !sameInteractionBinding(request.binding, result.binding)
1481
+ ) {
1482
+ throw new JsonRpcError(
1483
+ JSON_RPC_ERROR.INVALID_PARAMS,
1484
+ "client returned an invalid or stale question answer",
1485
+ );
1486
+ }
1487
+ return Object.hasOwn(result, "answer") ? result.answer : null;
1488
+ }
1489
+
1397
1490
  async _requestHumanTask({ task }) {
1398
1491
  const result = await this._requestClient("humanTask/decide", { task });
1399
1492
  const response = requireObject(result, "humanTask decision");
@@ -4,6 +4,7 @@ import { createNdjsonReader } from "./background-session-transport.js";
4
4
  import {
5
5
  BACKGROUND_AGENT_KEEPER_ARM,
6
6
  BACKGROUND_AGENT_KEEPER_ARMED,
7
+ BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS,
7
8
  BACKGROUND_AGENT_KEEPER_HELLO,
8
9
  BACKGROUND_AGENT_KEEPER_HEARTBEAT,
9
10
  BACKGROUND_AGENT_KEEPER_HEARTBEAT_INTERVAL_MS,
@@ -244,6 +245,7 @@ export async function connectBackgroundAgentKeeper(options = {}) {
244
245
  BACKGROUND_AGENT_KEEPER_ARM,
245
246
  BACKGROUND_AGENT_KEEPER_ARMED,
246
247
  normalized,
248
+ BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS,
247
249
  );
248
250
  activeTurn = normalized;
249
251
  return normalized;
@@ -50,6 +50,13 @@ export const BACKGROUND_AGENT_KEEPER_IDENTITY_PROBE_TIMEOUT_MS =
50
50
  export const BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS = 5_000;
51
51
  export const BACKGROUND_AGENT_KEEPER_PERSIST_RETRY_TIMEOUT_MS =
52
52
  3 * BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS;
53
+ // ARM durably binds a newly spawned turn. It can contend with a strict state
54
+ // lock and, on Windows, an incumbent identity probe. Keep this deadline
55
+ // independent from short HELLO requests and long destructive RETIRE cleanup.
56
+ export const BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS =
57
+ BACKGROUND_AGENT_KEEPER_IDENTITY_PROBE_TIMEOUT_MS +
58
+ BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS +
59
+ 10_000;
53
60
  // A 20-Agent macOS formal run can leave successfully SIGKILLed process groups
54
61
  // observable for several seconds while launchd reaps their orphaned leaders.
55
62
  // Two seconds made that bounded kernel/reaper delay look like an escaped tree.