chainlesschain 0.162.61 → 0.162.65

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 (162) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/assets/{AIOps-BiB8WfIz.js → AIOps-DjJf_QIn.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-NLBhC6jG.js → ActionButton-BT45g-KL.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-k62j-xiL.js → Analytics-CRaTHble.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-spr0Sm6J.js → AppLayout-72r5TM1u.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-C3NHJos3.js → Audit-BNlvJ3Yc.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-C2V9tGqF.js → Backup-Kuj0-vBg.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-DeKm11mH.js → BaseInput-_pKOPRf4.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-CHZ2CU7x.js → Chat-CMNhGWK5.js} +5 -5
  10. package/src/assets/web-panel/assets/ChatBubbleRenderer-DxJmwLv8.js +1 -0
  11. package/src/assets/web-panel/assets/{Checkbox-q6E9VeLr.js → Checkbox-B5R2TdAI.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen--4w4QpUI.js → Codegen-69RAQ0Gi.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-DLOkwTsj.js → Col-DlbssQEY.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-B1LxJGfE.js → Community-DU3SAZIS.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-C_769oQZ.js → Compact-BqdNnAZv.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-zsI0s7vB.js → Compliance-D9a9-ihS.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-A1WA6whF.js → Cowork-DWBtOBbU.js} +3 -3
  18. package/src/assets/web-panel/assets/{Cron-C3JDTyyd.js → Cron-ClSuf90k.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-D8O6uB86.js → Crosschain-BFjRKvpa.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-BpOebm5d.js → DID-BwBGRlMm.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-Defso6kA.js → Dashboard-CHrXGmQ3.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-Cv9BrwT_.js → Dropdown-C24B5sk2.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-BWKHbh4C.js → EmailListRenderer-DaXTSK5p.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard--m_Ru7Ci.js → FamilyGuardDashboard-65d89G5t.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-Bs6ZcAP0.js → Federation-CkWdqmVs.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CcAs3Acx.js → FormItemContext-BV4W2nrT.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-DI1oL4pK.js → GenericCardRenderer-D60KJ0_b.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-C27t3-fW.js → Git-BIKuoGvW.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-Dr_syXc_.js → Governance-CKnJpq5X.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-CWM8dIbA.js → Inference-C7G3YGeg.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph--cFDUZv3.js → KnowledgeGraph-D7fCUd4B.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-Cnn2_Onf.js → Logs-C0unjcbC.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-4T9ok3Gz.js → Marketplace-BzLlnyI8.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-BQvZwqcN.js → McpTools-DSKFRB1-.js} +4 -4
  35. package/src/assets/web-panel/assets/{Memory-BE9rPkM_.js → Memory-C_QrLAnt.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-DJ3j5lXC.js → MobileBridge-DBeaFERD.js} +2 -2
  37. package/src/assets/web-panel/assets/{MobileProjects-qasLvYdb.js → MobileProjects-C2L_RttC.js} +1 -1
  38. package/src/assets/web-panel/assets/{Mtc-D3CSPTD9.js → Mtc-B3Tdh6-l.js} +4 -4
  39. package/src/assets/web-panel/assets/{MtcAudit-DaYVGCN5.js → MtcAudit-B3O_EUvt.js} +4 -4
  40. package/src/assets/web-panel/assets/{Multisig-Dz1c5r5w.js → Multisig--60rVmDj.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-BIKV_K-a.js → NLProgramming-D60vxATf.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-f6t-rmOa.js → Notes-D2gj2uFI.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-DHLQh8Fy.js → NotificationSettings-D0DWHNlF.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-CDMZ3o6i.js → OrderTableRenderer-CNi1B7fH.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-DIsL758p.js → Organization-BRcdFgAd.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-BMM7apnZ.js → Overflow-C3_Oap7v.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-CTGMmTvi.js → P2P-DEbZ93QW.js} +2 -2
  48. package/src/assets/web-panel/assets/PdhVaultBrowser-DN_pmo2N.js +7 -0
  49. package/src/assets/web-panel/assets/{Permissions-Bed5JxMx.js → Permissions-CPj3C9o2.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-CIiZhSM5.js → PersonalDataHub-BZGupZzh.js} +4 -4
  51. package/src/assets/web-panel/assets/{Pipeline-CtirPodz.js → Pipeline-SMLW1BG7.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-DuXhXhE7.js → Privacy-o24SJ2no.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-DZrnguBl.js → ProjectInit-DxjAXD8f.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings-HIltqsJ1.js → ProjectSettings-DipynlqL.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-BWFkePg4.js → Projects-CZ9egQ8r.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-DEP0Jdvl.js → Providers-x3p-wcab.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-T2THoHNx.js → QuickAsk-CZ7beKFC.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-CvbxaSwm.js → Recommend-VJCd2i9_.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-6Afy6tfp.js → Reputation-pl12NmBF.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-DY8OPWaO.js → Row-NkSeo4Tb.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-wDGWb9pZ.js → RssFeed-B17vp67R.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-D_zHAwZY.js → Search-Dij0_m6W.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-Czq7AlGG.js → Security-n9CSBX-9.js} +4 -4
  64. package/src/assets/web-panel/assets/{Services-Ac1g0ZcG.js → Services-bZOzqHdK.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-DXQ3eeSW.js → Skeleton-B23D5vJ-.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-CWRioX4u.js → Skills-IXh-0mk0.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-BlHthzfs.js → Sla-QEofxmdK.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-Ct240JmL.js → SpeechSettings-u68R59ft.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-BgDIt8Q-.js → SyncSettings-B3tc986U.js} +2 -2
  70. package/src/assets/web-panel/assets/Tasks-Cp2QxGrr.js +1 -0
  71. package/src/assets/web-panel/assets/{Templates-Dp9QhyIw.js → Templates-CMWiWxiH.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-CHTYMxzY.js → Tenant-M8aPJ3C7.js} +1 -1
  73. package/src/assets/web-panel/assets/Terminal-CK3zKjIE.js +3 -0
  74. package/src/assets/web-panel/assets/{TimelineRenderer-Bh8jA18j.js → TimelineRenderer-DF6aIS-d.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-DWkTd5dv.js → Tokens-BcfMMw_e.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-CRgVg6sd.js → Trigger-jIbNmxvm.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-BgWOXd0W.js → Trust-ChLil6CZ.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-BlTUB9Y-.js → UkeySign-B1WzYAon.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-DI64XgNb.js → VideoEditing-Dwm0LyCc.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-CJ3TNGiG.js → Wallet-DVyxsX-O.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-B2-rWWoV.js → WebAuthn-WYPNy2Q7.js} +5 -5
  82. package/src/assets/web-panel/assets/{WorkflowEditor-VI9otbaH.js → WorkflowEditor-Br3dCsmv.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-CgYfiaVh.js → chat-fAKHY2HK.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-B9EhRTky.js → colors-BXqS-Bwi.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-Cb7bjraa.js → compact-item-BgCQhtW3.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-DlXPeXuj.js → createContext-weZBwqHy.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-BpXdFCJ4.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-BbgRfrdf.js → hasIn-Dx68UNFL.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-2ts5iOIB.js → index-5e-OAZOb.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-Caiu2avX.js → index-B0rgvjX8.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-OVrh8wTN.js → index-B8-2rQdr.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DPaffcT8.js → index-B8zNZ_oH.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-Ira0HLPr.js → index-B9NeNwHP.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-CMyzmvtJ.js → index-BC-4la9j.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DDzNdZcX.js → index-BSQEQCft.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-De59Xat-.js → index-BawcE_zG.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-Dx4sm6dm.js → index-Bazltj8w.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-5CrFMQjt.js → index-BehvfmYd.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-ojRAd7Nq.js → index-BjsidvP5.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DbLJShJB.js → index-Bo4UTTla.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-1iUK_kAw.js → index-BqcH_mKR.js} +1 -1
  102. package/src/assets/web-panel/assets/index-BrPKR2RZ.js +1 -0
  103. package/src/assets/web-panel/assets/{index-C95qWAh4.js → index-Bwv_UrNF.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DXxa7PR8.js → index-C0ZjD3Ac.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DUU9DY4J.js → index-CEjLe8FJ.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Bk7r1a9x.js → index-CJXZDwkf.js} +1 -1
  107. package/src/assets/web-panel/assets/index-CMEfvACO.js +1 -0
  108. package/src/assets/web-panel/assets/{index-Cf9zwbk-.js → index-CX9cxRnU.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bt-lPYpq.js → index-CfqzwaAV.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BfSS-U5o.js → index-ChdeuOni.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-D6t-Shqr.js → index-ClfP1Yax.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BU8hEUyq.js → index-Co5cQnlv.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DkQIyK-V.js → index-CxfVwfub.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-fG-1gXy0.js → index-Cxsfc5Ou.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C8DB27uJ.js → index-DCYJDUab.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-C73WgOc2.js → index-DG2KCc8h.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D8kB0k3E.js → index-DNF3aCJF.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BoEFFKn3.js → index-DXuz90bX.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Dh6qWb1v.js → index-Dbv5btEU.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-p03wNqiP.js → index-DgUC575c.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-BD2W-qsS.js → index-G_wPnPoA.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CGx8aO_Y.js → index-HIN85jl7.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-c7-Jd6WB.js → index-LxcdLeFj.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-D-Zz9PvD.js → index-loaP_41H.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-AR-QpAkP.js → index-ohVNy7ua.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-Cmr31VCO.js → index-qUBHSW_3.js} +3 -3
  127. package/src/assets/web-panel/assets/{index-CHR47Q5B.js → index-u2U9t07r.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-JT674ACa.js → initDefaultProps-M7xH4eUK.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-CokflrA9.js → motion-BrJP4mFE.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-CfMhRpyC.js → move-BufxEuU9.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-ClYc5II5.js → omit-s6dtQtFP.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-CTwEb_8h.js → pickAttrs-BcYdIZqz.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-Cb3StU_t.js → placementArrow-Ds-3Hw3n.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-uIxkx5M1.js → responsiveObserve-BRtrRTxl.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-B9HZBQ7i.js → slide-RJzqMQM4.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-C72bwYl0.js → statusUtils-BuBhJXvr.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-BFTtaQb8.js → styleChecker-so8acGHq.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-DKl5j41_.js → useFlexGapSupport-BpkV467K.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-BUHS6bo3.js → useFs-lES1RctZ.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-D8KrYSq4.js → usePersonalDataHub-DdCNi4bA.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-JYP-aZDj.js → vnode-nAeEg_3h.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-BFusdxdH.js → zoom-BWjRAfRy.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/agent.js +39 -0
  145. package/src/commands/review.js +463 -0
  146. package/src/index.js +2 -0
  147. package/src/lib/cost-budget.js +109 -0
  148. package/src/lib/ide-context.js +50 -0
  149. package/src/lib/personal-data-hub-wiring.js +16 -0
  150. package/src/repl/agent-repl.js +36 -0
  151. package/src/repl/tasks-status.js +82 -0
  152. package/src/runtime/agent-core.js +38 -3
  153. package/src/runtime/headless-runner.js +51 -3
  154. package/src/runtime/headless-stream.js +62 -4
  155. package/src/runtime/mcp-config.js +6 -0
  156. package/src/assets/web-panel/assets/ChatBubbleRenderer-DEXSa7tC.js +0 -1
  157. package/src/assets/web-panel/assets/PdhVaultBrowser-DWwmm0k1.js +0 -7
  158. package/src/assets/web-panel/assets/Tasks-3PTmatJP.js +0 -1
  159. package/src/assets/web-panel/assets/Terminal-X-NGwLpv.js +0 -3
  160. package/src/assets/web-panel/assets/devWarning-D-Hp8s_8.js +0 -1
  161. package/src/assets/web-panel/assets/index-BvnHuxVM.js +0 -1
  162. package/src/assets/web-panel/assets/index-Dkm5IGwX.js +0 -1
@@ -57,6 +57,8 @@ const {
57
57
  ZhihuAdapter,
58
58
  BossZhipinAdapter,
59
59
  CsdnAdapter,
60
+ DongchediAdapter,
61
+ TianyanchaAdapter,
60
62
  DouyinAdapter,
61
63
  XiaohongshuAdapter,
62
64
  ToutiaoAdapter,
@@ -74,12 +76,18 @@ const {
74
76
  KugouMusicAdapter,
75
77
  IqiyiVideoAdapter,
76
78
  TencentVideoAdapter,
79
+ XiguaVideoAdapter,
77
80
  WeReadAdapter,
78
81
  WpsDocAdapter,
79
82
  TencentDocsAdapter,
80
83
  BaiduNetdiskAdapter,
84
+ CamScannerDocAdapter,
85
+ IXiamenAdapter,
86
+ MeiyouAdapter,
87
+ TaxAdapter,
81
88
  DingTalkPcAdapter,
82
89
  FeishuPcAdapter,
90
+ WeWorkPcAdapter,
83
91
  BaiduMapAdapter,
84
92
  TencentMapAdapter,
85
93
  JdAdapter,
@@ -529,6 +537,8 @@ async function initHub() {
529
537
  ZhihuAdapter,
530
538
  BossZhipinAdapter,
531
539
  CsdnAdapter,
540
+ DongchediAdapter,
541
+ TianyanchaAdapter,
532
542
  DouyinAdapter,
533
543
  XiaohongshuAdapter,
534
544
  ToutiaoAdapter,
@@ -546,12 +556,18 @@ async function initHub() {
546
556
  KugouMusicAdapter,
547
557
  IqiyiVideoAdapter,
548
558
  TencentVideoAdapter,
559
+ XiguaVideoAdapter,
549
560
  WeReadAdapter,
550
561
  WpsDocAdapter,
551
562
  TencentDocsAdapter,
552
563
  BaiduNetdiskAdapter,
564
+ CamScannerDocAdapter,
565
+ IXiamenAdapter,
566
+ MeiyouAdapter,
567
+ TaxAdapter,
553
568
  DingTalkPcAdapter,
554
569
  FeishuPcAdapter,
570
+ WeWorkPcAdapter,
555
571
  BaiduMapAdapter,
556
572
  TencentMapAdapter,
557
573
  JdAdapter,
@@ -75,7 +75,10 @@ import {
75
75
  agentLoop as coreAgentLoop,
76
76
  formatToolArgs,
77
77
  killAllBackgroundShellTasks,
78
+ killBackgroundShellTask,
79
+ listBackgroundShellTasks,
78
80
  } from "../runtime/agent-core.js";
81
+ import { formatBackgroundTasks } from "./tasks-status.js";
79
82
  import { expandFileRefs } from "../runtime/file-ref-expander.js";
80
83
  import { composeSystemPrompt } from "../runtime/system-prompt.js";
81
84
  import {
@@ -833,6 +836,7 @@ export async function startAgentRepl(options = {}) {
833
836
  "/statusline",
834
837
  "/sub-agents",
835
838
  "/task",
839
+ "/tasks",
836
840
  "/terminal-setup",
837
841
  "/vim",
838
842
  ],
@@ -1253,6 +1257,9 @@ export async function startAgentRepl(options = {}) {
1253
1257
  logger.log(
1254
1258
  ` ${chalk.cyan("/sub-agents")} Show active/completed sub-agents`,
1255
1259
  );
1260
+ logger.log(
1261
+ ` ${chalk.cyan("/tasks")} Show background shell tasks (kill <id> · kill-all)`,
1262
+ );
1256
1263
  logger.log(
1257
1264
  ` ${chalk.cyan("/ide")} IDE bridge status (connected editor, tools, or why not)`,
1258
1265
  );
@@ -1292,6 +1299,35 @@ export async function startAgentRepl(options = {}) {
1292
1299
  return;
1293
1300
  }
1294
1301
 
1302
+ // `/tasks` — user-facing view of the agent's background shell tasks
1303
+ // (run_shell run_in_background). Must precede the `/task` handler below,
1304
+ // which matches with startsWith("/task") and would otherwise swallow it.
1305
+ if (trimmed === "/tasks" || trimmed.startsWith("/tasks ")) {
1306
+ const rest = trimmed.slice("/tasks".length).trim();
1307
+ if (rest === "kill-all") {
1308
+ const n = killAllBackgroundShellTasks();
1309
+ logger.log(chalk.dim(`Killed ${n} background shell task(s).`));
1310
+ } else if (rest.startsWith("kill ")) {
1311
+ const id = rest.slice("kill ".length).trim();
1312
+ const ok = id ? killBackgroundShellTask(id) : false;
1313
+ logger.log(
1314
+ ok
1315
+ ? chalk.dim(`Killed background shell task ${id}.`)
1316
+ : chalk.dim(`No running background shell task with id "${id}".`),
1317
+ );
1318
+ } else if (rest === "kill") {
1319
+ logger.log(chalk.dim("Usage: /tasks kill <id> · /tasks kill-all"));
1320
+ } else {
1321
+ logger.log(
1322
+ "
1323
+ " + formatBackgroundTasks(listBackgroundShellTasks()) + "
1324
+ ",
1325
+ );
1326
+ }
1327
+ prompt();
1328
+ return;
1329
+ }
1330
+
1295
1331
  if (trimmed === "/sub-agents" || trimmed === "/subagents") {
1296
1332
  try {
1297
1333
  const { SubAgentRegistry } =
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Pure renderer for the `/tasks` REPL command — a user-facing view of the
3
+ * agent's background shell tasks (the ones it starts with
4
+ * run_shell { run_in_background: true }). The data comes from agent-core's
5
+ * listBackgroundShellTasks(); this module only formats it, so it stays
6
+ * deterministic and unit-testable (inject `now` for stable elapsed time).
7
+ *
8
+ * Background shells are otherwise only visible to the agent (via its
9
+ * check_shell tool) — this surfaces them to the human, the way Claude Code's
10
+ * background-tasks view does. Sub-agents live under a separate registry and
11
+ * are shown by `/sub-agents`.
12
+ */
13
+
14
+ /** Coerce an ISO-string or epoch-ms timestamp to epoch ms, or null. */
15
+ function toMs(v) {
16
+ if (typeof v === "number" && Number.isFinite(v)) return v;
17
+ if (typeof v === "string") {
18
+ const t = Date.parse(v);
19
+ return Number.isFinite(t) ? t : null;
20
+ }
21
+ return null;
22
+ }
23
+
24
+ /** Human-friendly elapsed duration. */
25
+ function fmtElapsed(ms) {
26
+ if (!Number.isFinite(ms) || ms < 0) return "?";
27
+ const s = Math.floor(ms / 1000);
28
+ if (s < 60) return `${s}s`;
29
+ const m = Math.floor(s / 60);
30
+ if (m < 60) return `${m}m${s % 60}s`;
31
+ const h = Math.floor(m / 60);
32
+ return `${h}h${m % 60}m`;
33
+ }
34
+
35
+ /** A short status badge for one task. */
36
+ export function taskStatusLabel(t) {
37
+ switch (t?.status) {
38
+ case "running":
39
+ return "● running";
40
+ case "exited":
41
+ return `✓ exited${t.exitCode != null ? ` (${t.exitCode})` : ""}`;
42
+ case "failed":
43
+ return `✗ failed${t.exitCode != null ? ` (${t.exitCode})` : ""}`;
44
+ case "error":
45
+ return "✗ error";
46
+ default:
47
+ return t?.status || "?";
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Render the background-shell task list as a plain-text block.
53
+ * @param {Array} tasks from listBackgroundShellTasks()
54
+ * @param {object} opts { now?: epoch-ms } — defaults to Date.now()
55
+ */
56
+ export function formatBackgroundTasks(tasks, { now = Date.now() } = {}) {
57
+ const list = Array.isArray(tasks) ? tasks : [];
58
+ if (list.length === 0) {
59
+ return (
60
+ "No background shell tasks.\n" +
61
+ " (The agent starts these with run_shell run_in_background:true; " +
62
+ "sub-agents are under /sub-agents.)"
63
+ );
64
+ }
65
+ const running = list.filter((t) => t?.status === "running").length;
66
+ const lines = [
67
+ `Background shell tasks (${list.length}, ${running} running):`,
68
+ ];
69
+ for (const t of list) {
70
+ const started = toMs(t.startedAt);
71
+ const ended = toMs(t.endedAt);
72
+ const elapsed =
73
+ started != null ? fmtElapsed((ended ?? now) - started) : "?";
74
+ const cmd = String(t.command || "")
75
+ .replace(/\s+/g, " ")
76
+ .trim();
77
+ const cmdShort = cmd.length > 70 ? cmd.slice(0, 70) + "…" : cmd;
78
+ lines.push(` ${taskStatusLabel(t)} ${t.id} ${elapsed} ${cmdShort}`);
79
+ }
80
+ lines.push("Manage: /tasks kill <id> · /tasks kill-all");
81
+ return lines.join("\n");
82
+ }
@@ -175,6 +175,16 @@ function _killTask(task) {
175
175
  }
176
176
  }
177
177
 
178
+ /**
179
+ * Kill one background shell task by id (for the user-facing `/tasks kill <id>`).
180
+ * @returns {boolean} true if a running task with that id was signalled
181
+ */
182
+ export function killBackgroundShellTask(id) {
183
+ const task = _backgroundShellTasks.get(id);
184
+ if (!task) return false;
185
+ return _killTask(task);
186
+ }
187
+
178
188
  /**
179
189
  * Kill every still-running background shell task. Callers (REPL exit, headless
180
190
  * shutdown) invoke this so a backgrounded `npm run dev` doesn't outlive the
@@ -241,7 +251,9 @@ async function runSettingsPreToolUseHooks(name, args, context, cwd) {
241
251
  if (ide?.outcome === "accepted") {
242
252
  return { blocked: false, ideApplied: ide.result };
243
253
  }
244
- if (ide?.outcome === "rejected") {
254
+ // Both rejected and changes-requested mean "not applied + feed the
255
+ // verdict's message back" — same control flow, different message body.
256
+ if (ide?.outcome === "rejected" || ide?.outcome === "changes-requested") {
245
257
  return {
246
258
  blocked: true,
247
259
  reason: ide.result.error,
@@ -714,8 +726,12 @@ async function tryIdeDiffApprovalForEdit(
714
726
  if (typeof context.permissionConfirm !== "function") return null; // interactive only
715
727
  if (!context.mcpClient || !context.externalToolExecutors) return null;
716
728
  try {
717
- const { ideDiffApprovalEnabled, hasIdeOpenDiff, requestIdeDiffApproval } =
718
- await import("../lib/ide-context.js");
729
+ const {
730
+ ideDiffApprovalEnabled,
731
+ hasIdeOpenDiff,
732
+ requestIdeDiffApproval,
733
+ formatReviewComments,
734
+ } = await import("../lib/ide-context.js");
719
735
  const mcpLike = {
720
736
  mcpClient: context.mcpClient,
721
737
  externalToolExecutors: context.externalToolExecutors,
@@ -753,6 +769,25 @@ async function tryIdeDiffApprovalForEdit(
753
769
  },
754
770
  };
755
771
  }
772
+ if (verdict?.outcome === "changes-requested") {
773
+ // The reviewer annotated the diff instead of accepting/rejecting: the
774
+ // file is untouched and the notes flow back as the tool result, so the
775
+ // agent revises and re-proposes (Claude-Code inline-review parity).
776
+ const feedback =
777
+ formatReviewComments(verdict.comments, { path: proposal.filePath }) ||
778
+ "The user requested changes in the IDE diff review (no specific notes).";
779
+ return {
780
+ outcome: "changes-requested",
781
+ result: {
782
+ error:
783
+ `[IDE review] "${name}" was NOT applied — the user requested changes:\n` +
784
+ `${feedback}\n` +
785
+ "Revise the edit to address this feedback, then propose it again.",
786
+ policy: { decision: "deny", rule, via: "ide-diff-review" },
787
+ reviewComments: verdict.comments,
788
+ },
789
+ };
790
+ }
756
791
  } catch (_err) {
757
792
  // diff-approval routing is best-effort — fall back to the normal confirm
758
793
  }
@@ -47,6 +47,7 @@ import { expandFileRefs } from "./file-ref-expander.js";
47
47
  import { composeSystemPrompt } from "./system-prompt.js";
48
48
  import { buildUserContent } from "../lib/image-input.js";
49
49
  import { withQuietStdout } from "./quiet-stdout.js";
50
+ import { CostBudget } from "../lib/cost-budget.js";
50
51
 
51
52
  /** Tools that cannot mutate the filesystem or run commands. */
52
53
  export const READ_ONLY_TOOLS = Object.freeze([
@@ -525,6 +526,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
525
526
  mcpConfigPath: options.mcpConfig || null,
526
527
  db: db?.getDatabase?.() || null,
527
528
  includeRegistered: options.useRegisteredMcp !== false,
529
+ // --strict-mcp-config: use ONLY the --mcp-config servers, ignoring
530
+ // registered (cc mcp add) + IDE bridge auto-discovery.
531
+ strict: options.strictMcpConfig === true,
528
532
  ide: options.ide,
529
533
  cwd: options.cwd || process.cwd(),
530
534
  // advertise the session id to spawned stdio MCP servers
@@ -665,11 +669,19 @@ export async function runAgentHeadless(options = {}, deps = {}) {
665
669
  }
666
670
  }
667
671
 
672
+ // --max-budget-usd: a hard USD spend cap (Claude-Code parity). Accumulates
673
+ // per-call cost from token-usage events and stops the loop before the next
674
+ // paid call once the cap is reached. null → no cap (unchanged behavior).
675
+ const costBudget = options.maxCostUsd
676
+ ? new CostBudget({ limitUsd: options.maxCostUsd, table: options.priceTable })
677
+ : null;
678
+
668
679
  const startedAt = deps.now ? deps.now() : Date.now();
669
680
  const toolCalls = [];
670
681
  const usage = { input_tokens: 0, output_tokens: 0 };
671
682
  let finalText = "";
672
683
  let endReason = "complete";
684
+ let stopForCost = false;
673
685
 
674
686
  const emitStream = (obj) => {
675
687
  if (isStream) writeOut(JSON.stringify(obj) + "\n");
@@ -744,6 +756,31 @@ export async function runAgentHeadless(options = {}, deps = {}) {
744
756
  usage.input_tokens += event.usage?.input_tokens || 0;
745
757
  usage.output_tokens += event.usage?.output_tokens || 0;
746
758
  emitStream({ type: "token_usage", usage: event.usage });
759
+ if (costBudget) {
760
+ costBudget.add({
761
+ provider: event.provider,
762
+ model: event.model,
763
+ usage: event.usage,
764
+ });
765
+ if (costBudget.shouldWarnInactive()) {
766
+ const m = `cost cap $${options.maxCostUsd} set but model "${event.model}" is unpriced/free — cap inactive`;
767
+ if (isText) writeErr(` ${m}\n`);
768
+ emitStream({ type: "cost_warning", message: m });
769
+ }
770
+ if (costBudget.exceeded()) {
771
+ endReason = "cost-budget-exhausted";
772
+ stopForCost = true;
773
+ if (isText)
774
+ writeErr(
775
+ ` ⛔ cost budget $${options.maxCostUsd} reached (spent ≈$${costBudget.spentUsd}) — stopping\n`,
776
+ );
777
+ emitStream({
778
+ type: "cost_budget_exhausted",
779
+ limit_usd: options.maxCostUsd,
780
+ spent_usd: costBudget.spentUsd,
781
+ });
782
+ }
783
+ }
747
784
  break;
748
785
  }
749
786
  case "iteration-warning": {
@@ -772,6 +809,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
772
809
  if (isStream && event.type) emitStream(event);
773
810
  break;
774
811
  }
812
+ // Hard cost cap reached: stop consuming the loop so no further paid LLM
813
+ // call is made (break out of the for-await, not just the switch).
814
+ if (stopForCost) break;
775
815
  }
776
816
  } catch (err) {
777
817
  const message = err?.message || String(err);
@@ -837,11 +877,19 @@ export async function runAgentHeadless(options = {}, deps = {}) {
837
877
  }
838
878
 
839
879
  // coreAgentLoop emits run-ended reason "budget-exhausted" when the iteration
840
- // cap is hit; treat that as the max-turns error surface.
880
+ // cap is hit; treat that as the max-turns error surface. A cost-budget stop
881
+ // (--max-budget-usd) is its own error surface so callers can tell them apart.
841
882
  const exhausted =
842
883
  endReason === "budget-exhausted" || endReason === "max_turns";
843
- const isError = exhausted || endReason === "no-response";
844
- const subtype = exhausted ? "error_max_turns" : isError ? "error" : "success";
884
+ const costStopped = endReason === "cost-budget-exhausted";
885
+ const isError = exhausted || costStopped || endReason === "no-response";
886
+ const subtype = exhausted
887
+ ? "error_max_turns"
888
+ : costStopped
889
+ ? "error_max_budget"
890
+ : isError
891
+ ? "error"
892
+ : "success";
845
893
  const durationMs = (deps.now ? deps.now() : Date.now()) - startedAt;
846
894
 
847
895
  // Persist the assistant turn so a later --resume / --continue replays it.
@@ -26,6 +26,7 @@ import {
26
26
  makePermissionPromptConfirmer,
27
27
  } from "./mcp-config.js";
28
28
  import { IterationBudget } from "../lib/iteration-budget.js";
29
+ import { CostBudget } from "../lib/cost-budget.js";
29
30
  import {
30
31
  resolvePermissionMode,
31
32
  resolveEnabledTools,
@@ -140,11 +141,12 @@ export async function* readJsonLines(input) {
140
141
  * Run a single turn through the core agent loop, emitting NDJSON events.
141
142
  * Returns the turn outcome so the caller can grow history + the result line.
142
143
  */
143
- async function runTurn(messages, loopOptions, { runLoop, emit }) {
144
+ async function runTurn(messages, loopOptions, { runLoop, emit, costBudget }) {
144
145
  const usage = { input_tokens: 0, output_tokens: 0 };
145
146
  const toolCalls = [];
146
147
  let finalText = "";
147
148
  let endReason = "complete";
149
+ let stopForCost = false;
148
150
 
149
151
  for await (const event of runLoop(messages, loopOptions)) {
150
152
  switch (event.type) {
@@ -169,6 +171,17 @@ async function runTurn(messages, loopOptions, { runLoop, emit }) {
169
171
  usage.input_tokens += event.usage?.input_tokens || 0;
170
172
  usage.output_tokens += event.usage?.output_tokens || 0;
171
173
  emit({ type: "token_usage", usage: event.usage });
174
+ if (costBudget) {
175
+ costBudget.add({
176
+ provider: event.provider,
177
+ model: event.model,
178
+ usage: event.usage,
179
+ });
180
+ if (costBudget.exceeded()) {
181
+ endReason = "cost-budget-exhausted";
182
+ stopForCost = true;
183
+ }
184
+ }
172
185
  break;
173
186
  case "iteration-warning":
174
187
  emit({ type: "iteration_warning", message: event.message });
@@ -187,6 +200,9 @@ async function runTurn(messages, loopOptions, { runLoop, emit }) {
187
200
  if (event.type) emit(event);
188
201
  break;
189
202
  }
203
+ // Hard cost cap reached — stop consuming the loop (break the for-await, not
204
+ // just the switch) so no further paid LLM call is made.
205
+ if (stopForCost) break;
190
206
  }
191
207
  return { finalText, endReason, usage, toolCalls };
192
208
  }
@@ -458,6 +474,9 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
458
474
  mcpConfigPath: options.mcpConfig || null,
459
475
  db: db?.getDatabase?.() || null,
460
476
  includeRegistered: options.useRegisteredMcp !== false,
477
+ // --strict-mcp-config: only the --mcp-config servers (ignore
478
+ // registered + IDE bridge) for a reproducible MCP surface.
479
+ strict: options.strictMcpConfig === true,
461
480
  ide: options.ide,
462
481
  cwd: options.cwd || process.cwd(),
463
482
  // advertise the session id to spawned stdio MCP servers
@@ -553,6 +572,13 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
553
572
  : undefined,
554
573
  };
555
574
 
575
+ // --max-budget-usd: a SESSION-WIDE USD spend cap across all turns. Folded
576
+ // from token-usage in runTurn; once reached the session ends before the next
577
+ // paid call. null → no cap (unchanged behavior).
578
+ const costBudget = options.maxCostUsd
579
+ ? new CostBudget({ limitUsd: options.maxCostUsd, table: options.priceTable })
580
+ : null;
581
+
556
582
  let turns = 0;
557
583
  let sawError = false;
558
584
 
@@ -686,6 +712,18 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
686
712
  }
687
713
  }
688
714
 
715
+ // --replay-user-messages: echo each accepted user message back on the
716
+ // output stream (Claude-Code parity) so a consumer can correlate replies to
717
+ // inputs / log the transcript. Echoes the raw user text, before @file or
718
+ // IDE-context expansion.
719
+ if (options.replayUserMessages && parsed.text) {
720
+ emit({
721
+ type: "user",
722
+ message: { role: "user", content: parsed.text },
723
+ session_id: sessionId,
724
+ });
725
+ }
726
+
689
727
  // Per-turn iteration budget so one turn can't starve the rest.
690
728
  const budget = Number.isFinite(options.maxTurns)
691
729
  ? new IterationBudget({
@@ -795,7 +833,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
795
833
  outcome = await runTurn(
796
834
  messages,
797
835
  { ...loopOptionsBase, iterationBudget: budget, signal: turnSignal },
798
- { runLoop, emit },
836
+ { runLoop, emit, costBudget },
799
837
  );
800
838
  } catch (err) {
801
839
  currentAbort = null;
@@ -840,12 +878,29 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
840
878
  const exhausted =
841
879
  outcome.endReason === "budget-exhausted" ||
842
880
  outcome.endReason === "max_turns";
843
- const isError = exhausted || outcome.endReason === "no-response";
881
+ const costStopped = outcome.endReason === "cost-budget-exhausted";
882
+ const isError = exhausted || costStopped || outcome.endReason === "no-response";
844
883
  if (isError) sawError = true;
845
884
 
885
+ if (costStopped) {
886
+ emit({
887
+ type: "cost_budget_exhausted",
888
+ limit_usd: options.maxCostUsd,
889
+ spent_usd: costBudget?.spentUsd,
890
+ session_id: sessionId,
891
+ turn: turns,
892
+ });
893
+ }
894
+
846
895
  emit({
847
896
  type: "result",
848
- subtype: exhausted ? "error_max_turns" : isError ? "error" : "success",
897
+ subtype: exhausted
898
+ ? "error_max_turns"
899
+ : costStopped
900
+ ? "error_max_budget"
901
+ : isError
902
+ ? "error"
903
+ : "success",
849
904
  is_error: isError,
850
905
  result: outcome.finalText,
851
906
  session_id: sessionId,
@@ -853,6 +908,9 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
853
908
  usage: outcome.usage,
854
909
  });
855
910
 
911
+ // Session-wide cost cap reached → stop accepting further turns.
912
+ if (costStopped) break;
913
+
856
914
  // While planning, blocked tool calls grew the plan during this turn —
857
915
  // push the fresh snapshot so the panel's plan card stays live.
858
916
  {
@@ -400,6 +400,12 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
400
400
  if (args.mcpConfigPath) {
401
401
  result = await doFile(args.mcpConfigPath, fwd); // fail-fast on bad file
402
402
  }
403
+ // --strict-mcp-config: use ONLY the explicit --mcp-config servers; ignore the
404
+ // registered (cc mcp add) set and IDE-bridge auto-discovery so the run's MCP
405
+ // surface is fully reproducible (Claude-Code parity).
406
+ if (args.strict) {
407
+ return result;
408
+ }
403
409
  if (args.includeRegistered !== false && args.db) {
404
410
  result = await doReg(args.db, {
405
411
  ...fwd,
@@ -1 +0,0 @@
1
- import{I as v,P as u,J as S,U as n,R as a,S as y,K as C,Q as x,V as w,_ as B,b as s}from"./vendor-BvqAck49.js";import{_ as k}from"./index-Cmr31VCO.js";import"./icons-DP3uiYxy.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=s(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=s(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=s(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=s(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=s(()=>{if(!t.event.occurredAt)return"";try{const e=new Date(t.event.occurredAt),p=e.getFullYear(),f=String(e.getMonth()+1).padStart(2,"0"),g=String(e.getDate()).padStart(2,"0"),b=String(e.getHours()).padStart(2,"0"),h=String(e.getMinutes()).padStart(2,"0");return`${p}-${f}-${g} ${b}:${h}`}catch{return""}}),_={props:t,messageText:r,actorLabel:i,isMine:l,adapterColor:o,formattedTime:m,computed:s};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},T={class:"bubble"},M={class:"meta"},R={class:"actor"},V={class:"time"},q={class:"body"};function A(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[n("div",T,[n("div",M,[n("span",R,a(r.actorLabel),1),n("span",V,a(r.formattedTime),1)]),n("div",q,a(r.messageText),1),t.event.source.adapter?(u(),y(o,{key:0,class:"src",color:r.adapterColor},{default:C(()=>[x(a(t.event.source.adapter),1)]),_:1},8,["color"])):w("v-if",!0)])],2)}const j=k(N,[["render",A],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{j as default};
@@ -1,7 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ChatBubbleRenderer-DEXSa7tC.js","./vendor-BvqAck49.js","./index-Cmr31VCO.js","./icons-DP3uiYxy.js","./index-Cq93VfoF.css","./ChatBubbleRenderer-gy5SDGw2.css","./OrderTableRenderer-CDMZ3o6i.js","./OrderTableRenderer-CfrDjSHT.css","./TimelineRenderer-Bh8jA18j.js","./TimelineRenderer-BlTAtkOc.css","./EmailListRenderer-BWKHbh4C.js","./EmailListRenderer-DTPZPx_S.css","./GenericCardRenderer-DI1oL4pK.js","./GenericCardRenderer-o85VDYQS.css"])))=>i.map(i=>d[i]);
2
- import{E as ue,r as R,b as C,I as y,P as u,J as O,U as v,c,S as w,V as E,_ as M,F as V,Z as se,a0 as le,R as A,K as m,Q as b,W as L,o as J}from"./vendor-BvqAck49.js";import{u as U}from"./usePersonalDataHub-D8KrYSq4.js";import{_ as D,e as F,d as P}from"./index-Cmr31VCO.js";import{a9 as q,af as K,M as z,aH as Q,u as G,aG as H,ap as W,ab as Y,e as de,d as fe,k as pe,ah as me,az as _e,R as ge}from"./icons-DP3uiYxy.js";const I=Object.freeze({q:"",category:null,adapter:null,subtype:null,since:null,until:null}),B=50,Z=300,X=ue("pdhBrowser",()=>{const r=R({...I}),t=R([]),n=R(null),e=R(!1),o=R(!1),l=R(null),a=R(null),s=R(!1),i=R({byCategory:{},byAdapter:{},bySubtype:{},total:0});let d=0,_=null;const x=C(()=>t.value.length>0),j=C(()=>n.value!=null);function h(S={}){const p={},f=r.value;return f.q&&f.q.trim()&&(p.q=f.q.trim()),f.category&&(p.category=f.category),f.adapter&&(p.adapter=f.adapter),f.subtype&&(p.subtype=f.subtype),Number.isFinite(f.since)&&(p.since=f.since),Number.isFinite(f.until)&&(p.until=f.until),{...p,...S}}async function g(){const S=++d;e.value=!0,l.value=null;const p=U();try{const[f,T]=await Promise.all([p.searchEvents(h({limit:B})),p.facetCounts({...r.value.q&&r.value.q.trim()?{q:r.value.q.trim()}:{},...Number.isFinite(r.value.since)?{since:r.value.since}:{},...Number.isFinite(r.value.until)?{until:r.value.until}:{}})]);if(S!==d)return;t.value=f.rows||[],n.value=f.nextCursor||null,a.value=f.mode||"like",s.value=!!f.shortQuery,i.value={byCategory:T.byCategory||{},byAdapter:T.byAdapter||{},bySubtype:T.bySubtype||{},total:T.total||0}}catch(f){if(S!==d)return;l.value=f&&f.message?f.message:String(f),t.value=[],n.value=null}finally{S===d&&(e.value=!1)}}async function k(){if(!n.value||o.value)return;o.value=!0,l.value=null;const S=U();try{const p=await S.searchEvents(h({cursor:n.value,limit:B}));t.value=t.value.concat(p.rows||[]),n.value=p.nextCursor||null,a.value=p.mode||a.value}catch(p){l.value=p&&p.message?p.message:String(p)}finally{o.value=!1}}function ae(S,p){if(!(S in I))throw new Error(`pdhBrowser.setFilter: unknown key "${S}"`);r.value={...r.value,[S]:p},_&&clearTimeout(_),_=setTimeout(()=>{_=null,g()},Z)}function ie(S){return r.value={...I,...S},_&&(clearTimeout(_),_=null),g()}function ce(){r.value={...I},t.value=[],n.value=null,l.value=null,i.value={byCategory:{},byAdapter:{},bySubtype:{},total:0}}return{filters:r,results:t,cursor:n,isLoading:e,isAppending:o,error:l,mode:a,shortQuery:s,facets:i,hasResults:x,canLoadMore:j,search:g,loadMore:k,setFilter:ae,setFilters:ie,reset:ce,PAGE_SIZE:B,SEARCH_DEBOUNCE_MS:Z}}),ye=Object.freeze(["chat","social","email","shopping","travel","system","ai-chat","other"]),ve=Object.freeze({chat:"社交聊天",social:"内容平台",email:"邮件",shopping:"支付订单",travel:"出行",system:"系统数据","ai-chat":"AI 对话",other:"其他"});function N(r){return ve[r]||r||"未知"}const be=Object.freeze([["wechat","chat"],["messaging-","chat"],["social-","social"],["email-","email"],["shopping-","shopping"],["alipay-","shopping"],["travel-","travel"],["system-data","system"],["browser-","system"],["vscode","system"],["win-recent","system"],["git-activity","system"],["shell-history","system"],["local-files","system"],["ai-chat-","ai-chat"]]);function $(r){if(typeof r!="string"||r.length===0)return"other";for(const[t,n]of be)if(t.endsWith("-")||t==="system-data"){if(r.startsWith(t))return n}else if(r===t)return n;return"other"}const he={__name:"CategorySidebar",props:{selected:{type:String,default:null},facets:{type:Object,default:()=>({byCategory:{},total:0})}},emits:["select"],setup(r,{expose:t}){t();const n=r,e=C(()=>n.facets.total||0),o={chat:Y,social:W,email:H,shopping:G,travel:Q,system:z,"ai-chat":K,other:q};function l(i){return o[i]||q}function a(i){return i?{backgroundColor:"#fff",color:"#1677ff"}:{backgroundColor:"#f0f0f0",color:"#666"}}const s={props:n,total:e,ICONS:o,iconFor:l,badgeStyle:a,computed:C,get AppstoreOutlined(){return q},get MessageOutlined(){return Y},get PlayCircleOutlined(){return W},get MailOutlined(){return H},get ShoppingOutlined(){return G},get CarOutlined(){return Q},get MobileOutlined(){return z},get RobotOutlined(){return K},get CATEGORIES(){return ye},get categoryLabel(){return N}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}},Se={class:"pdh-sidebar"},Oe=["onClick"],Ce={class:"label"};function we(r,t,n,e,o,l){const a=y("a-badge");return u(),O("div",Se,[t[2]||(t[2]=v("div",{class:"sidebar-title"},"数据类型",-1)),v("div",{class:M(["cat-item",{active:n.selected===null}]),onClick:t[0]||(t[0]=s=>r.$emit("select",null))},[c(e.AppstoreOutlined,{class:"icon"}),t[1]||(t[1]=v("span",{class:"label"},"全部",-1)),e.total>0?(u(),w(a,{key:0,count:e.total,"number-style":e.badgeStyle(n.selected===null),"overflow-count":9999},null,8,["count","number-style"])):E("v-if",!0)],2),(u(!0),O(V,null,se(e.CATEGORIES,s=>(u(),O("div",{key:s,class:M(["cat-item",{active:n.selected===s,dim:!n.facets.byCategory[s]}]),onClick:i=>r.$emit("select",s)},[(u(),w(le(e.iconFor(s)),{class:"icon"})),v("span",Ce,A(e.categoryLabel(s)),1),n.facets.byCategory[s]?(u(),w(a,{key:0,count:n.facets.byCategory[s],"number-style":e.badgeStyle(n.selected===s),"overflow-count":9999},null,8,["count","number-style"])):E("v-if",!0)],10,Oe))),128))])}const ke=D(he,[["render",we],["__scopeId","data-v-6b62a22e"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/components/pdh/CategorySidebar.vue"]]),Ee={__name:"SearchFilterBar",props:{filters:{type:Object,required:!0},facets:{type:Object,default:()=>({byAdapter:{}})},isLoading:{type:Boolean,default:!1},mode:{type:String,default:null},shortQuery:{type:Boolean,default:!1}},emits:["set-filter","reset"],setup(r,{expose:t,emit:n}){t();const e=r,o=n,l=C(()=>e.filters.category?`在「${e.filters.category}」类目内搜索…`:"搜索关键词(如:支付宝、罗技、Kotlin)…"),a=C(()=>Object.entries(e.facets.byAdapter||{}).sort((g,k)=>k[1]-g[1]).map(([g,k])=>({value:g,label:`${g} (${k})`}))),s=C(()=>!e.filters.since&&!e.filters.until?null:[e.filters.since?new Date(e.filters.since):null,e.filters.until?new Date(e.filters.until):null]),i=C(()=>!!(e.filters.q||e.filters.adapter||e.filters.subtype||e.filters.since||e.filters.until));function d(h){o("set-filter","q",h||"")}function _(h){o("set-filter","q",h||"")}function x(h){if(!h||h.length===0){o("set-filter","since",null),o("set-filter","until",null);return}const[g,k]=h;o("set-filter","since",g?+g:null),o("set-filter","until",k?+k:null)}const j={props:e,emit:o,placeholderText:l,adapterOptions:a,dateRangeValue:s,hasActiveFilters:i,onQInput:d,onSearch:_,onDateChange:x,computed:C,get SearchOutlined(){return pe},get CloseCircleOutlined(){return fe},get InfoCircleOutlined(){return de}};return Object.defineProperty(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}},Re={class:"pdh-filter-bar"},Ae={key:1,class:"hint"},xe={key:2,class:"hint"};function je(r,t,n,e,o,l){const a=y("a-input-search"),s=y("a-select"),i=y("a-range-picker"),d=y("a-button");return u(),O("div",Re,[c(a,{value:n.filters.q,placeholder:e.placeholderText,"enter-button":"搜索","allow-clear":"",loading:n.isLoading,style:{flex:"1","max-width":"480px"},"onUpdate:value":e.onQInput,onSearch:e.onSearch},{prefix:m(()=>[c(e.SearchOutlined)]),_:1},8,["value","placeholder","loading"]),c(s,{value:n.filters.adapter,placeholder:"所有 adapter","allow-clear":"",options:e.adapterOptions,style:{width:"200px"},"onUpdate:value":t[0]||(t[0]=_=>r.$emit("set-filter","adapter",_||null))},null,8,["value","options"]),c(i,{value:e.dateRangeValue,placeholder:["开始日期","结束日期"],style:{width:"280px"},"onUpdate:value":e.onDateChange},null,8,["value"]),e.hasActiveFilters?(u(),w(d,{key:0,type:"link",danger:"",onClick:t[1]||(t[1]=_=>r.$emit("reset"))},{icon:m(()=>[c(e.CloseCircleOutlined)]),default:m(()=>[t[2]||(t[2]=b(" 清空筛选 ",-1))]),_:1})):E("v-if",!0),n.shortQuery?(u(),O("span",Ae,[c(e.InfoCircleOutlined),t[3]||(t[3]=b(" 关键词需至少 3 字 (FTS5 trigram 限制) ",-1))])):n.mode==="like"?(u(),O("span",xe,[c(e.InfoCircleOutlined),t[4]||(t[4]=b(" 当前为 LIKE 兜底模式 ",-1))])):E("v-if",!0)])}const Le=D(Ee,[["render",je],["__scopeId","data-v-d7cce6e9"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/components/pdh/SearchFilterBar.vue"]]),Fe={__name:"RendererDispatcher",props:{event:{type:Object,required:!0}},setup(r,{expose:t}){t();const n=L(()=>F(()=>import("./ChatBubbleRenderer-DEXSa7tC.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url)),e=L(()=>F(()=>import("./OrderTableRenderer-CDMZ3o6i.js"),__vite__mapDeps([6,1,2,3,4,7]),import.meta.url)),o=L(()=>F(()=>import("./TimelineRenderer-Bh8jA18j.js"),__vite__mapDeps([8,1,2,3,4,9]),import.meta.url)),l=L(()=>F(()=>import("./EmailListRenderer-BWKHbh4C.js"),__vite__mapDeps([10,1,2,3,4,11]),import.meta.url)),a=L(()=>F(()=>import("./GenericCardRenderer-DI1oL4pK.js"),__vite__mapDeps([12,1,2,3,4,13]),import.meta.url));function s(d){const _=d&&d.source&&d.source.adapter;switch($(_)){case"chat":case"ai-chat":return n;case"shopping":return e;case"travel":return o;case"email":return l;default:return a}}const i={ChatBubbleRenderer:n,OrderTableRenderer:e,TimelineRenderer:o,EmailListRenderer:l,GenericCardRenderer:a,rendererFor:s,defineAsyncComponent:L,get getCategory(){return $}};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}};function De(r,t,n,e,o,l){return u(),w(le(e.rendererFor(n.event)),{event:n.event},null,8,["event"])}const Te=D(Fe,[["render",De],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/components/pdh/renderers/RendererDispatcher.vue"]]);function ee(r){return JSON.stringify(r,null,2)}function te(r){return r.map(t=>JSON.stringify(t)).join(`
3
- `)+`
4
- `}function ne(r){const n=["id","subtype","occurredAt","occurredAtIso","actor","place","adapter","summary","contentJson","extraJson"].join(","),e=r.map(o=>{const l=Number.isFinite(o.occurredAt)?o.occurredAt:null,a=l?new Date(l).toISOString():"",s=o.source&&o.source.adapter||"",i=o.content&&(o.content.text||o.content.title||o.content.subject)||"";return[o.id||"",o.subtype||"",l!=null?String(l):"",a,o.actor||"",o.place||"",s,i,o.content?JSON.stringify(o.content):"",o.extra?JSON.stringify(o.extra):""].map(Ie).join(",")});return[n,...e].join(`
5
- `)+`
6
- `}function Ie(r){const t=String(r??"");return t.includes(",")||t.includes('"')||t.includes(`
7
- `)||t.includes("\r")?'"'+t.replace(/"/g,'""')+'"':t}function re(r,t,n="application/octet-stream"){if(typeof window>"u"||typeof document>"u")return t;const e=new Blob([r],{type:n}),o=URL.createObjectURL(e),l=document.createElement("a");return l.href=o,l.download=t,document.body.appendChild(l),l.click(),document.body.removeChild(l),setTimeout(()=>URL.revokeObjectURL(o),1e3),t}function oe(r,t=null){const n=new Date,e=n.getFullYear(),o=String(n.getMonth()+1).padStart(2,"0"),l=String(n.getDate()).padStart(2,"0"),a=r==="ndjson"?"ndjson":r,s=t?`-${t}`:"";return`pdh-events-${e}-${o}-${l}${s}.${a}`}const Pe={__name:"ExportDropdown",props:{events:{type:Array,required:!0},category:{type:String,default:null}},setup(r,{expose:t}){t();const n=r,e=C(()=>n.events.length>0),o={json:"application/json;charset=utf-8",ndjson:"application/x-ndjson;charset=utf-8",csv:"text/csv;charset=utf-8"};function l(i){switch(i){case"json":return ee(n.events);case"ndjson":return te(n.events);case"csv":return ne(n.events);default:throw new Error(`unknown format: ${i}`)}}function a({key:i}){try{const d=l(i),_=oe(i,n.category);re(d,_,o[i]),P.success(`已导出 ${n.events.length} 条到 ${_}`)}catch(d){P.error(`导出失败: ${d.message||d}`)}}const s={props:n,hasResults:e,MIME:o,serialize:l,onClick:a,computed:C,get DownloadOutlined(){return _e},get DownOutlined(){return me},get message(){return P},get eventsToJson(){return ee},get eventsToNdjson(){return te},get eventsToCsv(){return ne},get downloadAs(){return re},get suggestFilename(){return oe}};return Object.defineProperty(s,"__isScriptSetup",{enumerable:!1,value:!0}),s}};function qe(r,t,n,e,o,l){const a=y("a-button"),s=y("a-menu-item"),i=y("a-menu"),d=y("a-dropdown");return u(),w(d,{disabled:!e.hasResults},{overlay:m(()=>[c(i,{onClick:e.onClick},{default:m(()=>[c(s,{key:"json"},{default:m(()=>[...t[0]||(t[0]=[b("JSON (.json)",-1)])]),_:1}),c(s,{key:"ndjson"},{default:m(()=>[...t[1]||(t[1]=[b("NDJSON (.ndjson)",-1)])]),_:1}),c(s,{key:"csv"},{default:m(()=>[...t[2]||(t[2]=[b("CSV (.csv)",-1)])]),_:1})]),_:1})]),default:m(()=>[c(a,{disabled:!e.hasResults},{icon:m(()=>[c(e.DownloadOutlined)]),default:m(()=>[b(" 导出 ("+A(n.events.length)+") ",1),c(e.DownOutlined)]),_:1},8,["disabled"])]),_:1},8,["disabled"])}const Be=D(Pe,[["render",qe],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/components/pdh/ExportDropdown.vue"]]),Ve={__name:"PdhVaultBrowser",setup(r,{expose:t}){t();const n=X(),e=C(()=>n.filters.q?`没有匹配 "${n.filters.q}" 的事件 — 试试更短的关键词或换个类目`:n.filters.category?`「${N(n.filters.category)}」类目下还没有数据 — 去采集页同步对应 adapter`:"Vault 里还没有数据 — 去「个人数据中台」页面同步任意 adapter");function o(s){n.filters.category=s,n.search()}function l(s,i){n.setFilter(s,i)}J(()=>{!n.hasResults&&!n.isLoading&&n.search()});const a={store:n,emptyHint:e,onCategorySelect:o,onSetFilter:l,onMounted:J,computed:C,get ReloadOutlined(){return ge},get usePdhBrowserStore(){return X},get categoryLabel(){return N},CategorySidebar:ke,SearchFilterBar:Le,RendererDispatcher:Te,ExportDropdown:Be};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}},Ne={class:"pdh-browser-page"},Me={class:"page-header"},Je={class:"main-pane"},Ue={class:"results-summary"},Ke={key:0},ze={key:0},Qe={key:1},Ge={class:"loaded-of"},He={class:"results-list"},We={key:2,class:"load-more"};function Ye(r,t,n,e,o,l){const a=y("a-tag"),s=y("a-button"),i=y("a-space"),d=y("a-col"),_=y("a-spin"),x=y("a-alert"),j=y("a-empty"),h=y("a-row");return u(),O("div",Ne,[v("div",Me,[t[6]||(t[6]=v("div",null,[v("h2",{class:"page-title"},"数据浏览器"),v("p",{class:"page-sub"}," Vault 里所有已采集的数据,按类目浏览 / 全文检索 / 时间窗口筛选。 完全离线,不外传。 ")],-1)),c(i,null,{default:m(()=>[e.store.mode==="fts5"?(u(),w(a,{key:0,color:"green"},{default:m(()=>[...t[3]||(t[3]=[b("FTS5 trigram",-1)])]),_:1})):e.store.mode==="like"?(u(),w(a,{key:1,color:"orange"},{default:m(()=>[...t[4]||(t[4]=[b("LIKE 兜底",-1)])]),_:1})):E("v-if",!0),c(e.ExportDropdown,{events:e.store.results,category:e.store.filters.category},null,8,["events","category"]),c(s,{onClick:t[0]||(t[0]=g=>e.store.search()),loading:e.store.isLoading},{icon:m(()=>[c(e.ReloadOutlined)]),default:m(()=>[t[5]||(t[5]=b(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),c(h,{gutter:16,class:"browser-layout"},{default:m(()=>[c(d,{xs:24,sm:24,md:6,lg:5,xl:4},{default:m(()=>[c(e.CategorySidebar,{selected:e.store.filters.category,facets:e.store.facets,onSelect:e.onCategorySelect},null,8,["selected","facets"])]),_:1}),c(d,{xs:24,sm:24,md:18,lg:19,xl:20},{default:m(()=>[v("div",Je,[c(e.SearchFilterBar,{filters:e.store.filters,facets:e.store.facets,"is-loading":e.store.isLoading,mode:e.store.mode,"short-query":e.store.shortQuery,onSetFilter:e.onSetFilter,onReset:t[1]||(t[1]=g=>{e.store.reset(),e.store.search()})},null,8,["filters","facets","is-loading","mode","short-query"]),v("div",Ue,[e.store.isLoading&&e.store.results.length===0?(u(),O("span",Ke,[c(_,{size:"small"}),t[7]||(t[7]=b(" 载入中… ",-1))])):(u(),O(V,{key:1},[v("strong",null,A(e.store.facets.total),1),t[11]||(t[11]=b(" 条事件 ",-1)),e.store.filters.category?(u(),O("span",ze,[t[8]||(t[8]=b(" / 当前类目 ",-1)),v("strong",null,A(e.categoryLabel(e.store.filters.category)),1),v("strong",null,A(e.store.facets.byCategory[e.store.filters.category]||0),1)])):E("v-if",!0),e.store.filters.q?(u(),O("span",Qe,[t[9]||(t[9]=b(' / 关键词 "',-1)),v("em",null,A(e.store.filters.q),1),t[10]||(t[10]=b('"',-1))])):E("v-if",!0),v("span",Ge," / 已显示 "+A(e.store.results.length),1)],64))]),e.store.error?(u(),w(x,{key:0,type:"error","show-icon":"",message:e.store.error,closable:"",style:{margin:"12px 0"}},null,8,["message"])):E("v-if",!0),!e.store.isLoading&&e.store.results.length===0&&!e.store.error?(u(),w(j,{key:1,description:e.emptyHint,style:{"margin-top":"40px"}},null,8,["description"])):E("v-if",!0),v("div",He,[(u(!0),O(V,null,se(e.store.results,(g,k)=>(u(),w(e.RendererDispatcher,{key:`r-${k}-${g.id}`,event:g},null,8,["event"]))),128))]),e.store.canLoadMore?(u(),O("div",We,[c(s,{loading:e.store.isAppending,onClick:t[2]||(t[2]=g=>e.store.loadMore()),block:""},{default:m(()=>[...t[12]||(t[12]=[b(" 加载下一页 (50 条) ",-1)])]),_:1},8,["loading"])])):E("v-if",!0)])]),_:1})]),_:1})])}const tt=D(Ve,[["render",Ye],["__scopeId","data-v-0f7c02cd"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/views/PdhVaultBrowser.vue"]]);export{tt as default};
@@ -1 +0,0 @@
1
- import{E as B,b as z,r as D,I as p,J as c,U as _,c as n,K as a,S,V as w,o as P,x as I,P as i,Q as g,R as r,F as h,Z as F}from"./vendor-BvqAck49.js";import{u as R,_ as O}from"./index-Cmr31VCO.js";import{R as E}from"./icons-DP3uiYxy.js";const V=B("tasks",()=>{const k=D([]),l=D(!1);let u=null,e=null;const x=z(()=>k.value.filter(t=>t.status==="running")),b=z(()=>k.value.filter(t=>t.status==="pending")),y=z(()=>k.value.filter(t=>t.status==="completed"||t.status==="failed"||t.status==="timeout"));async function f(){const t=R();l.value=!0;try{const s=await t.sendRaw({type:"tasks-list"});s&&Array.isArray(s.tasks)&&(k.value=s.tasks)}catch{}finally{l.value=!1}}async function o(t){const s=R();try{await s.sendRaw({type:"tasks-stop",taskId:t})}catch{}finally{await f()}}const d=D(null);function m(t=5e3){v(),f(),u=setInterval(f,t),T()}function v(){u&&(clearInterval(u),u=null),e&&(e(),e=null)}function T(){const t=R();if(e)return;const s=C=>{C.type==="task:notification"&&C.payload?.task&&(d.value=C.payload.task,f(),setTimeout(()=>{d.value=null},8e3))};e=t.onRuntimeEvent(s)}function N(t){return!t||t<0?"-":t<1e3?`${t}ms`:t<6e4?`${(t/1e3).toFixed(1)}s`:`${(t/6e4).toFixed(1)}m`}function A(t){switch(t){case"running":return"processing";case"pending":return"default";case"completed":return"success";case"failed":return"error";case"timeout":return"warning";default:return"default"}}return{tasks:k,loading:l,running:x,pending:b,completed:y,lastNotification:d,fetchTasks:f,stopTask:o,startPolling:m,stopPolling:v,formatDuration:N,getStatusColor:A}}),U={__name:"Tasks",setup(k,{expose:l}){l();const u=V(),e=[{title:"状态",key:"status",width:90},{title:"描述",key:"description",ellipsis:!0},{title:"类型",dataIndex:"type",width:100},{title:"耗时",key:"duration",width:90},{title:"创建时间",key:"createdAt",width:180},{title:"结果",key:"result",ellipsis:!0},{title:"操作",key:"action",width:80}];function x(o){return o.status==="running"&&o.startedAt?u.formatDuration(Date.now()-o.startedAt):o.completedAt&&o.startedAt?u.formatDuration(o.completedAt-o.startedAt):"-"}function b(o){return o?new Date(o).toLocaleString():"-"}function y(o,d){return o?o.length>d?`${o.slice(0,d)}...`:o:""}P(()=>u.startPolling(5e3)),I(()=>u.stopPolling());const f={store:u,columns:e,getDuration:x,formatTime:b,truncate:y,onMounted:P,onUnmounted:I,get ReloadOutlined(){return E},get useTasksStore(){return V}};return Object.defineProperty(f,"__isScriptSetup",{enumerable:!1,value:!0}),f}},K={class:"page-header"},L={key:0,class:"error-text"},j={key:1},J={class:"task-header"},M={class:"task-desc"},Q={class:"task-id"},W={class:"task-meta"},Z=["title"],q={key:0,class:"error-text"},G={key:1,class:"success-text"},H={key:2,class:"muted-text"};function X(k,l,u,e,x,b){const y=p("a-button"),f=p("a-space"),o=p("a-alert"),d=p("a-statistic"),m=p("a-card"),v=p("a-col"),T=p("a-row"),N=p("a-tag"),A=p("a-table");return i(),c("div",null,[_("div",K,[l[3]||(l[3]=_("div",null,[_("h2",{class:"page-title"},"后台任务"),_("p",{class:"page-sub"},"查看后台任务队列、实时通知和任务执行结果。")],-1)),n(f,null,{default:a(()=>[n(y,{ghost:"",loading:e.store.loading,onClick:l[0]||(l[0]=t=>e.store.fetchTasks())},{icon:a(()=>[n(e.ReloadOutlined)]),default:a(()=>[l[2]||(l[2]=g(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.store.lastNotification?(i(),S(o,{key:0,type:e.store.lastNotification.status==="completed"?"success":"error","show-icon":"",closable:"",class:"banner",onClose:l[1]||(l[1]=t=>e.store.lastNotification=null)},{message:a(()=>[g(" 任务"+r(e.store.lastNotification.status==="completed"?"完成":"结束")+": "+r(e.store.lastNotification.description||e.store.lastNotification.id.slice(0,16)),1)]),description:a(()=>[e.store.lastNotification.error?(i(),c("span",L,r(e.store.lastNotification.error),1)):e.store.lastNotification.result?(i(),c("span",j,r(e.truncate(String(e.store.lastNotification.result),120)),1)):w("v-if",!0)]),_:1},8,["type"])):w("v-if",!0),n(T,{gutter:[16,16],class:"stats-row"},{default:a(()=>[n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"全部任务",value:e.store.tasks.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"运行中",value:e.store.running.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"等待中",value:e.store.pending.length},null,8,["value"])]),_:1})]),_:1}),n(v,{xs:12,sm:6},{default:a(()=>[n(m,{class:"stat-card",size:"small"},{default:a(()=>[n(d,{title:"已完成",value:e.store.completed.length},null,8,["value"])]),_:1})]),_:1})]),_:1}),e.store.running.length>0?(i(),S(m,{key:1,title:"运行中的任务",class:"panel-card",size:"small"},{default:a(()=>[(i(!0),c(h,null,F(e.store.running,t=>(i(),c("div",{key:t.id,class:"task-item running"},[_("div",J,[n(N,{color:e.store.getStatusColor(t.status)},{default:a(()=>[g(r(t.status.toUpperCase()),1)]),_:2},1032,["color"]),_("span",M,r(t.description),1),_("span",Q,r(t.id.slice(0,16)),1)]),_("div",W,[_("span",null,"类型: "+r(t.type||"-"),1),_("span",null,"已运行: "+r(e.store.formatDuration(Date.now()-t.startedAt)),1),n(y,{size:"small",danger:"",onClick:s=>e.store.stopTask(t.id)},{default:a(()=>[...l[4]||(l[4]=[g("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):w("v-if",!0),n(m,{class:"panel-card"},{default:a(()=>[n(A,{columns:e.columns,"data-source":e.store.tasks,pagination:{pageSize:15,size:"small"},loading:e.store.loading,"row-key":"id",size:"small"},{bodyCell:a(({column:t,record:s})=>[t.key==="status"?(i(),S(N,{key:0,color:e.store.getStatusColor(s.status)},{default:a(()=>[g(r(s.status),1)]),_:2},1032,["color"])):t.key==="description"?(i(),c("span",{key:1,title:s.command},r(s.description),9,Z)):t.key==="duration"?(i(),c(h,{key:2},[g(r(e.getDuration(s)),1)],64)):t.key==="createdAt"?(i(),c(h,{key:3},[g(r(e.formatTime(s.createdAt)),1)],64)):t.key==="result"?(i(),c(h,{key:4},[s.error?(i(),c("span",q,r(e.truncate(s.error,60)),1)):s.result?(i(),c("span",G,r(e.truncate(String(s.result),60)),1)):(i(),c("span",H,"-"))],64)):t.key==="action"?(i(),c(h,{key:5},[s.status==="running"?(i(),S(y,{key:0,size:"small",danger:"",onClick:C=>e.store.stopTask(s.id)},{default:a(()=>[...l[5]||(l[5]=[g(" 停止 ",-1)])]),_:1},8,["onClick"])):w("v-if",!0)],64)):w("v-if",!0)]),_:1},8,["data-source","loading"])]),_:1})])}const et=O(U,[["render",X],["__scopeId","data-v-da5ff6a2"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/views/Tasks.vue"]]);export{et as default};
@@ -1,3 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./xterm-BZcWGsqw.js","./markdown-CsiA8-E5.js","./markdown-Dfs9RUU9.css","./addon-fit-CK6X9sAG.js","./xterm-DFuMZ0ql.css"])))=>i.map(i=>d[i]);
2
- import{u as fe,_ as me,d as V,e as U}from"./index-Cmr31VCO.js";import{I as z,J as x,U as _,Q as D,S as Q,K as T,V as R,c as A,F as Y,Z,R as E,o as G,f as H,w as $,n as q,b as ee,r as S,P as y,_ as ve,a2 as we,a3 as he,a4 as _e}from"./vendor-BvqAck49.js";import{R as ye,b as pe,as as ge}from"./icons-DP3uiYxy.js";const k=new Map,C=new Map,N=new Set,F=new Set;let te=!1;function xe(c){te||(te=!0,c.onMessage(o=>{if(!(!o||typeof o.type!="string")){if(o.type==="terminal.stdout"){const{sessionId:s,data:e,seq:i}=o.payload||{};if(!s)return;let w;try{const d=atob(e||""),f=new Uint8Array(d.length);for(let n=0;n<d.length;n++)f[n]=d.charCodeAt(n);w=new TextDecoder("utf-8").decode(f)}catch{w=""}const u={sessionId:s,data:w,seq:i};k.get(s)?.forEach(d=>d(u)),N.forEach(d=>d(u))}else if(o.type==="terminal.exit"){const{sessionId:s,exitCode:e,signal:i}=o.payload||{};if(!s)return;const w={sessionId:s,exitCode:e,signal:i};C.get(s)?.forEach(u=>u(w)),F.forEach(u=>u(w))}}}))}function ne(c){const o=new TextEncoder().encode(c);let s="";for(let e=0;e<o.length;e++)s+=String.fromCharCode(o[e]);return btoa(s)}function ae(c){const o=atob(c||""),s=new Uint8Array(o.length);for(let e=0;e<o.length;e++)s[e]=o.charCodeAt(e);return new TextDecoder("utf-8").decode(s)}function oe(){const c=fe();xe(c);async function o(n={}){const a=await c.sendRaw({type:"terminal.create",payload:{shell:n.shell,cwd:n.cwd,env:n.env,cols:n.cols,rows:n.rows}});if(a.ok===!1)throw new Error(a.error||"terminal_create_failed");return a.result??a}async function s(){const n=await c.sendRaw({type:"terminal.list",payload:{}});if(n.ok===!1)throw new Error(n.error||"terminal_list_failed");const a=n.result??n;return Array.isArray(a.sessions)?a.sessions:[]}async function e(n,a){const r=await c.sendRaw({type:"terminal.stdin",payload:{sessionId:n,data:ne(String(a))}});if(r.ok===!1)throw new Error(r.error||"terminal_stdin_failed");return r.result??r}async function i(n,a,r){const h=await c.sendRaw({type:"terminal.resize",payload:{sessionId:n,cols:a,rows:r}});if(h.ok===!1)throw new Error(h.error||"terminal_resize_failed");return h.result??h}async function w(n){const a=await c.sendRaw({type:"terminal.close",payload:{sessionId:n}});if(a.ok===!1)throw new Error(a.error||"terminal_close_failed");return a.result??a}async function u(n,a=0){const r=await c.sendRaw({type:"terminal.history",payload:{sessionId:n,fromSeq:a}});if(r.ok===!1)throw new Error(r.error||"terminal_history_failed");const h=r.result??r;return{truncated:!!h.truncated,chunks:(h.chunks||[]).map(L=>({seq:L.seq,data:ae(L.data)}))}}function d(n,a){return n?(k.has(n)||k.set(n,new Set),k.get(n).add(a),()=>{k.get(n)?.delete(a),k.get(n)?.size===0&&k.delete(n)}):(N.add(a),()=>N.delete(a))}function f(n,a){return n?(C.has(n)||C.set(n,new Set),C.get(n).add(a),()=>{C.get(n)?.delete(a),C.get(n)?.size===0&&C.delete(n)}):(F.add(a),()=>F.delete(a))}return{create:o,list:s,stdin:e,resize:i,close:w,history:u,onStdout:d,onExit:f,_internal:{stdoutSubs:k,exitSubs:C,toBase64Utf8:ne,fromBase64Utf8:ae}}}const Se={__name:"Terminal",setup(c,{expose:o}){o();const s=oe(),e=S([]),i=S(null),w=S("pwsh"),u=S(!1),d=S(!1),f=S(""),n=S(""),a=S([]),r=[{value:"pwsh",label:"PowerShell"},{value:"cmd",label:"CMD"},{value:"bash",label:"Bash"},{value:"wsl",label:"WSL"}],h=ee(()=>e.value.find(t=>t.id===i.value));function L(t){return t?t.slice(0,8):""}let O=null,M=null;async function I(){if(O)return{xtermMod:O,fitAddonMod:M};try{O=await U(()=>import("./xterm-BZcWGsqw.js").then(t=>t.x),__vite__mapDeps([0,1,2]),import.meta.url),M=await U(()=>import("./addon-fit-CK6X9sAG.js").then(t=>t.a),__vite__mapDeps([3,1,2]),import.meta.url),await U(()=>Promise.resolve({}),__vite__mapDeps([4]),import.meta.url)}catch(t){throw n.value="xterm 资源加载失败:"+(t?.message||"未知错误"),t}return{xtermMod:O,fitAddonMod:M}}async function B(t){await q();const{xtermMod:l,fitAddonMod:p}=await I(),b=a.value.find(v=>v?.dataset?.sessionId===t.id);if(!b)return;const m=new l.Terminal({cursorBlink:!0,fontFamily:'Consolas, "Courier New", monospace',fontSize:13,theme:{background:"#1e1e1e",foreground:"#d4d4d4"},convertEol:!1}),P=new p.FitAddon;m.loadAddon(P),m.open(b);try{P.fit()}catch{}t.xterm=m,t.fitAddon=P;const ie=m.onData(v=>{s.stdin(t.id,v).catch(g=>{String(g?.message||"").includes("dangerous_keyword_blocked")?V.warning("该命令被桌面端拦截(高危关键字)"):V.error("stdin 失败: "+(g?.message||g))})}),ce=s.onStdout(t.id,({data:v,seq:g})=>{t.lastSeq=g,m.write(v)}),de=s.onExit(t.id,({exitCode:v,signal:g})=>{t.alive=!1,t.exitCode=v,t.signal=g,m.writeln(`\r
3
- \x1B[33m[session exited, code=${v}, signal=${g??"-"}]\x1B[0m`)});t.offs=()=>{try{ie.dispose?.()}catch{}ce(),de()};try{const{chunks:v,truncated:g}=await s.history(t.id,0);g&&m.writeln("\x1B[2m[history truncated — earlier output was evicted]\x1B[0m");for(const J of v)m.write(J.data),t.lastSeq=J.seq}catch(v){m.writeln(`\x1B[31m[history fetch failed: ${v?.message||v}]\x1B[0m`)}const j=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});j.observe(b);const ue=t.offs;t.offs=()=>{try{j.disconnect()}catch{}ue()}}async function re(){u.value=!0,f.value="";try{const t=await s.create({shell:w.value,cols:80,rows:24}),l={id:t.sessionId,shell:t.shell,cwd:"",alive:!0,lastSeq:0,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(l),i.value=l.id,await B(l)}catch(t){f.value=t?.message||String(t)}finally{u.value=!1}}async function se(t){try{await s.close(t)}catch(l){f.value=l?.message||String(l)}setTimeout(()=>W(t),500)}function W(t){const l=e.value.findIndex(b=>b.id===t);if(l===-1)return;const p=e.value[l];try{p.offs?.()}catch{}try{p.xterm?.dispose?.()}catch{}e.value.splice(l,1),i.value===t&&(i.value=e.value[0]?.id||null)}function le(t){i.value=t,q(()=>{const l=e.value.find(p=>p.id===t);try{l?.fitAddon?.fit()}catch{}})}async function K(){d.value=!0,f.value="";try{const t=await s.list();for(const l of t){const p=e.value.find(m=>m.id===l.id);if(p){p.alive=l.alive,p.lastSeq=l.lastSeq;continue}const b={id:l.id,shell:l.shell,cwd:l.cwd,alive:l.alive,lastSeq:l.lastSeq,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(b),await B(b)}!i.value&&e.value.length>0&&(i.value=e.value[0].id)}catch(t){f.value=t?.message||String(t)}finally{d.value=!1}}G(async()=>{await K()}),H(()=>{for(const t of e.value){try{t.offs?.()}catch{}try{t.xterm?.dispose?.()}catch{}}}),$(i,()=>{q(()=>{const t=h.value;try{t?.fitAddon?.fit()}catch{}})});const X={term:s,sessions:e,activeId:i,newShell:w,creating:u,loadingList:d,error:f,warning:n,xtermContainers:a,shellOptions:r,active:h,shortId:L,get xtermMod(){return O},set xtermMod(t){O=t},get fitAddonMod(){return M},set fitAddonMod(t){M=t},loadXterm:I,mountXterm:B,onCreate:re,onClose:se,removeSession:W,activate:le,refreshList:K,ref:S,computed:ee,onMounted:G,onBeforeUnmount:H,nextTick:q,watch:$,get message(){return V},get PlusOutlined(){return ge},get CloseOutlined(){return pe},get ReloadOutlined(){return ye},get useTerminal(){return oe}};return Object.defineProperty(X,"__isScriptSetup",{enumerable:!1,value:!0}),X}},be={class:"terminal-page"},ke={class:"terminal-header"},Ce={class:"page-sub"},Ae={class:"terminal-body"},Ee={class:"session-tabs"},Oe=["onClick"],Te={class:"session-shell"},Re={class:"session-id"},Me={key:0,class:"session-empty"},ze={class:"xterm-host"},Le=["data-session-id"],Pe={key:0,class:"xterm-placeholder"},De={key:1,class:"terminal-footer"},qe={key:0,class:"footer-exit"};function Be(c,o,s,e,i,w){const u=z("a-tag"),d=z("a-select"),f=z("a-button"),n=z("a-space"),a=z("a-alert");return y(),x("div",be,[_("div",ke,[_("div",null,[o[3]||(o[3]=_("h2",{class:"page-title"},"远程终端",-1)),_("p",Ce,[o[2]||(o[2]=D(" 桌面端托管的 PTY 会话;Android 端可远程操控同一通道 ",-1)),e.warning?(y(),Q(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:T(()=>[D(E(e.warning),1)]),_:1})):R("v-if",!0)])]),A(n,null,{default:T(()=>[A(d,{value:e.newShell,"onUpdate:value":o[0]||(o[0]=r=>e.newShell=r),style:{width:"130px"},size:"small",options:e.shellOptions},null,8,["value"]),A(f,{type:"primary",size:"small",loading:e.creating,onClick:e.onCreate},{icon:T(()=>[A(e.PlusOutlined)]),default:T(()=>[o[4]||(o[4]=D(" 新会话 ",-1))]),_:1},8,["loading"]),A(f,{size:"small",loading:e.loadingList,onClick:e.refreshList},{icon:T(()=>[A(e.ReloadOutlined)]),default:T(()=>[o[5]||(o[5]=D(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.error?(y(),Q(a,{key:0,message:e.error,type:"error","show-icon":"",closable:"",style:{"margin-bottom":"12px"},onClose:o[1]||(o[1]=r=>e.error="")},null,8,["message"])):R("v-if",!0),_("div",Ae,[_("div",Ee,[(y(!0),x(Y,null,Z(e.sessions,r=>(y(),x("div",{key:r.id,class:ve(["session-tab",{active:r.id===e.activeId,dead:!r.alive}]),onClick:h=>e.activate(r.id)},[_("span",Te,E(r.shell),1),_("span",Re,E(e.shortId(r.id)),1),A(e.CloseOutlined,{class:"session-close",onClick:we(h=>e.onClose(r.id),["stop"])},null,8,["onClick"])],10,Oe))),128)),e.sessions.length===0?(y(),x("div",Me,' 点击 "新会话" 创建第一个终端 ')):R("v-if",!0)]),_("div",ze,[(y(!0),x(Y,null,Z(e.sessions,r=>he((y(),x("div",{key:r.id,ref_for:!0,ref:"xtermContainers","data-session-id":r.id,class:"xterm-container"},null,8,Le)),[[_e,r.id===e.activeId]])),128)),e.sessions.length===0?(y(),x("div",Pe,[...o[6]||(o[6]=[_("span",null,"无活跃会话",-1)])])):R("v-if",!0)])]),e.active?(y(),x("div",De,[_("span",null,E(e.active.shell)+" · "+E(e.active.cwd||"(默认 cwd)")+" · seq "+E(e.active.lastSeq),1),e.active.alive?R("v-if",!0):(y(),x("span",qe,"已退出 (code="+E(e.active.exitCode??"-")+")",1))])):R("v-if",!0)])}const Fe=me(Se,[["render",Be],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-K6ACs6/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Fe as default};
@@ -1 +0,0 @@
1
- import{O as r}from"./index-Cmr31VCO.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-DLOkwTsj.js";import{U as t}from"./index-Cmr31VCO.js";import"./vendor-BvqAck49.js";import"./index-Dh6qWb1v.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-DY8OPWaO.js";import{U as t}from"./index-Cmr31VCO.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-uIxkx5M1.js";import"./useFlexGapSupport-DKl5j41_.js";import"./styleChecker-BFTtaQb8.js";import"./index-Dh6qWb1v.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};