@qwen-code/qwen-code 0.19.10 → 0.19.11-nightly.20260718.767a32484

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 (307) hide show
  1. package/bundled/qc-helper/docs/configuration/model-providers.md +11 -0
  2. package/bundled/qc-helper/docs/configuration/settings.md +15 -14
  3. package/bundled/qc-helper/docs/features/approval-mode.md +2 -2
  4. package/bundled/qc-helper/docs/features/channels/dingtalk.md +30 -0
  5. package/bundled/qc-helper/docs/features/channels/overview.md +66 -17
  6. package/bundled/qc-helper/docs/features/channels/wecom.md +8 -7
  7. package/bundled/qc-helper/docs/features/sandbox.md +2 -0
  8. package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +42 -7
  9. package/bundled/qc-helper/docs/qwen-serve.md +77 -46
  10. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
  11. package/bundled/review/SKILL.md +163 -403
  12. package/chunks/{MaxSizedBox-67ODZ4SZ.js → MaxSizedBox-ZFHA4QEQ.js} +30 -30
  13. package/chunks/{StandaloneSessionPicker-SIPBQT5Z.js → StandaloneSessionPicker-YRWOQVQA.js} +44 -44
  14. package/chunks/{acpAgent-VPZJXLFX.js → acpAgent-U2P2IESZ.js} +1423 -487
  15. package/chunks/{agent-Z7NWL6XL.js → agent-GQXX6X5Y.js} +26 -26
  16. package/chunks/{agent-headless-73HZ6ROQ.js → agent-headless-3572NBCK.js} +26 -26
  17. package/chunks/{anthropicContentGenerator-56U3YCP2.js → anthropicContentGenerator-Y65DMM64.js} +103 -18
  18. package/chunks/{artifact-tool-BWZZJ42H.js → artifact-tool-WR7I2XON.js} +2 -2
  19. package/chunks/{askUserQuestion-WU3S5A5T.js → askUserQuestion-B4FUTPHD.js} +2 -44
  20. package/chunks/{bridge-XFKW6S7Q.js → bridge-N5RMGD7G.js} +31 -33
  21. package/chunks/{ca-C2JTT2N5.js → ca-M3GQQ26D.js} +7 -2
  22. package/chunks/channel-worker-group-HZVJKLGX.js +21 -0
  23. package/chunks/{channel-worker-manager-5RWKSGEU.js → channel-worker-manager-3WDK4HNS.js} +34 -10
  24. package/chunks/{channel-worker-supervisor-PCDAZN4D.js → channel-worker-supervisor-U2W6Q5F7.js} +6 -4
  25. package/chunks/{chunk-YYPXHMWO.js → chunk-2XRGFF5K.js} +6 -6
  26. package/chunks/{chunk-ZKMGAFYV.js → chunk-2YSZE74N.js} +2 -2
  27. package/chunks/{chunk-L5U3ELZX.js → chunk-335ECZTA.js} +1 -1
  28. package/chunks/{chunk-5EBKKSBX.js → chunk-336KPNNV.js} +2 -2
  29. package/chunks/{chunk-Q5GLXH5Q.js → chunk-3CL5SEDT.js} +6 -6
  30. package/chunks/{chunk-2FO5GFKZ.js → chunk-3DJY4IFO.js} +1 -1
  31. package/chunks/{chunk-CJFNEBYB.js → chunk-3NWYQ7FX.js} +2 -2
  32. package/chunks/{chunk-WIASPMLX.js → chunk-3X2CFOUM.js} +358 -298
  33. package/chunks/{chunk-K7CRWKOE.js → chunk-3YJZ6WNY.js} +5812 -4520
  34. package/chunks/{chunk-Y66VOBRP.js → chunk-4CA4WUMS.js} +2 -2
  35. package/chunks/{chunk-LQIDP6K5.js → chunk-4CHDYDG3.js} +1 -1
  36. package/chunks/{chunk-TISZXPAX.js → chunk-4HCYNDMG.js} +1 -1
  37. package/chunks/chunk-4JBTZBCW.js +140 -0
  38. package/chunks/{chunk-TV6K2FB4.js → chunk-4RPARQ5D.js} +2 -2
  39. package/chunks/{chunk-RCEEXIOO.js → chunk-4XCVGEEX.js} +3 -3
  40. package/chunks/{chunk-N6FXRR6P.js → chunk-57RWF6R7.js} +1 -1
  41. package/chunks/chunk-5O34IMY5.js +59 -0
  42. package/chunks/{chunk-5LROA5W4.js → chunk-5QRK2VZG.js} +8 -8
  43. package/chunks/{chunk-7L4XBYVW.js → chunk-632KROVU.js} +10 -3
  44. package/chunks/{chunk-65N2J6V2.js → chunk-64XGKNSI.js} +3 -3
  45. package/chunks/{chunk-P6LART6G.js → chunk-66IT3EY2.js} +1059 -129
  46. package/chunks/{chunk-FXMC7SL2.js → chunk-6ITLKEOZ.js} +3 -3
  47. package/chunks/{chunk-F7NXQH4Y.js → chunk-6YIRYY3P.js} +1 -1
  48. package/chunks/{chunk-GGJII3FM.js → chunk-6Z5NRZVU.js} +92 -3
  49. package/chunks/{chunk-DPFBNG72.js → chunk-AEKYFMYE.js} +1 -1
  50. package/chunks/{chunk-2UUAIFQO.js → chunk-ANRANWVE.js} +9 -1
  51. package/chunks/{chunk-SXU3KKNI.js → chunk-ATJ7H5AS.js} +419 -76
  52. package/chunks/{chunk-6GETGQWP.js → chunk-C5NSOSF4.js} +64 -18
  53. package/chunks/{chunk-TQBODCFD.js → chunk-CMVFTMRD.js} +251 -3
  54. package/chunks/{chunk-DK33QJ3V.js → chunk-CZSAIBUB.js} +733 -14
  55. package/chunks/{chunk-3MX7D6QN.js → chunk-DASWPKXR.js} +32 -4
  56. package/chunks/{chunk-JSJFKYWT.js → chunk-DPSHAB47.js} +2 -2
  57. package/chunks/{chunk-7MJAZMXK.js → chunk-ECZFTRTP.js} +29 -78
  58. package/chunks/{chunk-H3FQOPPS.js → chunk-EKG3BHQY.js} +4 -4
  59. package/chunks/{chunk-FSA7ERJ2.js → chunk-F2RR4HO2.js} +1 -1
  60. package/chunks/{chunk-EQY6POVO.js → chunk-F5XYN5VF.js} +2 -2
  61. package/chunks/chunk-FEOZBUMT.js +77 -0
  62. package/chunks/{chunk-L62SEJWY.js → chunk-FHUXCRAF.js} +4 -4
  63. package/chunks/{chunk-OFEVHGVU.js → chunk-FSJGBUQI.js} +818 -31
  64. package/chunks/{chunk-FBU7WRZI.js → chunk-FUTHTZVV.js} +1 -1
  65. package/chunks/{chunk-ZRKBI3DP.js → chunk-FZRES4GK.js} +1 -1
  66. package/chunks/{chunk-OKAIGAYW.js → chunk-G274ETR6.js} +3 -3
  67. package/chunks/{chunk-6GKMJPOC.js → chunk-GA3WUOO7.js} +5 -5
  68. package/chunks/{chunk-X362TMXZ.js → chunk-GAQOQMHY.js} +8 -6
  69. package/chunks/{chunk-WLXYAKV7.js → chunk-GG6RSNWS.js} +9 -4
  70. package/chunks/{chunk-CEW4HDPK.js → chunk-GUNTLALV.js} +2484 -362
  71. package/chunks/{chunk-LXLTBIDP.js → chunk-HCCR43AY.js} +1 -1
  72. package/chunks/{chunk-RDRVMDWV.js → chunk-HIMIG6PI.js} +11 -11
  73. package/chunks/{chunk-MO7O5722.js → chunk-HQXQCIT2.js} +45 -5
  74. package/chunks/{chunk-LTNI523B.js → chunk-HT7L5FCZ.js} +28 -5
  75. package/chunks/{chunk-7NAWTFVY.js → chunk-IENO2YAT.js} +3 -3
  76. package/chunks/{chunk-3XJFUTNM.js → chunk-IK5TYYVR.js} +59 -12
  77. package/chunks/{chunk-AAR5SGMD.js → chunk-IVKLDHU6.js} +7 -5
  78. package/chunks/{chunk-6W6DI34P.js → chunk-IX7O5WI3.js} +180 -8
  79. package/chunks/{chunk-SPJQO2CE.js → chunk-J2MKYJKZ.js} +2 -2
  80. package/chunks/{chunk-SPUYQB4T.js → chunk-JBAQ5BYX.js} +1 -1
  81. package/chunks/{chunk-TYLOFD2U.js → chunk-JCJPZMJV.js} +1 -1
  82. package/chunks/chunk-JDIUK2Y3.js +226 -0
  83. package/chunks/{chunk-L37RC7MQ.js → chunk-JUVTV4NF.js} +1 -1
  84. package/chunks/{chunk-WDWJ4OQJ.js → chunk-K2GBHL73.js} +4 -4
  85. package/chunks/{chunk-HHEFI4RP.js → chunk-KEVDWH3U.js} +857 -137
  86. package/chunks/{chunk-YU56QGXX.js → chunk-KTKETHMY.js} +1 -1
  87. package/chunks/{chunk-WDW64OW3.js → chunk-LGY7PG7Q.js} +5 -5
  88. package/chunks/{chunk-E67NFMF4.js → chunk-LKR7QQ63.js} +37 -3
  89. package/chunks/{chunk-4YWLED2A.js → chunk-LSFVUGXT.js} +9 -6
  90. package/chunks/{chunk-W34A5MJH.js → chunk-LTD3CHGS.js} +1 -1
  91. package/chunks/chunk-LXXMOYPL.js +22 -0
  92. package/chunks/{chunk-BBNVFRGD.js → chunk-MI2V6IWU.js} +1 -1
  93. package/chunks/{chunk-UFOKA4PR.js → chunk-O2K6BLPZ.js} +114 -4
  94. package/chunks/{chunk-B5I2IIWY.js → chunk-OBYAX5QZ.js} +6 -6
  95. package/chunks/{chunk-V7EQTZYR.js → chunk-OCQ2QTFJ.js} +203 -47
  96. package/chunks/{chunk-VBRRNQB7.js → chunk-OPVIKLKK.js} +112 -25
  97. package/chunks/{chunk-2Z5UX4KI.js → chunk-OSSDHJDU.js} +1 -1
  98. package/chunks/{chunk-TTUO4DNG.js → chunk-OXOEOOQU.js} +126 -734
  99. package/chunks/{chunk-4FMG7EDJ.js → chunk-PWYLF7SS.js} +79 -16
  100. package/chunks/chunk-QFEY6OXH.js +45 -0
  101. package/chunks/{chunk-YX4LLZ3D.js → chunk-QPRDXJIC.js} +115 -40
  102. package/chunks/{chunk-7R4DPSRA.js → chunk-R3VWUU2E.js} +1 -1
  103. package/chunks/{chunk-XLIRF7IK.js → chunk-S4N3G4BB.js} +1 -1
  104. package/chunks/{chunk-ARKANCNX.js → chunk-SGPFJMRP.js} +1 -1
  105. package/chunks/{chunk-WTSXKLG5.js → chunk-SUARMD4Q.js} +1 -1
  106. package/chunks/{chunk-PZL23GTM.js → chunk-T3W4SDRB.js} +2 -0
  107. package/chunks/chunk-T4TZQJ7W.js +48 -0
  108. package/chunks/{chunk-K4PZ5F5T.js → chunk-TVYM3Q3J.js} +101 -8
  109. package/chunks/{chunk-4LD5APFL.js → chunk-TYQMGACW.js} +1 -0
  110. package/chunks/{chunk-6OATMEYN.js → chunk-U2LNTX56.js} +12 -4
  111. package/chunks/{chunk-422XAKCK.js → chunk-U2XBPBO3.js} +4 -3
  112. package/chunks/{chunk-LNUXFLLJ.js → chunk-U4FJ26D2.js} +54 -6
  113. package/chunks/{chunk-ZQTZXVHP.js → chunk-U6OPT4H2.js} +4 -18
  114. package/chunks/{chunk-7NFB7LBQ.js → chunk-UE5TZ55T.js} +8 -0
  115. package/chunks/{chunk-CUUXANEQ.js → chunk-URP6O2PP.js} +6 -1
  116. package/chunks/{chunk-GDQQRV43.js → chunk-V2FRLYHN.js} +3 -3
  117. package/chunks/{chunk-WIEO4CWB.js → chunk-VAJS2E2D.js} +1 -1
  118. package/chunks/{chunk-TXY2C3D2.js → chunk-VNN3JNYT.js} +1 -1
  119. package/chunks/{chunk-YHN5SUIJ.js → chunk-W7H223ZZ.js} +1 -1
  120. package/chunks/{chunk-WX6SD4IQ.js → chunk-WEPXQKGP.js} +1 -1
  121. package/chunks/{chunk-KSO42X3Z.js → chunk-X6YQWCIJ.js} +21 -2
  122. package/chunks/{chunk-URU5UEK6.js → chunk-XA7OKDWM.js} +135 -68
  123. package/chunks/{chunk-Q6TUALBE.js → chunk-XAAEDML2.js} +1 -1
  124. package/chunks/{chunk-KKRTYONM.js → chunk-XSPFQQRE.js} +3 -3
  125. package/chunks/{chunk-OATTJGPJ.js → chunk-Y72B36CP.js} +7 -7
  126. package/chunks/{chunk-ZPAHLFZU.js → chunk-Z2LBNX3R.js} +2 -2
  127. package/chunks/{chunk-XXJKGHZV.js → chunk-ZTSDZQZO.js} +131 -4
  128. package/chunks/{computer-use-IYTX45WA.js → computer-use-UIFBH25Y.js} +26 -26
  129. package/chunks/{config-utils-CFT33LTP.js → config-utils-2LHI7JXU.js} +3 -3
  130. package/chunks/{contextCommand-272V77WU.js → contextCommand-VGZHKEH2.js} +28 -28
  131. package/chunks/{create-sub-session-WNX2OQVX.js → create-sub-session-DIJOV6HV.js} +2 -2
  132. package/chunks/{create-sub-session-CBJMQLYP.js → create-sub-session-OFVI4H6I.js} +26 -26
  133. package/chunks/{cron-create-36TIFKRT.js → cron-create-34GVLSW5.js} +4 -4
  134. package/chunks/{cron-delete-OQD3WULU.js → cron-delete-NMVKUL45.js} +4 -4
  135. package/chunks/{cron-list-4533T2FH.js → cron-list-277ZOR7L.js} +4 -4
  136. package/chunks/{daemon-RNGFPMAB.js → daemon-72MEV3TY.js} +361 -84
  137. package/chunks/daemon-status-provider-ZJJ6AOG2.js +75 -0
  138. package/chunks/{de-2VCDRDGU.js → de-56TMDIKS.js} +7 -2
  139. package/chunks/{dist-3V3ZV6ML.js → dist-4W3UGU2A.js} +1 -1
  140. package/chunks/{dist-HNN7DR2L.js → dist-G6QCGO2K.js} +58 -30
  141. package/chunks/{dist-ERCPDVA6.js → dist-ILVRL322.js} +4 -51
  142. package/chunks/{dist-PHEPJLXD.js → dist-KEZ5JWH4.js} +2 -2
  143. package/chunks/{dist-JZE7F6YR.js → dist-LQHDHBPP.js} +1 -1
  144. package/chunks/{dist-MOEC47TR.js → dist-SVHAGOLN.js} +1 -1
  145. package/chunks/{earlyInputCapture-EN4BRREQ.js → earlyInputCapture-NPF4PVUE.js} +27 -27
  146. package/chunks/{edit-OMAF2QDR.js → edit-F7CT6NZH.js} +27 -27
  147. package/chunks/{en-NJCA3TAA.js → en-AXS2N62H.js} +12 -3
  148. package/chunks/{enter-worktree-BBZX52HG.js → enter-worktree-Z4ET3MZL.js} +26 -26
  149. package/chunks/{enterPlanMode-5NNFMBUY.js → enterPlanMode-VYR7T5NX.js} +27 -29
  150. package/chunks/{environment-7TEWMJYN.js → environment-MBTXL57Q.js} +28 -28
  151. package/chunks/{errors-I4VKVX3F.js → errors-HN36J4FR.js} +28 -28
  152. package/chunks/{exit-worktree-FUWRJI33.js → exit-worktree-RU7JYFMF.js} +26 -26
  153. package/chunks/exitPlanMode-LUBAWMZQ.js +390 -0
  154. package/chunks/{fast-path-ZA57TOH4.js → fast-path-RFT3CDNZ.js} +2 -2
  155. package/chunks/{fr-5F3E7WKD.js → fr-ZJPE5OVN.js} +7 -2
  156. package/chunks/{gemini-UOAKVXBG.js → gemini-37NTNKZF.js} +215 -231
  157. package/chunks/{geminiContentGenerator-G6UCE6MW.js → geminiContentGenerator-76HNOYNQ.js} +5 -5
  158. package/chunks/{glob-4GJQ2UFF.js → glob-DWD7JCZE.js} +32 -27
  159. package/chunks/{grep-5QSYXF2E.js → grep-NJRXFV5C.js} +32 -27
  160. package/chunks/{handleAutoUpdate-ULHNWL6R.js → handleAutoUpdate-7GBDXW6U.js} +30 -30
  161. package/chunks/{i18n-CYDUTF6F.js → i18n-MYD5VGED.js} +27 -27
  162. package/chunks/{initializer-NRFKUGIO.js → initializer-4DHPNAZG.js} +32 -32
  163. package/chunks/{installationInfo-WELKRHHE.js → installationInfo-RWOW6BZO.js} +27 -27
  164. package/chunks/{ja-66J6B53L.js → ja-57GG4QSL.js} +7 -2
  165. package/chunks/{keychain-token-storage-AU22CQI6.js → keychain-token-storage-K23CFKGN.js} +2 -2
  166. package/chunks/{list-JVDXEG2E.js → list-MMCNNHE7.js} +34 -34
  167. package/chunks/{loadedSettingsAdapter-WAM4VUTG.js → loadedSettingsAdapter-UK4JWPYU.js} +31 -31
  168. package/chunks/{loop-wakeup-MVUKDVCP.js → loop-wakeup-KCLY4XQM.js} +5 -5
  169. package/chunks/{ls-RXNIAQDE.js → ls-UNI4LAJ3.js} +4 -4
  170. package/chunks/{lsp-HB5LM5IL.js → lsp-HPACPJAN.js} +2 -2
  171. package/chunks/{mcp-YHOZN3ZM.js → mcp-AFCVA4UV.js} +31 -31
  172. package/chunks/{monitor-R7XZPJHQ.js → monitor-RK637BNO.js} +28 -27
  173. package/chunks/nonInteractiveCli-OUGWLHNV.js +129 -0
  174. package/chunks/{notebook-edit-6RNKE2L2.js → notebook-edit-LY2X3CMF.js} +27 -27
  175. package/chunks/{openaiContentGenerator-XNS5S64I.js → openaiContentGenerator-MDYDW7IA.js} +14 -14
  176. package/chunks/{pidfile-XE4RRR2P.js → pidfile-2NUYRLKB.js} +27 -27
  177. package/chunks/processUtils-7QH3VBVN.js +29 -0
  178. package/chunks/{pt-TFZO5Y6T.js → pt-MCGZ3RZ4.js} +7 -2
  179. package/chunks/{qwenContentGenerator-APDPJ3VN.js → qwenContentGenerator-3HT4TVDL.js} +28 -28
  180. package/chunks/{qwenOAuth2-LEYOU7RU.js → qwenOAuth2-3A4TJVZT.js} +5 -5
  181. package/chunks/{read-file-XSUWXSR7.js → read-file-NE4FREFR.js} +10 -10
  182. package/chunks/{read-mcp-resource-6LRTZKXI.js → read-mcp-resource-C6NT52T6.js} +2 -2
  183. package/chunks/{record-artifact-PMDTY4OS.js → record-artifact-ENCU7QCL.js} +2 -2
  184. package/chunks/{ripGrep-APB3CDMU.js → ripGrep-DBLXWQCJ.js} +26 -26
  185. package/chunks/{ru-4L4LFHIT.js → ru-GA3NZW5Q.js} +7 -2
  186. package/chunks/{run-qwen-serve-NWTGPERT.js → run-qwen-serve-3NOCI6IL.js} +63 -39
  187. package/chunks/{runtime-EIO3NQKR.js → runtime-ZI7DSZSS.js} +35 -35
  188. package/chunks/{scheduler-JJDZBDRN.js → scheduler-SOVEP5K7.js} +26 -26
  189. package/chunks/{send-message-SR4WSXP2.js → send-message-5IFPZTPE.js} +3 -3
  190. package/chunks/{serve-WTIPB3EI.js → serve-DB6OCXIA.js} +31 -31
  191. package/chunks/{server-NJPHQHLH.js → server-LDY4YVU4.js} +2257 -648
  192. package/chunks/{session-O4AO7FTS.js → session-D6OG5SKX.js} +99 -72
  193. package/chunks/{settings-HQNDK7TG.js → settings-L52ZV5LO.js} +30 -30
  194. package/chunks/{shell-UIXM6PWG.js → shell-IU27OY3Q.js} +28 -26
  195. package/chunks/{skill-3XMB4ULV.js → skill-BSOJT7LE.js} +12 -12
  196. package/chunks/{spawnChannel-3R632QRM.js → spawnChannel-HQAM25DD.js} +28 -29
  197. package/chunks/{src-USZKPUOC.js → src-7ZBIMTJZ.js} +130 -51
  198. package/chunks/{standalone-update-L5XW3D7K.js → standalone-update-77457VVK.js} +28 -28
  199. package/chunks/{startInteractiveUI-CPZOL2WB.js → startInteractiveUI-S7WC6EZG.js} +2310 -1835
  200. package/chunks/{syntheticOutput-YKFNUQZD.js → syntheticOutput-ULOVVLY4.js} +3 -3
  201. package/chunks/{task-create-NUFOHU53.js → task-create-V2DCDSET.js} +7 -7
  202. package/chunks/{task-list-Z2IKQY3S.js → task-list-DPL5ZN55.js} +5 -5
  203. package/chunks/{task-stop-KQFIVQTJ.js → task-stop-CPEQWOT6.js} +2 -2
  204. package/chunks/{task-update-HKADXSTD.js → task-update-ZR45M5Q7.js} +7 -7
  205. package/chunks/{team-create-XXPRF3IQ.js → team-create-CO7HSUON.js} +26 -26
  206. package/chunks/{team-delete-SDNTGZLG.js → team-delete-HIWXCWJU.js} +5 -5
  207. package/chunks/{team-plan-approval-EOTTKHDW.js → team-plan-approval-QDZF5YZY.js} +26 -26
  208. package/chunks/{theme-manager-P6UITO2L.js → theme-manager-UTUT3I4P.js} +27 -27
  209. package/chunks/todoWrite-HK6B3RHJ.js +358 -0
  210. package/chunks/{tool-search-DDNGK2LR.js → tool-search-2UUORA35.js} +11 -11
  211. package/chunks/{total-session-admission-PL5N7DNY.js → total-session-admission-NTWG6G3F.js} +32 -34
  212. package/chunks/{trustedFolders-C5LMF3UR.js → trustedFolders-YF37ZCN5.js} +27 -27
  213. package/chunks/update-relaunch-QFNHPMZZ.js +87 -0
  214. package/chunks/{updateCheck-QTVVISH7.js → updateCheck-B6O42VMD.js} +30 -28
  215. package/chunks/{validateNonInterActiveAuth-RY4RKBQG.js → validateNonInterActiveAuth-SCIWJ4CX.js} +65 -65
  216. package/chunks/{version-U45RYOSD.js → version-7DA6LAI3.js} +1 -1
  217. package/chunks/{web-fetch-ZSPR3PRR.js → web-fetch-B62SJXM2.js} +5 -6
  218. package/chunks/{workflow-TCIAQYOA.js → workflow-Q5WG4THP.js} +27 -27
  219. package/chunks/{workspace-providers-status-I3G2HYLY.js → workspace-providers-status-WWLAGWQW.js} +34 -34
  220. package/chunks/{workspace-registration-store-IH5GLZ6Y.js → workspace-registration-store-BVYQVY2H.js} +1 -1
  221. package/chunks/{workspace-registry-QEKBELIX.js → workspace-registry-OD7ACADD.js} +32 -34
  222. package/chunks/{workspace-service-ORKHGLP3.js → workspace-service-4LYJWS63.js} +37 -38
  223. package/chunks/{workspace-skills-status-D7QCNDYY.js → workspace-skills-status-P2AQLZZS.js} +32 -32
  224. package/chunks/{write-file-JGRQR5VM.js → write-file-TEPGXNM3.js} +60 -27
  225. package/chunks/{zh-FSAH32JB.js → zh-E34DZ2S3.js} +12 -3
  226. package/chunks/{zh-TW-D2YIE2LO.js → zh-TW-PEI2ZWUR.js} +12 -3
  227. package/cli-entry.js +92 -8
  228. package/cli.js +11 -11
  229. package/locales/ca.js +12 -2
  230. package/locales/de.js +12 -2
  231. package/locales/en.js +20 -5
  232. package/locales/fr.js +12 -2
  233. package/locales/ja.js +12 -2
  234. package/locales/pt.js +12 -2
  235. package/locales/ru.js +12 -2
  236. package/locales/zh-TW.js +19 -3
  237. package/locales/zh.js +19 -3
  238. package/package.json +3 -3
  239. package/web-shell/assets/{arc-CUeDlxvE.js → arc-Dh-N5oEG.js} +1 -1
  240. package/web-shell/assets/{architectureDiagram-3BPJPVTR-PiUszkQA.js → architectureDiagram-3BPJPVTR-DBOQgtfF.js} +1 -1
  241. package/web-shell/assets/{blockDiagram-GPEHLZMM-s2wYSO7e.js → blockDiagram-GPEHLZMM-Dyxbuyju.js} +1 -1
  242. package/web-shell/assets/{c4Diagram-AAUBKEIU-DyLxZoz9.js → c4Diagram-AAUBKEIU-DCJR5HPT.js} +1 -1
  243. package/web-shell/assets/channel-DY0fkcKT.js +1 -0
  244. package/web-shell/assets/{chunk-2J33WTMH-Dsdai7Tk.js → chunk-2J33WTMH-BkMUcy3O.js} +1 -1
  245. package/web-shell/assets/{chunk-4BX2VUAB-DEosOjV7.js → chunk-4BX2VUAB-BSm4pLQk.js} +1 -1
  246. package/web-shell/assets/{chunk-55IACEB6-sNsRLTXf.js → chunk-55IACEB6-CuRr-XgW.js} +1 -1
  247. package/web-shell/assets/{chunk-727SXJPM-DkRNZzmh.js → chunk-727SXJPM-CLv7-w3t.js} +1 -1
  248. package/web-shell/assets/{chunk-AQP2D5EJ-BrsRNpzd.js → chunk-AQP2D5EJ-Cz_n3-JW.js} +1 -1
  249. package/web-shell/assets/{chunk-FMBD7UC4-CI039lpl.js → chunk-FMBD7UC4-CFT_62Hq.js} +1 -1
  250. package/web-shell/assets/{chunk-ND2GUHAM-M-pkeIfu.js → chunk-ND2GUHAM-DWz6DOZ6.js} +1 -1
  251. package/web-shell/assets/{chunk-QZHKN3VN-C4ckGNbH.js → chunk-QZHKN3VN-C-mRhUzw.js} +1 -1
  252. package/web-shell/assets/classDiagram-4FO5ZUOK-DBvJ6PZo.js +1 -0
  253. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DBvJ6PZo.js +1 -0
  254. package/web-shell/assets/{cose-bilkent-S5V4N54A-BciKUAFq.js → cose-bilkent-S5V4N54A-BqCZS3i1.js} +1 -1
  255. package/web-shell/assets/{dagre-BM42HDAG-C1nTSgU6.js → dagre-BM42HDAG-BGasdP8i.js} +1 -1
  256. package/web-shell/assets/{diagram-2AECGRRQ-BDPNWr1m.js → diagram-2AECGRRQ-BSyLDkMy.js} +1 -1
  257. package/web-shell/assets/{diagram-5GNKFQAL-CNFhTszL.js → diagram-5GNKFQAL-CM-ZJxWC.js} +1 -1
  258. package/web-shell/assets/{diagram-KO2AKTUF-CjPa4p5a.js → diagram-KO2AKTUF-wJdzt_C5.js} +1 -1
  259. package/web-shell/assets/{diagram-LMA3HP47-ZzPykSyG.js → diagram-LMA3HP47-DiH2fhpL.js} +1 -1
  260. package/web-shell/assets/{diagram-OG6HWLK6-0UVtZ9A4.js → diagram-OG6HWLK6-BZ9z1ZBl.js} +1 -1
  261. package/web-shell/assets/{erDiagram-TEJ5UH35-CajDZCat.js → erDiagram-TEJ5UH35-BsyWDziR.js} +1 -1
  262. package/web-shell/assets/{flowDiagram-I6XJVG4X-BRuFBIvL.js → flowDiagram-I6XJVG4X-CzdkxIrq.js} +1 -1
  263. package/web-shell/assets/{ganttDiagram-6RSMTGT7-BevGmJqG.js → ganttDiagram-6RSMTGT7-javIv2r2.js} +1 -1
  264. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-DvPMpBMb.js → gitGraphDiagram-PVQCEYII-CjHstylC.js} +1 -1
  265. package/web-shell/assets/{index-DzHwQkQq.js → index-BnJGxpah.js} +1 -1
  266. package/web-shell/assets/index-DhXB9nTa.js +1161 -0
  267. package/web-shell/assets/index-vYHgZ7bL.css +5 -0
  268. package/web-shell/assets/{infoDiagram-5YYISTIA-Oixn7tA9.js → infoDiagram-5YYISTIA-yXuQsomo.js} +1 -1
  269. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BgKpeg-j.js → ishikawaDiagram-YF4QCWOH-a85JhE6F.js} +1 -1
  270. package/web-shell/assets/{journeyDiagram-JHISSGLW-74mwxIaA.js → journeyDiagram-JHISSGLW-Dak_4BVj.js} +1 -1
  271. package/web-shell/assets/{kanban-definition-UN3LZRKU-D4D6cEqA.js → kanban-definition-UN3LZRKU-COA-LuCV.js} +1 -1
  272. package/web-shell/assets/{linear-atZRE_L2.js → linear-DNAAAQWq.js} +1 -1
  273. package/web-shell/assets/{mermaid.core-KKudX-JC.js → mermaid.core-7Ff3aIUD.js} +5 -5
  274. package/web-shell/assets/{mindmap-definition-RKZ34NQL-CMCej9yG.js → mindmap-definition-RKZ34NQL-_rCOIODU.js} +1 -1
  275. package/web-shell/assets/{pieDiagram-4H26LBE5-nhx40X7q.js → pieDiagram-4H26LBE5-C9QCQ8EW.js} +1 -1
  276. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-CUmVcN3M.js → quadrantDiagram-W4KKPZXB-CsaE4FA8.js} +1 -1
  277. package/web-shell/assets/{requirementDiagram-4Y6WPE33-C_vyEwyy.js → requirementDiagram-4Y6WPE33-tV78naTg.js} +1 -1
  278. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-DU6G4VWR.js → sankeyDiagram-5OEKKPKP-Dk3Rw7BZ.js} +1 -1
  279. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DdeRR_KJ.js → sequenceDiagram-3UESZ5HK-BGsAWcMX.js} +1 -1
  280. package/web-shell/assets/{stateDiagram-AJRCARHV-C6iCI8ps.js → stateDiagram-AJRCARHV-zSxdtdoB.js} +1 -1
  281. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-vLEEtDpO.js +1 -0
  282. package/web-shell/assets/{timeline-definition-PNZ67QCA-B_Ea8Cb7.js → timeline-definition-PNZ67QCA-j0BQh9Go.js} +1 -1
  283. package/web-shell/assets/{vennDiagram-CIIHVFJN-BPUVZEJA.js → vennDiagram-CIIHVFJN-CRaUFFIu.js} +1 -1
  284. package/web-shell/assets/{wardley-L42UT6IY-BWEj0lKY.js → wardley-L42UT6IY-D7Py_ofm.js} +1 -1
  285. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BvDsdIQw.js → wardleyDiagram-YWT4CUSO-BrDIAZcp.js} +1 -1
  286. package/web-shell/assets/{xychartDiagram-2RQKCTM6-crz0QhF_.js → xychartDiagram-2RQKCTM6-Cecdw-w2.js} +1 -1
  287. package/web-shell/index.html +2 -2
  288. package/chunks/channel-worker-group-K7QKH6IG.js +0 -13
  289. package/chunks/chunk-2HRYPZT5.js +0 -25
  290. package/chunks/chunk-B7NUUEXC.js +0 -311
  291. package/chunks/chunk-CARU2RR2.js +0 -24
  292. package/chunks/chunk-GYTKQYDB.js +0 -23
  293. package/chunks/chunk-LQU7EVFA.js +0 -30
  294. package/chunks/chunk-OCPBI7J5.js +0 -18
  295. package/chunks/chunk-OJAMDVF5.js +0 -66
  296. package/chunks/chunk-QAW7PIHT.js +0 -168
  297. package/chunks/chunk-TEGEBB2I.js +0 -122
  298. package/chunks/daemon-status-provider-L4STG5VO.js +0 -76
  299. package/chunks/exitPlanMode-IHCJ5EEI.js +0 -909
  300. package/chunks/nonInteractiveCli-NSOB6D74.js +0 -129
  301. package/chunks/todoWrite-YNXB27GB.js +0 -531
  302. package/web-shell/assets/channel-DkuJJ0qd.js +0 -1
  303. package/web-shell/assets/classDiagram-4FO5ZUOK-CwqHc0TB.js +0 -1
  304. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CwqHc0TB.js +0 -1
  305. package/web-shell/assets/index-Cnvv4VcI.css +0 -5
  306. package/web-shell/assets/index-D1Uyklxa.js +0 -1088
  307. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-C0_6nR6C.js +0 -1
@@ -1,22 +1,25 @@
1
1
  // Force strict mode and setup for ESM
2
2
  "use strict";
3
3
  import {
4
- openQwenAsrRealtimeStream,
5
- openVoiceStream,
6
- openVoiceStreamWithRetry
7
- } from "./chunk-JSJFKYWT.js";
8
- import {
4
+ GENERATION_MAX_PROMPT_BYTES,
9
5
  MAX_REMEMBER_CONTENT_BYTES,
10
6
  createWorkspaceMemoryExtractionErrorLogger,
11
7
  extractRememberErrorCode,
12
8
  formatWorkspaceMemoryDreamSummary,
13
9
  formatWorkspaceMemoryForgetSummary,
14
10
  isValidServerName,
11
+ redactMcpServersSetting,
15
12
  replayTranscriptRecordPage,
13
+ restoreRedactedMcpServersSetting,
16
14
  shouldSuppressRememberErrorDetails,
17
15
  workspaceMemoryFailureCode,
18
16
  workspaceMemoryFailureDiagnostics
19
- } from "./chunk-6W6DI34P.js";
17
+ } from "./chunk-IX7O5WI3.js";
18
+ import {
19
+ openQwenAsrRealtimeStream,
20
+ openVoiceStream,
21
+ openVoiceStreamWithRetry
22
+ } from "./chunk-DPSHAB47.js";
20
23
  import {
21
24
  SetupGithubError,
22
25
  collectSessionData,
@@ -27,9 +30,9 @@ import {
27
30
  toJson,
28
31
  toJsonl,
29
32
  toMarkdown
30
- } from "./chunk-4FMG7EDJ.js";
31
- import "./chunk-SPUYQB4T.js";
32
- import "./chunk-WTSXKLG5.js";
33
+ } from "./chunk-PWYLF7SS.js";
34
+ import "./chunk-JBAQ5BYX.js";
35
+ import "./chunk-SUARMD4Q.js";
33
36
  import "./chunk-QHTIBUWB.js";
34
37
  import "./chunk-L573Z2QZ.js";
35
38
  import {
@@ -41,7 +44,6 @@ import {
41
44
  MAX_CLIENT_ID_LENGTH,
42
45
  MAX_CONCURRENT_VOICE_SESSIONS,
43
46
  MAX_SERVER_NAME_LENGTH,
44
- MAX_SKILL_NAME_LENGTH,
45
47
  MAX_TOOL_NAME_LENGTH,
46
48
  PathMutexRegistry,
47
49
  QWEN_CDP_MCP_COMMAND_ENV,
@@ -62,9 +64,11 @@ import {
62
64
  denyBrowserOriginCors,
63
65
  detectFromLoopback,
64
66
  getAdvertisedServeFeatures,
67
+ getDeferredRuntimeRequestTiming,
65
68
  getServeProtocolVersions,
66
69
  hostAllowlist,
67
70
  isBrowserAutomationMcpAvailable,
71
+ isDeepHealthQuery,
68
72
  parseAllowOriginPatterns,
69
73
  parseAndValidateWorkspaceClientId,
70
74
  parseClientIdHeader,
@@ -85,47 +89,51 @@ import {
85
89
  setRateLimiter,
86
90
  unsafeRevealSecret,
87
91
  validateMcpRuntimeServerName
88
- } from "./chunk-MO7O5722.js";
92
+ } from "./chunk-HQXQCIT2.js";
89
93
  import {
90
94
  isLoopbackBind
91
95
  } from "./chunk-RXFQM6FQ.js";
92
96
  import {
93
97
  createDaemonStatusProvider
94
- } from "./chunk-ZQTZXVHP.js";
95
- import "./chunk-WDWJ4OQJ.js";
98
+ } from "./chunk-U6OPT4H2.js";
99
+ import "./chunk-LXXMOYPL.js";
100
+ import "./chunk-K2GBHL73.js";
96
101
  import "./chunk-E5Z2AVNV.js";
97
102
  import {
98
103
  createWorkspaceProvidersStatusProvider
99
- } from "./chunk-7MJAZMXK.js";
104
+ } from "./chunk-ECZFTRTP.js";
100
105
  import {
101
106
  getAuthTypeFromEnv,
102
107
  resolveCliGenerationConfig
103
- } from "./chunk-GGJII3FM.js";
108
+ } from "./chunk-6Z5NRZVU.js";
104
109
  import {
105
110
  snapshotProcessEnv
106
- } from "./chunk-ZKMGAFYV.js";
111
+ } from "./chunk-2YSZE74N.js";
107
112
  import {
108
113
  createWorkspaceSkillsStatusProvider
109
- } from "./chunk-WLXYAKV7.js";
114
+ } from "./chunk-GG6RSNWS.js";
110
115
  import "./chunk-2W3OOD4W.js";
111
116
  import {
112
117
  EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
118
+ MAX_WORKSPACE_SKILL_NAME_LENGTH,
119
+ WorkspaceSkillManagementError,
113
120
  WorkspaceVoiceError,
114
121
  buildWorkspaceVoiceSettingsWrites,
115
122
  buildWorkspaceVoiceStatus,
116
123
  createDaemonWorkspaceService,
117
124
  hasConfiguredBatchVoiceTranscriptionModel,
118
125
  transcribeWorkspaceVoiceAudio,
126
+ validateWorkspaceSkillName,
119
127
  validateWorkspaceVoiceState,
120
128
  voiceSettingsScopeToWire
121
- } from "./chunk-OFEVHGVU.js";
129
+ } from "./chunk-FSJGBUQI.js";
122
130
  import {
123
131
  PermissionRulesValidationError,
124
132
  buildPermissionSettings,
125
133
  isPermissionRuleType,
126
134
  normalizePermissionRules,
127
135
  readPermissionRuleSet
128
- } from "./chunk-N6FXRR6P.js";
136
+ } from "./chunk-57RWF6R7.js";
129
137
  import {
130
138
  assertVoiceBaseUrlNetworkAllowed,
131
139
  isStreamingVoiceModel,
@@ -133,13 +141,13 @@ import {
133
141
  resolveVoiceTranscriptionConfig,
134
142
  sanitizeVoiceErrorMessage,
135
143
  transcribeVoiceAudio
136
- } from "./chunk-FXMC7SL2.js";
144
+ } from "./chunk-6ITLKEOZ.js";
137
145
  import {
138
146
  isVoiceEnabled,
139
147
  isVoiceMode,
140
148
  readVoiceModel
141
- } from "./chunk-DPFBNG72.js";
142
- import "./chunk-FSA7ERJ2.js";
149
+ } from "./chunk-AEKYFMYE.js";
150
+ import "./chunk-F2RR4HO2.js";
143
151
  import {
144
152
  WorkspacePermissionRulesSessionRequiredError,
145
153
  WorkspaceSettingsPartialPersistError,
@@ -148,24 +156,24 @@ import {
148
156
  } from "./chunk-OA4JVLSA.js";
149
157
  import {
150
158
  createTotalSessionAdmissionController
151
- } from "./chunk-7R4DPSRA.js";
159
+ } from "./chunk-R3VWUU2E.js";
152
160
  import {
153
161
  createSingleWorkspaceRegistry,
154
162
  createWorkspaceSessionOwnerIndex
155
- } from "./chunk-YHN5SUIJ.js";
163
+ } from "./chunk-W7H223ZZ.js";
156
164
  import "./chunk-GRC5HGPI.js";
157
165
  import {
158
166
  SessionArtifactAuthorizationError,
159
167
  SessionArtifactValidationError,
160
- createAcpSessionBridge
161
- } from "./chunk-HHEFI4RP.js";
162
- import "./chunk-PZL23GTM.js";
168
+ createAcpSessionBridge,
169
+ parseSessionSource
170
+ } from "./chunk-KEVDWH3U.js";
171
+ import "./chunk-T3W4SDRB.js";
163
172
  import {
164
173
  EVENT_SCHEMA_VERSION,
165
174
  SubscriberLimitExceededError
166
175
  } from "./chunk-6RLROE6G.js";
167
176
  import "./chunk-COH43MRJ.js";
168
- import "./chunk-OCPBI7J5.js";
169
177
  import {
170
178
  BranchWhilePromptActiveError,
171
179
  CancelSentinelCollisionError,
@@ -186,6 +194,7 @@ import {
186
194
  SessionBusyError,
187
195
  SessionConflictError,
188
196
  SessionLimitExceededError,
197
+ SessionNotArchivedError,
189
198
  SessionNotFoundError,
190
199
  SessionShellClientRequiredError,
191
200
  SessionShellDisabledError,
@@ -196,39 +205,44 @@ import {
196
205
  WorkspaceInitRaceError,
197
206
  WorkspaceInitSymlinkError,
198
207
  WorkspaceMismatchError
199
- } from "./chunk-KSO42X3Z.js";
208
+ } from "./chunk-X6YQWCIJ.js";
200
209
  import "./chunk-WBL3FJEU.js";
201
210
  import {
202
211
  loadChannelsConfig
203
- } from "./chunk-Q5GLXH5Q.js";
204
- import "./chunk-AAR5SGMD.js";
212
+ } from "./chunk-3CL5SEDT.js";
213
+ import "./chunk-IVKLDHU6.js";
205
214
  import "./chunk-57OAHC2Y.js";
206
215
  import {
207
216
  parseChannelWebhookConfigLenient
208
- } from "./chunk-OATTJGPJ.js";
209
- import "./chunk-ZRKBI3DP.js";
217
+ } from "./chunk-Y72B36CP.js";
218
+ import "./chunk-FZRES4GK.js";
210
219
  import "./chunk-V6WHFGST.js";
211
- import "./chunk-UFOKA4PR.js";
212
- import "./chunk-TEGEBB2I.js";
220
+ import "./chunk-O2K6BLPZ.js";
213
221
  import {
214
222
  STATUS_SCHEMA_VERSION,
215
223
  createIdleWorkspaceMemoryStatus,
216
224
  mapDomainErrorToErrorKind
217
- } from "./chunk-CUUXANEQ.js";
225
+ } from "./chunk-URP6O2PP.js";
218
226
  import {
219
227
  MAX_REGISTERED_WORKSPACES,
220
228
  WorkspaceRegistrationStoreCommittedError,
221
229
  WorkspaceRegistrationStoreLimitError,
222
230
  workspaceRegistrationId
223
- } from "./chunk-L37RC7MQ.js";
231
+ } from "./chunk-JUVTV4NF.js";
224
232
  import {
225
233
  MAX_WORKSPACE_PATH_LENGTH,
226
234
  canonicalizeWorkspace,
227
235
  canonicalizeWorkspaces
228
236
  } from "./chunk-W7FJ3N32.js";
229
237
  import {
230
- QWEN_SERVER_TOKEN_ENV
231
- } from "./chunk-GYTKQYDB.js";
238
+ MAX_CHANNEL_STARTUP_FAILURES,
239
+ MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
240
+ MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH,
241
+ MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH,
242
+ QWEN_SERVER_TOKEN_ENV,
243
+ isChannelWebhookEnqueueError,
244
+ normalizeWorkerDiagnostic
245
+ } from "./chunk-JDIUK2Y3.js";
232
246
  import {
233
247
  normalizeServeChannelSelection
234
248
  } from "./chunk-TJTKSVIV.js";
@@ -236,11 +250,10 @@ import {
236
250
  redactLogCredentials
237
251
  } from "./chunk-M5GB774H.js";
238
252
  import "./chunk-5HBA2Z7V.js";
239
- import {
240
- isChannelWebhookEnqueueError
241
- } from "./chunk-OJAMDVF5.js";
242
253
  import "./chunk-T2NCM2ET.js";
243
- import "./chunk-SXU3KKNI.js";
254
+ import {
255
+ sanitizeLogText
256
+ } from "./chunk-ATJ7H5AS.js";
244
257
  import "./chunk-UDXSXLER.js";
245
258
  import {
246
259
  getDialogSettingKeys,
@@ -251,18 +264,18 @@ import {
251
264
  getWritableScopes,
252
265
  loadSettings,
253
266
  validateSettingValue
254
- } from "./chunk-6GETGQWP.js";
267
+ } from "./chunk-C5NSOSF4.js";
255
268
  import "./chunk-RKUWKYED.js";
256
269
  import {
257
270
  SUPPORTED_LANGUAGES
258
- } from "./chunk-RDRVMDWV.js";
259
- import "./chunk-5EBKKSBX.js";
271
+ } from "./chunk-HIMIG6PI.js";
272
+ import "./chunk-336KPNNV.js";
260
273
  import "./chunk-GOXKNSDZ.js";
261
274
  import "./chunk-IDS7MSUP.js";
262
275
  import "./chunk-QRUIS3DN.js";
263
276
  import {
264
277
  getWorkspaceTrustStatus
265
- } from "./chunk-4YWLED2A.js";
278
+ } from "./chunk-LSFVUGXT.js";
266
279
  import "./chunk-ALGGS7UH.js";
267
280
  import {
268
281
  isWithinRoot as isWithinRoot2
@@ -270,7 +283,7 @@ import {
270
283
  import {
271
284
  writeStderrLine
272
285
  } from "./chunk-YUZI3WAC.js";
273
- import "./chunk-YU56QGXX.js";
286
+ import "./chunk-KTKETHMY.js";
274
287
  import "./chunk-VJNBRRZG.js";
275
288
  import {
276
289
  ALL_PROVIDERS,
@@ -284,7 +297,9 @@ import {
284
297
  InvalidSessionTranscriptCursorError,
285
298
  ModelsConfig,
286
299
  RUNTIME_MCP_IF_ABSENT_CONFIG_FLAG,
300
+ SESSION_TRANSCRIPT_MAX_INDEX_BYTES,
287
301
  SESSION_TRANSCRIPT_MAX_LIMIT,
302
+ SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
288
303
  SessionOrganizationError,
289
304
  SessionOrganizationService,
290
305
  SessionService,
@@ -315,18 +330,18 @@ import {
315
330
  stripTerminalControlSequences,
316
331
  watchRepoBranch,
317
332
  writeWorkspaceContextFile
318
- } from "./chunk-K7CRWKOE.js";
333
+ } from "./chunk-3YJZ6WNY.js";
334
+ import "./chunk-T4TZQJ7W.js";
319
335
  import "./chunk-H6XPXXMH.js";
320
336
  import "./chunk-5M6IDOMF.js";
321
337
  import {
322
338
  MAX_JOBS,
323
339
  nextDurableFireMs
324
- } from "./chunk-E67NFMF4.js";
325
- import "./chunk-RCEEXIOO.js";
326
- import "./chunk-KKRTYONM.js";
327
- import "./chunk-TV6K2FB4.js";
340
+ } from "./chunk-LKR7QQ63.js";
341
+ import "./chunk-4XCVGEEX.js";
342
+ import "./chunk-XSPFQQRE.js";
343
+ import "./chunk-4RPARQ5D.js";
328
344
  import "./chunk-E2UVIFI2.js";
329
- import "./chunk-6OATMEYN.js";
330
345
  import {
331
346
  nextFireTime,
332
347
  parseCron
@@ -339,7 +354,7 @@ import {
339
354
  readCronTasks,
340
355
  taskHasLegacyCondition,
341
356
  updateCronTasks
342
- } from "./chunk-SPJQO2CE.js";
357
+ } from "./chunk-J2MKYJKZ.js";
343
358
  import "./chunk-SZRN75WQ.js";
344
359
  import "./chunk-HTO4JFDZ.js";
345
360
  import "./chunk-CPBF7KYF.js";
@@ -347,12 +362,12 @@ import {
347
362
  APPROVAL_MODES,
348
363
  SubagentError,
349
364
  SubagentErrorCode
350
- } from "./chunk-TXY2C3D2.js";
365
+ } from "./chunk-VNN3JNYT.js";
351
366
  import "./chunk-6AM5D4ME.js";
352
- import "./chunk-2Z5UX4KI.js";
353
- import "./chunk-ARKANCNX.js";
354
- import "./chunk-L5U3ELZX.js";
355
- import "./chunk-TYLOFD2U.js";
367
+ import "./chunk-OSSDHJDU.js";
368
+ import "./chunk-SGPFJMRP.js";
369
+ import "./chunk-335ECZTA.js";
370
+ import "./chunk-JCJPZMJV.js";
356
371
  import {
357
372
  addDaemonRequestAttribute,
358
373
  decodeBufferWithEncodingInfo,
@@ -366,15 +381,15 @@ import {
366
381
  recordDaemonHttpRequest,
367
382
  recordDaemonHttpResponse,
368
383
  withDaemonRequestSpan
369
- } from "./chunk-P6LART6G.js";
384
+ } from "./chunk-66IT3EY2.js";
370
385
  import "./chunk-4WKAA4KS.js";
371
386
  import "./chunk-CR3C7WXL.js";
372
- import "./chunk-CARU2RR2.js";
387
+ import "./chunk-U2LNTX56.js";
373
388
  import "./chunk-VGC4I5JJ.js";
374
- import "./chunk-FBU7WRZI.js";
375
- import "./chunk-Y66VOBRP.js";
376
- import "./chunk-WX6SD4IQ.js";
377
- import "./chunk-2UUAIFQO.js";
389
+ import "./chunk-FUTHTZVV.js";
390
+ import "./chunk-4CA4WUMS.js";
391
+ import "./chunk-WEPXQKGP.js";
392
+ import "./chunk-ANRANWVE.js";
378
393
  import {
379
394
  QwenOAuth2Client,
380
395
  QwenOAuthPollError,
@@ -383,28 +398,28 @@ import {
383
398
  isDeviceAuthorizationSuccess,
384
399
  isDeviceTokenPending,
385
400
  isDeviceTokenSuccess
386
- } from "./chunk-OKAIGAYW.js";
387
- import "./chunk-ZPAHLFZU.js";
401
+ } from "./chunk-G274ETR6.js";
402
+ import "./chunk-Z2LBNX3R.js";
388
403
  import "./chunk-JESCGQM3.js";
389
- import "./chunk-WIEO4CWB.js";
404
+ import "./chunk-VAJS2E2D.js";
390
405
  import "./chunk-XVNQMZ2I.js";
391
- import "./chunk-B7NUUEXC.js";
392
- import "./chunk-TQBODCFD.js";
406
+ import "./chunk-FEOZBUMT.js";
407
+ import "./chunk-CMVFTMRD.js";
393
408
  import "./chunk-A4UCTEB5.js";
394
409
  import "./chunk-XWRJCPHC.js";
395
- import "./chunk-4LD5APFL.js";
410
+ import "./chunk-TYQMGACW.js";
396
411
  import {
397
412
  import_websocket_server
398
413
  } from "./chunk-TYAMGABM.js";
399
414
  import "./chunk-FCMNKVXT.js";
400
415
  import "./chunk-DJ2GSRLV.js";
401
- import "./chunk-LQIDP6K5.js";
416
+ import "./chunk-4CHDYDG3.js";
402
417
  import {
403
418
  FatalConfigError,
404
419
  Storage,
405
420
  createDebugLogger,
406
421
  runWithoutDebugLogSession
407
- } from "./chunk-7NFB7LBQ.js";
422
+ } from "./chunk-UE5TZ55T.js";
408
423
  import "./chunk-75DOP5OR.js";
409
424
  import "./chunk-DMTGGOSA.js";
410
425
  import "./chunk-YQ3U5MUC.js";
@@ -2900,7 +2915,7 @@ async function handleSetupGithub(req, res, deps) {
2900
2915
  const result = await setupGithub({
2901
2916
  cwd: deps.boundWorkspace,
2902
2917
  workspaceRoot: deps.boundWorkspace,
2903
- proxy: resolveSetupGithubProxy(deps.boundWorkspace),
2918
+ proxy: resolveSetupGithubProxy(deps.boundWorkspace, deps.env),
2904
2919
  abortSignal: requestAbortSignal(req, res),
2905
2920
  fileOps: createSetupGithubFileOps(factory, ROUTE, originatorClientId)
2906
2921
  });
@@ -3118,14 +3133,14 @@ function setupGithubEventData(result) {
3118
3133
  };
3119
3134
  }
3120
3135
  __name(setupGithubEventData, "setupGithubEventData");
3121
- function resolveSetupGithubProxy(boundWorkspace) {
3136
+ function resolveSetupGithubProxy(boundWorkspace, env) {
3122
3137
  const settings = loadSettings(boundWorkspace, { skipLoadEnvironment: true });
3123
3138
  const trustState = getWorkspaceTrustStatus(
3124
3139
  settingsForSetupGithubTrust(settings),
3125
3140
  boundWorkspace
3126
3141
  ).effective.state;
3127
3142
  const settingsProxy = trustState === "trusted" ? settings.merged.proxy : settings.user.settings.proxy || settings.system.settings.proxy || settings.systemDefaults.settings.proxy;
3128
- return settingsProxy || process.env["HTTPS_PROXY"] || process.env["https_proxy"] || process.env["HTTP_PROXY"] || process.env["http_proxy"];
3143
+ return settingsProxy || env["HTTPS_PROXY"] || env["https_proxy"] || env["HTTP_PROXY"] || env["http_proxy"];
3129
3144
  }
3130
3145
  __name(resolveSetupGithubProxy, "resolveSetupGithubProxy");
3131
3146
  function settingsForSetupGithubTrust(settings) {
@@ -6226,6 +6241,21 @@ async function assertSessionLoadable(workspaceCwd, sessionId) {
6226
6241
  return location;
6227
6242
  }
6228
6243
  __name(assertSessionLoadable, "assertSessionLoadable");
6244
+ async function assertSessionArchived(workspaceCwd, sessionId) {
6245
+ const location = await new SessionService(workspaceCwd).getSessionLocation(
6246
+ sessionId
6247
+ );
6248
+ if (location === "active") {
6249
+ throw new SessionNotArchivedError(sessionId);
6250
+ }
6251
+ if (location === "conflict") {
6252
+ throw new SessionConflictError(sessionId);
6253
+ }
6254
+ if (location === void 0) {
6255
+ throw new SessionNotFoundError(sessionId);
6256
+ }
6257
+ }
6258
+ __name(assertSessionArchived, "assertSessionArchived");
6229
6259
  function isSessionNotFoundError(err) {
6230
6260
  return err instanceof SessionNotFoundError || err instanceof Error && err.name === "SessionNotFoundError";
6231
6261
  }
@@ -6928,9 +6958,10 @@ function rpcErrorFrame(id, err) {
6928
6958
  __name(rpcErrorFrame, "rpcErrorFrame");
6929
6959
  var ACP_PROTOCOL_VERSION = 1;
6930
6960
  var AcpDispatcher = class {
6931
- constructor(bridge, boundWorkspace, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator()) {
6961
+ constructor(bridge, boundWorkspace, env, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator()) {
6932
6962
  this.bridge = bridge;
6933
6963
  this.boundWorkspace = boundWorkspace;
6964
+ this.env = env;
6934
6965
  this.workspace = workspace;
6935
6966
  this.workspaceRememberLane = workspaceRememberLane;
6936
6967
  this.fsFactory = fsFactory;
@@ -6944,8 +6975,14 @@ var AcpDispatcher = class {
6944
6975
  __name(this, "AcpDispatcher");
6945
6976
  }
6946
6977
  agentManager;
6947
- killOrphanSession(sessionId) {
6948
- void this.bridge.killSession(sessionId, { requireZeroAttaches: true }).catch(
6978
+ killOrphanSession(sessionId, removePersistedSession = false) {
6979
+ void this.bridge.killSession(sessionId, { requireZeroAttaches: true }).then(async (killed) => {
6980
+ if (killed && removePersistedSession) {
6981
+ await new SessionService(this.boundWorkspace).removeSession(
6982
+ sessionId
6983
+ );
6984
+ }
6985
+ }).catch(
6949
6986
  (err) => writeStderrLine(
6950
6987
  `qwen serve: /acp orphan killSession(${logSafe(sessionId)}) failed: ${logSafe(errMsg(err))}`
6951
6988
  )
@@ -7229,26 +7266,40 @@ var AcpDispatcher = class {
7229
7266
  return;
7230
7267
  case "session/new": {
7231
7268
  const cwd = parseOptionalWorkspaceCwd2(params, this.boundWorkspace);
7269
+ const source = parseSessionSource(
7270
+ params["sourceType"],
7271
+ params["sourceId"]
7272
+ );
7273
+ if ("error" in source) {
7274
+ if (id !== void 0) {
7275
+ conn.sendConn(error(id, RPC.INVALID_PARAMS, source.error));
7276
+ }
7277
+ return;
7278
+ }
7232
7279
  const session = await this.bridge.spawnOrAttach({
7233
7280
  workspaceCwd: cwd,
7234
7281
  clientId: conn.clientId,
7235
- sessionScope: "thread"
7282
+ sessionScope: "thread",
7283
+ ...source
7236
7284
  });
7237
7285
  if (conn.destroyed) {
7238
- this.killOrphanSession(session.sessionId);
7286
+ this.killOrphanSession(session.sessionId, true);
7239
7287
  return;
7240
7288
  }
7241
7289
  conn.getOrCreateSession(session.sessionId).clientId = session.clientId;
7242
7290
  conn.ownSession(session.sessionId);
7243
7291
  const configOptions = await this.configOptionsFor(session.sessionId);
7244
7292
  if (conn.destroyed) {
7245
- this.killOrphanSession(session.sessionId);
7293
+ this.killOrphanSession(session.sessionId, true);
7246
7294
  return;
7247
7295
  }
7248
7296
  const models = this.extractModelState(configOptions);
7249
7297
  const modes = this.extractModeState(configOptions);
7250
7298
  this.replyConn(conn, id, {
7251
7299
  sessionId: session.sessionId,
7300
+ ...session.sourceType ? { sourceType: session.sourceType } : {},
7301
+ ...session.sourceId !== void 0 ? { sourceId: session.sourceId } : {},
7302
+ ...session.sourcePersisted !== void 0 ? { sourcePersisted: session.sourcePersisted } : {},
7252
7303
  ...configOptions ? { configOptions } : {},
7253
7304
  ...models ? { models } : {},
7254
7305
  ...modes ? { modes } : {}
@@ -7283,20 +7334,20 @@ var AcpDispatcher = class {
7283
7334
  [sessionId],
7284
7335
  async () => {
7285
7336
  await assertSessionLoadable(cwd, sessionId);
7286
- const parentSessionId = await new SessionService(
7337
+ const metadata = await new SessionService(
7287
7338
  cwd
7288
- ).readParentSessionId(sessionId);
7339
+ ).readCreationMetadata(sessionId);
7289
7340
  return method === "session/load" ? await this.bridge.loadSession({
7290
7341
  sessionId,
7291
7342
  workspaceCwd: cwd,
7292
7343
  clientId: conn.clientId,
7293
7344
  historyReplay: "response",
7294
- ...parentSessionId !== void 0 ? { parentSessionId } : {}
7345
+ ...metadata
7295
7346
  }) : await this.bridge.resumeSession({
7296
7347
  sessionId,
7297
7348
  workspaceCwd: cwd,
7298
7349
  clientId: conn.clientId,
7299
- ...parentSessionId !== void 0 ? { parentSessionId } : {}
7350
+ ...metadata
7300
7351
  });
7301
7352
  }
7302
7353
  );
@@ -7395,6 +7446,13 @@ var AcpDispatcher = class {
7395
7446
  );
7396
7447
  }
7397
7448
  }
7449
+ const parsedSource = parseSessionSource(
7450
+ params["sourceType"],
7451
+ params["sourceId"]
7452
+ );
7453
+ if ("error" in parsedSource) {
7454
+ throw new AcpParamError(parsedSource.error);
7455
+ }
7398
7456
  const result = await listWorkspaceSessionsForResponse(
7399
7457
  this.bridge,
7400
7458
  workspaceCwd,
@@ -7404,7 +7462,8 @@ var AcpDispatcher = class {
7404
7462
  archiveState,
7405
7463
  view,
7406
7464
  group,
7407
- parentSessionId
7465
+ parentSessionId,
7466
+ ...parsedSource
7408
7467
  }
7409
7468
  );
7410
7469
  this.replyConn(conn, id, {
@@ -7417,6 +7476,8 @@ var AcpDispatcher = class {
7417
7476
  displayName: s.displayName,
7418
7477
  title: s.displayName,
7419
7478
  ...s.parentSessionId !== void 0 ? { parentSessionId: s.parentSessionId } : {},
7479
+ ...s.sourceType !== void 0 ? { sourceType: s.sourceType } : {},
7480
+ ...s.sourceId !== void 0 ? { sourceId: s.sourceId } : {},
7420
7481
  clientCount: s.clientCount,
7421
7482
  hasActivePrompt: s.hasActivePrompt,
7422
7483
  isArchived: s.isArchived === true,
@@ -8277,7 +8338,7 @@ var AcpDispatcher = class {
8277
8338
  const result = await setupGithub({
8278
8339
  cwd: this.boundWorkspace,
8279
8340
  workspaceRoot: this.boundWorkspace,
8280
- proxy: resolveSetupGithubProxy(this.boundWorkspace),
8341
+ proxy: resolveSetupGithubProxy(this.boundWorkspace, this.env),
8281
8342
  abortSignal: conn.abortSignal,
8282
8343
  fileOps: createSetupGithubFileOps(
8283
8344
  this.fsFactory,
@@ -11748,11 +11809,11 @@ function delay(ms) {
11748
11809
  return new Promise((resolve5) => setTimeout(resolve5, ms));
11749
11810
  }
11750
11811
  __name(delay, "delay");
11751
- function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname) {
11812
+ function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname, env) {
11752
11813
  if (localPort === void 0 || !Number.isInteger(localPort) || localPort <= 0) {
11753
11814
  return void 0;
11754
11815
  }
11755
- const command = resolveCdpMcpCommand(process.env);
11816
+ const command = resolveCdpMcpCommand(env);
11756
11817
  if (!command) {
11757
11818
  writeStderrLine(
11758
11819
  `qwen serve: set ${QWEN_CDP_MCP_COMMAND_ENV} to enable browser automation MCP (no adapter is bundled)`
@@ -11858,9 +11919,18 @@ function workspaceRateLimitKey(mount, clientKey) {
11858
11919
  return JSON.stringify([clientKey, mount.rateLimitScope]);
11859
11920
  }
11860
11921
  __name(workspaceRateLimitKey, "workspaceRateLimitKey");
11922
+ function runtimeEffectiveEnv(runtime, daemonEnv) {
11923
+ if (runtime.env.mode === "runtime-overlay") {
11924
+ return runtime.env.effectiveEnv ?? {};
11925
+ }
11926
+ return runtime.env.effectiveEnv ?? daemonEnv;
11927
+ }
11928
+ __name(runtimeEffectiveEnv, "runtimeEffectiveEnv");
11861
11929
  function mountAcpHttp(app, bridge, opts) {
11862
11930
  const enabled = opts.enabled ?? resolveAcpHttpEnabled();
11863
11931
  if (!enabled) return void 0;
11932
+ const daemonEnv = opts.daemonEnv ?? process.env;
11933
+ const primaryEnv = opts.workspaceRegistry ? runtimeEffectiveEnv(opts.workspaceRegistry.primary, daemonEnv) : daemonEnv;
11864
11934
  const path15 = opts.path ?? "/acp";
11865
11935
  const dispatcherRef = {};
11866
11936
  let disposed = false;
@@ -11950,7 +12020,8 @@ function mountAcpHttp(app, bridge, opts) {
11950
12020
  }
11951
12021
  const runtimeConfig = buildChromeDevToolsMcpRuntimeConfig(
11952
12022
  localPort,
11953
- opts.hostname
12023
+ opts.hostname,
12024
+ daemonEnv
11954
12025
  );
11955
12026
  if (!runtimeConfig) {
11956
12027
  cdpMcpTerminalSkipLogged = true;
@@ -12009,6 +12080,7 @@ function mountAcpHttp(app, bridge, opts) {
12009
12080
  const dispatcher = new AcpDispatcher(
12010
12081
  bridge,
12011
12082
  opts.boundWorkspace,
12083
+ primaryEnv,
12012
12084
  opts.workspace,
12013
12085
  opts.workspaceRememberLane,
12014
12086
  opts.fsFactory,
@@ -12297,6 +12369,7 @@ function mountAcpHttp(app, bridge, opts) {
12297
12369
  const secondaryDispatcher = new AcpDispatcher(
12298
12370
  rt.bridge,
12299
12371
  rt.workspaceCwd,
12372
+ runtimeEffectiveEnv(rt, daemonEnv),
12300
12373
  rt.workspaceService,
12301
12374
  workspaceRememberLane,
12302
12375
  rt.routeFileSystemFactory,
@@ -14402,7 +14475,13 @@ __name(getDemoHtml, "getDemoHtml");
14402
14475
 
14403
14476
  // packages/cli/src/serve/routes/health-demo.ts
14404
14477
  function createHealthDemoRoutes(deps) {
14405
- const { opts, getPort, bridge, getActiveSseCount: getActiveSseCount2, getRateLimiter } = deps;
14478
+ const {
14479
+ opts,
14480
+ getPort,
14481
+ workspaceRegistry,
14482
+ getActiveSseCount: getActiveSseCount2,
14483
+ getRateLimiter
14484
+ } = deps;
14406
14485
  const demoHandler = /* @__PURE__ */ __name((_req, res) => {
14407
14486
  try {
14408
14487
  res.type("html").set("X-Frame-Options", "DENY").set(
@@ -14417,32 +14496,55 @@ function createHealthDemoRoutes(deps) {
14417
14496
  }
14418
14497
  }, "demoHandler");
14419
14498
  const healthHandler = /* @__PURE__ */ __name((req, res) => {
14420
- const deepQuery = req.query["deep"];
14421
- const deep = deepQuery === "1" || deepQuery === "true" || deepQuery === "";
14422
- if (!deep) {
14499
+ if (!isDeepHealthQuery(req.query["deep"])) {
14423
14500
  res.status(200).json({ status: "ok" });
14424
14501
  return;
14425
14502
  }
14503
+ let failedWorkspaceId;
14426
14504
  try {
14427
- const lastActivity = bridge.lastActivityAt;
14505
+ const runtimes = workspaceRegistry.listManaged();
14506
+ let sessions = 0;
14507
+ let pendingPermissions = 0;
14508
+ let activePrompts = 0;
14509
+ let channelAlive = false;
14510
+ let lastActivity = null;
14511
+ for (const runtime of runtimes) {
14512
+ failedWorkspaceId = runtime.workspaceId;
14513
+ const bridge = runtime.bridge;
14514
+ const runtimeSessions = bridge.sessionCount;
14515
+ const runtimePendingPermissions = bridge.pendingPermissionCount;
14516
+ const runtimeActivePrompts = bridge.activePromptCount;
14517
+ const runtimeChannelAlive = bridge.isChannelLive();
14518
+ const runtimeLastActivity = bridge.lastActivityAt;
14519
+ sessions += runtimeSessions;
14520
+ pendingPermissions += runtimePendingPermissions;
14521
+ activePrompts += runtimeActivePrompts;
14522
+ channelAlive = channelAlive || runtimeChannelAlive;
14523
+ if (runtimeLastActivity !== null && (lastActivity === null || runtimeLastActivity > lastActivity)) {
14524
+ lastActivity = runtimeLastActivity;
14525
+ }
14526
+ failedWorkspaceId = void 0;
14527
+ }
14428
14528
  const now = Date.now();
14429
14529
  const rateLimiter = getRateLimiter();
14430
14530
  res.status(200).json({
14431
14531
  status: "ok",
14432
- sessions: bridge.sessionCount,
14433
- pendingPermissions: bridge.pendingPermissionCount,
14434
- activePrompts: bridge.activePromptCount,
14532
+ workspaceCount: runtimes.length,
14533
+ sessions,
14534
+ pendingPermissions,
14535
+ activePrompts,
14435
14536
  connectedClients: getActiveSseCount2(),
14436
- channelAlive: bridge.isChannelLive(),
14537
+ channelAlive,
14437
14538
  lastActivityAt: lastActivity !== null ? new Date(lastActivity).toISOString() : null,
14438
14539
  idleSinceMs: lastActivity !== null ? now - lastActivity : null,
14439
14540
  ...rateLimiter ? { rateLimitHits: rateLimiter.getHitCounts() } : {}
14440
14541
  });
14441
14542
  } catch (err) {
14543
+ const workspaceContext = failedWorkspaceId !== void 0 ? ` for workspace ${JSON.stringify(failedWorkspaceId)}` : "";
14442
14544
  writeStderrLine(
14443
- `qwen serve: /health deep probe failed: ${err instanceof Error ? err.message : String(err)}`
14545
+ `qwen serve: /health deep probe failed${workspaceContext}: ${err instanceof Error ? err.message : String(err)}`
14444
14546
  );
14445
- res.status(503).json({ status: "degraded" });
14547
+ res.status(503).json({ status: "degraded", reason: "aggregation_failed" });
14446
14548
  }
14447
14549
  }, "healthHandler");
14448
14550
  const loopback = isLoopbackBind(opts.hostname);
@@ -14950,6 +15052,7 @@ __name(registerWorkspaceAuthRoutes, "registerWorkspaceAuthRoutes");
14950
15052
 
14951
15053
  // packages/cli/src/serve/routes/workspace-extensions.ts
14952
15054
  init_esbuild_shims();
15055
+ import * as crypto2 from "node:crypto";
14953
15056
 
14954
15057
  // packages/cli/src/serve/extension-operation-scheduler.ts
14955
15058
  init_esbuild_shims();
@@ -15029,6 +15132,18 @@ init_esbuild_shims();
15029
15132
  import * as crypto from "node:crypto";
15030
15133
  var MAX_UNFINISHED_EXTENSION_OPERATIONS = 10;
15031
15134
  var sanitizeDaemonMessage = /* @__PURE__ */ __name((message) => redactUrlCredentials(stripAnsiAndControl(message)), "sanitizeDaemonMessage");
15135
+ var redactExtensionDisplaySource = /* @__PURE__ */ __name((source) => {
15136
+ const redacted = redactUrlCredentials(source);
15137
+ if (/^[A-Za-z]:[\\/]/.test(redacted)) return redacted;
15138
+ try {
15139
+ const url = new URL(redacted);
15140
+ url.search = "";
15141
+ url.hash = "";
15142
+ return url.toString();
15143
+ } catch {
15144
+ return redacted;
15145
+ }
15146
+ }, "redactExtensionDisplaySource");
15032
15147
  var EXTENSION_PREPARATION_CONCURRENCY = 2;
15033
15148
  var EXTENSION_REFRESH_TIMEOUT_MS = 3e4;
15034
15149
  var RECONCILE_SLOW_MS = 3e4;
@@ -15057,21 +15172,21 @@ function createExtensionsController(deps) {
15057
15172
  unfinishedOperationCount -= 1;
15058
15173
  };
15059
15174
  }, "acquireOperationSlot");
15060
- const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride) => new ExtensionManager({
15175
+ const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride, interactions) => new ExtensionManager({
15061
15176
  workspaceDir,
15062
15177
  isWorkspaceTrusted: trustedOverride ?? getWorkspaceTrustStatus(loadSettings(workspaceDir).merged, workspaceDir).effective.state === "trusted",
15063
15178
  requestConsent: /* @__PURE__ */ __name(() => Promise.resolve(), "requestConsent"),
15064
15179
  networkPolicy: "public",
15065
- requestSetting: /* @__PURE__ */ __name(async (setting) => {
15180
+ requestSetting: interactions?.requestSetting ?? (async (setting) => {
15066
15181
  throw new Error(
15067
15182
  `Extension setting "${setting.envVar}" requires interactive configuration and is not supported over the daemon install endpoint.`
15068
15183
  );
15069
- }, "requestSetting"),
15070
- requestChoicePlugin: /* @__PURE__ */ __name(async () => {
15184
+ }),
15185
+ requestChoicePlugin: interactions?.requestChoicePlugin ?? (async () => {
15071
15186
  throw new Error(
15072
15187
  "Marketplace plugin selection is not supported over the daemon install endpoint. Specify a plugin name in the source."
15073
15188
  );
15074
- }, "requestChoicePlugin")
15189
+ })
15075
15190
  }), "createExtensionManager");
15076
15191
  const validateExtensionMutationClient = /* @__PURE__ */ __name((req, res, opts = {}) => {
15077
15192
  const clientId = parseAndValidateWorkspaceClientId(
@@ -15090,10 +15205,10 @@ function createExtensionsController(deps) {
15090
15205
  return true;
15091
15206
  }, "validateExtensionMutationClient");
15092
15207
  const extensionOperations = /* @__PURE__ */ new Map();
15093
- const isTerminalExtensionOperation = /* @__PURE__ */ __name((operation) => operation.status !== "queued" && operation.status !== "running", "isTerminalExtensionOperation");
15208
+ const isTerminalExtensionOperation = /* @__PURE__ */ __name((operation) => operation.status !== "queued" && operation.status !== "running" && operation.status !== "waiting_for_input", "isTerminalExtensionOperation");
15094
15209
  const redactExtensionOperationResult = /* @__PURE__ */ __name((event) => ({
15095
15210
  ...event,
15096
- ...event.source ? { source: redactUrlCredentials(event.source) } : {}
15211
+ ...event.source ? { source: redactExtensionDisplaySource(event.source) } : {}
15097
15212
  }), "redactExtensionOperationResult");
15098
15213
  const bridgeMutationEvent = /* @__PURE__ */ __name((event) => {
15099
15214
  const redacted = redactExtensionOperationResult(event);
@@ -15174,7 +15289,7 @@ function createExtensionsController(deps) {
15174
15289
  status: "queued",
15175
15290
  createdAt: now,
15176
15291
  updatedAt: now,
15177
- ...failureContext.source ? { source: redactUrlCredentials(failureContext.source) } : {},
15292
+ ...failureContext.source ? { source: redactExtensionDisplaySource(failureContext.source) } : {},
15178
15293
  ...failureContext.name ? { name: failureContext.name } : {}
15179
15294
  });
15180
15295
  const operationBasePath = options.operationBasePath ?? "/workspace/extensions/operations";
@@ -15201,7 +15316,7 @@ function createExtensionsController(deps) {
15201
15316
  status: "running",
15202
15317
  phase: "preparing"
15203
15318
  });
15204
- const extensionManager = options.manager ?? createExtensionManager();
15319
+ const extensionManager = options.manager ?? options.createManager?.(operationId) ?? createExtensionManager();
15205
15320
  const deadlineController = new AbortController();
15206
15321
  let deadlineStarted = false;
15207
15322
  const startDeadline = /* @__PURE__ */ __name(() => {
@@ -15302,7 +15417,8 @@ function createExtensionsController(deps) {
15302
15417
  const event = await run(
15303
15418
  extensionManager,
15304
15419
  deadlineController.signal,
15305
- context
15420
+ context,
15421
+ operationId
15306
15422
  );
15307
15423
  mutationEvent = event;
15308
15424
  if (deadline) clearTimeout(deadline);
@@ -15527,7 +15643,9 @@ function createExtensionsController(deps) {
15527
15643
  bridge.broadcastExtensionsChanged({
15528
15644
  ...mutationEvent ? bridgeMutationEvent(mutationEvent) : {
15529
15645
  ...failureContext.source ? {
15530
- source: redactUrlCredentials(failureContext.source)
15646
+ source: redactExtensionDisplaySource(
15647
+ failureContext.source
15648
+ )
15531
15649
  } : {},
15532
15650
  ...failureContext.name ? { name: failureContext.name } : {}
15533
15651
  },
@@ -15548,13 +15666,14 @@ function createExtensionsController(deps) {
15548
15666
  updateExtensionOperation(operationId, {
15549
15667
  status: "failed",
15550
15668
  phase: void 0,
15669
+ interaction: void 0,
15551
15670
  error: message.slice(0, 500),
15552
15671
  ...code ? { code } : {}
15553
15672
  });
15554
15673
  try {
15555
15674
  bridge.broadcastExtensionsChanged({
15556
15675
  status: "failed",
15557
- ...failureContext.source ? { source: redactUrlCredentials(failureContext.source) } : {},
15676
+ ...failureContext.source ? { source: redactExtensionDisplaySource(failureContext.source) } : {},
15558
15677
  ...failureContext.name ? { name: failureContext.name } : {},
15559
15678
  refreshed: 0,
15560
15679
  failed: 0,
@@ -15576,6 +15695,7 @@ function createExtensionsController(deps) {
15576
15695
  } finally {
15577
15696
  if (deadline) clearTimeout(deadline);
15578
15697
  reconciliationReservation?.release();
15698
+ options.onSettled?.(operationId);
15579
15699
  releaseOperationSlot();
15580
15700
  }
15581
15701
  })();
@@ -15610,7 +15730,11 @@ function createExtensionsController(deps) {
15610
15730
  version: ext.version,
15611
15731
  isActive: ext.isActive,
15612
15732
  path: ext.path,
15613
- ...ext.installMetadata?.source ? { source: redactUrlCredentials(ext.installMetadata.source) } : {},
15733
+ ...ext.installMetadata?.source ? {
15734
+ source: redactExtensionDisplaySource(
15735
+ ext.installMetadata.source
15736
+ )
15737
+ } : {},
15614
15738
  ...ext.installMetadata?.type ? { installType: ext.installMetadata.type } : {},
15615
15739
  ...ext.installMetadata?.originSource ? { originSource: ext.installMetadata.originSource } : {},
15616
15740
  ...ext.installMetadata?.ref ? { ref: ext.installMetadata.ref } : {},
@@ -15646,6 +15770,10 @@ function createExtensionsController(deps) {
15646
15770
  buildLocalExtensionsStatus,
15647
15771
  refreshExtensionsForAllSessions,
15648
15772
  getOperation: /* @__PURE__ */ __name((operationId) => extensionOperations.get(operationId), "getOperation"),
15773
+ getActiveOperations: /* @__PURE__ */ __name(() => [...extensionOperations.values()].filter(
15774
+ (operation) => !isTerminalExtensionOperation(operation)
15775
+ ), "getActiveOperations"),
15776
+ updateOperation: updateExtensionOperation,
15649
15777
  preparationQueue,
15650
15778
  acquireOperationSlot,
15651
15779
  validateExtensionMutationClient,
@@ -15656,6 +15784,8 @@ __name(createExtensionsController, "createExtensionsController");
15656
15784
 
15657
15785
  // packages/cli/src/serve/routes/workspace-extensions.ts
15658
15786
  var EXTENSION_PREPARE_DEADLINE_MS = 10 * 6e4;
15787
+ var EXTENSION_INTERACTION_DEADLINE_MS = 10 * 6e4;
15788
+ var EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS = EXTENSION_PREPARE_DEADLINE_MS + EXTENSION_INTERACTION_DEADLINE_MS;
15659
15789
  var EXTENSION_UPDATE_CHECK_DEADLINE_MS = 2 * 6e4;
15660
15790
  var parseExtensionScope = /* @__PURE__ */ __name((body, res) => {
15661
15791
  const scope = body["scope"];
@@ -15761,6 +15891,96 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15761
15891
  const primaryController = createExtensionsController(
15762
15892
  controllerDeps(boundWorkspace, bridge, workspace)
15763
15893
  );
15894
+ const pendingExtensionInteractions = /* @__PURE__ */ new Map();
15895
+ const supersededInstallOperations = /* @__PURE__ */ new Set();
15896
+ const cancelPendingExtensionInteraction = /* @__PURE__ */ __name((operationId, reason) => {
15897
+ const pending = pendingExtensionInteractions.get(operationId);
15898
+ if (!pending) return;
15899
+ clearTimeout(pending.timeout);
15900
+ pendingExtensionInteractions.delete(operationId);
15901
+ pending.reject(new Error(reason));
15902
+ }, "cancelPendingExtensionInteraction");
15903
+ const supersedeActiveInstallOperations = /* @__PURE__ */ __name((controller, currentOperationId) => {
15904
+ for (const operation of controller.getActiveOperations()) {
15905
+ if (operation.operation !== "install" || operation.operationId === currentOperationId) {
15906
+ continue;
15907
+ }
15908
+ supersededInstallOperations.add(operation.operationId);
15909
+ cancelPendingExtensionInteraction(
15910
+ operation.operationId,
15911
+ "Extension installation cancelled by a new install request"
15912
+ );
15913
+ }
15914
+ }, "supersedeActiveInstallOperations");
15915
+ const waitForExtensionInteraction = /* @__PURE__ */ __name((controller, operationId, interaction) => {
15916
+ if (supersededInstallOperations.delete(operationId)) {
15917
+ return Promise.reject(
15918
+ new Error("Extension installation superseded by a new install request")
15919
+ );
15920
+ }
15921
+ const operation = controller.getOperation(operationId);
15922
+ if (operation && operation.status !== "queued" && operation.status !== "running" && operation.status !== "waiting_for_input") {
15923
+ return Promise.reject(new Error("Extension operation already completed"));
15924
+ }
15925
+ const pendingInteraction = {
15926
+ ...interaction,
15927
+ id: crypto2.randomUUID()
15928
+ };
15929
+ return new Promise((resolve5, reject) => {
15930
+ const timeout = setTimeout(() => {
15931
+ pendingExtensionInteractions.delete(operationId);
15932
+ controller.updateOperation(operationId, {
15933
+ status: "failed",
15934
+ phase: void 0,
15935
+ interaction: void 0,
15936
+ error: "Extension interaction timed out"
15937
+ });
15938
+ reject(new Error("Extension interaction timed out"));
15939
+ }, EXTENSION_INTERACTION_DEADLINE_MS);
15940
+ timeout.unref?.();
15941
+ pendingExtensionInteractions.set(operationId, {
15942
+ interaction: pendingInteraction,
15943
+ resolve: resolve5,
15944
+ reject,
15945
+ timeout
15946
+ });
15947
+ controller.updateOperation(operationId, {
15948
+ status: "waiting_for_input",
15949
+ phase: void 0,
15950
+ interaction: pendingInteraction
15951
+ });
15952
+ });
15953
+ }, "waitForExtensionInteraction");
15954
+ const extensionInteractionHandlers = /* @__PURE__ */ __name((controller, operationId) => ({
15955
+ requestSetting: /* @__PURE__ */ __name((setting) => waitForExtensionInteraction(controller, operationId, {
15956
+ kind: "setting",
15957
+ setting: {
15958
+ name: setting.name,
15959
+ description: setting.description,
15960
+ sensitive: setting.sensitive === true
15961
+ }
15962
+ }), "requestSetting"),
15963
+ requestChoicePlugin: /* @__PURE__ */ __name((marketplace) => {
15964
+ if (marketplace.plugins.length === 0) {
15965
+ return Promise.reject(
15966
+ new Error(`Marketplace "${marketplace.name}" has no plugins`)
15967
+ );
15968
+ }
15969
+ return waitForExtensionInteraction(controller, operationId, {
15970
+ kind: "marketplace_plugin",
15971
+ marketplace: { name: marketplace.name },
15972
+ plugins: marketplace.plugins.map((plugin) => ({
15973
+ name: plugin.name,
15974
+ ...plugin.description ? { description: plugin.description } : {},
15975
+ source: redactExtensionDisplaySource(
15976
+ typeof plugin.source === "string" ? plugin.source : plugin.source.source === "github" ? plugin.source.repo : plugin.source.url
15977
+ ),
15978
+ ...plugin.category ? { category: plugin.category } : {},
15979
+ ...plugin.tags ? { tags: plugin.tags } : {}
15980
+ }))
15981
+ });
15982
+ }, "requestChoicePlugin")
15983
+ }), "extensionInteractionHandlers");
15764
15984
  const runtimeReconciliationQueue = createFifoTaskQueue(1);
15765
15985
  const reserveRuntimeReconciliation = /* @__PURE__ */ __name(() => {
15766
15986
  let provideTask;
@@ -15877,6 +16097,11 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15877
16097
  sendBridgeError2(res, err, { route: `GET ${base}` });
15878
16098
  }
15879
16099
  });
16100
+ app.get(`${base}/operations`, async (req, res) => {
16101
+ const ctrl = resolve5(req, res, false);
16102
+ if (!ctrl) return;
16103
+ res.status(200).json({ v: 1, operations: ctrl.getActiveOperations() });
16104
+ });
15880
16105
  app.get(`${base}/operations/:operationId`, async (req, res) => {
15881
16106
  const ctrl = resolve5(req, res, false);
15882
16107
  if (!ctrl) return;
@@ -15918,11 +16143,85 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15918
16143
  });
15919
16144
  }
15920
16145
  });
16146
+ app.post(
16147
+ `${base}/operations/:operationId/interactions/:interactionId`,
16148
+ mutate({ strict: true }),
16149
+ async (req, res) => {
16150
+ const ctrl = resolve5(req, res, false);
16151
+ if (!ctrl) return;
16152
+ try {
16153
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16154
+ requireClientId: false
16155
+ })) {
16156
+ return;
16157
+ }
16158
+ const operationId = req.params["operationId"];
16159
+ const interactionId = req.params["interactionId"];
16160
+ const pending = operationId ? pendingExtensionInteractions.get(operationId) : void 0;
16161
+ if (!operationId || !interactionId || !pending) {
16162
+ res.status(404).json({ error: "Extension interaction not found" });
16163
+ return;
16164
+ }
16165
+ if (pending.interaction.id !== interactionId) {
16166
+ res.status(404).json({ error: "Extension interaction not found" });
16167
+ return;
16168
+ }
16169
+ const body = safeBody2(req);
16170
+ let value;
16171
+ if (body["cancelled"] === true) {
16172
+ clearTimeout(pending.timeout);
16173
+ pendingExtensionInteractions.delete(operationId);
16174
+ ctrl.updateOperation(operationId, {
16175
+ status: "failed",
16176
+ phase: void 0,
16177
+ interaction: void 0,
16178
+ error: "Extension operation cancelled"
16179
+ });
16180
+ pending.reject(new Error("Extension operation cancelled"));
16181
+ res.status(200).json({ accepted: true });
16182
+ return;
16183
+ }
16184
+ if (pending.interaction.kind === "marketplace_plugin") {
16185
+ const pluginName = body["pluginName"];
16186
+ if (typeof pluginName !== "string" || !pending.interaction.plugins.some(
16187
+ (plugin) => plugin.name === pluginName
16188
+ )) {
16189
+ res.status(400).json({ error: "Invalid marketplace plugin name" });
16190
+ return;
16191
+ }
16192
+ value = pluginName;
16193
+ } else {
16194
+ const settingValue = body["value"];
16195
+ if (typeof settingValue !== "string") {
16196
+ res.status(400).json({ error: "Extension setting value must be a string" });
16197
+ return;
16198
+ }
16199
+ value = settingValue;
16200
+ }
16201
+ clearTimeout(pending.timeout);
16202
+ pendingExtensionInteractions.delete(operationId);
16203
+ ctrl.updateOperation(operationId, {
16204
+ status: "running",
16205
+ phase: "preparing",
16206
+ interaction: void 0,
16207
+ error: void 0
16208
+ });
16209
+ pending.resolve(value);
16210
+ res.status(200).json({ accepted: true });
16211
+ } catch (err) {
16212
+ sendBridgeError2(res, err, {
16213
+ route: `POST ${base}/operations/:operationId/interactions/:interactionId`
16214
+ });
16215
+ }
16216
+ }
16217
+ );
15921
16218
  app.post(`${base}/install`, mutate({ strict: true }), async (req, res) => {
15922
16219
  const ctrl = resolve5(req, res, true);
15923
16220
  if (!ctrl) return;
15924
16221
  try {
15925
- if (!ctrl.validateExtensionMutationClient(req, res)) {
16222
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16223
+ requireClientId: false
16224
+ })) {
15926
16225
  return;
15927
16226
  }
15928
16227
  const body = safeBody2(req);
@@ -15972,11 +16271,56 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15972
16271
  if (!validateExtensionSourceHost(sourceValue, res)) {
15973
16272
  return;
15974
16273
  }
16274
+ const localSource = /^[A-Za-z]:[\\/]/.test(sourceValue) || sourceValue.startsWith("/") || sourceValue.startsWith(".");
16275
+ if (localSource) {
16276
+ try {
16277
+ const metadata = await parseInstallSource(sourceValue, {
16278
+ networkPolicy: "public"
16279
+ });
16280
+ if (metadata.type !== "git" && metadata.type !== "github-release" && metadata.type !== "npm") {
16281
+ res.status(400).json({
16282
+ error: "Only GitHub, Git, and npm extension installs are supported over the daemon endpoint."
16283
+ });
16284
+ return;
16285
+ }
16286
+ } catch (error2) {
16287
+ const message = error2 instanceof Error ? error2.message : "Invalid install source";
16288
+ res.status(400).json({
16289
+ error: redactUrlCredentials(
16290
+ message.replaceAll(
16291
+ sourceValue,
16292
+ redactExtensionDisplaySource(sourceValue)
16293
+ )
16294
+ )
16295
+ });
16296
+ return;
16297
+ }
16298
+ }
16299
+ const npmSource = sourceValue.startsWith("@");
16300
+ const remoteSource = npmSource || sourceValue.startsWith("https://") || /^[^/\s]+\/[^/\s]+/.test(sourceValue);
16301
+ if (!localSource && !remoteSource) {
16302
+ res.status(400).json({
16303
+ error: `Install source not found: ${redactExtensionDisplaySource(
16304
+ sourceValue
16305
+ )}`
16306
+ });
16307
+ return;
16308
+ }
16309
+ if (npmSource && refValue) {
16310
+ res.status(400).json({ error: "--ref is not applicable for npm extensions." });
16311
+ return;
16312
+ }
16313
+ if (!npmSource && registryValue) {
16314
+ res.status(400).json({
16315
+ error: "--registry is only applicable for npm extensions."
16316
+ });
16317
+ return;
16318
+ }
15975
16319
  ctrl.runQueuedExtensionMutation(
15976
16320
  "install",
15977
16321
  { source: sourceValue },
15978
16322
  res,
15979
- async (extensionManager, _signal, context) => {
16323
+ async (extensionManager, _signal, context, operationId) => {
15980
16324
  const prepared = await context.prepare(async (signal) => {
15981
16325
  const installMetadata = await parseInstallSource(sourceValue, {
15982
16326
  networkPolicy: "public"
@@ -16000,6 +16344,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16000
16344
  if (installMetadata.type === "npm" && registryUrl) {
16001
16345
  installMetadata.registryUrl = registryUrl;
16002
16346
  }
16347
+ supersedeActiveInstallOperations(ctrl, operationId);
16003
16348
  return await extensionManager.prepareExtensionInstall({
16004
16349
  installMetadata: {
16005
16350
  ...installMetadata,
@@ -16030,7 +16375,19 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16030
16375
  }
16031
16376
  },
16032
16377
  {
16033
- deadlineMs: EXTENSION_PREPARE_DEADLINE_MS,
16378
+ createManager: /* @__PURE__ */ __name((operationId) => ctrl.createExtensionManager(
16379
+ void 0,
16380
+ void 0,
16381
+ extensionInteractionHandlers(ctrl, operationId)
16382
+ ), "createManager"),
16383
+ onSettled: /* @__PURE__ */ __name((operationId) => {
16384
+ supersededInstallOperations.delete(operationId);
16385
+ cancelPendingExtensionInteraction(
16386
+ operationId,
16387
+ "Extension operation ended"
16388
+ );
16389
+ }, "onSettled"),
16390
+ deadlineMs: EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS,
16034
16391
  ...globalReconciliationOptions()
16035
16392
  }
16036
16393
  );
@@ -16047,7 +16404,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16047
16404
  let timer;
16048
16405
  let releaseOperationSlot;
16049
16406
  try {
16050
- if (!ctrl.validateExtensionMutationClient(req, res)) {
16407
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16408
+ requireClientId: false
16409
+ })) {
16051
16410
  return;
16052
16411
  }
16053
16412
  releaseOperationSlot = ctrl.acquireOperationSlot(res);
@@ -16107,7 +16466,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16107
16466
  const ctrl = resolve5(req, res, true);
16108
16467
  if (!ctrl) return;
16109
16468
  try {
16110
- if (!ctrl.validateExtensionMutationClient(req, res)) {
16469
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16470
+ requireClientId: false
16471
+ })) {
16111
16472
  return;
16112
16473
  }
16113
16474
  const releaseOperationSlot = ctrl.acquireOperationSlot(res);
@@ -16223,7 +16584,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16223
16584
  const ctrl = resolve5(req, res, true);
16224
16585
  if (!ctrl) return;
16225
16586
  try {
16226
- if (!ctrl.validateExtensionMutationClient(req, res)) {
16587
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16588
+ requireClientId: false
16589
+ })) {
16227
16590
  return;
16228
16591
  }
16229
16592
  const name = req.params["name"];
@@ -16280,7 +16643,18 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16280
16643
  }
16281
16644
  },
16282
16645
  {
16283
- deadlineMs: EXTENSION_PREPARE_DEADLINE_MS,
16646
+ createManager: /* @__PURE__ */ __name((operationId) => ctrl.createExtensionManager(
16647
+ void 0,
16648
+ void 0,
16649
+ extensionInteractionHandlers(ctrl, operationId)
16650
+ ), "createManager"),
16651
+ onSettled: /* @__PURE__ */ __name((operationId) => {
16652
+ cancelPendingExtensionInteraction(
16653
+ operationId,
16654
+ "Extension operation ended"
16655
+ );
16656
+ }, "onSettled"),
16657
+ deadlineMs: EXTENSION_INTERACTIVE_PREPARE_DEADLINE_MS,
16284
16658
  ...globalReconciliationOptions()
16285
16659
  }
16286
16660
  );
@@ -16293,7 +16667,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16293
16667
  const ctrl = resolve5(req, res, true);
16294
16668
  if (!ctrl) return;
16295
16669
  try {
16296
- if (!ctrl.validateExtensionMutationClient(req, res)) {
16670
+ if (!ctrl.validateExtensionMutationClient(req, res, {
16671
+ requireClientId: false
16672
+ })) {
16297
16673
  return;
16298
16674
  }
16299
16675
  const name = req.params["name"];
@@ -17355,67 +17731,682 @@ init_esbuild_shims();
17355
17731
 
17356
17732
  // packages/cli/src/serve/routes/session-runtime.ts
17357
17733
  init_esbuild_shims();
17358
- function requireSessionRuntime(opts) {
17359
- const {
17360
- sessionId,
17361
- route,
17362
- res,
17363
- workspaceRegistry,
17364
- daemonLog,
17365
- details = {}
17366
- } = opts;
17367
- if (workspaceRegistry.list().length === 1) {
17368
- return workspaceRegistry.primary;
17734
+
17735
+ // packages/cli/src/serve/server/telemetry.ts
17736
+ init_esbuild_shims();
17737
+ var legacySessionTelemetryRoutes = [
17738
+ {
17739
+ method: "POST",
17740
+ path: "/session",
17741
+ attribution: "handler_resolved",
17742
+ route: "POST /session"
17743
+ },
17744
+ {
17745
+ method: "POST",
17746
+ path: "/session/:id/load",
17747
+ attribution: "handler_resolved",
17748
+ route: "POST /session/:id/load"
17749
+ },
17750
+ {
17751
+ method: "POST",
17752
+ path: "/session/:id/resume",
17753
+ attribution: "handler_resolved",
17754
+ route: "POST /session/:id/resume"
17755
+ },
17756
+ {
17757
+ method: "POST",
17758
+ path: "/session/:id/branch",
17759
+ attribution: "handler_resolved",
17760
+ route: "POST /session/:id/branch"
17761
+ },
17762
+ {
17763
+ method: "POST",
17764
+ path: "/session/:id/fork",
17765
+ attribution: "handler_resolved",
17766
+ route: "POST /session/:id/fork"
17767
+ },
17768
+ {
17769
+ method: "POST",
17770
+ path: "/session/:id/cd",
17771
+ attribution: "handler_resolved",
17772
+ route: "POST /session/:id/cd"
17773
+ },
17774
+ {
17775
+ method: "GET",
17776
+ path: "/session/:id/status",
17777
+ attribution: "handler_resolved",
17778
+ route: "GET /session/:id/status"
17779
+ },
17780
+ {
17781
+ method: "GET",
17782
+ path: "/session/:id/export",
17783
+ attribution: "pre_resolved",
17784
+ route: "GET /session/:id/export"
17785
+ },
17786
+ {
17787
+ method: "GET",
17788
+ path: "/session/:id/transcript",
17789
+ attribution: "handler_resolved",
17790
+ route: "GET /session/:id/transcript"
17791
+ },
17792
+ {
17793
+ method: "GET",
17794
+ path: "/session/:id/context",
17795
+ attribution: "handler_resolved",
17796
+ route: "GET /session/:id/context"
17797
+ },
17798
+ {
17799
+ method: "GET",
17800
+ path: "/session/:id/context-usage",
17801
+ attribution: "handler_resolved",
17802
+ route: "GET /session/:id/context-usage"
17803
+ },
17804
+ {
17805
+ method: "GET",
17806
+ path: "/session/:id/stats",
17807
+ attribution: "handler_resolved",
17808
+ route: "GET /session/:id/stats"
17809
+ },
17810
+ {
17811
+ method: "GET",
17812
+ path: "/session/:id/supported-commands",
17813
+ attribution: "handler_resolved",
17814
+ route: "GET /session/:id/supported-commands"
17815
+ },
17816
+ {
17817
+ method: "GET",
17818
+ path: "/session/:id/tasks",
17819
+ attribution: "handler_resolved",
17820
+ route: "GET /session/:id/tasks"
17821
+ },
17822
+ {
17823
+ method: "GET",
17824
+ path: "/session/:id/lsp",
17825
+ attribution: "handler_resolved",
17826
+ route: "GET /session/:id/lsp"
17827
+ },
17828
+ {
17829
+ method: "GET",
17830
+ path: "/session/:id/hooks",
17831
+ attribution: "handler_resolved",
17832
+ route: "GET /session/:id/hooks"
17833
+ },
17834
+ {
17835
+ method: "GET",
17836
+ path: "/session/:id/artifacts",
17837
+ attribution: "handler_resolved",
17838
+ route: "GET /session/:id/artifacts"
17839
+ },
17840
+ {
17841
+ method: "POST",
17842
+ path: "/session/:id/artifacts",
17843
+ attribution: "handler_resolved",
17844
+ route: "POST /session/:id/artifacts"
17845
+ },
17846
+ {
17847
+ method: "DELETE",
17848
+ path: "/session/:id/artifacts/:artifactId",
17849
+ attribution: "handler_resolved",
17850
+ route: "DELETE /session/:id/artifacts/:artifactId"
17851
+ },
17852
+ {
17853
+ method: "POST",
17854
+ path: "/session/:id/tasks/:taskId/cancel",
17855
+ attribution: "handler_resolved",
17856
+ route: "POST /session/:id/tasks/:taskId/cancel"
17857
+ },
17858
+ {
17859
+ method: "POST",
17860
+ path: "/session/:id/goal/clear",
17861
+ attribution: "handler_resolved",
17862
+ route: "POST /session/:id/goal/clear"
17863
+ },
17864
+ {
17865
+ method: "POST",
17866
+ path: "/session/:id/continue",
17867
+ attribution: "handler_resolved",
17868
+ route: "POST /session/:id/continue"
17869
+ },
17870
+ {
17871
+ method: "POST",
17872
+ path: "/session/:id/prompt",
17873
+ attribution: "handler_resolved",
17874
+ route: "POST /session/:id/prompt"
17875
+ },
17876
+ {
17877
+ method: "POST",
17878
+ path: "/session/:id/generate",
17879
+ attribution: "handler_resolved",
17880
+ route: "POST /session/:id/generate"
17881
+ },
17882
+ {
17883
+ method: "POST",
17884
+ path: "/session/:id/heartbeat",
17885
+ attribution: "handler_resolved",
17886
+ route: "POST /session/:id/heartbeat"
17887
+ },
17888
+ {
17889
+ method: "POST",
17890
+ path: "/session/:id/detach",
17891
+ attribution: "handler_resolved",
17892
+ route: "POST /session/:id/detach"
17893
+ },
17894
+ {
17895
+ method: "POST",
17896
+ path: "/session/:id/cancel",
17897
+ attribution: "handler_resolved",
17898
+ route: "POST /session/:id/cancel"
17899
+ },
17900
+ {
17901
+ method: "DELETE",
17902
+ path: "/session/:id",
17903
+ attribution: "handler_resolved",
17904
+ route: "DELETE /session/:id"
17905
+ },
17906
+ {
17907
+ method: "POST",
17908
+ path: "/sessions/delete",
17909
+ attribution: "pre_resolved",
17910
+ route: "POST /sessions/delete"
17911
+ },
17912
+ {
17913
+ method: "POST",
17914
+ path: "/sessions/archive",
17915
+ attribution: "pre_resolved",
17916
+ route: "POST /sessions/archive"
17917
+ },
17918
+ {
17919
+ method: "POST",
17920
+ path: "/sessions/unarchive",
17921
+ attribution: "pre_resolved",
17922
+ route: "POST /sessions/unarchive"
17923
+ },
17924
+ {
17925
+ method: "PATCH",
17926
+ path: "/session/:id/metadata",
17927
+ attribution: "handler_resolved",
17928
+ route: "PATCH /session/:id/metadata"
17929
+ },
17930
+ {
17931
+ method: "PATCH",
17932
+ path: "/session/:id/organization",
17933
+ attribution: "pre_resolved",
17934
+ route: "PATCH /session/:id/organization"
17935
+ },
17936
+ {
17937
+ method: "POST",
17938
+ path: "/session/:id/model",
17939
+ attribution: "handler_resolved",
17940
+ route: "POST /session/:id/model"
17941
+ },
17942
+ {
17943
+ method: "POST",
17944
+ path: "/session/:id/recap",
17945
+ attribution: "handler_resolved",
17946
+ route: "POST /session/:id/recap"
17947
+ },
17948
+ {
17949
+ method: "POST",
17950
+ path: "/session/:id/btw",
17951
+ attribution: "handler_resolved",
17952
+ route: "POST /session/:id/btw"
17953
+ },
17954
+ {
17955
+ method: "POST",
17956
+ path: "/session/:id/mid-turn-message",
17957
+ attribution: "handler_resolved",
17958
+ route: "POST /session/:id/mid-turn-message"
17959
+ },
17960
+ {
17961
+ method: "GET",
17962
+ path: "/session/:id/pending-prompts",
17963
+ attribution: "handler_resolved",
17964
+ route: "GET /session/:id/pending-prompts"
17965
+ },
17966
+ {
17967
+ method: "DELETE",
17968
+ path: "/session/:id/pending-prompts/:promptId",
17969
+ attribution: "handler_resolved",
17970
+ route: "DELETE /session/:id/pending-prompts/:promptId"
17971
+ },
17972
+ {
17973
+ method: "POST",
17974
+ path: "/session/:id/shell",
17975
+ attribution: "handler_resolved",
17976
+ route: "POST /session/:id/shell"
17977
+ },
17978
+ {
17979
+ method: "GET",
17980
+ path: "/session/:id/rewind/snapshots",
17981
+ attribution: "handler_resolved",
17982
+ route: "GET /session/:id/rewind/snapshots"
17983
+ },
17984
+ {
17985
+ method: "POST",
17986
+ path: "/session/:id/rewind",
17987
+ attribution: "handler_resolved",
17988
+ route: "POST /session/:id/rewind"
17989
+ },
17990
+ {
17991
+ method: "POST",
17992
+ path: "/session/:id/approval-mode",
17993
+ attribution: "handler_resolved",
17994
+ route: "POST /session/:id/approval-mode"
17995
+ },
17996
+ {
17997
+ method: "POST",
17998
+ path: "/session/:id/language",
17999
+ attribution: "handler_resolved",
18000
+ route: "POST /session/:id/language"
18001
+ },
18002
+ {
18003
+ method: "POST",
18004
+ path: "/session/:id/permission/:requestId",
18005
+ attribution: "handler_resolved",
18006
+ route: "POST /session/:id/permission/:requestId"
18007
+ },
18008
+ {
18009
+ method: "POST",
18010
+ path: "/permission/:requestId",
18011
+ attribution: "pre_resolved",
18012
+ route: "POST /permission/:requestId"
18013
+ },
18014
+ {
18015
+ method: "GET",
18016
+ path: "/session/:id/events",
18017
+ attribution: "handler_resolved",
18018
+ route: "GET /session/:id/events"
18019
+ },
18020
+ {
18021
+ method: "POST",
18022
+ path: "/session/:id/a2ui-action",
18023
+ attribution: "pre_resolved",
18024
+ route: "POST /session/:id/a2ui-action"
17369
18025
  }
17370
- const resolution = workspaceRegistry.resolveLiveSessionOwner(sessionId);
17371
- if (resolution.kind === "found") {
17372
- const runtime = resolution.runtime;
17373
- if (!runtime.primary && !runtime.trusted) {
17374
- daemonLog?.warn("session routing failed", {
17375
- route,
17376
- resolutionKind: "untrusted_workspace",
17377
- sessionId,
17378
- workspaceId: runtime.workspaceId,
17379
- workspaceCwd: runtime.workspaceCwd,
17380
- ...details
17381
- });
17382
- sendUntrustedWorkspaceResponse(res, {
17383
- sessionId,
17384
- workspaceCwd: runtime.workspaceCwd,
17385
- workspaceId: runtime.workspaceId
17386
- });
17387
- return void 0;
17388
- }
17389
- return runtime;
18026
+ ];
18027
+ var daemonTelemetryResponseContext = Symbol("daemonTelemetryResponseContext");
18028
+ function decodePathSegment(value) {
18029
+ try {
18030
+ return decodeURIComponent(value);
18031
+ } catch {
18032
+ return value;
17390
18033
  }
17391
- if (resolution.kind === "not_found") {
17392
- daemonLog?.warn("session routing failed", {
17393
- route,
17394
- resolutionKind: "not_found",
17395
- sessionId,
17396
- ...details
17397
- });
17398
- res.status(404).json({
17399
- error: `No session with id "${sessionId}"`,
17400
- code: "session_not_found",
17401
- sessionId
17402
- });
18034
+ }
18035
+ __name(decodePathSegment, "decodePathSegment");
18036
+ function matchLegacySessionTelemetryRoute(method, requestPath) {
18037
+ const path15 = requestPath.length > 1 && requestPath.endsWith("/") ? requestPath.slice(0, -1) : requestPath;
18038
+ const requestSegments = path15.split("/").slice(1);
18039
+ const prefix = requestSegments[0]?.toLowerCase();
18040
+ if (prefix !== "session" && prefix !== "sessions" && prefix !== "permission") {
17403
18041
  return void 0;
17404
18042
  }
17405
- const workspaceIds = resolution.runtimes.map(
17406
- (runtime) => runtime.workspaceId
17407
- );
17408
- daemonLog?.warn("session routing failed", {
17409
- route,
17410
- resolutionKind: "ambiguous",
17411
- sessionId,
17412
- workspaceIds,
17413
- ...details
17414
- });
17415
- res.status(500).json({
17416
- error: `Session owner is ambiguous for "${sessionId}"`,
17417
- code: "ambiguous_session_owner",
17418
- sessionId,
18043
+ for (const entry of legacySessionTelemetryRoutes) {
18044
+ if (entry.method !== method) continue;
18045
+ const templateSegments = entry.path.split("/").slice(1);
18046
+ if (templateSegments.length !== requestSegments.length) continue;
18047
+ const params = /* @__PURE__ */ new Map();
18048
+ let matched = true;
18049
+ for (let index = 0; index < templateSegments.length; index += 1) {
18050
+ const templateSegment = templateSegments[index];
18051
+ const requestSegment = requestSegments[index];
18052
+ if (templateSegment.startsWith(":")) {
18053
+ if (requestSegment === "") {
18054
+ matched = false;
18055
+ break;
18056
+ }
18057
+ params.set(templateSegment.slice(1), requestSegment);
18058
+ } else if (templateSegment.toLowerCase() !== requestSegment.toLowerCase()) {
18059
+ matched = false;
18060
+ break;
18061
+ }
18062
+ }
18063
+ if (!matched) continue;
18064
+ const rawSessionId = params.get("id");
18065
+ const rawRequestId = params.get("requestId");
18066
+ const requestId = rawRequestId !== void 0 ? decodePathSegment(rawRequestId) : void 0;
18067
+ return {
18068
+ route: entry.route,
18069
+ attribution: entry.attribution,
18070
+ ...rawSessionId ? { sessionId: decodePathSegment(rawSessionId) } : {},
18071
+ ...requestId !== void 0 && requestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(requestId) ? { permissionRequestId: requestId } : {}
18072
+ };
18073
+ }
18074
+ return void 0;
18075
+ }
18076
+ __name(matchLegacySessionTelemetryRoute, "matchLegacySessionTelemetryRoute");
18077
+ function setDaemonTelemetryWorkspace(res, workspaceCwd) {
18078
+ try {
18079
+ const context = res[daemonTelemetryResponseContext];
18080
+ if (context && context.workspaceCwd === void 0) {
18081
+ context.workspaceCwd = workspaceCwd;
18082
+ }
18083
+ } catch {
18084
+ }
18085
+ }
18086
+ __name(setDaemonTelemetryWorkspace, "setDaemonTelemetryWorkspace");
18087
+ function resolveDaemonTelemetryRoute(req) {
18088
+ const legacyRoute = matchLegacySessionTelemetryRoute(req.method, req.path);
18089
+ if (legacyRoute) return legacyRoute;
18090
+ const path15 = req.path.replace(/\/$/, "") || "/";
18091
+ if (req.method === "GET" && path15 === "/daemon/status") {
18092
+ return { route: "GET /daemon/status" };
18093
+ }
18094
+ if (req.method === "GET" && /^\/workspace\/[^/]+\/sessions$/.test(path15)) {
18095
+ return { route: "GET /workspace/:id/sessions" };
18096
+ }
18097
+ if (req.method === "GET" && /^\/workspaces\/[^/]+\/sessions$/.test(path15)) {
18098
+ return { route: "GET /workspace/:id/sessions" };
18099
+ }
18100
+ if (req.method === "GET" && /^\/workspace\/[^/]+\/session-info$/.test(path15)) {
18101
+ return { route: "GET /workspace/:id/session-info" };
18102
+ }
18103
+ if (req.method === "GET" && /^\/workspaces\/[^/]+\/session-info$/.test(path15)) {
18104
+ return { route: "GET /workspace/:id/session-info" };
18105
+ }
18106
+ const workspaceTranscript = path15.match(
18107
+ /^\/workspaces\/[^/]+\/session\/([^/]+)\/transcript$/
18108
+ );
18109
+ if (workspaceTranscript?.[1] && req.method === "GET") {
18110
+ return {
18111
+ route: "GET /workspaces/:workspace/session/:id/transcript",
18112
+ sessionId: decodePathSegment(workspaceTranscript[1])
18113
+ };
18114
+ }
18115
+ const workspaceExport = path15.match(
18116
+ /^\/workspaces\/[^/]+\/session\/([^/]+)\/export$/
18117
+ );
18118
+ if (workspaceExport?.[1] && req.method === "GET") {
18119
+ return {
18120
+ route: "GET /workspaces/:workspace/session/:id/export",
18121
+ sessionId: decodePathSegment(workspaceExport[1])
18122
+ };
18123
+ }
18124
+ const workspaceArchivedExport = path15.match(
18125
+ /^\/workspaces\/[^/]+\/session\/([^/]+)\/archive\/export$/
18126
+ );
18127
+ if (workspaceArchivedExport?.[1] && req.method === "GET") {
18128
+ return {
18129
+ route: "GET /workspaces/:workspace/session/:id/archive/export",
18130
+ sessionId: decodePathSegment(workspaceArchivedExport[1])
18131
+ };
18132
+ }
18133
+ const pluralWorkspacePrefix = /^\/workspaces\/[^/]+/;
18134
+ if (pluralWorkspacePrefix.test(path15)) {
18135
+ const suffix = path15.replace(pluralWorkspacePrefix, "/workspace");
18136
+ if (req.method === "GET") {
18137
+ if (suffix === "/workspace/mcp" || suffix === "/workspace/skills" || suffix === "/workspace/tools" || suffix === "/workspace/providers" || suffix === "/workspace/env" || suffix === "/workspace/preflight" || suffix === "/workspace/hooks" || suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/permissions" || suffix === "/workspace/trust" || suffix === "/workspace/memory" || suffix === "/workspace/agents") {
18138
+ return { route: `GET ${suffix}` };
18139
+ }
18140
+ if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
18141
+ return { route: "GET /workspace/agents/:agentType" };
18142
+ }
18143
+ if (suffix === "/workspace/file") return { route: "GET /file" };
18144
+ if (suffix === "/workspace/file/bytes") {
18145
+ return { route: "GET /file/bytes" };
18146
+ }
18147
+ if (suffix === "/workspace/stat") return { route: "GET /stat" };
18148
+ if (suffix === "/workspace/list") return { route: "GET /list" };
18149
+ if (suffix === "/workspace/glob") return { route: "GET /glob" };
18150
+ if (/^\/workspace\/mcp\/[^/]+\/tools$/.test(suffix)) {
18151
+ return { route: "GET /workspace/mcp/:server/tools" };
18152
+ }
18153
+ if (/^\/workspace\/mcp\/[^/]+\/resources$/.test(suffix)) {
18154
+ return { route: "GET /workspace/mcp/:server/resources" };
18155
+ }
18156
+ }
18157
+ if (req.method === "POST") {
18158
+ if (suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/voice/transcribe" || suffix === "/workspace/permissions" || suffix === "/workspace/trust/request" || suffix === "/workspace/init" || suffix === "/workspace/reload" || suffix === "/workspace/file/write" || suffix === "/workspace/file/edit" || suffix === "/workspace/mcp/servers" || suffix === "/workspace/memory" || suffix === "/workspace/agents" || suffix === "/workspace/sessions/delete" || suffix === "/workspace/sessions/archive" || suffix === "/workspace/sessions/unarchive" || suffix === "/workspace/session-groups") {
18159
+ return { route: `POST ${suffix}` };
18160
+ }
18161
+ if (/^\/workspace\/tools\/[^/]+\/enable$/.test(suffix)) {
18162
+ return { route: "POST /workspace/tools/:name/enable" };
18163
+ }
18164
+ if (/^\/workspace\/mcp\/[^/]+\/restart$/.test(suffix)) {
18165
+ return { route: "POST /workspace/mcp/:server/restart" };
18166
+ }
18167
+ if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
18168
+ return { route: "POST /workspace/agents/:agentType" };
18169
+ }
18170
+ if (/^\/workspace\/mcp\/[^/]+\/(approve|enable|disable|authenticate|clear-auth)$/.test(
18171
+ suffix
18172
+ )) {
18173
+ return {
18174
+ route: `POST /workspace/mcp/:server/${suffix.split("/").at(-1)}`
18175
+ };
18176
+ }
18177
+ }
18178
+ if (req.method === "DELETE" && /^\/workspace\/mcp\/servers\/[^/]+$/.test(suffix)) {
18179
+ return { route: "DELETE /workspace/mcp/servers/:name" };
18180
+ }
18181
+ if (req.method === "DELETE" && /^\/workspace\/agents\/[^/]+$/.test(suffix)) {
18182
+ return { route: "DELETE /workspace/agents/:agentType" };
18183
+ }
18184
+ if (suffix === "/workspace/session-groups" && req.method === "GET") {
18185
+ return { route: "GET /workspace/session-groups" };
18186
+ }
18187
+ if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "PATCH") {
18188
+ return { route: "PATCH /workspace/session-groups/:groupId" };
18189
+ }
18190
+ if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "DELETE") {
18191
+ return { route: "DELETE /workspace/session-groups/:groupId" };
18192
+ }
18193
+ }
18194
+ if (req.method === "POST" && path15 === "/workspace/init") {
18195
+ return { route: "POST /workspace/init" };
18196
+ }
18197
+ if (req.method === "POST" && path15 === "/workspace/setup-github") {
18198
+ return { route: "POST /workspace/setup-github" };
18199
+ }
18200
+ if (req.method === "POST" && path15 === "/workspace/reload") {
18201
+ return { route: "POST /workspace/reload" };
18202
+ }
18203
+ const mcpRestart = path15.match(/^\/workspace\/mcp\/([^/]+)\/restart$/);
18204
+ if (mcpRestart?.[1] && req.method === "POST") {
18205
+ return { route: "POST /workspace/mcp/:server/restart" };
18206
+ }
18207
+ if (req.method === "POST" && path15 === "/workspace/mcp/servers") {
18208
+ return { route: "POST /workspace/mcp/servers" };
18209
+ }
18210
+ const mcpDelete = path15.match(/^\/workspace\/mcp\/servers\/([^/]+)$/);
18211
+ if (mcpDelete?.[1] && req.method === "DELETE") {
18212
+ return { route: "DELETE /workspace/mcp/servers/:name" };
18213
+ }
18214
+ if (req.method === "POST" && path15 === "/workspace/auth/device-flow") {
18215
+ return { route: "POST /workspace/auth/device-flow" };
18216
+ }
18217
+ const deviceFlowDelete = path15.match(
18218
+ /^\/workspace\/auth\/device-flow\/([^/]+)$/
18219
+ );
18220
+ if (deviceFlowDelete?.[1] && req.method === "DELETE") {
18221
+ return { route: "DELETE /workspace/auth/device-flow/:id" };
18222
+ }
18223
+ const toolEnable = path15.match(/^\/workspace\/tools\/([^/]+)\/enable$/);
18224
+ if (toolEnable?.[1] && req.method === "POST") {
18225
+ return { route: "POST /workspace/tools/:name/enable" };
18226
+ }
18227
+ if (path15 === "/workspace/settings") {
18228
+ if (req.method === "GET") return { route: "GET /workspace/settings" };
18229
+ if (req.method === "POST") return { route: "POST /workspace/settings" };
18230
+ }
18231
+ if (path15 === "/workspace/permissions") {
18232
+ if (req.method === "GET") return { route: "GET /workspace/permissions" };
18233
+ if (req.method === "POST") return { route: "POST /workspace/permissions" };
18234
+ }
18235
+ if (path15 === "/workspace/trust") {
18236
+ if (req.method === "GET") return { route: "GET /workspace/trust" };
18237
+ }
18238
+ if (req.method === "POST" && path15 === "/workspace/trust/request") {
18239
+ return { route: "POST /workspace/trust/request" };
18240
+ }
18241
+ if (path15 === "/workspace/voice") {
18242
+ if (req.method === "GET") return { route: "GET /workspace/voice" };
18243
+ if (req.method === "POST") return { route: "POST /workspace/voice" };
18244
+ }
18245
+ if (req.method === "POST" && path15 === "/workspace/voice/transcribe") {
18246
+ return { route: "POST /workspace/voice/transcribe" };
18247
+ }
18248
+ return void 0;
18249
+ }
18250
+ __name(resolveDaemonTelemetryRoute, "resolveDaemonTelemetryRoute");
18251
+ function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
18252
+ const workspaceHashByCwd = /* @__PURE__ */ new Map();
18253
+ const resolveWorkspaceHash = /* @__PURE__ */ __name((workspaceCwd) => {
18254
+ const existing = workspaceHashByCwd.get(workspaceCwd);
18255
+ if (existing !== void 0) return existing;
18256
+ const workspaceHash = hashDaemonWorkspace(workspaceCwd);
18257
+ workspaceHashByCwd.set(workspaceCwd, workspaceHash);
18258
+ return workspaceHash;
18259
+ }, "resolveWorkspaceHash");
18260
+ return (req, res, next) => {
18261
+ const route = resolveDaemonTelemetryRoute(req);
18262
+ if (!route) {
18263
+ next();
18264
+ return;
18265
+ }
18266
+ const sessionId = route.sessionId;
18267
+ let workspaceHash;
18268
+ if (route.attribution !== "handler_resolved") {
18269
+ try {
18270
+ workspaceHash = resolveWorkspaceHash(resolveWorkspaceCwd(req));
18271
+ } catch {
18272
+ }
18273
+ }
18274
+ const rawClientId = req.get(CLIENT_ID_HEADER);
18275
+ const clientId = rawClientId !== void 0 && rawClientId !== "" && rawClientId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawClientId) ? rawClientId : void 0;
18276
+ const deferredRuntime = getDeferredRuntimeRequestTiming(req);
18277
+ const startMs = deferredRuntime?.startedAt.getTime() ?? Date.now();
18278
+ const telemetryRes = res;
18279
+ if (route.attribution === "handler_resolved") {
18280
+ try {
18281
+ telemetryRes[daemonTelemetryResponseContext] = {};
18282
+ } catch {
18283
+ }
18284
+ }
18285
+ void withDaemonRequestSpan(
18286
+ {
18287
+ method: req.method,
18288
+ route: route.route,
18289
+ ...workspaceHash !== void 0 ? { workspaceHash } : {},
18290
+ ...sessionId ? { sessionId } : {},
18291
+ ...route.permissionRequestId ? { permissionRequestId: route.permissionRequestId } : {},
18292
+ ...clientId ? { clientId } : {},
18293
+ ...deferredRuntime?.waitMs !== void 0 ? {
18294
+ startTime: deferredRuntime.startedAt,
18295
+ deferredRuntimeWaitMs: deferredRuntime.waitMs,
18296
+ deferredRuntimePath: deferredRuntime.path
18297
+ } : {}
18298
+ },
18299
+ async (span) => await new Promise((resolve5, reject) => {
18300
+ let done = false;
18301
+ const finish = /* @__PURE__ */ __name(() => {
18302
+ if (done) return;
18303
+ done = true;
18304
+ try {
18305
+ const context = telemetryRes[daemonTelemetryResponseContext];
18306
+ delete telemetryRes[daemonTelemetryResponseContext];
18307
+ if (context?.workspaceCwd !== void 0) {
18308
+ span?.setAttribute(
18309
+ "qwen-code.workspace.hash",
18310
+ resolveWorkspaceHash(context.workspaceCwd)
18311
+ );
18312
+ }
18313
+ } catch {
18314
+ }
18315
+ recordDaemonHttpResponse(span, res.statusCode);
18316
+ const durationMs = Date.now() - startMs;
18317
+ const successfulSse = route.route === "GET /session/:id/events" && res.statusCode === 200 && res.headersSent;
18318
+ if (!successfulSse) {
18319
+ recordDaemonHttpRequest(
18320
+ durationMs,
18321
+ route.route,
18322
+ res.statusCode,
18323
+ deferredRuntime?.path
18324
+ );
18325
+ }
18326
+ if (!successfulSse && route.route !== "GET /daemon/status" && route.route !== "POST /session/:id/heartbeat") {
18327
+ recordRequest?.(durationMs, res.statusCode);
18328
+ }
18329
+ resolve5();
18330
+ }, "finish");
18331
+ res.once("finish", finish);
18332
+ res.once("close", finish);
18333
+ try {
18334
+ next();
18335
+ } catch (error2) {
18336
+ recordDaemonError(span, error2);
18337
+ reject(error2);
18338
+ }
18339
+ })
18340
+ ).catch(next);
18341
+ };
18342
+ }
18343
+ __name(daemonTelemetryMiddleware, "daemonTelemetryMiddleware");
18344
+
18345
+ // packages/cli/src/serve/routes/session-runtime.ts
18346
+ function requireSessionRuntime(opts) {
18347
+ const {
18348
+ sessionId,
18349
+ route,
18350
+ res,
18351
+ workspaceRegistry,
18352
+ daemonLog,
18353
+ details = {}
18354
+ } = opts;
18355
+ if (workspaceRegistry.list().length === 1) {
18356
+ const runtime = workspaceRegistry.primary;
18357
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18358
+ return runtime;
18359
+ }
18360
+ const resolution = workspaceRegistry.resolveLiveSessionOwner(sessionId);
18361
+ if (resolution.kind === "found") {
18362
+ const runtime = resolution.runtime;
18363
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18364
+ if (!runtime.primary && !runtime.trusted) {
18365
+ daemonLog?.warn("session routing failed", {
18366
+ route,
18367
+ resolutionKind: "untrusted_workspace",
18368
+ sessionId,
18369
+ workspaceId: runtime.workspaceId,
18370
+ workspaceCwd: runtime.workspaceCwd,
18371
+ ...details
18372
+ });
18373
+ sendUntrustedWorkspaceResponse(res, {
18374
+ sessionId,
18375
+ workspaceCwd: runtime.workspaceCwd,
18376
+ workspaceId: runtime.workspaceId
18377
+ });
18378
+ return void 0;
18379
+ }
18380
+ return runtime;
18381
+ }
18382
+ if (resolution.kind === "not_found") {
18383
+ daemonLog?.warn("session routing failed", {
18384
+ route,
18385
+ resolutionKind: "not_found",
18386
+ sessionId,
18387
+ ...details
18388
+ });
18389
+ res.status(404).json({
18390
+ error: `No session with id "${sessionId}"`,
18391
+ code: "session_not_found",
18392
+ sessionId
18393
+ });
18394
+ return void 0;
18395
+ }
18396
+ const workspaceIds = resolution.runtimes.map(
18397
+ (runtime) => runtime.workspaceId
18398
+ );
18399
+ daemonLog?.warn("session routing failed", {
18400
+ route,
18401
+ resolutionKind: "ambiguous",
18402
+ sessionId,
18403
+ workspaceIds,
18404
+ ...details
18405
+ });
18406
+ res.status(500).json({
18407
+ error: `Session owner is ambiguous for "${sessionId}"`,
18408
+ code: "ambiguous_session_owner",
18409
+ sessionId,
17419
18410
  route,
17420
18411
  workspaceIds
17421
18412
  });
@@ -17509,7 +18500,7 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
17509
18500
 
17510
18501
  // packages/cli/src/serve/routes/session.ts
17511
18502
  init_esbuild_shims();
17512
- import * as crypto2 from "node:crypto";
18503
+ import * as crypto3 from "node:crypto";
17513
18504
  import * as path11 from "node:path";
17514
18505
 
17515
18506
  // packages/cli/src/serve/server/prompt-deadline.ts
@@ -17566,7 +18557,7 @@ function parseOrganizedCursor(cursor, expected) {
17566
18557
  const decoded = Buffer.from(cursor, "base64url").toString("utf8");
17567
18558
  const parsed = JSON.parse(decoded);
17568
18559
  const last = parsed.last;
17569
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.isPinned !== "boolean" || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.group !== expected.group || parsed.archiveState !== expected.archiveState) {
18560
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.isPinned !== "boolean" || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.group !== expected.group || parsed.archiveState !== expected.archiveState || parsed.sourceType !== expected.sourceType || parsed.sourceId !== expected.sourceId) {
17570
18561
  throw new Error("invalid organized cursor");
17571
18562
  }
17572
18563
  return last;
@@ -17575,9 +18566,9 @@ function parseOrganizedCursor(cursor, expected) {
17575
18566
  }
17576
18567
  }
17577
18568
  __name(parseOrganizedCursor, "parseOrganizedCursor");
17578
- function encodeOrganizedCursor(last, group, archiveState) {
18569
+ function encodeOrganizedCursor(last, group, archiveState, sourceType, sourceId) {
17579
18570
  return Buffer.from(
17580
- JSON.stringify({ group, archiveState, last }),
18571
+ JSON.stringify({ group, archiveState, sourceType, sourceId, last }),
17581
18572
  "utf8"
17582
18573
  ).toString("base64url");
17583
18574
  }
@@ -17601,29 +18592,39 @@ function encodeLiveSessionCursor(last) {
17601
18592
  return Buffer.from(JSON.stringify(last), "utf8").toString("base64url");
17602
18593
  }
17603
18594
  __name(encodeLiveSessionCursor, "encodeLiveSessionCursor");
17604
- function parseParentSessionCursor(cursor, expected) {
18595
+ function matchesSessionMetadataSource(session, filter) {
18596
+ const sourceTypeMatches = filter.sourceType === void 0 || session.sourceType === filter.sourceType || // Legacy sessions without source metadata belong to the default catalog.
18597
+ filter.sourceType === "default" && session.sourceType === void 0;
18598
+ return sourceTypeMatches && // sourceId remains exact; only the default source type has legacy fallback.
18599
+ (filter.sourceId === void 0 || session.sourceId === filter.sourceId);
18600
+ }
18601
+ __name(matchesSessionMetadataSource, "matchesSessionMetadataSource");
18602
+ function parseMetadataSessionCursor(cursor, expected) {
17605
18603
  if (cursor === "") return void 0;
17606
18604
  try {
17607
18605
  const parsed = JSON.parse(
17608
18606
  Buffer.from(cursor, "base64url").toString("utf8")
17609
18607
  );
17610
18608
  const last = parsed.last;
17611
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.parentSessionId !== expected.parentSessionId || parsed.archiveState !== expected.archiveState) {
17612
- throw new Error("invalid parent cursor");
18609
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof last !== "object" || last === null || Array.isArray(last) || typeof last.activityTime !== "number" || !Number.isFinite(last.activityTime) || typeof last.sessionId !== "string" || last.sessionId.length === 0 || parsed.parentSessionId !== expected.parentSessionId || parsed.sourceType !== expected.sourceType || parsed.sourceId !== expected.sourceId || parsed.archiveState !== expected.archiveState) {
18610
+ throw new Error("invalid metadata cursor");
17613
18611
  }
17614
18612
  return { activityTime: last.activityTime, sessionId: last.sessionId };
17615
18613
  } catch {
17616
- throw new InvalidCursorError(cursor, "parent");
18614
+ throw new InvalidCursorError(
18615
+ cursor,
18616
+ expected.sourceType === void 0 ? "parent" : "metadata"
18617
+ );
17617
18618
  }
17618
18619
  }
17619
- __name(parseParentSessionCursor, "parseParentSessionCursor");
17620
- function encodeParentSessionCursor(last, parentSessionId, archiveState) {
18620
+ __name(parseMetadataSessionCursor, "parseMetadataSessionCursor");
18621
+ function encodeMetadataSessionCursor(last, filter, archiveState) {
17621
18622
  return Buffer.from(
17622
- JSON.stringify({ parentSessionId, archiveState, last }),
18623
+ JSON.stringify({ ...filter, archiveState, last }),
17623
18624
  "utf8"
17624
18625
  ).toString("base64url");
17625
18626
  }
17626
- __name(encodeParentSessionCursor, "encodeParentSessionCursor");
18627
+ __name(encodeMetadataSessionCursor, "encodeMetadataSessionCursor");
17627
18628
  function toSummary2(item) {
17628
18629
  return {
17629
18630
  sessionId: item.sessionId,
@@ -17632,6 +18633,8 @@ function toSummary2(item) {
17632
18633
  updatedAt: new Date(item.mtime).toISOString(),
17633
18634
  displayName: item.customTitle || item.prompt,
17634
18635
  ...item.parentSessionId ? { parentSessionId: item.parentSessionId } : {},
18636
+ ...item.sourceType ? { sourceType: item.sourceType } : {},
18637
+ ...item.sourceId !== void 0 ? { sourceId: item.sourceId } : {},
17635
18638
  clientCount: 0,
17636
18639
  hasActivePrompt: false,
17637
18640
  isArchived: item.isArchived === true
@@ -17647,6 +18650,8 @@ function mergeLiveSessionSummary(existing, live) {
17647
18650
  // Immutable lineage; the persisted transcript is authoritative, and a live
17648
18651
  // entry only carries it when spawned this run.
17649
18652
  parentSessionId: existing.parentSessionId ?? live.parentSessionId,
18653
+ sourceType: existing.sourceType ?? live.sourceType,
18654
+ sourceId: existing.sourceType !== void 0 ? existing.sourceId : live.sourceId,
17650
18655
  updatedAt: live.updatedAt ?? existing.updatedAt,
17651
18656
  clientCount: live.clientCount,
17652
18657
  hasActivePrompt: live.hasActivePrompt,
@@ -17746,7 +18751,12 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
17746
18751
  "group"
17747
18752
  );
17748
18753
  }
17749
- const cursorKey = options.cursor !== void 0 ? parseOrganizedCursor(options.cursor, { group, archiveState }) : void 0;
18754
+ const cursorKey = options.cursor !== void 0 ? parseOrganizedCursor(options.cursor, {
18755
+ group,
18756
+ archiveState,
18757
+ sourceType: options.sourceType,
18758
+ sourceId: options.sourceId
18759
+ }) : void 0;
17750
18760
  const isFirstPage = cursorKey === void 0;
17751
18761
  let liveMergeFailed = false;
17752
18762
  const bySessionId = /* @__PURE__ */ new Map();
@@ -17798,6 +18808,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
17798
18808
  }
17799
18809
  }
17800
18810
  const filtered = [...bySessionId.values()].filter((session) => {
18811
+ if (!matchesSessionMetadataSource(session, options)) return false;
17801
18812
  if (group === "all") return true;
17802
18813
  if (group === "pinned") return session.isPinned === true;
17803
18814
  if (group === "ungrouped")
@@ -17821,7 +18832,9 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
17821
18832
  const nextCursor = page.length < afterCursor.length ? encodeOrganizedCursor(
17822
18833
  getOrganizedCursorKey(activityTimeById, page[page.length - 1]),
17823
18834
  group,
17824
- archiveState
18835
+ archiveState,
18836
+ options.sourceType,
18837
+ options.sourceId
17825
18838
  ) : void 0;
17826
18839
  return {
17827
18840
  sessions: page,
@@ -17831,7 +18844,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
17831
18844
  };
17832
18845
  }
17833
18846
  __name(listOrganizedWorkspaceSessionsForResponse, "listOrganizedWorkspaceSessionsForResponse");
17834
- async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, options, pageSize, parentSessionId, readOptions) {
18847
+ async function listWorkspaceSessionsByMetadataForResponse(bridge, workspaceCwd, options, pageSize, filter, readOptions) {
17835
18848
  const archiveState = options.archiveState ?? "active";
17836
18849
  const sessionService = new SessionService(workspaceCwd);
17837
18850
  const bySessionId = /* @__PURE__ */ new Map();
@@ -17865,18 +18878,20 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
17865
18878
  } catch (error2) {
17866
18879
  liveMergeFailed = true;
17867
18880
  writeStderrLine(
17868
- `qwen serve: session-by-parent live merge failed; using persisted sessions only: ${error2 instanceof Error ? error2.message : String(error2)}`
18881
+ `qwen serve: session metadata filter live merge failed; using persisted sessions only: ${error2 instanceof Error ? error2.message : String(error2)}`
17869
18882
  );
17870
18883
  }
17871
18884
  }
17872
- const matches = [...bySessionId.values()].filter((session) => session.parentSessionId === parentSessionId).sort(
18885
+ const matches = [...bySessionId.values()].filter(
18886
+ (session) => (filter.parentSessionId === void 0 || session.parentSessionId === filter.parentSessionId) && matchesSessionMetadataSource(session, filter)
18887
+ ).sort(
17873
18888
  (a, b) => compareLiveSessionCursorKeys(
17874
18889
  getLiveSessionCursorKey(a),
17875
18890
  getLiveSessionCursorKey(b)
17876
18891
  )
17877
18892
  );
17878
- const cursorKey = options.cursor !== void 0 && options.cursor !== "" ? parseParentSessionCursor(options.cursor, {
17879
- parentSessionId,
18893
+ const cursorKey = options.cursor !== void 0 && options.cursor !== "" ? parseMetadataSessionCursor(options.cursor, {
18894
+ ...filter,
17880
18895
  archiveState
17881
18896
  }) : void 0;
17882
18897
  const afterCursor = cursorKey === void 0 ? matches : matches.filter(
@@ -17886,9 +18901,9 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
17886
18901
  ) < 0
17887
18902
  );
17888
18903
  const page = afterCursor.slice(0, pageSize);
17889
- const nextCursor = page.length < afterCursor.length ? encodeParentSessionCursor(
18904
+ const nextCursor = page.length < afterCursor.length ? encodeMetadataSessionCursor(
17890
18905
  getLiveSessionCursorKey(page[page.length - 1]),
17891
- parentSessionId,
18906
+ filter,
17892
18907
  archiveState
17893
18908
  ) : void 0;
17894
18909
  return {
@@ -17898,7 +18913,7 @@ async function listWorkspaceSessionsByParentForResponse(bridge, workspaceCwd, op
17898
18913
  ...persisted.truncated ? { truncated: true } : {}
17899
18914
  };
17900
18915
  }
17901
- __name(listWorkspaceSessionsByParentForResponse, "listWorkspaceSessionsByParentForResponse");
18916
+ __name(listWorkspaceSessionsByMetadataForResponse, "listWorkspaceSessionsByMetadataForResponse");
17902
18917
  async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, readOptions = {}) {
17903
18918
  const rawSize = options?.size;
17904
18919
  const requestedSize = typeof rawSize === "number" && Number.isSafeInteger(rawSize) ? rawSize : DEFAULT_SESSION_PAGE_SIZE;
@@ -17912,13 +18927,17 @@ async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, r
17912
18927
  readOptions
17913
18928
  );
17914
18929
  }
17915
- if (options?.parentSessionId !== void 0) {
17916
- return listWorkspaceSessionsByParentForResponse(
18930
+ if (options?.parentSessionId !== void 0 || options?.sourceType !== void 0) {
18931
+ return listWorkspaceSessionsByMetadataForResponse(
17917
18932
  bridge,
17918
18933
  workspaceCwd,
17919
18934
  options,
17920
18935
  pageSize,
17921
- options.parentSessionId,
18936
+ {
18937
+ ...options.parentSessionId !== void 0 ? { parentSessionId: options.parentSessionId } : {},
18938
+ ...options.sourceType !== void 0 ? { sourceType: options.sourceType } : {},
18939
+ ...options.sourceId !== void 0 ? { sourceId: options.sourceId } : {}
18940
+ },
17922
18941
  readOptions
17923
18942
  );
17924
18943
  }
@@ -17992,6 +19011,19 @@ function listLiveWorkspaceSessionsForResponse(bridge, workspaceCwd, options) {
17992
19011
  };
17993
19012
  }
17994
19013
  __name(listLiveWorkspaceSessionsForResponse, "listLiveWorkspaceSessionsForResponse");
19014
+ async function getWorkspaceSessionInfoForResponse(bridge, workspaceCwd, options = {}) {
19015
+ const counts = await new SessionService(workspaceCwd).getSessionInfoCounts();
19016
+ return {
19017
+ active: counts.active,
19018
+ archived: counts.archived,
19019
+ total: counts.total,
19020
+ ...options.includeLive === false ? {} : { live: bridge.listWorkspaceSessions(workspaceCwd).length },
19021
+ expensive: true,
19022
+ cost: "disk_scan",
19023
+ ...counts.truncated ? { truncated: true } : {}
19024
+ };
19025
+ }
19026
+ __name(getWorkspaceSessionInfoForResponse, "getWorkspaceSessionInfoForResponse");
17995
19027
  function parseSessionPageSizeQuery(raw) {
17996
19028
  if (typeof raw !== "string") return void 0;
17997
19029
  const trimmed = raw.trim();
@@ -18036,9 +19068,10 @@ function sessionExportFormatValues() {
18036
19068
  __name(sessionExportFormatValues, "sessionExportFormatValues");
18037
19069
  async function exportSessionTranscript(params) {
18038
19070
  const { workspaceCwd, sessionId, format } = params;
18039
- const sessionData = await new SessionService(workspaceCwd).loadSession(
18040
- sessionId
18041
- );
19071
+ const service = new SessionService(workspaceCwd);
19072
+ const sessionData = params.archiveState === "archived" ? await service.loadArchivedSession(sessionId, {
19073
+ maxBytes: SESSION_TRANSCRIPT_MAX_INDEX_BYTES
19074
+ }) : await service.loadSession(sessionId);
18042
19075
  if (!sessionData) {
18043
19076
  throw new SessionNotFoundError(sessionId);
18044
19077
  }
@@ -18063,10 +19096,63 @@ async function exportSessionTranscript(params) {
18063
19096
  __name(exportSessionTranscript, "exportSessionTranscript");
18064
19097
 
18065
19098
  // packages/cli/src/serve/routes/session.ts
18066
- var WORKSPACE_TRANSCRIPT_PAGE_SOURCE_MAX_BYTES = 4 * 1024 * 1024;
18067
19099
  var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
18068
19100
  var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
18069
19101
  var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
19102
+ var GENERATION_HEARTBEAT_MS = 15e3;
19103
+ var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
19104
+ "POST /session/:id/branch",
19105
+ "POST /session/:id/fork",
19106
+ "POST /session/:id/cd"
19107
+ ];
19108
+ function isPrimaryOnlyLiveSessionRoute(route) {
19109
+ return PRIMARY_ONLY_LIVE_SESSION_ROUTES.includes(
19110
+ route
19111
+ );
19112
+ }
19113
+ __name(isPrimaryOnlyLiveSessionRoute, "isPrimaryOnlyLiveSessionRoute");
19114
+ function formatGenerationSse(event, data) {
19115
+ return `event: ${event}
19116
+ data: ${JSON.stringify({ v: 1, ...data })}
19117
+
19118
+ `;
19119
+ }
19120
+ __name(formatGenerationSse, "formatGenerationSse");
19121
+ function writeGenerationSseChunk(res, chunk) {
19122
+ if (res.destroyed) {
19123
+ return Promise.reject(new Error("Generation SSE connection destroyed"));
19124
+ }
19125
+ const writable = res.write(chunk);
19126
+ const flush = res.flush;
19127
+ flush?.call(res);
19128
+ if (writable) {
19129
+ return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
19130
+ }
19131
+ return new Promise((resolve5, reject) => {
19132
+ const cleanup = /* @__PURE__ */ __name(() => {
19133
+ res.off("drain", onDrain);
19134
+ res.off("close", onClose);
19135
+ res.off("error", onError);
19136
+ }, "cleanup");
19137
+ const onDrain = /* @__PURE__ */ __name(() => {
19138
+ cleanup();
19139
+ resolve5();
19140
+ }, "onDrain");
19141
+ const onClose = /* @__PURE__ */ __name(() => {
19142
+ cleanup();
19143
+ reject(new Error("Generation SSE connection closed"));
19144
+ }, "onClose");
19145
+ const onError = /* @__PURE__ */ __name((error2) => {
19146
+ cleanup();
19147
+ reject(error2);
19148
+ }, "onError");
19149
+ res.once("drain", onDrain);
19150
+ res.once("close", onClose);
19151
+ res.once("error", onError);
19152
+ if (res.destroyed) onClose();
19153
+ });
19154
+ }
19155
+ __name(writeGenerationSseChunk, "writeGenerationSseChunk");
18070
19156
  function isReadOnlyWorkspaceInspection(runtime) {
18071
19157
  return !runtime.primary && !runtime.trusted;
18072
19158
  }
@@ -18153,6 +19239,32 @@ function parseTranscriptCursorQuery(rawCursor, res) {
18153
19239
  return rawCursor;
18154
19240
  }
18155
19241
  __name(parseTranscriptCursorQuery, "parseTranscriptCursorQuery");
19242
+ function parseTranscriptRecordBoundaryQuery(rawBoundary, res) {
19243
+ if (rawBoundary === void 0) return void 0;
19244
+ if (typeof rawBoundary !== "string" || rawBoundary.trim() === "" || rawBoundary.length > 200) {
19245
+ res.status(400).json({
19246
+ error: "`beforeRecordId` must be a non-empty record id",
19247
+ code: "invalid_transcript_cursor"
19248
+ });
19249
+ return null;
19250
+ }
19251
+ return rawBoundary;
19252
+ }
19253
+ __name(parseTranscriptRecordBoundaryQuery, "parseTranscriptRecordBoundaryQuery");
19254
+ function parseHistoryPageSize(body, res) {
19255
+ const value = body["historyPageSize"];
19256
+ if (value === void 0) return void 0;
19257
+ if (!Number.isSafeInteger(value) || value < 1 || value > SESSION_TRANSCRIPT_MAX_LIMIT) {
19258
+ res.status(400).json({
19259
+ error: `\`historyPageSize\` must be between 1 and ${SESSION_TRANSCRIPT_MAX_LIMIT}`,
19260
+ code: "invalid_transcript_limit",
19261
+ maxLimit: SESSION_TRANSCRIPT_MAX_LIMIT
19262
+ });
19263
+ return null;
19264
+ }
19265
+ return value;
19266
+ }
19267
+ __name(parseHistoryPageSize, "parseHistoryPageSize");
18156
19268
  function workspaceTranscriptCursorExceedsLimit(cursor, maxBytes = WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES) {
18157
19269
  return Buffer.byteLength(cursor) > maxBytes;
18158
19270
  }
@@ -18212,14 +19324,14 @@ function registerSessionRoutes(app, deps) {
18212
19324
  sessionShellCommandEnabled
18213
19325
  } = deps;
18214
19326
  const LANGUAGE_CODES = deps.languageCodes;
18215
- const transcriptCursorMasterKey = crypto2.randomBytes(32);
19327
+ const transcriptCursorMasterKey = crypto3.randomBytes(32);
18216
19328
  const transcriptCursorCodecs = /* @__PURE__ */ new Map();
18217
19329
  const getTranscriptCursorCodec = /* @__PURE__ */ __name((runtime) => {
18218
19330
  const canonicalCwd = canonicalizeWorkspace(runtime.workspaceCwd);
18219
19331
  const cacheKey = `${runtime.workspaceId}\0${canonicalCwd}`;
18220
19332
  const cached = transcriptCursorCodecs.get(cacheKey);
18221
19333
  if (cached) return cached;
18222
- const derivedKey = crypto2.hkdfSync(
19334
+ const derivedKey = crypto3.hkdfSync(
18223
19335
  "sha256",
18224
19336
  transcriptCursorMasterKey,
18225
19337
  Buffer.alloc(0),
@@ -18274,6 +19386,7 @@ function registerSessionRoutes(app, deps) {
18274
19386
  return void 0;
18275
19387
  }
18276
19388
  if (workspaceRegistry.list().length === 1) {
19389
+ setDaemonTelemetryWorkspace(res, workspaceRegistry.primary.workspaceCwd);
18277
19390
  return {
18278
19391
  runtime: workspaceRegistry.primary,
18279
19392
  workspaceCwd: "cwd" in body ? key : workspaceRegistry.primary.workspaceCwd
@@ -18289,6 +19402,7 @@ function registerSessionRoutes(app, deps) {
18289
19402
  sendWorkspaceMismatch2(res, key);
18290
19403
  return void 0;
18291
19404
  }
19405
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18292
19406
  if (!runtime.primary && !runtime.trusted) {
18293
19407
  logSessionRoutingFailure("POST /session", "untrusted_workspace", {
18294
19408
  workspaceId: runtime.workspaceId,
@@ -18397,11 +19511,16 @@ function registerSessionRoutes(app, deps) {
18397
19511
  const result = await archiveCoordinator.runSharedMany(
18398
19512
  [sessionId],
18399
19513
  async () => {
18400
- await assertSessionLoadable(target.workspaceCwd, sessionId);
19514
+ if (target.archiveState === "archived") {
19515
+ await assertSessionArchived(target.workspaceCwd, sessionId);
19516
+ } else {
19517
+ await assertSessionLoadable(target.workspaceCwd, sessionId);
19518
+ }
18401
19519
  return exportSessionTranscript({
18402
19520
  workspaceCwd: target.workspaceCwd,
18403
19521
  sessionId,
18404
19522
  format,
19523
+ archiveState: target.archiveState,
18405
19524
  config: { getChannel: /* @__PURE__ */ __name(() => "daemon", "getChannel") }
18406
19525
  });
18407
19526
  }
@@ -18536,6 +19655,7 @@ function registerSessionRoutes(app, deps) {
18536
19655
  sendWorkspaceMismatch2(res, key);
18537
19656
  return void 0;
18538
19657
  }
19658
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18539
19659
  if (!runtime.primary && !runtime.trusted) {
18540
19660
  logSessionRoutingFailure(route, "untrusted_workspace", {
18541
19661
  workspaceId: runtime.workspaceId,
@@ -18573,7 +19693,7 @@ function registerSessionRoutes(app, deps) {
18573
19693
  }), "resolveLiveSessionRuntime");
18574
19694
  const sendNonPrimarySessionRouteUnsupported = /* @__PURE__ */ __name((res, route, sessionId, runtime) => {
18575
19695
  res.status(400).json({
18576
- error: `Route "${route}" is primary-only for non-primary workspace sessions in Phase 2a.`,
19696
+ error: `Route "${route}" is only available for primary workspace sessions.`,
18577
19697
  code: "non_primary_session_route_not_supported",
18578
19698
  sessionId,
18579
19699
  workspaceId: runtime.workspaceId,
@@ -18621,6 +19741,7 @@ function registerSessionRoutes(app, deps) {
18621
19741
  }, "throwMissingActiveTranscript");
18622
19742
  if (workspaceRegistry.list().length === 1) {
18623
19743
  const runtime = workspaceRegistry.primary;
19744
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18624
19745
  if (await activeInRuntime(runtime)) {
18625
19746
  return runtime;
18626
19747
  }
@@ -18632,6 +19753,7 @@ function registerSessionRoutes(app, deps) {
18632
19753
  return void 0;
18633
19754
  }
18634
19755
  if (liveOwner.kind === "found") {
19756
+ setDaemonTelemetryWorkspace(res, liveOwner.runtime.workspaceCwd);
18635
19757
  if (!assertTrustedSessionOwner(res, route, sessionId, liveOwner.runtime)) {
18636
19758
  return void 0;
18637
19759
  }
@@ -18666,6 +19788,7 @@ function registerSessionRoutes(app, deps) {
18666
19788
  }
18667
19789
  if (activeRuntimes.length === 1) {
18668
19790
  const runtime = activeRuntimes[0];
19791
+ setDaemonTelemetryWorkspace(res, runtime.workspaceCwd);
18669
19792
  if (!assertTrustedSessionOwner(res, route, sessionId, runtime)) {
18670
19793
  return void 0;
18671
19794
  }
@@ -18722,23 +19845,37 @@ function registerSessionRoutes(app, deps) {
18722
19845
  }
18723
19846
  return key;
18724
19847
  }, "resolveWorkspaceParam");
18725
- const withMutableSession = /* @__PURE__ */ __name((route, handler) => async (req, res) => {
18726
- const sessionId = requireSessionId(req, res);
18727
- if (sessionId === null) return;
18728
- const runtime = resolveLiveSessionRuntime(sessionId, res, route);
18729
- if (!runtime) return;
18730
- if (!runtime.primary) {
18731
- sendNonPrimarySessionRouteUnsupported(res, route, sessionId, runtime);
18732
- return;
18733
- }
18734
- try {
18735
- await archiveCoordinator.runSharedMany([sessionId], async () => {
18736
- await handler(req, res, sessionId);
18737
- });
18738
- } catch (err) {
18739
- sendBridgeError2(res, err, { route, sessionId });
19848
+ const withPrimaryOnlyMutableSession = /* @__PURE__ */ __name((route, handler) => {
19849
+ if (!isPrimaryOnlyLiveSessionRoute(route)) {
19850
+ throw new Error(`Unregistered primary-only session route: ${route}`);
18740
19851
  }
18741
- }, "withMutableSession");
19852
+ return async (req, res) => {
19853
+ const sessionId = requireSessionId(req, res);
19854
+ if (sessionId === null) return;
19855
+ const runtime = resolveLiveSessionRuntime(sessionId, res, route);
19856
+ if (!runtime) return;
19857
+ if (!runtime.primary) {
19858
+ logSessionRoutingFailure(
19859
+ route,
19860
+ "non_primary_session_route_not_supported",
19861
+ {
19862
+ sessionId,
19863
+ workspaceId: runtime.workspaceId,
19864
+ workspaceCwd: runtime.workspaceCwd
19865
+ }
19866
+ );
19867
+ sendNonPrimarySessionRouteUnsupported(res, route, sessionId, runtime);
19868
+ return;
19869
+ }
19870
+ try {
19871
+ await archiveCoordinator.runSharedMany([sessionId], async () => {
19872
+ await handler(req, res, sessionId);
19873
+ });
19874
+ } catch (err) {
19875
+ sendBridgeError2(res, err, { route, sessionId });
19876
+ }
19877
+ };
19878
+ }, "withPrimaryOnlyMutableSession");
18742
19879
  app.post("/session", mutate(), async (req, res) => {
18743
19880
  const body = safeBody(req);
18744
19881
  const resolvedRuntime = resolveRuntimeForSessionCreation(body, res);
@@ -18759,6 +19896,14 @@ function registerSessionRoutes(app, deps) {
18759
19896
  }
18760
19897
  const approvalMode = parseOptionalApprovalMode(body, res);
18761
19898
  if (approvalMode === null) return;
19899
+ const source = parseSessionSource(body["sourceType"], body["sourceId"]);
19900
+ if ("error" in source) {
19901
+ res.status(400).json({
19902
+ error: source.error,
19903
+ code: "invalid_session_source"
19904
+ });
19905
+ return;
19906
+ }
18762
19907
  const clientId = parseClientIdHeader(req, res);
18763
19908
  if (clientId === null) return;
18764
19909
  try {
@@ -18767,7 +19912,9 @@ function registerSessionRoutes(app, deps) {
18767
19912
  modelServiceId,
18768
19913
  ...clientId !== void 0 ? { clientId } : {},
18769
19914
  ...sessionScope !== void 0 ? { sessionScope } : {},
18770
- ...approvalMode !== void 0 ? { approvalMode } : {}
19915
+ ...approvalMode !== void 0 ? { approvalMode } : {},
19916
+ ...source.sourceType !== void 0 ? { sourceType: source.sourceType } : {},
19917
+ ...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {}
18771
19918
  });
18772
19919
  if (daemonLog) {
18773
19920
  daemonLog.info(
@@ -18786,8 +19933,17 @@ function registerSessionRoutes(app, deps) {
18786
19933
  );
18787
19934
  }
18788
19935
  if (!session.attached) {
18789
- runtime.bridge.killSession(session.sessionId, { requireZeroAttaches: true }).catch(() => {
18790
- });
19936
+ try {
19937
+ const killed = await runtime.bridge.killSession(session.sessionId, {
19938
+ requireZeroAttaches: true
19939
+ });
19940
+ if (killed) {
19941
+ await new SessionService(runtime.workspaceCwd).removeSession(
19942
+ session.sessionId
19943
+ );
19944
+ }
19945
+ } catch {
19946
+ }
18791
19947
  } else {
18792
19948
  runtime.bridge.detachClient(session.sessionId, session.clientId).catch(() => {
18793
19949
  });
@@ -18830,6 +19986,11 @@ function registerSessionRoutes(app, deps) {
18830
19986
  releaseRestoreOwner();
18831
19987
  return;
18832
19988
  }
19989
+ const historyPageSize = action === "load" ? parseHistoryPageSize(body ?? {}, res) : void 0;
19990
+ if (historyPageSize === null) {
19991
+ releaseRestoreOwner();
19992
+ return;
19993
+ }
18833
19994
  const clientId = parseClientIdHeader(req, res);
18834
19995
  if (clientId === null) {
18835
19996
  releaseRestoreOwner();
@@ -18840,22 +20001,23 @@ function registerSessionRoutes(app, deps) {
18840
20001
  [sessionId],
18841
20002
  async () => {
18842
20003
  await assertSessionLoadable(workspaceCwd, sessionId);
18843
- const parentSessionId = await new SessionService(
20004
+ const metadata = await new SessionService(
18844
20005
  workspaceCwd
18845
- ).readParentSessionId(sessionId);
20006
+ ).readCreationMetadata(sessionId);
18846
20007
  return action === "load" ? await runtime.bridge.loadSession({
18847
20008
  sessionId,
18848
20009
  workspaceCwd,
18849
20010
  historyReplay: "response",
20011
+ ...historyPageSize !== void 0 ? { historyPageSize } : {},
18850
20012
  ...clientId !== void 0 ? { clientId } : {},
18851
20013
  ...approvalMode !== void 0 ? { approvalMode } : {},
18852
- ...parentSessionId !== void 0 ? { parentSessionId } : {}
20014
+ ...metadata
18853
20015
  }) : await runtime.bridge.resumeSession({
18854
20016
  sessionId,
18855
20017
  workspaceCwd,
18856
20018
  ...clientId !== void 0 ? { clientId } : {},
18857
20019
  ...approvalMode !== void 0 ? { approvalMode } : {},
18858
- ...parentSessionId !== void 0 ? { parentSessionId } : {}
20020
+ ...metadata
18859
20021
  });
18860
20022
  }
18861
20023
  );
@@ -18890,7 +20052,7 @@ function registerSessionRoutes(app, deps) {
18890
20052
  app.post(
18891
20053
  "/session/:id/branch",
18892
20054
  mutate(),
18893
- withMutableSession(
20055
+ withPrimaryOnlyMutableSession(
18894
20056
  "POST /session/:id/branch",
18895
20057
  async (req, res, sessionId) => {
18896
20058
  const body = safeBody(req);
@@ -18925,7 +20087,7 @@ function registerSessionRoutes(app, deps) {
18925
20087
  app.post(
18926
20088
  "/session/:id/fork",
18927
20089
  mutate(),
18928
- withMutableSession(
20090
+ withPrimaryOnlyMutableSession(
18929
20091
  "POST /session/:id/fork",
18930
20092
  async (req, res, sessionId) => {
18931
20093
  const body = safeBody(req);
@@ -18951,25 +20113,28 @@ function registerSessionRoutes(app, deps) {
18951
20113
  app.post(
18952
20114
  "/session/:id/cd",
18953
20115
  mutate(),
18954
- withMutableSession("POST /session/:id/cd", async (req, res, sessionId) => {
18955
- const body = safeBody(req);
18956
- const targetPath = body["path"];
18957
- if (typeof targetPath !== "string" || targetPath.length === 0 || !path11.isAbsolute(targetPath)) {
18958
- res.status(400).json({
18959
- error: "`path` is required and must be an absolute path",
18960
- code: "invalid_path"
18961
- });
18962
- return;
20116
+ withPrimaryOnlyMutableSession(
20117
+ "POST /session/:id/cd",
20118
+ async (req, res, sessionId) => {
20119
+ const body = safeBody(req);
20120
+ const targetPath = body["path"];
20121
+ if (typeof targetPath !== "string" || targetPath.length === 0 || !path11.isAbsolute(targetPath)) {
20122
+ res.status(400).json({
20123
+ error: "`path` is required and must be an absolute path",
20124
+ code: "invalid_path"
20125
+ });
20126
+ return;
20127
+ }
20128
+ const clientId = parseClientIdHeader(req, res);
20129
+ if (clientId === null) return;
20130
+ const result = await bridge.changeSessionCwd(
20131
+ sessionId,
20132
+ { path: targetPath },
20133
+ clientId !== void 0 ? { clientId } : void 0
20134
+ );
20135
+ res.status(200).json(result);
18963
20136
  }
18964
- const clientId = parseClientIdHeader(req, res);
18965
- if (clientId === null) return;
18966
- const result = await bridge.changeSessionCwd(
18967
- sessionId,
18968
- { path: targetPath },
18969
- clientId !== void 0 ? { clientId } : void 0
18970
- );
18971
- res.status(200).json(result);
18972
- })
20137
+ )
18973
20138
  );
18974
20139
  app.get("/session/:id/status", (req, res) => {
18975
20140
  const sessionId = requireSessionId(req, res);
@@ -19005,6 +20170,20 @@ function registerSessionRoutes(app, deps) {
19005
20170
  workspaceQualified: true
19006
20171
  });
19007
20172
  });
20173
+ app.get(
20174
+ "/workspaces/:workspace/session/:id/archive/export",
20175
+ async (req, res) => {
20176
+ const route = "GET /workspaces/:workspace/session/:id/archive/export";
20177
+ const runtime = requireTrustedRuntimeForWorkspaceRoute(req, res, route);
20178
+ if (!runtime) return;
20179
+ await handleSessionExport(req, res, {
20180
+ route,
20181
+ workspaceCwd: runtime.workspaceCwd,
20182
+ workspaceQualified: true,
20183
+ archiveState: "archived"
20184
+ });
20185
+ }
20186
+ );
19008
20187
  app.get("/session/:id/transcript", async (req, res) => {
19009
20188
  const route = "GET /session/:id/transcript";
19010
20189
  const sessionId = requireSessionId(req, res);
@@ -19013,6 +20192,18 @@ function registerSessionRoutes(app, deps) {
19013
20192
  if (limit === null) return;
19014
20193
  const cursor = parseTranscriptCursorQuery(req.query["cursor"], res);
19015
20194
  if (cursor === null) return;
20195
+ const beforeRecordId = parseTranscriptRecordBoundaryQuery(
20196
+ req.query["beforeRecordId"],
20197
+ res
20198
+ );
20199
+ if (beforeRecordId === null) return;
20200
+ if (cursor !== void 0 && beforeRecordId !== void 0) {
20201
+ res.status(400).json({
20202
+ error: "`cursor` and `beforeRecordId` are mutually exclusive",
20203
+ code: "invalid_transcript_cursor"
20204
+ });
20205
+ return;
20206
+ }
19016
20207
  try {
19017
20208
  const result = await archiveCoordinator.runSharedMany(
19018
20209
  [sessionId],
@@ -19027,7 +20218,8 @@ function registerSessionRoutes(app, deps) {
19027
20218
  return runtime.bridge.getSessionTranscriptPage({
19028
20219
  sessionId,
19029
20220
  ...limit !== void 0 ? { limit } : {},
19030
- ...cursor !== void 0 ? { cursor } : {}
20221
+ ...cursor !== void 0 ? { cursor } : {},
20222
+ ...beforeRecordId !== void 0 ? { beforeRecordId } : {}
19031
20223
  });
19032
20224
  }
19033
20225
  );
@@ -19062,6 +20254,18 @@ function registerSessionRoutes(app, deps) {
19062
20254
  if (limit === null) return;
19063
20255
  const cursor = parseTranscriptCursorQuery(req.query["cursor"], res);
19064
20256
  if (cursor === null) return;
20257
+ const beforeRecordId = parseTranscriptRecordBoundaryQuery(
20258
+ req.query["beforeRecordId"],
20259
+ res
20260
+ );
20261
+ if (beforeRecordId === null) return;
20262
+ if (cursor !== void 0 && beforeRecordId !== void 0) {
20263
+ res.status(400).json({
20264
+ error: "`cursor` and `beforeRecordId` are mutually exclusive",
20265
+ code: "invalid_transcript_cursor"
20266
+ });
20267
+ return;
20268
+ }
19065
20269
  if (cursor !== void 0 && workspaceTranscriptCursorExceedsLimit(cursor)) {
19066
20270
  res.status(400).json({
19067
20271
  error: "`cursor` exceeds the maximum size",
@@ -19086,7 +20290,8 @@ function registerSessionRoutes(app, deps) {
19086
20290
  page = await reader.readPage(sessionId, {
19087
20291
  ...limit !== void 0 ? { limit } : {},
19088
20292
  ...cursor !== void 0 ? { cursor } : {},
19089
- maxBytes: WORKSPACE_TRANSCRIPT_PAGE_SOURCE_MAX_BYTES
20293
+ ...beforeRecordId !== void 0 ? { beforeRecordId } : {},
20294
+ maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
19090
20295
  });
19091
20296
  } catch (error2) {
19092
20297
  if (error2.code !== "ENOENT") {
@@ -19348,7 +20553,7 @@ function registerSessionRoutes(app, deps) {
19348
20553
  async (req, res, sessionId, runtime) => {
19349
20554
  const clientId = parseClientIdHeader(req, res);
19350
20555
  if (clientId === null) return;
19351
- const promptId = crypto2.randomUUID();
20556
+ const promptId = crypto3.randomUUID();
19352
20557
  res.status(200).json(
19353
20558
  await runtime.bridge.continueSession(sessionId, {
19354
20559
  ...clientId !== void 0 ? { clientId } : {},
@@ -19395,7 +20600,7 @@ function registerSessionRoutes(app, deps) {
19395
20600
  }
19396
20601
  const clientId = parseClientIdHeader(req, res);
19397
20602
  if (clientId === null) return;
19398
- const promptId = crypto2.randomUUID();
20603
+ const promptId = crypto3.randomUUID();
19399
20604
  const forwardedBody = { ...body };
19400
20605
  delete forwardedBody["deadlineMs"];
19401
20606
  const lastEventId = ownerBridge.getSessionLastEventId(sessionId);
@@ -19496,6 +20701,88 @@ function registerSessionRoutes(app, deps) {
19496
20701
  }
19497
20702
  )
19498
20703
  );
20704
+ app.post(
20705
+ "/session/:id/generate",
20706
+ mutate(),
20707
+ withOwnerReadSession(
20708
+ "POST /session/:id/generate",
20709
+ async (req, res, sessionId, runtime) => {
20710
+ const body = safeBody(req);
20711
+ const prompt = body["prompt"];
20712
+ if (typeof prompt !== "string" || prompt.trim().length === 0 || Buffer.byteLength(prompt, "utf8") > GENERATION_MAX_PROMPT_BYTES) {
20713
+ res.status(400).json({
20714
+ error: `\`prompt\` must be a non-empty string no larger than ${GENERATION_MAX_PROMPT_BYTES} UTF-8 bytes`,
20715
+ code: "invalid_prompt"
20716
+ });
20717
+ return;
20718
+ }
20719
+ const clientId = parseClientIdHeader(req, res);
20720
+ if (clientId === null) return;
20721
+ if (!runtime.bridge.generateSessionContent) {
20722
+ res.status(501).json({
20723
+ error: "Stateless generation is not supported by this bridge",
20724
+ code: "generation_not_supported"
20725
+ });
20726
+ return;
20727
+ }
20728
+ const abort = new AbortController();
20729
+ let completed = false;
20730
+ const onClose = /* @__PURE__ */ __name(() => {
20731
+ if (!completed) abort.abort();
20732
+ }, "onClose");
20733
+ res.once("close", onClose);
20734
+ const stream = runtime.bridge.generateSessionContent(
20735
+ sessionId,
20736
+ prompt,
20737
+ abort.signal,
20738
+ clientId !== void 0 ? { clientId } : void 0
20739
+ );
20740
+ res.status(200);
20741
+ res.setHeader("Content-Type", "text/event-stream");
20742
+ res.setHeader("Cache-Control", "no-cache, no-transform");
20743
+ res.setHeader("Connection", "keep-alive");
20744
+ res.setHeader("X-Accel-Buffering", "no");
20745
+ res.flushHeaders();
20746
+ let writeChain = Promise.resolve();
20747
+ const write = /* @__PURE__ */ __name((chunk) => {
20748
+ writeChain = writeChain.then(
20749
+ () => writeGenerationSseChunk(res, chunk)
20750
+ );
20751
+ return writeChain;
20752
+ }, "write");
20753
+ await write(": connected\n\n");
20754
+ const heartbeat = setInterval(() => {
20755
+ void write(": heartbeat\n\n").catch(() => abort.abort());
20756
+ }, GENERATION_HEARTBEAT_MS);
20757
+ heartbeat.unref();
20758
+ try {
20759
+ for await (const event of stream) {
20760
+ await write(formatGenerationSse(event.type, event));
20761
+ }
20762
+ } catch (err) {
20763
+ if (!abort.signal.aborted && !res.destroyed) {
20764
+ daemonLog?.error(
20765
+ "session generation failed",
20766
+ err instanceof Error ? err : new Error(String(err)),
20767
+ { sessionId, clientId }
20768
+ );
20769
+ await write(
20770
+ formatGenerationSse("error", {
20771
+ type: "error",
20772
+ code: "generation_failed",
20773
+ message: "Generation failed"
20774
+ })
20775
+ ).catch(() => void 0);
20776
+ }
20777
+ } finally {
20778
+ completed = true;
20779
+ clearInterval(heartbeat);
20780
+ res.off("close", onClose);
20781
+ if (!res.destroyed) res.end();
20782
+ }
20783
+ }
20784
+ )
20785
+ );
19499
20786
  app.post(
19500
20787
  "/session/:id/heartbeat",
19501
20788
  mutate(),
@@ -20064,16 +21351,28 @@ function registerSessionRoutes(app, deps) {
20064
21351
  }
20065
21352
  parentSessionId = rawParentSessionId;
20066
21353
  }
21354
+ const parsedSource = parseSessionSource(
21355
+ req.query["sourceType"],
21356
+ req.query["sourceId"]
21357
+ );
21358
+ if ("error" in parsedSource) {
21359
+ res.status(400).json({
21360
+ error: parsedSource.error,
21361
+ code: "invalid_session_source"
21362
+ });
21363
+ return;
21364
+ }
20067
21365
  const options = {
20068
21366
  ...cursor !== void 0 ? { cursor } : {},
20069
21367
  ...size !== void 0 ? { size } : {},
20070
21368
  ...archiveState !== void 0 ? { archiveState } : {},
20071
21369
  ...view !== void 0 ? { view } : {},
20072
21370
  ...group !== void 0 ? { group } : {},
20073
- ...parentSessionId !== void 0 ? { parentSessionId } : {}
21371
+ ...parentSessionId !== void 0 ? { parentSessionId } : {},
21372
+ ...parsedSource
20074
21373
  };
20075
- const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(key));
20076
- if (!usePersisted && (view !== void 0 || archiveState === "archived")) {
21374
+ const usePersisted = readOnlySecondary || runtime.primary || view === "organized" || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0 || (cursor !== void 0 && cursor !== "" ? isNumericSessionCursor(cursor) : await hasActivePersistedSessions(key));
21375
+ if (!usePersisted && (view !== void 0 || archiveState === "archived" || parentSessionId !== void 0 || parsedSource.sourceType !== void 0)) {
20077
21376
  throw new Error(
20078
21377
  "session list live path received persisted-only options"
20079
21378
  );
@@ -20123,6 +21422,36 @@ function registerSessionRoutes(app, deps) {
20123
21422
  "/workspaces/:workspace/sessions",
20124
21423
  listWorkspaceSessionsHandler("workspace")
20125
21424
  );
21425
+ const workspaceSessionInfoHandler = /* @__PURE__ */ __name((paramName) => async (req, res) => {
21426
+ const route = paramName === "workspace" ? "GET /workspaces/:workspace/session-info" : "GET /workspace/:id/session-info";
21427
+ const runtime = resolveRuntimeForCatalogRoute(req, res, paramName, route);
21428
+ if (runtime === null) return;
21429
+ const key = runtime.workspaceCwd;
21430
+ try {
21431
+ const info = await runWorkspaceInspectionWithLogPolicy(
21432
+ runtime,
21433
+ () => getWorkspaceSessionInfoForResponse(runtime.bridge, key, {
21434
+ includeLive: !isReadOnlyWorkspaceInspection(runtime)
21435
+ })
21436
+ );
21437
+ res.status(200).json(info);
21438
+ } catch (err) {
21439
+ writeStderrLine(
21440
+ `qwen serve: failed to read session-info for workspace ${safeLogValue(
21441
+ key
21442
+ )}: ${safeLogValue(err instanceof Error ? err.message : String(err))}`
21443
+ );
21444
+ res.status(500).json({
21445
+ error: "Failed to read session info",
21446
+ code: "session_info_failed"
21447
+ });
21448
+ }
21449
+ }, "workspaceSessionInfoHandler");
21450
+ app.get("/workspace/:id/session-info", workspaceSessionInfoHandler("id"));
21451
+ app.get(
21452
+ "/workspaces/:workspace/session-info",
21453
+ workspaceSessionInfoHandler("workspace")
21454
+ );
20126
21455
  app.post(
20127
21456
  "/session/:id/model",
20128
21457
  mutate(),
@@ -20672,6 +22001,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
20672
22001
  }
20673
22002
  const recurring = body["recurring"] !== false;
20674
22003
  const enabled = body["enabled"] !== false;
22004
+ const taskId = generateCronTaskId();
20675
22005
  let boundSessionId;
20676
22006
  if (bridge) {
20677
22007
  try {
@@ -20687,7 +22017,9 @@ function registerScheduledTaskCrudRoutes(app, deps) {
20687
22017
  try {
20688
22018
  const session = await bridge.spawnOrAttach({
20689
22019
  workspaceCwd,
20690
- sessionScope: "thread"
22020
+ sessionScope: "thread",
22021
+ sourceType: "scheduled_task",
22022
+ sourceId: taskId
20691
22023
  });
20692
22024
  boundSessionId = session.sessionId;
20693
22025
  try {
@@ -20709,7 +22041,7 @@ function registerScheduledTaskCrudRoutes(app, deps) {
20709
22041
  }
20710
22042
  const now = Date.now();
20711
22043
  const task = {
20712
- id: generateCronTaskId(),
22044
+ id: taskId,
20713
22045
  cron,
20714
22046
  prompt,
20715
22047
  recurring,
@@ -21192,7 +22524,9 @@ async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawn
21192
22524
  binding.add(task.id);
21193
22525
  const rawSpawn = bridge.spawnOrAttach({
21194
22526
  workspaceCwd: boundWorkspace,
21195
- sessionScope: "thread"
22527
+ sessionScope: "thread",
22528
+ sourceType: "scheduled_task",
22529
+ sourceId: task.id
21196
22530
  });
21197
22531
  let timedOut = false;
21198
22532
  rawSpawn.then(({ sessionId: sessionId2 }) => {
@@ -21301,12 +22635,16 @@ function startScheduledTaskKeepalive(opts) {
21301
22635
  continue;
21302
22636
  }
21303
22637
  log.debug("keepalive: recordHeartbeat failed for", sessionId, err);
22638
+ reviving.add(sessionId);
22639
+ const metadata = await new SessionService(
22640
+ boundWorkspace
22641
+ ).readCreationMetadata(sessionId);
21304
22642
  const load = bridge.loadSession({
21305
22643
  sessionId,
21306
22644
  workspaceCwd: boundWorkspace,
21307
- historyReplay: "response"
22645
+ historyReplay: "response",
22646
+ ...metadata
21308
22647
  });
21309
- reviving.add(sessionId);
21310
22648
  void load.catch(() => {
21311
22649
  }).finally(() => {
21312
22650
  reviving.delete(sessionId);
@@ -21417,10 +22755,14 @@ async function rehydrateScheduledTaskSessions(deps) {
21417
22755
  const loaded = [];
21418
22756
  const failed = [];
21419
22757
  const loadOne = /* @__PURE__ */ __name(async (sessionId) => {
22758
+ const metadata = await new SessionService(
22759
+ boundWorkspace
22760
+ ).readCreationMetadata(sessionId);
21420
22761
  const load = bridge.loadSession({
21421
22762
  sessionId,
21422
22763
  workspaceCwd: boundWorkspace,
21423
- historyReplay: "response"
22764
+ historyReplay: "response",
22765
+ ...metadata
21424
22766
  });
21425
22767
  void load.catch(() => {
21426
22768
  });
@@ -21767,6 +23109,7 @@ function createServeFeatures(deps) {
21767
23109
  boundWorkspace,
21768
23110
  persistSettingAvailable,
21769
23111
  sessionArtifactsPersistenceAvailable,
23112
+ sessionGenerationAvailable,
21770
23113
  reloadAvailable,
21771
23114
  channelReloadAvailable,
21772
23115
  channelControlAvailable,
@@ -21800,6 +23143,7 @@ function createServeFeatures(deps) {
21800
23143
  persistSettingAvailable,
21801
23144
  sessionShellCommandEnabled,
21802
23145
  sessionArtifactsPersistenceAvailable,
23146
+ sessionGenerationAvailable: sessionGenerationAvailable(),
21803
23147
  rateLimit: opts.rateLimit === true,
21804
23148
  reloadAvailable,
21805
23149
  channelReloadAvailable: channelReloadAvailable(),
@@ -22089,6 +23433,7 @@ init_esbuild_shims();
22089
23433
  var TUI_ONLY_SETTINGS = /* @__PURE__ */ new Set([
22090
23434
  "general.vimMode",
22091
23435
  "general.terminalBell",
23436
+ "general.notificationMode",
22092
23437
  "general.preferredEditor",
22093
23438
  "general.outputLanguage",
22094
23439
  "ide.enabled",
@@ -22099,9 +23444,14 @@ var TUI_ONLY_SETTINGS = /* @__PURE__ */ new Set([
22099
23444
  "ui.accessibility.enableLoadingPhrases",
22100
23445
  "ui.enableWelcomeBack"
22101
23446
  ]);
22102
- var WEB_SHELL_SETTINGS = /* @__PURE__ */ new Set(["ui.compactMode", "voiceModel"]);
23447
+ var WEB_SHELL_SETTINGS = /* @__PURE__ */ new Set([
23448
+ "ui.compactMode",
23449
+ "voiceModel",
23450
+ "mcpServers"
23451
+ ]);
22103
23452
  var VALID_WRITE_SCOPES = /* @__PURE__ */ new Set(["workspace", "user"]);
22104
23453
  var QUALIFIED_WRITE_SCOPES = /* @__PURE__ */ new Set(["workspace"]);
23454
+ var mcpServerMutationQueues = /* @__PURE__ */ new Map();
22105
23455
  var SECURITY_SENSITIVE_SETTINGS = /* @__PURE__ */ new Set(["tools.approvalMode"]);
22106
23456
  function getAllowedKeys() {
22107
23457
  const keys = new Set(
@@ -22133,11 +23483,12 @@ function buildSettingsResponse(boundWorkspace, keys) {
22133
23483
  loaded.workspace.settings,
22134
23484
  key
22135
23485
  );
23486
+ const publicValue = /* @__PURE__ */ __name((value) => key === "mcpServers" ? redactMcpServersSetting(value) : value, "publicValue");
22136
23487
  const values = {
22137
- effective: effective !== void 0 ? effective : def.default
23488
+ effective: publicValue(effective !== void 0 ? effective : def.default)
22138
23489
  };
22139
- if (userVal !== void 0) values.user = userVal;
22140
- if (wsVal !== void 0) values.workspace = wsVal;
23490
+ if (userVal !== void 0) values.user = publicValue(userVal);
23491
+ if (wsVal !== void 0) values.workspace = publicValue(wsVal);
22141
23492
  settings.push({
22142
23493
  key,
22143
23494
  type: def.type,
@@ -22165,9 +23516,62 @@ function buildSettingsResponse(boundWorkspace, keys) {
22165
23516
  }
22166
23517
  __name(buildSettingsResponse, "buildSettingsResponse");
22167
23518
  var SCOPE_MAP = {
22168
- workspace: "Workspace" /* Workspace */,
22169
- user: "User" /* User */
23519
+ user: "User" /* User */,
23520
+ workspace: "Workspace" /* Workspace */
22170
23521
  };
23522
+ function prepareSettingWrite(workspace, scope, key, value, mcpServerMutation) {
23523
+ if (key !== "mcpServers") {
23524
+ return { persistedValue: value, publicValue: value };
23525
+ }
23526
+ const existing = loadSettings(workspace).forScope(scope).settings.mcpServers ?? {};
23527
+ let nextValue = value;
23528
+ if (mcpServerMutation) {
23529
+ const servers = { ...existing };
23530
+ if (mcpServerMutation.operation === "set") {
23531
+ servers[mcpServerMutation.name] = value;
23532
+ } else {
23533
+ delete servers[mcpServerMutation.name];
23534
+ }
23535
+ nextValue = servers;
23536
+ }
23537
+ const persistedValue = restoreRedactedMcpServersSetting(nextValue, existing);
23538
+ return {
23539
+ persistedValue,
23540
+ publicValue: redactMcpServersSetting(persistedValue)
23541
+ };
23542
+ }
23543
+ __name(prepareSettingWrite, "prepareSettingWrite");
23544
+ function parseMcpServerMutation(key, value) {
23545
+ if (value === void 0) return void 0;
23546
+ if (key !== "mcpServers" || typeof value !== "object" || value === null) {
23547
+ throw new Error("mcpServerMutation is only valid for mcpServers");
23548
+ }
23549
+ const operation = value["operation"];
23550
+ const name = value["name"];
23551
+ if (operation !== "set" && operation !== "remove" || typeof name !== "string" || !name.trim()) {
23552
+ throw new Error("mcpServerMutation requires a valid operation and name");
23553
+ }
23554
+ return { operation, name };
23555
+ }
23556
+ __name(parseMcpServerMutation, "parseMcpServerMutation");
23557
+ async function withMcpServerMutationLock(workspace, scope, operation) {
23558
+ const key = `${workspace}\0${scope}`;
23559
+ const previous = mcpServerMutationQueues.get(key) ?? Promise.resolve();
23560
+ const run = previous.catch(() => void 0).then(operation);
23561
+ const tail = run.then(
23562
+ () => void 0,
23563
+ () => void 0
23564
+ );
23565
+ mcpServerMutationQueues.set(key, tail);
23566
+ try {
23567
+ return await run;
23568
+ } finally {
23569
+ if (mcpServerMutationQueues.get(key) === tail) {
23570
+ mcpServerMutationQueues.delete(key);
23571
+ }
23572
+ }
23573
+ }
23574
+ __name(withMcpServerMutationLock, "withMcpServerMutationLock");
22171
23575
  function registerWorkspaceSettingsRoutes(app, deps) {
22172
23576
  const {
22173
23577
  boundWorkspace,
@@ -22200,6 +23604,19 @@ function registerWorkspaceSettingsRoutes(app, deps) {
22200
23604
  const scope = body["scope"];
22201
23605
  const key = body["key"];
22202
23606
  const value = body["value"];
23607
+ let mcpServerMutation;
23608
+ try {
23609
+ mcpServerMutation = parseMcpServerMutation(
23610
+ typeof key === "string" ? key : "",
23611
+ body["mcpServerMutation"]
23612
+ );
23613
+ } catch (error2) {
23614
+ res.status(400).json({
23615
+ error: error2 instanceof Error ? error2.message : String(error2),
23616
+ code: "invalid_mcp_server_mutation"
23617
+ });
23618
+ return;
23619
+ }
22203
23620
  if (typeof scope !== "string" || !VALID_WRITE_SCOPES.has(scope)) {
22204
23621
  res.status(400).json({
22205
23622
  error: `scope must be one of: ${[...VALID_WRITE_SCOPES].join(", ")}`,
@@ -22246,16 +23663,41 @@ function registerWorkspaceSettingsRoutes(app, deps) {
22246
23663
  }
22247
23664
  const clientId = parseAndValidateClientId(req, res);
22248
23665
  if (clientId === null) return;
23666
+ const settingScope = SCOPE_MAP[scope];
23667
+ if (!settingScope) {
23668
+ res.status(400).json({
23669
+ error: `scope must be one of: ${[...VALID_WRITE_SCOPES].join(", ")}`,
23670
+ code: "invalid_scope"
23671
+ });
23672
+ return;
23673
+ }
23674
+ let publicValue = value;
22249
23675
  try {
22250
- const settingScope = SCOPE_MAP[scope];
22251
- if (!settingScope) {
22252
- res.status(400).json({
22253
- error: `scope must be one of: ${[...VALID_WRITE_SCOPES].join(", ")}`,
22254
- code: "invalid_scope"
22255
- });
22256
- return;
23676
+ const persist = /* @__PURE__ */ __name(async () => {
23677
+ const prepared = prepareSettingWrite(
23678
+ boundWorkspace,
23679
+ settingScope,
23680
+ key,
23681
+ value,
23682
+ mcpServerMutation
23683
+ );
23684
+ publicValue = prepared.publicValue;
23685
+ await persistSetting(
23686
+ boundWorkspace,
23687
+ settingScope,
23688
+ key,
23689
+ prepared.persistedValue
23690
+ );
23691
+ }, "persist");
23692
+ if (mcpServerMutation) {
23693
+ await withMcpServerMutationLock(
23694
+ boundWorkspace,
23695
+ settingScope,
23696
+ persist
23697
+ );
23698
+ } else {
23699
+ await persist();
22257
23700
  }
22258
- await persistSetting(boundWorkspace, settingScope, key, value);
22259
23701
  } catch (err) {
22260
23702
  writeStderrLine(
22261
23703
  `qwen serve: POST /workspace/settings persist error (key=${key}, scope=${scope}, workspace=${boundWorkspace}): ${err instanceof Error ? err.message : String(err)}`
@@ -22267,7 +23709,7 @@ function registerWorkspaceSettingsRoutes(app, deps) {
22267
23709
  return;
22268
23710
  }
22269
23711
  try {
22270
- broadcastSettingsChanged(key, value, scope, clientId);
23712
+ broadcastSettingsChanged(key, publicValue, scope, clientId);
22271
23713
  } catch (err) {
22272
23714
  writeStderrLine(
22273
23715
  `qwen serve: POST /workspace/settings broadcast error (key=${key}, scope=${scope}): ${err instanceof Error ? err.message : String(err)}`
@@ -22276,7 +23718,7 @@ function registerWorkspaceSettingsRoutes(app, deps) {
22276
23718
  res.status(200).json({
22277
23719
  key,
22278
23720
  scope,
22279
- value,
23721
+ value: publicValue,
22280
23722
  requiresRestart: def.requiresRestart
22281
23723
  });
22282
23724
  }
@@ -22319,6 +23761,19 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
22319
23761
  const scope = body["scope"];
22320
23762
  const key = body["key"];
22321
23763
  const value = body["value"];
23764
+ let mcpServerMutation;
23765
+ try {
23766
+ mcpServerMutation = parseMcpServerMutation(
23767
+ typeof key === "string" ? key : "",
23768
+ body["mcpServerMutation"]
23769
+ );
23770
+ } catch (error2) {
23771
+ res.status(400).json({
23772
+ error: error2 instanceof Error ? error2.message : String(error2),
23773
+ code: "invalid_mcp_server_mutation"
23774
+ });
23775
+ return;
23776
+ }
22322
23777
  if (typeof scope !== "string" || !QUALIFIED_WRITE_SCOPES.has(scope)) {
22323
23778
  res.status(400).json({
22324
23779
  error: `scope must be one of: ${[...QUALIFIED_WRITE_SCOPES].join(", ")}`,
@@ -22377,13 +23832,33 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
22377
23832
  });
22378
23833
  return;
22379
23834
  }
23835
+ let publicValue = value;
22380
23836
  try {
22381
- await deps.persistSetting(
22382
- runtime.workspaceCwd,
22383
- settingScope,
22384
- key,
22385
- value
22386
- );
23837
+ const persist = /* @__PURE__ */ __name(async () => {
23838
+ const prepared = prepareSettingWrite(
23839
+ runtime.workspaceCwd,
23840
+ settingScope,
23841
+ key,
23842
+ value,
23843
+ mcpServerMutation
23844
+ );
23845
+ publicValue = prepared.publicValue;
23846
+ await deps.persistSetting(
23847
+ runtime.workspaceCwd,
23848
+ settingScope,
23849
+ key,
23850
+ prepared.persistedValue
23851
+ );
23852
+ }, "persist");
23853
+ if (mcpServerMutation) {
23854
+ await withMcpServerMutationLock(
23855
+ runtime.workspaceCwd,
23856
+ settingScope,
23857
+ persist
23858
+ );
23859
+ } else {
23860
+ await persist();
23861
+ }
22387
23862
  } catch (err) {
22388
23863
  writeStderrLine(
22389
23864
  `qwen serve: POST /workspaces/:workspace/settings persist error (key=${key}, scope=${scope}, workspace=${runtime.workspaceCwd}): ${err instanceof Error ? err.message : String(err)}`
@@ -22397,13 +23872,13 @@ function registerWorkspaceQualifiedSettingsRoutes(app, deps) {
22397
23872
  deps.invalidateServeFeaturesCache();
22398
23873
  runtime.bridge.publishWorkspaceEvent({
22399
23874
  type: "settings_changed",
22400
- data: { key, value, scope },
23875
+ data: { key, value: publicValue, scope },
22401
23876
  ...clientId ? { originatorClientId: clientId } : {}
22402
23877
  });
22403
23878
  res.status(200).json({
22404
23879
  key,
22405
23880
  scope,
22406
- value,
23881
+ value: publicValue,
22407
23882
  requiresRestart: def.requiresRestart
22408
23883
  });
22409
23884
  }
@@ -22479,7 +23954,7 @@ function sendBridgeError(res, err, ctx, daemonLog) {
22479
23954
  if (err instanceof WorkspaceSkillNotToggleableError) {
22480
23955
  res.status(409).json({
22481
23956
  error: err.message,
22482
- code: "skill_not_toggleable",
23957
+ code: err.reason === "inactive_extension" ? "skill_inactive_extension" : "skill_not_toggleable",
22483
23958
  skillName: err.skillName,
22484
23959
  reason: err.reason,
22485
23960
  ...err.lockedScope ? { lockedScope: err.lockedScope } : {}
@@ -22621,6 +24096,14 @@ function sendBridgeError(res, err, ctx, daemonLog) {
22621
24096
  });
22622
24097
  return;
22623
24098
  }
24099
+ if (err instanceof SessionNotArchivedError) {
24100
+ res.status(409).json({
24101
+ error: err.message,
24102
+ code: "session_not_archived",
24103
+ sessionId: err.sessionId
24104
+ });
24105
+ return;
24106
+ }
22624
24107
  if (err instanceof SessionConflictError) {
22625
24108
  res.status(409).json({
22626
24109
  error: err.message,
@@ -22674,7 +24157,7 @@ function sendBridgeError(res, err, ctx, daemonLog) {
22674
24157
  }
22675
24158
  if (err instanceof WorkspaceMismatchError) {
22676
24159
  writeStderrLine(
22677
- `qwen serve: workspace_mismatch (POST /session): daemon bound to ${JSON.stringify(err.bound)}, rejected ${JSON.stringify(err.requested)}`
24160
+ `qwen serve: workspace_mismatch (POST /session): runtime bound to ${JSON.stringify(err.bound)}, rejected ${JSON.stringify(err.requested)}`
22678
24161
  );
22679
24162
  res.status(400).json({
22680
24163
  error: err.message,
@@ -22862,9 +24345,20 @@ function sendBridgeError(res, err, ctx, daemonLog) {
22862
24345
  const d = data;
22863
24346
  res.status(413).json({
22864
24347
  error: errorMessage2(err),
22865
- code: "transcript_too_large",
24348
+ code: "transcript_too_large",
24349
+ ...d.sessionId ? { sessionId: d.sessionId } : {},
24350
+ ...typeof d.snapshotSize === "number" ? { snapshotSize: d.snapshotSize } : {},
24351
+ ...typeof d.maxBytes === "number" ? { maxBytes: d.maxBytes } : {}
24352
+ });
24353
+ return;
24354
+ }
24355
+ if (kind === "transcript_page_too_large") {
24356
+ const d = data;
24357
+ res.status(413).json({
24358
+ error: errorMessage2(err),
24359
+ code: "transcript_page_too_large",
22866
24360
  ...d.sessionId ? { sessionId: d.sessionId } : {},
22867
- ...typeof d.snapshotSize === "number" ? { snapshotSize: d.snapshotSize } : {},
24361
+ ...typeof d.pageBytes === "number" ? { pageBytes: d.pageBytes } : {},
22868
24362
  ...typeof d.maxBytes === "number" ? { maxBytes: d.maxBytes } : {}
22869
24363
  });
22870
24364
  return;
@@ -23635,320 +25129,26 @@ function parseIdeWorkspacePathEnv(value) {
23635
25129
  }
23636
25130
  return value.split(path14.delimiter).filter((workspace) => workspace.length > 0 && path14.isAbsolute(workspace));
23637
25131
  }
23638
- __name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
23639
- function dropNestedWorkspacesPreservingPrimary(workspaces) {
23640
- const primary = workspaces[0];
23641
- if (primary === void 0) return [];
23642
- const withoutPrimaryOverlaps = workspaces.filter(
23643
- (workspace, i) => i === 0 || workspace !== primary && !isWithinRoot2(workspace, primary) && !isWithinRoot2(primary, workspace)
23644
- );
23645
- const filtered = withoutPrimaryOverlaps.filter(
23646
- (workspace, i) => i === 0 || !withoutPrimaryOverlaps.some(
23647
- (other, j) => i !== j && j !== 0 && workspace !== other && isWithinRoot2(workspace, other)
23648
- )
23649
- );
23650
- if (filtered.length < workspaces.length) {
23651
- writeStderrLine(
23652
- "qwen serve: dropping nested IDE workspace roots (parent folders already cover children)"
23653
- );
23654
- }
23655
- return filtered;
23656
- }
23657
- __name(dropNestedWorkspacesPreservingPrimary, "dropNestedWorkspacesPreservingPrimary");
23658
-
23659
- // packages/cli/src/serve/server/telemetry.ts
23660
- init_esbuild_shims();
23661
- function decodePathSegment(value) {
23662
- try {
23663
- return decodeURIComponent(value);
23664
- } catch {
23665
- return value;
23666
- }
23667
- }
23668
- __name(decodePathSegment, "decodePathSegment");
23669
- function resolveDaemonTelemetryRoute(req) {
23670
- const path15 = req.path.replace(/\/$/, "") || "/";
23671
- if (req.method === "POST" && path15 === "/session") {
23672
- return { route: "POST /session" };
23673
- }
23674
- if (req.method === "POST" && path15 === "/sessions/delete") {
23675
- return { route: "POST /sessions/delete" };
23676
- }
23677
- if (req.method === "GET" && path15 === "/daemon/status") {
23678
- return { route: "GET /daemon/status" };
23679
- }
23680
- const rewindSnapshots = path15.match(/^\/session\/([^/]+)\/rewind\/snapshots$/);
23681
- if (rewindSnapshots?.[1] && req.method === "GET") {
23682
- return {
23683
- route: "GET /session/:id/rewind/snapshots",
23684
- sessionId: rewindSnapshots[1]
23685
- };
23686
- }
23687
- const sessionAction = path15.match(
23688
- /^\/session\/([^/]+)\/(load|resume|prompt|cancel|recap|btw|mid-turn-message|model|shell|detach|rewind|approval-mode|language|a2ui-action)$/
23689
- );
23690
- const sessionActionId = sessionAction?.[1];
23691
- const sessionActionName = sessionAction?.[2];
23692
- if (sessionActionId && sessionActionName && req.method === "POST") {
23693
- return {
23694
- route: `POST /session/:id/${sessionActionName}`,
23695
- sessionId: sessionActionId
23696
- };
23697
- }
23698
- const sessionMetadata = path15.match(/^\/session\/([^/]+)\/metadata$/);
23699
- if (sessionMetadata?.[1] && req.method === "PATCH") {
23700
- return {
23701
- route: "PATCH /session/:id/metadata",
23702
- sessionId: sessionMetadata[1]
23703
- };
23704
- }
23705
- const sessionArtifacts = path15.match(/^\/session\/([^/]+)\/artifacts$/);
23706
- if (sessionArtifacts?.[1]) {
23707
- if (req.method === "GET") {
23708
- return {
23709
- route: "GET /session/:id/artifacts",
23710
- sessionId: sessionArtifacts[1]
23711
- };
23712
- }
23713
- if (req.method === "POST") {
23714
- return {
23715
- route: "POST /session/:id/artifacts",
23716
- sessionId: sessionArtifacts[1]
23717
- };
23718
- }
23719
- }
23720
- const sessionArtifact = path15.match(
23721
- /^\/session\/([^/]+)\/artifacts\/([^/]+)$/
23722
- );
23723
- if (sessionArtifact?.[1] && req.method === "DELETE") {
23724
- return {
23725
- route: "DELETE /session/:id/artifacts/:artifactId",
23726
- sessionId: sessionArtifact[1]
23727
- };
23728
- }
23729
- const sessionPermission = path15.match(
23730
- /^\/session\/([^/]+)\/permission\/([^/]+)$/
23731
- );
23732
- if (sessionPermission?.[1] && sessionPermission?.[2] && req.method === "POST") {
23733
- const rawRequestId = sessionPermission[2];
23734
- return {
23735
- route: "POST /session/:id/permission/:requestId",
23736
- sessionId: sessionPermission[1],
23737
- ...rawRequestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawRequestId) ? { permissionRequestId: rawRequestId } : {}
23738
- };
23739
- }
23740
- const globalPermission = path15.match(/^\/permission\/([^/]+)$/);
23741
- if (globalPermission?.[1] && req.method === "POST") {
23742
- const rawRequestId = globalPermission[1];
23743
- return {
23744
- route: "POST /permission/:requestId",
23745
- ...rawRequestId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawRequestId) ? { permissionRequestId: rawRequestId } : {}
23746
- };
23747
- }
23748
- const deleteSession = path15.match(/^\/session\/([^/]+)$/);
23749
- const deleteSessionId = deleteSession?.[1];
23750
- if (deleteSessionId && req.method === "DELETE") {
23751
- return { route: "DELETE /session/:id", sessionId: deleteSessionId };
23752
- }
23753
- if (req.method === "GET" && /^\/workspace\/[^/]+\/sessions$/.test(path15)) {
23754
- return { route: "GET /workspace/:id/sessions" };
23755
- }
23756
- if (req.method === "GET" && /^\/workspaces\/[^/]+\/sessions$/.test(path15)) {
23757
- return { route: "GET /workspace/:id/sessions" };
23758
- }
23759
- const workspaceTranscript = path15.match(
23760
- /^\/workspaces\/[^/]+\/session\/([^/]+)\/transcript$/
23761
- );
23762
- if (workspaceTranscript?.[1] && req.method === "GET") {
23763
- return {
23764
- route: "GET /workspaces/:workspace/session/:id/transcript",
23765
- sessionId: workspaceTranscript[1]
23766
- };
23767
- }
23768
- const workspaceExport = path15.match(
23769
- /^\/workspaces\/[^/]+\/session\/([^/]+)\/export$/
23770
- );
23771
- if (workspaceExport?.[1] && req.method === "GET") {
23772
- return {
23773
- route: "GET /workspaces/:workspace/session/:id/export",
23774
- sessionId: workspaceExport[1]
23775
- };
23776
- }
23777
- const pluralWorkspacePrefix = /^\/workspaces\/[^/]+/;
23778
- if (pluralWorkspacePrefix.test(path15)) {
23779
- const suffix = path15.replace(pluralWorkspacePrefix, "/workspace");
23780
- if (req.method === "GET") {
23781
- if (suffix === "/workspace/mcp" || suffix === "/workspace/skills" || suffix === "/workspace/tools" || suffix === "/workspace/providers" || suffix === "/workspace/env" || suffix === "/workspace/preflight" || suffix === "/workspace/hooks" || suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/permissions" || suffix === "/workspace/trust" || suffix === "/workspace/memory" || suffix === "/workspace/agents") {
23782
- return { route: `GET ${suffix}` };
23783
- }
23784
- if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
23785
- return { route: "GET /workspace/agents/:agentType" };
23786
- }
23787
- if (suffix === "/workspace/file") return { route: "GET /file" };
23788
- if (suffix === "/workspace/file/bytes") {
23789
- return { route: "GET /file/bytes" };
23790
- }
23791
- if (suffix === "/workspace/stat") return { route: "GET /stat" };
23792
- if (suffix === "/workspace/list") return { route: "GET /list" };
23793
- if (suffix === "/workspace/glob") return { route: "GET /glob" };
23794
- if (/^\/workspace\/mcp\/[^/]+\/tools$/.test(suffix)) {
23795
- return { route: "GET /workspace/mcp/:server/tools" };
23796
- }
23797
- if (/^\/workspace\/mcp\/[^/]+\/resources$/.test(suffix)) {
23798
- return { route: "GET /workspace/mcp/:server/resources" };
23799
- }
23800
- }
23801
- if (req.method === "POST") {
23802
- if (suffix === "/workspace/settings" || suffix === "/workspace/voice" || suffix === "/workspace/voice/transcribe" || suffix === "/workspace/permissions" || suffix === "/workspace/trust/request" || suffix === "/workspace/init" || suffix === "/workspace/reload" || suffix === "/workspace/file/write" || suffix === "/workspace/file/edit" || suffix === "/workspace/mcp/servers" || suffix === "/workspace/memory" || suffix === "/workspace/agents" || suffix === "/workspace/sessions/delete" || suffix === "/workspace/sessions/archive" || suffix === "/workspace/sessions/unarchive" || suffix === "/workspace/session-groups") {
23803
- return { route: `POST ${suffix}` };
23804
- }
23805
- if (/^\/workspace\/tools\/[^/]+\/enable$/.test(suffix)) {
23806
- return { route: "POST /workspace/tools/:name/enable" };
23807
- }
23808
- if (/^\/workspace\/mcp\/[^/]+\/restart$/.test(suffix)) {
23809
- return { route: "POST /workspace/mcp/:server/restart" };
23810
- }
23811
- if (/^\/workspace\/agents\/[^/]+$/.test(suffix)) {
23812
- return { route: "POST /workspace/agents/:agentType" };
23813
- }
23814
- if (/^\/workspace\/mcp\/[^/]+\/(enable|disable|authenticate|clear-auth)$/.test(
23815
- suffix
23816
- )) {
23817
- return {
23818
- route: `POST /workspace/mcp/:server/${suffix.split("/").at(-1)}`
23819
- };
23820
- }
23821
- }
23822
- if (req.method === "DELETE" && /^\/workspace\/mcp\/servers\/[^/]+$/.test(suffix)) {
23823
- return { route: "DELETE /workspace/mcp/servers/:name" };
23824
- }
23825
- if (req.method === "DELETE" && /^\/workspace\/agents\/[^/]+$/.test(suffix)) {
23826
- return { route: "DELETE /workspace/agents/:agentType" };
23827
- }
23828
- if (suffix === "/workspace/session-groups" && req.method === "GET") {
23829
- return { route: "GET /workspace/session-groups" };
23830
- }
23831
- if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "PATCH") {
23832
- return { route: "PATCH /workspace/session-groups/:groupId" };
23833
- }
23834
- if (/^\/workspace\/session-groups\/[^/]+$/.test(suffix) && req.method === "DELETE") {
23835
- return { route: "DELETE /workspace/session-groups/:groupId" };
23836
- }
23837
- }
23838
- if (req.method === "POST" && path15 === "/workspace/init") {
23839
- return { route: "POST /workspace/init" };
23840
- }
23841
- if (req.method === "POST" && path15 === "/workspace/setup-github") {
23842
- return { route: "POST /workspace/setup-github" };
23843
- }
23844
- if (req.method === "POST" && path15 === "/workspace/reload") {
23845
- return { route: "POST /workspace/reload" };
23846
- }
23847
- const mcpRestart = path15.match(/^\/workspace\/mcp\/([^/]+)\/restart$/);
23848
- if (mcpRestart?.[1] && req.method === "POST") {
23849
- return { route: "POST /workspace/mcp/:server/restart" };
23850
- }
23851
- if (req.method === "POST" && path15 === "/workspace/mcp/servers") {
23852
- return { route: "POST /workspace/mcp/servers" };
23853
- }
23854
- const mcpDelete = path15.match(/^\/workspace\/mcp\/servers\/([^/]+)$/);
23855
- if (mcpDelete?.[1] && req.method === "DELETE") {
23856
- return { route: "DELETE /workspace/mcp/servers/:name" };
23857
- }
23858
- if (req.method === "POST" && path15 === "/workspace/auth/device-flow") {
23859
- return { route: "POST /workspace/auth/device-flow" };
23860
- }
23861
- const deviceFlowDelete = path15.match(
23862
- /^\/workspace\/auth\/device-flow\/([^/]+)$/
23863
- );
23864
- if (deviceFlowDelete?.[1] && req.method === "DELETE") {
23865
- return { route: "DELETE /workspace/auth/device-flow/:id" };
23866
- }
23867
- const toolEnable = path15.match(/^\/workspace\/tools\/([^/]+)\/enable$/);
23868
- if (toolEnable?.[1] && req.method === "POST") {
23869
- return { route: "POST /workspace/tools/:name/enable" };
23870
- }
23871
- if (path15 === "/workspace/settings") {
23872
- if (req.method === "GET") return { route: "GET /workspace/settings" };
23873
- if (req.method === "POST") return { route: "POST /workspace/settings" };
23874
- }
23875
- if (path15 === "/workspace/permissions") {
23876
- if (req.method === "GET") return { route: "GET /workspace/permissions" };
23877
- if (req.method === "POST") return { route: "POST /workspace/permissions" };
23878
- }
23879
- if (path15 === "/workspace/trust") {
23880
- if (req.method === "GET") return { route: "GET /workspace/trust" };
23881
- }
23882
- if (req.method === "POST" && path15 === "/workspace/trust/request") {
23883
- return { route: "POST /workspace/trust/request" };
23884
- }
23885
- if (path15 === "/workspace/voice") {
23886
- if (req.method === "GET") return { route: "GET /workspace/voice" };
23887
- if (req.method === "POST") return { route: "POST /workspace/voice" };
23888
- }
23889
- if (req.method === "POST" && path15 === "/workspace/voice/transcribe") {
23890
- return { route: "POST /workspace/voice/transcribe" };
23891
- }
23892
- return void 0;
23893
- }
23894
- __name(resolveDaemonTelemetryRoute, "resolveDaemonTelemetryRoute");
23895
- function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest, resolveSessionWorkspaceCwd) {
23896
- const workspaceHashByCwd = /* @__PURE__ */ new Map();
23897
- const resolveWorkspaceHash = /* @__PURE__ */ __name((workspaceCwd) => {
23898
- const existing = workspaceHashByCwd.get(workspaceCwd);
23899
- if (existing !== void 0) return existing;
23900
- const workspaceHash = hashDaemonWorkspace(workspaceCwd);
23901
- workspaceHashByCwd.set(workspaceCwd, workspaceHash);
23902
- return workspaceHash;
23903
- }, "resolveWorkspaceHash");
23904
- return (req, res, next) => {
23905
- const route = resolveDaemonTelemetryRoute(req);
23906
- if (!route) {
23907
- next();
23908
- return;
23909
- }
23910
- const resolveOwnerWorkspace = route.route === "GET /session/:id/rewind/snapshots" || route.route === "POST /session/:id/rewind" || route.route === "POST /session/:id/shell";
23911
- const sessionId = route.sessionId ? decodePathSegment(route.sessionId) : void 0;
23912
- const workspaceCwd = (resolveOwnerWorkspace && sessionId ? resolveSessionWorkspaceCwd?.(sessionId) : void 0) ?? resolveWorkspaceCwd(req);
23913
- const workspaceHash = resolveWorkspaceHash(workspaceCwd);
23914
- const rawClientId = req.get(CLIENT_ID_HEADER);
23915
- const clientId = rawClientId !== void 0 && rawClientId !== "" && rawClientId.length <= MAX_CLIENT_ID_LENGTH && CLIENT_ID_RE.test(rawClientId) ? rawClientId : void 0;
23916
- const startMs = Date.now();
23917
- void withDaemonRequestSpan(
23918
- {
23919
- method: req.method,
23920
- route: route.route,
23921
- workspaceHash,
23922
- ...sessionId ? { sessionId } : {},
23923
- ...route.permissionRequestId ? { permissionRequestId: route.permissionRequestId } : {},
23924
- ...clientId ? { clientId } : {}
23925
- },
23926
- async (span) => await new Promise((resolve5, reject) => {
23927
- let done = false;
23928
- const finish = /* @__PURE__ */ __name(() => {
23929
- if (done) return;
23930
- done = true;
23931
- recordDaemonHttpResponse(span, res.statusCode);
23932
- const durationMs = Date.now() - startMs;
23933
- recordDaemonHttpRequest(durationMs, route.route, res.statusCode);
23934
- if (route.route !== "GET /daemon/status") {
23935
- recordRequest?.(durationMs, res.statusCode);
23936
- }
23937
- resolve5();
23938
- }, "finish");
23939
- res.once("finish", finish);
23940
- res.once("close", finish);
23941
- try {
23942
- next();
23943
- } catch (error2) {
23944
- recordDaemonError(span, error2);
23945
- reject(error2);
23946
- }
23947
- })
23948
- ).catch(next);
23949
- };
25132
+ __name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
25133
+ function dropNestedWorkspacesPreservingPrimary(workspaces) {
25134
+ const primary = workspaces[0];
25135
+ if (primary === void 0) return [];
25136
+ const withoutPrimaryOverlaps = workspaces.filter(
25137
+ (workspace, i) => i === 0 || workspace !== primary && !isWithinRoot2(workspace, primary) && !isWithinRoot2(primary, workspace)
25138
+ );
25139
+ const filtered = withoutPrimaryOverlaps.filter(
25140
+ (workspace, i) => i === 0 || !withoutPrimaryOverlaps.some(
25141
+ (other, j) => i !== j && j !== 0 && workspace !== other && isWithinRoot2(workspace, other)
25142
+ )
25143
+ );
25144
+ if (filtered.length < workspaces.length) {
25145
+ writeStderrLine(
25146
+ "qwen serve: dropping nested IDE workspace roots (parent folders already cover children)"
25147
+ );
25148
+ }
25149
+ return filtered;
23950
25150
  }
23951
- __name(daemonTelemetryMiddleware, "daemonTelemetryMiddleware");
25151
+ __name(dropNestedWorkspacesPreservingPrimary, "dropNestedWorkspacesPreservingPrimary");
23952
25152
 
23953
25153
  // packages/cli/src/serve/server/access-log.ts
23954
25154
  init_esbuild_shims();
@@ -24473,9 +25673,10 @@ __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLif
24473
25673
 
24474
25674
  // packages/cli/src/serve/routes/workspace-management.ts
24475
25675
  init_esbuild_shims();
24476
- import { stat } from "node:fs/promises";
25676
+ import { readdir, stat } from "node:fs/promises";
24477
25677
  import { realpathSync } from "node:fs";
24478
- import { isAbsolute as isAbsolute7, resolve as resolve4 } from "node:path";
25678
+ import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join7, resolve as resolve4, sep as sep3 } from "node:path";
25679
+ var MAX_PATH_SUGGESTIONS = 50;
24479
25680
  function registerWorkspaceManagementRoutes(app, deps) {
24480
25681
  const {
24481
25682
  workspaceRegistry,
@@ -24505,6 +25706,72 @@ function registerWorkspaceManagementRoutes(app, deps) {
24505
25706
  code: "daemon_shutting_down"
24506
25707
  });
24507
25708
  }, "sendSealed");
25709
+ app.get(
25710
+ "/workspace-path-suggestions",
25711
+ async (req, res) => {
25712
+ const prefixRaw = req.query["prefix"];
25713
+ if (typeof prefixRaw !== "string" || prefixRaw.trim().length === 0) {
25714
+ res.status(400).json({
25715
+ error: "`prefix` must be a non-empty string",
25716
+ code: "invalid_prefix"
25717
+ });
25718
+ return;
25719
+ }
25720
+ const prefix = prefixRaw;
25721
+ if (prefix.length > MAX_WORKSPACE_PATH_LENGTH) {
25722
+ res.status(400).json({
25723
+ error: `\`prefix\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`,
25724
+ code: "invalid_prefix"
25725
+ });
25726
+ return;
25727
+ }
25728
+ if (!isAbsolute7(prefix)) {
25729
+ res.status(400).json({
25730
+ error: "`prefix` must be an absolute path",
25731
+ code: "invalid_prefix"
25732
+ });
25733
+ return;
25734
+ }
25735
+ const endsWithSep = prefix.endsWith("/") || process.platform === "win32" && prefix.endsWith("\\");
25736
+ const dir = endsWithSep ? join7(prefix, ".") : dirname4(prefix);
25737
+ const filter = endsWithSep ? "" : basename4(prefix);
25738
+ const filterLower = filter.toLowerCase();
25739
+ const suggestions = [];
25740
+ let truncated = false;
25741
+ try {
25742
+ const entries = await readdir(dir, { withFileTypes: true });
25743
+ entries.sort((a, b) => a.name.localeCompare(b.name));
25744
+ for (const entry of entries) {
25745
+ if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
25746
+ if (filter && !entry.name.toLowerCase().startsWith(filterLower)) {
25747
+ continue;
25748
+ }
25749
+ let isDir = entry.isDirectory();
25750
+ if (!isDir && entry.isSymbolicLink()) {
25751
+ try {
25752
+ isDir = (await stat(join7(dir, entry.name))).isDirectory();
25753
+ } catch {
25754
+ continue;
25755
+ }
25756
+ }
25757
+ if (!isDir) continue;
25758
+ if (suggestions.length >= MAX_PATH_SUGGESTIONS) {
25759
+ truncated = true;
25760
+ break;
25761
+ }
25762
+ suggestions.push({ name: entry.name, path: join7(dir, entry.name) });
25763
+ }
25764
+ } catch {
25765
+ }
25766
+ res.status(200).json({
25767
+ kind: "workspace-path-suggestions",
25768
+ dir,
25769
+ sep: sep3,
25770
+ suggestions,
25771
+ truncated
25772
+ });
25773
+ }
25774
+ );
24508
25775
  app.post(
24509
25776
  "/workspaces",
24510
25777
  mutate({ strict: true }),
@@ -25330,6 +26597,30 @@ function registerWorkspaceMcpControlRoutes(app, deps) {
25330
26597
  parseAndValidateClientId
25331
26598
  } = deps;
25332
26599
  const buildWorkspaceCtx = createBuildWorkspaceCtx(boundWorkspace);
26600
+ app.post(
26601
+ "/workspace/mcp/initialize",
26602
+ mutate({ strict: true }),
26603
+ async (_req, res) => {
26604
+ try {
26605
+ const result = await bridge.initializeWorkspaceMcp();
26606
+ res.status(202).json(result);
26607
+ } catch (err) {
26608
+ sendBridgeError2(res, err, { route: "POST /workspace/mcp/initialize" });
26609
+ }
26610
+ }
26611
+ );
26612
+ app.post(
26613
+ "/workspace/mcp/reload",
26614
+ mutate({ strict: true }),
26615
+ async (_req, res) => {
26616
+ try {
26617
+ const result = await bridge.reloadWorkspaceMcp();
26618
+ res.status(202).json(result);
26619
+ } catch (err) {
26620
+ sendBridgeError2(res, err, { route: "POST /workspace/mcp/reload" });
26621
+ }
26622
+ }
26623
+ );
25333
26624
  app.post(
25334
26625
  "/workspace/mcp/:server/restart",
25335
26626
  mutate({ strict: true }),
@@ -25384,6 +26675,7 @@ function registerWorkspaceMcpControlRoutes(app, deps) {
25384
26675
  }
25385
26676
  );
25386
26677
  for (const [routeAction, bridgeAction] of [
26678
+ ["approve", "approve"],
25387
26679
  ["enable", "enable"],
25388
26680
  ["disable", "disable"],
25389
26681
  ["authenticate", "authenticate"],
@@ -25498,6 +26790,44 @@ function resolveTrustedMcpRuntime(registry, req, res) {
25498
26790
  }
25499
26791
  __name(resolveTrustedMcpRuntime, "resolveTrustedMcpRuntime");
25500
26792
  function registerWorkspaceQualifiedMcpControlRoutes(app, deps) {
26793
+ app.post(
26794
+ "/workspaces/:workspace/mcp/initialize",
26795
+ deps.mutate({ strict: true }),
26796
+ async (req, res) => {
26797
+ const runtime = resolveTrustedMcpRuntime(
26798
+ deps.workspaceRegistry,
26799
+ req,
26800
+ res
26801
+ );
26802
+ if (!runtime) return;
26803
+ const route = "POST /workspaces/:workspace/mcp/initialize";
26804
+ try {
26805
+ const result = await runtime.bridge.initializeWorkspaceMcp();
26806
+ res.status(202).json(result);
26807
+ } catch (err) {
26808
+ deps.sendBridgeError(res, err, { route });
26809
+ }
26810
+ }
26811
+ );
26812
+ app.post(
26813
+ "/workspaces/:workspace/mcp/reload",
26814
+ deps.mutate({ strict: true }),
26815
+ async (req, res) => {
26816
+ const runtime = resolveTrustedMcpRuntime(
26817
+ deps.workspaceRegistry,
26818
+ req,
26819
+ res
26820
+ );
26821
+ if (!runtime) return;
26822
+ const route = "POST /workspaces/:workspace/mcp/reload";
26823
+ try {
26824
+ const result = await runtime.bridge.reloadWorkspaceMcp();
26825
+ res.status(202).json(result);
26826
+ } catch (err) {
26827
+ deps.sendBridgeError(res, err, { route });
26828
+ }
26829
+ }
26830
+ );
25501
26831
  app.post(
25502
26832
  "/workspaces/:workspace/mcp/:server/restart",
25503
26833
  deps.mutate({ strict: true }),
@@ -25561,6 +26891,7 @@ function registerWorkspaceQualifiedMcpControlRoutes(app, deps) {
25561
26891
  }
25562
26892
  );
25563
26893
  for (const [routeAction, bridgeAction] of [
26894
+ ["approve", "approve"],
25564
26895
  ["enable", "enable"],
25565
26896
  ["disable", "disable"],
25566
26897
  ["authenticate", "authenticate"],
@@ -25752,11 +27083,84 @@ function parseSelection(body, res) {
25752
27083
  }
25753
27084
  }
25754
27085
  __name(parseSelection, "parseSelection");
27086
+ function sanitizeControlDiagnostic(value, maxLength) {
27087
+ return sanitizeLogText(
27088
+ redactLogCredentials(normalizeWorkerDiagnostic(value)),
27089
+ maxLength
27090
+ );
27091
+ }
27092
+ __name(sanitizeControlDiagnostic, "sanitizeControlDiagnostic");
27093
+ function startupFailureResponseFields(error2) {
27094
+ if (!error2 || typeof error2 !== "object") return {};
27095
+ let rawFailures;
27096
+ let rawTruncated;
27097
+ try {
27098
+ rawFailures = Reflect.get(error2, "startupFailures");
27099
+ rawTruncated = Reflect.get(error2, "startupFailuresTruncated");
27100
+ } catch {
27101
+ return {};
27102
+ }
27103
+ if (!Array.isArray(rawFailures)) return {};
27104
+ let limitedFailures;
27105
+ let rawFailureCount;
27106
+ try {
27107
+ limitedFailures = rawFailures.slice(0, MAX_CHANNEL_STARTUP_FAILURES);
27108
+ rawFailureCount = rawFailures.length;
27109
+ } catch {
27110
+ return {};
27111
+ }
27112
+ const startupFailures = limitedFailures.flatMap((raw) => {
27113
+ try {
27114
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
27115
+ const failure = raw;
27116
+ if (typeof failure["workspaceCwd"] !== "string" || failure["workspaceCwd"].length === 0 || typeof failure["channel"] !== "string" || failure["channel"].length === 0 || failure["phase"] !== "connect" || typeof failure["message"] !== "string" || failure["message"].length === 0 || failure["code"] !== void 0 && (typeof failure["code"] !== "string" || failure["code"].length === 0)) {
27117
+ return [];
27118
+ }
27119
+ const workspaceCwd = sanitizeControlDiagnostic(
27120
+ failure["workspaceCwd"],
27121
+ MAX_WORKSPACE_PATH_LENGTH
27122
+ );
27123
+ const channel = sanitizeControlDiagnostic(
27124
+ failure["channel"],
27125
+ MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH
27126
+ );
27127
+ const message = sanitizeControlDiagnostic(
27128
+ failure["message"],
27129
+ MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH
27130
+ );
27131
+ const code = typeof failure["code"] === "string" ? sanitizeControlDiagnostic(
27132
+ failure["code"],
27133
+ MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH
27134
+ ) : void 0;
27135
+ if (!workspaceCwd || !channel || !message) return [];
27136
+ return [
27137
+ {
27138
+ workspaceCwd,
27139
+ channel,
27140
+ phase: "connect",
27141
+ ...code ? { code } : {},
27142
+ message
27143
+ }
27144
+ ];
27145
+ } catch {
27146
+ return [];
27147
+ }
27148
+ });
27149
+ if (startupFailures.length === 0) return {};
27150
+ const truncated = rawTruncated === true || rawFailureCount > MAX_CHANNEL_STARTUP_FAILURES;
27151
+ return {
27152
+ startupFailures,
27153
+ ...truncated ? { startupFailuresTruncated: true } : {}
27154
+ };
27155
+ }
27156
+ __name(startupFailureResponseFields, "startupFailureResponseFields");
25755
27157
  function sendChannelControlError(res, error2, getState) {
25756
27158
  const code = error2 && typeof error2 === "object" && "code" in error2 ? error2.code : void 0;
25757
- const message = redactLogCredentials(
25758
- error2 instanceof Error ? error2.message : String(error2)
25759
- );
27159
+ const rawMessage = error2 instanceof Error ? error2.message : String(error2);
27160
+ const message = code === "channel_worker_start_failed" ? sanitizeControlDiagnostic(
27161
+ rawMessage,
27162
+ MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH
27163
+ ) : redactLogCredentials(rawMessage);
25760
27164
  if (code === "channel_workspace_mismatch" || code === "ambiguous_channel_workspace") {
25761
27165
  res.status(400).json({ error: message, code });
25762
27166
  return true;
@@ -25792,7 +27196,13 @@ function sendChannelControlError(res, error2, getState) {
25792
27196
  error: message,
25793
27197
  code,
25794
27198
  ...typeof controlError.rolledBack === "boolean" ? { rolledBack: controlError.rolledBack } : {},
25795
- ...typeof controlError.rollbackError === "string" && controlError.rollbackError ? { rollbackError: redactLogCredentials(controlError.rollbackError) } : {},
27199
+ ...typeof controlError.rollbackError === "string" && controlError.rollbackError ? {
27200
+ rollbackError: sanitizeControlDiagnostic(
27201
+ controlError.rollbackError,
27202
+ 512
27203
+ )
27204
+ } : {},
27205
+ ...code === "channel_worker_start_failed" ? startupFailureResponseFields(error2) : {},
25796
27206
  state: getState()
25797
27207
  });
25798
27208
  return true;
@@ -26053,9 +27463,9 @@ function parseSkillToggleRequest(req, res, safeBody2) {
26053
27463
  });
26054
27464
  return void 0;
26055
27465
  }
26056
- if (skillName.length > MAX_SKILL_NAME_LENGTH) {
27466
+ if (skillName.length > MAX_WORKSPACE_SKILL_NAME_LENGTH) {
26057
27467
  res.status(400).json({
26058
- error: `Skill name exceeds ${MAX_SKILL_NAME_LENGTH}-character limit`,
27468
+ error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
26059
27469
  code: "invalid_skill_name"
26060
27470
  });
26061
27471
  return void 0;
@@ -26071,11 +27481,138 @@ function parseSkillToggleRequest(req, res, safeBody2) {
26071
27481
  return { skillName, enabled };
26072
27482
  }
26073
27483
  __name(parseSkillToggleRequest, "parseSkillToggleRequest");
27484
+ function parseSkillScope(value, res) {
27485
+ if (value === "workspace" || value === "global") return value;
27486
+ res.status(400).json({
27487
+ error: '`scope` must be "workspace" or "global"',
27488
+ code: "invalid_skill_scope"
27489
+ });
27490
+ return void 0;
27491
+ }
27492
+ __name(parseSkillScope, "parseSkillScope");
27493
+ function parseSkillInstallRequest(req, res, safeBody2) {
27494
+ const body = safeBody2(req);
27495
+ const name = body["name"];
27496
+ if (typeof name !== "string" || !name.trim()) {
27497
+ res.status(400).json({
27498
+ error: "`name` is required and must be a string",
27499
+ code: "invalid_skill_name"
27500
+ });
27501
+ return void 0;
27502
+ }
27503
+ if (name.trim().length > MAX_WORKSPACE_SKILL_NAME_LENGTH) {
27504
+ res.status(400).json({
27505
+ error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
27506
+ code: "invalid_skill_name"
27507
+ });
27508
+ return void 0;
27509
+ }
27510
+ const scope = parseSkillScope(body["scope"], res);
27511
+ if (!scope) return void 0;
27512
+ const rawSource = body["source"];
27513
+ if (!rawSource || typeof rawSource !== "object" || Array.isArray(rawSource)) {
27514
+ res.status(400).json({
27515
+ error: "`source` is required",
27516
+ code: "invalid_skill_source"
27517
+ });
27518
+ return void 0;
27519
+ }
27520
+ const source = rawSource;
27521
+ if (source["type"] === "github" && typeof source["url"] === "string") {
27522
+ return { name, scope, source: { type: "github", url: source["url"] } };
27523
+ }
27524
+ if (source["type"] === "zip" && typeof source["contentBase64"] === "string") {
27525
+ return {
27526
+ name,
27527
+ scope,
27528
+ source: { type: "zip", contentBase64: source["contentBase64"] }
27529
+ };
27530
+ }
27531
+ if (source["type"] === "folder" && typeof source["path"] === "string") {
27532
+ return {
27533
+ name,
27534
+ scope,
27535
+ source: { type: "folder", path: source["path"] }
27536
+ };
27537
+ }
27538
+ res.status(400).json({
27539
+ error: "Invalid Skill install source",
27540
+ code: "invalid_skill_source"
27541
+ });
27542
+ return void 0;
27543
+ }
27544
+ __name(parseSkillInstallRequest, "parseSkillInstallRequest");
27545
+ function parseDeleteScope(req, res) {
27546
+ return parseSkillScope(req.query["scope"], res);
27547
+ }
27548
+ __name(parseDeleteScope, "parseDeleteScope");
27549
+ function sendSkillManagementError(res, error2) {
27550
+ if (!(error2 instanceof WorkspaceSkillManagementError)) return false;
27551
+ res.status(error2.statusCode).json({
27552
+ error: error2.message,
27553
+ code: error2.code
27554
+ });
27555
+ return true;
27556
+ }
27557
+ __name(sendSkillManagementError, "sendSkillManagementError");
26074
27558
  function registerWorkspaceSkillsRoutes(app, deps) {
26075
27559
  const buildWorkspaceCtx = createBuildWorkspaceCtx(
26076
27560
  deps.workspaceRuntime.workspaceCwd
26077
27561
  );
26078
27562
  const route = "POST /workspace/skills/:name/enable";
27563
+ app.post(
27564
+ "/workspace/skills/install",
27565
+ deps.mutate({ strict: true }),
27566
+ async (req, res) => {
27567
+ if (!requireTrustedWorkspaceRuntime(deps.workspaceRuntime, res)) return;
27568
+ const input = parseSkillInstallRequest(req, res, deps.safeBody);
27569
+ if (!input) return;
27570
+ const clientId = deps.parseAndValidateClientId(req, res);
27571
+ if (clientId === null) return;
27572
+ const installRoute = "POST /workspace/skills/install";
27573
+ try {
27574
+ const result = await deps.workspaceRuntime.workspaceService.installWorkspaceSkill(
27575
+ buildWorkspaceCtx(installRoute, clientId),
27576
+ input
27577
+ );
27578
+ res.status(200).json(result);
27579
+ } catch (err) {
27580
+ if (!sendSkillManagementError(res, err))
27581
+ deps.sendBridgeError(res, err, { route: installRoute });
27582
+ }
27583
+ }
27584
+ );
27585
+ app.delete(
27586
+ "/workspace/skills/:name",
27587
+ deps.mutate({ strict: true }),
27588
+ async (req, res) => {
27589
+ if (!requireTrustedWorkspaceRuntime(deps.workspaceRuntime, res)) return;
27590
+ const rawSkillName = req.params["name"];
27591
+ const scope = parseDeleteScope(req, res);
27592
+ if (!rawSkillName || !scope) return;
27593
+ let skillName;
27594
+ try {
27595
+ skillName = validateWorkspaceSkillName(rawSkillName);
27596
+ } catch (error2) {
27597
+ sendSkillManagementError(res, error2);
27598
+ return;
27599
+ }
27600
+ const clientId = deps.parseAndValidateClientId(req, res);
27601
+ if (clientId === null) return;
27602
+ const deleteRoute = "DELETE /workspace/skills/:name";
27603
+ try {
27604
+ const result = await deps.workspaceRuntime.workspaceService.deleteWorkspaceSkill(
27605
+ buildWorkspaceCtx(deleteRoute, clientId),
27606
+ skillName,
27607
+ scope
27608
+ );
27609
+ res.status(200).json(result);
27610
+ } catch (err) {
27611
+ if (!sendSkillManagementError(res, err))
27612
+ deps.sendBridgeError(res, err, { route: deleteRoute });
27613
+ }
27614
+ }
27615
+ );
26079
27616
  app.post(
26080
27617
  "/workspace/skills/:name/enable",
26081
27618
  deps.mutate({ strict: true }),
@@ -26101,6 +27638,77 @@ function registerWorkspaceSkillsRoutes(app, deps) {
26101
27638
  __name(registerWorkspaceSkillsRoutes, "registerWorkspaceSkillsRoutes");
26102
27639
  function registerWorkspaceQualifiedSkillsRoutes(app, deps) {
26103
27640
  const route = "POST /workspaces/:workspace/skills/:name/enable";
27641
+ app.post(
27642
+ "/workspaces/:workspace/skills/install",
27643
+ deps.mutate({ strict: true }),
27644
+ async (req, res) => {
27645
+ const runtime = resolveWorkspaceRuntimeFromParam(
27646
+ deps.workspaceRegistry,
27647
+ req,
27648
+ res
27649
+ );
27650
+ if (!runtime || !requireTrustedWorkspaceRuntime(runtime, res)) return;
27651
+ const input = parseSkillInstallRequest(req, res, deps.safeBody);
27652
+ if (!input) return;
27653
+ const clientId = parseAndValidateWorkspaceClientId(
27654
+ req,
27655
+ res,
27656
+ runtime.bridge
27657
+ );
27658
+ if (clientId === null) return;
27659
+ const installRoute = "POST /workspaces/:workspace/skills/install";
27660
+ try {
27661
+ const result = await runtime.workspaceService.installWorkspaceSkill(
27662
+ createBuildWorkspaceCtx(runtime.workspaceCwd)(installRoute, clientId),
27663
+ input
27664
+ );
27665
+ res.status(200).json(result);
27666
+ } catch (err) {
27667
+ if (!sendSkillManagementError(res, err))
27668
+ deps.sendBridgeError(res, err, { route: installRoute });
27669
+ }
27670
+ }
27671
+ );
27672
+ app.delete(
27673
+ "/workspaces/:workspace/skills/:name",
27674
+ deps.mutate({ strict: true }),
27675
+ async (req, res) => {
27676
+ const runtime = resolveWorkspaceRuntimeFromParam(
27677
+ deps.workspaceRegistry,
27678
+ req,
27679
+ res
27680
+ );
27681
+ if (!runtime || !requireTrustedWorkspaceRuntime(runtime, res)) return;
27682
+ const rawSkillName = req.params["name"];
27683
+ const scope = parseDeleteScope(req, res);
27684
+ if (!rawSkillName || !scope) return;
27685
+ let skillName;
27686
+ try {
27687
+ skillName = validateWorkspaceSkillName(rawSkillName);
27688
+ } catch (error2) {
27689
+ sendSkillManagementError(res, error2);
27690
+ return;
27691
+ }
27692
+ const clientId = parseAndValidateWorkspaceClientId(
27693
+ req,
27694
+ res,
27695
+ runtime.bridge
27696
+ );
27697
+ if (clientId === null) return;
27698
+ const deleteRoute = "DELETE /workspaces/:workspace/skills/:name";
27699
+ try {
27700
+ const result = await runtime.workspaceService.deleteWorkspaceSkill(
27701
+ createBuildWorkspaceCtx(runtime.workspaceCwd)(deleteRoute, clientId),
27702
+ skillName,
27703
+ scope
27704
+ );
27705
+ res.status(200).json(result);
27706
+ } catch (err) {
27707
+ if (!sendSkillManagementError(res, err))
27708
+ deps.sendBridgeError(res, err, { route: deleteRoute });
27709
+ }
27710
+ }
27711
+ );
26104
27712
  app.post(
26105
27713
  "/workspaces/:workspace/skills/:name/enable",
26106
27714
  deps.mutate({ strict: true }),
@@ -26525,6 +28133,12 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26525
28133
  boundWorkspace,
26526
28134
  persistSettingAvailable: deps.persistSetting !== void 0,
26527
28135
  sessionArtifactsPersistenceAvailable: deps.sessionArtifactsPersistenceAvailable !== false,
28136
+ sessionGenerationAvailable: /* @__PURE__ */ __name(() => {
28137
+ const runtimes = workspaceRegistry.list();
28138
+ return runtimes.length > 0 && runtimes.every(
28139
+ (runtime) => runtime.bridge.generateSessionContent !== void 0
28140
+ );
28141
+ }, "sessionGenerationAvailable"),
26528
28142
  // Registry injection supplies the primary workspace service through the
26529
28143
  // runtime, so it has the same reload surface as legacy deps.workspace.
26530
28144
  reloadAvailable: deps.workspace !== void 0 || injectedWorkspaceRegistry !== void 0,
@@ -26609,6 +28223,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26609
28223
  primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
26610
28224
  ),
26611
28225
  workspaceSkillsStatusProvider: createWorkspaceSkillsStatusProvider(),
28226
+ ...primaryEffectiveEnv ? { skillInstallEnv: primaryEffectiveEnv } : {},
26612
28227
  ...primaryEffectiveEnv ? { voiceEnv: primaryEffectiveEnv } : {},
26613
28228
  isChannelLive: /* @__PURE__ */ __name(() => bridge.isChannelLive(), "isChannelLive"),
26614
28229
  persistDisabledTools: deps.persistDisabledTools ?? (async () => {
@@ -26653,6 +28268,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26653
28268
  );
26654
28269
  app.locals.workspaceRegistry = workspaceRegistry;
26655
28270
  const primaryRuntime = workspaceRegistry.primary;
28271
+ const daemonEnv = deps.daemonEnv ?? process.env;
28272
+ const primaryRuntimeEffectiveEnv = getRuntimeEffectiveEnv(primaryRuntime.env) ?? daemonEnv;
26656
28273
  const voiceCoordinator = deps.voiceCoordinator ?? new WorkspaceVoiceCoordinator();
26657
28274
  const primaryBoundWorkspace = primaryRuntime.workspaceCwd;
26658
28275
  const primaryBridge = primaryRuntime.bridge;
@@ -26681,7 +28298,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26681
28298
  const healthDemoRoutes = createHealthDemoRoutes({
26682
28299
  opts,
26683
28300
  getPort,
26684
- bridge: primaryBridge,
28301
+ workspaceRegistry,
26685
28302
  getActiveSseCount,
26686
28303
  getRateLimiter: /* @__PURE__ */ __name(() => rateLimiter, "getRateLimiter")
26687
28304
  });
@@ -26742,38 +28359,27 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26742
28359
  requireAuth: opts.requireAuth === true
26743
28360
  });
26744
28361
  app.use(
26745
- daemonTelemetryMiddleware(
26746
- (req) => {
26747
- const match = req.path.match(/^\/workspaces\/([^/]+)/);
26748
- const rawSelector = match?.[1];
26749
- if (rawSelector) {
26750
- try {
26751
- const selector = decodeURIComponent(rawSelector);
26752
- const byId = workspaceRegistry.getByWorkspaceId(selector);
26753
- if (byId) return byId.workspaceCwd;
26754
- if (isPortableAbsolutePath(selector)) {
26755
- const runtime = resolveRegisteredWorkspaceRuntimeByPathSelector(
26756
- workspaceRegistry,
26757
- selector
26758
- );
26759
- if (runtime) return runtime.workspaceCwd;
26760
- }
26761
- } catch {
26762
- return primaryBoundWorkspace;
26763
- }
26764
- }
26765
- return primaryBoundWorkspace;
26766
- },
26767
- deps.recordDaemonRequest,
26768
- (sessionId) => {
28362
+ daemonTelemetryMiddleware((req) => {
28363
+ const match = req.path.match(/^\/workspaces\/([^/]+)/);
28364
+ const rawSelector = match?.[1];
28365
+ if (rawSelector) {
26769
28366
  try {
26770
- const owner = workspaceRegistry.resolveLiveSessionOwner(sessionId);
26771
- return owner.kind === "found" ? owner.runtime.workspaceCwd : void 0;
28367
+ const selector = decodeURIComponent(rawSelector);
28368
+ const byId = workspaceRegistry.getByWorkspaceId(selector);
28369
+ if (byId) return byId.workspaceCwd;
28370
+ if (isPortableAbsolutePath(selector)) {
28371
+ const runtime = resolveRegisteredWorkspaceRuntimeByPathSelector(
28372
+ workspaceRegistry,
28373
+ selector
28374
+ );
28375
+ if (runtime) return runtime.workspaceCwd;
28376
+ }
26772
28377
  } catch {
26773
- return void 0;
28378
+ return primaryBoundWorkspace;
26774
28379
  }
26775
28380
  }
26776
- )
28381
+ return primaryBoundWorkspace;
28382
+ }, deps.recordDaemonRequest)
26777
28383
  );
26778
28384
  const buildWorkspaceCtx = createBuildWorkspaceCtx(primaryBoundWorkspace);
26779
28385
  const acpHandleRef = {};
@@ -26915,6 +28521,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
26915
28521
  registerWorkspaceSetupGithubRoutes(app, {
26916
28522
  boundWorkspace: primaryBoundWorkspace,
26917
28523
  bridge: primaryBridge,
28524
+ env: primaryRuntimeEffectiveEnv,
26918
28525
  mutate,
26919
28526
  parseClientId: parseClientIdHeader,
26920
28527
  safeBody
@@ -27211,6 +28818,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
27211
28818
  });
27212
28819
  acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
27213
28820
  boundWorkspace: primaryBoundWorkspace,
28821
+ daemonEnv,
27214
28822
  // Phase 4 (issue #6378): pass the registry so `/workspaces/:workspace/acp`
27215
28823
  // mounts a per-runtime ACP dispatcher for each registered workspace.
27216
28824
  workspaceRegistry,
@@ -27282,6 +28890,7 @@ export {
27282
28890
  createServeApp,
27283
28891
  detectFromLoopback,
27284
28892
  getActiveSseCount,
28893
+ getWorkspaceSessionInfoForResponse,
27285
28894
  listWorkspaceSessionsForResponse,
27286
28895
  resolveBoundWorkspacesFromIdeEnv,
27287
28896
  resolveBridgeFsFactory,