chainlesschain 0.162.43 → 0.162.45

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 (151) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-B0VFIcg3.js → AIOps-D-W6s4eA.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-V20enLcA.js → ActionButton-nPOyfwP_.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DndClUmA.js → Analytics-DoX0H6wa.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-D2rOhyu6.js → AppLayout-BYNnmmUE.js} +5 -5
  6. package/src/assets/web-panel/assets/{Audit-DqfIKxsM.js → Audit-AjglOteL.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-Cuqlers6.js → Backup-DT38xAKk.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-C5hGNJ5N.js → BaseInput-DT1pD4sT.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-jbQSEg4t.js → Chat-Z77BT13i.js} +6 -6
  10. package/src/assets/web-panel/assets/ChatBubbleRenderer-C1MKMzjB.js +1 -0
  11. package/src/assets/web-panel/assets/{Checkbox-DbUBGgg0.js → Checkbox-CVOMmTDm.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-B99Mk_oQ.js → Codegen-Bqy11vCf.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-Uxc3P9FF.js → Col-C3A1d5Wt.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-CCCVsol2.js → Community-D2q6UNaX.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-DpVZkM4n.js → Compact-C2701nAm.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-CZic_otw.js → Compliance-SJnaA5oN.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-mfrcXT5E.js → Cowork-BvTYuhJy.js} +2 -2
  18. package/src/assets/web-panel/assets/{Cron-DZgYJquv.js → Cron-sJ-9lLUV.js} +2 -2
  19. package/src/assets/web-panel/assets/{Crosschain-CsJE5KNs.js → Crosschain-CStGE_K9.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-DhzhW9OD.js → DID-JY0Kx-7a.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dashboard-wRXP3tMC.js → Dashboard-BiZEZPRN.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-B-J3c7n7.js → Dropdown-DK2BszlZ.js} +1 -1
  23. package/src/assets/web-panel/assets/{EmailListRenderer-sNbeZPLo.js → EmailListRenderer-DtjOYS0Q.js} +1 -1
  24. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CzfFKArY.js → FamilyGuardDashboard-D2EI2B5E.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-DYehIJb9.js → Federation-CebAtHrY.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-DpDqU3yC.js → FormItemContext-Bd8WNQLm.js} +1 -1
  27. package/src/assets/web-panel/assets/{GenericCardRenderer-MSm4ZBE2.js → GenericCardRenderer-tH3zcpN9.js} +1 -1
  28. package/src/assets/web-panel/assets/{Git-CJJpll9b.js → Git-DARoXdm7.js} +2 -2
  29. package/src/assets/web-panel/assets/{Governance-D93XtWte.js → Governance-gcKIyn7g.js} +1 -1
  30. package/src/assets/web-panel/assets/{Inference-8fZkwWyg.js → Inference-Rh4pllPC.js} +1 -1
  31. package/src/assets/web-panel/assets/{KnowledgeGraph-BbbI-D3L.js → KnowledgeGraph-Cvh73WwA.js} +1 -1
  32. package/src/assets/web-panel/assets/{Logs-B6n1Hcn8.js → Logs-BBZSagwy.js} +2 -2
  33. package/src/assets/web-panel/assets/{Marketplace-B92T5ZT1.js → Marketplace-e5C7xHES.js} +1 -1
  34. package/src/assets/web-panel/assets/{McpTools-DKddzSA8.js → McpTools-BzfXvajQ.js} +5 -5
  35. package/src/assets/web-panel/assets/{Memory-CAHamDmS.js → Memory-C3ZgSBrL.js} +2 -2
  36. package/src/assets/web-panel/assets/{MobileBridge-BTPLGA6_.js → MobileBridge-BYVobYJJ.js} +3 -3
  37. package/src/assets/web-panel/assets/MobileProjects-Bl8xCXs4.js +1 -0
  38. package/src/assets/web-panel/assets/{Mtc-BGm92GtT.js → Mtc-BxNytLEb.js} +6 -6
  39. package/src/assets/web-panel/assets/{MtcAudit-CL6I9XX4.js → MtcAudit-BUadScwJ.js} +4 -4
  40. package/src/assets/web-panel/assets/{Multisig-BYQujNg6.js → Multisig-BWZmAn6M.js} +3 -3
  41. package/src/assets/web-panel/assets/{NLProgramming-x4DYENrx.js → NLProgramming-B4eau0Yo.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-DyW_mhF0.js → Notes-eHe1Jd1n.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-CgeAblV8.js → NotificationSettings-DFMSI_xu.js} +1 -1
  44. package/src/assets/web-panel/assets/{OrderTableRenderer-COT7rmDe.js → OrderTableRenderer-Ctejeurt.js} +1 -1
  45. package/src/assets/web-panel/assets/{Organization-Pm-XRWB1.js → Organization-M_NYVPks.js} +4 -4
  46. package/src/assets/web-panel/assets/{Overflow-Batydsoy.js → Overflow-Bi-TzxkX.js} +1 -1
  47. package/src/assets/web-panel/assets/{P2P-qwLlvxlM.js → P2P-vtorIyuM.js} +2 -2
  48. package/src/assets/web-panel/assets/{PdhVaultBrowser-CYvPhc0M.js → PdhVaultBrowser-D9I3WUUZ.js} +3 -3
  49. package/src/assets/web-panel/assets/{Permissions-gRGKScdi.js → Permissions-YFbIKLZw.js} +4 -4
  50. package/src/assets/web-panel/assets/{PersonalDataHub-Bob9qL_z.js → PersonalDataHub-JM8yN0w0.js} +3 -3
  51. package/src/assets/web-panel/assets/{Pipeline-DvP3SdFD.js → Pipeline-Cyvwlqpr.js} +1 -1
  52. package/src/assets/web-panel/assets/{Privacy-B-c--IOb.js → Privacy-CIKHwg7m.js} +1 -1
  53. package/src/assets/web-panel/assets/{ProjectInit-UYJYk1VO.js → ProjectInit-Bj6-CmbC.js} +2 -2
  54. package/src/assets/web-panel/assets/{ProjectSettings--euwin_I.js → ProjectSettings-CBnTXhIt.js} +2 -2
  55. package/src/assets/web-panel/assets/{Projects-2xn0tfJt.js → Projects-B3CwPTNd.js} +1 -1
  56. package/src/assets/web-panel/assets/{Providers-Bgq2bGTl.js → Providers-dtUZaXuY.js} +1 -1
  57. package/src/assets/web-panel/assets/{QuickAsk-Ck0iiQiv.js → QuickAsk-BWzt81Dm.js} +1 -1
  58. package/src/assets/web-panel/assets/{Recommend-CuW6xeEE.js → Recommend-CToDb_n9.js} +1 -1
  59. package/src/assets/web-panel/assets/{Reputation-JiNIQHms.js → Reputation-B6MCFsXH.js} +1 -1
  60. package/src/assets/web-panel/assets/{Row-BCudZU5T.js → Row-CipchQUs.js} +1 -1
  61. package/src/assets/web-panel/assets/{RssFeed-CH0VQaou.js → RssFeed-CR3mpmuE.js} +3 -3
  62. package/src/assets/web-panel/assets/{Search-CJjlSa50.js → Search-DRvRD7_k.js} +1 -1
  63. package/src/assets/web-panel/assets/{Security-B8Cf8rVb.js → Security-Bv1bEvfO.js} +4 -4
  64. package/src/assets/web-panel/assets/{Services-BocEJ7ad.js → Services-BLAljjtu.js} +2 -2
  65. package/src/assets/web-panel/assets/{Skeleton-DpI6YIya.js → Skeleton-BRFNIS9s.js} +1 -1
  66. package/src/assets/web-panel/assets/{Skills-C2lt0BNa.js → Skills-B6dEwkkO.js} +1 -1
  67. package/src/assets/web-panel/assets/{Sla-BxSG8zOp.js → Sla-A97O6hQJ.js} +1 -1
  68. package/src/assets/web-panel/assets/{SpeechSettings-DzOejchn.js → SpeechSettings-DNBeqO5l.js} +1 -1
  69. package/src/assets/web-panel/assets/{SyncSettings-CgKxL89k.js → SyncSettings-C61PTeaN.js} +2 -2
  70. package/src/assets/web-panel/assets/{Tasks-CYDrs0ND.js → Tasks-C8q-8JXF.js} +1 -1
  71. package/src/assets/web-panel/assets/{Templates-CRIQTXNH.js → Templates-R-4ZBAPY.js} +1 -1
  72. package/src/assets/web-panel/assets/{Tenant-DC4HO1F6.js → Tenant-dRpKvdmN.js} +1 -1
  73. package/src/assets/web-panel/assets/Terminal-egMhD-wn.js +3 -0
  74. package/src/assets/web-panel/assets/{TimelineRenderer-D-TTq2sh.js → TimelineRenderer-BbXUD3AZ.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tokens-NUv03cX9.js → Tokens-CuYIAO1f.js} +1 -1
  76. package/src/assets/web-panel/assets/{Trigger-X-FBeIBO.js → Trigger-bt_5ffBh.js} +1 -1
  77. package/src/assets/web-panel/assets/{Trust-BFd9yV9d.js → Trust-rk4LCtlg.js} +1 -1
  78. package/src/assets/web-panel/assets/{UkeySign-BVJ0bGzq.js → UkeySign-Bgf8zhuS.js} +1 -1
  79. package/src/assets/web-panel/assets/{VideoEditing-C3Q7lvPF.js → VideoEditing-B_D_kcq5.js} +1 -1
  80. package/src/assets/web-panel/assets/{Wallet-Doxo0C8S.js → Wallet-BuhroOcU.js} +4 -4
  81. package/src/assets/web-panel/assets/{WebAuthn-DveIKeGo.js → WebAuthn-DNVp_EWD.js} +4 -4
  82. package/src/assets/web-panel/assets/{WorkflowEditor-CTzSNXfX.js → WorkflowEditor-C94Nr2Yq.js} +1 -1
  83. package/src/assets/web-panel/assets/{chat-eQ6OL2Nl.js → chat-CqvcO82L.js} +1 -1
  84. package/src/assets/web-panel/assets/{colors-B7NzPMJ1.js → colors-CiHv7zLX.js} +1 -1
  85. package/src/assets/web-panel/assets/{compact-item-DA8_yifp.js → compact-item-BbL_7DRy.js} +1 -1
  86. package/src/assets/web-panel/assets/{createContext-CAdn_TqD.js → createContext-BcnUkPGe.js} +1 -1
  87. package/src/assets/web-panel/assets/devWarning-BSbU0obw.js +1 -0
  88. package/src/assets/web-panel/assets/{hasIn-ko4B6kih.js → hasIn-bKZM79uJ.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-DQ-4d9yy.js → index-2nrwvHPn.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-BX1VHvqW.js → index-ABAWaz7Y.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-Co5moC1M.js → index-AJLQ9KfF.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DmEcUTX3.js → index-B1StZUmz.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-C2qPPvCv.js → index-B76qMGe0.js} +3 -3
  94. package/src/assets/web-panel/assets/{index-CJY-yrWh.js → index-BSzQlPjx.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BKAgTgeT.js → index-Bd0u4iTg.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DLn-aR4t.js → index-Bfcq_Svy.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-B6M0zm0k.js → index-Bh9TSxy7.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Dq_DwzU4.js → index-BlIYy94Y.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BNt9GIgX.js → index-ByEejvcB.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-D38_8grM.js → index-BySbK7vA.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DMGbCVXZ.js → index-C0Dew6UJ.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-b2I5q4bm.js → index-C1b8TGYq.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BBIQJRlz.js → index-CPJ4NWCv.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CqNS5nZH.js → index-CQonLmOf.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Dnz_7pqU.js → index-CWPLkrPr.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-llKEnU9Q.js → index-Cc48TfA8.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DZ0Dd5mp.js → index-Csgtimo8.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-dhQxLUnV.js → index-D-jqR16_.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CgcRhqah.js → index-D5X8cqw-.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-dMx6z8Kk.js → index-DAayTu3W.js} +1 -1
  111. package/src/assets/web-panel/assets/index-DHgbmZ-Y.js +1 -0
  112. package/src/assets/web-panel/assets/{index-DGCgSG2a.js → index-DNBdA_cQ.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-D4yrKz8e.js → index-DPHskdVZ.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-ku6l6unx.js → index-DYH3St42.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B_sjoYmu.js → index-Dpb_Zh3w.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CzerRnMr.js → index-Drdlb5iB.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-v8QteGiY.js → index-J8Xba8Zt.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CDweqnrF.js → index-JteeOvFE.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B0I9Q9uH.js → index-Kl_dtIkL.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BBq7mqhI.js → index-Kt6y6Hh5.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-aClwSoZt.js → index-SeP48n4C.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-snb01c99.js → index-UrCGcZXp.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-N7_jPRVy.js → index-Zxnsweba.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-Bb6JBiCG.js → index-kHUuRAFp.js} +1 -1
  125. package/src/assets/web-panel/assets/index-pr3q7Jlo.js +1 -0
  126. package/src/assets/web-panel/assets/{index-DyfLqass.js → index-sdSZZzwh.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CloqX2ad.js → index-vzVBm4mg.js} +1 -1
  128. package/src/assets/web-panel/assets/{initDefaultProps-BE1YKWp0.js → initDefaultProps-Cg2ZQCW2.js} +1 -1
  129. package/src/assets/web-panel/assets/{motion-B4Pkg4rs.js → motion-CVup4XZf.js} +1 -1
  130. package/src/assets/web-panel/assets/{move-DbLtadAv.js → move-0we4XeEJ.js} +1 -1
  131. package/src/assets/web-panel/assets/{omit-Dn52nvgx.js → omit-DNvkWjsk.js} +1 -1
  132. package/src/assets/web-panel/assets/{pickAttrs-D4B5N6WV.js → pickAttrs-DNGWkffo.js} +1 -1
  133. package/src/assets/web-panel/assets/{placementArrow-CKSjiqCc.js → placementArrow-DdMP7Lk2.js} +1 -1
  134. package/src/assets/web-panel/assets/{responsiveObserve-g5NpHuRh.js → responsiveObserve-CgCiGZ6t.js} +1 -1
  135. package/src/assets/web-panel/assets/{slide-WYVY3fl7.js → slide-CQxOWXtr.js} +1 -1
  136. package/src/assets/web-panel/assets/{statusUtils-YAkHF6HM.js → statusUtils-BVYop9K6.js} +1 -1
  137. package/src/assets/web-panel/assets/{styleChecker-Cv_nVk4H.js → styleChecker-BTkUPq_y.js} +1 -1
  138. package/src/assets/web-panel/assets/{useFlexGapSupport-D1JaeNmU.js → useFlexGapSupport-CKncli3p.js} +1 -1
  139. package/src/assets/web-panel/assets/{useFs-DYfXeCVm.js → useFs-B7k6cPxd.js} +1 -1
  140. package/src/assets/web-panel/assets/{usePersonalDataHub-DdtPxV0b.js → usePersonalDataHub-CiVRczRO.js} +1 -1
  141. package/src/assets/web-panel/assets/{vnode-nFZXhzTF.js → vnode-CPueAEhr.js} +1 -1
  142. package/src/assets/web-panel/assets/{zoom-CmyXMc6s.js → zoom-BhzuJF_P.js} +1 -1
  143. package/src/assets/web-panel/index.html +1 -1
  144. package/src/commands/agent.js +5 -0
  145. package/src/runtime/headless-stream.js +151 -5
  146. package/src/assets/web-panel/assets/ChatBubbleRenderer-43u4DJn6.js +0 -1
  147. package/src/assets/web-panel/assets/MobileProjects-DvGxl7Bd.js +0 -1
  148. package/src/assets/web-panel/assets/Terminal-CqMZJzEh.js +0 -3
  149. package/src/assets/web-panel/assets/devWarning-UBrKMao4.js +0 -1
  150. package/src/assets/web-panel/assets/index-BcOtgvfX.js +0 -1
  151. package/src/assets/web-panel/assets/index-DogBvgW2.js +0 -1
@@ -84,6 +84,17 @@ export function parseInputEvent(line) {
84
84
  const action = String(obj.action || "").toLowerCase();
85
85
  return action ? { plan: action } : null;
86
86
  }
87
+ // Turn interrupt (panel Stop / Claude-Code Esc parity): aborts the
88
+ // in-flight turn without ending the conversation. {"type":"interrupt"}
89
+ if (obj && typeof obj === "object" && obj.type === "interrupt") {
90
+ return { interrupt: true };
91
+ }
92
+ // Approval verdicts (panel Approve/Deny for --interactive-approvals):
93
+ // {"type":"approval","id":"appr-1","approve":true|false}
94
+ if (obj && typeof obj === "object" && obj.type === "approval") {
95
+ if (!obj.id) return null;
96
+ return { approval: { id: String(obj.id), approve: obj.approve === true } };
97
+ }
87
98
  const msg = obj && typeof obj === "object" ? obj.message || obj : {};
88
99
  let content = msg.content ?? obj.text ?? obj.prompt;
89
100
  if (Array.isArray(content)) {
@@ -267,12 +278,64 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
267
278
  };
268
279
  const persist = Boolean(options.sessionId);
269
280
 
281
+ // ── Interactive approvals (--interactive-approvals; chat-panel UX) ────────
282
+ // CONFIRM-tier decisions (risky shell via the ApprovalGate, settings/hook
283
+ // `ask`) normally fail closed in headless. With this opt-in they become a
284
+ // structured round-trip instead: emit `approval_request`, BLOCK the tool
285
+ // until a {"type":"approval",id,approve} arrives on stdin (handled by the
286
+ // concurrent pump below, so the wait never deadlocks), fail closed on
287
+ // timeout (CC_APPROVAL_TIMEOUT_MS, default 120s) or stdin close. The
288
+ // resolution is echoed as `approval_resolved` so UIs can settle their cards.
289
+ const interactive = options.interactiveApprovals === true;
290
+ const pendingApprovals = new Map();
291
+ let approvalSeq = 0;
292
+ const approvalTimeoutMs =
293
+ Number(process.env.CC_APPROVAL_TIMEOUT_MS) > 0
294
+ ? Number(process.env.CC_APPROVAL_TIMEOUT_MS)
295
+ : 120000;
296
+ const settleApproval = (id, approve, via) => {
297
+ const p = pendingApprovals.get(id);
298
+ if (!p) return;
299
+ pendingApprovals.delete(id);
300
+ clearTimeout(p.timer);
301
+ emit({
302
+ type: "approval_resolved",
303
+ id,
304
+ approved: approve === true,
305
+ via,
306
+ session_id: sessionId,
307
+ });
308
+ p.resolve(approve === true);
309
+ };
310
+ const interactiveConfirm = (ctx = {}) =>
311
+ new Promise((resolve) => {
312
+ const id = `appr-${++approvalSeq}`;
313
+ const timer = setTimeout(
314
+ () => settleApproval(id, false, "timeout"),
315
+ approvalTimeoutMs,
316
+ );
317
+ timer.unref?.();
318
+ pendingApprovals.set(id, { resolve, timer });
319
+ emit({
320
+ type: "approval_request",
321
+ id,
322
+ session_id: sessionId,
323
+ tool: ctx.tool || ctx.toolName || null,
324
+ command: ctx.command || ctx.args?.command || null,
325
+ risk: ctx.riskLevel || ctx.risk || null,
326
+ rule: ctx.rule || null,
327
+ reason: ctx.reason || null,
328
+ });
329
+ });
330
+
270
331
  let approvalGate = null;
271
332
  try {
272
333
  approvalGate = await getApprovalGate();
273
334
  if (approvalGate) {
274
335
  approvalGate.setSessionPolicy?.(sessionId, perm.sessionPolicy);
275
- approvalGate.setConfirmer?.(perm.confirmer);
336
+ approvalGate.setConfirmer?.(
337
+ interactive ? interactiveConfirm : perm.confirmer,
338
+ );
276
339
  }
277
340
  } catch {
278
341
  approvalGate = null;
@@ -448,6 +511,10 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
448
511
  settingsHooks,
449
512
  enabledToolNames,
450
513
  disabledTools,
514
+ // --interactive-approvals: settings/hook `ask` (and, with an IDE bridge,
515
+ // edit reviews via openDiff) route to the structured approval round-trip
516
+ // instead of failing closed. Absent in CI/pipes → unchanged fail-closed.
517
+ permissionConfirm: interactive ? interactiveConfirm : undefined,
451
518
  prepareCall: goalPrepareCallFn,
452
519
  // --mcp-config wiring (tool defs + dispatch map + live client).
453
520
  mcpClient: mcp?.mcpClient || null,
@@ -474,9 +541,62 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
474
541
  let turns = 0;
475
542
  let sawError = false;
476
543
 
477
- for await (const line of readJsonLines(input)) {
478
- const parsed = parseInputEvent(line);
479
- if (parsed == null) continue; // blank line
544
+ // ── Concurrent stdin pump (turn-interrupt support) ────────────────────────
545
+ // Input is consumed AS IT ARRIVES — not between turns — so an
546
+ // {"type":"interrupt"} can abort the IN-FLIGHT turn immediately (chat-panel
547
+ // Stop / Claude-Code Esc parity) instead of waiting in line behind it.
548
+ // Normal events queue for the serial turn loop below; interrupts act on the
549
+ // live per-turn AbortController and are never queued.
550
+ const queue = [];
551
+ let wakeQueue = null;
552
+ let inputDone = false;
553
+ let currentAbort = null;
554
+ (async () => {
555
+ try {
556
+ for await (const line of readJsonLines(input)) {
557
+ const parsed = parseInputEvent(line);
558
+ if (parsed == null) continue;
559
+ if (parsed.interrupt) {
560
+ currentAbort?.abort();
561
+ continue;
562
+ }
563
+ if (parsed.approval) {
564
+ // Approval verdicts settle a BLOCKED tool — never queued.
565
+ settleApproval(
566
+ parsed.approval.id,
567
+ parsed.approval.approve,
568
+ parsed.approval.approve ? "user-approve" : "user-deny",
569
+ );
570
+ continue;
571
+ }
572
+ queue.push(parsed);
573
+ if (wakeQueue) wakeQueue();
574
+ }
575
+ } catch {
576
+ /* input stream error → treat as EOF */
577
+ }
578
+ inputDone = true;
579
+ // stdin closed while approvals were pending → fail closed so the blocked
580
+ // turn can finish and the process can exit.
581
+ for (const id of [...pendingApprovals.keys()]) {
582
+ settleApproval(id, false, "stdin-closed");
583
+ }
584
+ if (wakeQueue) wakeQueue();
585
+ })();
586
+ const nextEvent = async () => {
587
+ for (;;) {
588
+ if (queue.length > 0) return queue.shift();
589
+ if (inputDone) return null;
590
+ await new Promise((r) => {
591
+ wakeQueue = r;
592
+ });
593
+ wakeQueue = null;
594
+ }
595
+ };
596
+
597
+ for (;;) {
598
+ const parsed = await nextEvent();
599
+ if (parsed == null) break; // stdin closed
480
600
  if (parsed.error) {
481
601
  emit({
482
602
  type: "result",
@@ -617,14 +737,39 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
617
737
  }
618
738
  turns += 1;
619
739
 
740
+ // Per-turn abort scope: an {"type":"interrupt"} from the pump above
741
+ // aborts THIS turn (LLM fetch included — the signal reaches chatWithTools)
742
+ // while the conversation/process stays alive for the next message.
743
+ currentAbort = new AbortController();
744
+ const turnSignal = options.signal
745
+ ? AbortSignal.any([options.signal, currentAbort.signal])
746
+ : currentAbort.signal;
747
+
620
748
  let outcome;
621
749
  try {
622
750
  outcome = await runTurn(
623
751
  messages,
624
- { ...loopOptionsBase, iterationBudget: budget },
752
+ { ...loopOptionsBase, iterationBudget: budget, signal: turnSignal },
625
753
  { runLoop, emit },
626
754
  );
627
755
  } catch (err) {
756
+ currentAbort = null;
757
+ const isAbort =
758
+ err?.name === "AbortError" || /abort/i.test(err?.message || "");
759
+ if (isAbort && !options.signal?.aborted) {
760
+ // User-initiated turn interrupt — not an error; no assistant message
761
+ // is recorded (the dangling user turn is fine for the next exchange).
762
+ emit({
763
+ type: "result",
764
+ subtype: "interrupted",
765
+ is_error: false,
766
+ interrupted: true,
767
+ session_id: sessionId,
768
+ turn: turns,
769
+ });
770
+ continue;
771
+ }
772
+ if (isAbort) break; // outer options.signal — caller is shutting down
628
773
  emit({
629
774
  type: "result",
630
775
  subtype: "error",
@@ -635,6 +780,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
635
780
  sawError = true;
636
781
  continue;
637
782
  }
783
+ currentAbort = null;
638
784
 
639
785
  // Grow the conversation so the next turn has context.
640
786
  messages.push({ role: "assistant", content: outcome.finalText });
@@ -1 +0,0 @@
1
- import{I as v,P as u,J as S,U as s,R as a,S as y,K as C,Q as x,V as w,_ as B,b as n}from"./vendor-BvqAck49.js";import{_ as k}from"./index-C2qPPvCv.js";import"./icons-DP3uiYxy.js";const N={__name:"ChatBubbleRenderer",props:{event:{type:Object,required:!0}},setup(c,{expose:d}){d();const t=c,r=n(()=>{const e=t.event.content||{};return e.text||e.body||e.message||e.title||JSON.stringify(e).slice(0,200)}),i=n(()=>{const e=t.event.content||{};return e.from||e.sender||e.senderName||t.event.actor||"(unknown)"}),l=n(()=>{const e=(t.event.actor||"").toLowerCase();return e.includes("self")||e==="me"||e.endsWith("_self")}),o=n(()=>{const e=t.event.source.adapter||"";return e.startsWith("messaging-qq")?"magenta":e==="wechat"?"green":"blue"}),m=n(()=>{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:n};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}},R={class:"bubble"},T={class:"meta"},M={class:"actor"},V={class:"time"},q={class:"body"};function D(c,d,t,r,i,l){const o=v("a-tag");return u(),S("div",{class:B(["chat-row",{mine:r.isMine}])},[s("div",R,[s("div",T,[s("span",M,a(r.actorLabel),1),s("span",V,a(r.formattedTime),1)]),s("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",D],["__scopeId","data-v-49238629"],["__file","/tmp/cc-web-panel-nNRGJZ/repo/packages/web-panel/src/components/pdh/renderers/ChatBubbleRenderer.vue"]]);export{j as default};
@@ -1 +0,0 @@
1
- import{I as n,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-BvqAck49.js";import{_ as v,b as m}from"./index-C2qPPvCv.js";import{a7 as y,M}from"./icons-DP3uiYxy.js";const B={__name:"MobileProjects",setup(p,{expose:i}){i();const c=u(),{t:e}=m();function a(){c.push("/projects")}function _(){c.push("/mobile-bridge")}const s={router:c,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}},x={class:"mobile-projects-placeholder"},O={class:"title"},k={class:"subtitle"},w={class:"explainer"};function T(p,i,c,e,a,_){const s=n("a-alert"),d=n("a-button"),f=n("a-space"),P=n("a-empty"),j=n("a-card");return h(),g("div",x,[l(j,null,{default:r(()=>[l(P,{description:!1},{image:r(()=>[l(e.MobileOutlined,{style:{fontSize:"64px",color:"#bfbfbf"}})]),default:r(()=>[o("h2",O,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 I=v(B,[["render",T],["__scopeId","data-v-9262cc45"],["__file","/tmp/cc-web-panel-nNRGJZ/repo/packages/web-panel/src/views/MobileProjects.vue"]]);export{I 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-C2qPPvCv.js";import{I as z,J as x,U as _,Q as D,S as G,K as R,V as T,c as A,F as K,Z as Q,R as E,o as Y,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 Z=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});Z.observe(b);const ue=t.offs;t.offs=()=>{try{Z.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 J(){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}}Y(async()=>{await J()}),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:J,ref:S,computed:ee,onMounted:Y,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"],Re={class:"session-shell"},Te={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(),G(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:R(()=>[D(E(e.warning),1)]),_:1})):T("v-if",!0)])]),A(n,null,{default:R(()=>[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:R(()=>[A(e.PlusOutlined)]),default:R(()=>[o[4]||(o[4]=D(" 新会话 ",-1))]),_:1},8,["loading"]),A(f,{size:"small",loading:e.loadingList,onClick:e.refreshList},{icon:R(()=>[A(e.ReloadOutlined)]),default:R(()=>[o[5]||(o[5]=D(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.error?(y(),G(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"])):T("v-if",!0),_("div",Ae,[_("div",Ee,[(y(!0),x(K,null,Q(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",Re,E(r.shell),1),_("span",Te,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,' 点击 "新会话" 创建第一个终端 ')):T("v-if",!0)]),_("div",ze,[(y(!0),x(K,null,Q(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)])])):T("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?T("v-if",!0):(y(),x("span",qe,"已退出 (code="+E(e.active.exitCode??"-")+")",1))])):T("v-if",!0)])}const Fe=me(Se,[["render",Be],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-nNRGJZ/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Fe as default};
@@ -1 +0,0 @@
1
- import{O as r}from"./index-C2qPPvCv.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-BCudZU5T.js";import{U as t}from"./index-C2qPPvCv.js";import"./vendor-BvqAck49.js";import"./responsiveObserve-g5NpHuRh.js";import"./useFlexGapSupport-D1JaeNmU.js";import"./styleChecker-Cv_nVk4H.js";import"./index-b2I5q4bm.js";import"./icons-DP3uiYxy.js";const l=t(o);export{l as default};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-Uxc3P9FF.js";import{U as t}from"./index-C2qPPvCv.js";import"./vendor-BvqAck49.js";import"./index-b2I5q4bm.js";import"./icons-DP3uiYxy.js";const s=t(o);export{s as default};