chainlesschain 0.162.152 → 0.162.153

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/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-CVLVJS-Q.js → AIOps-CBilhs1R.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CJ2_GJsI.js → ActionButton-Cf-RnC5Y.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-CZsmlTF8.js → Analytics-S8tkGhw0.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-DREvMZ62.js → AppLayout-CNXI3Bw5.js} +5 -5
  7. package/src/assets/web-panel/assets/{Audit-B4NR42w_.js → Audit-DF2zVFZ0.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-CJFmf3In.js → Backup-CMEiwQZL.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-Bh8_iUZY.js → BaseInput-rwLw4K70.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-DEwKjIxV.js → Chat-C478H8u9.js} +5 -5
  11. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BOqHkxK_.js → ChatBubbleRenderer-DNQsKN61.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-DYWCqYI9.js → Checkbox-D-47X635.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-BlXrfZAJ.js → Codegen-Cb9Ihed5.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-DLPM22eX.js → Col-CQsdzczt.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-PFyzqijs.js → Community-DiqzeAy-.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-7DIfY5Wp.js → Compact-Bq-APyyF.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-DF4CinPU.js → Compliance-Dnb1YxPr.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-B1J80Vcj.js → Cowork-CZljerdQ.js} +3 -3
  19. package/src/assets/web-panel/assets/{Cron-B7sx2OXX.js → Cron-gAdbZOq7.js} +2 -2
  20. package/src/assets/web-panel/assets/{Crosschain-omLkxmu-.js → Crosschain-DMPGXttD.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-B_7r7b5F.js → DID-C7dBDAv8.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dashboard-Cp7k3GZg.js → Dashboard-ByR4VcF8.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-BCKO89Y8.js → Dropdown-Bc4tbiQN.js} +1 -1
  24. package/src/assets/web-panel/assets/{EmailListRenderer-CNgTSsFZ.js → EmailListRenderer-BhUN2pDw.js} +1 -1
  25. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DobM83JP.js → FamilyGuardDashboard-DpJuANCD.js} +1 -1
  26. package/src/assets/web-panel/assets/{Federation-XVAYQIeu.js → Federation-BEm4TvcE.js} +1 -1
  27. package/src/assets/web-panel/assets/{FormItemContext-DV5ka1KQ.js → FormItemContext-JnkPkhiC.js} +1 -1
  28. package/src/assets/web-panel/assets/{GenericCardRenderer-Dg5q-KpC.js → GenericCardRenderer-BfCzFUIC.js} +1 -1
  29. package/src/assets/web-panel/assets/{Git-Dsn3Xhxf.js → Git-1c0MWpmD.js} +2 -2
  30. package/src/assets/web-panel/assets/{Governance-D06S4Qow.js → Governance-C_j3EBpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{Inference-nAvwxUXy.js → Inference-Cb7XRgtY.js} +1 -1
  32. package/src/assets/web-panel/assets/{KnowledgeGraph-CtqRP_rF.js → KnowledgeGraph-DoHPvHyK.js} +1 -1
  33. package/src/assets/web-panel/assets/Logs-CYriKpy-.js +2 -0
  34. package/src/assets/web-panel/assets/{Marketplace-CaeY23Kj.js → Marketplace-BT56-GD0.js} +1 -1
  35. package/src/assets/web-panel/assets/{McpTools-C2HHnwnE.js → McpTools-B6XX_wnZ.js} +3 -3
  36. package/src/assets/web-panel/assets/{Memory-CWBrdKlR.js → Memory-DRgNuaQc.js} +2 -2
  37. package/src/assets/web-panel/assets/{MobileBridge-CBLQ8uCY.js → MobileBridge-B0qgvBN2.js} +1 -1
  38. package/src/assets/web-panel/assets/MobileProjects-CRRfswf7.js +1 -0
  39. package/src/assets/web-panel/assets/{Mtc-BXur-euo.js → Mtc-DnSFj9jw.js} +4 -4
  40. package/src/assets/web-panel/assets/{MtcAudit-CpQSlOQC.js → MtcAudit-c0tuz1sm.js} +5 -5
  41. package/src/assets/web-panel/assets/{Multisig-DlFwdEOA.js → Multisig-CVLBGioX.js} +3 -3
  42. package/src/assets/web-panel/assets/{NLProgramming-DSh7fevc.js → NLProgramming-CFaqmNbx.js} +1 -1
  43. package/src/assets/web-panel/assets/{Notes-Bv4NOVxg.js → Notes-BM_mNwU_.js} +3 -3
  44. package/src/assets/web-panel/assets/{NotificationSettings-CzHNnIfa.js → NotificationSettings-Sa1k3ReS.js} +1 -1
  45. package/src/assets/web-panel/assets/{OrderTableRenderer-D7pHfKK4.js → OrderTableRenderer-lWzmtqBh.js} +1 -1
  46. package/src/assets/web-panel/assets/{Organization-COzV01ed.js → Organization-C2blcq-P.js} +4 -4
  47. package/src/assets/web-panel/assets/{Overflow-CYRZJb2_.js → Overflow-B3PwOJnK.js} +1 -1
  48. package/src/assets/web-panel/assets/{P2P-DFm49FE0.js → P2P-DaB9T6tb.js} +2 -2
  49. package/src/assets/web-panel/assets/{PdhVaultBrowser-Ctr-6k5B.js → PdhVaultBrowser-BpEBZ72n.js} +5 -5
  50. package/src/assets/web-panel/assets/{Permissions-DXVrhFyv.js → Permissions-BTkWInyH.js} +4 -4
  51. package/src/assets/web-panel/assets/{PersonalDataHub-BO5utpLK.js → PersonalDataHub-LHEwNmyL.js} +2 -2
  52. package/src/assets/web-panel/assets/{Pipeline-C9irYCg7.js → Pipeline-DvWIxqH-.js} +1 -1
  53. package/src/assets/web-panel/assets/{Privacy-r13hrvoF.js → Privacy-BDbpBagU.js} +1 -1
  54. package/src/assets/web-panel/assets/{ProjectInit-PRKNPZZC.js → ProjectInit-DLeMDWWv.js} +2 -2
  55. package/src/assets/web-panel/assets/{ProjectSettings-QvxM1ZDO.js → ProjectSettings-BK3NsxIz.js} +2 -2
  56. package/src/assets/web-panel/assets/Projects-BPWPg9zA.js +1 -0
  57. package/src/assets/web-panel/assets/{Providers-DxbrccZ7.js → Providers-D2EvmPAd.js} +1 -1
  58. package/src/assets/web-panel/assets/{QrScannerModal-BMHVRxBX.js → QrScannerModal-DAcu2fNg.js} +1 -1
  59. package/src/assets/web-panel/assets/{QuickAsk-Co3_ndAH.js → QuickAsk-B7U850Yt.js} +1 -1
  60. package/src/assets/web-panel/assets/{Recommend-Cv3UWR6s.js → Recommend-bxNXLzOR.js} +1 -1
  61. package/src/assets/web-panel/assets/{RemoteSession-CSDsO2zA.js → RemoteSession-BsCjAfSJ.js} +2 -2
  62. package/src/assets/web-panel/assets/{Reputation-Bdj59vzM.js → Reputation-DZ9LPu-R.js} +1 -1
  63. package/src/assets/web-panel/assets/{Row-CejfUjmo.js → Row-cIYkCB3Y.js} +1 -1
  64. package/src/assets/web-panel/assets/{RssFeed-C83yKkvU.js → RssFeed-BxTNTtTp.js} +2 -2
  65. package/src/assets/web-panel/assets/{Search-Ck4l_VI3.js → Search-DSar6GhE.js} +1 -1
  66. package/src/assets/web-panel/assets/{Security-DGIIEx6K.js → Security-oCbIGysL.js} +4 -4
  67. package/src/assets/web-panel/assets/{Services-Cj2aNAy3.js → Services-D8yojrNv.js} +2 -2
  68. package/src/assets/web-panel/assets/{Skeleton-Dlyy8akb.js → Skeleton-vTA6P1eL.js} +1 -1
  69. package/src/assets/web-panel/assets/{Skills-C4aDa9Zh.js → Skills-BXLf_KgZ.js} +1 -1
  70. package/src/assets/web-panel/assets/{Sla-tHd_Bauo.js → Sla-Cpwxzz__.js} +1 -1
  71. package/src/assets/web-panel/assets/{SpeechSettings-DI7R0Qgd.js → SpeechSettings-DcPN9kCb.js} +1 -1
  72. package/src/assets/web-panel/assets/{SyncSettings-OOxiPdsE.js → SyncSettings-DY0U5Vuj.js} +2 -2
  73. package/src/assets/web-panel/assets/{Tasks-Nro_Ltg5.js → Tasks-DKu3-sZJ.js} +1 -1
  74. package/src/assets/web-panel/assets/{Templates-Bm7eSMWH.js → Templates-MD3nfWGm.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tenant-B8F8eFvD.js → Tenant-DKVnyGXM.js} +1 -1
  76. package/src/assets/web-panel/assets/{Terminal-2oWhR7QF.js → Terminal-DQMIZfWf.js} +2 -2
  77. package/src/assets/web-panel/assets/{TimelineRenderer-GLnecmpd.js → TimelineRenderer-CugmNZTs.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tokens-CtpFyati.js → Tokens-Cjvlttu6.js} +1 -1
  79. package/src/assets/web-panel/assets/{Trigger-DGkXZzbN.js → Trigger-CzNOEcoI.js} +1 -1
  80. package/src/assets/web-panel/assets/{Trust-ClYZMkXN.js → Trust-D5jg9iPA.js} +1 -1
  81. package/src/assets/web-panel/assets/{UkeySign-C1AuEW5-.js → UkeySign-59bMlvxY.js} +1 -1
  82. package/src/assets/web-panel/assets/{VideoEditing-DHa9ekSK.js → VideoEditing-DmCzSBqn.js} +1 -1
  83. package/src/assets/web-panel/assets/{Wallet-CyQv8ZAN.js → Wallet-DoFe8V6W.js} +3 -3
  84. package/src/assets/web-panel/assets/{WebAuthn-DPxEEb5Y.js → WebAuthn-9POLER-w.js} +4 -4
  85. package/src/assets/web-panel/assets/{WorkflowEditor-C-fCM8Si.js → WorkflowEditor-cFQH0Og6.js} +1 -1
  86. package/src/assets/web-panel/assets/{chat-BMu1Pk8B.js → chat-D3fR2NkZ.js} +1 -1
  87. package/src/assets/web-panel/assets/{colors-DYPOXyWQ.js → colors-DiLEwE_P.js} +1 -1
  88. package/src/assets/web-panel/assets/{compact-item-C5r_plPk.js → compact-item-CGfFDdic.js} +1 -1
  89. package/src/assets/web-panel/assets/{createContext-9fWrWmuJ.js → createContext-BbIbOPL2.js} +1 -1
  90. package/src/assets/web-panel/assets/devWarning-B6FRgsmP.js +1 -0
  91. package/src/assets/web-panel/assets/{hasIn-CjZM2-qE.js → hasIn-DqyWp63_.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DWwI0Jjd.js → index-BCoDp6o_.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-Co9kBFxY.js → index-BKeRBUtO.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DjTB4wPn.js → index-BKxvHCqz.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-B56CI20h.js → index-BiLP6SNu.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DNxR1CHs.js → index-BtcjYHgn.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CcDGi9U1.js → index-BtwvOuvO.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CJJx0kbR.js → index-ByE5tKjP.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-phHPSXlV.js → index-C1S30j-Z.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BsHmE__1.js → index-C2lZXIEA.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DLCoKst9.js → index-CH8gSMSA.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-jO4lIpFE.js → index-CHpI6g_S.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-0DVMoDzF.js → index-CIleIMTT.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Bti4lpw5.js → index-CToOzfR2.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-D6zyUpD6.js → index-CZQshOyI.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-D0rFX-xN.js → index-ComvO4hy.js} +1 -1
  107. package/src/assets/web-panel/assets/index-Cq411qtc.js +1 -0
  108. package/src/assets/web-panel/assets/{index-BPucc_ES.js → index-CweXQM71.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CTnaRErh.js → index-CySlHabI.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-B_bTdeou.js → index-D16FSRMW.js} +1 -1
  111. package/src/assets/web-panel/assets/index-D1oX0DK3.js +1 -0
  112. package/src/assets/web-panel/assets/{index-Du-w2i6G.js → index-D3vQv3Kq.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-I3Qdrfcf.js → index-DH6qaU1a.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Cd9_KCPs.js → index-DPxmTldu.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-Mipa7XgU.js → index-DQH--Uw5.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BBVCXmJV.js → index-Db9UJVjj.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CDaA4A0b.js → index-DdLwxj-F.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CyUtBxnC.js → index-DdjXemK-.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-ByVDaARk.js → index-DzuGkFvy.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BVFtY8Y4.js → index-FFlp8Jx9.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DJk9cPrs.js → index-Km36XQ3z.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BW-x3mUK.js → index-auI9fxYH.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B1iUe3Ba.js → index-fCfaVIr7.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-HJdfPSMz.js → index-hVGbmc7y.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CYoS2cwK.js → index-kL8f4MRS.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-C3E7xVl1.js → index-ns6bNnGo.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Bglw_kmu.js → index-qHvMk0U3.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CvUR6l7C.js → index-rTrejDjk.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-oerotzoq.js → index-tLaW5UzZ.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CGqrVLWe.js → index-xm1KHUEQ.js} +3 -3
  131. package/src/assets/web-panel/assets/{initDefaultProps-B7tpABc_.js → initDefaultProps-pg_7pnd6.js} +1 -1
  132. package/src/assets/web-panel/assets/{motion-DmvaRoVv.js → motion-B5GoJSZL.js} +1 -1
  133. package/src/assets/web-panel/assets/{move-DF4X29Wf.js → move-BaJoe2FW.js} +1 -1
  134. package/src/assets/web-panel/assets/{mtc-parser-C0cbg4PO.js → mtc-parser-CiQGbqtr.js} +1 -1
  135. package/src/assets/web-panel/assets/{omit-DZzcYy0l.js → omit-BFNEsKvU.js} +1 -1
  136. package/src/assets/web-panel/assets/{pickAttrs-DaZWfzuH.js → pickAttrs-YbSoANHm.js} +1 -1
  137. package/src/assets/web-panel/assets/{placementArrow-CBxOEyvn.js → placementArrow-C40MJPIH.js} +1 -1
  138. package/src/assets/web-panel/assets/{responsiveObserve-CGl8NIlO.js → responsiveObserve-LaVz2zF6.js} +1 -1
  139. package/src/assets/web-panel/assets/{slide-Bv330MSZ.js → slide-BkSoAGxF.js} +1 -1
  140. package/src/assets/web-panel/assets/{statusUtils-DJVy5oEM.js → statusUtils-C4jWjohA.js} +1 -1
  141. package/src/assets/web-panel/assets/{styleChecker-BiY1H5ST.js → styleChecker-BGqeIh-m.js} +1 -1
  142. package/src/assets/web-panel/assets/{useFlexGapSupport-D1sN2OlQ.js → useFlexGapSupport-JsR5NMrM.js} +1 -1
  143. package/src/assets/web-panel/assets/{useFs-DxxHawzW.js → useFs-DOiP38RR.js} +1 -1
  144. package/src/assets/web-panel/assets/{usePersonalDataHub-C1HblLrD.js → usePersonalDataHub-C-nC0ymt.js} +1 -1
  145. package/src/assets/web-panel/assets/{vnode-Dex0jy4T.js → vnode-BalilHOU.js} +1 -1
  146. package/src/assets/web-panel/assets/{zoom-Bk1MScAD.js → zoom-DjUELqks.js} +1 -1
  147. package/src/assets/web-panel/index.html +1 -1
  148. package/src/commands/team.js +34 -0
  149. package/src/data/changelog.json +7 -2
  150. package/src/harness/mcp-client.js +115 -1
  151. package/src/lib/agent-team/team-runner.js +20 -0
  152. package/src/lib/config-manager.js +14 -1
  153. package/src/lib/sub-agent-context.js +28 -7
  154. package/src/lib/telemetry/span-recorder.js +13 -1
  155. package/src/repl/agent-repl.js +52 -13
  156. package/src/repl/permission-prompt.js +58 -0
  157. package/src/runtime/agent-core.js +236 -1
  158. package/src/runtime/coding-agent-contract-shared.cjs +5 -0
  159. package/src/assets/web-panel/assets/Logs-J5aGAyfY.js +0 -2
  160. package/src/assets/web-panel/assets/MobileProjects-Q_Cy_W4_.js +0 -1
  161. package/src/assets/web-panel/assets/Projects-DfgmsN3j.js +0 -1
  162. package/src/assets/web-panel/assets/devWarning-DmRz5Pet.js +0 -1
  163. package/src/assets/web-panel/assets/index-CrsL7YBW.js +0 -1
  164. package/src/assets/web-panel/assets/index-zW69WSDA.js +0 -1
@@ -336,13 +336,19 @@ export class SubAgentContext {
336
336
 
337
337
  // Check abort signal
338
338
  if (this._signal?.aborted) {
339
- this.forceComplete("cancelled");
339
+ this.forceComplete("cancelled", {
340
+ partialContent: lastContent,
341
+ artifacts,
342
+ });
340
343
  break;
341
344
  }
342
345
 
343
346
  // Enforce token budget
344
347
  if (this.tokenBudget && this._tokenCount >= this.tokenBudget) {
345
- this.forceComplete("token-budget-exceeded");
348
+ this.forceComplete("token-budget-exceeded", {
349
+ partialContent: lastContent,
350
+ artifacts,
351
+ });
346
352
  break;
347
353
  }
348
354
 
@@ -355,9 +361,17 @@ export class SubAgentContext {
355
361
  } catch (err) {
356
362
  this.status = "failed";
357
363
  this.completedAt = new Date().toISOString();
364
+ // Return partial work to the parent instead of discarding it: the
365
+ // summary is the only channel the parent model sees, so a mid-run API
366
+ // error (rate limit, network drop) must not erase what was already
367
+ // produced. Artifacts collected before the failure are kept as-is.
368
+ const partial =
369
+ lastContent && lastContent.length > 0
370
+ ? `\n\nPartial output before failure:\n${this.summarize(lastContent)}`
371
+ : "";
358
372
  this.result = {
359
- summary: `Sub-agent failed: ${err.message}`,
360
- artifacts: [],
373
+ summary: `Sub-agent failed: ${err.message}${partial}`,
374
+ artifacts,
361
375
  tokenCount: this._tokenCount,
362
376
  toolsUsed: [...new Set(this._toolsUsed)],
363
377
  iterationCount: this._iterationCount,
@@ -447,15 +461,22 @@ export class SubAgentContext {
447
461
  /**
448
462
  * Force-complete this sub-agent (e.g. on timeout or parent cancellation).
449
463
  * @param {string} [reason] - Reason for force-completion
464
+ * @param {{partialContent?: string, artifacts?: Array}} [partial] - Work
465
+ * produced before the cutoff; returned to the parent instead of being
466
+ * discarded (a truncated run should still hand over what it has).
450
467
  */
451
- forceComplete(reason = "forced") {
468
+ forceComplete(reason = "forced", partial = {}) {
452
469
  if (this.status === "active") {
453
470
  this.status = "completed";
454
471
  this.completedAt = new Date().toISOString();
455
472
  if (!this.result) {
473
+ const partialText =
474
+ partial.partialContent && partial.partialContent.length > 0
475
+ ? `\n\nPartial output before cutoff:\n${this.summarize(partial.partialContent)}`
476
+ : "";
456
477
  this.result = {
457
- summary: `(Sub-agent force-completed: ${reason})`,
458
- artifacts: [],
478
+ summary: `(Sub-agent force-completed: ${reason})${partialText}`,
479
+ artifacts: Array.isArray(partial.artifacts) ? partial.artifacts : [],
459
480
  tokenCount: this._tokenCount,
460
481
  toolsUsed: [...new Set(this._toolsUsed)],
461
482
  iterationCount: this._iterationCount,
@@ -41,15 +41,27 @@ export class TelemetryRecorder {
41
41
  constructor({
42
42
  now = () => Date.now(),
43
43
  serviceName = "chainlesschain-cli",
44
+ defaultAttributes = {},
44
45
  } = {}) {
45
46
  this._now = typeof now === "function" ? now : () => now;
46
47
  this.serviceName = serviceName;
47
48
  this.traceId = newTraceId(); // one trace per recorder (valid non-zero id)
49
+ // Stamped onto EVERY span (per-span attributes win on key collision).
50
+ // Used for run-level correlation: workflow.run_id / workflow.name let a
51
+ // collector group all model/tool/task spans of one run (Claude-Code
52
+ // 2.1.202 workflow-tracing attributes).
53
+ this.defaultAttributes = { ...defaultAttributes };
48
54
  this._spans = []; // completed spans
49
55
  this._counters = new Map(); // name → { total, byAttr }
50
56
  this._failures = new Map(); // category → count
51
57
  }
52
58
 
59
+ /** Set (or overwrite) an attribute stamped onto every span from now on. */
60
+ setDefaultAttribute(key, value) {
61
+ this.defaultAttributes[key] = value;
62
+ return this;
63
+ }
64
+
53
65
  /**
54
66
  * Start a span. Returns a handle; call `.end()` (optionally with a status /
55
67
  * extra attributes) to record it. Nesting is expressed via `parentId`.
@@ -57,7 +69,7 @@ export class TelemetryRecorder {
57
69
  startSpan(name, attributes = {}, { parentId = null } = {}) {
58
70
  const id = spanId();
59
71
  const start = this._now();
60
- const attrs = { ...attributes };
72
+ const attrs = { ...this.defaultAttributes, ...attributes };
61
73
  const events = [];
62
74
  const self = this;
63
75
  let ended = false;
@@ -105,7 +105,11 @@ import { parseThinkCommand, parseEffortCommand } from "./think-command.js";
105
105
  import { parseBtwCommand, buildAsideBlock, applyAside } from "./btw-command.js";
106
106
  import { shouldStreamLive } from "./stream-decision.js";
107
107
  import { emptyTurnNotice } from "./empty-turn-notice.js";
108
- import { buildPermissionPrompt } from "./permission-prompt.js";
108
+ import {
109
+ buildPermissionPrompt,
110
+ resolveAskIdleTimeoutMs,
111
+ questionWithIdleTimeout,
112
+ } from "./permission-prompt.js";
109
113
  import {
110
114
  parsePermissionTier,
111
115
  describeTier,
@@ -425,11 +429,17 @@ export async function startAgentRepl(options = {}) {
425
429
  // CC_AUTO_PIN env ("1"/"0") > config `context.autoPin` (true/false/object) >
426
430
  // default on. See resolveAutoPinOption.
427
431
  let _autoPinCfgValue;
432
+ // Idle timeout for interactive permission prompts (0 = wait forever).
433
+ // CC_PERMISSION_ASK_TIMEOUT_MS env > config permissions.askTimeoutMs > off.
434
+ let _askIdleTimeoutMs = resolveAskIdleTimeoutMs();
428
435
  try {
429
436
  const { loadConfig } = await import("../lib/config-manager.js");
430
437
  const _cfg = loadConfig();
431
438
  _visionModel = _cfg?.llm?.visionModel || undefined;
432
439
  _autoPinCfgValue = _cfg?.context?.autoPin;
440
+ _askIdleTimeoutMs = resolveAskIdleTimeoutMs({
441
+ config: _cfg?.permissions?.askTimeoutMs,
442
+ });
433
443
  const raw = _cfg?.llm?.streamStallTimeoutMs;
434
444
  const t = Number(raw);
435
445
  // Accept 0 (explicit disable) — only ignore absent/invalid values.
@@ -559,17 +569,24 @@ export async function startAgentRepl(options = {}) {
559
569
  });
560
570
  const q = (p) => new Promise((res) => rlConfirm.question(p, res));
561
571
  const cmd = args?.command ? ` ${args.command}` : "";
562
- const ans = (
563
- await q(
572
+ const res = await questionWithIdleTimeout(
573
+ q,
574
+ chalk.yellow(
575
+ `\n[ApprovalGate] ${riskLevel || "medium"} risk command:${cmd}\n` +
576
+ ` Proceed? [y]es once / [a]lways allow / [N]o: `,
577
+ ),
578
+ _askIdleTimeoutMs,
579
+ );
580
+ rlConfirm.close();
581
+ if (res.timedOut) {
582
+ process.stdout.write(
564
583
  chalk.yellow(
565
- `\n[ApprovalGate] ${riskLevel || "medium"} risk command:${cmd}\n` +
566
- ` Proceed? [y]es once / [a]lways allow / [N]o: `,
584
+ `\n no response in ${_askIdleTimeoutMs}ms auto-denied\n`,
567
585
  ),
568
- )
569
- )
570
- .trim()
571
- .toLowerCase();
572
- rlConfirm.close();
586
+ );
587
+ return false;
588
+ }
589
+ const ans = res.answer.trim().toLowerCase();
573
590
  if (ans === "a" || ans === "always") {
574
591
  const saved = await _persistAlwaysAllow(tool || "run_shell", args);
575
592
  if (saved) {
@@ -625,10 +642,21 @@ export async function startAgentRepl(options = {}) {
625
642
  // (settings/hook ask) or a `reason` (destructive-git / sensitive-file
626
643
  // guards) — avoids the literal "null" the old template printed.
627
644
  const header = buildPermissionPrompt({ tool, args, rule, reason });
628
- const ans = (await q(chalk.yellow(`\n${header}\n Proceed? (y/N) `)))
629
- .trim()
630
- .toLowerCase();
645
+ const res = await questionWithIdleTimeout(
646
+ q,
647
+ chalk.yellow(`\n${header}\n Proceed? (y/N) `),
648
+ _askIdleTimeoutMs,
649
+ );
631
650
  rl.close();
651
+ if (res.timedOut) {
652
+ process.stdout.write(
653
+ chalk.yellow(
654
+ `\n ⏱ no response in ${_askIdleTimeoutMs}ms — auto-denied\n`,
655
+ ),
656
+ );
657
+ return false;
658
+ }
659
+ const ans = res.answer.trim().toLowerCase();
632
660
  return ans === "y" || ans === "yes";
633
661
  };
634
662
  } catch (_err) {
@@ -2383,6 +2411,17 @@ export async function startAgentRepl(options = {}) {
2383
2411
  const expanded = target.replace(/^~(?=$|[\\/])/, os.homedir());
2384
2412
  process.chdir(path.resolve(process.cwd(), expanded));
2385
2413
  logger.log(chalk.green(`cwd → ${process.cwd()}`));
2414
+ // MCP roots derive from cwd — tell connected servers to re-query
2415
+ // roots/list (Claude-Code 2.1.203 change-notification parity).
2416
+ for (const c of [_adhocMcp?.mcpClient, _bundleMcpClient]) {
2417
+ if (c && typeof c.notifyRootsListChanged === "function") {
2418
+ try {
2419
+ c.notifyRootsListChanged();
2420
+ } catch {
2421
+ /* best-effort */
2422
+ }
2423
+ }
2424
+ }
2386
2425
  } catch (err) {
2387
2426
  logger.error(`/cd failed: ${err.message}`);
2388
2427
  }
@@ -24,3 +24,61 @@ export function buildPermissionPrompt({ tool, args, rule, reason } = {}) {
24
24
  if (reason) return `[Permission] ${reason}`;
25
25
  return `[Permission] confirm ${tool}:${detail}`;
26
26
  }
27
+
28
+ /**
29
+ * Resolve the idle timeout (ms) for interactive permission prompts.
30
+ *
31
+ * An unanswered prompt blocks the whole agent turn forever (e.g. the user
32
+ * walked away mid-run). With a timeout configured, the prompt auto-denies
33
+ * after `ms` of silence — deny is the only safe unattended answer.
34
+ *
35
+ * Precedence: CC_PERMISSION_ASK_TIMEOUT_MS env > config
36
+ * `permissions.askTimeoutMs` > default 0 (disabled — waits forever, the
37
+ * historical behavior). Non-finite / non-positive values disable it.
38
+ *
39
+ * @param {{env?: string, config?: unknown}} [opts] - injectable for tests
40
+ * @returns {number} timeout in ms, 0 = disabled
41
+ */
42
+ export function resolveAskIdleTimeoutMs({ env, config } = {}) {
43
+ const envRaw =
44
+ env !== undefined ? env : process.env.CC_PERMISSION_ASK_TIMEOUT_MS;
45
+ const candidate =
46
+ envRaw !== undefined && envRaw !== null && envRaw !== ""
47
+ ? Number(envRaw)
48
+ : typeof config === "number" || typeof config === "string"
49
+ ? Number(config)
50
+ : NaN; // booleans/objects are not a timeout — disabled
51
+ return Number.isFinite(candidate) && candidate > 0 ? candidate : 0;
52
+ }
53
+
54
+ /**
55
+ * Race an interactive question against an idle timeout.
56
+ *
57
+ * `ask` is the readline-question-as-promise (never rejects). On timeout the
58
+ * caller must still close its readline interface; the stranded question
59
+ * callback becomes a no-op once the interface is closed.
60
+ *
61
+ * @param {(prompt: string) => Promise<string>} ask
62
+ * @param {string} prompt
63
+ * @param {number} timeoutMs - 0/negative = no timeout (plain await)
64
+ * @returns {Promise<{answer: string|null, timedOut: boolean}>}
65
+ */
66
+ export async function questionWithIdleTimeout(ask, prompt, timeoutMs) {
67
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
68
+ return { answer: await ask(prompt), timedOut: false };
69
+ }
70
+ let timer = null;
71
+ try {
72
+ return await Promise.race([
73
+ ask(prompt).then((answer) => ({ answer, timedOut: false })),
74
+ new Promise((res) => {
75
+ timer = setTimeout(
76
+ () => res({ answer: null, timedOut: true }),
77
+ timeoutMs,
78
+ );
79
+ }),
80
+ ]);
81
+ } finally {
82
+ if (timer) clearTimeout(timer);
83
+ }
84
+ }
@@ -1443,6 +1443,8 @@ export async function executeTool(name, args, context = {}) {
1443
1443
  subAgentBudget: context.subAgentBudget || null,
1444
1444
  interactiveApproval: context.interactiveApproval || false,
1445
1445
  settingsHooks: context.settingsHooks || null,
1446
+ signal: context.signal || null,
1447
+ backgroundSubAgents: context.backgroundSubAgents || null,
1446
1448
  });
1447
1449
  } catch (err) {
1448
1450
  if (hookDb) {
@@ -1541,7 +1543,10 @@ export async function executeTool(name, args, context = {}) {
1541
1543
  name === "spawn_sub_agent" &&
1542
1544
  context.settingsHooks &&
1543
1545
  toolResult &&
1544
- typeof toolResult === "object"
1546
+ typeof toolResult === "object" &&
1547
+ // Background spawns return a "running" handle here — their SubagentStop
1548
+ // fires later, when the RESULT is drained into the conversation.
1549
+ !(toolResult.background === true && toolResult.status === "running")
1545
1550
  ) {
1546
1551
  try {
1547
1552
  const outcome = runObserveHooks(
@@ -2056,6 +2061,8 @@ async function executeToolInner(
2056
2061
  subAgentBudget = null,
2057
2062
  interactiveApproval = false,
2058
2063
  settingsHooks = null,
2064
+ signal = null,
2065
+ backgroundSubAgents = null,
2059
2066
  },
2060
2067
  ) {
2061
2068
  const localToolDescriptor =
@@ -2777,6 +2784,8 @@ async function executeToolInner(
2777
2784
  subAgentDepth,
2778
2785
  subAgentBudget,
2779
2786
  settingsHooks,
2787
+ signal,
2788
+ backgroundSubAgents,
2780
2789
  }),
2781
2790
  );
2782
2791
  }
@@ -3703,6 +3712,46 @@ export function safeStringifyToolResult(value) {
3703
3712
  * @param {object} ctx - { skillLoader, cwd, parentMessages, interaction, sessionId }
3704
3713
  * @returns {Promise<object>}
3705
3714
  */
3715
+ /**
3716
+ * Remove and return every SETTLED background sub-agent entry from the run's
3717
+ * map. Called by agentLoop before each LLM call (deliver fresh results) and
3718
+ * after the end-of-run wait (deliver stragglers).
3719
+ */
3720
+ function _takeSettledBackgroundSubAgents(map) {
3721
+ const done = [];
3722
+ for (const [id, entry] of map) {
3723
+ if (entry.settled) {
3724
+ done.push(entry);
3725
+ map.delete(id);
3726
+ }
3727
+ }
3728
+ return done;
3729
+ }
3730
+
3731
+ /**
3732
+ * Render a settled background sub-agent's outcome as the user-role message
3733
+ * injected into the parent conversation (the only channel that reaches the
3734
+ * model between turns — there is no open tool_call to attach a result to).
3735
+ */
3736
+ function _backgroundSubAgentResultText(entry) {
3737
+ const o = entry.outcome || {};
3738
+ const status = o.error ? "FAILED" : "completed";
3739
+ const summary =
3740
+ (o.result && o.result.summary) || o.error || "(no output from sub-agent)";
3741
+ const tools =
3742
+ o.result && Array.isArray(o.result.toolsUsed) && o.result.toolsUsed.length
3743
+ ? `\nTools used: ${o.result.toolsUsed.join(", ")}`
3744
+ : "";
3745
+ const feedback = entry.hookFeedback
3746
+ ? `\nHook feedback: ${entry.hookFeedback}`
3747
+ : "";
3748
+ return (
3749
+ `[Background sub-agent "${entry.role}" (${entry.id}) ${status}]\n` +
3750
+ `Task: ${entry.task}\n` +
3751
+ `Result:\n${summary}${tools}${feedback}`
3752
+ );
3753
+ }
3754
+
3706
3755
  async function _executeSpawnSubAgent(args, ctx) {
3707
3756
  // Nesting cap: refuse before any context/registry work.
3708
3757
  const currentDepth = ctx.subAgentDepth || 0;
@@ -3897,6 +3946,88 @@ async function _executeSpawnSubAgent(args, ctx) {
3897
3946
  }
3898
3947
  }
3899
3948
 
3949
+ // ── Background mode (Claude-Code 2.1.198 parity) ────────────────────────
3950
+ // Return a running handle immediately; the parent loop keeps working and
3951
+ // drains the result into the conversation when it settles (agentLoop also
3952
+ // refuses to finish while any background sub-agent is still running). Only
3953
+ // available when the calling loop provided the per-run map — a bare
3954
+ // executeTool() without it falls through to the blocking path.
3955
+ if (args.background === true && ctx.backgroundSubAgents instanceof Map) {
3956
+ // Cancel with the parent: forward the loop's abort signal so killing the
3957
+ // run doesn't orphan a detached child mid-LLM-call.
3958
+ subCtx._signal = subCtx._signal || ctx.signal || null;
3959
+ if (registry) {
3960
+ try {
3961
+ registry.register(subCtx);
3962
+ } catch (_err) {
3963
+ // Registry not available — non-critical
3964
+ }
3965
+ }
3966
+ emit("sub-agent.started", {
3967
+ task: subCtx.task,
3968
+ background: true,
3969
+ allowedTools: allowedTools || null,
3970
+ maxIterations: subCtx.maxIterations,
3971
+ createdAt: subCtx.createdAt,
3972
+ });
3973
+ const entry = {
3974
+ id: subCtx.id,
3975
+ role: subCtx.role,
3976
+ task: subCtx.task,
3977
+ settled: false,
3978
+ outcome: null,
3979
+ hookFeedback: null,
3980
+ promise: null,
3981
+ };
3982
+ // Settle-capture wrapper: the stored promise NEVER rejects, so an
3983
+ // unconsumed handle can't surface as an unhandled rejection.
3984
+ entry.promise = subCtx
3985
+ .run(task)
3986
+ .then(
3987
+ (result) => ({ result, error: null }),
3988
+ (err) => {
3989
+ subCtx.forceComplete(err.message);
3990
+ return { result: subCtx.result, error: err.message };
3991
+ },
3992
+ )
3993
+ .then((outcome) => {
3994
+ entry.settled = true;
3995
+ entry.outcome = outcome;
3996
+ if (registry) {
3997
+ try {
3998
+ registry.complete(subCtx.id, outcome.result);
3999
+ } catch (_err) {
4000
+ // Non-critical
4001
+ }
4002
+ }
4003
+ emit(outcome.error ? "sub-agent.failed" : "sub-agent.completed", {
4004
+ status: subCtx.status,
4005
+ background: true,
4006
+ ...(outcome.error
4007
+ ? { error: outcome.error }
4008
+ : {
4009
+ summary: outcome.result?.summary,
4010
+ toolsUsed: outcome.result?.toolsUsed,
4011
+ iterationCount: outcome.result?.iterationCount,
4012
+ tokenCount: outcome.result?.tokenCount,
4013
+ artifactCount: outcome.result?.artifacts?.length || 0,
4014
+ }),
4015
+ completedAt: subCtx.completedAt,
4016
+ });
4017
+ return outcome;
4018
+ });
4019
+ ctx.backgroundSubAgents.set(subCtx.id, entry);
4020
+ return {
4021
+ success: true,
4022
+ background: true,
4023
+ status: "running",
4024
+ subAgentId: subCtx.id,
4025
+ role: subCtx.role,
4026
+ parentSessionId,
4027
+ note: "Sub-agent is running in the background. Its result will be delivered to you automatically in a later turn — continue with other work; the run will not finish before the result arrives.",
4028
+ };
4029
+ }
4030
+
3900
4031
  try {
3901
4032
  // Notify registry if available
3902
4033
  if (registry) {
@@ -5385,7 +5516,17 @@ export async function* agentLoop(messages, options) {
5385
5516
  spawned: 0,
5386
5517
  max: MAX_SUB_AGENTS_PER_RUN,
5387
5518
  },
5519
+ // Abort signal — forwarded to background sub-agents so cancelling the
5520
+ // parent run also cancels children still running detached.
5521
+ signal,
5522
+ // Background sub-agents spawned THIS loop (spawn_sub_agent background:true).
5523
+ // id → { id, role, task, promise, settled, outcome }. Results are drained
5524
+ // into `messages` before each LLM call; the loop refuses to finish while
5525
+ // any are still running (it waits, injects, and gives the model one more
5526
+ // turn) so a background result can never be silently lost.
5527
+ backgroundSubAgents: new Map(),
5388
5528
  };
5529
+ const backgroundSubAgents = toolContext.backgroundSubAgents;
5389
5530
 
5390
5531
  throwIfAborted(signal);
5391
5532
 
@@ -5490,6 +5631,18 @@ export async function* agentLoop(messages, options) {
5490
5631
  const runId =
5491
5632
  options.runId ||
5492
5633
  `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5634
+ // Workflow-tracing attributes (Claude-Code 2.1.202): stamp the run id (and
5635
+ // an optional caller-provided workflow name) onto EVERY span this run emits,
5636
+ // so a collector can group one run's model/tool spans into one workflow.
5637
+ if (recorder && typeof recorder.setDefaultAttribute === "function") {
5638
+ recorder.setDefaultAttribute("workflow.run_id", runId);
5639
+ if (options.workflowName) {
5640
+ recorder.setDefaultAttribute(
5641
+ "workflow.name",
5642
+ String(options.workflowName),
5643
+ );
5644
+ }
5645
+ }
5493
5646
  yield {
5494
5647
  type: "run-started",
5495
5648
  runId,
@@ -5657,6 +5810,52 @@ export async function* agentLoop(messages, options) {
5657
5810
  }
5658
5811
  }
5659
5812
 
5813
+ // Deliver background sub-agent results that settled since the last turn:
5814
+ // inject them as user-role context so THIS LLM call sees them. (There is
5815
+ // no open tool_call to attach a late result to — the spawn call already
5816
+ // returned its "running" handle.)
5817
+ if (backgroundSubAgents.size > 0) {
5818
+ for (const entry of _takeSettledBackgroundSubAgents(
5819
+ backgroundSubAgents,
5820
+ )) {
5821
+ // SubagentStop fires at RESULT time for background spawns (the
5822
+ // spawn-time handle skips it); a block reason rides along as feedback.
5823
+ if (options.settingsHooks) {
5824
+ try {
5825
+ const outcome = runObserveHooks(
5826
+ options.settingsHooks,
5827
+ "SubagentStop",
5828
+ {
5829
+ stop_hook_active: false,
5830
+ session_id: options.sessionId || null,
5831
+ subagent_response: JSON.stringify(
5832
+ entry.outcome?.result || { error: entry.outcome?.error },
5833
+ ).substring(0, 2000),
5834
+ },
5835
+ { cwd: toolContext.cwd },
5836
+ );
5837
+ if (outcome.decision === "block" && outcome.reason) {
5838
+ entry.hookFeedback = outcome.reason;
5839
+ }
5840
+ } catch (_err) {
5841
+ // SubagentStop hooks are best-effort
5842
+ }
5843
+ }
5844
+ messages.push({
5845
+ role: "user",
5846
+ content: _backgroundSubAgentResultText(entry),
5847
+ });
5848
+ yield {
5849
+ type: "background-sub-agent-result",
5850
+ runId,
5851
+ subAgentId: entry.id,
5852
+ role: entry.role,
5853
+ error: entry.outcome?.error || null,
5854
+ summary: entry.outcome?.result?.summary || null,
5855
+ };
5856
+ }
5857
+ }
5858
+
5660
5859
  // Turn-scoped context injection (open-agents prepareCall parity).
5661
5860
  // prepareCall runs fresh each iteration and returns an ephemeral
5662
5861
  // system-message supplement that is NOT persisted to messages history.
@@ -5736,6 +5935,42 @@ export async function* agentLoop(messages, options) {
5736
5935
  const toolCalls = msg.tool_calls;
5737
5936
 
5738
5937
  if (!toolCalls || toolCalls.length === 0) {
5938
+ // A final answer while background sub-agents are still outstanding is
5939
+ // premature — their results must not be silently lost. Wait for ALL of
5940
+ // them, inject the results, and give the model one more turn to fold
5941
+ // them into its real final answer. The iteration budget is the backstop
5942
+ // if it keeps spawning more.
5943
+ if (backgroundSubAgents.size > 0) {
5944
+ yield {
5945
+ type: "waiting-background-sub-agents",
5946
+ runId,
5947
+ count: backgroundSubAgents.size,
5948
+ };
5949
+ await Promise.all(
5950
+ [...backgroundSubAgents.values()].map((e) => e.promise),
5951
+ );
5952
+ throwIfAborted(signal);
5953
+ messages.push({ role: "assistant", content: msg.content || "" });
5954
+ for (const entry of _takeSettledBackgroundSubAgents(
5955
+ backgroundSubAgents,
5956
+ )) {
5957
+ messages.push({
5958
+ role: "user",
5959
+ content:
5960
+ _backgroundSubAgentResultText(entry) +
5961
+ "\n\nAll background sub-agents have finished. Incorporate their results and give your final answer.",
5962
+ });
5963
+ yield {
5964
+ type: "background-sub-agent-result",
5965
+ runId,
5966
+ subAgentId: entry.id,
5967
+ role: entry.role,
5968
+ error: entry.outcome?.error || null,
5969
+ summary: entry.outcome?.result?.summary || null,
5970
+ };
5971
+ }
5972
+ continue;
5973
+ }
5739
5974
  // Surface the final answer's extended-thinking reasoning (Anthropic, when
5740
5975
  // --think is on) so non-streaming consumers (the REPL) can show it. The
5741
5976
  // streaming path forwards reasoning live via onThinking instead.
@@ -588,6 +588,11 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
588
588
  description:
589
589
  "Optional declarative profile (from sub-agent-profiles). When set, seeds systemPrompt / tool allowlist / iteration cap. Explicit `tools` overrides the profile allowlist.",
590
590
  },
591
+ background: {
592
+ type: "boolean",
593
+ description:
594
+ "Run the sub-agent in the BACKGROUND: the call returns immediately with a running handle and you continue working; the sub-agent's result is delivered to you automatically in a later turn (the run waits for stragglers before finishing). Use for independent subtasks you don't need before your next step.",
595
+ },
591
596
  },
592
597
  required: ["task"],
593
598
  },
@@ -1,2 +0,0 @@
1
- import{I as s,J as g,U as d,c as n,K as _,V as k,S as W,R as S,F as K,Z as Q,w as M,n as C,o as R,b as T,r,P as p,Q as O,_ as U}from"./vendor-BMxUs6UX.js";import{_ as q,u as N}from"./index-CGqrVLWe.js";import{R as E}from"./icons-BsDmGpcT.js";const j={__name:"Logs",setup(V,{expose:a}){a();const x=N(),e=r("status"),y=r(!1),v=r(""),c=r(""),i=r(""),f=r(!0),o=r(null),h={status:"status",doctor:"doctor","skill-sources":"skill sources","llm-providers":"llm providers"},m=T(()=>c.value.split(`
2
- `)),b=T(()=>{if(!i.value)return m.value;const t=i.value.toLowerCase();return m.value.filter(u=>u.toLowerCase().includes(t))});function L(t){return t.includes("✖")||t.includes("error")||t.includes("Error")||t.includes("failed")?"line-error":t.includes("✔")||t.includes("✓")||t.includes("success")||t.includes("running")?"line-success":t.includes("warn")||t.includes("Warn")||t.includes("○")?"line-warn":t.startsWith(" ")||t.startsWith(" ")?"line-indent":""}function l(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function w(t){if(!i.value)return t;const u=i.value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.replace(new RegExp(`(${u})`,"gi"),"<mark>$1</mark>")}async function B(){y.value=!0,v.value="",c.value="";const t=h[e.value]||"status";try{const{output:u}=await x.execute(t,3e4);c.value=u,f.value&&(await C(),o.value&&(o.value.scrollTop=o.value.scrollHeight))}catch(u){v.value=`执行失败: ${u.message}`,c.value=v.value}finally{y.value=!1}}M(b,async()=>{f.value&&(await C(),o.value&&(o.value.scrollTop=o.value.scrollHeight))}),R(B);const H={ws:x,activeTab:e,loading:y,error:v,rawOutput:c,searchQuery:i,autoScroll:f,logContainer:o,TAB_COMMANDS:h,allLines:m,filteredLines:b,lineClass:L,escapeHtml:l,highlightSearch:w,loadLog:B,ref:r,computed:T,watch:M,nextTick:C,onMounted:R,get ReloadOutlined(){return E},get useWsStore(){return N}};return Object.defineProperty(H,"__isScriptSetup",{enumerable:!1,value:!0}),H}},z={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},A={style:{display:"flex",gap:"10px",margin:"12px 0"}},D={ref:"logContainer",class:"log-box"},F={key:0,style:{"text-align":"center",padding:"40px",color:"var(--text-muted)"}},I={key:1,style:{"text-align":"center",padding:"40px",color:"var(--text-muted)"}},P={key:2},J=["innerHTML"];function Z(V,a,x,e,y,v){const c=s("a-checkbox"),i=s("a-button"),f=s("a-space"),o=s("a-tab-pane"),h=s("a-tabs"),m=s("a-input-search"),b=s("a-tag"),L=s("a-spin");return p(),g("div",null,[d("div",z,[a[5]||(a[5]=d("div",null,[d("h2",{class:"page-title"},"日志查看"),d("p",{class:"page-sub"},"系统运行日志与诊断输出")],-1)),n(f,null,{default:_(()=>[n(c,{checked:e.autoScroll,"onUpdate:checked":a[0]||(a[0]=l=>e.autoScroll=l)},{default:_(()=>[...a[3]||(a[3]=[O("自动滚动",-1)])]),_:1},8,["checked"]),n(i,{type:"primary",ghost:"",loading:e.loading,onClick:e.loadLog},{icon:_(()=>[n(e.ReloadOutlined)]),default:_(()=>[a[4]||(a[4]=O(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),k(" Tab Selector "),n(h,{activeKey:e.activeTab,"onUpdate:activeKey":a[1]||(a[1]=l=>e.activeTab=l),onChange:e.loadLog,style:{"margin-bottom":"0"}},{default:_(()=>[n(o,{key:"status",tab:"系统状态"}),n(o,{key:"doctor",tab:"环境诊断"}),n(o,{key:"skill-sources",tab:"技能来源"}),n(o,{key:"llm-providers",tab:"LLM 提供商"})]),_:1},8,["activeKey"]),k(" Search Bar "),d("div",A,[n(m,{value:e.searchQuery,"onUpdate:value":a[2]||(a[2]=l=>e.searchQuery=l),placeholder:"搜索日志内容...","allow-clear":"",style:{flex:"1"}},null,8,["value"]),e.filteredLines.length!==e.allLines.length?(p(),W(b,{key:0,color:"blue"},{default:_(()=>[O(S(e.filteredLines.length)+" / "+S(e.allLines.length)+" 行 ",1)]),_:1})):k("v-if",!0)]),k(" Log Output "),d("div",D,[e.loading?(p(),g("div",F,[n(L,{size:"large"}),a[6]||(a[6]=d("div",{style:{"margin-top":"10px"}},"加载中...",-1))])):e.filteredLines.length?(p(),g("div",P,[(p(!0),g(K,null,Q(e.filteredLines,(l,w)=>(p(),g("div",{key:w,class:U(["log-line",e.lineClass(l)]),innerHTML:e.highlightSearch(e.escapeHtml(l))},null,10,J))),128))])):(p(),g("div",I,S(e.error||"暂无日志内容,点击刷新加载"),1))],512)])}const $=q(j,[["render",Z],["__scopeId","data-v-8c2906e0"],["__file","/tmp/cc-web-panel-7Oqy5c/repo/packages/web-panel/src/views/Logs.vue"]]);export{$ as default};
@@ -1 +0,0 @@
1
- import{I as c,J as g,c as l,K as r,N as u,P as h,U as o,R as t,Q as b}from"./vendor-BMxUs6UX.js";import{_ as v,b as m}from"./index-CGqrVLWe.js";import{a7 as y,M}from"./icons-BsDmGpcT.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const n=u(),{t:e}=m();function a(){n.push("/projects")}function _(){n.push("/mobile-bridge")}const s={router:n,t:e,goToProjects:a,goToMobileBridge:_,get useRouter(){return u},get useI18n(){return m},get MobileOutlined(){return M},get FolderOutlined(){return y}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},O={class:"mobile-projects-placeholder"},x={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,n,e,a,_){const s=c("a-alert"),d=c("a-button"),f=c("a-space"),P=c("a-empty"),j=c("a-card");return h(),g("div",O,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",x,t(e.t("mobileProjects.title")),1),o("p",k,t(e.t("mobileProjects.subtitle")),1),l(s,{message:e.t("mobileProjects.v02Banner"),type:"info","show-icon":"",class:"banner"},null,8,["message"]),o("div",w,[o("h3",null,t(e.t("mobileProjects.currentDirection")),1),o("p",null,t(e.t("mobileProjects.currentDirectionBody")),1),o("ul",null,[o("li",null,t(e.t("mobileProjects.stepPhone")),1),o("li",null,t(e.t("mobileProjects.stepTap")),1),o("li",null,t(e.t("mobileProjects.stepPull")),1)]),o("h3",null,t(e.t("mobileProjects.reverseDirection")),1),o("p",null,t(e.t("mobileProjects.reverseDirectionBody")),1)]),l(f,{class:"actions"},{default:r(()=>[l(d,{type:"primary",onClick:e.goToProjects},{default:r(()=>[l(e.FolderOutlined),b(" "+t(e.t("mobileProjects.viewLocalProjects")),1)]),_:1}),l(d,{onClick:e.goToMobileBridge},{default:r(()=>[l(e.MobileOutlined),b(" "+t(e.t("mobileProjects.checkBridge")),1)]),_:1})]),_:1})]),_:1})]),_:1})])}const N=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-7Oqy5c/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{N as default};
@@ -1 +0,0 @@
1
- import{I as i,J as I,U,R as s,Q as r,c as t,K as a,V as _,S as x,o as oe,b as ee,r as u,P as p,F as ne,a2 as ge}from"./vendor-BMxUs6UX.js";import{_ as we,b as re,u as ie,d}from"./index-CGqrVLWe.js";import{u as de}from"./useShellMode-CgR0wCYM.js";import{aM as ke,aN as Fe,aO as be,f as je,a4 as Ce,a7 as xe,as as Oe,R as Se}from"./icons-BsDmGpcT.js";const Pe={__name:"Projects",setup(se,{expose:l}){l();const{t:te}=re(),e=ie(),{isEmbedded:W}=de();async function w(o,f,ye,ae=8e3){if(W){const Z=await e.sendRaw({...f,type:o},ae);if(!Z?.ok){const $=Z?.error;throw new Error(typeof $=="string"?$:$?.message||`${o} failed`)}return Z.result}return e.executeJson(ye,ae)}const B=u(!1),y=u([]),O=u(""),S=u(""),P=u(!1),v=u(null),h=u([]),k=u(!1),E=u(!1),L=u(!1),F=u({name:"",description:"",type:"document",rootPath:""}),z=[{title:"ID",key:"id",width:110},{title:"名称",key:"name"},{title:"类型",key:"project_type",width:120},{title:"状态",key:"status",width:100},{title:"同步",key:"sync_status",width:100},{title:"更新",key:"updated_at",width:160},{title:"操作",key:"actions",width:180,fixed:"right"}],M=ee(()=>{const o={active:0,draft:0,completed:0,archived:0};for(const f of y.value)o[f.status]!==void 0&&(o[f.status]+=1);return o}),J=ee(()=>y.value.filter(o=>!(O.value&&o.status!==O.value||S.value&&!o.name.toLowerCase().includes(S.value.toLowerCase()))));function g(o){switch(o){case"active":return"green";case"draft":return"default";case"completed":return"cyan";case"archived":return"gold";default:return"default"}}function K(o){switch(o){case"synced":return"green";case"pending":return"orange";case"conflict":return"red";case"error":return"red";default:return"default"}}function Q(o){return!o&&o!==0?"-":new Date(typeof o=="number"?o:parseInt(o,10)).toLocaleString("zh-CN",{hour12:!1})}async function C(){B.value=!0;try{const o=await w("project.list",{limit:500},"project list --limit 500 --json",1e4);y.value=Array.isArray(o?.projects)?o.projects:Array.isArray(o)?o:[]}catch(o){d.error("加载失败: "+(o.message||o)),y.value=[]}finally{B.value=!1}}function G(o){return{onClick:()=>V(o)}}async function V(o){v.value=o,P.value=!0,k.value=!0,h.value=[];try{const f=await w("project.listFiles",{projectId:o.id,limit:200},`project list-files ${o.id} --json`,8e3);h.value=Array.isArray(f?.files)?f.files:[]}catch{h.value=[]}finally{k.value=!1}}async function H(o){try{(await w("project.delete",{id:o.id},`project delete ${o.id} --json`,8e3))?.ok?(d.success(`已删除项目 '${o.name}'`),P.value=!1,await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}function X(){F.value={name:"",description:"",type:"document",rootPath:""},E.value=!0}async function T(){if(!F.value.name.trim()){d.warning("请输入项目名称");return}L.value=!0;try{const o=await w("project.init",{name:F.value.name.trim(),description:F.value.description||null,projectType:F.value.type,rootPath:F.value.rootPath||null},`project init "${F.value.name.trim()}" --type ${F.value.type} --json`,8e3);o?.id?(d.success(`已创建项目 '${o.name}'`),E.value=!1,await C()):d.error("创建失败")}catch(o){d.error(o.message||String(o))}finally{L.value=!1}}const b=u(!1),D=u(!1),j=u({path:"",content:""}),A=u(!1),m=u(!1),R=u({path:""}),n=u(!1),c=u(null),q=u(""),Y=u(!1);function ue(){j.value={path:"",content:""},b.value=!0}function ce(){R.value={path:""},A.value=!0}async function N(){if(v.value){k.value=!0;try{const o=await w("project.listFiles",{projectId:v.value.id,limit:200},`project list-files ${v.value.id} --json`,8e3);h.value=Array.isArray(o?.files)?o.files:[]}catch(o){d.error("刷新文件失败: "+(o.message||o))}finally{k.value=!1}}}async function fe(){if(!j.value.path.trim()){d.warning("请输入文件路径");return}if(v.value){D.value=!0;try{const o=await w("project.createFile",{projectId:v.value.id,filePath:j.value.path.trim(),content:j.value.content||""},`project create-file ${v.value.id} "${j.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件 '${o.file_name}'`),b.value=!1,await N(),await C()):d.error("创建文件失败")}catch(o){d.error(o.message||String(o))}finally{D.value=!1}}}async function pe(){if(!R.value.path.trim()){d.warning("请输入文件夹路径");return}if(v.value){m.value=!0;try{const o=await w("project.createFolder",{projectId:v.value.id,folderPath:R.value.path.trim()},`project create-folder ${v.value.id} "${R.value.path.trim()}" --json`,8e3);o?.id?(d.success(`已创建文件夹 '${o.file_name}'`),A.value=!1,await N(),await C()):d.error("创建文件夹失败")}catch(o){d.error(o.message||String(o))}finally{m.value=!1}}}async function ve(o){try{(await w("project.deleteFile",{fileId:o.id},`project delete-file ${o.id} --json`,8e3))?.deleted?(d.success(`已删除 '${o.file_name}'`),await N(),await C()):d.error("删除失败")}catch(f){d.error(f.message||String(f))}}async function me(o){if(o.is_folder){d.info("文件夹无内容可编辑");return}try{const f=await w("project.getFile",{fileId:o.id},`project get-file ${o.id} --json`,8e3);c.value=o,q.value=f?.content||"",n.value=!0}catch(f){d.error("读取文件失败: "+(f.message||f))}}async function _e(){if(c.value){Y.value=!0;try{(await w("project.writeFile",{fileId:c.value.id,content:q.value},`project write-file ${c.value.id} --json`,8e3))?.id?(d.success("已保存"),n.value=!1,await N()):d.error("保存失败")}catch(o){d.error(o.message||String(o))}finally{Y.value=!1}}}oe(()=>{C()});const le={t:te,ws:e,isEmbedded:W,callProjectTopic:w,loading:B,projects:y,statusFilter:O,nameFilter:S,detailOpen:P,detail:v,files:h,filesLoading:k,createOpen:E,creating:L,newProject:F,columns:z,countByStatus:M,filteredProjects:J,statusColor:g,syncColor:K,formatTime:Q,loadAll:C,onRowClick:G,openDetail:V,onDelete:H,onShowCreate:X,onCreate:T,createFileOpen:b,creatingFile:D,newFile:j,createFolderOpen:A,creatingFolder:m,newFolder:R,editFileOpen:n,editingFile:c,editFileContent:q,savingFile:Y,openCreateFile:ue,openCreateFolder:ce,refreshFiles:N,onCreateFile:fe,onCreateFolder:pe,onDeleteFile:ve,openEditFile:me,onSaveFile:_e,ref:u,computed:ee,onMounted:oe,get ReloadOutlined(){return Se},get PlusOutlined(){return Oe},get FolderOutlined(){return xe},get FileTextOutlined(){return Ce},get CheckCircleOutlined(){return je},get CheckSquareOutlined(){return be},get FileAddOutlined(){return Fe},get FolderAddOutlined(){return ke},get message(){return d},get useI18n(){return re},get useWsStore(){return ie},get useShellMode(){return de}};return Object.defineProperty(le,"__isScriptSetup",{enumerable:!1,value:!0}),le}},ze={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},Ae={class:"page-title"},Ie={class:"page-sub"},Ue={class:"filter-bar",style:{"margin-bottom":"12px",display:"flex",gap:"12px","align-items":"center"}},he={key:0,style:{"font-size":"12px",color:"#888"}},De={key:0,style:{color:"#888","font-size":"12px"}},Re={key:0},Te={key:1,style:{color:"#888"}},Be=["onClick"],Ee={key:0,style:{color:"#888","font-size":"12px"}};function Le(se,l,te,e,W,w){const B=i("router-link"),y=i("a-button"),O=i("a-space"),S=i("a-statistic"),P=i("a-card"),v=i("a-col"),h=i("a-row"),k=i("a-radio-button"),E=i("a-radio-group"),L=i("a-input-search"),F=i("a-alert"),z=i("a-tag"),M=i("a-popconfirm"),J=i("a-table"),g=i("a-descriptions-item"),K=i("a-descriptions"),Q=i("a-divider"),C=i("a-empty"),G=i("a-list-item"),V=i("a-list"),H=i("a-spin"),X=i("a-drawer"),T=i("a-input"),b=i("a-form-item"),D=i("a-textarea"),j=i("a-form"),A=i("a-modal"),m=i("a-select-option"),R=i("a-select");return p(),I("div",null,[U("div",ze,[U("div",null,[U("h2",Ae,s(e.t("projects.title")),1),U("p",Ie,[l[17]||(l[17]=r("桌面 / CLI / 手机 三端共享同一份项目数据,Phase 3d sync 自动同步 (",-1)),t(B,{to:"/project-init"},{default:a(()=>[...l[16]||(l[16]=[r("项目初始化 / 环境设置",-1)])]),_:1}),l[18]||(l[18]=r(")",-1))])]),t(O,null,{default:a(()=>[t(y,{loading:e.loading,onClick:e.loadAll},{icon:a(()=>[t(e.ReloadOutlined)]),default:a(()=>[l[19]||(l[19]=r(" 刷新 ",-1))]),_:1},8,["loading"]),t(y,{type:"primary",onClick:e.onShowCreate},{icon:a(()=>[t(e.PlusOutlined)]),default:a(()=>[l[20]||(l[20]=r(" 新建项目 ",-1))]),_:1})]),_:1})]),_(" Stats "),t(h,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:a(()=>[t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"总项目",value:e.projects.length,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:a(()=>[t(e.FolderOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"活跃",value:e.countByStatus.active,"value-style":{color:"#52c41a",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckCircleOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"草稿",value:e.countByStatus.draft,"value-style":{color:"#8c8c8c",fontSize:"20px"}},{prefix:a(()=>[t(e.FileTextOutlined)]),_:1},8,["value"])]),_:1})]),_:1}),t(v,{xs:12,sm:8,lg:6},{default:a(()=>[t(P,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:a(()=>[t(S,{title:"已完成",value:e.countByStatus.completed,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:a(()=>[t(e.CheckSquareOutlined)]),_:1},8,["value"])]),_:1})]),_:1})]),_:1}),_(" Filter "),U("div",Ue,[t(E,{value:e.statusFilter,"onUpdate:value":l[0]||(l[0]=n=>e.statusFilter=n),size:"small","button-style":"solid"},{default:a(()=>[t(k,{value:""},{default:a(()=>[...l[21]||(l[21]=[r("全部",-1)])]),_:1}),t(k,{value:"active"},{default:a(()=>[...l[22]||(l[22]=[r("活跃",-1)])]),_:1}),t(k,{value:"draft"},{default:a(()=>[...l[23]||(l[23]=[r("草稿",-1)])]),_:1}),t(k,{value:"completed"},{default:a(()=>[...l[24]||(l[24]=[r("已完成",-1)])]),_:1}),t(k,{value:"archived"},{default:a(()=>[...l[25]||(l[25]=[r("已归档",-1)])]),_:1})]),_:1},8,["value"]),t(L,{value:e.nameFilter,"onUpdate:value":l[1]||(l[1]=n=>e.nameFilter=n),placeholder:"按名称过滤",style:{"max-width":"260px"},"allow-clear":""},null,8,["value"])]),!e.projects.length&&!e.loading?(p(),x(F,{key:0,type:"info",message:"还没有项目",description:'运行 `cc project init <name>` 或点击右上角"新建项目"按钮创建。桌面 / CLI / 手机三端共享同一份数据。',"show-icon":"",style:{"margin-bottom":"16px"}})):_("v-if",!0),e.projects.length||e.loading?(p(),x(J,{key:1,columns:e.columns,"data-source":e.filteredProjects,loading:e.loading,pagination:{pageSize:20,showSizeChanger:!0},"row-key":"id","custom-row":e.onRowClick},{bodyCell:a(({column:n,record:c})=>[n.key==="id"?(p(),I("code",he,s(c.id.slice(0,8))+"…",1)):n.key==="name"?(p(),I(ne,{key:1},[U("strong",null,s(c.name),1),c.description?(p(),I("div",De,s(c.description),1)):_("v-if",!0)],64)):n.key==="project_type"?(p(),x(z,{key:2},{default:a(()=>[r(s(c.project_type),1)]),_:2},1024)):n.key==="status"?(p(),x(z,{key:3,color:e.statusColor(c.status)},{default:a(()=>[r(s(c.status),1)]),_:2},1032,["color"])):n.key==="sync_status"?(p(),x(z,{key:4,color:e.syncColor(c.sync_status)},{default:a(()=>[r(s(c.sync_status||"unknown"),1)]),_:2},1032,["color"])):n.key==="updated_at"?(p(),I(ne,{key:5},[r(s(e.formatTime(c.updated_at)),1)],64)):n.key==="actions"?(p(),x(O,{key:6,onClick:l[2]||(l[2]=ge(()=>{},["stop"]))},{default:a(()=>[t(y,{size:"small",onClick:q=>e.openDetail(c)},{default:a(()=>[...l[26]||(l[26]=[r("详情",-1)])]),_:1},8,["onClick"]),t(M,{title:`删除项目 '${c.name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:q=>e.onDelete(c)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[27]||(l[27]=[r("删除",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)):_("v-if",!0)]),_:1},8,["data-source","loading"])):_("v-if",!0),_(" Detail drawer "),t(X,{open:e.detailOpen,"onUpdate:open":l[3]||(l[3]=n=>e.detailOpen=n),title:e.detail?.name||"项目详情",width:"640",placement:"right"},{default:a(()=>[e.detail?(p(),x(K,{key:0,column:1,bordered:"",size:"small"},{default:a(()=>[t(g,{label:"ID"},{default:a(()=>[U("code",null,s(e.detail.id),1)]),_:1}),t(g,{label:"名称"},{default:a(()=>[r(s(e.detail.name),1)]),_:1}),t(g,{label:"描述"},{default:a(()=>[r(s(e.detail.description||"-"),1)]),_:1}),t(g,{label:"类型"},{default:a(()=>[t(z,null,{default:a(()=>[r(s(e.detail.project_type),1)]),_:1})]),_:1}),t(g,{label:"状态"},{default:a(()=>[t(z,{color:e.statusColor(e.detail.status)},{default:a(()=>[r(s(e.detail.status),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"同步状态"},{default:a(()=>[t(z,{color:e.syncColor(e.detail.sync_status)},{default:a(()=>[r(s(e.detail.sync_status||"unknown"),1)]),_:1},8,["color"])]),_:1}),t(g,{label:"用户"},{default:a(()=>[r(s(e.detail.user_id),1)]),_:1}),t(g,{label:"根路径"},{default:a(()=>[e.detail.root_path?(p(),I("code",Re,s(e.detail.root_path),1)):(p(),I("span",Te,"(无)"))]),_:1}),t(g,{label:"文件数"},{default:a(()=>[r(s(e.detail.file_count||0),1)]),_:1}),t(g,{label:"创建"},{default:a(()=>[r(s(e.formatTime(e.detail.created_at)),1)]),_:1}),t(g,{label:"更新"},{default:a(()=>[r(s(e.formatTime(e.detail.updated_at)),1)]),_:1})]),_:1})):_("v-if",!0),t(Q,null,{default:a(()=>[...l[28]||(l[28]=[r("文件",-1)])]),_:1}),_(" Sub-phase 7.3 (2026-05-17): 文件 CRUD toolbar "),t(O,{style:{"margin-bottom":"12px"}},{default:a(()=>[t(y,{size:"small",type:"primary",disabled:!e.detail,onClick:e.openCreateFile},{default:a(()=>[t(e.FileAddOutlined),l[29]||(l[29]=r(" 新建文件 ",-1))]),_:1},8,["disabled"]),t(y,{size:"small",disabled:!e.detail,onClick:e.openCreateFolder},{default:a(()=>[t(e.FolderAddOutlined),l[30]||(l[30]=r(" 新建文件夹 ",-1))]),_:1},8,["disabled"])]),_:1}),t(H,{spinning:e.filesLoading},{default:a(()=>[!e.files.length&&!e.filesLoading?(p(),x(C,{key:0,description:"无文件 (点上方按钮新建)"})):(p(),x(V,{key:1,size:"small","data-source":e.files},{renderItem:a(({item:n})=>[t(G,null,{extra:a(()=>[t(O,null,{default:a(()=>[n.file_size?(p(),I("span",Ee,s(n.file_size)+" B",1)):_("v-if",!0),t(M,{title:`删除 ${n.is_folder?"文件夹":"文件"} '${n.file_name}' ?`,"ok-text":"删除","ok-type":"danger","cancel-text":"取消",onConfirm:c=>e.onDeleteFile(n)},{default:a(()=>[t(y,{size:"small",danger:""},{default:a(()=>[...l[31]||(l[31]=[r("×",-1)])]),_:1})]),_:1},8,["title","onConfirm"])]),_:2},1024)]),default:a(()=>[U("span",{style:{cursor:"pointer"},onClick:c=>e.openEditFile(n)},s(n.is_folder?"📁":"📄")+" "+s(n.file_path),9,Be)]),_:2},1024)]),_:1},8,["data-source"]))]),_:1},8,["spinning"])]),_:1},8,["open","title"]),_(" Sub-phase 7.3: Create file modal "),t(A,{open:e.createFileOpen,"onUpdate:open":l[6]||(l[6]=n=>e.createFileOpen=n),title:"新建文件","confirm-loading":e.creatingFile,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFile},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFile.path,"onUpdate:value":l[4]||(l[4]=n=>e.newFile.path=n),placeholder:"例如 README.md 或 src/main.kt"},null,8,["value"])]),_:1}),t(b,{label:"初始内容(可选)"},{default:a(()=>[t(D,{value:e.newFile.content,"onUpdate:value":l[5]||(l[5]=n=>e.newFile.content=n),rows:6,placeholder:"留空创建空文件"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Create folder modal "),t(A,{open:e.createFolderOpen,"onUpdate:open":l[8]||(l[8]=n=>e.createFolderOpen=n),title:"新建文件夹","confirm-loading":e.creatingFolder,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreateFolder},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"文件夹路径(项目内)",required:""},{default:a(()=>[t(T,{value:e.newFolder.path,"onUpdate:value":l[7]||(l[7]=n=>e.newFolder.path=n),placeholder:"例如 src/utils"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"]),_(" Sub-phase 7.3: Edit file content modal "),t(A,{open:e.editFileOpen,"onUpdate:open":l[10]||(l[10]=n=>e.editFileOpen=n),title:`编辑 ${e.editingFile?.file_name||""}`,"confirm-loading":e.savingFile,"ok-text":"保存","cancel-text":"取消",onOk:e.onSaveFile,width:"720"},{default:a(()=>[t(D,{value:e.editFileContent,"onUpdate:value":l[9]||(l[9]=n=>e.editFileContent=n),rows:18,"auto-size":{minRows:12,maxRows:24},style:{"font-family":"monospace"}},null,8,["value"])]),_:1},8,["open","title","confirm-loading"]),_(" Create modal "),t(A,{open:e.createOpen,"onUpdate:open":l[15]||(l[15]=n=>e.createOpen=n),title:"新建项目","confirm-loading":e.creating,"ok-text":"创建","cancel-text":"取消",onOk:e.onCreate},{default:a(()=>[t(j,{layout:"vertical"},{default:a(()=>[t(b,{label:"项目名称",required:""},{default:a(()=>[t(T,{value:e.newProject.name,"onUpdate:value":l[11]||(l[11]=n=>e.newProject.name=n),placeholder:"例如:旅行计划-上海"},null,8,["value"])]),_:1}),t(b,{label:"描述"},{default:a(()=>[t(D,{value:e.newProject.description,"onUpdate:value":l[12]||(l[12]=n=>e.newProject.description=n),rows:2},null,8,["value"])]),_:1}),t(b,{label:"类型"},{default:a(()=>[t(R,{value:e.newProject.type,"onUpdate:value":l[13]||(l[13]=n=>e.newProject.type=n)},{default:a(()=>[t(m,{value:"document"},{default:a(()=>[...l[32]||(l[32]=[r("文档 (document)",-1)])]),_:1}),t(m,{value:"data"},{default:a(()=>[...l[33]||(l[33]=[r("数据 (data)",-1)])]),_:1}),t(m,{value:"web"},{default:a(()=>[...l[34]||(l[34]=[r("Web",-1)])]),_:1}),t(m,{value:"app"},{default:a(()=>[...l[35]||(l[35]=[r("应用 (app)",-1)])]),_:1}),t(m,{value:"presentation"},{default:a(()=>[...l[36]||(l[36]=[r("演示文稿",-1)])]),_:1}),t(m,{value:"spreadsheet"},{default:a(()=>[...l[37]||(l[37]=[r("表格",-1)])]),_:1}),t(m,{value:"design"},{default:a(()=>[...l[38]||(l[38]=[r("设计",-1)])]),_:1}),t(m,{value:"code"},{default:a(()=>[...l[39]||(l[39]=[r("代码",-1)])]),_:1}),t(m,{value:"workflow"},{default:a(()=>[...l[40]||(l[40]=[r("工作流",-1)])]),_:1}),t(m,{value:"knowledge"},{default:a(()=>[...l[41]||(l[41]=[r("知识库",-1)])]),_:1})]),_:1},8,["value"])]),_:1}),t(b,{label:"根路径 (可选)"},{default:a(()=>[t(T,{value:e.newProject.rootPath,"onUpdate:value":l[14]||(l[14]=n=>e.newProject.rootPath=n),placeholder:"留空则仅元数据"},null,8,["value"])]),_:1})]),_:1})]),_:1},8,["open","confirm-loading"])])}const We=we(Pe,[["render",Le],["__scopeId","data-v-019ac5aa"],["__file","/tmp/cc-web-panel-7Oqy5c/repo/packages/web-panel/src/views/Projects.vue"]]);export{We as default};