chainlesschain 0.162.78 → 0.162.79

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 (196) hide show
  1. package/README.md +37 -1
  2. package/bin/chainlesschain.js +20 -1
  3. package/package.json +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BhKMd38k.js → AIOps-D89fD_7T.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-BzhKY5C_.js → ActionButton-d75flwX8.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-CATIz2Jc.js → Analytics-gvvBEb4T.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-eCx64YWg.js → AppLayout-DzHOVS64.js} +5 -5
  8. package/src/assets/web-panel/assets/{Audit-CGOHfCHj.js → Audit-15K7MhRC.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-Dyr6R0Ra.js → Backup-BgVHsglI.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CVhBu7NZ.js → BaseInput-BRnvd4sF.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-DOCCKp2k.js → Chat-B2vtXu7s.js} +5 -5
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DcXCCnjN.js → ChatBubbleRenderer-d1EFM3dh.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-3yjnENud.js → Checkbox-B5uV5Jhr.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-D06sn8kB.js → Codegen-cVDMBVGV.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-Bjn5vFES.js → Col-DtL6q7Hw.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-BYHpQHmf.js → Community-DSyPZkqQ.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-MKRmnUDQ.js → Compact-CzfV_q4O.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CVtPe8dh.js → Compliance-B_xhhLE1.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-BRu5M3dv.js → Cowork-Y49Qf0JX.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-D_7eU5Ut.js → Cron-B7JG-oLj.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BFyVp_e9.js → Crosschain-CukEkQtf.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-DRoG7638.js → DID-Bd4UVKdn.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-NfM_v-Oe.js → Dashboard-DRCQl7H1.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-CGN1Ksu0.js → Dropdown-De47CuRY.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-DhsY_z_a.js → EmailListRenderer-C-wAkceB.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-vW_VsKUG.js → FamilyGuardDashboard-DhLF_E0k.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-D2ob_c7h.js → Federation-DAipUS1m.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-Cpem15Pr.js → FormItemContext-BCFyAd2j.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-P6XfmXwT.js → GenericCardRenderer-wMdxrEV9.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-CfSeec1R.js → Git-CcwP7HUN.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-4ipIpqNl.js → Governance-VF760JcB.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CiQY_P9Y.js → Inference-DnR-GIn2.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-B3Qem78R.js → KnowledgeGraph-j-ewVKWO.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-De2zWVy6.js → Logs-DgB7wSor.js} +2 -2
  35. package/src/assets/web-panel/assets/{Marketplace-CTNu4c1A.js → Marketplace-fiKjzVWE.js} +1 -1
  36. package/src/assets/web-panel/assets/{McpTools-Xx25EA2f.js → McpTools-BjXSMQrd.js} +5 -5
  37. package/src/assets/web-panel/assets/{Memory-YzzCCrch.js → Memory-C0L5lnSS.js} +2 -2
  38. package/src/assets/web-panel/assets/{MobileBridge-CJZY98f0.js → MobileBridge-C0Rgg1Su.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileProjects-Dw7yl4KN.js → MobileProjects-BPA50hQb.js} +1 -1
  40. package/src/assets/web-panel/assets/{Mtc-D7TzGJhH.js → Mtc-BUsHuAjB.js} +4 -4
  41. package/src/assets/web-panel/assets/{MtcAudit-THyGhf0h.js → MtcAudit-dlH8Q_7U.js} +6 -6
  42. package/src/assets/web-panel/assets/{Multisig-RVxuGPUR.js → Multisig-L3_9beuW.js} +3 -3
  43. package/src/assets/web-panel/assets/{NLProgramming-DK7TCzKF.js → NLProgramming-BG4sXy27.js} +1 -1
  44. package/src/assets/web-panel/assets/Notes-felgIvGS.js +7 -0
  45. package/src/assets/web-panel/assets/{NotificationSettings-BMivJy85.js → NotificationSettings-DHDT96AK.js} +1 -1
  46. package/src/assets/web-panel/assets/OrderTableRenderer-BYrkEfvR.js +1 -0
  47. package/src/assets/web-panel/assets/{Organization-zVRtW1n_.js → Organization-DdtOLkHG.js} +4 -4
  48. package/src/assets/web-panel/assets/{Overflow-C0YLldFH.js → Overflow-DLw5Pni7.js} +1 -1
  49. package/src/assets/web-panel/assets/{P2P-Xxgzghqp.js → P2P-B-mZ5EXz.js} +2 -2
  50. package/src/assets/web-panel/assets/{PdhVaultBrowser-DH_LO13b.js → PdhVaultBrowser-DeOmNCwK.js} +5 -5
  51. package/src/assets/web-panel/assets/{Permissions-CvAd1VBw.js → Permissions-BeQMX71K.js} +4 -4
  52. package/src/assets/web-panel/assets/{PersonalDataHub-CWQGgCAK.js → PersonalDataHub-D5PoqtQI.js} +3 -3
  53. package/src/assets/web-panel/assets/{Pipeline-BNAoh-Lb.js → Pipeline-B0f5sqKF.js} +1 -1
  54. package/src/assets/web-panel/assets/{Privacy-CNO5pFq-.js → Privacy-Dj_gcxio.js} +1 -1
  55. package/src/assets/web-panel/assets/{ProjectInit-WaVVDsm3.js → ProjectInit-DmfPgied.js} +2 -2
  56. package/src/assets/web-panel/assets/{ProjectSettings-D1WfkuJ3.js → ProjectSettings-BmBfocrv.js} +2 -2
  57. package/src/assets/web-panel/assets/Projects-BUif48cc.js +1 -0
  58. package/src/assets/web-panel/assets/{Providers-IOOJ4_wy.js → Providers-B0ztEAOV.js} +1 -1
  59. package/src/assets/web-panel/assets/{QuickAsk-ChHZqVZy.js → QuickAsk-BtMG4jH5.js} +1 -1
  60. package/src/assets/web-panel/assets/{Recommend-CSiW6Qv9.js → Recommend-DQKN1En8.js} +1 -1
  61. package/src/assets/web-panel/assets/{Reputation-BQe0rkfF.js → Reputation-D34CvUxg.js} +1 -1
  62. package/src/assets/web-panel/assets/{Row-Dem0Wxxb.js → Row-nnuDNx31.js} +1 -1
  63. package/src/assets/web-panel/assets/{RssFeed-pBY5G41C.js → RssFeed-DHx9x8_B.js} +2 -2
  64. package/src/assets/web-panel/assets/{Search-CtRepO6B.js → Search-CH-JYtn_.js} +1 -1
  65. package/src/assets/web-panel/assets/{Security-nrSlKpWq.js → Security-nNKBmzm4.js} +4 -4
  66. package/src/assets/web-panel/assets/{Services-DeaDBASi.js → Services-xYk_lDxy.js} +2 -2
  67. package/src/assets/web-panel/assets/{Skeleton-Cz9R-Wjb.js → Skeleton-DTYyRduA.js} +1 -1
  68. package/src/assets/web-panel/assets/{Skills-B3U-XLH3.js → Skills-DS19-9sF.js} +1 -1
  69. package/src/assets/web-panel/assets/{Sla-Bu46dIA_.js → Sla-Cr_ir42Y.js} +1 -1
  70. package/src/assets/web-panel/assets/{SpeechSettings-C9Z0V0pk.js → SpeechSettings-Ch5Iq7Wy.js} +1 -1
  71. package/src/assets/web-panel/assets/{SyncSettings-Ctj9KHHr.js → SyncSettings-CTblfa_E.js} +2 -2
  72. package/src/assets/web-panel/assets/{Tasks-D4upQgR_.js → Tasks-z7lz3hjG.js} +1 -1
  73. package/src/assets/web-panel/assets/{Templates-JHsPGU_c.js → Templates-DGoMFd4r.js} +1 -1
  74. package/src/assets/web-panel/assets/{Tenant-uoaQL3fB.js → Tenant-DQUPvHxx.js} +1 -1
  75. package/src/assets/web-panel/assets/{Terminal-CWRWr8bq.js → Terminal-Wt2wrbE6.js} +2 -2
  76. package/src/assets/web-panel/assets/{TimelineRenderer-BTicmSAV.js → TimelineRenderer-DGTc2UqL.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tokens-Bp3BUe2K.js → Tokens-DPVnuARF.js} +1 -1
  78. package/src/assets/web-panel/assets/{Trigger-CgoISw5d.js → Trigger-DV5MPXC1.js} +1 -1
  79. package/src/assets/web-panel/assets/{Trust-CC29awNT.js → Trust-BBkMKqwS.js} +1 -1
  80. package/src/assets/web-panel/assets/{UkeySign-CB1SB6Nc.js → UkeySign-B_2E0qev.js} +1 -1
  81. package/src/assets/web-panel/assets/{VideoEditing-D7vptDUg.js → VideoEditing-CA-qKeVb.js} +1 -1
  82. package/src/assets/web-panel/assets/{Wallet-BWfjzF7p.js → Wallet-Ds4WURh-.js} +4 -4
  83. package/src/assets/web-panel/assets/{WebAuthn-Dzz5OnPc.js → WebAuthn-BApiHjzz.js} +5 -5
  84. package/src/assets/web-panel/assets/{WorkflowEditor-CiDeVmsG.js → WorkflowEditor-DFzmAnzV.js} +1 -1
  85. package/src/assets/web-panel/assets/{chat-DQbciNb5.js → chat-DZ6sHPit.js} +1 -1
  86. package/src/assets/web-panel/assets/{colors-DcLbPJzb.js → colors-DgbwhHtE.js} +1 -1
  87. package/src/assets/web-panel/assets/{compact-item-CvYrR3rc.js → compact-item-C4QVYSzd.js} +1 -1
  88. package/src/assets/web-panel/assets/{createContext-BR4P7Rgm.js → createContext-yXIs4TwU.js} +1 -1
  89. package/src/assets/web-panel/assets/devWarning-C-HfIeF7.js +1 -0
  90. package/src/assets/web-panel/assets/{hasIn-IQ88RNRJ.js → hasIn-CPtuUtBl.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-B5W1vQHV.js → index-4g6pGxnX.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DHIp5msb.js → index-B91hax9S.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-BUTN1VlO.js → index-B9DUiQ24.js} +3 -3
  94. package/src/assets/web-panel/assets/index-BBgWatYO.js +1 -0
  95. package/src/assets/web-panel/assets/{index-DgaCUxpi.js → index-BCb7MYMS.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BmPuR0aA.js → index-BIAxMDe9.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-Dpmnk2qv.js → index-BJiGrT6V.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-D8OJdOc_.js → index-BOKVSmKh.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Mn8_ryOe.js → index-BWJGry74.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BiMlLIZ-.js → index-BaVYCMJa.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CPOupQSX.js → index-Bd0JznCS.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Bo7HAK6G.js → index-BpBCKK6W.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Db5LFFCN.js → index-BsXF9cn5.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BQXs-5db.js → index-BxclR5gc.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BVb6RI7f.js → index-C0LyE6R6.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CiOZ_Whh.js → index-CBAgy5pf.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DdQBxvpt.js → index-CJ550XXg.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Cm74AosZ.js → index-CTlz3MP6.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bw0Dm_P6.js → index-CaC4gaQZ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BxY0ozve.js → index-CnP2ftM5.js} +1 -1
  111. package/src/assets/web-panel/assets/index-CvCTol_u.js +1 -0
  112. package/src/assets/web-panel/assets/{index-eKd1n8pw.js → index-D2KRfjEI.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-b6FjzfoJ.js → index-DA0ePxNn.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CE2mqX8w.js → index-DC5iP1VB.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Bl1TSbTE.js → index-DCGmeXfl.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BH2RT15D.js → index-DHnWI0jj.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-UbB2IcFR.js → index-DN4qpkKQ.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CgP5aQmA.js → index-DTLaRwKx.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BHxJnExB.js → index-DdFjcgqH.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-JqOP7puJ.js → index-DopuoTzG.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Dox9vEhP.js → index-DpDAGvyU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DGwa8mnJ.js → index-EGVlUtH-.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-bRT7u-51.js → index-IFh9qCi0.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Bu8931Yi.js → index-UEeNpaDD.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CCO8yc1h.js → index-ZCyyy3Zt.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CzERBV9P.js → index-aKZjRwjv.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CeCWyiFl.js → index-jBlY6-bF.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BhkZZXtI.js → index-kbcTc6Pf.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BvQpTO67.js → index-x9bXmSNB.js} +1 -1
  130. package/src/assets/web-panel/assets/{initDefaultProps-C0arzCLE.js → initDefaultProps-BDsxioXk.js} +1 -1
  131. package/src/assets/web-panel/assets/{motion-C1K6JxwD.js → motion-erZ2fiIQ.js} +1 -1
  132. package/src/assets/web-panel/assets/{move-DREsRLHj.js → move-BFiiw4WK.js} +1 -1
  133. package/src/assets/web-panel/assets/{omit-BtPS3EDq.js → omit-BRMVd4pM.js} +1 -1
  134. package/src/assets/web-panel/assets/{pickAttrs-BPz6tHoT.js → pickAttrs-CGjoFXsq.js} +1 -1
  135. package/src/assets/web-panel/assets/{placementArrow-B0CR_CSI.js → placementArrow-DU_Bnf7w.js} +1 -1
  136. package/src/assets/web-panel/assets/{responsiveObserve-Ch2ojiNn.js → responsiveObserve-DPdkYupg.js} +1 -1
  137. package/src/assets/web-panel/assets/{slide-9qU9vOhj.js → slide-JfHiG96y.js} +1 -1
  138. package/src/assets/web-panel/assets/{statusUtils-Cr4fICjV.js → statusUtils-Dy-1guyd.js} +1 -1
  139. package/src/assets/web-panel/assets/{styleChecker-Cor2-FwV.js → styleChecker-Chaljnux.js} +1 -1
  140. package/src/assets/web-panel/assets/{useFlexGapSupport-BINo_rNH.js → useFlexGapSupport-DOHIHBgY.js} +1 -1
  141. package/src/assets/web-panel/assets/{useFs-Dm1tDNYC.js → useFs-BxSoQhIY.js} +1 -1
  142. package/src/assets/web-panel/assets/{usePersonalDataHub-__JgBEkX.js → usePersonalDataHub-MOR76PYB.js} +1 -1
  143. package/src/assets/web-panel/assets/{vnode-1hQKpRgP.js → vnode-BBGIyeYD.js} +1 -1
  144. package/src/assets/web-panel/assets/{zoom-C1EY9X2J.js → zoom-C1oFENec.js} +1 -1
  145. package/src/assets/web-panel/index.html +1 -1
  146. package/src/commands/audit.js +4 -3
  147. package/src/commands/automation.js +6 -14
  148. package/src/commands/bi.js +10 -9
  149. package/src/commands/codegen.js +5 -13
  150. package/src/commands/dao.js +8 -6
  151. package/src/commands/dbevo.js +13 -14
  152. package/src/commands/economy.js +3 -2
  153. package/src/commands/evolution.js +3 -2
  154. package/src/commands/federation.js +4 -3
  155. package/src/commands/governance.js +9 -4
  156. package/src/commands/hardening.js +5 -4
  157. package/src/commands/incentive.js +6 -5
  158. package/src/commands/kg.js +17 -10
  159. package/src/commands/lowcode.js +23 -11
  160. package/src/commands/marketplace.js +4 -3
  161. package/src/commands/mcp.js +17 -5
  162. package/src/commands/ops.js +9 -4
  163. package/src/commands/recommend.js +7 -5
  164. package/src/commands/scim.js +3 -2
  165. package/src/commands/session.js +9 -6
  166. package/src/commands/social.js +4 -3
  167. package/src/commands/sync.js +3 -2
  168. package/src/commands/tenant.js +11 -6
  169. package/src/commands/zkp.js +8 -9
  170. package/src/gateways/ws/ws-agent-handler.js +12 -3
  171. package/src/gateways/ws/ws-server.js +6 -0
  172. package/src/harness/background-task-manager.js +44 -18
  173. package/src/harness/mcp-client.js +125 -46
  174. package/src/lib/chat-core.js +209 -107
  175. package/src/lib/claude-code-bridge.js +13 -1
  176. package/src/lib/dao-governance.js +3 -3
  177. package/src/lib/downloader.js +82 -25
  178. package/src/lib/headless-config-command.js +62 -0
  179. package/src/lib/json-schema-output.js +55 -11
  180. package/src/lib/mcp-oauth.js +110 -21
  181. package/src/lib/mcp-serve.js +70 -11
  182. package/src/lib/multisig-runtime.js +22 -3
  183. package/src/lib/parse-json-option.js +35 -0
  184. package/src/lib/parse-number-option.js +27 -0
  185. package/src/lib/runnable-provider.js +97 -0
  186. package/src/repl/agent-repl.js +76 -17
  187. package/src/repl/config-summary.js +66 -0
  188. package/src/runtime/agent-core.js +189 -36
  189. package/src/runtime/headless-runner.js +49 -1
  190. package/src/runtime/headless-stream.js +34 -0
  191. package/src/assets/web-panel/assets/Notes-BaOU0psj.js +0 -7
  192. package/src/assets/web-panel/assets/OrderTableRenderer-BZOiY8Yw.js +0 -1
  193. package/src/assets/web-panel/assets/Projects-BzjvJYMW.js +0 -1
  194. package/src/assets/web-panel/assets/devWarning-CnV02N63.js +0 -1
  195. package/src/assets/web-panel/assets/index-DJ2gkaIH.js +0 -1
  196. package/src/assets/web-panel/assets/index-Dvm_-AOi.js +0 -1
@@ -5,6 +5,7 @@
5
5
 
6
6
  import chalk from "chalk";
7
7
  import { logger } from "../lib/logger.js";
8
+ import { parseJsonOption } from "../lib/parse-json-option.js";
8
9
  import { bootstrap, shutdown } from "../runtime/bootstrap.js";
9
10
  import {
10
11
  ensureZKPTables,
@@ -100,10 +101,8 @@ export function registerZkpCommand(program) {
100
101
  const db = ctx.db.getDatabase();
101
102
  ensureZKPTables(db);
102
103
 
103
- const privateInputs = options.private
104
- ? JSON.parse(options.private)
105
- : {};
106
- const publicInputs = options.public ? JSON.parse(options.public) : [];
104
+ const privateInputs = parseJsonOption(options.private, "--private", {});
105
+ const publicInputs = parseJsonOption(options.public, "--public", []);
107
106
  const proveOpts = options.scheme ? { scheme: options.scheme } : {};
108
107
  const proof = generateProof(
109
108
  db,
@@ -174,7 +173,7 @@ export function registerZkpCommand(program) {
174
173
  .option("--json", "Output as JSON")
175
174
  .action(async (options) => {
176
175
  try {
177
- const claims = options.claims ? JSON.parse(options.claims) : {};
176
+ const claims = parseJsonOption(options.claims, "--claims", {});
178
177
  const disclose = options.disclose
179
178
  ? options.disclose.split(",").map((s) => s.trim())
180
179
  : [];
@@ -404,7 +403,7 @@ export function registerZkpCommand(program) {
404
403
  const db = ctx.db.getDatabase();
405
404
  ensureZKPTables(db);
406
405
 
407
- const claims = options.claims ? JSON.parse(options.claims) : {};
406
+ const claims = parseJsonOption(options.claims, "--claims", {});
408
407
  const cred = registerCredential(db, {
409
408
  did: options.did,
410
409
  claims,
@@ -622,7 +621,7 @@ export function registerZkpCommand(program) {
622
621
  }
623
622
  const db = ctx.db.getDatabase();
624
623
  ensureZKPTables(db);
625
- const def = options.definition ? JSON.parse(options.definition) : {};
624
+ const def = parseJsonOption(options.definition, "--definition", {});
626
625
  const circuit = compileCircuitV2(db, {
627
626
  name,
628
627
  definition: def,
@@ -675,8 +674,8 @@ export function registerZkpCommand(program) {
675
674
  ensureZKPTables(db);
676
675
  const proof = generateProofV2(db, {
677
676
  circuitId,
678
- privateInputs: JSON.parse(options.private),
679
- publicInputs: JSON.parse(options.public),
677
+ privateInputs: parseJsonOption(options.private, "--private"),
678
+ publicInputs: parseJsonOption(options.public, "--public"),
680
679
  scheme: options.scheme,
681
680
  });
682
681
  logger.success("Proof generated (V2)");
@@ -16,6 +16,7 @@ import {
16
16
  detectTaskType,
17
17
  selectModelForTask,
18
18
  } from "../../lib/task-model-selector.js";
19
+ import { runnableTaskModel } from "../../lib/runnable-provider.js";
19
20
  import { PlanState } from "../../lib/plan-mode.js";
20
21
  import { CLISlotFiller } from "../../lib/slot-filler.js";
21
22
  import { createAbortError, isAbortError } from "../../lib/abort-utils.js";
@@ -63,7 +64,9 @@ export class WSAgentHandler {
63
64
  // Add user message
64
65
  session.messages.push({ role: "user", content: userMessage });
65
66
 
66
- // Auto-select model based on task type
67
+ // Auto-select model based on task type — runnable-first: never switch
68
+ // onto a provider with no usable key (you'd just 401). Keep the
69
+ // configured model in that case.
67
70
  let activeModel = session.model;
68
71
  const taskDetection = detectTaskType(userMessage);
69
72
  if (taskDetection.confidence > 0.3) {
@@ -71,8 +74,14 @@ export class WSAgentHandler {
71
74
  session.provider,
72
75
  taskDetection.taskType,
73
76
  );
74
- if (recommended && recommended !== activeModel) {
75
- activeModel = recommended;
77
+ const switchTo = runnableTaskModel({
78
+ provider: session.provider,
79
+ currentModel: activeModel,
80
+ recommended,
81
+ apiKey: session.apiKey,
82
+ });
83
+ if (switchTo) {
84
+ activeModel = switchTo;
76
85
  this.interaction.emit("model-switch", {
77
86
  requestId,
78
87
  from: session.model,
@@ -855,6 +855,12 @@ export class ChainlessChainWSServer extends EventEmitter {
855
855
  }
856
856
 
857
857
  _startHeartbeat() {
858
+ // Idempotent: clear any existing timer first so a repeated start() (or a
859
+ // re-fired "listening" event) can't leak the previous interval — stop()
860
+ // only clears the most recent handle, so an overwrite would orphan it.
861
+ if (this._heartbeatTimer) {
862
+ clearInterval(this._heartbeatTimer);
863
+ }
858
864
  this._heartbeatTimer = setInterval(() => {
859
865
  for (const [clientId, client] of this.clients) {
860
866
  if (!client.alive) {
@@ -9,12 +9,7 @@
9
9
  */
10
10
 
11
11
  import { fork } from "node:child_process";
12
- import {
13
- existsSync,
14
- mkdirSync,
15
- appendFileSync,
16
- readFileSync,
17
- } from "node:fs";
12
+ import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
18
13
  import { join } from "node:path";
19
14
  import { createHash } from "node:crypto";
20
15
  import { EventEmitter } from "node:events";
@@ -38,7 +33,10 @@ export const TaskStatus = {
38
33
  TIMEOUT: "timeout",
39
34
  };
40
35
 
41
- const RECOVERABLE_TASK_STATUSES = new Set([TaskStatus.PENDING, TaskStatus.RUNNING]);
36
+ const RECOVERABLE_TASK_STATUSES = new Set([
37
+ TaskStatus.PENDING,
38
+ TaskStatus.RUNNING,
39
+ ]);
42
40
 
43
41
  export class BackgroundTaskManager extends EventEmitter {
44
42
  constructor(options = {}) {
@@ -47,7 +45,9 @@ export class BackgroundTaskManager extends EventEmitter {
47
45
  this.heartbeatTimeout = options.heartbeatTimeout || 60000;
48
46
  this.historyLimit = options.historyLimit || 50;
49
47
  this.nodeId =
50
- options.nodeId || process.env.CC_NODE_ID || `${process.pid}@${process.platform}`;
48
+ options.nodeId ||
49
+ process.env.CC_NODE_ID ||
50
+ `${process.pid}@${process.platform}`;
51
51
  this.recoveryPolicy = options.recoveryPolicy || "claim-stale";
52
52
  this.staleNodeTimeout = options.staleNodeTimeout || 5 * 60 * 1000;
53
53
  this.tasks = new Map();
@@ -139,7 +139,12 @@ export class BackgroundTaskManager extends EventEmitter {
139
139
  child.on("exit", (code) => {
140
140
  if (task.status === TaskStatus.RUNNING) {
141
141
  if (code === 0) {
142
- this._complete(taskId, TaskStatus.COMPLETED, "Process exited (0)", null);
142
+ this._complete(
143
+ taskId,
144
+ TaskStatus.COMPLETED,
145
+ "Process exited (0)",
146
+ null,
147
+ );
143
148
  } else {
144
149
  this._complete(
145
150
  taskId,
@@ -178,8 +183,12 @@ export class BackgroundTaskManager extends EventEmitter {
178
183
 
179
184
  getHistory(taskId, options = {}) {
180
185
  const history = this.get(taskId)?.history || [];
181
- const limit = Number.isFinite(options.limit) ? Math.max(1, options.limit) : null;
182
- const offset = Number.isFinite(options.offset) ? Math.max(0, options.offset) : 0;
186
+ const limit = Number.isFinite(options.limit)
187
+ ? Math.max(1, options.limit)
188
+ : null;
189
+ const offset = Number.isFinite(options.offset)
190
+ ? Math.max(0, options.offset)
191
+ : 0;
183
192
 
184
193
  if (limit === null && offset === 0) {
185
194
  return history;
@@ -192,7 +201,8 @@ export class BackgroundTaskManager extends EventEmitter {
192
201
  offset,
193
202
  limit: limit || history.length,
194
203
  hasMore: offset + items.length < history.length,
195
- nextOffset: offset + items.length < history.length ? offset + items.length : null,
204
+ nextOffset:
205
+ offset + items.length < history.length ? offset + items.length : null,
196
206
  };
197
207
  }
198
208
 
@@ -212,9 +222,16 @@ export class BackgroundTaskManager extends EventEmitter {
212
222
  const child = this.processes.get(taskId);
213
223
  if (child) {
214
224
  child.kill("SIGTERM");
215
- setTimeout(() => {
225
+ // Escalate to SIGKILL only if SIGTERM didn't take. unref() + clear-on-exit
226
+ // so a prompt exit (or process shutdown right after stop) isn't held open
227
+ // for the full grace period by this timer.
228
+ const killTimer = setTimeout(() => {
216
229
  if (child.exitCode === null) child.kill("SIGKILL");
217
230
  }, 2000);
231
+ if (killTimer && typeof killTimer.unref === "function") killTimer.unref();
232
+ if (typeof child.once === "function") {
233
+ child.once("exit", () => clearTimeout(killTimer));
234
+ }
218
235
  }
219
236
  const task = this.tasks.get(taskId);
220
237
  if (task) {
@@ -335,7 +352,8 @@ export class BackgroundTaskManager extends EventEmitter {
335
352
  }
336
353
 
337
354
  _normalizePersistedTask(entry) {
338
- const task = entry?.kind === "task_snapshot" && entry.task ? entry.task : entry;
355
+ const task =
356
+ entry?.kind === "task_snapshot" && entry.task ? entry.task : entry;
339
357
 
340
358
  if (!task || typeof task !== "object") {
341
359
  return null;
@@ -354,7 +372,11 @@ export class BackgroundTaskManager extends EventEmitter {
354
372
  if (normalized.history.length === 0) {
355
373
  normalized.history.push({
356
374
  event: "loaded",
357
- timestamp: normalized.completedAt || normalized.startedAt || normalized.createdAt || Date.now(),
375
+ timestamp:
376
+ normalized.completedAt ||
377
+ normalized.startedAt ||
378
+ normalized.createdAt ||
379
+ Date.now(),
358
380
  status: normalized.status,
359
381
  });
360
382
  }
@@ -414,8 +436,10 @@ export class BackgroundTaskManager extends EventEmitter {
414
436
 
415
437
  _decideRecovery(task) {
416
438
  const previousOwnerNodeId = task.ownerNodeId || null;
417
- const sameNode = previousOwnerNodeId === this.nodeId || !previousOwnerNodeId;
418
- const lastSeenAt = task.lastHeartbeat || task.startedAt || task.createdAt || 0;
439
+ const sameNode =
440
+ previousOwnerNodeId === this.nodeId || !previousOwnerNodeId;
441
+ const lastSeenAt =
442
+ task.lastHeartbeat || task.startedAt || task.createdAt || 0;
419
443
  const stale = Date.now() - lastSeenAt > this.staleNodeTimeout;
420
444
 
421
445
  if (sameNode) {
@@ -440,7 +464,9 @@ export class BackgroundTaskManager extends EventEmitter {
440
464
  return {
441
465
  shouldRecover: false,
442
466
  policy: this.recoveryPolicy,
443
- reason: stale ? "foreign-node-stale-observed" : "foreign-node-active-observed",
467
+ reason: stale
468
+ ? "foreign-node-stale-observed"
469
+ : "foreign-node-active-observed",
444
470
  previousOwnerNodeId,
445
471
  };
446
472
  }
@@ -33,6 +33,14 @@ export const ServerState = {
33
33
  /** Transport kinds that carry a URL (no stdio process). */
34
34
  const URL_TRANSPORTS = new Set(["http", "https", "sse", "ws", "wss"]);
35
35
 
36
+ /**
37
+ * Default per-call timeout for HTTP MCP requests, mirroring the 30s stdio
38
+ * timeout so a hung/dead HTTP server can't block a request forever. Servers
39
+ * flagged `longRunning` (e.g. the IDE bridge, whose openDiff blocks on human
40
+ * review) are exempt; override per server with `config.requestTimeoutMs`.
41
+ */
42
+ const HTTP_REQUEST_TIMEOUT_MS = 30000;
43
+
36
44
  /**
37
45
  * Infer the transport kind for a server config. Falls back to "stdio".
38
46
  * Prefers an explicit `transport` field; otherwise derives from URL scheme
@@ -218,13 +226,32 @@ export class MCPClient extends EventEmitter {
218
226
  this.emit("server-error", { name, error: data.toString("utf8") });
219
227
  });
220
228
 
229
+ // If the server process dies with requests in flight, reject them
230
+ // immediately with a clear error instead of letting each hang until its
231
+ // 30s timeout (fail-fast on a crashed/exited MCP server).
232
+ const failPending = (errMsg) => {
233
+ for (const [, pending] of entry._pending) {
234
+ if (pending.timeout) clearTimeout(pending.timeout);
235
+ try {
236
+ pending.reject(new Error(errMsg));
237
+ } catch {
238
+ // already settled — ignore
239
+ }
240
+ }
241
+ entry._pending.clear();
242
+ };
243
+
221
244
  proc.on("close", (code) => {
222
245
  entry.state = ServerState.DISCONNECTED;
246
+ failPending(
247
+ `MCP server "${name}" process exited (code ${code}) before responding`,
248
+ );
223
249
  this.emit("server-disconnected", { name, code });
224
250
  });
225
251
 
226
252
  proc.on("error", (err) => {
227
253
  entry.state = ServerState.ERROR;
254
+ failPending(`MCP server "${name}" process error: ${err.message}`);
228
255
  this.emit("server-error", { name, error: err.message });
229
256
  });
230
257
  } else {
@@ -247,12 +274,24 @@ export class MCPClient extends EventEmitter {
247
274
  entry.serverInfo = initResult?.serverInfo || {};
248
275
  entry.capabilities = initResult?.capabilities || {};
249
276
 
250
- // Fetch available tools
277
+ // Fetch available tools. Per MCP a server advertises a `tools` capability
278
+ // in its initialize response; if it does and tools/list then fails, that
279
+ // is a genuine fetch failure we must surface (Claude-Code 2.1.181 — show
280
+ // "Connected · tools fetch failed" rather than a misleading "Tools: 0").
281
+ // A server that did not advertise tools simply has none, so a failure
282
+ // there is expected and stays quiet.
283
+ entry.tools = [];
284
+ entry.toolsError = null;
285
+ const advertisesTools =
286
+ entry.capabilities && entry.capabilities.tools !== undefined;
251
287
  try {
252
288
  const toolsResult = await this._sendRequest(name, "tools/list", {});
253
289
  entry.tools = toolsResult?.tools || [];
254
- } catch {
255
- // Server may not support tools
290
+ } catch (err) {
291
+ if (advertisesTools) {
292
+ entry.toolsError = err?.message || String(err);
293
+ }
294
+ // else: server did not advertise tools — legitimately none.
256
295
  }
257
296
 
258
297
  // Fetch available resources
@@ -275,11 +314,16 @@ export class MCPClient extends EventEmitter {
275
314
  // Server may not support prompts
276
315
  }
277
316
 
278
- this.emit("server-connected", { name, tools: entry.tools.length });
317
+ this.emit("server-connected", {
318
+ name,
319
+ tools: entry.tools.length,
320
+ toolsError: entry.toolsError,
321
+ });
279
322
  return {
280
323
  name,
281
324
  state: entry.state,
282
325
  tools: entry.tools,
326
+ toolsError: entry.toolsError,
283
327
  resources: entry.resources,
284
328
  prompts: entry.prompts,
285
329
  serverInfo: entry.serverInfo,
@@ -338,6 +382,7 @@ export class MCPClient extends EventEmitter {
338
382
  name,
339
383
  state: entry.state,
340
384
  tools: entry.tools.length,
385
+ toolsError: entry.toolsError || null,
341
386
  resources: entry.resources.length,
342
387
  prompts: (entry.prompts || []).length,
343
388
  serverInfo: entry.serverInfo || {},
@@ -599,53 +644,87 @@ export class MCPClient extends EventEmitter {
599
644
  headers["Mcp-Session-Id"] = entry.httpSessionId;
600
645
  }
601
646
 
602
- const response = await _deps.fetch(entry.httpUrl, {
603
- method: "POST",
604
- headers,
605
- body,
606
- });
607
-
608
- // Capture session id (server may emit on initialize response only)
609
- const sessionId =
610
- (response.headers && typeof response.headers.get === "function"
611
- ? response.headers.get("mcp-session-id") ||
612
- response.headers.get("Mcp-Session-Id")
613
- : null) || null;
614
- if (sessionId && !entry.httpSessionId) {
615
- entry.httpSessionId = sessionId;
616
- }
617
-
618
- if (!response.ok) {
619
- const text =
620
- typeof response.text === "function" ? await response.text() : "";
621
- throw new Error(
622
- `HTTP ${response.status}${text ? `: ${text.slice(0, 200)}` : ""}`,
623
- );
647
+ // Per-call timeout (parity with the 30s stdio timeout) so a hung or dead
648
+ // HTTP MCP server can't block the request forever. Servers flagged
649
+ // longRunning — e.g. the IDE bridge, whose openDiff blocks on human review
650
+ // (see ideServerToMcpConfig) — are exempt. Override per server with
651
+ // config.requestTimeoutMs (0 disables).
652
+ const longRunning = Boolean(entry.config && entry.config.longRunning);
653
+ const timeoutMs = Number.isFinite(entry.config?.requestTimeoutMs)
654
+ ? entry.config.requestTimeoutMs
655
+ : HTTP_REQUEST_TIMEOUT_MS;
656
+ let controller = null;
657
+ let timer = null;
658
+ if (
659
+ !longRunning &&
660
+ timeoutMs > 0 &&
661
+ typeof AbortController === "function"
662
+ ) {
663
+ controller = new AbortController();
664
+ timer = setTimeout(() => controller.abort(), timeoutMs);
624
665
  }
625
666
 
626
- const contentType = response.headers?.get
627
- ? String(response.headers.get("content-type") || "").toLowerCase()
628
- : "";
667
+ try {
668
+ const response = await _deps.fetch(entry.httpUrl, {
669
+ method: "POST",
670
+ headers,
671
+ body,
672
+ ...(controller ? { signal: controller.signal } : {}),
673
+ });
629
674
 
630
- let envelope;
631
- if (contentType.includes("text/event-stream")) {
632
- envelope = await _extractSseResponse(response, id);
633
- } else {
634
- envelope =
635
- typeof response.json === "function"
636
- ? await response.json()
637
- : JSON.parse(
638
- typeof response.text === "function" ? await response.text() : "",
639
- );
640
- }
675
+ // Capture session id (server may emit on initialize response only)
676
+ const sessionId =
677
+ (response.headers && typeof response.headers.get === "function"
678
+ ? response.headers.get("mcp-session-id") ||
679
+ response.headers.get("Mcp-Session-Id")
680
+ : null) || null;
681
+ if (sessionId && !entry.httpSessionId) {
682
+ entry.httpSessionId = sessionId;
683
+ }
641
684
 
642
- if (!envelope || typeof envelope !== "object") {
643
- throw new Error("Empty or invalid JSON-RPC response");
644
- }
645
- if (envelope.error) {
646
- throw new Error(envelope.error.message || "Unknown error");
685
+ if (!response.ok) {
686
+ const text =
687
+ typeof response.text === "function" ? await response.text() : "";
688
+ throw new Error(
689
+ `HTTP ${response.status}${text ? `: ${text.slice(0, 200)}` : ""}`,
690
+ );
691
+ }
692
+
693
+ const contentType = response.headers?.get
694
+ ? String(response.headers.get("content-type") || "").toLowerCase()
695
+ : "";
696
+
697
+ let envelope;
698
+ if (contentType.includes("text/event-stream")) {
699
+ envelope = await _extractSseResponse(response, id);
700
+ } else {
701
+ envelope =
702
+ typeof response.json === "function"
703
+ ? await response.json()
704
+ : JSON.parse(
705
+ typeof response.text === "function"
706
+ ? await response.text()
707
+ : "",
708
+ );
709
+ }
710
+
711
+ if (!envelope || typeof envelope !== "object") {
712
+ throw new Error("Empty or invalid JSON-RPC response");
713
+ }
714
+ if (envelope.error) {
715
+ throw new Error(envelope.error.message || "Unknown error");
716
+ }
717
+ return envelope.result;
718
+ } catch (err) {
719
+ if (controller && controller.signal.aborted) {
720
+ throw new Error(
721
+ `Request timeout: ${method} (HTTP, no response in ${timeoutMs}ms)`,
722
+ );
723
+ }
724
+ throw err;
725
+ } finally {
726
+ if (timer) clearTimeout(timer);
647
727
  }
648
- return envelope.result;
649
728
  }
650
729
 
651
730
  /** Fire-and-forget JSON-RPC notification over HTTP. Errors swallowed. */