chainlesschain 0.162.158 → 0.162.160

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 (219) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-BwpTJTN_.js → AIOps-CkRHjW8e.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BtQOoo3l.js → ActionButton-BP3MeNi2.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Duf_rXZa.js → Analytics-CjbjQsOr.js} +2 -2
  6. package/src/assets/web-panel/assets/{AppLayout-XQK3wjvB.js → AppLayout-i0adH1M8.js} +5 -5
  7. package/src/assets/web-panel/assets/Artifacts-CCCG2GOU.js +1 -0
  8. package/src/assets/web-panel/assets/{Audit-DNjOGQLh.js → Audit-DrsgvwHC.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-FH9RAfB5.js → BackgroundAgents-DkXNkbZM.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-ZIbrR4-U.js → Backup-DarTWCex.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-DSt3NaND.js → BaseInput-DaDzhcto.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-CY-wvbjv.js → Chat-C4EzGw6V.js} +5 -5
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-lkavIWMS.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-8JVadE_B.js → Checkbox-gddNgaQi.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CN83nPYI.js → Codegen-BKldFWf9.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-xPSvqdN8.js → Col-ChR-brDs.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-D78cnIjG.js → Community-DlHtZX86.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-CSw6Csbp.js → Compact-BAhfcBpC.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-E_HhjcYR.js → Compliance-gIrKkm6m.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DybeQjmm.js → Cowork-BYnzLBO3.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-DS0BJeLY.js → Cron-ByUDIljI.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-BOwVgkbs.js → Crosschain-DOdNbHFp.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DRUr9YuX.js → DID-BJHaNWD2.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-Cht-yUKW.js → Dashboard-Drm_tClz.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BLr_EJ9X.js → Dropdown-CA1WLzGN.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-Drexuh5W.js → EmailListRenderer-Di1SKjNO.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D9Q2Kq63.js → FamilyGuardDashboard-44Ve7ZFe.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-C-Z1xI-T.js → Federation-CubPwv_N.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-DLHPMkQF.js → FormItemContext-CsUFe5bU.js} +1 -1
  30. package/src/assets/web-panel/assets/GenericCardRenderer-D7xRjPjZ.js +1 -0
  31. package/src/assets/web-panel/assets/{Git-syATcaBt.js → Git-D-Qx9dhO.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-CYe_r8Zf.js → Governance-_YMYaU4n.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-GWxErB7k.js → Inference-J7Yzh-K_.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-qQvVCZoi.js → KnowledgeGraph-D37iI_Mo.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-BenAU2W8.js → Logs-oMTSYfGY.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-7agE3Or1.js → MarkdownRenderer-BqaPmC0W.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-D4Jn5fpD.js → Marketplace-DKUqYDaF.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DtAwoqiQ.js → McpTools-BEv3Gx61.js} +4 -4
  39. package/src/assets/web-panel/assets/{Memory-BI_O50I8.js → Memory-CtA8XD2y.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-CQWE2lqx.js → MobileBridge-ug7c1mMj.js} +1 -1
  41. package/src/assets/web-panel/assets/MobileProjects-BpX5g9It.js +1 -0
  42. package/src/assets/web-panel/assets/{Mtc-Dnr16qsn.js → Mtc-WJaMs4i2.js} +2 -2
  43. package/src/assets/web-panel/assets/{MtcAudit-CQ5Xe4-a.js → MtcAudit-DXnK_-ru.js} +2 -2
  44. package/src/assets/web-panel/assets/{Multisig-Bjr8O-wy.js → Multisig-C4Ev7726.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-CEe-KirU.js → NLProgramming-BMFb9_zk.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-spKJIKF9.js → Notes-Bl93nvBX.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-DRp83LFG.js → NotificationSettings-BN2W5cl6.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-h1A0XB2a.js → OrderTableRenderer-Dxc9oN4o.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BlgB0IYg.js → Organization-CAs48637.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-a_35HqZI.js → Overflow-Bhq27Zoc.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-CSNHCNPC.js → P2P-D61-2542.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-C8M1JH-1.js → PdhVaultBrowser-C1j4iUxz.js} +5 -5
  53. package/src/assets/web-panel/assets/{Permissions-DmjJi9Ms.js → Permissions-rJ2-fScM.js} +3 -3
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DfuwRyf4.js → PersonalDataHub-DFIlTok6.js} +2 -2
  55. package/src/assets/web-panel/assets/{Pipeline-B2-S4ekE.js → Pipeline-BjIgEWoZ.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-B1dOiBLC.js → Privacy-BQoH5wcX.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-_pNmc-DX.js → ProjectInit-CYR_-_Ub.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-DmwG2Ii1.js → ProjectSettings-nkatCq-9.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-SS9uZKCl.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-C6HSjg1d.js → Providers-BnKM9fsF.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-CrDmS7l1.js → QrScannerModal-Cfe82dbz.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-CfKvWt-x.js → QuickAsk-r1RbPufV.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-DMa6Kuzv.js → Recommend-CjCbM2WE.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DrktUo5x.js → RemoteSession-BuMGPH6V.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-BTPQ1vjL.js → Reputation-Bmj3NY1F.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-B6Q7QkMG.js → Row-BIsNcE_1.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-B1IJhAmX.js → RssFeed-BObmojD2.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-xbea1kGD.js → Search-BRmbkQNS.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-7rs0cO3F.js → Security-_rF3DRpY.js} +2 -2
  70. package/src/assets/web-panel/assets/{Services-0fjixK0S.js → Services-D0If9ZV4.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-B_rVq9Cu.js → Skeleton-o7zIksUg.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-C5uM90b9.js → Skills-oUR7zi9u.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-U4pYCIZH.js → Sla-fqKyGi03.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-Cdz4yTWx.js → SpeechSettings-B1wZ_gxx.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-Me3aetHv.js → SyncSettings-B3qJWYXq.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-Cf6aNkL_.js → Tasks-BH5_dUfr.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CYatk4tU.js → Templates-CCIVpjRP.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-DIMKLw7o.js → Tenant-2GZtTGnB.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-C_cp-uSJ.js → Terminal-BlMkfs_u.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-cUPVNADp.js → TimelineRenderer-U6hi5OMc.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-CiaEIXVf.js → Tokens-C-_BerGJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-DB1WU5lQ.js → Trigger-DaKzBgN3.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-Cfht9Ijy.js → Trust-CLvcsco3.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-K3P4Vt9S.js → UkeySign-BFn_Y1zZ.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-DWjhjXRh.js → VideoEditing-B0V18dLT.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-D9-Q1Kan.js → Wallet-BbmP7Imu.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-BDszy-oV.js → WebAuthn-Dewj_0kt.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-DIhij4rA.js → WorkflowEditor-DOxz3Lwa.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-D7VCiKbh.js → chat-B1OIpZnh.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-BvOd9pVn.js → colors-CSGNVdri.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-DoqXBiAO.js → compact-item-8S0vcg0u.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-CrKRzUtp.js → createContext-vZyc27TN.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DYEZcY55.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-BWAev4WC.js → hasIn-DWw3-UhA.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DvDOpsJB.js → index-B4pP2ycr.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-oY45XrkG.js → index-BDHyovnK.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CmJ6xKBO.js → index-BKEmQQvR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BoYrS_L2.js → index-BQssf0EQ.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-ww1QtLnX.js → index-BZnauCqN.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BWWsaimP.js → index-BdyokEau.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CoD31Ndm.js → index-BeBv896m.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DlGu7As6.js → index-BjC-TrOb.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-zH-tuuGZ.js → index-BkWd6YL7.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CEXfKSiI.js → index-BoIPHP4R.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CEPHMSih.js → index-BuB5P0TR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-PDxGjKRu.js → index-BwKrTVV0.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BkgnGX7v.js → index-C6r27A-o.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DV-Rfmfx.js → index-CB2MOS_8.js} +3 -3
  109. package/src/assets/web-panel/assets/{index-KR1-Em9C.js → index-CFQWZvak.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-8g5TJCZ3.js → index-CI3slBKI.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BCyP071m.js → index-CJgKP2cm.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CSb-tnIo.js → index-CLPr2vC_.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-1poMpMU0.js → index-CbZqw7pg.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BZGk8AbZ.js → index-CfEvacz7.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BXyl8O23.js → index-CwXBblm-.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BHOcVYrx.js → index-D1i_8oop.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bq_ctRpz.js → index-D8qXVfoV.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-gmxqu5Kk.js → index-DKwl1AkQ.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D23L1V76.js → index-DLAvUtOH.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CDGLdn12.js → index-DLgkAhEE.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-YGDy7nNq.js → index-DPgY5GLy.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Cx7M7PSF.js → index-Dc40pX3F.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-JzUmJMvn.js → index-DcfLXAW7.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-HwHdTusY.js → index-DeCS12Mh.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B30NvR21.js → index-Dg0Izipr.js} +1 -1
  126. package/src/assets/web-panel/assets/index-DmVFfcNR.js +1 -0
  127. package/src/assets/web-panel/assets/{index-B0vGEbJT.js → index-DtHWHJnj.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Bf9YlbDn.js → index-Q6oyLnKC.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Bj7EgmOp.js → index-dxocDVD_.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-ISvPZ05r.js → index-t-q3rkVm.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-C5kRmj3P.js → index-tr1x96W9.js} +1 -1
  132. package/src/assets/web-panel/assets/index-x7YyhMUa.js +1 -0
  133. package/src/assets/web-panel/assets/{index-BN9m4Ux2.js → index-xx5M5Rbj.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-XW-OR3mL.js → initDefaultProps-Di5YFId0.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-CeuEHh20.js → motion-BVSN0aeL.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-Dva79Keg.js → move-DHNiaP2l.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-C0B6bD2j.js → mtc-parser-xJPf3gQD.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-AkZvO-a2.js → omit-C7qzUdkN.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-B4r55qGc.js → pickAttrs-pSpjg3Le.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-BLH-z7YE.js → placementArrow-cs_jL_UC.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-ksEGZ2Wf.js → responsiveObserve-DkS_Zs4r.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-Cth4OD1Z.js → slide-B5O1Kpxo.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-9S83ezxw.js → statusUtils-BX02GnZp.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-7yQmQGZ4.js → styleChecker-EmBYRftd.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-DpGnMmPc.js → useFlexGapSupport-ZGzN1cU8.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-C4zDZIXH.js → useFs-CfP7M1m7.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-CoLICdUZ.js → usePersonalDataHub-CbIPHgNh.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-CKyH-35X.js → vnode-7xh0If_O.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-DRDGit17.js → zoom-DmitvTR2.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-manifest.json +17 -3
  152. package/src/commands/agent.js +72 -6
  153. package/src/commands/background-session.js +173 -3
  154. package/src/commands/browse.js +86 -0
  155. package/src/commands/cloud.js +232 -0
  156. package/src/commands/doctor.js +61 -6
  157. package/src/commands/mcp.js +107 -0
  158. package/src/commands/plugin.js +63 -1
  159. package/src/commands/routine.js +367 -0
  160. package/src/commands/session.js +396 -0
  161. package/src/data/changelog.json +12 -2
  162. package/src/harness/jsonl-session-store.js +152 -3
  163. package/src/harness/mcp-client.js +50 -0
  164. package/src/harness/session-index.js +295 -0
  165. package/src/harness/session-mirror.js +142 -0
  166. package/src/harness/transcript-integrity.js +182 -0
  167. package/src/index.js +8 -0
  168. package/src/lib/agent-sandbox.js +68 -0
  169. package/src/lib/agents.js +12 -4
  170. package/src/lib/api-key-helper.js +62 -0
  171. package/src/lib/background-agent-supervisor.js +158 -2
  172. package/src/lib/channels/channel-manager.js +126 -0
  173. package/src/lib/channels/telegram-channel.js +112 -0
  174. package/src/lib/channels/webhook-channel.js +140 -0
  175. package/src/lib/chrome-connector.js +386 -0
  176. package/src/lib/cloud/bundle.js +110 -0
  177. package/src/lib/cloud/cloud-client.js +152 -0
  178. package/src/lib/computer-use/authorization.js +173 -0
  179. package/src/lib/computer-use/computer-use-server.js +276 -0
  180. package/src/lib/computer-use/control-backend.js +150 -0
  181. package/src/lib/dependency-install-policy.js +130 -0
  182. package/src/lib/doctor-checkup.js +652 -0
  183. package/src/lib/exit-codes.cjs +77 -0
  184. package/src/lib/headless-manifest.js +175 -0
  185. package/src/lib/hook-runner.cjs +70 -4
  186. package/src/lib/ide-context-redaction.js +130 -0
  187. package/src/lib/ide-context.js +89 -13
  188. package/src/lib/jsonl-session-store.js +6 -0
  189. package/src/lib/llm-config-defaults.js +24 -8
  190. package/src/lib/lsp/lsp-server-registry.js +48 -21
  191. package/src/lib/plugin-runtime/governance.js +174 -0
  192. package/src/lib/pr-link-ledger.js +221 -0
  193. package/src/lib/project-mcp-trust.js +87 -0
  194. package/src/lib/routine-store.js +352 -0
  195. package/src/lib/sensitive-file-guard.js +51 -0
  196. package/src/lib/session-store-guard.js +40 -0
  197. package/src/lib/session-usage.js +318 -2
  198. package/src/lib/sub-agent-context.js +30 -3
  199. package/src/repl/agent-repl.js +361 -3
  200. package/src/repl/bg-dashboard.js +355 -0
  201. package/src/repl/fast-mode.js +103 -0
  202. package/src/repl/fullscreen-tui.js +197 -0
  203. package/src/repl/slash-command-registry.js +11 -3
  204. package/src/repl/voice-dictation.js +132 -0
  205. package/src/runtime/agent-core.js +344 -7
  206. package/src/runtime/coding-agent-contract-shared.cjs +107 -2
  207. package/src/runtime/coding-agent-policy.cjs +17 -0
  208. package/src/runtime/headless-runner.js +137 -14
  209. package/src/runtime/headless-stream.js +43 -9
  210. package/src/runtime/mcp-config.js +32 -1
  211. package/src/runtime/policies/agent-policy.js +3 -0
  212. package/src/assets/web-panel/assets/Artifacts-DQvJoQ6E.js +0 -1
  213. package/src/assets/web-panel/assets/ChatBubbleRenderer-BAV9V-t-.js +0 -1
  214. package/src/assets/web-panel/assets/GenericCardRenderer-DxxEdn2r.js +0 -1
  215. package/src/assets/web-panel/assets/MobileProjects-CVtTqgtg.js +0 -1
  216. package/src/assets/web-panel/assets/Projects-COATmHxF.js +0 -1
  217. package/src/assets/web-panel/assets/devWarning-nDB--2xr.js +0 -1
  218. package/src/assets/web-panel/assets/index-B1_pRTtB.js +0 -1
  219. package/src/assets/web-panel/assets/index-TMM9FuW-.js +0 -1
@@ -521,7 +521,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
521
521
  kind: "code",
522
522
  tier: "extension",
523
523
  description:
524
- "Write and execute code in Python, Node.js, or Bash. Use this when the user needs data processing, calculations, file batch operations, API calls, or any task best solved with a script. Scripts are saved for reference. Missing Python packages are auto-installed.",
524
+ "Write and execute code in Python, Node.js, or Bash. Use this when the user needs data processing, calculations, file batch operations, API calls, or any task best solved with a script. Scripts run from a temp file unless persist:true. Missing Python packages are NOT auto-installed unless the user opted in (settings runCode.autoInstall).",
525
525
  inputSchema: {
526
526
  type: "object",
527
527
  properties: {
@@ -538,7 +538,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
538
538
  persist: {
539
539
  type: "boolean",
540
540
  description:
541
- "If true (default), save script in .chainlesschain/agent-scripts/. If false, use temp file and clean up.",
541
+ "If true, save the script in .chainlesschain/agent-scripts/ for reference. Default false: run from a temp file outside the project.",
542
542
  },
543
543
  },
544
544
  required: ["language", "code"],
@@ -599,6 +599,23 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
599
599
  description:
600
600
  "Run the sub-agent in the BACKGROUND: the call returns immediately with a running handle and you continue working; the sub-agent's result is delivered to you automatically in a later turn (the run waits for stragglers before finishing). Use for independent subtasks you don't need before your next step.",
601
601
  },
602
+ disallowedTools: {
603
+ type: "array",
604
+ items: { type: "string" },
605
+ description:
606
+ "Optional tool DENY-list for the sub-agent: these are removed from whatever tool set it would otherwise get (explicit `tools`, agent-file allowlist, or all).",
607
+ },
608
+ maxTurns: {
609
+ type: "number",
610
+ description:
611
+ "Optional iteration cap for the sub-agent's own loop (positive integer; default 8 or the profile's cap).",
612
+ },
613
+ isolation: {
614
+ type: "string",
615
+ enum: ["worktree"],
616
+ description:
617
+ "Optional isolation mode: \"worktree\" runs the sub-agent in a fresh git worktree so its file edits land on an isolated branch (diff/merge summary comes back with the result).",
618
+ },
602
619
  },
603
620
  required: ["task"],
604
621
  },
@@ -1058,6 +1075,94 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
1058
1075
  tags: ["tool:browser_state", "contract:coding-agent", "tier:extension"],
1059
1076
  },
1060
1077
  },
1078
+ {
1079
+ name: "browser_act",
1080
+ title: "Browser Actions",
1081
+ kind: "browser",
1082
+ tier: "extension",
1083
+ description:
1084
+ "Perform EXPLICIT actions in the user's connected Chrome over loopback CDP: click, type, press, navigate (http/https only), waitForSelector, screenshot (saved to a generated temp path — never a chosen one), assertText. Approval-gated (HIGH risk): use browser_state first to observe; only act when the task genuinely requires driving the browser. Steps run in order and fail fast unless continue_on_error; each returns {ok, action, detail, durationMs} and every executed step is audit-logged under ~/.chainlesschain/browser-actions/. Requires a debuggable Chrome (`cc browse chrome launch`).",
1085
+ inputSchema: {
1086
+ type: "object",
1087
+ properties: {
1088
+ actions: {
1089
+ type: "array",
1090
+ description:
1091
+ "Ordered action steps. Each item: {type: click|type|press|navigate|waitForSelector|screenshot|assertText} plus its fields — click/waitForSelector/assertText need selector; type needs selector+text; press needs key; navigate needs url (http/https); waitForSelector accepts timeout_ms (capped 30000); assertText needs expected (substring); screenshot takes NO path (generated internally).",
1092
+ items: {
1093
+ type: "object",
1094
+ properties: {
1095
+ type: {
1096
+ type: "string",
1097
+ enum: [
1098
+ "click",
1099
+ "type",
1100
+ "press",
1101
+ "navigate",
1102
+ "waitForSelector",
1103
+ "screenshot",
1104
+ "assertText",
1105
+ ],
1106
+ description: "Action kind",
1107
+ },
1108
+ selector: {
1109
+ type: "string",
1110
+ description:
1111
+ "CSS selector (click/type/waitForSelector/assertText)",
1112
+ },
1113
+ text: { type: "string", description: "Text to type (type)" },
1114
+ key: {
1115
+ type: "string",
1116
+ description: "Key to press, e.g. Enter (press)",
1117
+ },
1118
+ url: {
1119
+ type: "string",
1120
+ description: "http(s):// URL to open (navigate)",
1121
+ },
1122
+ timeout_ms: {
1123
+ type: "number",
1124
+ description:
1125
+ "waitForSelector timeout in ms (default 5000, max 30000)",
1126
+ },
1127
+ expected: {
1128
+ type: "string",
1129
+ description: "Expected substring (assertText)",
1130
+ },
1131
+ },
1132
+ required: ["type"],
1133
+ },
1134
+ },
1135
+ cdp_url: {
1136
+ type: "string",
1137
+ description:
1138
+ "CDP endpoint — loopback-only, e.g. http://127.0.0.1:9222 (default port 9222)",
1139
+ },
1140
+ port: {
1141
+ type: "number",
1142
+ description: "CDP port of the debuggable Chrome (default 9222)",
1143
+ },
1144
+ tab: {
1145
+ type: "number",
1146
+ description: "Tab index to act in (default 0)",
1147
+ },
1148
+ continue_on_error: {
1149
+ type: "boolean",
1150
+ description:
1151
+ "Keep executing remaining steps after a failed one (default false: fail fast)",
1152
+ },
1153
+ },
1154
+ required: ["actions"],
1155
+ },
1156
+ ...TOOL_POLICY_METADATA.browser_act,
1157
+ permissions: {
1158
+ level: "elevated",
1159
+ scopes: ["browser:act"],
1160
+ },
1161
+ telemetry: {
1162
+ category: "browser",
1163
+ tags: ["tool:browser_act", "contract:coding-agent", "tier:extension"],
1164
+ },
1165
+ },
1061
1166
  ]);
1062
1167
 
1063
1168
  const CODING_AGENT_MVP_TOOL_NAMES = Object.freeze(
@@ -320,6 +320,23 @@ const TOOL_POLICY_METADATA = Object.freeze({
320
320
  approvalFlow: "auto",
321
321
  isReadOnly: true,
322
322
  },
323
+ // DRIVES the user's connected Chrome over loopback CDP — clicks, typing,
324
+ // key presses, navigation, screenshots, text assertions. Unlike
325
+ // browser_state (pure observation, the default) this mutates the page and
326
+ // acts inside whatever session that browser is logged into, so it carries
327
+ // the same gating as run_shell/run_code: HIGH risk (the ApprovalGate
328
+ // CONFIRMs HIGH even on the trusted/auto tier, so auto mode still prompts),
329
+ // blocked in plan mode, plan approval + explicit confirmation required.
330
+ browser_act: {
331
+ riskLevel: RISK_LEVELS.HIGH,
332
+ category: TOOL_CATEGORIES.EXECUTE,
333
+ availableInPlanMode: false,
334
+ planModeBehavior: "blocked",
335
+ requiresPlanApproval: true,
336
+ requiresConfirmation: true,
337
+ approvalFlow: "policy",
338
+ isReadOnly: false,
339
+ },
323
340
  });
324
341
 
325
342
  function normalizeGitCommand(command) {
@@ -42,16 +42,30 @@ import {
42
42
  appendUserMessage as jsonlAppendUserMessage,
43
43
  appendAssistantMessage as jsonlAppendAssistantMessage,
44
44
  appendTokenUsage as jsonlAppendTokenUsage,
45
+ appendToolCallCompact as jsonlAppendToolCallCompact,
45
46
  appendCompactEvent as jsonlAppendCompactEvent,
46
47
  rebuildMessages as jsonlRebuildMessages,
47
48
  sessionExists as jsonlSessionExists,
48
49
  getLastSessionId as jsonlGetLastSessionId,
50
+ verifySession as jsonlVerifySession,
49
51
  } from "../harness/jsonl-session-store.js";
50
52
  import { expandFileRefsAsync } from "./file-ref-expander.js";
51
53
  import { composeSystemPrompt } from "./system-prompt.js";
52
54
  import { buildUserContent } from "../lib/image-input.js";
53
55
  import { mergeConsecutiveMessages } from "./message-roles.js";
54
56
  import { isHeadlessConfigCommand } from "../lib/headless-config-command.js";
57
+ import {
58
+ STREAM_PROTOCOL_VERSION,
59
+ computePolicyDigest,
60
+ computeToolsHash,
61
+ buildLoadedSources,
62
+ } from "../lib/headless-manifest.js";
63
+ import {
64
+ HEADLESS_EXIT_CODES,
65
+ classifyLoopError,
66
+ exitCodeForEndReason,
67
+ } from "../lib/exit-codes.cjs";
68
+ import { isolationLevel } from "../lib/agent-sandbox.js";
55
69
  import { withQuietStdout } from "./quiet-stdout.js";
56
70
  import { CostBudget } from "../lib/cost-budget.js";
57
71
  import {
@@ -198,13 +212,18 @@ export function parseToolList(value) {
198
212
  * Persistence is intentionally OFF unless a resume/continue/persist intent is
199
213
  * present, so a plain one-shot `cc agent -p "..."` writes nothing to disk.
200
214
  *
201
- * @param {object} options { resume, continueSession, sessionId, persistSession }
215
+ * `--ephemeral` forces persistence OFF regardless of the above: a resume id
216
+ * still REPLAYS prior history into context, but nothing new is written — the
217
+ * deterministic-CI shape ("read context, leave no trace").
218
+ *
219
+ * @param {object} options { resume, continueSession, sessionId, persistSession, ephemeral }
202
220
  * @param {object} store { getLastSessionId } (injection seam)
203
221
  * @param {string} fallbackId used when nothing is being resumed
204
222
  * @returns {{ sessionId:string, resumeId:string|null, persist:boolean, wantLatest:boolean }}
205
223
  */
206
224
  export function resolveHeadlessSession(options = {}, store = {}, fallbackId) {
207
- const { resume, continueSession, sessionId, persistSession } = options;
225
+ const { resume, continueSession, sessionId, persistSession, ephemeral } =
226
+ options;
208
227
  const wantLatest = continueSession === true || resume === true;
209
228
  let resumeId = null;
210
229
  if (wantLatest) {
@@ -215,7 +234,10 @@ export function resolveHeadlessSession(options = {}, store = {}, fallbackId) {
215
234
  } else if (typeof resume === "string" && resume.trim()) {
216
235
  resumeId = resume.trim();
217
236
  }
218
- const persist = persistSession === true || resumeId != null || wantLatest;
237
+ const persist =
238
+ ephemeral === true
239
+ ? false
240
+ : persistSession === true || resumeId != null || wantLatest;
219
241
  const id = resumeId || sessionId || fallbackId;
220
242
  return { sessionId: id, resumeId, persist, wantLatest };
221
243
  }
@@ -436,8 +458,11 @@ export async function runAgentHeadless(options = {}, deps = {}) {
436
458
  appendAssistantMessage:
437
459
  deps.appendAssistantMessage || jsonlAppendAssistantMessage,
438
460
  appendTokenUsage: deps.appendTokenUsage || jsonlAppendTokenUsage,
461
+ appendToolCallCompact:
462
+ deps.appendToolCallCompact || jsonlAppendToolCallCompact,
439
463
  appendCompactEvent: deps.appendCompactEvent || jsonlAppendCompactEvent,
440
464
  getLastSessionId: deps.getLastSessionId || jsonlGetLastSessionId,
465
+ verifySession: deps.verifySession || jsonlVerifySession,
441
466
  };
442
467
  const isStream = outputFormat === "stream-json";
443
468
  const isJson = outputFormat === "json";
@@ -626,6 +651,30 @@ export async function runAgentHeadless(options = {}, deps = {}) {
626
651
  // never duplicated.
627
652
  let history = [];
628
653
  if (resumeId && store.sessionExists(resumeId)) {
654
+ // Tamper gate: a broken transcript hash chain means the file was edited
655
+ // outside the store. Headless runs fail closed — a tampered transcript is
656
+ // never silently rebuilt into trusted model context. Escape hatch:
657
+ // CC_ALLOW_TAMPERED_RESUME=1 resumes with a stderr warning.
658
+ let trust = null;
659
+ try {
660
+ trust = store.verifySession(resumeId);
661
+ } catch {
662
+ trust = null; // verification unavailable → keep legacy behaviour
663
+ }
664
+ if (trust && trust.status === "tampered") {
665
+ if (process.env.CC_ALLOW_TAMPERED_RESUME !== "1") {
666
+ const msg =
667
+ `Session ${resumeId} transcript failed integrity verification (${trust.reason}` +
668
+ (trust.firstInvalidLine ? ` at line ${trust.firstInvalidLine}` : "") +
669
+ `). Refusing to resume tampered context; run 'cc session verify ${resumeId}', or set CC_ALLOW_TAMPERED_RESUME=1 to override.`;
670
+ emitHeadlessError(msg);
671
+ writeErr(msg + "\n");
672
+ return { exitCode: 1, result: msg, isError: true };
673
+ }
674
+ writeErr(
675
+ `⚠ Resuming a TAMPERED transcript (${trust.reason}) — restored context is untrusted.\n`,
676
+ );
677
+ }
629
678
  try {
630
679
  history = (store.rebuildMessages(resumeId) || []).filter(
631
680
  (m) => m && m.role !== "system",
@@ -871,7 +920,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
871
920
  } catch (err) {
872
921
  writeErr(`Error: ${err.message}\n`);
873
922
  emitHeadlessError(err.message);
874
- return { exitCode: 1, result: err.message, isError: true };
923
+ // Bad --mcp-config / MCP wiring is a CONFIG error, not a run failure.
924
+ return {
925
+ exitCode: HEADLESS_EXIT_CODES.CONFIG_ERROR,
926
+ result: err.message,
927
+ isError: true,
928
+ };
875
929
  }
876
930
  }
877
931
 
@@ -914,7 +968,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
914
968
  writeErr(`Error: ${err.message}\n`);
915
969
  if (mcp?.mcpClient) await mcp.mcpClient.disconnectAll().catch(() => {});
916
970
  emitHeadlessError(err.message);
917
- return { exitCode: 1, result: err.message, isError: true };
971
+ // A bad --permission-prompt-tool reference is a CONFIG error.
972
+ return {
973
+ exitCode: HEADLESS_EXIT_CODES.CONFIG_ERROR,
974
+ result: err.message,
975
+ isError: true,
976
+ };
918
977
  }
919
978
  if (approvalGate && typeof approvalGate.setConfirmer === "function") {
920
979
  approvalGate.setConfirmer(
@@ -1114,6 +1173,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1114
1173
  cache_read_input_tokens: 0,
1115
1174
  cache_creation_input_tokens: 0,
1116
1175
  };
1176
+ // 用量归因: attributed child-loop usage (spawn_sub_agent / isolated
1177
+ // run_skill). Kept OUT of the `usage` accumulator above so the result
1178
+ // envelope and the end-of-run aggregate token_usage event keep their
1179
+ // long-standing "main loop only" semantics — the attributed records are
1180
+ // persisted as their own token_usage events instead (no double count).
1181
+ const attributedUsage = [];
1117
1182
  let finalText = "";
1118
1183
  let endReason = "complete";
1119
1184
  let stopForCost = false;
@@ -1140,11 +1205,32 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1140
1205
  emitStream({
1141
1206
  type: "system",
1142
1207
  subtype: "init",
1208
+ // Deterministic-headless manifest (gap-analysis 2026-07-11): protocol
1209
+ // version + persistence + live sources + policy/tool digests so CI can
1210
+ // assert the run shape. Mirrors agent-sdk PROTOCOL_VERSION.
1211
+ protocol_version: STREAM_PROTOCOL_VERSION,
1143
1212
  session_id: sessionId,
1213
+ session_persistence: persist,
1144
1214
  model,
1145
1215
  provider,
1146
1216
  permission_mode: options.permissionMode || "default",
1147
1217
  tools: enabledToolNames,
1218
+ tools_hash: computeToolsHash(enabledToolNames),
1219
+ policy_digest: computePolicyDigest({
1220
+ permissionMode: options.permissionMode,
1221
+ allowedTools: options.allowedTools,
1222
+ disallowedTools: options.disallowedTools,
1223
+ permissionRules,
1224
+ }),
1225
+ loaded_sources: buildLoadedSources({
1226
+ permissionRules,
1227
+ settingsHooks,
1228
+ mcp: Boolean(mcp),
1229
+ enabledToolNames,
1230
+ }),
1231
+ // True isolation level for tool subprocesses: os-sandbox (bwrap) /
1232
+ // container (docker) / policy-only (no sandbox — rules are pre-execution).
1233
+ isolation_level: isolationLevel(options.sandbox),
1148
1234
  max_turns: budget.limit,
1149
1235
  resumed_from: resumeId,
1150
1236
  history_messages: history.length,
@@ -1274,13 +1360,26 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1274
1360
  break;
1275
1361
  }
1276
1362
  case "token-usage": {
1277
- usage.input_tokens += event.usage?.input_tokens || 0;
1278
- usage.output_tokens += event.usage?.output_tokens || 0;
1279
- // Carry prompt-cache tokens into accumulated usage (cost accuracy).
1280
- usage.cache_read_input_tokens +=
1281
- event.usage?.cache_read_input_tokens || 0;
1282
- usage.cache_creation_input_tokens +=
1283
- event.usage?.cache_creation_input_tokens || 0;
1363
+ if (event.attribution) {
1364
+ // Child-loop (sub-agent / isolated-skill) spend: excluded from
1365
+ // the main `usage` envelope, persisted with its attribution
1366
+ // frame below, but still counted toward the cost budget — it
1367
+ // is real money on the same key.
1368
+ attributedUsage.push({
1369
+ provider: event.provider ?? null,
1370
+ model: event.model ?? null,
1371
+ usage: event.usage || null,
1372
+ attribution: event.attribution,
1373
+ });
1374
+ } else {
1375
+ usage.input_tokens += event.usage?.input_tokens || 0;
1376
+ usage.output_tokens += event.usage?.output_tokens || 0;
1377
+ // Carry prompt-cache tokens into accumulated usage (cost accuracy).
1378
+ usage.cache_read_input_tokens +=
1379
+ event.usage?.cache_read_input_tokens || 0;
1380
+ usage.cache_creation_input_tokens +=
1381
+ event.usage?.cache_creation_input_tokens || 0;
1382
+ }
1284
1383
  emitStream({ type: "token_usage", usage: event.usage });
1285
1384
  if (costBudget) {
1286
1385
  costBudget.add({
@@ -1423,7 +1522,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1423
1522
  } else {
1424
1523
  writeErr(`Error: ${message}\n`);
1425
1524
  }
1426
- return { exitCode: 1, result: message, isError: true };
1525
+ // Provider/transport failures get their own exit code (5) so CI can tell
1526
+ // "the model call failed" from "the run itself errored" (1).
1527
+ return { exitCode: classifyLoopError(err), result: message, isError: true };
1427
1528
  } finally {
1428
1529
  // Drop the signal handlers first — a normal return must not leave a
1429
1530
  // process-wide SIGINT/SIGTERM listener behind (a later Ctrl-C would wrongly
@@ -1539,6 +1640,22 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1539
1640
  if (persist && !isError) {
1540
1641
  try {
1541
1642
  if (finalText) store.appendAssistantMessage(sessionId, finalText);
1643
+ // 用量归因: compact per-tool records (name + error flag + skill hint —
1644
+ // never args) so `cc session usage --by tool|mcp` can aggregate
1645
+ // headless sessions too.
1646
+ for (const tc of toolCalls) {
1647
+ store.appendToolCallCompact(sessionId, {
1648
+ tool: tc.tool,
1649
+ isError: Boolean(tc.is_error),
1650
+ skill:
1651
+ tc.tool === "run_skill" ? tc.args?.skill_name || null : undefined,
1652
+ });
1653
+ }
1654
+ // Attributed child-loop usage first (chronology: it happened during
1655
+ // the run), then the unchanged main-loop aggregate.
1656
+ for (const au of attributedUsage) {
1657
+ store.appendTokenUsage(sessionId, au);
1658
+ }
1542
1659
  store.appendTokenUsage(sessionId, usage);
1543
1660
  } catch {
1544
1661
  // Persistence is best-effort — never fail the run over it.
@@ -1675,7 +1792,13 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1675
1792
  }
1676
1793
  }
1677
1794
 
1678
- return { exitCode: isError ? 1 : 0, result: finalText, isError };
1795
+ // Exit-code taxonomy: max-turns → 3, cost cap → 4 (both still non-zero, so
1796
+ // "any failure" checks keep working; scripts can now tell exhaustion apart).
1797
+ return {
1798
+ exitCode: exitCodeForEndReason(endReason, isError),
1799
+ result: finalText,
1800
+ isError,
1801
+ };
1679
1802
  }
1680
1803
 
1681
1804
  function buildResultEnvelope({
@@ -43,6 +43,12 @@ import {
43
43
  makePermissionPromptConfirmer,
44
44
  } from "./mcp-config.js";
45
45
  import { maybeApplyToolSearch } from "./mcp-tool-search.js";
46
+ import {
47
+ STREAM_PROTOCOL_VERSION,
48
+ computePolicyDigest,
49
+ computeToolsHash,
50
+ buildLoadedSources,
51
+ } from "../lib/headless-manifest.js";
46
52
  import { IterationBudget } from "../lib/iteration-budget.js";
47
53
  import { CostBudget } from "../lib/cost-budget.js";
48
54
  import {
@@ -494,14 +500,20 @@ async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
494
500
  break;
495
501
  }
496
502
  case "token-usage":
497
- usage.input_tokens += event.usage?.input_tokens || 0;
498
- usage.output_tokens += event.usage?.output_tokens || 0;
499
- // Carry prompt-cache tokens into the turn's accumulated usage so the
500
- // final `result` envelope (read by IDE panels) reflects caching too.
501
- usage.cache_read_input_tokens +=
502
- event.usage?.cache_read_input_tokens || 0;
503
- usage.cache_creation_input_tokens +=
504
- event.usage?.cache_creation_input_tokens || 0;
503
+ // 用量归因: attributed child-loop usage (sub-agent / isolated skill)
504
+ // is forwarded on the stream (same wire shape) and counted toward the
505
+ // cost budget, but stays out of the turn's `usage` envelope, which
506
+ // keeps its long-standing main-loop-only semantics.
507
+ if (!event.attribution) {
508
+ usage.input_tokens += event.usage?.input_tokens || 0;
509
+ usage.output_tokens += event.usage?.output_tokens || 0;
510
+ // Carry prompt-cache tokens into the turn's accumulated usage so the
511
+ // final `result` envelope (read by IDE panels) reflects caching too.
512
+ usage.cache_read_input_tokens +=
513
+ event.usage?.cache_read_input_tokens || 0;
514
+ usage.cache_creation_input_tokens +=
515
+ event.usage?.cache_creation_input_tokens || 0;
516
+ }
505
517
  emit({ type: "token_usage", usage: event.usage });
506
518
  if (costBudget) {
507
519
  costBudget.add({
@@ -712,7 +724,9 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
712
724
  deps.appendAssistantMessage || jsonlAppendAssistantMessage,
713
725
  rebuildMessages: deps.rebuildMessages || jsonlRebuildMessages,
714
726
  };
715
- const persist = Boolean(options.sessionId);
727
+ // --ephemeral forces persistence OFF even with an explicit session id (the
728
+ // id is kept for event correlation only; nothing is written or replayed).
729
+ const persist = Boolean(options.sessionId) && options.ephemeral !== true;
716
730
 
717
731
  // ── Interactive approvals (--interactive-approvals; chat-panel UX) ────────
718
732
  // CONFIRM-tier decisions (risky shell via the ApprovalGate, settings/hook
@@ -955,11 +969,31 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
955
969
  emit({
956
970
  type: "system",
957
971
  subtype: "init",
972
+ // Deterministic-headless manifest (gap-analysis 2026-07-11): protocol
973
+ // version + persistence + live sources + policy/tool digests. The init
974
+ // event fires BEFORE MCP resolution here (stream consumers expect it
975
+ // promptly), so `mcp` in loaded_sources reflects the run's MCP intent
976
+ // (config file / registry auto-connect enabled), not connection outcome.
977
+ protocol_version: STREAM_PROTOCOL_VERSION,
958
978
  session_id: sessionId,
979
+ session_persistence: persist,
959
980
  model,
960
981
  provider,
961
982
  permission_mode: options.permissionMode || "default",
962
983
  tools: enabledToolNames,
984
+ tools_hash: computeToolsHash(enabledToolNames),
985
+ policy_digest: computePolicyDigest({
986
+ permissionMode: options.permissionMode,
987
+ allowedTools: options.allowedTools,
988
+ disallowedTools: disabledTools,
989
+ permissionRules,
990
+ }),
991
+ loaded_sources: buildLoadedSources({
992
+ permissionRules,
993
+ settingsHooks,
994
+ mcp: Boolean(options.mcpConfig) || options.useRegisteredMcp !== false,
995
+ enabledToolNames,
996
+ }),
963
997
  input_format: "stream-json",
964
998
  additional_directories: additionalDirectories,
965
999
  resumed_messages: resumedMessages,
@@ -631,17 +631,48 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
631
631
  if (root) files.push(path.join(root, ".mcp.json"));
632
632
  files.push(path.join(cwd, ".mcp.json"));
633
633
 
634
+ // Fingerprint trust (gap 2026-07-11): the --project-mcp opt-in covers the
635
+ // file as last seen. First use records a sha256; a CHANGED file is refused
636
+ // (fail-closed) until re-trusted via CC_PROJECT_MCP_TRUST=1 or
637
+ // `cc mcp trust-project`. Injectable for tests.
638
+ const trust =
639
+ deps.projectMcpTrust ||
640
+ (await import("../lib/project-mcp-trust.js").catch(() => null));
641
+
634
642
  const servers = {};
635
643
  const seenFiles = [];
636
644
  for (const file of files) {
637
645
  if (!fileExists(file)) continue;
646
+ let content;
638
647
  let raw;
639
648
  try {
640
- raw = JSON.parse(readFile(file));
649
+ content = readFile(file);
650
+ raw = JSON.parse(content);
641
651
  } catch (err) {
642
652
  writeErr(` mcp: ignoring malformed ${file} (${err.message})\n`);
643
653
  continue;
644
654
  }
655
+ if (trust) {
656
+ try {
657
+ const check = trust.checkProjectMcpTrust(file, content);
658
+ if (check.status === "changed") {
659
+ if (trust.projectMcpRetrustRequested(env)) {
660
+ trust.recordProjectMcpTrust(file, content);
661
+ writeErr(` mcp: ${file} re-trusted (CC_PROJECT_MCP_TRUST).\n`);
662
+ } else {
663
+ writeErr(
664
+ ` mcp: SKIPPING ${file} — its content changed since it was last trusted. ` +
665
+ `Review the diff, then re-trust with CC_PROJECT_MCP_TRUST=1 or \`cc mcp trust-project\`.\n`,
666
+ );
667
+ continue;
668
+ }
669
+ } else if (check.status === "first-use") {
670
+ trust.recordProjectMcpTrust(file, content);
671
+ }
672
+ } catch {
673
+ /* trust bookkeeping is best-effort; the opt-in gate above still holds */
674
+ }
675
+ }
645
676
  const parsed = parseMcpServers(raw);
646
677
  if (Object.keys(parsed).length > 0) {
647
678
  Object.assign(servers, parsed); // later file (cwd) overrides earlier (root)
@@ -59,6 +59,9 @@ export function resolveAgentPolicy({
59
59
  // --remote-control also applies interactively: the REPL starts the
60
60
  // paired-device approval bridge at startup (批26).
61
61
  remoteControl: overrides.remoteControl === true,
62
+ // --channels: inbound channel listeners (webhook/telegram) whose events
63
+ // become user turns in the interactive session (gap-2026-07-11 P0#5).
64
+ channels: overrides.channels || null,
62
65
  };
63
66
  }
64
67
 
@@ -1 +0,0 @@
1
- import{E as J,b as z,r as C,I as k,J as y,U as _,c as r,K as o,S,V as B,o as V,f as D,P as d,Q as f,R as p,F as j}from"./vendor-Bn1JzzAn.js";import{M as Q}from"./MarkdownRenderer-7agE3Or1.js";import{u as F,_ as W,d as R}from"./index-DV-Rfmfx.js";import{R as q}from"./icons-DG5UD-6K.js";import"./markdown-Yo_c6Krv.js";import"./markdown-CsiA8-E5.js";const K=J("artifacts",()=>{const h=C([]),t=C(!1),u=C(""),e=C(""),w=C(null),b=C(!1),A=z(()=>[...new Set(h.value.map(a=>a.kind).filter(Boolean))].sort());async function l(){const n=F();t.value=!0;try{const a={type:"artifact-list"};u.value&&(a.kind=u.value),e.value&&(a.session=e.value);const s=await n.sendRaw(a);s&&Array.isArray(s.artifacts)&&(h.value=[...s.artifacts].reverse())}catch{}finally{t.value=!1}}async function g(n){const a=F();b.value=!0,w.value={entry:n,previewable:!1};try{const s=await a.sendRaw({type:"artifact-content",artifactId:n.id});w.value={entry:n,previewable:s?.previewable===!0,encoding:s?.encoding||null,content:s?.content||"",truncated:s?.truncated===!0,reason:s?.reason||null}}catch(s){w.value={entry:n,previewable:!1,reason:s?.message||"preview failed"}}finally{b.value=!1}}function i(){w.value=null}const m=z(()=>{const n=w.value;return!n?.previewable||n.encoding!=="base64"?null:`data:${n.entry?.mime||"image/png"};base64,${n.content}`}),O=z(()=>{const n=w.value;return n?.previewable===!0&&n.encoding==="utf8"&&String(n.entry?.mime||"").toLowerCase()==="text/markdown"});async function P(n,a={}){if(!n?.id)return!1;const s=a.fetch||globalThis.fetch,L=a.document||globalThis.document,T=a.URL||globalThis.URL,N=(a.config||globalThis.window?.__CC_CONFIG__)??{};try{const U=await s(`/api/artifacts/${n.id}/download`,{headers:N.wsToken?{Authorization:`Bearer ${N.wsToken}`}:{}});if(!U.ok)return!1;const G=await U.blob(),E=T.createObjectURL(G),I=L.createElement("a");return I.href=E,I.download=n.title||n.id,L.body.appendChild(I),I.click(),I.remove(),T.revokeObjectURL(E),!0}catch{return!1}}async function M(n){const a=F();if(!n)return!1;try{const s=await a.sendRaw({type:"artifact-remove",artifactId:n});return w.value?.entry?.id===n&&(w.value=null),await l(),s?.found===!0}catch{return!1}}async function c(){const n=F();try{const a=await n.sendRaw({type:"artifact-clean"});return await l(),Number(a?.removed)||0}catch{return 0}}function v(n){const a=Number(n)||0;return a<1024?`${a} B`:a<1024*1024?`${(a/1024).toFixed(1)} KB`:`${(a/(1024*1024)).toFixed(1)} MB`}function x(n){switch(n){case"report":return"blue";case"patch":return"purple";case"screenshot":return"cyan";case"log":return"default";case"data":return"green";default:return"default"}}return{artifacts:h,loading:t,kindFilter:u,sessionFilter:e,kinds:A,preview:w,previewLoading:b,previewImageSrc:m,previewIsMarkdown:O,fetchArtifacts:l,openPreview:g,closePreview:i,removeArtifact:M,cleanExpired:c,downloadArtifact:P,formatSize:v,kindColor:x}}),H={__name:"Artifacts",setup(h,{expose:t}){t();const u=K(),e=[{title:"标题",key:"title",dataIndex:"title",ellipsis:!0},{title:"类型",key:"kind",dataIndex:"kind",width:110},{title:"MIME",dataIndex:"mime",width:160,ellipsis:!0},{title:"大小",key:"size",dataIndex:"size",width:90},{title:"发布时间",key:"createdAt",dataIndex:"createdAt",width:170},{title:"会话",dataIndex:"sessionId",width:160,ellipsis:!0},{title:"操作",key:"actions",width:150}],w=z(()=>u.kinds.map(i=>({label:i,value:i})));async function b(i){await u.removeArtifact(i)?R.success("已删除"):R.error("删除失败")}async function A(){const i=await u.cleanExpired();R.info(i>0?`清理了 ${i} 个过期交付物`:"没有过期交付物")}async function l(i){await u.downloadArtifact(i)||R.error("下载失败")}V(()=>{u.fetchArtifacts()}),D(()=>{u.closePreview()});const g={store:u,columns:e,kindOptions:w,onRemove:b,onClean:A,onDownload:l,computed:z,onBeforeUnmount:D,onMounted:V,get ReloadOutlined(){return q},get message(){return R},MarkdownRenderer:Q,get useArtifactsStore(){return K}};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}},X={class:"page-header"},Y=["onClick"],Z=["src"],$={key:1,class:"preview-markdown"},ee={key:2,class:"preview-text"},te={class:"preview-meta"},ne={key:0};function ae(h,t,u,e,w,b){const A=k("a-select"),l=k("a-button"),g=k("a-popconfirm"),i=k("a-space"),m=k("a-tag"),O=k("a-table"),P=k("a-empty"),M=k("a-card");return d(),y("div",null,[_("div",X,[t[7]||(t[7]=_("div",null,[_("h2",{class:"page-title"},"交付物"),_("p",{class:"page-sub"}," agent 用 publish_artifact 发布的交付物(报告 / patch / 截图 / 日志),在这里预览与管理(cc artifacts 同源)。 ")],-1)),r(i,null,{default:o(()=>[r(A,{value:e.store.kindFilter,"onUpdate:value":t[0]||(t[0]=c=>e.store.kindFilter=c),style:{"min-width":"120px"},placeholder:"全部类型","allow-clear":"",options:e.kindOptions,onChange:t[1]||(t[1]=c=>e.store.fetchArtifacts())},null,8,["value","options"]),r(g,{title:"删除所有过期交付物?",onConfirm:e.onClean},{default:o(()=>[r(l,null,{default:o(()=>[...t[5]||(t[5]=[f("清理过期",-1)])]),_:1})]),_:1}),r(l,{ghost:"",loading:e.store.loading,onClick:t[2]||(t[2]=c=>e.store.fetchArtifacts())},{icon:o(()=>[r(e.ReloadOutlined)]),default:o(()=>[t[6]||(t[6]=f(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),r(O,{"data-source":e.store.artifacts,columns:e.columns,"row-key":"id",size:"small",pagination:{pageSize:10,hideOnSinglePage:!0}},{bodyCell:o(({column:c,record:v})=>[c.key==="title"?(d(),y("a",{key:0,onClick:x=>e.store.openPreview(v)},p(v.title),9,Y)):c.key==="kind"?(d(),S(m,{key:1,color:e.store.kindColor(v.kind)},{default:o(()=>[f(p(v.kind),1)]),_:2},1032,["color"])):c.key==="size"?(d(),y(j,{key:2},[f(p(e.store.formatSize(v.size)),1)],64)):c.key==="createdAt"?(d(),y(j,{key:3},[f(p((v.createdAt||"").replace("T"," ").slice(0,19)),1)],64)):c.key==="actions"?(d(),S(i,{key:4},{default:o(()=>[r(l,{size:"small",onClick:x=>e.store.openPreview(v)},{default:o(()=>[...t[8]||(t[8]=[f("预览",-1)])]),_:1},8,["onClick"]),r(l,{size:"small",onClick:x=>e.onDownload(v)},{default:o(()=>[...t[9]||(t[9]=[f("下载",-1)])]),_:1},8,["onClick"]),r(g,{title:"删除该交付物?",onConfirm:x=>e.onRemove(v.id)},{default:o(()=>[r(l,{size:"small",danger:""},{default:o(()=>[...t[10]||(t[10]=[f("删除",-1)])]),_:1})]),_:1},8,["onConfirm"])]),_:2},1024)):B("v-if",!0)]),_:1},8,["data-source"]),e.store.preview?(d(),S(M,{key:0,size:"small",class:"preview-card",loading:e.store.previewLoading},{title:o(()=>[r(i,null,{default:o(()=>[_("span",null,p(e.store.preview.entry?.title),1),r(m,{color:e.store.kindColor(e.store.preview.entry?.kind)},{default:o(()=>[f(p(e.store.preview.entry?.kind),1)]),_:1},8,["color"]),r(m,{color:"default"},{default:o(()=>[f(p(e.store.preview.entry?.mime),1)]),_:1}),e.store.preview.truncated?(d(),S(m,{key:0,color:"warning"},{default:o(()=>[...t[11]||(t[11]=[f("已截断预览",-1)])]),_:1})):B("v-if",!0)]),_:1})]),extra:o(()=>[r(i,null,{default:o(()=>[r(l,{size:"small",onClick:t[3]||(t[3]=c=>e.onDownload(e.store.preview.entry))},{default:o(()=>[...t[12]||(t[12]=[f("下载",-1)])]),_:1}),r(l,{size:"small",onClick:t[4]||(t[4]=c=>e.store.closePreview())},{default:o(()=>[...t[13]||(t[13]=[f("关闭",-1)])]),_:1})]),_:1})]),default:o(()=>[e.store.previewImageSrc?(d(),y("img",{key:0,src:e.store.previewImageSrc,class:"preview-image",alt:"artifact preview"},null,8,Z)):e.store.previewIsMarkdown?(d(),y("div",$,[r(e.MarkdownRenderer,{content:e.store.preview.content||""},null,8,["content"])])):e.store.preview.previewable?(d(),y("pre",ee,p(e.store.preview.content||"(空文件)"),1)):(d(),S(P,{key:3,description:e.store.preview.reason||"该类型不支持在线预览,可在本机用 cc artifacts open <id> 打开"},null,8,["description"])),_("div",te,[_("span",null,p(e.store.preview.entry?.id),1),e.store.preview.entry?.sessionId?(d(),y("span",ne," · session "+p(e.store.preview.entry.sessionId),1)):B("v-if",!0),_("span",null," · sha256 "+p((e.store.preview.entry?.sha256||"").slice(0,12))+"…",1)])]),_:1},8,["loading"])):B("v-if",!0)])}const de=W(H,[["render",ae],["__scopeId","data-v-c8b48f8c"],["__file","/tmp/cc-web-panel-StwILP/repo/packages/web-panel/src/views/Artifacts.vue"]]);export{de as default};
@@ -1 +0,0 @@
1
- import{I as v,P as u,J as S,U as n,R as a,S as y,K as C,Q as w,V as x,_ as B,b as s}from"./vendor-Bn1JzzAn.js";import{_ as k}from"./index-DV-Rfmfx.js";import"./icons-DG5UD-6K.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),g=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},L={class:"meta"},M={class:"actor"},R={class:"time"},V={class:"body"};function q(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",T,[n("div",L,[n("span",M,a(r.actorLabel),1),n("span",R,a(r.formattedTime),1)]),n("div",V,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[w(a(t.event.source.adapter),1)]),_:1},8,["color"])):x("v-if",!0)])],2)}const P=k(N,[["render",q],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-StwILP/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{P as default};
@@ -1 +0,0 @@
1
- import{I as x,P as s,J as i,U as l,R as n,c as g,K as u,Q as _,V as m,F as C,Z as N,S as T,b as p}from"./vendor-Bn1JzzAn.js";import{_ as w}from"./index-DV-Rfmfx.js";import"./icons-DG5UD-6K.js";const V={__name:"GenericCardRenderer",props:{event:{type:Object,required:!0}},setup(v,{expose:f}){f();const t=v,o=p(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),c=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,"0"),k=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),S=String(e.getMinutes()).padStart(2,"0");return`${c}-${r}-${k} ${b}:${S}`}catch{return""}}),h=p(()=>{const e=t.event.content||{};return e.text||e.title||e.subject||e.name||e.prompt||JSON.stringify(e).slice(0,200)}),y=p(()=>{const e=t.event.content||{};return e.body||e.snippet||e.description||e.from||e.counterparty||null}),d=p(()=>{const e=t.event.content||{},c=t.event.extra||{},r=[];return e.amount!=null&&r.push({k:"金额",v:e.amount,color:"gold"}),c.merchant&&r.push({k:"商户",v:c.merchant,color:"green"}),c.orderNo&&r.push({k:"订单",v:c.orderNo,color:"purple"}),e.from&&e.to&&r.push({k:"路线",v:`${e.from} → ${e.to}`,color:"cyan"}),e.trainNo&&r.push({k:"车次",v:e.trainNo,color:"cyan"}),e.model&&r.push({k:"模型",v:e.model,color:"magenta"}),t.event.place&&r.push({k:"地点",v:t.event.place,color:"geekblue"}),r}),a={props:t,formattedTime:o,primaryText:h,secondaryText:y,metaChips:d,computed:p};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}},B={class:"event-card"},R={class:"card-head"},j={class:"time"},D={key:0,class:"actor"},F={class:"card-body"},G={class:"primary"},I={key:0,class:"secondary"},O={key:0,class:"card-meta"},P={class:"meta-k"};function A(v,f,t,o,h,y){const d=x("a-tag");return s(),i("div",B,[l("div",R,[l("span",j,n(o.formattedTime),1),g(d,{color:"blue",class:"adapter"},{default:u(()=>[_(n(t.event.source.adapter),1)]),_:1}),g(d,{class:"subtype"},{default:u(()=>[_(n(t.event.subtype),1)]),_:1}),t.event.actor?(s(),i("span",D,"@"+n(t.event.actor),1)):m("v-if",!0)]),l("div",F,[l("div",G,n(o.primaryText),1),o.secondaryText?(s(),i("div",I,n(o.secondaryText),1)):m("v-if",!0)]),o.metaChips.length>0?(s(),i("div",O,[(s(!0),i(C,null,N(o.metaChips,a=>(s(),T(d,{key:a.k,color:a.color},{default:u(()=>[l("span",P,n(a.k)+":",1),_(" "+n(a.v),1)]),_:2},1032,["color"]))),128))])):m("v-if",!0)])}const q=w(V,[["render",A],["__scopeId","data-v-c52d08ab"],["__file","/tmp/cc-web-panel-StwILP/repo/packages/web-panel/src/components/pdh/renderers/GenericCardRenderer.vue"]]);export{q as default};
@@ -1 +0,0 @@
1
- import{I as n,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-Bn1JzzAn.js";import{_ as v,b as m}from"./index-DV-Rfmfx.js";import{a8 as y,M}from"./icons-DG5UD-6K.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return M},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},x={class:"mobile-projects-placeholder"},O={class:"title"},w={class:"subtitle"},k={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,t(e.t("mobileProjects.title")),1),o("p",w,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",k,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const C=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-StwILP/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{C as default};