chainlesschain 0.162.177 → 0.162.178

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 (207) hide show
  1. package/README.md +10 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DT-VPWuN.js → AIOps-DRftcSue.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-DyOreOVN.js → ActionButton-BFvUaMKR.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DslNsKux.js → Analytics-C0-Rru4P.js} +3 -3
  7. package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
  8. package/src/assets/web-panel/assets/{Artifacts-DoaAtEcY.js → Artifacts-DAJ8B3Un.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DPG3WdJ9.js → Audit-hOk4L1lr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-C_JO6R5G.js → BackgroundAgents-3pbDpM9z.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-Cv3BooyX.js → Backup-BtziGDn9.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-D2uQXWu-.js → BaseInput-kmshphJ3.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-B4Vczyf3.js → Chat-d7tGSosA.js} +5 -5
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-p-_PBpX_.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-qTgk4VeP.js → Checkbox-C4Eh4Tz5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DlLWcIzj.js → Codegen-r7gmhZyA.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-DNO73qp7.js → Col-U7mDaGlL.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-vRDNpc4j.js → Community-Bpu8aH1T.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-CEWtIXni.js → Compact-CHb2XBJe.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-KgYC9Fxi.js → Compliance-Cn_r4dey.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-zj5wvkpT.js → Cowork-CdMWfDcz.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-BLDoCozU.js → Cron-BtnREHWy.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BYnff4VY.js → Crosschain-BKI9TSzr.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-C75VFsVm.js → DID-pkNubzzJ.js} +2 -2
  25. package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
  26. package/src/assets/web-panel/assets/{Dropdown-B5dbO4Kx.js → Dropdown-DLyFVxDc.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-BDipZtHJ.js → EmailListRenderer-CtUWfYVq.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DmIzt8jj.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-D9QOS-uW.js → Federation-D8lsDGus.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-B47HRwAm.js → FormItemContext-CRYt_aIw.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-3R4mXmgV.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-DrNXZf1C.js → Git-BXj5Dney.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-BGd7JR98.js → Governance-Cm-I8RMz.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-D-2he1ed.js → Inference-CPvbhvgt.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-C0sHIbK5.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-DiBQO-jL.js → Logs-BZY_3CRZ.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-DL_5eV2D.js → MarkdownRenderer-up0BW6pv.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-VR59OdrC.js → Marketplace-C5MEJ2Qe.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DrPzwSd3.js → McpTools-ihdrn43I.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-CBgKALwQ.js → Memory-Br8bPMlh.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-pQ9Tn-Mn.js → MobileBridge-BNntgrYW.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-mASB6jyj.js → MobileProjects-BdV915mw.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-DTMgE7HC.js → Mtc-A3wDmlqL.js} +2 -2
  44. package/src/assets/web-panel/assets/{MtcAudit-CwTnCtiL.js → MtcAudit-CF-mBLWM.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-ngm6WU8f.js → Multisig-Iy2k_MSo.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-4YO4Qww9.js → NLProgramming-kk0W7HUb.js} +1 -1
  47. package/src/assets/web-panel/assets/Notes-B5u5t_4S.js +7 -0
  48. package/src/assets/web-panel/assets/{NotificationSettings-r2H8yPKb.js → NotificationSettings-BN0POf6_.js} +1 -1
  49. package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
  50. package/src/assets/web-panel/assets/{Organization-DrO7jRWS.js → Organization-DwWQESuN.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-Cnwu4i4t.js → Overflow-DG6klrcC.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-zi-cDwA_.js → P2P-BwJcKkgZ.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-DBEryDv7.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
  54. package/src/assets/web-panel/assets/{Permissions-lqXK2C3x.js → Permissions-CGMXe4TX.js} +4 -4
  55. package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
  56. package/src/assets/web-panel/assets/{Pipeline-Kep5KAGW.js → Pipeline-BzJfeoGt.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-CHdvOAh1.js → Privacy-DLh3Bblx.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-BhKfdwe9.js → ProjectInit-USVWW36c.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Yavk9K8A.js → ProjectSettings-CiiOn62h.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-Bfym6SQn.js → Providers-CBPWWzpu.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-CLSQcrlR.js → QrScannerModal-QVwoRUq3.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-VPa2WKQN.js → QuickAsk-CXnR-2Vn.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-CGXR8jVU.js → Recommend-ClaNzjmF.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-C_20YfMB.js → RemoteSession-C3rGw8vJ.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-awZh68UV.js → Reputation-Ci-OWAoP.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-Ctb4oiYN.js → Row-DRhAwXOS.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-D3sdjvUV.js → RssFeed-BQLJQ2_y.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-C-zfA4kT.js → Search-QQUpkfFd.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-D9XlmHA3.js → Security-DdXKzuKT.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-C3UKnr41.js → Services-x2Zh62Qd.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-BQxagZfF.js → Skeleton-GdY4KwRz.js} +1 -1
  73. package/src/assets/web-panel/assets/Skills-Bv4tY1Fd.js +1 -0
  74. package/src/assets/web-panel/assets/{Sla-DveENvek.js → Sla-C3QnM-11.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-BFjXLNgF.js → SpeechSettings-Bl3ytvmI.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-BpHgbaP9.js → SyncSettings-Wp9IwTsP.js} +2 -2
  77. package/src/assets/web-panel/assets/Tasks-CF3rIrDe.js +1 -0
  78. package/src/assets/web-panel/assets/{Templates-DEiaoyve.js → Templates-CGfvVVM9.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-ITg774nY.js → Tenant-CVXmwQ3U.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-D3ZBcvnb.js → Terminal-bvwrt03E.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BsLU6JjU.js → TimelineRenderer-D0g74KhH.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-Cb5Pquc9.js → Tokens-BH4IwzlT.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-Dwfy-m9N.js → Trigger-DJOpM533.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CnlSRGG0.js → Trust-B43EPRLr.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-Y4TlvKVo.js → UkeySign-BmBFG-em.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-BpKLtTTO.js → VideoEditing-n9oJwB8k.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-LLBzIq8x.js → Wallet-D5QeivHp.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-BeSRiusP.js → WebAuthn-DcNy7igO.js} +4 -4
  89. package/src/assets/web-panel/assets/{WorkflowEditor-BK_l1tXO.js → WorkflowEditor-BVjc7-5-.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-DYd-X7Wg.js → chat-Dy5Tfj3m.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-C9uip71j.js → colors-C4c2CNZU.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-JBrfjUP6.js → compact-item-DPa3O5vN.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-D03fbuiq.js → createContext-TLcfNA6_.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DLQOR6l-.js → hasIn-D41LVFkp.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-rIxxfdTN.js → index-0oevYjfT.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CChaISMb.js → index-388pLGJ1.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BfOs_bmg.js → index-B8nLBZbv.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-D-1SqEpQ.js → index-BPTGAjee.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BYv-LWdy.js → index-BPtrOBmW.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Cpn19c9k.js → index-BQiIxHBy.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BpYKLrUT.js → index-BSM1cHVK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CS63r8h3.js → index-BYPr9fkz.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Q7mmL6w4.js → index-BsQ7Ev6i.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-SO6lgMg0.js → index-Btk9qLL2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-iahNhZwm.js → index-BvmziZSG.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BnQgRjsm.js → index-BvopLC_T.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Ba-Ps_AJ.js → index-C7xhTVyP.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BuNFCZCx.js → index-CNk_ZooP.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CL0ixCxk.js → index-CQrEHoOG.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CChQBM1d.js → index-CSxex23J.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-5YN7F5bO.js → index-CVjgm992.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CwoDpKzW.js → index-CWK4zOPe.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BcBZwlnG.js → index-CX0VsoP4.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B46YcgsV.js → index-CXl0YPNG.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-l08afIbV.js → index-Cip7LWml.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-6GuLRpBQ.js → index-Cq_hlWNt.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DYLZY4uh.js → index-CzZ49YZL.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B0X76LjX.js → index-D2Nkivlm.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BdH9l8wl.js → index-DBUgRs4D.js} +1 -1
  121. package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
  122. package/src/assets/web-panel/assets/{index-D4UY5Z60.js → index-DNsBj2Ob.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Ce0Bf1YF.js → index-Di4X8cfI.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ByHO3SqZ.js → index-DljFsVGI.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C2zmOsyD.js → index-Korc3QIe.js} +1 -1
  126. package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
  127. package/src/assets/web-panel/assets/{index-BNCdRmWf.js → index-MKZDje0H.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-D8KvuDz0.js → index-OHAfRu_3.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DaokIHt3.js → index-WEJr8PL5.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CILVyK3b.js → index-WinCp6du.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CVZWiUE_.js → index-Yjr6cqSK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CqWk1FLG.js → index-iQ6gtFih.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DNMAAUVk.js → index-pt3s7yvV.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Ck17i0OD.js → index-tQ3igERQ.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-CG9z1c6w.js → initDefaultProps-BFZu87WZ.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-B1Ky7Zff.js → motion-DJIo7qvt.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DME8X2P1.js → move-Cfr5qknL.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-cuJYSWB7.js → mtc-parser-Bgc-OadH.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-UI_EE0uZ.js → omit-X3WI-TNp.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-BIoE_Z_V.js → pickAttrs-pJhU9IxK.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-B48-9HKN.js → placementArrow-BNg_Vj3T.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-D7x_GDgD.js → responsiveObserve-TeSEGQ5-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-DjzC5_7m.js → slide-D_t_P0bv.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-C6BIymhh.js → statusUtils-DrrIMwAT.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-B4dGrdD9.js → styleChecker-BjZCuFRm.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-Bken4aNE.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-BMlqECqv.js → useFs-BidCpfLX.js} +1 -1
  148. package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
  149. package/src/assets/web-panel/assets/{vnode-CKJQmxa0.js → vnode-BrbcRiHZ.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-CaZunuau.js → zoom-PISX7AkR.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/commands/__tests__/hub-wechat.test.js +45 -0
  153. package/src/commands/background-session.js +5 -2
  154. package/src/commands/context.js +33 -1
  155. package/src/commands/hub.js +473 -39
  156. package/src/commands/init.js +212 -110
  157. package/src/commands/llm.js +22 -6
  158. package/src/commands/skill.js +11 -1
  159. package/src/data/changelog.json +76 -270
  160. package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
  161. package/src/harness/golden-transcript.js +3 -0
  162. package/src/index.js +18 -7
  163. package/src/lib/approval-authority-store.js +891 -0
  164. package/src/lib/background-interaction-resolver.js +399 -54
  165. package/src/lib/background-session-transport.js +3 -1
  166. package/src/lib/context-breakdown.js +82 -3
  167. package/src/lib/event-runtime-host.js +225 -0
  168. package/src/lib/event-runtime-store.js +102 -21
  169. package/src/lib/event-runtime-worker.js +70 -2
  170. package/src/lib/hooks-v2-producers.js +33 -8
  171. package/src/lib/hooks-v2-runtime.js +360 -40
  172. package/src/lib/interaction-adapter.js +66 -0
  173. package/src/lib/operation-fingerprint.js +107 -2
  174. package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
  175. package/src/lib/personal-data-hub-wiring.js +327 -52
  176. package/src/lib/process-execution-broker/credential-agent.js +954 -111
  177. package/src/lib/process-execution-broker/index.js +369 -85
  178. package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
  179. package/src/lib/provider-http-error.js +94 -0
  180. package/src/lib/remote-approval-bridge.js +222 -26
  181. package/src/lib/side-effect-ledger-store.js +65 -14
  182. package/src/lib/skill-loader.js +215 -12
  183. package/src/lib/skill-process-broker.js +15 -1
  184. package/src/lib/sub-agent-context.js +42 -0
  185. package/src/lib/turn-binding-store.js +64 -15
  186. package/src/lib/turn-binding.js +85 -16
  187. package/src/repl/agent-repl.js +40 -6
  188. package/src/repl/remote-approval.js +13 -13
  189. package/src/repl/repl-turn-binding.js +46 -16
  190. package/src/runtime/agent-core.js +286 -35
  191. package/src/runtime/coding-agent-contract-shared.cjs +16 -0
  192. package/src/runtime/headless-runner.js +147 -34
  193. package/src/runtime/headless-stream.js +147 -7
  194. package/src/workers/background-agent-worker.js +70 -38
  195. package/src/assets/web-panel/assets/AppLayout-BNJJAYME.js +0 -9
  196. package/src/assets/web-panel/assets/ChatBubbleRenderer-DE6reP99.js +0 -1
  197. package/src/assets/web-panel/assets/Dashboard-C4Gutni2.js +0 -3
  198. package/src/assets/web-panel/assets/Notes-DP1k45mF.js +0 -7
  199. package/src/assets/web-panel/assets/OrderTableRenderer-CoM_Zw0J.js +0 -1
  200. package/src/assets/web-panel/assets/PersonalDataHub-b63T3HJM.js +0 -9
  201. package/src/assets/web-panel/assets/Projects-CN8E_5Mq.js +0 -1
  202. package/src/assets/web-panel/assets/Skills-q6eb6KPZ.js +0 -1
  203. package/src/assets/web-panel/assets/Tasks-DvepRb8-.js +0 -1
  204. package/src/assets/web-panel/assets/devWarning-B8LQ8leS.js +0 -1
  205. package/src/assets/web-panel/assets/index-Bh8BPtqR.js +0 -1
  206. package/src/assets/web-panel/assets/index-CeVrHLzZ.js +0 -1
  207. package/src/assets/web-panel/assets/usePersonalDataHub-DLdrfmMa.js +0 -1
@@ -59,6 +59,7 @@ import {
59
59
  } from "../lib/idempotency.js";
60
60
  import { buildSearchCommand } from "../lib/search-command.js";
61
61
  import { discoverCommands } from "../lib/slash-commands.js";
62
+ import { createSkillProcessBroker } from "../lib/skill-process-broker.js";
62
63
  import {
63
64
  isRetryableStreamError,
64
65
  STREAM_RETRY_BASE_MS,
@@ -79,12 +80,21 @@ import {
79
80
  imageUrlBlockToAnthropic,
80
81
  } from "../lib/image-input.js";
81
82
  import { executeToolSearch, gateDeferredMcpCall } from "./mcp-tool-search.js";
82
- import { emitHooksV2Event } from "../lib/hooks-v2-producers.js";
83
+ import {
84
+ emitHooksV2Event,
85
+ executeHooksV2Event,
86
+ } from "../lib/hooks-v2-producers.js";
83
87
  import {
84
88
  admitTool,
85
89
  buildToolAttribution,
86
90
  } from "../lib/agent-tool-admission.js";
87
91
  import { evaluateUnattendedShellAction } from "../lib/unattended-action-policy.js";
92
+ import {
93
+ formatProviderHttpError,
94
+ formatProviderResponseError,
95
+ } from "../lib/provider-http-error.js";
96
+
97
+ export { formatProviderHttpError };
88
98
 
89
99
  /**
90
100
  * Names of MCP servers currently mounted by an in-flight run_skill call.
@@ -660,6 +670,33 @@ async function requestInteractivePermission(
660
670
  cwd,
661
671
  confirmArgs,
662
672
  ) {
673
+ const hooksV2 = await executeHooksV2Event(
674
+ "PermissionRequest",
675
+ {
676
+ schema_version: 1,
677
+ session_id: context.sessionId || null,
678
+ turn_id: context.turnId || null,
679
+ tool_use_id: context.toolCallId || null,
680
+ tool_name: name,
681
+ input_keys:
682
+ args && typeof args === "object" ? Object.keys(args).sort() : [],
683
+ reason: confirmArgs?.reason || null,
684
+ cwd,
685
+ },
686
+ { failClosed: true },
687
+ );
688
+ if (hooksV2.decision === "allow") return true;
689
+ if (hooksV2.blocked || hooksV2.decision === "block") {
690
+ emitHooksV2Event("PermissionDenied", {
691
+ schema_version: 1,
692
+ session_id: context.sessionId || null,
693
+ turn_id: context.turnId || null,
694
+ tool_use_id: context.toolCallId || null,
695
+ tool_name: name,
696
+ source: "hooks-v2",
697
+ });
698
+ return false;
699
+ }
663
700
  const verdict = runSettingsPermissionRequestHooks(
664
701
  name,
665
702
  args,
@@ -668,9 +705,31 @@ async function requestInteractivePermission(
668
705
  confirmArgs?.reason,
669
706
  );
670
707
  if (verdict.decision === "allow") return true;
671
- if (verdict.decision === "deny") return false;
708
+ if (verdict.decision === "deny") {
709
+ emitHooksV2Event("PermissionDenied", {
710
+ schema_version: 1,
711
+ session_id: context.sessionId || null,
712
+ turn_id: context.turnId || null,
713
+ tool_use_id: context.toolCallId || null,
714
+ tool_name: name,
715
+ source: "settings-hook",
716
+ });
717
+ return false;
718
+ }
672
719
  const confirm = context.permissionConfirm || context.shellConfirm || null;
673
- return typeof confirm === "function" ? await confirm(confirmArgs) : false;
720
+ const approved =
721
+ typeof confirm === "function" ? await confirm(confirmArgs) : false;
722
+ if (!approved) {
723
+ emitHooksV2Event("PermissionDenied", {
724
+ schema_version: 1,
725
+ session_id: context.sessionId || null,
726
+ turn_id: context.turnId || null,
727
+ tool_use_id: context.toolCallId || null,
728
+ tool_name: name,
729
+ source: typeof confirm === "function" ? "user" : "no-confirmer",
730
+ });
731
+ }
732
+ return approved;
674
733
  }
675
734
 
676
735
  // ─── Tool definitions ────────────────────────────────────────────────────
@@ -1006,13 +1065,14 @@ export function buildSystemPrompt(cwd, opts = {}) {
1006
1065
 
1007
1066
  // Append auto-activated persona skills
1008
1067
  try {
1009
- const loader = new CLISkillLoader();
1010
- const allSkills = loader.getResolvedSkills();
1011
- const personaSkills = allSkills.filter(
1012
- (s) => s.category === "persona" && s.activation === "auto",
1013
- );
1068
+ const loader = opts.skillLoader || new CLISkillLoader();
1069
+ const personaSkills = loader.getAutoActivatedPersonas({
1070
+ sessionId: opts.sessionId,
1071
+ turnId: opts.turnId,
1072
+ loadedBecause: "persona_auto",
1073
+ });
1014
1074
  if (typeof opts.onSkillsLoaded === "function") {
1015
- opts.onSkillsLoaded(personaSkills);
1075
+ opts.onSkillsLoaded(personaSkills, loader.getCacheLedger());
1016
1076
  }
1017
1077
  for (const p of personaSkills) {
1018
1078
  if (p.body?.trim()) {
@@ -1810,6 +1870,52 @@ export async function executeTool(name, args, context = {}) {
1810
1870
  // capable: a `block` (exit 2 / {decision:block}) stops the tool here, an
1811
1871
  // `ask` routes to the confirmer. Runs after permission resolution so a
1812
1872
  // settings deny / host deny short-circuits before any hook process spawns.
1873
+ const hooksV2Pre = await executeHooksV2Event(
1874
+ "PreToolUse",
1875
+ {
1876
+ schema_version: 1,
1877
+ session_id: context.sessionId || null,
1878
+ turn_id: context.turnId || null,
1879
+ tool_use_id: context.toolCallId || null,
1880
+ tool_name: name,
1881
+ input_keys:
1882
+ args && typeof args === "object" ? Object.keys(args).sort() : [],
1883
+ cwd,
1884
+ },
1885
+ { failClosed: true },
1886
+ );
1887
+ if (hooksV2Pre.blocked || hooksV2Pre.decision === "block") {
1888
+ return {
1889
+ error: `[Hook v2] PreToolUse blocked "${name}".`,
1890
+ policy: { decision: "block", via: "hooks-v2" },
1891
+ };
1892
+ }
1893
+ if (hooksV2Pre.requiresApproval || hooksV2Pre.decision === "ask") {
1894
+ const confirm = context.permissionConfirm || context.shellConfirm || null;
1895
+ const approved =
1896
+ typeof confirm === "function"
1897
+ ? await confirm({
1898
+ tool: name,
1899
+ args,
1900
+ reason: "Hooks v2 PreToolUse requested confirmation",
1901
+ source: "hooks-v2",
1902
+ })
1903
+ : false;
1904
+ if (!approved) {
1905
+ emitHooksV2Event("PermissionDenied", {
1906
+ schema_version: 1,
1907
+ session_id: context.sessionId || null,
1908
+ turn_id: context.turnId || null,
1909
+ tool_use_id: context.toolCallId || null,
1910
+ tool_name: name,
1911
+ source: "hooks-v2",
1912
+ });
1913
+ return {
1914
+ error: `[Hook v2] PreToolUse confirmation denied for "${name}".`,
1915
+ policy: { decision: "deny", via: "hooks-v2" },
1916
+ };
1917
+ }
1918
+ }
1813
1919
  if (hookDb) {
1814
1920
  try {
1815
1921
  await executeHooks(hookDb, HookEvents.PreToolUse, {
@@ -1849,6 +1955,8 @@ export async function executeTool(name, args, context = {}) {
1849
1955
  parentMessages: context.parentMessages,
1850
1956
  interaction: context.interaction,
1851
1957
  sessionId: context.sessionId || null,
1958
+ turnId: context.turnId || null,
1959
+ toolCallId: context.toolCallId || null,
1852
1960
  // Parent LLM config — documented at toolContext as forwarded to
1853
1961
  // spawn_sub_agent for provider/key inheritance; without this line it
1854
1962
  // never actually reached executeToolInner (sub-agents silently fell
@@ -2660,6 +2768,8 @@ async function executeToolInner(
2660
2768
  parentMessages,
2661
2769
  interaction,
2662
2770
  sessionId,
2771
+ turnId,
2772
+ toolCallId,
2663
2773
  hostManagedToolPolicy,
2664
2774
  externalToolDescriptors,
2665
2775
  externalToolExecutors,
@@ -3883,16 +3993,62 @@ async function executeToolInner(
3883
3993
  multiSelect: args.multiSelect === true,
3884
3994
  timeoutMs:
3885
3995
  typeof args.timeoutMs === "number" ? args.timeoutMs : 60000,
3996
+ defaultValue: args.defaultValue,
3997
+ onTimeout: args.onTimeout || "error",
3998
+ onReject: args.onReject || "error",
3886
3999
  sessionId,
4000
+ turnId,
4001
+ toolUseId: toolCallId,
3887
4002
  });
3888
4003
  return attachDescriptor({ answer });
3889
4004
  } catch (err) {
3890
- if (err && err.code === "USER_TIMEOUT") {
4005
+ const failureKind =
4006
+ err?.code === "USER_TIMEOUT"
4007
+ ? "timeout"
4008
+ : [
4009
+ "USER_REJECTED",
4010
+ "INTERACTION_REJECTED",
4011
+ "INTERACTION_CANCELLED",
4012
+ ].includes(err?.code)
4013
+ ? "reject"
4014
+ : null;
4015
+ const strategy =
4016
+ failureKind === "timeout"
4017
+ ? args.onTimeout || "error"
4018
+ : failureKind === "reject"
4019
+ ? args.onReject || "error"
4020
+ : "error";
4021
+ if (failureKind && strategy === "useDefault") {
4022
+ if (!Object.prototype.hasOwnProperty.call(args, "defaultValue")) {
4023
+ return attachDescriptor({
4024
+ error: `${failureKind === "timeout" ? "user_timeout" : "user_rejected"}: useDefault requires defaultValue`,
4025
+ });
4026
+ }
4027
+ return attachDescriptor({
4028
+ answer: args.defaultValue,
4029
+ fallback: "default",
4030
+ reason: failureKind,
4031
+ });
4032
+ }
4033
+ if (failureKind && strategy === "skip") {
4034
+ return attachDescriptor({
4035
+ answer: null,
4036
+ skipped: true,
4037
+ reason: failureKind,
4038
+ });
4039
+ }
4040
+ if (failureKind === "timeout") {
3891
4041
  return attachDescriptor({
3892
4042
  error: "user_timeout",
3893
4043
  hint: "User did not respond in time. Proceed with best judgement.",
3894
4044
  });
3895
4045
  }
4046
+ if (failureKind === "reject") {
4047
+ return attachDescriptor({
4048
+ error: "user_rejected",
4049
+ hint: "The user declined this question. Do not assume consent.",
4050
+ });
4051
+ }
3896
4052
  return attachDescriptor({
3897
4053
  error: `ask_user_question failed: ${err.message}`,
3898
4054
  });
@@ -4421,7 +4577,7 @@ async function executeToolInner(
4421
4577
  : "No skills found. Make sure you're in the ChainlessChain project root or have skills installed.",
4422
4578
  });
4423
4579
  }
4424
- const match = allSkills.find(
4580
+ let match = allSkills.find(
4425
4581
  (s) => s.id === args.skill_name || s.dirName === args.skill_name,
4426
4582
  );
4427
4583
  if (!match || !match.hasHandler) {
@@ -4429,6 +4585,20 @@ async function executeToolInner(
4429
4585
  error: `Skill "${args.skill_name}" not found or has no handler. Use list_skills to see available skills.`,
4430
4586
  });
4431
4587
  }
4588
+ try {
4589
+ if (typeof skillLoader.materializeSkill === "function") {
4590
+ match = skillLoader.materializeSkill(match, {
4591
+ sessionId,
4592
+ turnId,
4593
+ loadedBecause: "run_skill",
4594
+ bodyIncluded: false,
4595
+ });
4596
+ }
4597
+ } catch (error) {
4598
+ return attachDescriptor({
4599
+ error: `Skill "${args.skill_name}" body could not be loaded: ${error.message}`,
4600
+ });
4601
+ }
4432
4602
 
4433
4603
  // Check if skill requests isolation (via SKILL.md frontmatter)
4434
4604
  const skillIsolation = match.isolation === true;
@@ -4534,6 +4704,7 @@ async function executeToolInner(
4534
4704
  const taskContext = {
4535
4705
  projectRoot: cwd,
4536
4706
  workspacePath: cwd,
4707
+ processBroker: createSkillProcessBroker(match),
4537
4708
  // Expose the MCP client + mounted servers so the skill handler
4538
4709
  // can call MCP tools directly without going through the agent
4539
4710
  // loop. Handlers that don't need MCP can ignore these.
@@ -4586,6 +4757,11 @@ async function executeToolInner(
4586
4757
  s.category.toLowerCase().includes(q),
4587
4758
  );
4588
4759
  }
4760
+ skillLoader.recordDescriptorUse?.(skills, {
4761
+ sessionId,
4762
+ turnId,
4763
+ loadedBecause: "list_skills",
4764
+ });
4589
4765
  return attachDescriptor({
4590
4766
  count: skills.length,
4591
4767
  skills: skills.map((s) => ({
@@ -5121,6 +5297,55 @@ export function safeStringifyToolResult(value) {
5121
5297
  }
5122
5298
  }
5123
5299
 
5300
+ function emitToolHookLifecycle({
5301
+ tool,
5302
+ args,
5303
+ result,
5304
+ error = null,
5305
+ sessionId = null,
5306
+ turnId = null,
5307
+ toolUseId = null,
5308
+ cwd = process.cwd(),
5309
+ }) {
5310
+ const failed = Boolean(error || result?.error);
5311
+ const base = {
5312
+ schema_version: 1,
5313
+ session_id: sessionId,
5314
+ turn_id: turnId,
5315
+ tool_use_id: toolUseId,
5316
+ tool_name: tool,
5317
+ duration_ms: Number(result?.toolTelemetryRecord?.durationMs || 0),
5318
+ cwd,
5319
+ };
5320
+ emitHooksV2Event(failed ? "PostToolUseFailure" : "PostToolUse", {
5321
+ ...base,
5322
+ ...(failed
5323
+ ? {
5324
+ error_code:
5325
+ result?.error?.code ||
5326
+ result?.code ||
5327
+ (typeof error === "object" ? error?.code : null) ||
5328
+ "tool_error",
5329
+ }
5330
+ : {}),
5331
+ });
5332
+ if (!failed && GUARDED_FILE_MUTATION_TOOLS.has(tool)) {
5333
+ const changedPath =
5334
+ args?.path ||
5335
+ args?.filePath ||
5336
+ args?.file_path ||
5337
+ args?.targetPath ||
5338
+ args?.target_path ||
5339
+ null;
5340
+ emitHooksV2Event("FileChanged", {
5341
+ ...base,
5342
+ path: changedPath == null ? null : String(changedPath),
5343
+ operation: tool,
5344
+ });
5345
+ }
5346
+ return failed;
5347
+ }
5348
+
5124
5349
  /**
5125
5350
  * Execute a spawn_sub_agent tool call.
5126
5351
  * Creates an isolated SubAgentContext, runs it, and returns only the summary.
@@ -5784,6 +6009,8 @@ async function _executeSpawnSubAgent(args, ctx) {
5784
6009
  outcome: null,
5785
6010
  hookFeedback: null,
5786
6011
  promise: null,
6012
+ recoveryBinding: () =>
6013
+ subCtx.recoveryBinding(entry.outcome?.result || null),
5787
6014
  };
5788
6015
  // Settle-capture wrapper: the stored promise NEVER rejects, so an
5789
6016
  // unconsumed handle can't surface as an unhandled rejection.
@@ -5830,6 +6057,7 @@ async function _executeSpawnSubAgent(args, ctx) {
5830
6057
  subAgentId: subCtx.id,
5831
6058
  role: subCtx.role,
5832
6059
  parentSessionId,
6060
+ childBinding: subCtx.recoveryBinding(),
5833
6061
  note: "Sub-agent is running in the background. Its result will be delivered to you automatically in a later turn — continue with other work; the run will not finish before the result arrives.",
5834
6062
  };
5835
6063
  }
@@ -5877,6 +6105,7 @@ async function _executeSpawnSubAgent(args, ctx) {
5877
6105
  subAgentId: subCtx.id,
5878
6106
  role: subCtx.role,
5879
6107
  parentSessionId,
6108
+ childBinding: subCtx.recoveryBinding(result),
5880
6109
  summary: result.summary,
5881
6110
  toolsUsed: result.toolsUsed,
5882
6111
  iterationCount: result.iterationCount,
@@ -5908,6 +6137,7 @@ async function _executeSpawnSubAgent(args, ctx) {
5908
6137
  subAgentId: subCtx.id,
5909
6138
  role: subCtx.role,
5910
6139
  parentSessionId,
6140
+ childBinding: subCtx.recoveryBinding(subCtx.result),
5911
6141
  };
5912
6142
  }
5913
6143
  }
@@ -5998,7 +6228,7 @@ export async function chatWithTools(rawMessages, options) {
5998
6228
  }),
5999
6229
  });
6000
6230
  if (!response.ok) {
6001
- throw new Error(formatProviderHttpError("ollama", response.status));
6231
+ throw new Error(await formatProviderResponseError("ollama", response));
6002
6232
  }
6003
6233
  const data = await response.json();
6004
6234
  if (data.prompt_eval_count || data.eval_count) {
@@ -6125,7 +6355,7 @@ export async function chatWithTools(rawMessages, options) {
6125
6355
  });
6126
6356
 
6127
6357
  if (!response.ok) {
6128
- throw new Error(formatProviderHttpError("anthropic", response.status));
6358
+ throw new Error(await formatProviderResponseError("anthropic", response));
6129
6359
  }
6130
6360
 
6131
6361
  const data = await response.json();
@@ -6232,7 +6462,7 @@ export async function chatWithTools(rawMessages, options) {
6232
6462
  });
6233
6463
 
6234
6464
  if (!response.ok) {
6235
- throw new Error(formatProviderHttpError(provider, response.status));
6465
+ throw new Error(await formatProviderResponseError(provider, response));
6236
6466
  }
6237
6467
 
6238
6468
  const data = await response.json();
@@ -6355,23 +6585,9 @@ export function _streamErrorDisposition(err, signal, partialText) {
6355
6585
  * means a missing/invalid API key for the ACTIVE provider — and because the
6356
6586
  * provider is resolved from config, a surprise "anthropic 401" usually means
6357
6587
  * the effective provider differs from what the user configured. Name the
6358
- * provider and point at the fix instead of dumping a bare status code. Pure +
6359
- * exported for tests.
6588
+ * provider and point at the appropriate key, billing, or permission fix
6589
+ * instead of dumping a bare status code. Pure + exported for tests.
6360
6590
  */
6361
- export function formatProviderHttpError(provider, status) {
6362
- const base = `${provider} API error: HTTP ${status}`;
6363
- if (status === 401 || status === 403) {
6364
- return (
6365
- `${base} — authentication failed: the API key for provider "${provider}" ` +
6366
- `is missing or invalid. Check "cc config get llm.provider" and ` +
6367
- `"cc config get llm.apiKey" (or run Configure LLM). A surprise "${provider}" ` +
6368
- `here usually means the effective provider differs from the one you configured.`
6369
- );
6370
- }
6371
- if (status === 429) return `${base} — rate limited; please retry shortly.`;
6372
- return base;
6373
- }
6374
-
6375
6591
  /**
6376
6592
  * Is this error from a streaming chat request a transient API CONNECTION drop
6377
6593
  * that is safe to retry? True only for genuine network failures (reset /
@@ -6565,7 +6781,7 @@ async function _chatOllamaStreaming(
6565
6781
  body: JSON.stringify({ ...body, stream: true }),
6566
6782
  });
6567
6783
  if (!response.ok) {
6568
- throw new Error(formatProviderHttpError("ollama", response.status));
6784
+ throw new Error(await formatProviderResponseError("ollama", response));
6569
6785
  }
6570
6786
  const state = _ollamaInitState();
6571
6787
  const reader = response.body.getReader();
@@ -6751,7 +6967,7 @@ async function _chatAnthropicStreaming(
6751
6967
  body: JSON.stringify(body),
6752
6968
  });
6753
6969
  if (!response.ok) {
6754
- throw new Error(formatProviderHttpError("anthropic", response.status));
6970
+ throw new Error(await formatProviderResponseError("anthropic", response));
6755
6971
  }
6756
6972
  const state = _anthropicInitState();
6757
6973
  const reader = response.body.getReader();
@@ -6903,7 +7119,7 @@ async function _chatOpenAIStreaming(
6903
7119
  body: JSON.stringify(body),
6904
7120
  });
6905
7121
  if (!response.ok) {
6906
- throw new Error(formatProviderHttpError(provider, response.status));
7122
+ throw new Error(await formatProviderResponseError(provider, response));
6907
7123
  }
6908
7124
  const state = _openaiInitState();
6909
7125
  const reader = response.body.getReader();
@@ -7333,6 +7549,10 @@ export async function* agentLoop(messages, options) {
7333
7549
  cwd: options.cwd || process.cwd(),
7334
7550
  planManager: options.planManager || null,
7335
7551
  sessionId: options.sessionId || null,
7552
+ // One agentLoop invocation represents one user turn even when it performs
7553
+ // several model/tool iterations. Hosts may supply their persisted turn id;
7554
+ // otherwise the run id is the stable in-process binding.
7555
+ turnId: options.turnId || runId,
7336
7556
  hostManagedToolPolicy: options.hostManagedToolPolicy || null,
7337
7557
  externalToolDescriptors: options.externalToolDescriptors || null,
7338
7558
  externalToolExecutors: options.externalToolExecutors || null,
@@ -7762,6 +7982,7 @@ export async function* agentLoop(messages, options) {
7762
7982
  role: entry.role,
7763
7983
  error: entry.outcome?.error || null,
7764
7984
  summary: entry.outcome?.result?.summary || null,
7985
+ childBinding: entry.recoveryBinding?.() || null,
7765
7986
  };
7766
7987
  }
7767
7988
  }
@@ -7905,6 +8126,7 @@ export async function* agentLoop(messages, options) {
7905
8126
  role: entry.role,
7906
8127
  error: entry.outcome?.error || null,
7907
8128
  summary: entry.outcome?.result?.summary || null,
8129
+ childBinding: entry.recoveryBinding?.() || null,
7908
8130
  };
7909
8131
  }
7910
8132
  continue;
@@ -8050,6 +8272,8 @@ export async function* agentLoop(messages, options) {
8050
8272
  type: "tool-executing",
8051
8273
  tool: call.function.name,
8052
8274
  args: toolArgs,
8275
+ tool_use_id: call.id,
8276
+ turn_id: `${runId}:t${budget.consumed}`,
8053
8277
  };
8054
8278
  const { result: toolResult, error: toolError } = await promise;
8055
8279
  throwIfAborted(signal);
@@ -8065,6 +8289,12 @@ export async function* agentLoop(messages, options) {
8065
8289
  tool: call.function.name,
8066
8290
  result: toolResult,
8067
8291
  error: toolError,
8292
+ tool_use_id: call.id,
8293
+ turn_id: `${runId}:t${budget.consumed}`,
8294
+ permission_decision_id: permissionDecisionId(
8295
+ call.id,
8296
+ toolResult?.policy,
8297
+ ),
8068
8298
  };
8069
8299
  messages.push({
8070
8300
  role: "tool",
@@ -8093,6 +8323,8 @@ export async function* agentLoop(messages, options) {
8093
8323
  tool: "(unknown)",
8094
8324
  result: { error: reason },
8095
8325
  error: reason,
8326
+ tool_use_id: call?.id || null,
8327
+ turn_id: `${runId}:t${budget.consumed}`,
8096
8328
  };
8097
8329
  messages.push({
8098
8330
  role: "tool",
@@ -8119,9 +8351,22 @@ export async function* agentLoop(messages, options) {
8119
8351
  toolName,
8120
8352
  toolArgs,
8121
8353
  );
8122
- if (cpId) yield { type: "checkpoint", id: cpId, tool: toolName };
8354
+ if (cpId)
8355
+ yield {
8356
+ type: "checkpoint",
8357
+ id: cpId,
8358
+ tool: toolName,
8359
+ tool_use_id: call.id,
8360
+ turn_id: `${runId}:t${budget.consumed}`,
8361
+ };
8123
8362
 
8124
- yield { type: "tool-executing", tool: toolName, args: toolArgs };
8363
+ yield {
8364
+ type: "tool-executing",
8365
+ tool: toolName,
8366
+ args: toolArgs,
8367
+ tool_use_id: call.id,
8368
+ turn_id: `${runId}:t${budget.consumed}`,
8369
+ };
8125
8370
 
8126
8371
  let toolResult;
8127
8372
  let toolError = null;
@@ -8218,6 +8463,12 @@ export async function* agentLoop(messages, options) {
8218
8463
  tool: toolName,
8219
8464
  result: toolResult,
8220
8465
  error: toolError,
8466
+ tool_use_id: call.id,
8467
+ turn_id: `${runId}:t${budget.consumed}`,
8468
+ permission_decision_id: permissionDecisionId(
8469
+ call.id,
8470
+ toolResult?.policy,
8471
+ ),
8221
8472
  };
8222
8473
 
8223
8474
  messages.push({
@@ -876,6 +876,22 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
876
876
  type: "number",
877
877
  description: "Max wait for user reply in ms (default: 60000)",
878
878
  },
879
+ defaultValue: {
880
+ description:
881
+ "Fallback answer used only when onTimeout/onReject is useDefault",
882
+ },
883
+ onTimeout: {
884
+ type: "string",
885
+ enum: ["error", "useDefault", "skip"],
886
+ description:
887
+ "Timeout policy: error (default), useDefault, or skip with a null answer",
888
+ },
889
+ onReject: {
890
+ type: "string",
891
+ enum: ["error", "useDefault", "skip"],
892
+ description:
893
+ "User-rejection policy: error (default), useDefault, or skip with a null answer",
894
+ },
879
895
  },
880
896
  required: ["question"],
881
897
  },