chainlesschain 0.162.61 → 0.162.66

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 (164) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/assets/{AIOps-BiB8WfIz.js → AIOps-BeJlvHR1.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-NLBhC6jG.js → ActionButton-B93fwcal.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-k62j-xiL.js → Analytics-B-Lc0FRK.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-spr0Sm6J.js → AppLayout-nv2C8TdH.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-C3NHJos3.js → Audit-B4pwb1Oe.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-C2V9tGqF.js → Backup-B4HFWkJA.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-DeKm11mH.js → BaseInput-BQk1ONWO.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-CHZ2CU7x.js → Chat-B2IobFfI.js} +5 -5
  10. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DEXSa7tC.js → ChatBubbleRenderer-jJL-hGlG.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-q6E9VeLr.js → Checkbox-BHCU5kit.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen--4w4QpUI.js → Codegen-Bqgq9-0q.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-DLOkwTsj.js → Col-BqDf398Z.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-B1LxJGfE.js → Community-Cd58ltip.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-C_769oQZ.js → Compact-CWa3CY1X.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-zsI0s7vB.js → Compliance-BNJWsGi0.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-A1WA6whF.js → Cowork-ChOCC2KD.js} +3 -3
  18. package/src/assets/web-panel/assets/{Cron-C3JDTyyd.js → Cron-BpWtgfDE.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-D8O6uB86.js → Crosschain-Csy7U94a.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-BpOebm5d.js → DID-CIh7lr9T.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-Defso6kA.js → Dashboard-DYJUc9Jy.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-Cv9BrwT_.js → Dropdown-GnUptPAU.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-BWKHbh4C.js → EmailListRenderer-sE9mvxjT.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard--m_Ru7Ci.js → FamilyGuardDashboard-Dg7-GHSu.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-Bs6ZcAP0.js → Federation-BiH_O7jy.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CcAs3Acx.js → FormItemContext-C1AZ_qE-.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-DI1oL4pK.js → GenericCardRenderer-WpsC5meD.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-C27t3-fW.js → Git-L4XGb5Qj.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-Dr_syXc_.js → Governance-CJ9Gn_A9.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-CWM8dIbA.js → Inference-Dlc9Ey87.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph--cFDUZv3.js → KnowledgeGraph-CfndHiBW.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-Cnn2_Onf.js → Logs-CSOLZERs.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-4T9ok3Gz.js → Marketplace-Cjiz9wPY.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-BQvZwqcN.js → McpTools-C8UNhnTj.js} +4 -4
  35. package/src/assets/web-panel/assets/{Memory-BE9rPkM_.js → Memory-BhOoGXRL.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-DJ3j5lXC.js → MobileBridge-rKKcGEvg.js} +2 -2
  37. package/src/assets/web-panel/assets/{MobileProjects-qasLvYdb.js → MobileProjects-KvGFVl79.js} +1 -1
  38. package/src/assets/web-panel/assets/{Mtc-D3CSPTD9.js → Mtc-jyA3mXYt.js} +5 -5
  39. package/src/assets/web-panel/assets/{MtcAudit-DaYVGCN5.js → MtcAudit-BYi6sulR.js} +2 -2
  40. package/src/assets/web-panel/assets/{Multisig-Dz1c5r5w.js → Multisig-CWZGD6_3.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-BIKV_K-a.js → NLProgramming-bOIPDOh5.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-f6t-rmOa.js → Notes-_I6Hs_bJ.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-DHLQh8Fy.js → NotificationSettings-Bj9Bcy2A.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-CDMZ3o6i.js → OrderTableRenderer-C5zZeOhJ.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-DIsL758p.js → Organization-B-SfOynT.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-BMM7apnZ.js → Overflow-CG7JBYts.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-CTGMmTvi.js → P2P-vpebJYvr.js} +2 -2
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-DWwmm0k1.js → PdhVaultBrowser-CPeKixo2.js} +3 -3
  49. package/src/assets/web-panel/assets/{Permissions-Bed5JxMx.js → Permissions-CpflO2Ac.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-CIiZhSM5.js → PersonalDataHub-D6CjgWDH.js} +4 -4
  51. package/src/assets/web-panel/assets/{Pipeline-CtirPodz.js → Pipeline-CgC59gHt.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-DuXhXhE7.js → Privacy-CoZn6LrI.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-DZrnguBl.js → ProjectInit-BmNYdFPv.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-HIltqsJ1.js → ProjectSettings-C13HHOUG.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-BWFkePg4.js → Projects-BSHYaYKU.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-DEP0Jdvl.js → Providers-Dh6ys5NR.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-T2THoHNx.js → QuickAsk-Cljz9ZIS.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-CvbxaSwm.js → Recommend-CEAVAYGZ.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-6Afy6tfp.js → Reputation-C7AxH6cu.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-DY8OPWaO.js → Row-D5Jgzbof.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-wDGWb9pZ.js → RssFeed-V6vBnNBE.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-D_zHAwZY.js → Search-dfDC6aHa.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-Czq7AlGG.js → Security-BOSRXul6.js} +4 -4
  64. package/src/assets/web-panel/assets/{Services-Ac1g0ZcG.js → Services-dsNT3Tra.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-DXQ3eeSW.js → Skeleton-_rXFZqCe.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-CWRioX4u.js → Skills-WWvbl-N6.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-BlHthzfs.js → Sla-BZT_pwjV.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-Ct240JmL.js → SpeechSettings-BSVqkQ0F.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-BgDIt8Q-.js → SyncSettings-TLHuQW_s.js} +2 -2
  70. package/src/assets/web-panel/assets/Tasks-8-jiv3Dt.js +1 -0
  71. package/src/assets/web-panel/assets/{Templates-Dp9QhyIw.js → Templates-D7qs_H3G.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-CHTYMxzY.js → Tenant-B4hRLxlc.js} +1 -1
  73. package/src/assets/web-panel/assets/{Terminal-X-NGwLpv.js → Terminal-lrlEETgH.js} +2 -2
  74. package/src/assets/web-panel/assets/{TimelineRenderer-Bh8jA18j.js → TimelineRenderer-Do8UQaNj.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-DWkTd5dv.js → Tokens-wyuwl9gS.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-CRgVg6sd.js → Trigger-Ck4j8Emr.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-BgWOXd0W.js → Trust-Z07lGZvX.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-BlTUB9Y-.js → UkeySign-5rI48ojV.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-DI64XgNb.js → VideoEditing-Dm8PV-Ss.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-CJ3TNGiG.js → Wallet-BwWYuV0j.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-B2-rWWoV.js → WebAuthn-CavU3f2i.js} +5 -5
  82. package/src/assets/web-panel/assets/{WorkflowEditor-VI9otbaH.js → WorkflowEditor-jj1aB37x.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-CgYfiaVh.js → chat-BpRqPqbA.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-B9EhRTky.js → colors-BBJU99fO.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-Cb7bjraa.js → compact-item-t2Elz5Kg.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-DlXPeXuj.js → createContext-B_D6Nida.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-CmJstpP_.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-BbgRfrdf.js → hasIn-D5k1KNpe.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-ojRAd7Nq.js → index-1lcpLp-e.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-BoEFFKn3.js → index-2KvtrQkP.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-BU8hEUyq.js → index-33FQbw3H.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-Bt-lPYpq.js → index-3TymUGUQ.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-D8kB0k3E.js → index-6iwQSswx.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-c7-Jd6WB.js → index-B2cxsdFe.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DPaffcT8.js → index-BCpJT0on.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-p03wNqiP.js → index-BH_HjIO6.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-1iUK_kAw.js → index-BVEb-kUY.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-AR-QpAkP.js → index-BaS1rfcr.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BfSS-U5o.js → index-BfKFGtsC.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DDzNdZcX.js → index-Bo72gKe8.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CGx8aO_Y.js → index-C-271Q6Z.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-2ts5iOIB.js → index-C3alXfss.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-C95qWAh4.js → index-CB1AFQiL.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-De59Xat-.js → index-CHyyhgQ3.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cmr31VCO.js → index-CP2Nz1mx.js} +3 -3
  106. package/src/assets/web-panel/assets/{index-fG-1gXy0.js → index-CT_-tscA.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-D6t-Shqr.js → index-CWwjhqgi.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C73WgOc2.js → index-CYdBeNTv.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CMyzmvtJ.js → index-CgCeon6Z.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DUU9DY4J.js → index-Ctt8xM0M.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BD2W-qsS.js → index-CwAKqpJd.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Ira0HLPr.js → index-CwEJnamf.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Dh6qWb1v.js → index-D8LnFSKZ.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-D-Zz9PvD.js → index-DGtbeySv.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Bk7r1a9x.js → index-DHHTczBZ.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DbLJShJB.js → index-DIgtJB5J.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Cf9zwbk-.js → index-DLfAmDGs.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Caiu2avX.js → index-DRh9m8hf.js} +1 -1
  119. package/src/assets/web-panel/assets/index-Dric_1LC.js +1 -0
  120. package/src/assets/web-panel/assets/{index-CHR47Q5B.js → index-DzIq7BlR.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-OVrh8wTN.js → index-E4x-hzLB.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-5CrFMQjt.js → index-GSUbdu-w.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Dx4sm6dm.js → index-GSpv5udU.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DkQIyK-V.js → index-NMj4bTp1.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-C8DB27uJ.js → index-OmJk1MzD.js} +1 -1
  126. package/src/assets/web-panel/assets/index-eFol7ymc.js +1 -0
  127. package/src/assets/web-panel/assets/{index-DXxa7PR8.js → index-eVBDpynR.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-JT674ACa.js → initDefaultProps-CuryY55W.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-CokflrA9.js → motion-IVsWxV-s.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-CfMhRpyC.js → move-DNKsQLrH.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-ClYc5II5.js → omit-gXu4NluL.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-CTwEb_8h.js → pickAttrs-CVb4Ykex.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-Cb3StU_t.js → placementArrow-BarpAJK0.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-uIxkx5M1.js → responsiveObserve-eaDhQlY1.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-B9HZBQ7i.js → slide-C8oU8Wlo.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-C72bwYl0.js → statusUtils-DrBdj2xb.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-BFTtaQb8.js → styleChecker-_Rycq1-Q.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-DKl5j41_.js → useFlexGapSupport-BagU5XLY.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-BUHS6bo3.js → useFs-DZYMOaAQ.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-D8KrYSq4.js → usePersonalDataHub-CDMZ5QvU.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-JYP-aZDj.js → vnode-Bg7MuEf5.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-BFusdxdH.js → zoom-oJIwomWy.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/agent.js +39 -0
  145. package/src/commands/insights.js +137 -0
  146. package/src/commands/review.js +807 -0
  147. package/src/index.js +4 -0
  148. package/src/lib/cost-budget.js +109 -0
  149. package/src/lib/ide-context.js +50 -0
  150. package/src/lib/personal-data-hub-wiring.js +36 -0
  151. package/src/lib/session-insights.js +145 -0
  152. package/src/lib/skill-loader.js +18 -3
  153. package/src/repl/agent-repl.js +34 -0
  154. package/src/repl/tasks-status.js +82 -0
  155. package/src/runtime/agent-core.js +38 -3
  156. package/src/runtime/headless-runner.js +51 -3
  157. package/src/runtime/headless-stream.js +62 -4
  158. package/src/runtime/mcp-config.js +6 -0
  159. package/src/skills-bundled/run/SKILL.md +49 -0
  160. package/src/skills-bundled/verify/SKILL.md +49 -0
  161. package/src/assets/web-panel/assets/Tasks-3PTmatJP.js +0 -1
  162. package/src/assets/web-panel/assets/devWarning-D-Hp8s_8.js +0 -1
  163. package/src/assets/web-panel/assets/index-BvnHuxVM.js +0 -1
  164. package/src/assets/web-panel/assets/index-Dkm5IGwX.js +0 -1
@@ -47,6 +47,7 @@ import { expandFileRefs } from "./file-ref-expander.js";
47
47
  import { composeSystemPrompt } from "./system-prompt.js";
48
48
  import { buildUserContent } from "../lib/image-input.js";
49
49
  import { withQuietStdout } from "./quiet-stdout.js";
50
+ import { CostBudget } from "../lib/cost-budget.js";
50
51
 
51
52
  /** Tools that cannot mutate the filesystem or run commands. */
52
53
  export const READ_ONLY_TOOLS = Object.freeze([
@@ -525,6 +526,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
525
526
  mcpConfigPath: options.mcpConfig || null,
526
527
  db: db?.getDatabase?.() || null,
527
528
  includeRegistered: options.useRegisteredMcp !== false,
529
+ // --strict-mcp-config: use ONLY the --mcp-config servers, ignoring
530
+ // registered (cc mcp add) + IDE bridge auto-discovery.
531
+ strict: options.strictMcpConfig === true,
528
532
  ide: options.ide,
529
533
  cwd: options.cwd || process.cwd(),
530
534
  // advertise the session id to spawned stdio MCP servers
@@ -665,11 +669,19 @@ export async function runAgentHeadless(options = {}, deps = {}) {
665
669
  }
666
670
  }
667
671
 
672
+ // --max-budget-usd: a hard USD spend cap (Claude-Code parity). Accumulates
673
+ // per-call cost from token-usage events and stops the loop before the next
674
+ // paid call once the cap is reached. null → no cap (unchanged behavior).
675
+ const costBudget = options.maxCostUsd
676
+ ? new CostBudget({ limitUsd: options.maxCostUsd, table: options.priceTable })
677
+ : null;
678
+
668
679
  const startedAt = deps.now ? deps.now() : Date.now();
669
680
  const toolCalls = [];
670
681
  const usage = { input_tokens: 0, output_tokens: 0 };
671
682
  let finalText = "";
672
683
  let endReason = "complete";
684
+ let stopForCost = false;
673
685
 
674
686
  const emitStream = (obj) => {
675
687
  if (isStream) writeOut(JSON.stringify(obj) + "\n");
@@ -744,6 +756,31 @@ export async function runAgentHeadless(options = {}, deps = {}) {
744
756
  usage.input_tokens += event.usage?.input_tokens || 0;
745
757
  usage.output_tokens += event.usage?.output_tokens || 0;
746
758
  emitStream({ type: "token_usage", usage: event.usage });
759
+ if (costBudget) {
760
+ costBudget.add({
761
+ provider: event.provider,
762
+ model: event.model,
763
+ usage: event.usage,
764
+ });
765
+ if (costBudget.shouldWarnInactive()) {
766
+ const m = `cost cap $${options.maxCostUsd} set but model "${event.model}" is unpriced/free — cap inactive`;
767
+ if (isText) writeErr(` ${m}\n`);
768
+ emitStream({ type: "cost_warning", message: m });
769
+ }
770
+ if (costBudget.exceeded()) {
771
+ endReason = "cost-budget-exhausted";
772
+ stopForCost = true;
773
+ if (isText)
774
+ writeErr(
775
+ ` ⛔ cost budget $${options.maxCostUsd} reached (spent ≈$${costBudget.spentUsd}) — stopping\n`,
776
+ );
777
+ emitStream({
778
+ type: "cost_budget_exhausted",
779
+ limit_usd: options.maxCostUsd,
780
+ spent_usd: costBudget.spentUsd,
781
+ });
782
+ }
783
+ }
747
784
  break;
748
785
  }
749
786
  case "iteration-warning": {
@@ -772,6 +809,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
772
809
  if (isStream && event.type) emitStream(event);
773
810
  break;
774
811
  }
812
+ // Hard cost cap reached: stop consuming the loop so no further paid LLM
813
+ // call is made (break out of the for-await, not just the switch).
814
+ if (stopForCost) break;
775
815
  }
776
816
  } catch (err) {
777
817
  const message = err?.message || String(err);
@@ -837,11 +877,19 @@ export async function runAgentHeadless(options = {}, deps = {}) {
837
877
  }
838
878
 
839
879
  // coreAgentLoop emits run-ended reason "budget-exhausted" when the iteration
840
- // cap is hit; treat that as the max-turns error surface.
880
+ // cap is hit; treat that as the max-turns error surface. A cost-budget stop
881
+ // (--max-budget-usd) is its own error surface so callers can tell them apart.
841
882
  const exhausted =
842
883
  endReason === "budget-exhausted" || endReason === "max_turns";
843
- const isError = exhausted || endReason === "no-response";
844
- const subtype = exhausted ? "error_max_turns" : isError ? "error" : "success";
884
+ const costStopped = endReason === "cost-budget-exhausted";
885
+ const isError = exhausted || costStopped || endReason === "no-response";
886
+ const subtype = exhausted
887
+ ? "error_max_turns"
888
+ : costStopped
889
+ ? "error_max_budget"
890
+ : isError
891
+ ? "error"
892
+ : "success";
845
893
  const durationMs = (deps.now ? deps.now() : Date.now()) - startedAt;
846
894
 
847
895
  // Persist the assistant turn so a later --resume / --continue replays it.
@@ -26,6 +26,7 @@ import {
26
26
  makePermissionPromptConfirmer,
27
27
  } from "./mcp-config.js";
28
28
  import { IterationBudget } from "../lib/iteration-budget.js";
29
+ import { CostBudget } from "../lib/cost-budget.js";
29
30
  import {
30
31
  resolvePermissionMode,
31
32
  resolveEnabledTools,
@@ -140,11 +141,12 @@ export async function* readJsonLines(input) {
140
141
  * Run a single turn through the core agent loop, emitting NDJSON events.
141
142
  * Returns the turn outcome so the caller can grow history + the result line.
142
143
  */
143
- async function runTurn(messages, loopOptions, { runLoop, emit }) {
144
+ async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
144
145
  const usage = { input_tokens: 0, output_tokens: 0 };
145
146
  const toolCalls = [];
146
147
  let finalText = "";
147
148
  let endReason = "complete";
149
+ let stopForCost = false;
148
150
 
149
151
  for await (const event of runLoop(messages, loopOptions)) {
150
152
  switch (event.type) {
@@ -169,6 +171,17 @@ async function runTurn(messages, loopOptions, { runLoop, emit }) {
169
171
  usage.input_tokens += event.usage?.input_tokens || 0;
170
172
  usage.output_tokens += event.usage?.output_tokens || 0;
171
173
  emit({ type: "token_usage", usage: event.usage });
174
+ if (costBudget) {
175
+ costBudget.add({
176
+ provider: event.provider,
177
+ model: event.model,
178
+ usage: event.usage,
179
+ });
180
+ if (costBudget.exceeded()) {
181
+ endReason = "cost-budget-exhausted";
182
+ stopForCost = true;
183
+ }
184
+ }
172
185
  break;
173
186
  case "iteration-warning":
174
187
  emit({ type: "iteration_warning", message: event.message });
@@ -187,6 +200,9 @@ async function runTurn(messages, loopOptions, { runLoop, emit }) {
187
200
  if (event.type) emit(event);
188
201
  break;
189
202
  }
203
+ // Hard cost cap reached — stop consuming the loop (break the for-await, not
204
+ // just the switch) so no further paid LLM call is made.
205
+ if (stopForCost) break;
190
206
  }
191
207
  return { finalText, endReason, usage, toolCalls };
192
208
  }
@@ -458,6 +474,9 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
458
474
  mcpConfigPath: options.mcpConfig || null,
459
475
  db: db?.getDatabase?.() || null,
460
476
  includeRegistered: options.useRegisteredMcp !== false,
477
+ // --strict-mcp-config: only the --mcp-config servers (ignore
478
+ // registered + IDE bridge) for a reproducible MCP surface.
479
+ strict: options.strictMcpConfig === true,
461
480
  ide: options.ide,
462
481
  cwd: options.cwd || process.cwd(),
463
482
  // advertise the session id to spawned stdio MCP servers
@@ -553,6 +572,13 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
553
572
  : undefined,
554
573
  };
555
574
 
575
+ // --max-budget-usd: a SESSION-WIDE USD spend cap across all turns. Folded
576
+ // from token-usage in runTurn; once reached the session ends before the next
577
+ // paid call. null → no cap (unchanged behavior).
578
+ const costBudget = options.maxCostUsd
579
+ ? new CostBudget({ limitUsd: options.maxCostUsd, table: options.priceTable })
580
+ : null;
581
+
556
582
  let turns = 0;
557
583
  let sawError = false;
558
584
 
@@ -686,6 +712,18 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
686
712
  }
687
713
  }
688
714
 
715
+ // --replay-user-messages: echo each accepted user message back on the
716
+ // output stream (Claude-Code parity) so a consumer can correlate replies to
717
+ // inputs / log the transcript. Echoes the raw user text, before @file or
718
+ // IDE-context expansion.
719
+ if (options.replayUserMessages && parsed.text) {
720
+ emit({
721
+ type: "user",
722
+ message: { role: "user", content: parsed.text },
723
+ session_id: sessionId,
724
+ });
725
+ }
726
+
689
727
  // Per-turn iteration budget so one turn can't starve the rest.
690
728
  const budget = Number.isFinite(options.maxTurns)
691
729
  ? new IterationBudget({
@@ -795,7 +833,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
795
833
  outcome = await runTurn(
796
834
  messages,
797
835
  { ...loopOptionsBase, iterationBudget: budget, signal: turnSignal },
798
- { runLoop, emit },
836
+ { runLoop, emit, costBudget },
799
837
  );
800
838
  } catch (err) {
801
839
  currentAbort = null;
@@ -840,12 +878,29 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
840
878
  const exhausted =
841
879
  outcome.endReason === "budget-exhausted" ||
842
880
  outcome.endReason === "max_turns";
843
- const isError = exhausted || outcome.endReason === "no-response";
881
+ const costStopped = outcome.endReason === "cost-budget-exhausted";
882
+ const isError = exhausted || costStopped || outcome.endReason === "no-response";
844
883
  if (isError) sawError = true;
845
884
 
885
+ if (costStopped) {
886
+ emit({
887
+ type: "cost_budget_exhausted",
888
+ limit_usd: options.maxCostUsd,
889
+ spent_usd: costBudget?.spentUsd,
890
+ session_id: sessionId,
891
+ turn: turns,
892
+ });
893
+ }
894
+
846
895
  emit({
847
896
  type: "result",
848
- subtype: exhausted ? "error_max_turns" : isError ? "error" : "success",
897
+ subtype: exhausted
898
+ ? "error_max_turns"
899
+ : costStopped
900
+ ? "error_max_budget"
901
+ : isError
902
+ ? "error"
903
+ : "success",
849
904
  is_error: isError,
850
905
  result: outcome.finalText,
851
906
  session_id: sessionId,
@@ -853,6 +908,9 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
853
908
  usage: outcome.usage,
854
909
  });
855
910
 
911
+ // Session-wide cost cap reached → stop accepting further turns.
912
+ if (costStopped) break;
913
+
856
914
  // While planning, blocked tool calls grew the plan during this turn —
857
915
  // push the fresh snapshot so the panel's plan card stays live.
858
916
  {
@@ -400,6 +400,12 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
400
400
  if (args.mcpConfigPath) {
401
401
  result = await doFile(args.mcpConfigPath, fwd); // fail-fast on bad file
402
402
  }
403
+ // --strict-mcp-config: use ONLY the explicit --mcp-config servers; ignore the
404
+ // registered (cc mcp add) set and IDE-bridge auto-discovery so the run's MCP
405
+ // surface is fully reproducible (Claude-Code parity).
406
+ if (args.strict) {
407
+ return result;
408
+ }
403
409
  if (args.includeRegistered !== false && args.db) {
404
410
  result = await doReg(args.db, {
405
411
  ...fwd,
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: run
3
+ description: Launch and drive this project's app to see a change actually working — not just passing tests. Use when asked to run, start, or screenshot the app, or to confirm a change works in the real running app. Detects the project type (CLI, server, TUI, Electron, browser app, or library) and uses the right launch pattern.
4
+ category: development
5
+ activation: manual
6
+ tags: [run, launch, app, dev, smoke-test]
7
+ ---
8
+
9
+ # Run the app
10
+
11
+ Goal: actually launch this project and exercise the change, so "it works" means
12
+ observed behavior — not a green test suite. $ARGUMENTS may name what to run or
13
+ which change to exercise; if empty, infer from the recent work.
14
+
15
+ ## 1. Find how this project is meant to run (in priority order)
16
+
17
+ 1. **A project skill/command** that already launches it — check `.chainlesschain/`,
18
+ `.claude/`, `package.json` `scripts` (`dev`, `start`, `serve`), `Makefile`,
19
+ `Procfile`, `docker-compose.yml`, README "Quick Start".
20
+ 2. **The dev command** for the detected stack. Prefer the one a human would use
21
+ locally, not the production/CI one.
22
+
23
+ ## 2. Launch pattern by project type
24
+
25
+ - **CLI tool**: run the binary with a realistic subcommand + flags (e.g.
26
+ `node bin/<cli>.js <cmd> --help`, then a real invocation). Read stdout/stderr.
27
+ - **HTTP/API server**: start it in the background, poll the health/route until it
28
+ responds, hit the relevant endpoint with `curl`, then stop it. Never leave a
29
+ server running — capture its task id and kill it when done.
30
+ - **TUI**: launch with a scripted/non-interactive path if one exists; otherwise
31
+ describe the exact keystrokes and capture the first screen.
32
+ - **Electron / desktop**: use the project's `dev` script (e.g. `npm run dev`);
33
+ if there's no display, say so and fall back to building + smoke-importing the
34
+ changed module.
35
+ - **Browser/web app**: start the dev server, open the route that exercises the
36
+ change, take a screenshot or read the rendered DOM/console.
37
+ - **Library (no app)**: there's nothing to "launch" — write a tiny throwaway
38
+ script that imports the changed API and runs the new path, then run it.
39
+
40
+ ## 3. Drive the change, then report
41
+
42
+ - Exercise the specific path the change touched (the new flag, route, screen,
43
+ function) with realistic input.
44
+ - Report what you OBSERVED: the actual output / status code / screenshot / log
45
+ line — quoting it. Distinguish "ran and behaved correctly" from "started but I
46
+ couldn't reach the changed path".
47
+ - Clean up: stop any background process you started. If you couldn't run it
48
+ (no display, missing service, needs a device), say exactly what's blocking and
49
+ what you'd run once unblocked — don't claim success you didn't observe.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: verify
3
+ description: Verify that a code change actually does what it's supposed to by running the app and observing behavior. Use when asked to verify a PR, confirm a fix works, test a change manually, check that a feature works, or validate local changes before pushing — beyond just unit tests.
4
+ category: development
5
+ activation: manual
6
+ tags: [verify, validate, confirm, qa, smoke-test]
7
+ ---
8
+
9
+ # Verify the change
10
+
11
+ Goal: confirm a specific change does what it claims, by observing real behavior —
12
+ not by trusting the diff or a passing test alone. $ARGUMENTS may name the change /
13
+ PR / expected behavior to verify; if empty, infer it from the recent work or the
14
+ current diff.
15
+
16
+ ## 1. State the claim precisely
17
+
18
+ Write down, in one line, what the change is supposed to do and how you'd know it
19
+ worked ("after the fix, `avg([1,2,3])` returns 2, not NaN"). If you can't state a
20
+ checkable claim, ask for one rather than guessing.
21
+
22
+ ## 2. Establish the before/after when feasible
23
+
24
+ - If practical and safe, observe the BUGGY behavior first (e.g. on the base
25
+ revision, or by reverting the change in a scratch copy / `cc checkpoint`), then
26
+ the FIXED behavior — so the verification is differential, not just "it ran".
27
+ - For a pure feature add, exercising the new path is enough.
28
+
29
+ ## 3. Exercise it for real
30
+
31
+ - Use the `run` skill's launch patterns to start the app and drive the exact path
32
+ the change touches (the new flag / route / screen / function) with realistic
33
+ input — including an edge case the change was meant to handle.
34
+ - Prefer observing the running app; fall back to a focused script or a targeted
35
+ test ONLY if the app genuinely can't be launched here (say which and why).
36
+ - Run the existing tests too if they're relevant, but treat them as supporting
37
+ evidence, not the verification itself.
38
+
39
+ ## 4. Verdict
40
+
41
+ Give a clear verdict with evidence:
42
+
43
+ - **VERIFIED** — quote the observed output/behavior that proves the claim, and
44
+ note any edge case you checked.
45
+ - **NOT VERIFIED** — show what you observed that contradicts the claim (the bug
46
+ still reproduces, an error, wrong output).
47
+ - **BLOCKED** — state exactly what stopped you (no display, missing service,
48
+ needs a device/credentials) and the precise command/steps you'd run once
49
+ unblocked. Never report VERIFIED for something you did not actually observe.
@@ -1 +0,0 @@
1
- import{E as B,b as z,r as D,I as p,J as c,U as _,c as n,K as a,S,V as w,o as P,x as I,P as i,Q as g,R as r,F as h,Z as F}from"./vendor-BvqAck49.js";import{u as R,_ as O}from"./index-Cmr31VCO.js";import{R as E}from"./icons-DP3uiYxy.js";const V=B("tasks",()=>{const k=D([]),l=D(!1);let u=null,e=null;const x=z(()=>k.value.filter(t=>t.status==="running")),b=z(()=>k.value.filter(t=>t.status==="pending")),y=z(()=>k.value.filter(t=>t.status==="completed"||t.status==="failed"||t.status==="timeout"));async function f(){const t=R();l.value=!0;try{const s=await t.sendRaw({type:"tasks-list"});s&&Array.isArray(s.tasks)&&(k.value=s.tasks)}catch{}finally{l.value=!1}}async function o(t){const s=R();try{await s.sendRaw({type:"tasks-stop",taskId:t})}catch{}finally{await f()}}const d=D(null);function m(t=5e3){v(),f(),u=setInterval(f,t),T()}function v(){u&&(clearInterval(u),u=null),e&&(e(),e=null)}function T(){const t=R();if(e)return;const s=C=>{C.type==="task:notification"&&C.payload?.task&&(d.value=C.payload.task,f(),setTimeout(()=>{d.value=null},8e3))};e=t.onRuntimeEvent(s)}function N(t){return!t||t<0?"-":t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${(t/6e4).toFixed(1)}m`}function A(t){switch(t){case"running":return"processing";case"pending":return"default";case"completed":return"success";case"failed":return"error";case"timeout":return"warning";default:return"default"}}return{tasks:k,loading:l,running:x,pending:b,completed:y,lastNotification:d,fetchTasks:f,stopTask:o,startPolling:m,stopPolling:v,formatDuration:N,getStatusColor:A}}),U={__name:"Tasks",setup(k,{expose:l}){l();const u=V(),e=[{title:"状态",key:"status",width:90},{title:"描述",key:"description",ellipsis:!0},{title:"类型",dataIndex:"type",width:100},{title:"耗时",key:"duration",width:90},{title:"创建时间",key:"createdAt",width:180},{title:"结果",key:"result",ellipsis:!0},{title:"操作",key:"action",width:80}];function x(o){return o.status==="running"&&o.startedAt?u.formatDuration(Date.now()-o.startedAt):o.completedAt&&o.startedAt?u.formatDuration(o.completedAt-o.startedAt):"-"}function b(o){return o?new Date(o).toLocaleString():"-"}function y(o,d){return o?o.length>d?`${o.slice(0,d)}...`:o:""}P(()=>u.startPolling(5e3)),I(()=>u.stopPolling());const f={store:u,columns:e,getDuration:x,formatTime:b,truncate:y,onMounted:P,onUnmounted:I,get ReloadOutlined(){return E},get useTasksStore(){return V}};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}},K={class:"page-header"},L={key:0,class:"error-text"},j={key:1},J={class:"task-header"},M={class:"task-desc"},Q={class:"task-id"},W={class:"task-meta"},Z=["title"],q={key:0,class:"error-text"},G={key:1,class:"success-text"},H={key:2,class:"muted-text"};function X(k,l,u,e,x,b){const y=p("a-button"),f=p("a-space"),o=p("a-alert"),d=p("a-statistic"),m=p("a-card"),v=p("a-col"),T=p("a-row"),N=p("a-tag"),A=p("a-table");return i(),c("div",null,[_("div",K,[l[3]||(l[3]=_("div",null,[_("h2",{class:"page-title"},"后台任务"),_("p",{class:"page-sub"},"查看后台任务队列、实时通知和任务执行结果。")],-1)),n(f,null,{default:a(()=>[n(y,{ghost:"",loading:e.store.loading,onClick:l[0]||(l[0]=t=>e.store.fetchTasks())},{icon:a(()=>[n(e.ReloadOutlined)]),default:a(()=>[l[2]||(l[2]=g(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.store.lastNotification?(i(),S(o,{key:0,type:e.store.lastNotification.status==="completed"?"success":"error","show-icon":"",closable:"",class:"banner",onClose:l[1]||(l[1]=t=>e.store.lastNotification=null)},{message:a(()=>[g(" 任务"+r(e.store.lastNotification.status==="completed"?"完成":"结束")+": "+r(e.store.lastNotification.description||e.store.lastNotification.id.slice(0,16)),1)]),description:a(()=>[e.store.lastNotification.error?(i(),c("span",L,r(e.store.lastNotification.error),1)):e.store.lastNotification.result?(i(),c("span",j,r(e.truncate(String(e.store.lastNotification.result),120)),1)):w("v-if",!0)]),_:1},8,["type"])):w("v-if",!0),n(T,{gutter:[16,16],class:"stats-row"},{default:a(()=>[n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"全部任务",value:e.store.tasks.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"运行中",value:e.store.running.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"等待中",value:e.store.pending.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"已完成",value:e.store.completed.length},null,8,["value"])]),_:1})]),_:1})]),_:1}),e.store.running.length>0?(i(),S(m,{key:1,title:"运行中的任务",class:"panel-card",size:"small"},{default:a(()=>[(i(!0),c(h,null,F(e.store.running,t=>(i(),c("div",{key:t.id,class:"task-item running"},[_("div",J,[n(N,{color:e.store.getStatusColor(t.status)},{default:a(()=>[g(r(t.status.toUpperCase()),1)]),_:2},1032,["color"]),_("span",M,r(t.description),1),_("span",Q,r(t.id.slice(0,16)),1)]),_("div",W,[_("span",null,"类型: "+r(t.type||"-"),1),_("span",null,"已运行: "+r(e.store.formatDuration(Date.now()-t.startedAt)),1),n(y,{size:"small",danger:"",onClick:s=>e.store.stopTask(t.id)},{default:a(()=>[...l[4]||(l[4]=[g("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):w("v-if",!0),n(m,{class:"panel-card"},{default:a(()=>[n(A,{columns:e.columns,"data-source":e.store.tasks,pagination:{pageSize:15,size:"small"},loading:e.store.loading,"row-key":"id",size:"small"},{bodyCell:a(({column:t,record:s})=>[t.key==="status"?(i(),S(N,{key:0,color:e.store.getStatusColor(s.status)},{default:a(()=>[g(r(s.status),1)]),_:2},1032,["color"])):t.key==="description"?(i(),c("span",{key:1,title:s.command},r(s.description),9,Z)):t.key==="duration"?(i(),c(h,{key:2},[g(r(e.getDuration(s)),1)],64)):t.key==="createdAt"?(i(),c(h,{key:3},[g(r(e.formatTime(s.createdAt)),1)],64)):t.key==="result"?(i(),c(h,{key:4},[s.error?(i(),c("span",q,r(e.truncate(s.error,60)),1)):s.result?(i(),c("span",G,r(e.truncate(String(s.result),60)),1)):(i(),c("span",H,"-"))],64)):t.key==="action"?(i(),c(h,{key:5},[s.status==="running"?(i(),S(y,{key:0,size:"small",danger:"",onClick:C=>e.store.stopTask(s.id)},{default:a(()=>[...l[5]||(l[5]=[g(" 停止 ",-1)])]),_:1},8,["onClick"])):w("v-if",!0)],64)):w("v-if",!0)]),_:1},8,["data-source","loading"])]),_:1})])}const et=O(U,[["render",X],["__scopeId","data-v-da5ff6a2"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/views/Tasks.vue"]]);export{et as default};
@@ -1 +0,0 @@
1
- import{O as r}from"./index-Cmr31VCO.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-DLOkwTsj.js";import{U as t}from"./index-Cmr31VCO.js";import"./vendor-BvqAck49.js";import"./index-Dh6qWb1v.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-DY8OPWaO.js";import{U as t}from"./index-Cmr31VCO.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-uIxkx5M1.js";import"./useFlexGapSupport-DKl5j41_.js";import"./styleChecker-BFTtaQb8.js";import"./index-Dh6qWb1v.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};