chainlesschain 0.165.6 → 0.165.8

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 (238) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/assets/{AIOps-vfoDb6HZ.js → AIOps-B3gWmXjo.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-Cm5f7p93.js → ActionButton-G9pdT-0e.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-yRuvgWxa.js → Analytics-Ca30J7m2.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-BROsC4h1.js → AppLayout-BtVTm8PU.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-CimHApb1.js → Artifacts-BhViNa6u.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-DI8kr8zI.js → Audit-DhKq-FnY.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DSLzKy-n.js → BackgroundAgents-BL0SVbnE.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DkH_n2r1.js → Backup-BWkblnFi.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CKSrUoRA.js → BaseInput-ClaRNrF8.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-ClwfMXUS.js → Chat-sZE2Z77o.js} +4 -4
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CjMaqfL7.js → ChatBubbleRenderer-BAfKOnRe.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-BYTehcQG.js → Checkbox-Cvhay5WM.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-B8AMcp6J.js → Codegen-BpejL-4N.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-BNSogPo3.js → Col-g2Ki6g_1.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-JxPvGb8O.js → Community-D2xKbNo9.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-DF7bFAgE.js → Compact-DbL1Pds3.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Bvhqnwrq.js → Compliance-DGtZCV4c.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-BDS0CJvM.js → Cowork-4kQpoNsI.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-DqvRfxoQ.js → Cron-BxTYXXAN.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-CDcIvnqS.js → Crosschain-k0J0LT2N.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-D7jaUxU3.js → DID-BaqhoPgN.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-B5A18wEV.js → Dashboard-T4RVPIM1.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-_6IVkGag.js → Dropdown-DszOToWq.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-C9PeiKCG.js → EmailListRenderer-C9KJU7HF.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DXjuEHrX.js → FamilyGuardDashboard-Cmr0JnsA.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-B4IAR9zv.js → Federation-BI-_2xZX.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CxQeSNx1.js → FormItemContext-DsnDEPsl.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-B8GS-Y3N.js → GenericCardRenderer-BLncAKKK.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-BS8SouUX.js → Git-BPQhGXDn.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-Dq9aYb5Q.js → Governance-CyElbUQW.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-BrCEe9AJ.js → Inference-CcSntBQD.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DybOpiY2.js → KnowledgeGraph-p6e7HZ2r.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-DBpzbRfx.js → Logs-CNEtr-wz.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-Cc7CCSCu.js → Marketplace-Dd2notAJ.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-DFaIhOfu.js → McpTools-BBsN2CSW.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-KCqlp9ol.js → Memory-Dg2uTvwx.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-Bys84ySN.js → MobileBridge-r1YMRiJV.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-B-6qU-je.js → MobileProjects-C-89kSm4.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BgY-fvCq.js → Mtc-CrPZcVgf.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-B8pCmqQJ.js → MtcAudit-sxi7hqJb.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-BbOmYutA.js → Multisig-CAgOMfF1.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-BocLQz_M.js → NLProgramming-DafaPts3.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-CSwbxEop.js → Notes-CJM-xUW_.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-CqFNSYG3.js → NotificationSettings-L0ZjfAh_.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C6gMfAk7.js → OrderTableRenderer-BB1CvCK0.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-QrDXVdMJ.js → Organization-DeLtgAD8.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Cxntotjt.js → Overflow-CKC2b10z.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CIdBOwNq.js → P2P-eyf2rzY1.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CT5aP8rD.js → PdhVaultBrowser-5upNIOW8.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DH7OM8XU.js → Permissions-B8p3W6JK.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CnJqbWce.js → PersonalDataHub-BnRMxTq3.js} +5 -5
  54. package/src/assets/web-panel/assets/{Pipeline-5C3HG1kH.js → Pipeline-DjCNI1li.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-B4yIp7xK.js → Privacy-u6gXLbWT.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-BMvt-2M0.js → ProjectInit-BZAw4tkM.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-CvSTEMRG.js → ProjectSettings-B1Tr72q7.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-BKBJxEek.js → Projects-DO7HFuBQ.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-BdwUqFWN.js → Providers-BjCztyhj.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-DtnCKlTm.js → QrScannerModal-ZWyCUbR1.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-sTbgwyNr.js → QuickAsk-DhDjeW4G.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Bzr14gSb.js → Recommend-R_CN2MuU.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C_TF5IaJ.js → RemoteSession-uxFcujeu.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-GCAM4H2K.js → Reputation-DX8D7rks.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-Dir0r6OQ.js → Row-BYahQILD.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-CpGnlecX.js → RssFeed-CUSQ2tm-.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DMMamC6u.js → Search-CnN_S8Cs.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-yqay5yG-.js → Security-DcZlh-O4.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-C5i2wh9G.js → Services-ZhBOjzIX.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-vUqk35yj.js → Skeleton-D5Qnq_lI.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-DzcSkhot.js → Skills-BC9cZ3Be.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CB6qbYNr.js → Sla-DauJ3E8_.js} +1 -1
  73. package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +1 -0
  74. package/src/assets/web-panel/assets/{SyncSettings-D-RrsxTJ.js → SyncSettings-DUvJbSct.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-DFxdOJiq.js → Tasks-BXa-5noQ.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-SKAob_Aq.js → Templates-JxaiUt_3.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-BPfsfHQ-.js → Tenant-BW4ERQN8.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-8iw7FpUf.js → Terminal-DltUbdtv.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-C4Gjj5Su.js → TimelineRenderer-CMoZz0Tc.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-COYhN18e.js → Tokens-D_VEV60K.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-B-JzXcf6.js → Trigger-CCXTCs0R.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BJ5bg0nI.js → Trust-lkGRIPcG.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-BG_ByRMf.js → UkeySign-BfGeQ9HX.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-B3kOnSiU.js → VideoEditing-BEC7pYvc.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-CcoGFnK7.js → Wallet-BZdG24o0.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-DdT8vRC_.js → WebAuthn-yoEddedp.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-CZu3M9N8.js → WorkflowEditor-BXZEprOW.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DxJt3Qba.js → chat-gg0bzZal.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-DdYfwJaB.js → colors-DjRVRuin.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-BG3SUzwj.js → compact-item-su-dieAc.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-By51z2-1.js → createContext-Ci3S8oKF.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-B0apZ3KJ.js → hasIn-D8F10heH.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DE76D-kA.js → index-11wtYQiF.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BkvcEo4p.js → index-1IgxgALJ.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-Bos5_aMV.js → index-1agckWSq.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BfWYsB9t.js → index-5JqhujnR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CAhHirVH.js → index-6Tniqk1s.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BYINoRLK.js → index-8Z-8BIlN.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-B5rLiEo0.js → index-BCI5v0yB.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BZ_0qm4g.js → index-BDJntYmJ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CWEuZWCK.js → index-BGzixOGZ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BLIbGOLX.js → index-BMMOVoLD.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-bP_VlDb4.js → index-BTFpdBtt.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B3rWuPMW.js → index-Ba_HyPnE.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Da_WBdLX.js → index-BbF1IHof.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-RD6O-0C6.js → index-BgT9su_e.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CpjZhgNd.js → index-BzPB6kGZ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Q2SCX-MI.js → index-C6ygzplr.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BIrJfqO4.js → index-CC3ZDjzY.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BBPf3TpM.js → index-CEmXRhAE.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CJGOlduY.js +1 -0
  113. package/src/assets/web-panel/assets/{index-Cp6e-hGw.js → index-CMPqd5Cv.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-kf57LJ93.js → index-COWd8uGx.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CW93tZDv.js → index-CPIYSp4H.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BewKYrX9.js → index-CR0h6seT.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-p1_8SbI1.js → index-CUmDhC4j.js} +1 -1
  118. package/src/assets/web-panel/assets/index-CkBCN5yH.js +1 -0
  119. package/src/assets/web-panel/assets/{index-ZxtP8jG7.js → index-CusgZPtc.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BWF8_mkx.js → index-DBAETXft.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BP94CrBV.js → index-DIJ2qFOC.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CNIxXMmN.js → index-Dbq4NMET.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CzmQElZy.js → index-DkMEF5VT.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ZFbps9po.js → index-DkfQR3hM.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Dz49VOyQ.js → index-DnLucOn9.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-oxRrmFO9.js → index-DugB_aKa.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Bissefox.js → index-DyLUarhZ.js} +3 -3
  128. package/src/assets/web-panel/assets/{index-DaIz0NAW.js → index-T6_6ygJZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-SQqOlR3d.js → index-Tu8eWqh-.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DCn8IcxV.js → index-W7XUgdVL.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-3jWkIu5j.js → index-dHZinfko.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-C1C9i79A.js → index-jyNgp5FI.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-BWJktcg8.js → initDefaultProps-Cv4p8e4w.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BEXBzUFV.js → motion-B8EwmMOw.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-BUKwn2sx.js → move-B8R9F8TK.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-FTI7btqQ.js → mtc-parser-DoFYz5Bp.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-CsLtSPH3.js → omit-CHWYLBjI.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-DWZxsT_S.js → pickAttrs-CXuPDO77.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-Bcfs43CX.js → placementArrow-BaAtUUon.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-a9bcC1p-.js → responsiveObserve-DCc4zcDD.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-BDTzgOXN.js → slide-B_lx89oZ.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-Iq1j_HUg.js → statusUtils-DE8DPmR0.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-DAZEYxeh.js → styleChecker-1ktXOsL_.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-DVkjyDrh.js → useFlexGapSupport-xH89-wjh.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-wXTpNTHt.js → useFs-DscvfW5p.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-CtQM_aZr.js → usePersonalDataHub-RdMKQta7.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-hjEoG85v.js → vnode-Z3wTni2T.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-BHVpyKg_.js → zoom-B0iChCsm.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +3 -3
  151. package/src/commands/agent.js +91 -60
  152. package/src/commands/git.js +39 -0
  153. package/src/commands/plugin.js +17 -2
  154. package/src/commands/session-group.js +131 -0
  155. package/src/commands/session-location.js +48 -0
  156. package/src/commands/session.js +11 -0
  157. package/src/commands/sync-providers.js +4 -1
  158. package/src/commands/update.js +1 -0
  159. package/src/data/changelog.json +27 -1
  160. package/src/gateways/ws/ws-agent-handler.js +20 -12
  161. package/src/harness/jsonl-session-store.js +279 -37
  162. package/src/harness/mcp-client.js +701 -91
  163. package/src/harness/session-index.js +15 -4
  164. package/src/lib/agent-worktree.js +8 -1
  165. package/src/lib/auto-mode-safety-classifier.js +3 -17
  166. package/src/lib/background-agent-keeper-protocol.js +26 -6
  167. package/src/lib/background-agent-supervisor.js +17 -1
  168. package/src/lib/browser-evidence.js +1405 -0
  169. package/src/lib/chrome-connector.js +465 -79
  170. package/src/lib/claude-project-auto-memory.js +481 -0
  171. package/src/lib/claude-project-storage-layout.js +104 -0
  172. package/src/lib/cloud/cloud-client.js +40 -0
  173. package/src/lib/execution-location-local-supervisor.mjs +226 -0
  174. package/src/lib/execution-location-runner-lifecycle.js +991 -0
  175. package/src/lib/execution-location-target-preflight.js +333 -0
  176. package/src/lib/execution-location-target.js +783 -13
  177. package/src/lib/file-lines.js +6 -1
  178. package/src/lib/gateway-client-resilience.js +571 -0
  179. package/src/lib/gitlab-mr-worktree.js +176 -0
  180. package/src/lib/hooks-v2-producers.js +119 -15
  181. package/src/lib/hooks-v2-workspace-context.js +44 -1
  182. package/src/lib/host-resource-budget.js +295 -0
  183. package/src/lib/ide-context.js +15 -2
  184. package/src/lib/llm-config-defaults.js +43 -0
  185. package/src/lib/mcp-lifecycle-authority.js +887 -0
  186. package/src/lib/mcp-oauth.js +101 -20
  187. package/src/lib/mcp-tls.js +103 -3
  188. package/src/lib/paths.js +260 -32
  189. package/src/lib/permission-request.js +48 -0
  190. package/src/lib/plugin-runtime/bin.js +3 -1
  191. package/src/lib/plugin-runtime/hooks.js +3 -1
  192. package/src/lib/plugin-runtime/install.js +117 -1
  193. package/src/lib/plugin-runtime/lsp.js +4 -4
  194. package/src/lib/plugin-runtime/marketplace-archive-source.js +40 -5
  195. package/src/lib/plugin-runtime/marketplace-catalog.js +13 -2
  196. package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
  197. package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
  198. package/src/lib/plugin-runtime/marketplace-source-adapter.js +33 -8
  199. package/src/lib/plugin-runtime/mcp.js +3 -1
  200. package/src/lib/plugin-runtime/monitors.js +3 -1
  201. package/src/lib/plugin-runtime/remote-source.js +151 -6
  202. package/src/lib/plugin-runtime/settings.js +3 -1
  203. package/src/lib/plugin-runtime/trust.js +274 -13
  204. package/src/lib/process-execution-broker/credential-agent.js +210 -41
  205. package/src/lib/process-execution-broker/index.js +15 -1
  206. package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
  207. package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
  208. package/src/lib/project-mcp-trust.js +165 -10
  209. package/src/lib/resume-session.js +9 -6
  210. package/src/lib/session-core-singletons.js +26 -11
  211. package/src/lib/session-host-lease.js +52 -16
  212. package/src/lib/session-lifecycle-scope.js +153 -0
  213. package/src/lib/session-message-fabric.js +168 -21
  214. package/src/lib/session-projection.js +244 -4
  215. package/src/lib/session-store-guard.js +3 -1
  216. package/src/lib/session-workbench-store.js +466 -0
  217. package/src/lib/spellcheck.js +211 -0
  218. package/src/lib/sub-agent-context.js +9 -9
  219. package/src/lib/sync-cli-db.js +485 -129
  220. package/src/lib/sync-credentials.js +31 -20
  221. package/src/lib/web-fetch.js +112 -40
  222. package/src/lib/web-search.js +127 -61
  223. package/src/lib/workspace-trust.js +793 -0
  224. package/src/repl/agent-repl.js +124 -5
  225. package/src/repl/permission-prompt.js +10 -12
  226. package/src/runtime/agent-core.js +311 -18
  227. package/src/runtime/bootstrap.js +37 -13
  228. package/src/runtime/coding-agent-contract-shared.cjs +11 -4
  229. package/src/runtime/headless-runner.js +234 -36
  230. package/src/runtime/headless-stream.js +181 -6
  231. package/src/runtime/mcp-config.js +298 -8
  232. package/src/runtime/policies/agent-policy.js +8 -0
  233. package/src/runtime/status-diagnostics-lite.js +9 -1
  234. package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +0 -1
  235. package/src/assets/web-panel/assets/SpeechSettings-BHUI7cox.js +0 -1
  236. package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +0 -1
  237. package/src/assets/web-panel/assets/index-BETiL0a3.js +0 -1
  238. package/src/assets/web-panel/assets/index-BhAVHuW8.js +0 -1
@@ -21,9 +21,9 @@
21
21
 
22
22
  import fs from "node:fs";
23
23
  import path from "node:path";
24
- import os from "node:os";
25
24
  import crypto from "node:crypto";
26
25
  import { withFileLock } from "./with-file-lock.js";
26
+ import { ensureDir, getHomeDir } from "./paths.js";
27
27
 
28
28
  const SENSITIVE_FIELDS = ["sync.webdav.password", "sync.oss.secretAccessKey"];
29
29
  const ALLOWED_PROVIDER_IDS = ["webdav", "oss"];
@@ -37,10 +37,7 @@ let _ccDirOverride = null;
37
37
 
38
38
  function _ccDir() {
39
39
  if (_ccDirOverride) return _ccDirOverride;
40
- return (
41
- process.env.CHAINLESSCHAIN_HOME ||
42
- path.join(os.homedir(), ".chainlesschain")
43
- );
40
+ return getHomeDir();
44
41
  }
45
42
 
46
43
  function _keyPath() {
@@ -53,7 +50,13 @@ function _vaultPath() {
53
50
 
54
51
  function _ensureDir() {
55
52
  const dir = _ccDir();
56
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
53
+ // Explicit test-only override keeps the existing isolated fake-filesystem
54
+ // seam lightweight; production roots always go through owner-only setup.
55
+ if (_ccDirOverride) {
56
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
57
+ return;
58
+ }
59
+ ensureDir(dir);
57
60
  }
58
61
 
59
62
  /**
@@ -217,24 +220,32 @@ function setCredentials(providerId, creds) {
217
220
  // Credential metadata is security-critical: never decrypt-modify-encrypt
218
221
  // without exclusion, because a lost update can silently restore/revoke the
219
222
  // wrong provider credentials.
220
- return withFileLock(_vaultPath(), () => {
221
- const all = loadAll();
222
- if (!all.sync || typeof all.sync !== "object") all.sync = {};
223
- all.sync[providerId] = { ...creds };
224
- return saveAll(all);
225
- }, { failIfUnavailable: true });
223
+ return withFileLock(
224
+ _vaultPath(),
225
+ () => {
226
+ const all = loadAll();
227
+ if (!all.sync || typeof all.sync !== "object") all.sync = {};
228
+ all.sync[providerId] = { ...creds };
229
+ return saveAll(all);
230
+ },
231
+ { failIfUnavailable: true },
232
+ );
226
233
  }
227
234
 
228
235
  function clearCredentials(providerId) {
229
236
  assertProviderId(providerId);
230
- return withFileLock(_vaultPath(), () => {
231
- const all = loadAll();
232
- if (all?.sync?.[providerId]) {
233
- delete all.sync[providerId];
234
- return saveAll(all);
235
- }
236
- return true;
237
- }, { failIfUnavailable: true });
237
+ return withFileLock(
238
+ _vaultPath(),
239
+ () => {
240
+ const all = loadAll();
241
+ if (all?.sync?.[providerId]) {
242
+ delete all.sync[providerId];
243
+ return saveAll(all);
244
+ }
245
+ return true;
246
+ },
247
+ { failIfUnavailable: true },
248
+ );
238
249
  }
239
250
 
240
251
  /** Test seam: override the resolved chainlesschain dir without env leak. */
@@ -9,6 +9,7 @@ import http from "node:http";
9
9
  import https from "node:https";
10
10
  import { lookup as dnsLookup } from "node:dns";
11
11
  import { URL } from "node:url";
12
+ import { createHash } from "node:crypto";
12
13
 
13
14
  const DEFAULT_MAX_BYTES = 2_000_000;
14
15
  const DEFAULT_TIMEOUT_MS = 15_000;
@@ -140,6 +141,35 @@ function stripTags(html) {
140
141
  return String(html).replace(/<[^>]+>/g, "");
141
142
  }
142
143
 
144
+ function webFetchCacheKey(parsed, { format, maxBytes, maxRedirects, headers }) {
145
+ // A caller-provided header can carry credentials or change representation.
146
+ // Keep those requests out of the shared host cache entirely.
147
+ if (
148
+ (headers && Object.keys(headers).length > 0) ||
149
+ parsed.username ||
150
+ parsed.password
151
+ ) {
152
+ return null;
153
+ }
154
+ const payload = JSON.stringify({
155
+ url: parsed.toString(),
156
+ format,
157
+ maxBytes,
158
+ maxRedirects,
159
+ });
160
+ // Do not retain a raw URL/query as a long-lived Map key in the host cache.
161
+ return `web-fetch:${createHash("sha256").update(payload).digest("hex")}`;
162
+ }
163
+
164
+ function hostBudgetUnavailable(tool, error) {
165
+ const reason = String(error?.budgetReason || "unavailable").slice(0, 128);
166
+ return {
167
+ error: `${tool} unavailable: host resource budget (${reason})`,
168
+ code: "ERR_HOST_RESOURCE_BUDGET",
169
+ reason,
170
+ };
171
+ }
172
+
143
173
  /**
144
174
  * A `lookup` for http(s).request that resolves the hostname and REJECTS the
145
175
  * connection if any resolved IP is private/loopback/link-local. checkAllowed
@@ -243,6 +273,7 @@ export async function webFetch(url, options = {}) {
243
273
  config = {},
244
274
  headers = {},
245
275
  maxRedirects = 3,
276
+ hostResourceBudget = null,
246
277
  } = options;
247
278
 
248
279
  const check = checkAllowed(url, config);
@@ -250,53 +281,94 @@ export async function webFetch(url, options = {}) {
250
281
  return { error: `web_fetch blocked: ${check.reason}` };
251
282
  }
252
283
 
253
- let parsed = check.url;
254
- let redirects = 0;
255
- let response;
256
- while (true) {
257
- response = await _doRequest(parsed, {
258
- maxBytes,
259
- timeout,
260
- headers,
261
- allowPrivateHosts: config.allowPrivateHosts,
262
- });
263
- if (!response.redirect) break;
264
- if (++redirects > maxRedirects) {
265
- return { error: "too many redirects" };
266
- }
267
- const next = new URL(response.redirect, parsed);
268
- const nextCheck = checkAllowed(next.toString(), config);
269
- if (!nextCheck.allowed) {
270
- return { error: `redirect blocked: ${nextCheck.reason}` };
284
+ const cacheKey = webFetchCacheKey(check.url, {
285
+ format,
286
+ maxBytes,
287
+ maxRedirects,
288
+ headers,
289
+ });
290
+ if (cacheKey && hostResourceBudget?.getWebFetch) {
291
+ try {
292
+ const cached = hostResourceBudget.getWebFetch(cacheKey);
293
+ if (cached) return { ...cached, cached: true };
294
+ } catch (error) {
295
+ return hostBudgetUnavailable("web_fetch", error);
271
296
  }
272
- parsed = nextCheck.url;
273
297
  }
274
298
 
275
- const { statusCode, headers: respHeaders, body } = response;
276
- const contentType = String(respHeaders["content-type"] || "");
277
-
278
- let output = body;
279
- let outputFormat = format;
280
- if (format === "markdown") {
281
- output = /html/i.test(contentType) ? htmlToMarkdown(body) : body;
282
- } else if (format === "text") {
283
- output = /html/i.test(contentType) ? stripTags(body) : body;
284
- } else if (format === "json") {
299
+ let toolLease = null;
300
+ if (hostResourceBudget) {
285
301
  try {
286
- output = JSON.parse(body);
287
- } catch {
288
- return { error: "response is not valid JSON", statusCode, body };
302
+ if (typeof hostResourceBudget.admitTool !== "function") {
303
+ throw new TypeError(
304
+ "host resource budget does not provide admitTool()",
305
+ );
306
+ }
307
+ toolLease = hostResourceBudget.admitTool({ kind: "web-fetch" });
308
+ } catch (error) {
309
+ return hostBudgetUnavailable("web_fetch", error);
289
310
  }
290
311
  }
291
312
 
292
- return {
293
- url: parsed.toString(),
294
- statusCode,
295
- contentType,
296
- format: outputFormat,
297
- bytes: Buffer.byteLength(body, "utf8"),
298
- content: output,
299
- };
313
+ try {
314
+ let parsed = check.url;
315
+ let redirects = 0;
316
+ let response;
317
+ while (true) {
318
+ response = await _doRequest(parsed, {
319
+ maxBytes,
320
+ timeout,
321
+ headers,
322
+ allowPrivateHosts: config.allowPrivateHosts,
323
+ });
324
+ if (!response.redirect) break;
325
+ if (++redirects > maxRedirects) {
326
+ return { error: "too many redirects" };
327
+ }
328
+ const next = new URL(response.redirect, parsed);
329
+ const nextCheck = checkAllowed(next.toString(), config);
330
+ if (!nextCheck.allowed) {
331
+ return { error: `redirect blocked: ${nextCheck.reason}` };
332
+ }
333
+ parsed = nextCheck.url;
334
+ }
335
+
336
+ const { statusCode, headers: respHeaders, body } = response;
337
+ const contentType = String(respHeaders["content-type"] || "");
338
+
339
+ let output = body;
340
+ let outputFormat = format;
341
+ if (format === "markdown") {
342
+ output = /html/i.test(contentType) ? htmlToMarkdown(body) : body;
343
+ } else if (format === "text") {
344
+ output = /html/i.test(contentType) ? stripTags(body) : body;
345
+ } else if (format === "json") {
346
+ try {
347
+ output = JSON.parse(body);
348
+ } catch {
349
+ return { error: "response is not valid JSON", statusCode, body };
350
+ }
351
+ }
352
+
353
+ const result = {
354
+ url: parsed.toString(),
355
+ statusCode,
356
+ contentType,
357
+ format: outputFormat,
358
+ bytes: Buffer.byteLength(body, "utf8"),
359
+ content: output,
360
+ };
361
+ if (cacheKey && hostResourceBudget?.putWebFetch) {
362
+ try {
363
+ hostResourceBudget.putWebFetch(cacheKey, result);
364
+ } catch {
365
+ // Cache failures never weaken the completed, bounded I/O result.
366
+ }
367
+ }
368
+ return result;
369
+ } finally {
370
+ toolLease?.release();
371
+ }
300
372
  }
301
373
 
302
374
  // `lookup` is injectable so tests can resolve a domain to a private IP without
@@ -18,6 +18,7 @@ import { URL } from "url";
18
18
  const DEFAULT_MAX_BYTES = 2_000_000;
19
19
  const DEFAULT_TIMEOUT_MS = 15_000;
20
20
  const DEFAULT_MAX_RESULTS = 8;
21
+ export const MAX_WEB_SEARCH_RESULTS = 20;
21
22
 
22
23
  const KEYED_PROVIDERS = ["tavily", "brave", "bocha", "qianfan"];
23
24
  const KEYLESS_PROVIDERS = ["duckduckgo", "searxng", "baidu"];
@@ -38,7 +39,11 @@ export function resolveApiKey(provider, options = {}, config = {}) {
38
39
  switch (provider) {
39
40
  case "tavily":
40
41
  return (
41
- options.apiKey || config.tavilyApiKey || config.apiKey || env.TAVILY_API_KEY || ""
42
+ options.apiKey ||
43
+ config.tavilyApiKey ||
44
+ config.apiKey ||
45
+ env.TAVILY_API_KEY ||
46
+ ""
42
47
  );
43
48
  case "brave":
44
49
  return (
@@ -51,7 +56,11 @@ export function resolveApiKey(provider, options = {}, config = {}) {
51
56
  );
52
57
  case "bocha":
53
58
  return (
54
- options.apiKey || config.bochaApiKey || config.apiKey || env.BOCHA_API_KEY || ""
59
+ options.apiKey ||
60
+ config.bochaApiKey ||
61
+ config.apiKey ||
62
+ env.BOCHA_API_KEY ||
63
+ ""
55
64
  );
56
65
  case "qianfan":
57
66
  return (
@@ -82,7 +91,10 @@ export function resolveProvider(options = {}, config = {}) {
82
91
  return "duckduckgo";
83
92
  }
84
93
 
85
- function _request(urlStr, { method = "GET", headers = {}, body = null, timeout, maxBytes }) {
94
+ function _request(
95
+ urlStr,
96
+ { method = "GET", headers = {}, body = null, timeout, maxBytes },
97
+ ) {
86
98
  const parsed = new URL(urlStr);
87
99
  const lib = parsed.protocol === "https:" ? _deps.https : _deps.http;
88
100
  return new Promise((resolve, reject) => {
@@ -147,6 +159,22 @@ function _clean(s) {
147
159
  return _decodeEntities(_stripTags(s)).replace(/\s+/g, " ").trim();
148
160
  }
149
161
 
162
+ function normalizeMaxResults(value) {
163
+ const parsed = Number(value);
164
+ const requested =
165
+ Number.isSafeInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_RESULTS;
166
+ return Math.min(requested, MAX_WEB_SEARCH_RESULTS);
167
+ }
168
+
169
+ function hostBudgetUnavailable(error) {
170
+ const reason = String(error?.budgetReason || "unavailable").slice(0, 128);
171
+ return {
172
+ error: `web_search unavailable: host resource budget (${reason})`,
173
+ code: "ERR_HOST_RESOURCE_BUDGET",
174
+ reason,
175
+ };
176
+ }
177
+
150
178
  // ---- Provider adapters: each returns { results: [{title,url,snippet}], answer } ----
151
179
 
152
180
  async function _searchTavily(query, { apiKey, maxResults, timeout, maxBytes }) {
@@ -167,7 +195,9 @@ async function _searchTavily(query, { apiKey, maxResults, timeout, maxBytes }) {
167
195
  maxBytes,
168
196
  });
169
197
  if (res.statusCode >= 400) {
170
- return { error: `tavily HTTP ${res.statusCode}: ${res.body.slice(0, 200)}` };
198
+ return {
199
+ error: `tavily HTTP ${res.statusCode}: ${res.body.slice(0, 200)}`,
200
+ };
171
201
  }
172
202
  let json;
173
203
  try {
@@ -326,10 +356,7 @@ async function _searchQianfan(
326
356
  url: r.url || "",
327
357
  snippet: _clean(r.content || r.web_anchor || ""),
328
358
  }));
329
- const answer =
330
- json.answer ||
331
- json.choices?.[0]?.message?.content ||
332
- "";
359
+ const answer = json.answer || json.choices?.[0]?.message?.content || "";
333
360
  return { results, answer: typeof answer === "string" ? answer : "" };
334
361
  }
335
362
 
@@ -362,7 +389,8 @@ async function _searchBaidu(query, { maxResults, timeout, maxBytes }) {
362
389
  // Markup-agnostic: anchor each result on its <h3 class="t|c-title"> heading,
363
390
  // pull the URL from the anchor inside it (a baidu.com/link?url= redirect that
364
391
  // web_fetch resolves), and take the text up to the next heading as snippet.
365
- const h3re = /<h3[^>]*class="[^"]*\b(?:t|c-title)\b[^"]*"[^>]*>([\s\S]*?)<\/h3>/gi;
392
+ const h3re =
393
+ /<h3[^>]*class="[^"]*\b(?:t|c-title)\b[^"]*"[^>]*>([\s\S]*?)<\/h3>/gi;
366
394
  const marks = [];
367
395
  let m;
368
396
  while ((m = h3re.exec(html)) !== null) {
@@ -381,7 +409,10 @@ async function _searchBaidu(query, { maxResults, timeout, maxBytes }) {
381
409
  return { results, answer: "" };
382
410
  }
383
411
 
384
- async function _searchSearxng(query, { instanceUrl, maxResults, timeout, maxBytes }) {
412
+ async function _searchSearxng(
413
+ query,
414
+ { instanceUrl, maxResults, timeout, maxBytes },
415
+ ) {
385
416
  if (!instanceUrl) return { error: "searxng: missing instanceUrl" };
386
417
  const base = instanceUrl.replace(/\/+$/, "");
387
418
  const url = `${base}/search?q=${encodeURIComponent(query)}&format=json`;
@@ -398,7 +429,9 @@ async function _searchSearxng(query, { instanceUrl, maxResults, timeout, maxByte
398
429
  try {
399
430
  json = JSON.parse(res.body);
400
431
  } catch {
401
- return { error: "searxng: invalid JSON response (is json format enabled?)" };
432
+ return {
433
+ error: "searxng: invalid JSON response (is json format enabled?)",
434
+ };
402
435
  }
403
436
  const results = (json.results || []).slice(0, maxResults).map((r) => ({
404
437
  title: _clean(r.title || ""),
@@ -419,10 +452,7 @@ export async function webSearch(query, options = {}) {
419
452
 
420
453
  const config = options.config || {};
421
454
  const provider = resolveProvider(options, config);
422
- const maxResults =
423
- Number(options.maxResults) ||
424
- Number(config.maxResults) ||
425
- DEFAULT_MAX_RESULTS;
455
+ let maxResults = normalizeMaxResults(options.maxResults ?? config.maxResults);
426
456
  const timeout = Number(options.timeout) || DEFAULT_TIMEOUT_MS;
427
457
  const maxBytes = Number(options.maxBytes) || DEFAULT_MAX_BYTES;
428
458
 
@@ -432,56 +462,92 @@ export async function webSearch(query, options = {}) {
432
462
  };
433
463
  }
434
464
 
435
- const apiKey = resolveApiKey(provider, options, config);
436
- const common = { apiKey, maxResults, timeout, maxBytes };
465
+ const hostResourceBudget = options.hostResourceBudget || null;
466
+ if (hostResourceBudget?.capWebSearchResults) {
467
+ try {
468
+ maxResults = normalizeMaxResults(
469
+ hostResourceBudget.capWebSearchResults(maxResults),
470
+ );
471
+ } catch (error) {
472
+ return hostBudgetUnavailable(error);
473
+ }
474
+ }
437
475
 
438
- let out;
439
- try {
440
- switch (provider) {
441
- case "tavily":
442
- out = await _searchTavily(q, common);
443
- break;
444
- case "brave":
445
- out = await _searchBrave(q, common);
446
- break;
447
- case "bocha":
448
- out = await _searchBocha(q, common);
449
- break;
450
- case "qianfan":
451
- out = await _searchQianfan(q, {
452
- ...common,
453
- endpoint: options.qianfanUrl || config.qianfanUrl,
454
- });
455
- break;
456
- case "searxng":
457
- out = await _searchSearxng(q, {
458
- instanceUrl: options.instanceUrl || config.instanceUrl,
459
- maxResults,
460
- timeout,
461
- maxBytes,
462
- });
463
- break;
464
- case "baidu":
465
- out = await _searchBaidu(q, { maxResults, timeout, maxBytes });
466
- break;
467
- case "duckduckgo":
468
- default:
469
- out = await _searchDuckDuckGo(q, { maxResults, timeout, maxBytes });
470
- break;
476
+ let toolLease = null;
477
+ if (hostResourceBudget) {
478
+ try {
479
+ if (typeof hostResourceBudget.admitTool !== "function") {
480
+ throw new TypeError(
481
+ "host resource budget does not provide admitTool()",
482
+ );
483
+ }
484
+ toolLease = hostResourceBudget.admitTool({ kind: "web-search" });
485
+ } catch (error) {
486
+ return hostBudgetUnavailable(error);
471
487
  }
472
- } catch (err) {
473
- return { error: `web_search (${provider}) failed: ${err.message}`, provider };
474
488
  }
475
489
 
476
- if (out && out.error) return { ...out, provider };
477
- const results = (out && out.results) || [];
478
- return {
479
- query: q,
480
- provider,
481
- count: results.length,
482
- results,
483
- answer: (out && out.answer) || "",
484
- };
490
+ try {
491
+ const apiKey = resolveApiKey(provider, options, config);
492
+ const common = { apiKey, maxResults, timeout, maxBytes };
493
+
494
+ let out;
495
+ try {
496
+ switch (provider) {
497
+ case "tavily":
498
+ out = await _searchTavily(q, common);
499
+ break;
500
+ case "brave":
501
+ out = await _searchBrave(q, common);
502
+ break;
503
+ case "bocha":
504
+ out = await _searchBocha(q, common);
505
+ break;
506
+ case "qianfan":
507
+ out = await _searchQianfan(q, {
508
+ ...common,
509
+ endpoint: options.qianfanUrl || config.qianfanUrl,
510
+ });
511
+ break;
512
+ case "searxng":
513
+ out = await _searchSearxng(q, {
514
+ instanceUrl: options.instanceUrl || config.instanceUrl,
515
+ maxResults,
516
+ timeout,
517
+ maxBytes,
518
+ });
519
+ break;
520
+ case "baidu":
521
+ out = await _searchBaidu(q, { maxResults, timeout, maxBytes });
522
+ break;
523
+ case "duckduckgo":
524
+ default:
525
+ out = await _searchDuckDuckGo(q, {
526
+ maxResults,
527
+ timeout,
528
+ maxBytes,
529
+ });
530
+ break;
531
+ }
532
+ } catch (err) {
533
+ return {
534
+ error: `web_search (${provider}) failed: ${err.message}`,
535
+ provider,
536
+ };
537
+ }
538
+
539
+ if (out && out.error) return { ...out, provider };
540
+ const results = (out && out.results) || [];
541
+ return {
542
+ query: q,
543
+ provider,
544
+ count: results.length,
545
+ results,
546
+ answer: (out && out.answer) || "",
547
+ };
548
+ } finally {
549
+ toolLease?.release();
550
+ }
485
551
  }
486
552
 
487
553
  export const _deps = { http, https };