chainlesschain 0.162.180 → 0.162.181

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 (249) hide show
  1. package/package.json +6 -3
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-D_TIL54O.js → AIOps-cq0dwbnf.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-eQwy9r-f.js → ActionButton-CvcgGl3w.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D2eNuDgT.js → Analytics-hM2-jFqg.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-CFhwOFsf.js → AppLayout-B9_Gsd_g.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-CJUMw6PB.js → Artifacts-B7bu52Og.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-CDB9V58o.js → Audit-DThfDgqB.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-TBppYFjN.js → BackgroundAgents-DjlFiD4v.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CYEOUpzJ.js → Backup-CK9xJKnG.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-C88fFT2u.js → BaseInput-DEiSU8K8.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-mkr1vC3N.js → Chat-CpT96czj.js} +6 -6
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-C7bofJuA.js → ChatBubbleRenderer-BKPPNmZI.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-CVU4xqti.js → Checkbox-C1GfDnO0.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-rrNcByz3.js → Codegen-3DAKgiLx.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-Cqu-zCvh.js → Col-74cOwZU1.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-RGRlSgXV.js → Community-tn9Kkz9j.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-DBm6epOK.js → Compact-BcoXH7m4.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-BgKw5iaW.js → Compliance-DIPGUBgi.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-BqQcNO3Z.js → Cowork-doD5_91c.js} +2 -2
  21. package/src/assets/web-panel/assets/{Cron-DO5gTFNb.js → Cron-C-IDvubz.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-B8hbJNuN.js → Crosschain-CdcCoBdj.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-B08bFJ2C.js → DID-DdH5aMMA.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-xNdy_ifo.js → Dashboard-DHLA4mm0.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-D-KIZgWL.js → Dropdown-dEeCt7Md.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-DKCvsaGo.js → EmailListRenderer-BMaecFv9.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D_cfqama.js → FamilyGuardDashboard-DUaUukTN.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-B-UqQD68.js → Federation-CMBE0_rp.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BWWvWuJW.js → FormItemContext-PG-JDbXq.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-CPchx6N7.js → GenericCardRenderer-Bcb0p88m.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Vx4co9Ff.js → Git-Bgv15myB.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-D4x0pp_m.js → Governance-DB8YTArI.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-T3KvwPYR.js → Inference-BQMwCWaS.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-Ddv3KUv3.js → KnowledgeGraph-B1_ZziiB.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DfH-Dkae.js → Logs-DovEEnt_.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-DHW3PbCq.js → MarkdownRenderer-D201OL4T.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-tjgb0R3D.js → Marketplace-BlCXSpyB.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DHAk5nYX.js → McpTools-CsCR09Wj.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-A2Yx7thM.js → Memory-CBVRLKno.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-BEmTVfN5.js → MobileBridge-C9OIafgA.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-DuFHUgE4.js → MobileProjects-D_zoJ8Xs.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-BDSll0OZ.js → Mtc-vE-HdvLj.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-CuBvluaS.js → MtcAudit-CPLaekCd.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-BmXAA-Sb.js → Multisig-C_UP9C2o.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-ci2stZAe.js → NLProgramming-2nODJcU1.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-D-1RpqnS.js → Notes-BhE-SJGu.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-C0GyitIT.js → NotificationSettings-D21q7BNU.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-U2bN-hj5.js → OrderTableRenderer-0b62GYOD.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BNZgpPci.js → Organization-CEqmw_sb.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-CDidKmUN.js → Overflow-MW-gMDO_.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-BnreBaXq.js → P2P-CY0hjI_G.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-DwJUxO9j.js → PdhVaultBrowser-BbWh7Man.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-BQGgJPH0.js → Permissions-ChqEA_4Q.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-k_fSkCwL.js → PersonalDataHub-B3YrbYfD.js} +5 -5
  55. package/src/assets/web-panel/assets/{Pipeline-WGqKMqau.js → Pipeline-B8WBhhlW.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-DtHj9Ymq.js → Privacy-Cmb0PXNx.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-B3wH2SFC.js → ProjectInit-hF6zW3Nz.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-Cd0cgcA1.js → ProjectSettings-BFSVfpW0.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-DAWkVFkc.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-DTpxEXur.js → Providers-B8yux8Dx.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-B2v6gR-C.js → QrScannerModal-N76cQluO.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-D3Nr9xXR.js → QuickAsk-ClvZ0KYR.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-C9inoMky.js → Recommend-B-GfgBpT.js} +1 -1
  64. package/src/assets/web-panel/assets/RemoteSession-mlglCdQi.js +5 -0
  65. package/src/assets/web-panel/assets/{Reputation-41KFG646.js → Reputation-DJIZzQeG.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-DqAaqqCv.js → Row-COzxu_bb.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-CMDpCDKc.js → RssFeed-CoYsJQuE.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-B6mtegNL.js → Search-DC77Mq9S.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-BaePFVZ8.js → Security-Loy2EdMO.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-DeG3Qscl.js → Services-GUD07Eu0.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-D_QP7F90.js → Skeleton-DWzkptYU.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-DLGyUgIA.js → Skills-CEDn1r-Z.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-BN2pxW1Q.js → Sla-ub_k4pXh.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-BWsZPd8B.js → SpeechSettings-D7HLX9CA.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-VOZRPODW.js → SyncSettings-DbwOvl6m.js} +2 -2
  76. package/src/assets/web-panel/assets/Tasks-CBQzoAu5.js +1 -0
  77. package/src/assets/web-panel/assets/{Templates-eJSob-q0.js → Templates-BNVeIhud.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-Bdwk8Rwy.js → Tenant-PS9AzhXU.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CsMLKIoV.js → Terminal-Cgb4eLB_.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-D5qkbPKT.js → TimelineRenderer-CrmXMOkg.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-DKgwn8hI.js → Tokens-DD-VDHw1.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-HlEHniGM.js → Trigger-BsoN_n-n.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-CdPcsBpN.js → Trust-n8LmN4ZV.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-vAdXd-vG.js → UkeySign-C9_7MImA.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-9hHBYFnH.js → VideoEditing-DyBteNgn.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-Dxh5d1yR.js → Wallet-BS5ixeXI.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-BsFmLHkp.js → WebAuthn-spc4UImU.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-Cn0OIwLn.js → WorkflowEditor-D7iVvaBO.js} +1 -1
  89. package/src/assets/web-panel/assets/chat-6CmBkHrL.js +1 -0
  90. package/src/assets/web-panel/assets/{colors-Du9jzLN0.js → colors-BGoCLkxI.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-DhEscfzw.js → compact-item-fYZBetMO.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-CwzEfF3i.js → createContext-BeM-1UVj.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DT_GSE6J.js → hasIn-CE7ZuEnV.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-53z1YUxX.js → index--lap6cf7.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-NA2oBLSB.js → index-ATcSr_2O.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DWL3SYN3.js → index-B2U-ObMq.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-D-QkW1fp.js → index-B3CDgvNW.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BF-ZCVGE.js → index-B4wiTEOM.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-D4kZoXNr.js → index-B8BsdNV_.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DnVVYKCE.js → index-BEVm0lCS.js} +10 -10
  102. package/src/assets/web-panel/assets/{index-DfRDyY1q.js → index-BNZDILcO.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-B8s5FxJY.js → index-BU_2qiDk.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BnHhFnwt.js → index-BV551878.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DhXay17G.js → index-BfPL-m46.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-B6QDWRLk.js → index-BowH1eLQ.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DN60VBn5.js → index-BsMfoaeo.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Cnok8mhZ.js → index-BunaQCa0.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dny_ZnAO.js → index-C0v6YKKO.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D8gt0j7r.js → index-C4SJVjs4.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Mobw3PHs.js → index-C9Y3k0HI.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CAVW0cWM.js → index-CIpVrf5P.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CyEhUJcu.js → index-CRLjEP1H.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DzjzrOli.js → index-CRnUE8Cb.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-D5IytTND.js → index-Cip8emOQ.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BQWENaZf.js → index-CpIGIB85.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CQWxDOvM.js → index-D1r9tT3J.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BrkJ7JPm.js → index-DT3zPSVX.js} +1 -1
  119. package/src/assets/web-panel/assets/index-DacrAdc-.js +1 -0
  120. package/src/assets/web-panel/assets/{index-BFD0cEna.js → index-De0quFDw.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-v5HLYCVa.js → index-DoXk5KJ8.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DtRwLhee.js → index-DsvfrESp.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BgSR2WMG.js → index-Dw1PyYPm.js} +1 -1
  124. package/src/assets/web-panel/assets/index-EHzNJozo.js +1 -0
  125. package/src/assets/web-panel/assets/{index-CGvgnfl9.js → index-MtOuq2i6.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-1LoutPJd.js → index-Puq6Luf1.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-tND8-TDU.js → index-QIpnpZgz.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-D3llLkYM.js → index-RMZ8a7Yt.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C4SN3by5.js → index-WUrJ6S1j.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-VeHs6qH0.js → index-YjcumOZ4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cc9aPkv-.js → index-lJBjB1QX.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BIYTjbv_.js → index-ukg99D1V.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-gFjYdstW.js → index-zb7rVOhV.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-Cvt59c10.js → initDefaultProps-CYHMs1ag.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-D15pPEzl.js → motion-DDB2Ffk5.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-N55KeXJ7.js → move-Bg3cD-dX.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-CyFO1bYP.js → mtc-parser-B5nedjTS.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-B5IXfxU2.js → omit-BHyuUILu.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CpVqsulV.js → pickAttrs-C9YQnEN9.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-ME36sMF3.js → placementArrow-DBUFYUe7.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-BXAIR1r-.js → responsiveObserve-nBs2Obnk.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-BkOX3-Dp.js → slide-DkCEaXNU.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-Cy4Aklpt.js → statusUtils-aqE1Wi6U.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-gUd2T206.js → styleChecker-CN5bhfHB.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-CaVD4o99.js → useFlexGapSupport-B_oX_kvJ.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs--pFGl0KD.js → useFs-rCuXHeme.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-D45iP86i.js → usePersonalDataHub-DZR9Abyd.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-BayoChH_.js → vnode-ConCYQlX.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-CpP38poi.js → zoom-CUdDxG5M.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/commands/agent.js +4 -1
  152. package/src/commands/background-session.js +2 -1
  153. package/src/commands/context.js +69 -2
  154. package/src/data/changelog.json +13 -0
  155. package/src/gateways/ws/background-agent-protocol.js +38 -0
  156. package/src/gateways/ws/message-dispatcher.js +1 -0
  157. package/src/gateways/ws/remote-session-protocol.js +65 -6
  158. package/src/gateways/ws/ws-server.js +8 -1
  159. package/src/harness/feature-flags.js +15 -8
  160. package/src/harness/mcp-client.js +618 -43
  161. package/src/lazy-dispatch.js +30 -1
  162. package/src/lib/agent-authority.js +22 -0
  163. package/src/lib/agent-core.js +2 -0
  164. package/src/lib/agent-sandbox.js +161 -0
  165. package/src/lib/agent-team/team-runner.js +22 -0
  166. package/src/lib/artifact-store.js +35 -0
  167. package/src/lib/async-hook-supervisor.cjs +13 -2
  168. package/src/lib/audit-mtc.js +3 -2
  169. package/src/lib/background-agent-supervisor.js +104 -3
  170. package/src/lib/background-interaction-journal.js +407 -0
  171. package/src/lib/background-interaction-resolver.js +23 -34
  172. package/src/lib/background-session-transport.js +12 -2
  173. package/src/lib/capability-manifest.js +41 -3
  174. package/src/lib/capability-negotiation.js +1 -1
  175. package/src/lib/channels/channel-manager.js +33 -0
  176. package/src/lib/channels/telegram-channel.js +23 -5
  177. package/src/lib/channels/webhook-channel.js +38 -15
  178. package/src/lib/chrome-connector.js +169 -23
  179. package/src/lib/config-manager.js +23 -9
  180. package/src/lib/context-breakdown.js +31 -0
  181. package/src/lib/cowork-cron.js +274 -32
  182. package/src/lib/cross-chain-mtc.js +3 -2
  183. package/src/lib/durable-security-store.js +124 -0
  184. package/src/lib/event-runtime-host.js +67 -6
  185. package/src/lib/event-runtime-store.js +163 -0
  186. package/src/lib/goal-store.js +32 -12
  187. package/src/lib/headless-manifest.js +2 -1
  188. package/src/lib/hook-environment.cjs +58 -0
  189. package/src/lib/hook-manager.js +12 -5
  190. package/src/lib/hook-runner.cjs +122 -28
  191. package/src/lib/hook-runner.js +1 -0
  192. package/src/lib/hooks-v2-producers.js +36 -0
  193. package/src/lib/hooks-v2-runtime.js +329 -52
  194. package/src/lib/interaction-adapter.js +60 -19
  195. package/src/lib/interaction-binding.js +64 -0
  196. package/src/lib/json-schema-output.js +439 -14
  197. package/src/lib/json-schema-validate.js +514 -883
  198. package/src/lib/lan-pairing-tokens.js +115 -57
  199. package/src/lib/lsp/__tests__/lsp-client.test.js +32 -0
  200. package/src/lib/lsp/__tests__/lsp-manager.test.js +25 -0
  201. package/src/lib/lsp/lsp-client.js +4 -0
  202. package/src/lib/lsp/lsp-manager.js +3 -0
  203. package/src/lib/lsp/lsp-server-registry.js +18 -0
  204. package/src/lib/mcp-client.js +1 -0
  205. package/src/lib/mcp-oauth.js +35 -21
  206. package/src/lib/packer/pkg-config-generator.js +1 -0
  207. package/src/lib/permission-decision.js +99 -0
  208. package/src/lib/plugin-monitor-supervisor.js +3 -0
  209. package/src/lib/plugin-runtime/capabilities.js +50 -0
  210. package/src/lib/plugin-runtime/capability-consent.js +42 -35
  211. package/src/lib/plugin-runtime/hooks.js +36 -9
  212. package/src/lib/plugin-runtime/install.js +23 -7
  213. package/src/lib/plugin-runtime/lsp.js +4 -0
  214. package/src/lib/plugin-runtime/manifest.js +50 -2
  215. package/src/lib/plugin-runtime/mcp.js +30 -5
  216. package/src/lib/plugin-runtime/monitors.js +11 -0
  217. package/src/lib/plugin-runtime/plugin-options.js +94 -38
  218. package/src/lib/plugin-runtime/policy.js +29 -2
  219. package/src/lib/plugin-runtime/sandbox-policy.js +84 -0
  220. package/src/lib/plugin-runtime/scopes.js +7 -3
  221. package/src/lib/plugin-runtime/trust.js +36 -31
  222. package/src/lib/process-execution-broker/credential-agent.js +114 -16
  223. package/src/lib/process-execution-broker/credential-transport-worker.js +312 -0
  224. package/src/lib/process-execution-broker/credential-transport.js +378 -0
  225. package/src/lib/process-execution-broker/index.js +408 -19
  226. package/src/lib/process-execution-broker/platform-sandbox.js +561 -21
  227. package/src/lib/process-execution-broker/windows-sandbox.ps1 +999 -0
  228. package/src/lib/project-mcp-trust.js +21 -26
  229. package/src/lib/protocol-replay.js +19 -12
  230. package/src/lib/settings-hooks.cjs +13 -0
  231. package/src/lib/skill-loader.js +83 -10
  232. package/src/lib/sync-credentials.js +5 -4
  233. package/src/lib/turn-binding.js +8 -6
  234. package/src/repl/agent-repl.js +113 -28
  235. package/src/repl/repl-turn-binding.js +5 -2
  236. package/src/runtime/agent-core.js +331 -26
  237. package/src/runtime/coding-agent-contract-shared.cjs +3 -3
  238. package/src/runtime/headless-runner.js +101 -4
  239. package/src/runtime/headless-stream.js +209 -23
  240. package/src/runtime/mcp-config.js +29 -17
  241. package/src/runtime/policies/agent-policy.js +2 -0
  242. package/src/workers/background-agent-worker.js +128 -13
  243. package/src/assets/web-panel/assets/Projects-BbgmyQnS.js +0 -1
  244. package/src/assets/web-panel/assets/RemoteSession-Bqk3EYSu.js +0 -4
  245. package/src/assets/web-panel/assets/Tasks-3bDAUz8K.js +0 -1
  246. package/src/assets/web-panel/assets/chat-CJ19O6Dh.js +0 -1
  247. package/src/assets/web-panel/assets/devWarning-BBMFnsja.js +0 -1
  248. package/src/assets/web-panel/assets/index-Do8JMV4N.js +0 -1
  249. package/src/assets/web-panel/assets/index-UYAJ6iNM.js +0 -1
@@ -21,6 +21,7 @@ import {
21
21
  describeAuthorityChain,
22
22
  } from "../agent-authority.js";
23
23
  import { EventRuntimeStore } from "../event-runtime-store.js";
24
+ import { getDefaultEventRuntimeHost } from "../event-runtime-host.js";
24
25
 
25
26
  export const CHANNEL_KINDS = ["webhook", "telegram"];
26
27
 
@@ -128,8 +129,31 @@ export async function startChannels(specsInput, opts = {}) {
128
129
  // `approve`) before the caller's handler sees it — so a channel message can
129
130
  // never be mistaken for a user approval no matter what it contains.
130
131
  const onEvent = stampChannelAuthority(opts.onEvent);
132
+ const eventRuntimeHost =
133
+ opts.eventRuntimeHost ||
134
+ (eventRuntimeStore && process.env.CC_EVENT_RUNTIME_DURABLE === "1"
135
+ ? getDefaultEventRuntimeHost({ store: eventRuntimeStore })
136
+ : null);
131
137
 
132
138
  const started = [];
139
+ const unregisterRuntimeHandlers = [];
140
+ if (eventRuntimeHost) {
141
+ for (const origin of new Set(specs.map((spec) => spec.kind))) {
142
+ unregisterRuntimeHandlers.push(
143
+ eventRuntimeHost.registerHandler(
144
+ (event) =>
145
+ onEvent({
146
+ channel: event.channel || origin,
147
+ sender: event.sender,
148
+ text: event.text,
149
+ ...(event.meta == null ? {} : { meta: event.meta }),
150
+ eventId: event.event_id || event.eventId || event.id || null,
151
+ }),
152
+ { queue: "inbox", type: "channel.event", origin },
153
+ ),
154
+ );
155
+ }
156
+ }
133
157
  const stopAll = () => {
134
158
  for (const c of started) {
135
159
  try {
@@ -138,6 +162,13 @@ export async function startChannels(specsInput, opts = {}) {
138
162
  /* best-effort */
139
163
  }
140
164
  }
165
+ for (const unregister of unregisterRuntimeHandlers.splice(0)) {
166
+ try {
167
+ unregister();
168
+ } catch {
169
+ /* best-effort */
170
+ }
171
+ }
141
172
  };
142
173
 
143
174
  try {
@@ -154,6 +185,7 @@ export async function startChannels(specsInput, opts = {}) {
154
185
  onEvent,
155
186
  log,
156
187
  eventRuntimeStore,
188
+ eventRuntimeHost,
157
189
  });
158
190
  started.push({ kind: "webhook", describe: handle.describe, ...handle });
159
191
  } else if (spec.kind === "telegram") {
@@ -167,6 +199,7 @@ export async function startChannels(specsInput, opts = {}) {
167
199
  onEvent,
168
200
  log,
169
201
  eventRuntimeStore,
202
+ eventRuntimeHost,
170
203
  });
171
204
  started.push({
172
205
  kind: "telegram",
@@ -29,6 +29,7 @@ export async function startTelegramChannel(options = {}) {
29
29
  // the event loop (timers, stop()) entirely.
30
30
  pollPauseMs = 50,
31
31
  eventRuntimeStore = null,
32
+ eventRuntimeHost = null,
32
33
  } = options;
33
34
  const runtimeProducer = eventRuntimeStore
34
35
  ? new EventRuntimeProducer({ store: eventRuntimeStore })
@@ -74,13 +75,30 @@ export async function startTelegramChannel(options = {}) {
74
75
  channel: "telegram",
75
76
  sender: String(chatId),
76
77
  text,
78
+ eventId: `telegram:${update.update_id}`,
77
79
  meta: { updateId: update.update_id },
78
80
  };
79
- runtimeProducer?.publish(event, {
80
- origin: "telegram",
81
- id: `telegram:${update.update_id}`,
82
- });
83
- onEvent?.(event);
81
+ if (runtimeProducer) {
82
+ const record = runtimeProducer.publish(
83
+ {
84
+ ...event,
85
+ type: "channel.event",
86
+ requiresHandler: true,
87
+ },
88
+ {
89
+ origin: "telegram",
90
+ id: `telegram:${update.update_id}`,
91
+ },
92
+ );
93
+ if (eventRuntimeHost) {
94
+ await eventRuntimeHost.runOnce();
95
+ } else {
96
+ const result = await onEvent?.(event);
97
+ eventRuntimeStore.acknowledgeInbox?.(record.id, result);
98
+ }
99
+ } else {
100
+ await onEvent?.(event);
101
+ }
84
102
  } catch {
85
103
  /* downstream owns its failures */
86
104
  }
@@ -36,6 +36,7 @@ export async function startWebhookChannel(options = {}) {
36
36
  onEvent,
37
37
  log = () => {},
38
38
  eventRuntimeStore = null,
39
+ eventRuntimeHost = null,
39
40
  } = options;
40
41
  const runtimeProducer = eventRuntimeStore
41
42
  ? new EventRuntimeProducer({ store: eventRuntimeStore })
@@ -80,7 +81,7 @@ export async function startWebhookChannel(options = {}) {
80
81
  }
81
82
  chunks.push(chunk);
82
83
  });
83
- req.on("end", () => {
84
+ req.on("end", async () => {
84
85
  if (aborted) return;
85
86
  let payload;
86
87
  try {
@@ -92,30 +93,52 @@ export async function startWebhookChannel(options = {}) {
92
93
  if (!text) return respond(400, { error: "missing text" });
93
94
  const sender =
94
95
  typeof payload.sender === "string" ? payload.sender : "webhook";
96
+ const eventId = payload.event_id || payload.eventId || null;
95
97
  if (Array.isArray(allowlist) && allowlist.length > 0) {
96
98
  if (!allowlist.includes(sender)) {
97
99
  return respond(403, { error: "sender not in allowlist" });
98
100
  }
99
101
  }
100
102
  const event = {
101
- channel: "webhook",
102
- sender,
103
- text,
104
- meta:
105
- payload.meta && typeof payload.meta === "object"
106
- ? payload.meta
107
- : undefined,
108
- };
103
+ channel: "webhook",
104
+ sender,
105
+ text,
106
+ ...(eventId == null ? {} : { eventId: String(eventId) }),
107
+ meta:
108
+ payload.meta && typeof payload.meta === "object"
109
+ ? payload.meta
110
+ : undefined,
111
+ };
109
112
  try {
110
- runtimeProducer?.publish(event, {
111
- origin: "webhook",
112
- id: payload.event_id || payload.eventId || null,
113
- });
114
- onEvent?.(event);
113
+ if (runtimeProducer) {
114
+ const record = runtimeProducer.publish(
115
+ {
116
+ ...event,
117
+ type: "channel.event",
118
+ requiresHandler: true,
119
+ },
120
+ {
121
+ origin: "webhook",
122
+ id: eventId,
123
+ },
124
+ );
125
+ if (eventRuntimeHost) {
126
+ const stats = await eventRuntimeHost.runOnce();
127
+ if (Number(stats?.inboxFailed || 0) > 0) {
128
+ throw new Error("durable event delivery failed");
129
+ }
130
+ } else {
131
+ const result = await onEvent?.(event);
132
+ eventRuntimeStore.acknowledgeInbox?.(record.id, result);
133
+ }
134
+ } else {
135
+ await onEvent?.(event);
136
+ }
115
137
  } catch {
116
138
  // A configured durable runtime is the recovery boundary. Refuse the
117
139
  // request rather than acknowledging an event that was not persisted.
118
- if (runtimeProducer) return respond(503, { error: "event persistence unavailable" });
140
+ if (runtimeProducer)
141
+ return respond(503, { error: "event persistence unavailable" });
119
142
  }
120
143
  respond(202, { ok: true });
121
144
  });
@@ -31,6 +31,7 @@ import os from "os";
31
31
  import path from "path";
32
32
  import http from "http";
33
33
  import executionBroker from "./process-execution-broker/index.js";
34
+ import { redactSecrets } from "./secret-scan.js";
34
35
 
35
36
  export const DEFAULT_CDP_PORT = 9222;
36
37
 
@@ -67,6 +68,122 @@ export function normalizeLaunchUrl(url) {
67
68
  }
68
69
  export const DEFAULT_DOM_CAP = 150000;
69
70
 
71
+ /** Secret-safe text carried from a browser into transcripts or audit logs. */
72
+ export function redactBrowserText(value, cap = 500) {
73
+ if (value == null) return "";
74
+ const text = redactSecrets(String(value));
75
+ return text.length > cap ? `${text.slice(0, cap)}…` : text;
76
+ }
77
+
78
+ /**
79
+ * Preserve the page origin/path and query KEY names while removing credentials,
80
+ * fragments, and every query value. Query values often contain opaque sessions
81
+ * that a generic secret scanner cannot recognize.
82
+ */
83
+ export function redactBrowserUrl(value, cap = 500) {
84
+ const raw = String(value || "");
85
+ if (!raw) return "";
86
+ try {
87
+ const parsed = new URL(raw);
88
+ if (!["http:", "https:"].includes(parsed.protocol)) {
89
+ return redactBrowserText(raw, cap);
90
+ }
91
+ const keys = [...new Set(parsed.searchParams.keys())].slice(0, 64);
92
+ const query =
93
+ keys.length > 0
94
+ ? `?${keys
95
+ .map((key) => `${encodeURIComponent(key)}=[REDACTED]`)
96
+ .join("&")}`
97
+ : "";
98
+ return redactBrowserText(
99
+ `${parsed.protocol}//${parsed.host}${parsed.pathname}${query}`,
100
+ cap,
101
+ );
102
+ } catch {
103
+ return redactBrowserText(raw, cap);
104
+ }
105
+ }
106
+
107
+ function redactBrowserDomUrl(value, cap = 1000) {
108
+ const raw = String(value || "");
109
+ if (!raw) return "";
110
+ if (/^https?:\/\//i.test(raw)) return redactBrowserUrl(raw, cap);
111
+ if (raw.startsWith("//")) {
112
+ const safe = redactBrowserUrl(`https:${raw}`, cap + 6);
113
+ return safe.startsWith("https:")
114
+ ? redactBrowserText(safe.slice(6), cap)
115
+ : redactBrowserText(safe, cap);
116
+ }
117
+
118
+ const withoutFragment = raw.split("#", 1)[0];
119
+ const queryIndex = withoutFragment.indexOf("?");
120
+ if (queryIndex < 0) return redactBrowserText(withoutFragment, cap);
121
+ const prefix = withoutFragment.slice(0, queryIndex);
122
+ const keys = [
123
+ ...new Set(
124
+ withoutFragment
125
+ .slice(queryIndex + 1)
126
+ .split(/&(?:amp;)?/i)
127
+ .map((part) => part.split("=", 1)[0].trim())
128
+ .filter(Boolean)
129
+ .slice(0, 64),
130
+ ),
131
+ ];
132
+ const query =
133
+ keys.length > 0
134
+ ? `?${keys
135
+ .map((key) => `${encodeURIComponent(key.slice(0, 128))}=[REDACTED]`)
136
+ .join("&")}`
137
+ : "";
138
+ return redactBrowserText(`${prefix}${query}`, cap);
139
+ }
140
+
141
+ /**
142
+ * Redact secret-shaped text, sensitive form values, and DOM URL query values
143
+ * from the bounded snapshot before it crosses the tool boundary.
144
+ */
145
+ export function redactBrowserDom(value, cap = DEFAULT_DOM_CAP) {
146
+ let html = redactSecrets(String(value || ""));
147
+ html = html.replace(/<input\b[^>]*>/gi, (tag) => {
148
+ const sensitive =
149
+ /\btype\s*=\s*["']?password\b/i.test(tag) ||
150
+ /\b(?:name|id)\s*=\s*["'][^"']*(?:password|passwd|token|secret|api[-_]?key)[^"']*["']/i.test(
151
+ tag,
152
+ );
153
+ if (!sensitive) return tag;
154
+ return tag.replace(/\bvalue\s*=\s*(["'])[^"']*\1/i, 'value="[REDACTED]"');
155
+ });
156
+ html = html.replace(
157
+ /(<textarea\b[^>]*(?:name|id)\s*=\s*["'][^"']*(?:password|passwd|token|secret|api[-_]?key)[^"']*["'][^>]*>)[\s\S]*?(<\/textarea>)/gi,
158
+ "$1[REDACTED]$2",
159
+ );
160
+ html = html.replace(
161
+ /\b(href|src|action)\s*=\s*(["'])([^"']+)\2/gi,
162
+ (_match, attr, quote, url) =>
163
+ `${attr}=${quote}${redactBrowserDomUrl(url, 1000)}${quote}`,
164
+ );
165
+ return html.slice(0, Math.max(0, Number(cap) || 0));
166
+ }
167
+
168
+ function redactScreenshotFailure(error, generatedPath, cap = 300) {
169
+ let message = String(error && error.message ? error.message : error);
170
+ if (generatedPath) {
171
+ message = message
172
+ .split(String(generatedPath))
173
+ .join("[SCREENSHOT_PATH]");
174
+ }
175
+ return redactBrowserText(message.split("\n")[0], cap);
176
+ }
177
+
178
+ function cleanupFailedScreenshot(generatedPath, deps) {
179
+ if (!generatedPath) return;
180
+ try {
181
+ deps.fs.rmSync(generatedPath, { force: true });
182
+ } catch {
183
+ // Failure cleanup is best-effort; never mask the browser action error.
184
+ }
185
+ }
186
+
70
187
  const _deps = {
71
188
  fs,
72
189
  spawn: executionBroker.spawn.bind(executionBroker),
@@ -286,15 +403,18 @@ export async function captureState({
286
403
  const networkEntries = [];
287
404
  const onConsole = (m) => {
288
405
  if (consoleEntries.length < 200) {
289
- consoleEntries.push({ type: m.type(), text: m.text().slice(0, 500) });
406
+ consoleEntries.push({
407
+ type: redactBrowserText(m.type(), 40),
408
+ text: redactBrowserText(m.text(), 500),
409
+ });
290
410
  }
291
411
  };
292
412
  const onRequestFailed = (r) => {
293
413
  if (networkEntries.length < 200) {
294
414
  networkEntries.push({
295
415
  kind: "failed",
296
- url: r.url().slice(0, 300),
297
- error: r.failure()?.errorText || "",
416
+ url: redactBrowserUrl(r.url(), 300),
417
+ error: redactBrowserText(r.failure()?.errorText || "", 300),
298
418
  });
299
419
  }
300
420
  };
@@ -302,7 +422,7 @@ export async function captureState({
302
422
  if (res.status() >= 400 && networkEntries.length < 200) {
303
423
  networkEntries.push({
304
424
  kind: "http-error",
305
- url: res.url().slice(0, 300),
425
+ url: redactBrowserUrl(res.url(), 300),
306
426
  status: res.status(),
307
427
  });
308
428
  }
@@ -322,22 +442,33 @@ export async function captureState({
322
442
  ok: true,
323
443
  port,
324
444
  tab: index,
325
- url: page.url(),
326
- title: await page.title().catch(() => ""),
327
- tabs: pages.map((p, i) => ({ index: i, url: p.url() })),
445
+ url: redactBrowserUrl(page.url()),
446
+ title: redactBrowserText(await page.title().catch(() => ""), 500),
447
+ tabs: pages.map((p, i) => ({
448
+ index: i,
449
+ url: redactBrowserUrl(p.url()),
450
+ })),
328
451
  console: consoleEntries,
329
452
  network: networkEntries,
330
453
  };
331
454
  if (includeDom) {
332
455
  const html = await page.content().catch(() => "");
333
- state.html = html.slice(0, domCap);
456
+ state.html = redactBrowserDom(html, domCap);
334
457
  state.htmlTruncated = html.length > domCap;
335
458
  }
336
459
  if (screenshotPath) {
337
460
  await page.screenshot({ path: screenshotPath }).catch((err) => {
338
- state.screenshotError = err.message.split("\n")[0];
461
+ cleanupFailedScreenshot(screenshotPath, deps);
462
+ state.screenshotError = redactScreenshotFailure(
463
+ err,
464
+ screenshotPath,
465
+ 300,
466
+ );
339
467
  });
340
- if (!state.screenshotError) state.screenshotPath = screenshotPath;
468
+ if (!state.screenshotError) {
469
+ state.screenshotPath = screenshotPath;
470
+ state.screenshotRef = path.basename(screenshotPath);
471
+ }
341
472
  }
342
473
  return state;
343
474
  } finally {
@@ -417,8 +548,7 @@ export function resolveLoopbackCdpPort(
417
548
  }
418
549
 
419
550
  function truncateForAudit(value, cap = 200) {
420
- const s = String(value);
421
- return s.length > cap ? `${s.slice(0, cap)}…` : s;
551
+ return redactBrowserText(value, cap);
422
552
  }
423
553
 
424
554
  /**
@@ -592,7 +722,7 @@ async function runOneAction(page, act, timeoutMs) {
592
722
  return `selector appeared: ${act.selector}`;
593
723
  case "screenshot":
594
724
  await page.screenshot({ path: act.screenshotPath });
595
- return `screenshot saved: ${act.screenshotPath}`;
725
+ return "screenshot captured";
596
726
  case "assertText": {
597
727
  const text = await page.textContent(act.selector, {
598
728
  timeout: timeoutMs,
@@ -693,16 +823,24 @@ export async function performActions(
693
823
  for (const act of normalized) {
694
824
  const started = Date.now();
695
825
  const step = { ok: false, action: act.type, detail: "", durationMs: 0 };
826
+ const pageBefore = redactBrowserUrl(page.url());
696
827
  try {
697
- step.detail = await runOneAction(page, act, stepTimeout);
828
+ const detail = await runOneAction(page, act, stepTimeout);
829
+ step.detail =
830
+ act.type === "navigate"
831
+ ? `navigated to ${redactBrowserUrl(act.url)}`
832
+ : redactBrowserText(detail, 500);
698
833
  step.ok = true;
699
- if (act.screenshotPath) step.screenshotPath = act.screenshotPath;
834
+ if (act.screenshotPath) {
835
+ step.screenshotPath = act.screenshotPath;
836
+ step.screenshotRef = path.basename(act.screenshotPath);
837
+ }
700
838
  } catch (err) {
701
- step.detail = String(err && err.message ? err.message : err).split(
702
- "\n",
703
- )[0];
839
+ cleanupFailedScreenshot(act.screenshotPath, deps);
840
+ step.detail = redactScreenshotFailure(err, act.screenshotPath, 500);
704
841
  }
705
842
  step.durationMs = Date.now() - started;
843
+ const pageAfter = redactBrowserUrl(page.url());
706
844
  result.steps.push(step);
707
845
  try {
708
846
  const entry = {
@@ -710,14 +848,22 @@ export async function performActions(
710
848
  action: act.type,
711
849
  ok: step.ok,
712
850
  durationMs: step.durationMs,
851
+ pageBefore,
852
+ pageAfter,
853
+ result: step.detail,
713
854
  };
714
- if (sessionId) entry.sessionId = String(sessionId);
855
+ if (sessionId) {
856
+ entry.sessionId = redactBrowserText(sessionId, 160);
857
+ }
715
858
  if (act.selector) entry.selector = truncateForAudit(act.selector);
716
- if (act.url) entry.url = truncateForAudit(act.url);
859
+ if (act.url) entry.url = redactBrowserUrl(act.url);
717
860
  if (act.key) entry.key = truncateForAudit(act.key, 50);
861
+ if (step.ok && act.screenshotPath) {
862
+ entry.screenshotRef = path.basename(act.screenshotPath);
863
+ }
718
864
  appendActionAudit(entry, deps);
719
865
  } catch (err) {
720
- auditError = err.message;
866
+ auditError = redactBrowserText(err.message, 300);
721
867
  }
722
868
  if (!step.ok && !continueOnError) break;
723
869
  }
@@ -727,8 +873,8 @@ export async function performActions(
727
873
  result.steps.length === normalized.length &&
728
874
  result.steps.every((s) => s.ok);
729
875
  if (auditError) result.auditError = auditError;
730
- result.url = page.url();
731
- result.title = await page.title().catch(() => "");
876
+ result.url = redactBrowserUrl(page.url());
877
+ result.title = redactBrowserText(await page.title().catch(() => ""), 500);
732
878
  return result;
733
879
  } finally {
734
880
  // connectOverCDP close() disconnects the client; the browser lives on.
@@ -22,7 +22,7 @@ export const _deps = {
22
22
  },
23
23
  };
24
24
 
25
- export function loadConfig() {
25
+ export function loadConfig({ failIfUnavailable = false } = {}) {
26
26
  const configPath = getConfigPath();
27
27
  if (!existsSync(configPath)) {
28
28
  return { ...structuredClone(DEFAULT_CONFIG) };
@@ -32,6 +32,14 @@ export function loadConfig() {
32
32
  const parsed = JSON.parse(raw);
33
33
  return deepMerge(structuredClone(DEFAULT_CONFIG), parsed);
34
34
  } catch (err) {
35
+ if (failIfUnavailable) {
36
+ const error = new Error(
37
+ `Could not read durable config at ${configPath}: ${err.message}`,
38
+ { cause: err },
39
+ );
40
+ error.code = "CONFIG_STORE_UNAVAILABLE";
41
+ throw error;
42
+ }
35
43
  // The file EXISTS but couldn't be read/parsed (a typo, trailing comma, or
36
44
  // truncated write). Silently returning defaults drops the user's entire
37
45
  // config — provider, model, baseUrl, API key — and falls back to the
@@ -134,14 +142,20 @@ export function getConfigValue(key) {
134
142
  export function setConfigValue(key, value) {
135
143
  // Serialize the read-modify-write across processes: two concurrent
136
144
  // `cc config set` invocations would otherwise each load, mutate, and write
137
- // back, silently losing one update. Best-effort lock (see with-file-lock):
138
- // on contention timeout it proceeds anyway, so the CLI never hangs.
139
- return withFileLock(getConfigPath(), () => {
140
- const config = loadConfig();
141
- setNestedValue(config, key, parseValue(value));
142
- saveConfig(config);
143
- return config;
144
- });
145
+ // back, silently losing one update. Configuration can carry credentials and
146
+ // permission policy, so bounded lock failure must never write unlocked.
147
+ const configPath = getConfigPath();
148
+ mkdirSync(dirname(configPath), { recursive: true });
149
+ return withFileLock(
150
+ configPath,
151
+ () => {
152
+ const config = loadConfig({ failIfUnavailable: true });
153
+ setNestedValue(config, key, parseValue(value));
154
+ saveConfig(config);
155
+ return config;
156
+ },
157
+ { failIfUnavailable: true },
158
+ );
145
159
  }
146
160
 
147
161
  export function resetConfig() {
@@ -105,11 +105,32 @@ export function breakdownSkillCache(cache) {
105
105
  scans: Number(descriptors.scans) || 0,
106
106
  cacheHits: Number(descriptors.cacheHits) || 0,
107
107
  estimatedTokens: Number(descriptors.estimatedTokens) || 0,
108
+ contextLoads: Number(descriptors.contextLoads) || 0,
109
+ contextTokens: Number(descriptors.contextTokens) || 0,
110
+ entries: Array.isArray(descriptors.entries)
111
+ ? descriptors.entries.map((entry) => ({
112
+ id: String(entry?.id || "skill"),
113
+ source: String(entry?.source || "skill"),
114
+ estimatedTokens: Number(entry?.estimatedTokens) || 0,
115
+ contextLoads: Number(entry?.contextLoads) || 0,
116
+ contextTokens: Number(entry?.contextTokens) || 0,
117
+ loadedBecause: Array.isArray(entry?.loadedBecause)
118
+ ? entry.loadedBecause.map(String)
119
+ : [],
120
+ }))
121
+ : [],
108
122
  },
109
123
  bodies: {
110
124
  resident: Number(bodies.resident) || 0,
111
125
  cacheHits: Number(bodies.cacheHits) || 0,
112
126
  cacheMisses: Number(bodies.cacheMisses) || 0,
127
+ estimatedTokensResident:
128
+ Number(bodies.estimatedTokensResident) || 0,
129
+ estimatedTokensServed: Number(bodies.estimatedTokensServed) || 0,
130
+ estimatedTokensAvoidedByCache:
131
+ Number(bodies.estimatedTokensAvoidedByCache) || 0,
132
+ contextLoads: Number(bodies.contextLoads) || 0,
133
+ contextTokens: Number(bodies.contextTokens) || 0,
113
134
  entries: Array.isArray(bodies.entries)
114
135
  ? bodies.entries.map((entry) => ({
115
136
  id: String(entry?.id || "skill"),
@@ -117,6 +138,16 @@ export function breakdownSkillCache(cache) {
117
138
  estimatedTokens: Number(entry?.estimatedTokens) || 0,
118
139
  loads: Number(entry?.loads) || 0,
119
140
  cacheHits: Number(entry?.cacheHits) || 0,
141
+ cacheMisses:
142
+ Number(entry?.cacheMisses) ||
143
+ Math.max(
144
+ 0,
145
+ (Number(entry?.loads) || 0) -
146
+ (Number(entry?.cacheHits) || 0),
147
+ ),
148
+ contextLoads: Number(entry?.contextLoads) || 0,
149
+ contextCacheHits: Number(entry?.contextCacheHits) || 0,
150
+ contextTokens: Number(entry?.contextTokens) || 0,
120
151
  loadedBecause: Array.isArray(entry?.loadedBecause)
121
152
  ? entry.loadedBecause.map(String)
122
153
  : [],