chainlesschain 0.162.165 → 0.162.167

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 (181) hide show
  1. package/package.json +3 -1
  2. package/src/assets/web-panel/assets/{AIOps-DgGZr3PR.js → AIOps-BZJrchIA.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BAOgBIc_.js → ActionButton-Bhlrylt7.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-Ds4GAvNF.js → Analytics-pHtXVQYs.js} +2 -2
  5. package/src/assets/web-panel/assets/{AppLayout-CoJvCkoF.js → AppLayout-ORpuri4R.js} +4 -4
  6. package/src/assets/web-panel/assets/{Artifacts-6EgUaE1T.js → Artifacts-eC77yr1_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-BYie_i74.js → Audit-B2dZIiqz.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-D5gxOhjd.js → BackgroundAgents-COZiTiwP.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-CIsVK2pT.js → Backup-vY_Srl5d.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-ClorP55M.js → BaseInput-Dili5BdM.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-CnhTPGGA.js → Chat-EzKBf0XL.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bl1VXgwp.js → ChatBubbleRenderer-D1CtRAyy.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-BRavl7TP.js → Checkbox-Beh6BmuW.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-BXg_ErNT.js → Codegen-C3fA6kBU.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-CfDPzFPq.js → Col-CefMqONH.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-Cgo0httP.js → Community-CBAxFJtB.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-DU5JcEQM.js → Compact--flHc-sM.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-DCH_TVBl.js → Compliance-CPeNLvA6.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-IGb5O2IH.js → Cowork-Bv5yv4BU.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CPp_Xp9F.js → Cron-C22yMEas.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-Cwrqklzw.js → Crosschain-Dsb2bcpu.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-D55sBQwM.js → DID-DAxei4w0.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-CedXhGmP.js → Dashboard-DEUwuVZ8.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-Dm6_v3V4.js → Dropdown-BVp4si2j.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-CWjnuE3G.js → EmailListRenderer-CyFkybOG.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DubTh7y-.js → FamilyGuardDashboard-BWmmsbVx.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-DlSM4uJv.js → Federation-Cxw27A5d.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-BYhg0vtG.js → FormItemContext-Q9XthzL1.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-Bkh7qjfK.js → GenericCardRenderer-DS5DIdsW.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DSLWPKvn.js → Git-BOliHfxP.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-DIj9O8BB.js → Governance-CD4oxa-W.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-Dhep3e5Y.js → Inference-CMlcivo8.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-Cj8vzxB_.js → KnowledgeGraph-BwhERcC4.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-Ba4SsPja.js → Logs-BjVcZR5P.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-BfRhXdyG.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-CGs9IIbf.js → Marketplace-DQLU3E2w.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-BTPAoX4K.js → McpTools-CeK0XkpB.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-BJ6ISf2c.js → Memory-DLFkgwaz.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-Ca6n3Dcn.js → MobileBridge-Bh6ymXyj.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-lvilHuLt.js → MobileProjects-D950tUIe.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-CMo0acBV.js → Mtc-Bx5x9_2m.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-Hz5wBvFX.js → MtcAudit-a1-Fexsq.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-BK2aKWE6.js → Multisig-eaw0X8X1.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CExpnYMI.js → NLProgramming-BaNsPV4k.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-B7IFbuBo.js → Notes-C7pevN2X.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-VrGchtb0.js → NotificationSettings-HDqeoP0r.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-CyrNTxkU.js → OrderTableRenderer-DvzVl5T3.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-I0C17GBP.js → Organization-D_xHDlGW.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-CXcWvERe.js → Overflow-B5sRnueL.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-FFSCXrZq.js → P2P-C-IRjOPW.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-1PB-p8Zk.js → PdhVaultBrowser-BqgUPlcU.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-C1YHejsb.js → Permissions-Bm_T1uWw.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CEMPpgf8.js → PersonalDataHub-DujDllye.js} +4 -4
  54. package/src/assets/web-panel/assets/{Pipeline-FoIScdLr.js → Pipeline-DyNPOLIG.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-DDfbEzEj.js → Privacy-CYKTW3iK.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-Dso4kB0O.js → ProjectInit-CGf03uZ0.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-WvDoydDc.js → ProjectSettings-DIec4bTI.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-NJp0kzkd.js → Projects-BY43-bmi.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-BuJXnOLI.js → Providers-RrnUmgPk.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-Bb3lMvGG.js → QrScannerModal-BBWfqd4y.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-Ddxra3fK.js → QuickAsk-BsICSrFp.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-BW-dR9qw.js → Recommend-B8y0b4ys.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-Hnm7-Qkm.js → RemoteSession-0QgdB1Oe.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-DKz6meHE.js → Reputation-DBJGM0YO.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-BuAsoNTS.js → Row-DtWQ5otv.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-_do9DMIH.js → RssFeed-2zBxHd5H.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-CMlcw7ND.js → Search-BofliSkZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-DhAkfSpM.js → Security-ockRBBEL.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-5zKLhy46.js → Services-QyvG7Vd0.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-DCMZ3wfv.js → Skeleton-DwbOndX3.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-DxQgYCC_.js → Skills-cHWa63sZ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CJmE4cSN.js → Sla-BHnTEydQ.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-BgpRTPQp.js → SpeechSettings-DE2hrrLb.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DkogtYbB.js → SyncSettings-CZ9vnbJH.js} +2 -2
  75. package/src/assets/web-panel/assets/Tasks-DWgoAHvM.js +1 -0
  76. package/src/assets/web-panel/assets/{Templates-DAZIu5nN.js → Templates-DiR3ad4X.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-BRJMI-su.js → Tenant-NqcW3frV.js} +1 -1
  78. package/src/assets/web-panel/assets/Terminal-iYeqRQZ0.js +3 -0
  79. package/src/assets/web-panel/assets/{TimelineRenderer-D4z9aSGD.js → TimelineRenderer-C5GOoxFz.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-zgYA4UOI.js → Tokens-82dz0XdU.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-DMOgHX4m.js → Trigger-B3JCNrOi.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-CEtoNwcT.js → Trust-BehFYsN_.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-DFx2pQfO.js → UkeySign-BfOxJjVf.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DLssy-7B.js → VideoEditing-DdITCCPz.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DQHc6gTl.js → Wallet-B0EhkCmD.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-DgKcODkn.js → WebAuthn-DJ4i1f3-.js} +2 -2
  87. package/src/assets/web-panel/assets/{WorkflowEditor-cPEWfMOf.js → WorkflowEditor-Dr9XTqIT.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-Coj7rSO1.js → chat-Dc2nFyOj.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-DiyGfr-6.js → colors-Drw9djBR.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-DB63aMXh.js → compact-item-BdLXbU52.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-CENpsYHg.js → createContext-BpQMZiWY.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-CnfpDzMr.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-B9NOmk0K.js → hasIn-CbYwawHf.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BvQq6gX2.js → index-B1ANzVc6.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-mTK_ZHhE.js → index-B3uRI8_y.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-D_rZCxxI.js → index-B5KboakZ.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DAMKhjtT.js → index-B9_u4Qhe.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-7IMjHwGU.js → index-BAq-4KqY.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DqLC0iE4.js → index-BBueKSTR.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-Kp2AETEw.js → index-BIcEW07n.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-KDCuTzdx.js → index-BWUoc9-s.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-nio98wGC.js → index-BZxzdAI0.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BxvNtndl.js → index-BiGDrEt4.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-B45osqnZ.js → index-Blv7c80V.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BpmTl8QC.js → index-BmQlot_u.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DANoIqXP.js → index-Bo_KwJTF.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Dg0v-CXZ.js → index-Bu8Vy-mj.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-U_snupDl.js → index-C1eo1Qkd.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-ClEy1v1o.js → index-C3Alz2QD.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Bvj07Ab1.js → index-CBwQwtsE.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CKNt2vfs.js → index-CJQiSQw7.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CXRknr9W.js → index-CKmz3Is-.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CRhEJ8JO.js → index-COoIIMbO.js} +1 -1
  114. package/src/assets/web-panel/assets/index-CYTEB0tb.js +1 -0
  115. package/src/assets/web-panel/assets/index-CgsEp5bm.js +1 -0
  116. package/src/assets/web-panel/assets/{index-CxVfbuj9.js → index-CpmlTfpv.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CmNCDN5t.js → index-D7Ipfs4F.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-B0C6zl0y.js → index-DHMeEu-P.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DsPDEHOg.js → index-DKQlF7Pw.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Yb9EfUnY.js → index-DO7LD_1t.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CvTJ-x6b.js → index-DSmZjrFy.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-C9d8hdgY.js → index-DTeqWdAS.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Y_UKQpsV.js → index-DWUN8c01.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-t6hXF2Cw.js → index-D_lkTnZ0.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-VDFbduzG.js → index-DyU21xVi.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-76GMjcbq.js → index-GG_MXjSL.js} +3 -3
  127. package/src/assets/web-panel/assets/{index-BramLq29.js → index-IG3__pGj.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BXzMKVLp.js → index-UX_Mfyfv.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CwkK9Kl2.js → index-VIyNlXPX.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CAXouogg.js → index-XYe6kBmi.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CTuX_MU0.js → index-_vVucYqC.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BkoqtJzV.js → index-aHrUfrv1.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-GTwJVIOz.js → initDefaultProps-DybC85E4.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BJQLsPx8.js → motion-BNNuyDg7.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-DVQM0bdG.js → move-Bm8gSjEN.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-CMXI1I2y.js → mtc-parser-CuHQvzzr.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-CAc8MDw9.js → omit-lv4NO7Ng.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-BgqzoyP7.js → pickAttrs-BoSMfjHq.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-B9ebCdRy.js → placementArrow-BOMDSvgz.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-Dy8D0D3n.js → responsiveObserve-C064Ubmu.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-Bcrc8J39.js → slide-CeqhbKoG.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-CDW6FOlc.js → statusUtils-CunFoYww.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CWhJrDON.js → styleChecker-Cxz3wPL7.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-C82c33XI.js → useFlexGapSupport-DJsIaU2S.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-A6m--mih.js → useFs-DnAygceJ.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-m-1laJY5.js → usePersonalDataHub-CrEUY7ta.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-CL9oKKRa.js → vnode-Cq3rN2eT.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-DrOyaof3.js → zoom-TMzcOx__.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/agent.js +75 -0
  151. package/src/commands/session.js +132 -0
  152. package/src/data/changelog.json +12 -2
  153. package/src/harness/jsonl-session-store.js +9 -0
  154. package/src/harness/session-mirror.js +212 -6
  155. package/src/lib/async-hook-queue.cjs +288 -0
  156. package/src/lib/async-hook-supervisor.cjs +52 -0
  157. package/src/lib/background-session-transport.js +24 -2
  158. package/src/lib/doctor-checkup.js +184 -4
  159. package/src/lib/governance-coverage.js +179 -0
  160. package/src/lib/install-command-policy.js +333 -0
  161. package/src/lib/jsonl-session-store.js +1 -0
  162. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +27 -0
  163. package/src/lib/lsp/lsp-server-registry.js +14 -0
  164. package/src/lib/packer/smoke-runner.js +85 -15
  165. package/src/lib/protocol-replay.js +153 -0
  166. package/src/lib/runtime-checkup.js +33 -0
  167. package/src/lib/settings-hook-events.cjs +157 -0
  168. package/src/lib/settings-hooks.cjs +4 -0
  169. package/src/lib/shell-approval.js +47 -1
  170. package/src/repl/add-dir.js +59 -1
  171. package/src/repl/agent-repl.js +85 -3
  172. package/src/runtime/agent-core.js +35 -0
  173. package/src/runtime/headless-runner.js +69 -1
  174. package/src/runtime/headless-stream.js +22 -0
  175. package/src/runtime/system-prompt.js +39 -12
  176. package/src/assets/web-panel/assets/MarkdownRenderer-DUjyuVB3.js +0 -1
  177. package/src/assets/web-panel/assets/Tasks-D5OrwAl9.js +0 -1
  178. package/src/assets/web-panel/assets/Terminal-CMXLqQKF.js +0 -3
  179. package/src/assets/web-panel/assets/devWarning-XvRaIiyt.js +0 -1
  180. package/src/assets/web-panel/assets/index-CbO1zSXV.js +0 -1
  181. package/src/assets/web-panel/assets/index-aCu2gbUb.js +0 -1
@@ -184,6 +184,35 @@ export function listBackgroundShellTasks() {
184
184
  // spawned detached (its own process group), so signal the group via the
185
185
  // negative pid. Windows: `taskkill /T` walks and kills the whole tree.
186
186
  // Returns true if a running task was signalled.
187
+ // Release the parent-side handles of a background task's child: the stdout/
188
+ // stderr PIPES (ref'd — on their own they keep the event loop alive) and the
189
+ // process handle. Called once a task is terminal or has been signalled to die,
190
+ // so a still-draining or slowly-dying child can never pin the process past a
191
+ // teardown. In production the agent's own REPL/run loop holds the loop open, so
192
+ // this changes nothing there; in the vitest forks pool nothing else does, and a
193
+ // SIGTERM'd-but-not-yet-dead child was tripping the worker-terminate deadline
194
+ // (the POSIX-only "Timeout terminating forks worker / Worker exited
195
+ // unexpectedly" unit-shard flake). Idempotent + best-effort.
196
+ function _releaseBgChildHandles(task) {
197
+ const child = task?.child;
198
+ if (!child) return;
199
+ try {
200
+ child.stdout?.destroy();
201
+ } catch {
202
+ /* noop */
203
+ }
204
+ try {
205
+ child.stderr?.destroy();
206
+ } catch {
207
+ /* noop */
208
+ }
209
+ try {
210
+ child.unref?.();
211
+ } catch {
212
+ /* noop */
213
+ }
214
+ }
215
+
187
216
  function _killTask(task) {
188
217
  const child = task?.child;
189
218
  if (!child || child.killed || task?.status !== "running") return false;
@@ -217,6 +246,9 @@ function _killTask(task) {
217
246
  } else {
218
247
  child.kill("SIGTERM");
219
248
  }
249
+ // Drop the ref'd pipe/process handles now — the group signal is away, so a
250
+ // slowly-dying child must not pin the loop while it finishes exiting.
251
+ _releaseBgChildHandles(task);
220
252
  return true;
221
253
  } catch (_err) {
222
254
  return false;
@@ -276,6 +308,7 @@ function _killTaskSync(task) {
276
308
  } else {
277
309
  child.kill("SIGKILL");
278
310
  }
311
+ _releaseBgChildHandles(task);
279
312
  return true;
280
313
  } catch (_err) {
281
314
  return false;
@@ -2692,6 +2725,7 @@ async function executeToolInner(
2692
2725
  task.status = "error";
2693
2726
  task.error = String(err?.message || err).substring(0, 2000);
2694
2727
  task.endedAt = new Date().toISOString();
2728
+ _releaseBgChildHandles(task);
2695
2729
  });
2696
2730
  // 'close' (not 'exit') so stdout/stderr are fully drained before the
2697
2731
  // status leaves "running" — otherwise a poll can observe completion
@@ -2704,6 +2738,7 @@ async function executeToolInner(
2704
2738
  task.exitCode = code;
2705
2739
  task.signal = signal;
2706
2740
  task.endedAt = new Date().toISOString();
2741
+ _releaseBgChildHandles(task);
2707
2742
  });
2708
2743
  } catch (err) {
2709
2744
  task.status = "error";
@@ -707,6 +707,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
707
707
  let sideEffectSeq = 0;
708
708
  let currentSideEffectOpId = null;
709
709
  let resumeSideEffectContext = null;
710
+ let resumeAsyncHookContext = null;
710
711
  const persistSideEffectLedger = () => {
711
712
  if (!persist) return;
712
713
  try {
@@ -767,6 +768,34 @@ export async function runAgentHeadless(options = {}, deps = {}) {
767
768
  } catch {
768
769
  resumeSideEffectContext = null;
769
770
  }
771
+ // On resume, recover any async-hook REWAKE (a background check that opted
772
+ // in and FAILED) that the previous run parked but died before draining —
773
+ // surface it to the model instead of silently swallowing the failure. The
774
+ // take also clears the bucket so it isn't replayed on a later resume.
775
+ try {
776
+ const { takePending } = await import("../lib/async-hook-queue.cjs");
777
+ const recovered = takePending(
778
+ { sessionId, now: deps.now ? deps.now() : Date.now() },
779
+ deps.asyncHookQueuePath || undefined,
780
+ deps.asyncHookQueueFs || undefined,
781
+ );
782
+ if (Array.isArray(recovered) && recovered.length > 0) {
783
+ const lines = recovered.map((r) => {
784
+ const detail = r.error || r.additionalContext || "failed";
785
+ return ` • ${r.command} — ${detail}`;
786
+ });
787
+ resumeAsyncHookContext =
788
+ "Recovery notice — the previous run was interrupted after these " +
789
+ "background (async) hook checks FAILED but before you were told. " +
790
+ "Review each failure and decide whether it still needs action:\n" +
791
+ lines.join("\n");
792
+ writeErr(
793
+ `⚠ Recovered ${recovered.length} failed async-hook check(s) from interrupted run (resume ${resumeId}).\n`,
794
+ );
795
+ }
796
+ } catch {
797
+ resumeAsyncHookContext = null;
798
+ }
770
799
  }
771
800
  }
772
801
 
@@ -856,6 +885,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
856
885
  // rules.md (in buildSystemPrompt) + the cc.md/CLAUDE.md block. Absent flag
857
886
  // (undefined) leaves both paths byte-identical.
858
887
  const _leanNoProjectMemory = options.projectMemory === false;
888
+ let _loadedInstructions = null;
859
889
  const systemContent = composeSystemPrompt(
860
890
  buildSystemPrompt(cwd, {
861
891
  additionalDirectories,
@@ -867,6 +897,9 @@ export async function runAgentHeadless(options = {}, deps = {}) {
867
897
  outputStyle: outputStyleBody,
868
898
  instructionExcludes,
869
899
  projectMemory: _leanNoProjectMemory ? false : undefined,
900
+ onInstructionsLoaded: (loaded) => {
901
+ _loadedInstructions = loaded;
902
+ },
870
903
  },
871
904
  );
872
905
 
@@ -896,6 +929,26 @@ export async function runAgentHeadless(options = {}, deps = {}) {
896
929
  }
897
930
  }
898
931
 
932
+ // settings.json InstructionsLoaded hooks (observe-only): the project-instruction
933
+ // block was just composed — fire with the EXACT loaded file set so a hook can
934
+ // audit which cc.md/CLAUDE.md/AGENTS.md/rules are authoritative this session.
935
+ // Any emitted context is injected like SessionStart's. Best-effort; no-op when
936
+ // project memory is off (no loaded set) or no hook is registered.
937
+ let instructionsLoadedContext = null;
938
+ if (settingsHooks && _loadedInstructions) {
939
+ try {
940
+ const { runInstructionsLoadedHooks } =
941
+ await import("../lib/settings-hook-events.cjs");
942
+ instructionsLoadedContext = runInstructionsLoadedHooks(settingsHooks, {
943
+ files: _loadedInstructions.files,
944
+ cwd,
945
+ sessionId,
946
+ }).additionalContext;
947
+ } catch (_err) {
948
+ instructionsLoadedContext = null;
949
+ }
950
+ }
951
+
899
952
  // settings.json SessionStart hooks → inject session context (observe-only).
900
953
  let sessionStartContext = null;
901
954
  if (settingsHooks) {
@@ -950,12 +1003,18 @@ export async function runAgentHeadless(options = {}, deps = {}) {
950
1003
  // No-op on a healthy alternating transcript.
951
1004
  const messages = mergeConsecutiveMessages([
952
1005
  { role: "system", content: systemContent },
1006
+ ...(instructionsLoadedContext
1007
+ ? [{ role: "system", content: instructionsLoadedContext }]
1008
+ : []),
953
1009
  ...(sessionStartContext
954
1010
  ? [{ role: "system", content: sessionStartContext }]
955
1011
  : []),
956
1012
  ...(resumeSideEffectContext
957
1013
  ? [{ role: "system", content: resumeSideEffectContext }]
958
1014
  : []),
1015
+ ...(resumeAsyncHookContext
1016
+ ? [{ role: "system", content: resumeAsyncHookContext }]
1017
+ : []),
959
1018
  ...history,
960
1019
  { role: "user", content: userMessageContent },
961
1020
  ]);
@@ -1160,7 +1219,16 @@ export async function runAgentHeadless(options = {}, deps = {}) {
1160
1219
  try {
1161
1220
  const { AsyncHookSupervisor } =
1162
1221
  await import("../lib/async-hook-supervisor.cjs");
1163
- _hookSupervisor = new AsyncHookSupervisor({ persistStats: true });
1222
+ _hookSupervisor = new AsyncHookSupervisor({
1223
+ persistStats: true,
1224
+ // Durably park failed-rewake signals keyed by session so a crash before
1225
+ // the turn loop drains them doesn't lose the failure — recovered on the
1226
+ // next `--resume` (see the resume block above). Only a PERSISTABLE
1227
+ // session can be resumed, so the queue follows `persist`; a one-shot /
1228
+ // --ephemeral run stays byte-unchanged (no session id → no writes).
1229
+ persistQueue: persist,
1230
+ sessionId: persist ? sessionId : null,
1231
+ });
1164
1232
  } catch {
1165
1233
  _hookSupervisor = null; // async hooks are best-effort
1166
1234
  }
@@ -1078,6 +1078,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
1078
1078
  // cc.md/CLAUDE.md instruction block. Only `=== false` changes anything; when
1079
1079
  // the flag is absent (undefined) both paths stay byte-identical.
1080
1080
  const _leanNoProjectMemory = options.projectMemory === false;
1081
+ let _loadedInstructions = null;
1081
1082
  const systemContent = composeSystemPrompt(
1082
1083
  buildSystemPrompt(cwd, {
1083
1084
  additionalDirectories,
@@ -1093,10 +1094,31 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
1093
1094
  outputStyle: outputStyleBody,
1094
1095
  instructionExcludes,
1095
1096
  projectMemory: _leanNoProjectMemory ? false : undefined,
1097
+ onInstructionsLoaded: (loaded) => {
1098
+ _loadedInstructions = loaded;
1099
+ },
1096
1100
  },
1097
1101
  );
1098
1102
  const messages = [{ role: "system", content: systemContent }];
1099
1103
 
1104
+ // settings.json InstructionsLoaded hooks (observe-only): fire once with the
1105
+ // exact loaded instruction file set right after the system prompt is built.
1106
+ // Best-effort; no-op when project memory is off or no hook is registered.
1107
+ if (settingsHooks && _loadedInstructions) {
1108
+ try {
1109
+ const { runInstructionsLoadedHooks } =
1110
+ await import("../lib/settings-hook-events.cjs");
1111
+ const ctx = runInstructionsLoadedHooks(settingsHooks, {
1112
+ files: _loadedInstructions.files,
1113
+ cwd,
1114
+ sessionId,
1115
+ }).additionalContext;
1116
+ if (ctx) messages.push({ role: "system", content: ctx });
1117
+ } catch (_err) {
1118
+ // best-effort
1119
+ }
1120
+ }
1121
+
1100
1122
  // §3.5.13 flywheel consumption (design module 101): in a PDH session, lead
1101
1123
  // with the user's standing feedback preferences learned ACROSS sessions
1102
1124
  // (corrections + net sentiment) so the agent honours past corrections from
@@ -15,7 +15,10 @@
15
15
 
16
16
  import fsDefault from "fs";
17
17
  import pathDefault from "path";
18
- import { loadProjectInstructionsBlock } from "../lib/project-instructions.js";
18
+ import {
19
+ loadProjectInstructions,
20
+ renderProjectInstructionsBlock,
21
+ } from "../lib/project-instructions.js";
19
22
 
20
23
  /**
21
24
  * Resolve a CLI prompt value. A leading `@` means "read this file"; anything
@@ -48,7 +51,12 @@ export function resolvePromptText(value, opts = {}) {
48
51
  * - an append is added after, separated by a blank line.
49
52
  *
50
53
  * @param {string} base
51
- * @param {object} [opts] { systemPrompt, appendSystemPrompt }
54
+ * @param {object} [opts] { systemPrompt, appendSystemPrompt, outputStyle,
55
+ * projectMemory, cwd, instructionExcludes, onInstructionsLoaded }.
56
+ * `onInstructionsLoaded(loaded)` — optional observe-only callback invoked with
57
+ * the loaded project-instruction object ({files:[{path,scope,truncated,…}]})
58
+ * right after it is rendered, so a caller can fire an InstructionsLoaded
59
+ * lifecycle hook. Never affects the returned prompt.
52
60
  * @returns {string}
53
61
  */
54
62
  export function composeSystemPrompt(base, opts = {}) {
@@ -77,16 +85,35 @@ export function composeSystemPrompt(base, opts = {}) {
77
85
  else pmMode = process.env.VITEST ? "off" : "full";
78
86
  }
79
87
  if (pmMode !== "off") {
80
- const block = loadProjectInstructionsBlock({
81
- cwd,
82
- home: opts.projectMemoryHome,
83
- deps: opts.projectMemoryDeps,
84
- // Large-monorepo reduction lever: subtrees whose instruction/rule/@import
85
- // files never load (config `instructionExcludes`, forwarded by the caller).
86
- instructionExcludes: opts.instructionExcludes,
87
- // Lean mode → keep only the entry instruction files.
88
- entryOnly: pmMode === "lean",
89
- });
88
+ // Inlined loadProjectInstructionsBlock (load → render, fail-open to "") so
89
+ // the loaded metadata is available for the optional onInstructionsLoaded
90
+ // callback — the InstructionsLoaded lifecycle hook fires with the EXACT set
91
+ // that was injected (path/scope/truncated), never a re-discovery that could
92
+ // drift from what actually loaded. The prompt output is byte-identical.
93
+ let block = "";
94
+ try {
95
+ const loaded = loadProjectInstructions({
96
+ cwd,
97
+ home: opts.projectMemoryHome,
98
+ deps: opts.projectMemoryDeps,
99
+ // Large-monorepo reduction lever: subtrees whose instruction/rule/@import
100
+ // files never load (config `instructionExcludes`, forwarded by the caller).
101
+ instructionExcludes: opts.instructionExcludes,
102
+ // Lean mode → keep only the entry instruction files.
103
+ entryOnly: pmMode === "lean",
104
+ });
105
+ block = renderProjectInstructionsBlock(loaded);
106
+ if (typeof opts.onInstructionsLoaded === "function") {
107
+ // Observe-only: a callback throw must never affect the composed prompt.
108
+ try {
109
+ opts.onInstructionsLoaded(loaded);
110
+ } catch {
111
+ /* callback is best-effort */
112
+ }
113
+ }
114
+ } catch {
115
+ block = ""; // fail-open, identical to loadProjectInstructionsBlock
116
+ }
90
117
  if (block) result = result ? `${result}\n\n${block}` : block;
91
118
  }
92
119
  if (appendSystemPrompt) {
@@ -1 +0,0 @@
1
- import{P as c,J as p,b as s}from"./vendor-Bn1JzzAn.js";import{r as a}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-76GMjcbq.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=s(()=>a(e.content||"")),n={props:e,rendered:r,computed:s,get renderMarkdown(){return a}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function u(t,o,e,r,n,m){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const b=d(_,[["render",u],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-bNHuzk/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{b as M};
@@ -1 +0,0 @@
1
- import{E as F,b as D,r as R,I as p,J as c,U as _,c as n,K as a,S as C,V as b,o as I,x as V,P as i,Q as k,R as r,F as x,Z as O}from"./vendor-Bn1JzzAn.js";import{u as P,_ as E}from"./index-76GMjcbq.js";import{R as U}from"./icons-DG5UD-6K.js";const B=F("tasks",()=>{const y=R([]),l=R(!1);let u=null,t=null,d=null;const N=D(()=>y.value.filter(e=>e.status==="running")),v=D(()=>y.value.filter(e=>e.status==="pending")),w=D(()=>y.value.filter(e=>e.status==="completed"||e.status==="failed"||e.status==="timeout"));async function s(){const e=P();l.value=!0;try{const g=await e.sendRaw({type:"tasks-list"});g&&Array.isArray(g.tasks)&&(y.value=g.tasks)}catch{}finally{l.value=!1}}async function m(e){const g=P();try{await g.sendRaw({type:"tasks-stop",taskId:e})}catch{}finally{await s()}}const f=R(null);function h(e=5e3){T(),s(),u=setInterval(s,e),S()}function T(){u&&(clearInterval(u),u=null),t&&(t(),t=null),d&&(clearTimeout(d),d=null)}function S(){const e=P();if(t)return;const g=z=>{z.type==="task:notification"&&z.payload?.task&&(f.value=z.payload.task,s(),d&&clearTimeout(d),d=setTimeout(()=>{f.value=null,d=null},8e3))};t=e.onRuntimeEvent(g)}function A(e){return!e||e<0?"-":e<1e3?`${e}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${(e/6e4).toFixed(1)}m`}function o(e){switch(e){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:y,loading:l,running:N,pending:v,completed:w,lastNotification:f,fetchTasks:s,stopTask:m,startPolling:h,stopPolling:T,formatDuration:A,getStatusColor:o}}),L={__name:"Tasks",setup(y,{expose:l}){l();const u=B(),t=[{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 d(s){return s.status==="running"&&s.startedAt?u.formatDuration(Date.now()-s.startedAt):s.completedAt&&s.startedAt?u.formatDuration(s.completedAt-s.startedAt):"-"}function N(s){return s?new Date(s).toLocaleString():"-"}function v(s,m){return s?s.length>m?`${s.slice(0,m)}...`:s:""}I(()=>u.startPolling(5e3)),V(()=>u.stopPolling());const w={store:u,columns:t,getDuration:d,formatTime:N,truncate:v,onMounted:I,onUnmounted:V,get ReloadOutlined(){return U},get useTasksStore(){return B}};return Object.defineProperty(w,"__isScriptSetup",{enumerable:!1,value:!0}),w}},j={class:"page-header"},H={key:0,class:"error-text"},J={key:1},K={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"},X={key:2,class:"muted-text"};function Y(y,l,u,t,d,N){const v=p("a-button"),w=p("a-space"),s=p("a-alert"),m=p("a-statistic"),f=p("a-card"),h=p("a-col"),T=p("a-row"),S=p("a-tag"),A=p("a-table");return i(),c("div",null,[_("div",j,[l[3]||(l[3]=_("div",null,[_("h2",{class:"page-title"},"后台任务"),_("p",{class:"page-sub"},"查看后台任务队列、实时通知和任务执行结果。")],-1)),n(w,null,{default:a(()=>[n(v,{ghost:"",loading:t.store.loading,onClick:l[0]||(l[0]=o=>t.store.fetchTasks())},{icon:a(()=>[n(t.ReloadOutlined)]),default:a(()=>[l[2]||(l[2]=k(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),t.store.lastNotification?(i(),C(s,{key:0,type:t.store.lastNotification.status==="completed"?"success":"error","show-icon":"",closable:"",class:"banner",onClose:l[1]||(l[1]=o=>t.store.lastNotification=null)},{message:a(()=>[k(" 任务"+r(t.store.lastNotification.status==="completed"?"完成":"结束")+": "+r(t.store.lastNotification.description||t.store.lastNotification.id.slice(0,16)),1)]),description:a(()=>[t.store.lastNotification.error?(i(),c("span",H,r(t.store.lastNotification.error),1)):t.store.lastNotification.result?(i(),c("span",J,r(t.truncate(String(t.store.lastNotification.result),120)),1)):b("v-if",!0)]),_:1},8,["type"])):b("v-if",!0),n(T,{gutter:[16,16],class:"stats-row"},{default:a(()=>[n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"全部任务",value:t.store.tasks.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"运行中",value:t.store.running.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"等待中",value:t.store.pending.length},null,8,["value"])]),_:1})]),_:1}),n(h,{xs:12,sm:6},{default:a(()=>[n(f,{class:"stat-card",size:"small"},{default:a(()=>[n(m,{title:"已完成",value:t.store.completed.length},null,8,["value"])]),_:1})]),_:1})]),_:1}),t.store.running.length>0?(i(),C(f,{key:1,title:"运行中的任务",class:"panel-card",size:"small"},{default:a(()=>[(i(!0),c(x,null,O(t.store.running,o=>(i(),c("div",{key:o.id,class:"task-item running"},[_("div",K,[n(S,{color:t.store.getStatusColor(o.status)},{default:a(()=>[k(r(o.status.toUpperCase()),1)]),_:2},1032,["color"]),_("span",M,r(o.description),1),_("span",Q,r(o.id.slice(0,16)),1)]),_("div",W,[_("span",null,"类型: "+r(o.type||"-"),1),_("span",null,"已运行: "+r(t.store.formatDuration(Date.now()-o.startedAt)),1),n(v,{size:"small",danger:"",onClick:e=>t.store.stopTask(o.id)},{default:a(()=>[...l[4]||(l[4]=[k("停止",-1)])]),_:1},8,["onClick"])])]))),128))]),_:1})):b("v-if",!0),n(f,{class:"panel-card"},{default:a(()=>[n(A,{columns:t.columns,"data-source":t.store.tasks,pagination:{pageSize:15,size:"small"},loading:t.store.loading,"row-key":"id",size:"small"},{bodyCell:a(({column:o,record:e})=>[o.key==="status"?(i(),C(S,{key:0,color:t.store.getStatusColor(e.status)},{default:a(()=>[k(r(e.status),1)]),_:2},1032,["color"])):o.key==="description"?(i(),c("span",{key:1,title:e.command},r(e.description),9,Z)):o.key==="duration"?(i(),c(x,{key:2},[k(r(t.getDuration(e)),1)],64)):o.key==="createdAt"?(i(),c(x,{key:3},[k(r(t.formatTime(e.createdAt)),1)],64)):o.key==="result"?(i(),c(x,{key:4},[e.error?(i(),c("span",q,r(t.truncate(e.error,60)),1)):e.result?(i(),c("span",G,r(t.truncate(String(e.result),60)),1)):(i(),c("span",X,"-"))],64)):o.key==="action"?(i(),c(x,{key:5},[e.status==="running"?(i(),C(v,{key:0,size:"small",danger:"",onClick:g=>t.store.stopTask(e.id)},{default:a(()=>[...l[5]||(l[5]=[k(" 停止 ",-1)])]),_:1},8,["onClick"])):b("v-if",!0)],64)):b("v-if",!0)]),_:1},8,["data-source","loading"])]),_:1})])}const st=E(L,[["render",Y],["__scopeId","data-v-da5ff6a2"],["__file","/tmp/cc-web-panel-bNHuzk/repo/packages/web-panel/src/views/Tasks.vue"]]);export{st 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-76GMjcbq.js";import{I as z,J as x,U as _,Q as D,S as K,K as T,V as R,c as A,F as Q,Z as Y,R as E,o as Z,f as G,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-Bn1JzzAn.js";import{R as ye,b as pe,at as ge}from"./icons-DG5UD-6K.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 H=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});H.observe(b);const ue=t.offs;t.offs=()=>{try{H.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 X(){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}}Z(async()=>{await X()}),G(()=>{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 j={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:X,ref:S,computed:ee,onMounted:Z,onBeforeUnmount:G,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(j,"__isScriptSetup",{enumerable:!1,value:!0}),j}},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(),K(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(),K(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(Q,null,Y(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(Q,null,Y(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-bNHuzk/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Fe as default};
@@ -1 +0,0 @@
1
- import{Q as r}from"./index-76GMjcbq.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-CfDPzFPq.js";import{a0 as t}from"./index-76GMjcbq.js";import"./vendor-Bn1JzzAn.js";import"./index-Bvj07Ab1.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-BuAsoNTS.js";import{a0 as t}from"./index-76GMjcbq.js";import"./vendor-Bn1JzzAn.js";import"./responsiveObserve-Dy8D0D3n.js";import"./useFlexGapSupport-C82c33XI.js";import"./styleChecker-CWhJrDON.js";import"./index-Bvj07Ab1.js";import"./icons-DG5UD-6K.js";const l=t(o);export{l as default};