chainlesschain 0.162.107 → 0.162.109

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 (176) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-B7Hz-sMT.js → AIOps-DOMx_gkg.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-tIqg_ue9.js → ActionButton-C3V6-KN7.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-B6DbVy_b.js → Analytics-DhcH00zB.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-Cm_hOXV8.js → AppLayout-DxaARGVc.js} +4 -4
  6. package/src/assets/web-panel/assets/{Audit-Crc94mKO.js → Audit-B5v_yPs_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-DIZVZXve.js → Backup-y0trXy2c.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-BZWHuJyu.js → BaseInput-BKmOrsWP.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-BOCsYs8k.js → Chat-YxvzoXfA.js} +6 -6
  10. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BK6OX-J4.js → ChatBubbleRenderer-BT502wFg.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-_bsZN_Td.js → Checkbox-CWlobcH7.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-Cu-YIxg5.js → Codegen-DyDnpB9x.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-BMM77pN6.js → Col-vSk5m8e6.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-B4uw3_sc.js → Community-ms1KDyit.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-RxrnL4Ql.js → Compact-CgOlMunA.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-CKEfGRFH.js → Compliance-BtmnlvkF.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-jS0AVJjh.js → Cowork-oEgcjamv.js} +4 -4
  18. package/src/assets/web-panel/assets/{Cron-DNyVTsuS.js → Cron-C45dOmbZ.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-DRaSmfQP.js → Crosschain-COCW4N4S.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-B5UTlNum.js → DID-D6L3jdjB.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-OVoPMtcA.js → Dashboard-CZO_nWR9.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-5OA2sbK9.js → Dropdown-BHogrwxg.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-DUJPUE_n.js → EmailListRenderer-DVU5KA6Y.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BKFSlqTB.js → FamilyGuardDashboard-BpJuZRlS.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-BAhgrKK6.js → Federation-C8XUIu9h.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CZ8wh8ZQ.js → FormItemContext-Dkv__07L.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-Cnsg9gY4.js → GenericCardRenderer-PI4Hv6J7.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-EY6xhhH-.js → Git-DwoiOK7x.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-CKGWi2hF.js → Governance-CZMrVnKF.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-Bibz4dcl.js → Inference-DGMCR5fY.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-B1GhH4Rh.js → KnowledgeGraph-CHnyTP7N.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-Ce6yjdqa.js → Logs-aHwf1vTL.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-0dFzmO9J.js → Marketplace-DrrJWlYy.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-crttKADW.js → McpTools-FsvEQItl.js} +5 -5
  35. package/src/assets/web-panel/assets/{Memory-BjtmouRu.js → Memory-BaLEbZZU.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-Djm8NKL7.js → MobileBridge-Cbpe-UlH.js} +2 -2
  37. package/src/assets/web-panel/assets/MobileProjects-WpHJ6m0I.js +1 -0
  38. package/src/assets/web-panel/assets/{Mtc-UvDcNKPe.js → Mtc-B2-MRjt7.js} +2 -2
  39. package/src/assets/web-panel/assets/{MtcAudit-CCUvaVsw.js → MtcAudit-BPKg4478.js} +4 -4
  40. package/src/assets/web-panel/assets/{Multisig-CltVDZII.js → Multisig-DL-OMvg9.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-nVqmxQ1N.js → NLProgramming-BFbo7QJF.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-gyIOnFru.js → Notes-DxlawFPj.js} +4 -4
  43. package/src/assets/web-panel/assets/{NotificationSettings-C7VByx8y.js → NotificationSettings-mXTgzIC1.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-DopvBK5x.js → OrderTableRenderer-BUcf5CYv.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-VxnADtjw.js → Organization-FeID8_Wf.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-Du67ZgzE.js → Overflow-DTFS4Vaz.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-CXK6FzZK.js → P2P-BkylEhA8.js} +2 -2
  48. package/src/assets/web-panel/assets/PdhVaultBrowser-D8bxEEcj.js +7 -0
  49. package/src/assets/web-panel/assets/{Permissions-B23k4uT8.js → Permissions-BSQ09sRI.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-CjiMy8De.js → PersonalDataHub-Ba5iRuIi.js} +3 -3
  51. package/src/assets/web-panel/assets/{Pipeline-Z1KmgqP5.js → Pipeline-DmL3Gpxg.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-CmxIvTR1.js → Privacy-DAvd_DSh.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-Bts__Qz3.js → ProjectInit-AxBuFwBR.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-Bd_lhQgg.js → ProjectSettings-BZ40fAt5.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-DR-bmuRQ.js → Projects-BHNbHuBF.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-kaD-Hp-Y.js → Providers-CDkzXPon.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-qy3iXhzr.js → QuickAsk-CzKbOUkP.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-DONp9kRc.js → Recommend-D82aHoFt.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-DDyL2Aeq.js → Reputation-zpuCi7ft.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-D8YcGPf4.js → Row-BDq7p96-.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-DXUODZiL.js → RssFeed-pAo6EJPy.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-DEdHYWFg.js → Search-BXv5RRMM.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-H-o6s5e0.js → Security-Gn-HnKp5.js} +3 -3
  64. package/src/assets/web-panel/assets/{Services-UuIWNe9h.js → Services-BlfMJ4ZL.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-DYtxZPtS.js → Skeleton-Q8cKUNTJ.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-DDifBlN4.js → Skills-BjOLODy1.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-D1ZAkzmU.js → Sla-TbklgbfG.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-CKjGGj0q.js → SpeechSettings-DzKKyV6J.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-BGg86vP1.js → SyncSettings-Bq-76qhL.js} +2 -2
  70. package/src/assets/web-panel/assets/{Tasks-VxIkYJmg.js → Tasks-DWBUnqic.js} +1 -1
  71. package/src/assets/web-panel/assets/{Templates-DFRL3OpQ.js → Templates-CS77urAR.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-CmYigIMz.js → Tenant-B1hx8tjz.js} +1 -1
  73. package/src/assets/web-panel/assets/Terminal-CNX2SAIP.js +3 -0
  74. package/src/assets/web-panel/assets/{TimelineRenderer-B75R5MPw.js → TimelineRenderer-CS_iGXXB.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-BQjcUYi2.js → Tokens-CPfe_Ndx.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-B87osPjr.js → Trigger-DARLZ6w5.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-BMNsPMGf.js → Trust-R_mlmd7H.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-Dh8aq9A5.js → UkeySign-CysEd--z.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-BrW9UYwd.js → VideoEditing-eQ46o05K.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-rVZaz6JO.js → Wallet-C5788NxS.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-BaQ7s6Rr.js → WebAuthn-CK_CPM4k.js} +5 -5
  82. package/src/assets/web-panel/assets/{WorkflowEditor-DFo5Ff-W.js → WorkflowEditor-DhvdLkE6.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-BhGtd3vF.js → chat-CcKQhy1e.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-C_Hs-0Q_.js → colors-B4d3_MCE.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-Cxku8C7o.js → compact-item-DC-Xf92z.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-v6jUmogl.js → createContext-KBHDmwRY.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-Da3Hdd0q.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-BKhLdwbQ.js → hasIn-DEuYFeVL.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-DfD0hdcw.js → index-2Csz0FGD.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-C2rsPZun.js → index-8BCBAwoA.js} +3 -3
  91. package/src/assets/web-panel/assets/{index-Bgtv4PNS.js → index-B4RknAfS.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-CARZxqzf.js → index-B5cOdkHy.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-B2IZIcKV.js → index-BB9f50Gt.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DMiUs7VJ.js → index-BCbc993k.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-GoxGMHvm.js → index-BJbBr6_l.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BDW_6hBP.js → index-BK8vM7es.js} +1 -1
  97. package/src/assets/web-panel/assets/index-BMeXnsEn.js +1 -0
  98. package/src/assets/web-panel/assets/{index-B3pkWuB9.js → index-BZjC0VTy.js} +1 -1
  99. package/src/assets/web-panel/assets/index-BdqPeWvV.js +1 -0
  100. package/src/assets/web-panel/assets/{index-CBL2DZwT.js → index-Bm39r2a4.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DpO44b89.js → index-BwD3FKsC.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BolB2BAg.js → index-BxlEfskb.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DfjaeiC1.js → index-C4Ose5wC.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DaDs425R.js → index-CCnk_-ug.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BMCT14Fw.js → index-CTgs-ddr.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CVAVApRf.js → index-CdabmsmR.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CwKGHmaT.js → index-ChJ_B7b9.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BElj4Od7.js → index-Cl0As6V5.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-C2PkAyeB.js → index-CxtHBFqA.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Ha3xv10h.js → index-Cyb-NAiR.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-Mloutg2P.js → index-DE0-JQay.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CmhCbfio.js → index-DQMDCc8g.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DkFQKhAE.js → index-DQXNz0yD.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DgpKinbP.js → index-DSXxbnHU.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CZDVxpam.js → index-DTudiivg.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CfTpPsv6.js → index-DZN3yAE2.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BnYbnWuX.js → index-DhGYNT5Y.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dfnrfw8C.js → index-DkoDAyug.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CYz9sJYb.js → index-EnBI6ILp.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BLJ91vZT.js → index-JXP0mbdx.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-D8-PVIyz.js → index-N4xZOl6m.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-ITysWrpU.js → index-Tcf8b4Dr.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-gjdcCPuc.js → index-VkeJvcgx.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-D_vs8HEm.js → index-ZbZ9FKyc.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D7aePQoD.js → index-gOIec6-U.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-51MhKb2G.js → index-p5OuYAoC.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Hmuq7HiU.js → index-tW1RyKbL.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-3JYk3XrB.js → initDefaultProps-BSjGxzmn.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-DnWevrJa.js → motion-B5_Cszlm.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-9bW2GZpH.js → move-Zi4ZApRv.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-D8ydPKdj.js → omit-BNHsjZx4.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-l5iG1eRA.js → pickAttrs-GzJRqTuY.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-Bp1b6Ucy.js → placementArrow-CXfzbh2d.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-ChTuOCcn.js → responsiveObserve-lhENMtmd.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-Ck7EHmbe.js → slide-BaUzfEHc.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-Beih7s__.js → statusUtils-ZYc611Fn.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-Dddg8IJR.js → styleChecker-CaymUbb1.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-DU6cxKQF.js → useFlexGapSupport-9EAy_UPY.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-BISbGmgC.js → useFs-CUqinWaA.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-CuO7bBz3.js → usePersonalDataHub-eOXrcae-.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-Cq3NWQzC.js → vnode-gBQTchDv.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-BTh_EbRh.js → zoom-CCC5-LNi.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/__tests__/hub-query-events.test.js +134 -0
  145. package/src/commands/agent.js +6 -0
  146. package/src/commands/hub.js +39 -10
  147. package/src/commands/mcp.js +42 -10
  148. package/src/commands/pdh.js +191 -1
  149. package/src/constants.js +2 -2
  150. package/src/gateways/ws/video-protocol.js +7 -0
  151. package/src/harness/feature-flags.js +19 -6
  152. package/src/harness/prompt-compressor.js +1 -0
  153. package/src/lib/agent-core.js +2 -0
  154. package/src/lib/config-manager.js +42 -1
  155. package/src/lib/git-integration.js +1 -2
  156. package/src/lib/learning/learning-hooks.js +6 -0
  157. package/src/lib/llm-providers.js +2 -0
  158. package/src/lib/mcp-auth-target.js +53 -0
  159. package/src/lib/repl-completer.js +48 -9
  160. package/src/lib/shell-approval.js +7 -12
  161. package/src/lib/skill-loader.js +6 -2
  162. package/src/lib/suggest-name.js +91 -0
  163. package/src/lib/task-model-selector.js +5 -5
  164. package/src/repl/agent-repl.js +21 -1
  165. package/src/repl/slash-macro.js +7 -1
  166. package/src/runtime/agent-core.js +62 -3
  167. package/src/runtime/coding-agent-contract-shared.cjs +11 -1
  168. package/src/runtime/headless-runner.js +57 -4
  169. package/src/runtime/headless-stream.js +50 -2
  170. package/src/session/index.js +6 -2
  171. package/src/assets/web-panel/assets/MobileProjects-CuWSdENU.js +0 -1
  172. package/src/assets/web-panel/assets/PdhVaultBrowser-BH6PhZwi.js +0 -7
  173. package/src/assets/web-panel/assets/Terminal-DjjQrZtn.js +0 -3
  174. package/src/assets/web-panel/assets/devWarning-BnANFH7b.js +0 -1
  175. package/src/assets/web-panel/assets/index-CEJN-vG4.js +0 -1
  176. package/src/assets/web-panel/assets/index-CeJCYDPn.js +0 -1
@@ -15,6 +15,7 @@
15
15
  * All output supports --json for scripting. Default is human-readable.
16
16
  */
17
17
 
18
+ import { readFileSync, writeFileSync } from "node:fs";
18
19
  import chalk from "chalk";
19
20
  import ora from "ora";
20
21
  import { logger } from "../lib/logger.js";
@@ -528,7 +529,7 @@ async function cmdQueryEvents(options) {
528
529
  // skips the 77-adapter registry build (and is crash-resilient to a
529
530
  // partial pdh install). getHubMinimal() returns the full hub if one was
530
531
  // already built this process, so the vault instance is identical.
531
- const hub = await getHubMinimal();
532
+ const hub = await (options._getHub || getHubMinimal)();
532
533
  const q = {};
533
534
  if (options.subtype) q.subtype = options.subtype;
534
535
  if (options.since) q.since = Number(options.since);
@@ -543,10 +544,18 @@ async function cmdQueryEvents(options) {
543
544
  }
544
545
  logger.log(`${events.length} events:`);
545
546
  for (const ev of events) {
546
- const at = new Date(ev.at).toISOString();
547
- logger.log(
548
- ` ${chalk.gray(at)} ${chalk.cyan(ev.subtype)} ${ev.summary || ev.id}`,
549
- );
547
+ // Vault events carry `occurredAt` (epoch ms) + `content`, NOT `at` /
548
+ // `summary` — reading the wrong fields previously threw "Invalid time
549
+ // value" on the first row and killed the whole listing. Guard the
550
+ // timestamp so one malformed row can't crash the output.
551
+ const ts = Number(ev.occurredAt);
552
+ const at = Number.isFinite(ts) ? new Date(ts).toISOString() : "(no date)";
553
+ const summary =
554
+ (ev.content &&
555
+ (ev.content.text || ev.content.title || ev.content.subject)) ||
556
+ ev.summary ||
557
+ ev.id;
558
+ logger.log(` ${chalk.gray(at)} ${chalk.cyan(ev.subtype)} ${summary}`);
550
559
  }
551
560
  process.exit(0);
552
561
  } catch (err) {
@@ -601,7 +610,9 @@ async function cmdExportEvents(options) {
601
610
  const hub = await (options._getHub || getHubMinimal)();
602
611
  const all = exportAllEvents(hub.vault);
603
612
  if (options.output) {
604
- require("fs").writeFileSync(options.output, JSON.stringify(all), "utf-8");
613
+ // ESM module — must NOT use require("fs") (ReferenceError: require is
614
+ // not defined). Use the static node:fs import.
615
+ writeFileSync(options.output, JSON.stringify(all), "utf-8");
605
616
  if (options.json) {
606
617
  jsonAndExit({ ok: true, count: all.length, output: options.output });
607
618
  return;
@@ -623,7 +634,8 @@ async function cmdImportEvents(options) {
623
634
  "import-events: --input <file> is required (a JSON array of events)",
624
635
  );
625
636
  }
626
- const raw = require("fs").readFileSync(options.input, "utf-8");
637
+ // ESM module — use the static node:fs import, not require("fs").
638
+ const raw = readFileSync(options.input, "utf-8");
627
639
  const events = JSON.parse(raw);
628
640
  if (!Array.isArray(events)) {
629
641
  throw new Error("import-events: expected a JSON array of events");
@@ -789,7 +801,7 @@ async function cmdEventDetail(eventId, options) {
789
801
  }
790
802
  try {
791
803
  // Read-only single-event lookup — vault-only, use the minimal hub.
792
- const hub = await getHubMinimal();
804
+ const hub = await (options._getHub || getHubMinimal)();
793
805
  const event = hub.vault.getEvent(eventId);
794
806
  if (!event) {
795
807
  const result = { found: false, eventId };
@@ -802,9 +814,24 @@ async function cmdEventDetail(eventId, options) {
802
814
  } else {
803
815
  logger.log(chalk.bold(`event ${event.id}`));
804
816
  logger.log(` subtype: ${event.subtype}`);
805
- logger.log(` source: ${event.source}`);
806
- if (event.title) logger.log(` title: ${event.title}`);
817
+ // occurredAt (epoch ms) is the canonical timestamp; guard a bad value.
818
+ const ts = Number(event.occurredAt);
819
+ if (Number.isFinite(ts)) {
820
+ logger.log(` occurred: ${new Date(ts).toISOString()}`);
821
+ }
822
+ // `source` is an object ({ adapter, ... }) — print the adapter, not the
823
+ // object (which renders as "[object Object]").
824
+ const adapter =
825
+ event.source && typeof event.source === "object"
826
+ ? event.source.adapter
827
+ : event.source;
828
+ if (adapter) logger.log(` source: ${adapter}`);
807
829
  if (event.actor) logger.log(` actor: ${event.actor}`);
830
+ const summary =
831
+ event.content &&
832
+ (event.content.text || event.content.title || event.content.subject);
833
+ if (summary) logger.log(` content: ${summary}`);
834
+ if (event.title) logger.log(` title: ${event.title}`);
808
835
  if (event.amount != null) {
809
836
  logger.log(` amount: ${event.amount} ${event.currency || ""}`);
810
837
  }
@@ -3263,6 +3290,8 @@ export const _internal = {
3263
3290
  cmdRetrieveContext,
3264
3291
  cmdStats,
3265
3292
  cmdHealth,
3293
+ cmdQueryEvents,
3294
+ cmdEventDetail,
3266
3295
  parsePositiveInt,
3267
3296
  cmdAIChatList,
3268
3297
  cmdAIChatLogin,
@@ -23,6 +23,8 @@ import {
23
23
  SUPPORTED_TRANSPORTS,
24
24
  } from "../lib/mcp-scaffold.js";
25
25
  import { parseJsonOption } from "../lib/parse-json-option.js";
26
+ import { resolveMcpAuthTarget, isUrlLike } from "../lib/mcp-auth-target.js";
27
+ import { notFoundWithSuggestion } from "../lib/suggest-name.js";
26
28
  import {
27
29
  CATALOG as REGISTRY_CATALOG,
28
30
  CATEGORIES as REGISTRY_CATEGORIES,
@@ -39,6 +41,27 @@ function getClient() {
39
41
  return mcpClient;
40
42
  }
41
43
 
44
+ /**
45
+ * Resolve a `mcp login|logout <target>` argument (a URL or a configured server
46
+ * NAME — Claude-Code 2.1.186 parity) to a concrete server URL. The DB is only
47
+ * bootstrapped when a name lookup is actually needed, so a raw-URL login stays
48
+ * dependency-free.
49
+ */
50
+ async function resolveAuthTargetUrl(program, target) {
51
+ if (isUrlLike(target)) return resolveMcpAuthTarget(target).url;
52
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
53
+ const lookup = (name) => {
54
+ try {
55
+ return ctx.db
56
+ ? new MCPServerConfig(ctx.db.getDatabase()).get(name)
57
+ : null;
58
+ } catch {
59
+ return null; // a lookup failure surfaces as "unknown server" below
60
+ }
61
+ };
62
+ return resolveMcpAuthTarget(target, lookup).url;
63
+ }
64
+
42
65
  /**
43
66
  * Connect MCP server(s) for a one-shot query (resources / prompts). Connects
44
67
  * the named server, or every registered server when `serverName` is omitted.
@@ -56,8 +79,9 @@ async function connectForQuery(program, serverName) {
56
79
  if (serverName) {
57
80
  const row = config.get(serverName);
58
81
  if (!row) {
82
+ const names = config.list().map((s) => s.name);
59
83
  logger.error(
60
- `Server "${serverName}" not configured. Use 'mcp add' first.`,
84
+ `${notFoundWithSuggestion(serverName, names, { noun: "Server" })}. Use 'mcp add' first.`,
61
85
  );
62
86
  await shutdown();
63
87
  process.exit(1);
@@ -111,9 +135,9 @@ export function registerMcpCommand(program) {
111
135
 
112
136
  // mcp login — OAuth 2.0 (Auth Code + PKCE) for a remote MCP server.
113
137
  mcp
114
- .command("login <url>")
138
+ .command("login <target>")
115
139
  .description(
116
- "Authorize a remote MCP server via OAuth (opens a browser); stores the token",
140
+ "Authorize a remote MCP server via OAuth (opens a browser); stores the token. <target> is a URL or a configured server name.",
117
141
  )
118
142
  .option("--scope <scope>", "OAuth scope(s) to request")
119
143
  .option(
@@ -127,8 +151,9 @@ export function registerMcpCommand(program) {
127
151
  53682,
128
152
  )
129
153
  .option("--no-open", "Print the authorize URL instead of opening a browser")
130
- .action(async (url, options) => {
154
+ .action(async (target, options) => {
131
155
  try {
156
+ const url = await resolveAuthTargetUrl(program, target);
132
157
  const oauth = await import("../lib/mcp-oauth.js");
133
158
  if (options.open === false) {
134
159
  oauth._deps.openBrowser = () => false; // commander maps --no-open → open:false
@@ -159,10 +184,13 @@ export function registerMcpCommand(program) {
159
184
 
160
185
  // mcp logout — forget a stored OAuth token.
161
186
  mcp
162
- .command("logout <url>")
163
- .description("Delete the stored OAuth token for a remote MCP server")
164
- .action(async (url) => {
187
+ .command("logout <target>")
188
+ .description(
189
+ "Delete the stored OAuth token for a remote MCP server (<target> is a URL or a configured server name)",
190
+ )
191
+ .action(async (target) => {
165
192
  try {
193
+ const url = await resolveAuthTargetUrl(program, target);
166
194
  const { deleteStoredToken, serverKey } =
167
195
  await import("../lib/mcp-oauth.js");
168
196
  const ok = deleteStoredToken(url);
@@ -199,7 +227,7 @@ export function registerMcpCommand(program) {
199
227
  }
200
228
  if (rows.length === 0) {
201
229
  logger.log(
202
- chalk.gray("No MCP OAuth tokens. Run: cc mcp login <url>"),
230
+ chalk.gray("No MCP OAuth tokens. Run: cc mcp login <name|url>"),
203
231
  );
204
232
  return;
205
233
  }
@@ -497,12 +525,13 @@ export function registerMcpCommand(program) {
497
525
 
498
526
  const db = ctx.db.getDatabase();
499
527
  const config = new MCPServerConfig(db);
528
+ const names = config.list().map((s) => s.name);
500
529
  const removed = config.remove(name);
501
530
 
502
531
  if (removed) {
503
532
  logger.success(`MCP server "${name}" removed`);
504
533
  } else {
505
- logger.error(`Server "${name}" not found`);
534
+ logger.error(notFoundWithSuggestion(name, names, { noun: "Server" }));
506
535
  }
507
536
 
508
537
  await shutdown();
@@ -533,7 +562,10 @@ export function registerMcpCommand(program) {
533
562
  const serverConfig = config.get(name);
534
563
 
535
564
  if (!serverConfig) {
536
- logger.error(`Server "${name}" not configured. Use 'mcp add' first.`);
565
+ const names = config.list().map((s) => s.name);
566
+ logger.error(
567
+ `${notFoundWithSuggestion(name, names, { noun: "Server" })}. Use 'mcp add' first.`,
568
+ );
537
569
  process.exit(1);
538
570
  }
539
571
 
@@ -23,11 +23,125 @@ import {
23
23
  pdhLockDir,
24
24
  diagnosePdh,
25
25
  } from "../lib/pdh-bridge.js";
26
+ import { setupMcpFromConfig } from "../runtime/mcp-config.js";
27
+ import {
28
+ readFeedback,
29
+ summarizeFeedback,
30
+ } from "../lib/pdh-feedback-ledger.js";
26
31
 
27
32
  function emit(obj) {
28
33
  console.log(JSON.stringify(obj, null, 2));
29
34
  }
30
35
 
36
+ /** Concatenate the text blocks of an MCP tool result, else null. */
37
+ function mcpResultText(r) {
38
+ if (!r) return null;
39
+ if (Array.isArray(r.content)) {
40
+ const t = r.content
41
+ .filter((b) => b && b.type === "text" && typeof b.text === "string")
42
+ .map((b) => b.text)
43
+ .join("");
44
+ if (t) return t;
45
+ }
46
+ if (typeof r.result === "string") return r.result;
47
+ return null;
48
+ }
49
+
50
+ async function safeDisconnectAll(out) {
51
+ try {
52
+ await out?.mcpClient?.disconnectAll?.();
53
+ } catch {
54
+ /* best-effort cleanup */
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Live connectivity probe for the discovered PDH bridge — the cc-side
60
+ * diagnostic the list/status/doctor inspectors lack: list/status/doctor only
61
+ * read lockfiles, this actually **connects** and verifies the server responds
62
+ * (discover → connect → `pdh_ping` round-trip → report). Best-effort; always
63
+ * disconnects. The result NEVER carries the bearer token. Injectable for tests.
64
+ *
65
+ * @returns {Promise<object>} { ok, stage, reason?, device?, port?, transport?,
66
+ * tools?, latencyMs?, pingAttempted?, pingOk?, pingText?, pingError? }
67
+ */
68
+ export async function probePdhBridge(opts = {}, deps = {}) {
69
+ const env = opts.env || process.env;
70
+ const discover = deps.discoverPdhServer || discoverPdhServer;
71
+ const connect = deps.setupMcpFromConfig || setupMcpFromConfig;
72
+ const now = deps.now || (() => Date.now());
73
+
74
+ const lock = discover({ env });
75
+ if (!lock) {
76
+ return {
77
+ ok: false,
78
+ stage: "discover",
79
+ reason: "no live PDH server discovered (run `cc pdh doctor`)",
80
+ };
81
+ }
82
+ const base = {
83
+ device: lock.device,
84
+ port: lock.port,
85
+ transport: lock.transport,
86
+ };
87
+ const cfg = pdhServerToMcpConfig(lock);
88
+ const start = now();
89
+ let out;
90
+ try {
91
+ out = await connect({ pdh: cfg }, { writeErr: () => {} });
92
+ } catch (err) {
93
+ return { ok: false, stage: "connect", reason: err.message, ...base };
94
+ }
95
+ const conn = (out.connected || []).find((c) => c.server === "pdh");
96
+ if (!conn) {
97
+ await safeDisconnectAll(out);
98
+ return {
99
+ ok: false,
100
+ stage: "connect",
101
+ reason: "server did not connect (no tools)",
102
+ ...base,
103
+ };
104
+ }
105
+ // The bare tool names the bridge exposes (mcp__pdh__collect_files →
106
+ // collect_files), so the probe shows WHICH collectors a device advertises —
107
+ // confirming the bridge version/capabilities, not just a count.
108
+ const toolNames = (out.extraToolDefinitions || [])
109
+ .map((t) => t && t.function && t.function.name)
110
+ .filter((n) => typeof n === "string")
111
+ .map((n) =>
112
+ n.startsWith("mcp__pdh__") ? n.slice("mcp__pdh__".length) : n,
113
+ );
114
+ // Round-trip via pdh_ping when the bridge exposes it; otherwise the
115
+ // tools/list that connect already performed is itself proof of liveness.
116
+ const hasPing = toolNames.includes("pdh_ping");
117
+ let pingOk = null;
118
+ let pingText = null;
119
+ let pingError = null;
120
+ if (hasPing) {
121
+ try {
122
+ const r = await out.mcpClient.callTool("pdh", "pdh_ping", {});
123
+ pingOk = !r?.isError;
124
+ pingText = mcpResultText(r);
125
+ } catch (err) {
126
+ pingOk = false;
127
+ pingError = err.message;
128
+ }
129
+ }
130
+ await safeDisconnectAll(out);
131
+ return {
132
+ ok: pingOk !== false, // connected; an attempted ping must not have failed
133
+ stage: "ping",
134
+ ...base,
135
+ tools: conn.tools,
136
+ toolNames,
137
+ latencyMs: now() - start,
138
+ pingAttempted: hasPing,
139
+ pingOk,
140
+ pingText,
141
+ pingError,
142
+ };
143
+ }
144
+
31
145
  /** Strip the raw bearer token + internal _file path from a lock for output. */
32
146
  function redactLock(lock) {
33
147
  if (!lock) return null;
@@ -35,7 +149,8 @@ function redactLock(lock) {
35
149
  return { ...rest, hasToken: !!token };
36
150
  }
37
151
 
38
- export function registerPdhCommand(program) {
152
+ export function registerPdhCommand(program, deps = {}) {
153
+ const probe = deps.probePdhBridge || probePdhBridge;
39
154
  const pdh = program
40
155
  .command("pdh")
41
156
  .description(
@@ -158,5 +273,80 @@ export function registerPdhCommand(program) {
158
273
  console.log(` reason : ${diag.reason}`);
159
274
  });
160
275
 
276
+ pdh
277
+ .command("ping")
278
+ .description(
279
+ "Connect to the discovered PDH server and verify it responds (pdh_ping round-trip)",
280
+ )
281
+ .option("--json", "Machine-readable output")
282
+ .action(async (options) => {
283
+ const res = await probe({ env: process.env });
284
+ if (options.json) {
285
+ emit(res);
286
+ } else if (res.stage === "discover") {
287
+ console.log(
288
+ chalk.yellow("No PDH server discovered.") +
289
+ chalk.gray(" Run `cc pdh doctor` for why."),
290
+ );
291
+ } else if (!res.ok) {
292
+ console.log(
293
+ chalk.red(
294
+ `PDH ${res.device}:${res.port} — ${res.stage} failed: ` +
295
+ `${res.reason || res.pingError || "unknown"}`,
296
+ ),
297
+ );
298
+ } else {
299
+ const tag = res.pingAttempted
300
+ ? res.pingOk
301
+ ? chalk.green("pong")
302
+ : chalk.red("ping failed")
303
+ : chalk.gray("connected (no pdh_ping tool)");
304
+ console.log(
305
+ `PDH ${chalk.cyan(res.device)}:${res.port} ${chalk.green("OK")} — ` +
306
+ `${tag}, ${res.tools} tools, ${res.latencyMs}ms`,
307
+ );
308
+ if (res.toolNames && res.toolNames.length) {
309
+ console.log(chalk.gray(" tools: " + res.toolNames.join(", ")));
310
+ }
311
+ if (res.pingText) console.log(chalk.gray(" " + res.pingText));
312
+ }
313
+ if (!res.ok) process.exitCode = 1;
314
+ });
315
+
316
+ pdh
317
+ .command("feedback")
318
+ .description(
319
+ "Show what cc has learned from your cross-session corrections (§3.5.13 flywheel)",
320
+ )
321
+ .option("--json", "Machine-readable output")
322
+ .action((options) => {
323
+ const read = deps.readFeedback || readFeedback;
324
+ const summarize = deps.summarizeFeedback || summarizeFeedback;
325
+ const summary = summarize(read());
326
+ if (options.json) {
327
+ emit(summary);
328
+ return;
329
+ }
330
+ // Honest empty state (§3.5.18: surface "尚无" truthfully, never hide).
331
+ if (!summary.total) {
332
+ console.log(
333
+ chalk.gray("尚无跨会话反馈记录 (no cross-session feedback yet)."),
334
+ );
335
+ return;
336
+ }
337
+ console.log(chalk.bold(`PDH 自学习反馈 (${summary.total} 条)`));
338
+ console.log(
339
+ ` ${chalk.green("👍 " + summary.positive)} ` +
340
+ `${chalk.red("👎 " + summary.negative)} ` +
341
+ `净倾向 ${summary.sentiment >= 0 ? "+" : ""}${summary.sentiment}`,
342
+ );
343
+ if (summary.corrections.length) {
344
+ console.log(chalk.bold(" 已记住的纠正 (最新优先):"));
345
+ for (const c of summary.corrections) {
346
+ console.log(chalk.gray(` • ${c}`));
347
+ }
348
+ }
349
+ });
350
+
161
351
  return pdh;
162
352
  }
package/src/constants.js CHANGED
@@ -30,7 +30,7 @@ export const LLM_PROVIDERS = {
30
30
  volcengine: {
31
31
  name: "Volcengine (火山引擎/豆包)",
32
32
  defaultBaseUrl: "https://ark.cn-beijing.volces.com/api/v3",
33
- defaultModel: "doubao-seed-1-6-251015",
33
+ defaultModel: "doubao-seed-2-1-pro-260628",
34
34
  requiresApiKey: true,
35
35
  },
36
36
  openai: {
@@ -144,7 +144,7 @@ export const DEFAULT_CONFIG = {
144
144
  provider: "volcengine",
145
145
  apiKey: null,
146
146
  baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
147
- model: "doubao-seed-1-6-251015",
147
+ model: "doubao-seed-2-1-pro-260628",
148
148
  // When true, `cc ask` (provider=ollama only) overrides baseUrl to point at
149
149
  // the Android LocalLlmServer (127.0.0.1:18484). User opt-in toggle:
150
150
  // cc config set llm.preferAndroidLocal true
@@ -8,6 +8,13 @@
8
8
  * Route keys use dot-case: video.assets.list, video.deconstruct, etc.
9
9
  */
10
10
 
11
+ import { createRequire } from "node:module";
12
+ // ESM module — `require` is not a global here. createRequire gives a working
13
+ // require() for the lazy loads below (VideoPipeline + node core modules, kept
14
+ // lazy so importing this protocol module doesn't pull the video stack on
15
+ // every `cc` startup). Node >=22.12 (our engines floor) supports require(esm).
16
+ const require = createRequire(import.meta.url);
17
+
11
18
  function ok(data = {}) {
12
19
  return { ok: true, ...data };
13
20
  }
@@ -8,7 +8,13 @@
8
8
  * - object { enabled, variant, description }
9
9
  */
10
10
 
11
- import { loadConfig, getConfigValue, saveConfig } from "../lib/config-manager.js";
11
+ import {
12
+ loadConfig,
13
+ getConfigValue,
14
+ saveConfig,
15
+ } from "../lib/config-manager.js";
16
+ import { withFileLock } from "../lib/with-file-lock.js";
17
+ import { getConfigPath } from "../lib/paths.js";
12
18
  import { createHash } from "node:crypto";
13
19
  import { hostname } from "node:os";
14
20
 
@@ -51,7 +57,8 @@ export function feature(name) {
51
57
  if (value && typeof value === "object") return Boolean(value.enabled);
52
58
  const defaultValue = _getDefault(name);
53
59
  if (typeof defaultValue === "boolean") return defaultValue;
54
- if (typeof defaultValue === "number") return _percentageCheck(name, defaultValue);
60
+ if (typeof defaultValue === "number")
61
+ return _percentageCheck(name, defaultValue);
55
62
  if (defaultValue && typeof defaultValue === "object") {
56
63
  return Boolean(defaultValue.enabled);
57
64
  }
@@ -106,10 +113,16 @@ export function listFeatures() {
106
113
  }
107
114
 
108
115
  export function setFeature(name, value) {
109
- const config = loadConfig();
110
- if (!config.features) config.features = {};
111
- config.features[name] = value;
112
- saveConfig(config);
116
+ // Serialize the read-modify-write across processes so two concurrent
117
+ // `cc config features enable/disable` invocations don't clobber each other
118
+ // (and to space out writes so the atomic rename doesn't collide). Mirrors
119
+ // setConfigValue; the lock is best-effort and never hangs the CLI.
120
+ withFileLock(getConfigPath(), () => {
121
+ const config = loadConfig();
122
+ if (!config.features) config.features = {};
123
+ config.features[name] = value;
124
+ saveConfig(config);
125
+ });
113
126
  }
114
127
 
115
128
  export function getFlagInfo(name) {
@@ -77,6 +77,7 @@ export const CONTEXT_WINDOWS = {
77
77
  "moonshot-v1-32k": 32768,
78
78
  "moonshot-v1-128k": 131072,
79
79
  "doubao-seed-1-6-251015": 32768,
80
+ "doubao-seed-2-1-pro-260628": 32768,
80
81
  _provider_defaults: {
81
82
  ollama: 32768,
82
83
  openai: 128000,
@@ -3,6 +3,8 @@ export {
3
3
  AGENT_TOOLS,
4
4
  AGENT_TOOL_REGISTRY,
5
5
  MAX_SUB_AGENT_DEPTH,
6
+ MAX_TOOL_RESULT_CHARS,
7
+ capToolResultString,
6
8
  reloadSkills,
7
9
  getAgentToolDefinitions,
8
10
  getAgentToolDescriptors,
@@ -37,7 +37,7 @@ export function saveConfig(config) {
37
37
  const tmp = `${configPath}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`;
38
38
  try {
39
39
  writeFileSync(tmp, JSON.stringify(config, null, 2) + "\n", "utf-8");
40
- renameSync(tmp, configPath);
40
+ renameWithRetry(tmp, configPath);
41
41
  } catch (err) {
42
42
  try {
43
43
  if (existsSync(tmp)) unlinkSync(tmp);
@@ -48,6 +48,47 @@ export function saveConfig(config) {
48
48
  }
49
49
  }
50
50
 
51
+ // On Windows, `rename` over a target that another process currently has open
52
+ // (e.g. a concurrent `loadConfig` reader) fails with EPERM/EACCES/EBUSY instead
53
+ // of POSIX's silent atomic replace. Under bursts of concurrent `cc config`/`cc
54
+ // config features` invocations this surfaced as a flaky exit-1. Retry the rename
55
+ // a few times with a short synchronous backoff so the transient lock clears;
56
+ // the temp file is already fully written, so this stays crash-safe.
57
+ export function renameWithRetry(tmp, target, opts = {}) {
58
+ const {
59
+ attempts = 8,
60
+ baseDelayMs = 15,
61
+ _rename = renameSync,
62
+ _sleep = sleepSync,
63
+ } = opts;
64
+ for (let i = 0; ; i++) {
65
+ try {
66
+ _rename(tmp, target);
67
+ return;
68
+ } catch (err) {
69
+ const transient =
70
+ err &&
71
+ (err.code === "EPERM" ||
72
+ err.code === "EACCES" ||
73
+ err.code === "EBUSY" ||
74
+ err.code === "EEXIST");
75
+ if (!transient || i >= attempts - 1) throw err;
76
+ _sleep(baseDelayMs * (i + 1));
77
+ }
78
+ }
79
+ }
80
+
81
+ function sleepSync(ms) {
82
+ try {
83
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
84
+ } catch {
85
+ const end = Date.now() + ms; // SharedArrayBuffer unavailable — bounded spin
86
+ while (Date.now() < end) {
87
+ /* spin */
88
+ }
89
+ }
90
+ }
91
+
51
92
  export function getConfigValue(key) {
52
93
  const config = loadConfig();
53
94
  return getNestedValue(config, key);
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { execSync } from "child_process";
6
- import { existsSync } from "fs";
6
+ import { existsSync, writeFileSync, chmodSync } from "fs";
7
7
  import { join } from "path";
8
8
 
9
9
  /**
@@ -236,7 +236,6 @@ export function installHooks(dir) {
236
236
  echo "ChainlessChain: pre-commit hook running"
237
237
  `;
238
238
 
239
- const { writeFileSync, chmodSync } = require("fs");
240
239
  writeFileSync(hookPath, hookContent, "utf-8");
241
240
  try {
242
241
  chmodSync(hookPath, 0o755);
@@ -16,6 +16,12 @@
16
16
  * - Stateless — the trajectory ID is tracked on learningCtx
17
17
  */
18
18
 
19
+ import { createRequire } from "node:module";
20
+ // ESM module — `require` is not a global here. createRequire gives a working
21
+ // require() for the lazy TrajectoryStore load below (kept lazy to avoid a
22
+ // circular import). Node >=22.12 (our engines floor) supports require(esm).
23
+ const require = createRequire(import.meta.url);
24
+
19
25
  /**
20
26
  * @typedef {object} LearningContext
21
27
  * @property {import("./trajectory-store.js").TrajectoryStore} trajectoryStore
@@ -84,6 +84,8 @@ export const BUILT_IN_PROVIDERS = {
84
84
  baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
85
85
  apiKeyEnv: "VOLCENGINE_API_KEY",
86
86
  models: [
87
+ "doubao-seed-2-1-pro-260628",
88
+ "doubao-seed-2-0-lite-260215",
87
89
  "doubao-seed-1-6-251015",
88
90
  "doubao-seed-1-6-flash-250828",
89
91
  "doubao-seed-1-6-lite-251015",