@qwen-code/qwen-code 0.19.2 → 0.19.3-nightly.20260630.e00fe6a27

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 (286) hide show
  1. package/bundled/extension-creator/SKILL.md +357 -0
  2. package/bundled/loop/SKILL.md +21 -7
  3. package/bundled/loop/SKILL.test.ts +41 -0
  4. package/bundled/loop/loop-task-file.test.ts +1064 -0
  5. package/bundled/loop/loop-task-file.ts +404 -0
  6. package/bundled/loop/loop-tick-resolver.test.ts +665 -0
  7. package/bundled/loop/loop-tick-resolver.ts +347 -0
  8. package/bundled/qc-helper/SKILL.md +26 -19
  9. package/bundled/qc-helper/docs/configuration/auth.md +11 -11
  10. package/bundled/qc-helper/docs/configuration/model-providers.md +13 -13
  11. package/bundled/qc-helper/docs/configuration/settings.md +76 -75
  12. package/bundled/qc-helper/docs/features/channels/plugins.md +1 -1
  13. package/bundled/qc-helper/docs/features/commands.md +108 -77
  14. package/bundled/qc-helper/docs/features/hooks.md +6 -1
  15. package/bundled/qc-helper/docs/features/memory.md +52 -0
  16. package/bundled/qc-helper/docs/qwen-serve.md +24 -2
  17. package/bundled/qc-helper/docs/support/tos-privacy.md +16 -3
  18. package/bundled/qc-helper/docs/support/troubleshooting.md +6 -0
  19. package/chunks/{MaxSizedBox-7RERNLFK.js → MaxSizedBox-T5X5MN5Q.js} +29 -27
  20. package/chunks/{StandaloneSessionPicker-S22XBSN6.js → StandaloneSessionPicker-P3E3WTOQ.js} +42 -37
  21. package/chunks/{acpAgent-4MCETHF2.js → acpAgent-QEP6DXFW.js} +864 -175
  22. package/chunks/{agent-K3ENVYSB.js → agent-UDANDUF7.js} +24 -23
  23. package/chunks/{agent-headless-HO3V3A3A.js → agent-headless-KYVSZHSO.js} +24 -23
  24. package/chunks/{anthropicContentGenerator-E3TQ5XJJ.js → anthropicContentGenerator-KWSJAQ7B.js} +33 -12
  25. package/chunks/{artifact-tool-QA4KRO3B.js → artifact-tool-D2X7G3C3.js} +2 -2
  26. package/chunks/{askUserQuestion-HMWXW6VN.js → askUserQuestion-UGETICJQ.js} +2 -2
  27. package/chunks/{bridge-4LV2HBH2.js → bridge-X42LXPTA.js} +31 -30
  28. package/chunks/{ca-7WC7ELX6.js → ca-IUFWESZL.js} +1 -0
  29. package/chunks/{chunk-JXQ23SNT.js → chunk-2JKEQWDZ.js} +623 -78
  30. package/chunks/{chunk-2TJ3YN6Q.js → chunk-2RJA6J57.js} +416 -401
  31. package/chunks/{chunk-3UALQ56H.js → chunk-3227DZO4.js} +1 -1
  32. package/chunks/{chunk-BGUDAULQ.js → chunk-3CPCDXFR.js} +5 -5
  33. package/chunks/{chunk-5RVSM6NW.js → chunk-3HUHAQF3.js} +1 -1
  34. package/chunks/{chunk-D5E5TMYH.js → chunk-3M4W4U5G.js} +16 -2
  35. package/chunks/{chunk-DBZUXSSV.js → chunk-4X7NIEQJ.js} +3 -3
  36. package/chunks/chunk-5GOVVXEV.js +73 -0
  37. package/chunks/{chunk-2BAQ3ACS.js → chunk-5SM4VT6V.js} +405 -5
  38. package/chunks/{chunk-NYOHZYHM.js → chunk-5XQ4A26L.js} +45 -3
  39. package/chunks/{chunk-CI5O6SQL.js → chunk-6FKEVYCD.js} +4 -4
  40. package/chunks/{chunk-ZD3NW5KL.js → chunk-7LM4XHPE.js} +63 -9
  41. package/chunks/chunk-7UNP2XM7.js +840 -0
  42. package/chunks/{chunk-OQHQHJRK.js → chunk-ARYCHZ4B.js} +151 -4775
  43. package/chunks/chunk-BC3C4F3Q.js +40 -0
  44. package/chunks/{chunk-CGEGHF2C.js → chunk-BKXBARJZ.js} +1 -1
  45. package/chunks/chunk-BMFMJINR.js +45 -0
  46. package/chunks/chunk-BOJWHRMX.js +11273 -0
  47. package/chunks/{chunk-CGOMICBE.js → chunk-BSZEQNUA.js} +34 -1
  48. package/chunks/{chunk-OIC6S73E.js → chunk-BUUQ5HPX.js} +1 -1
  49. package/chunks/{chunk-2BIF2NVV.js → chunk-BVSVIN45.js} +2 -2
  50. package/chunks/{chunk-TOEGRAVX.js → chunk-BX5YO7UW.js} +17 -5
  51. package/chunks/{chunk-4W4T77MO.js → chunk-BXVWV4GI.js} +109 -6
  52. package/chunks/{chunk-VQRYPFCV.js → chunk-CYHVPQYT.js} +10 -460
  53. package/chunks/{chunk-PRYMDRBV.js → chunk-DDMOU62Q.js} +1 -1
  54. package/chunks/{chunk-S566HKUS.js → chunk-DHXWNSJA.js} +15 -1
  55. package/chunks/{chunk-F6XNTYNE.js → chunk-E6XQPQXW.js} +30 -307
  56. package/chunks/{chunk-QBZ22PQX.js → chunk-EWALXUAD.js} +3 -1
  57. package/chunks/{chunk-EL5IHQON.js → chunk-EWYQFWYF.js} +6 -27
  58. package/chunks/{chunk-HG6YKEBI.js → chunk-F2DOT6UZ.js} +161 -30
  59. package/chunks/{chunk-JTYRZODB.js → chunk-FOOIZCWL.js} +16 -7
  60. package/chunks/{chunk-EX4W6ZYG.js → chunk-G5G4TFZ7.js} +1 -1
  61. package/chunks/{chunk-EW6C27XX.js → chunk-GEHVIWAT.js} +9 -3
  62. package/chunks/chunk-HEVBZSXG.js +4923 -0
  63. package/chunks/chunk-HFQ2XSE7.js +690 -0
  64. package/chunks/{chunk-PF523XJX.js → chunk-HPGTGMP3.js} +1 -1
  65. package/chunks/{chunk-OTBK43JR.js → chunk-HYCC3XM3.js} +1 -1
  66. package/chunks/{chunk-TMBPDHXD.js → chunk-I4H7PRWQ.js} +1 -1
  67. package/chunks/{chunk-EEEZIVFJ.js → chunk-JOLIREYR.js} +1 -1
  68. package/chunks/{chunk-TZM5JIAX.js → chunk-JYPQTRA3.js} +10 -7
  69. package/chunks/chunk-K5XU6E4T.js +167 -0
  70. package/chunks/{chunk-BS64PXY3.js → chunk-KFVU7ODN.js} +1 -1
  71. package/chunks/{chunk-3RJ3ZPPR.js → chunk-KKQWC6WS.js} +7 -7
  72. package/chunks/{chunk-3QFE4OTE.js → chunk-LBW7NW7X.js} +4 -4
  73. package/chunks/{chunk-Z7XXFPGP.js → chunk-LDWTYE33.js} +1 -1
  74. package/chunks/{chunk-EXMX5YHG.js → chunk-LP5E4YIH.js} +1 -1
  75. package/chunks/{chunk-ZUAXI2OA.js → chunk-M2U5NM24.js} +188 -11366
  76. package/chunks/{chunk-I5T6PIBQ.js → chunk-MBV2CTRL.js} +1010 -925
  77. package/chunks/{chunk-5JZLXFPD.js → chunk-MTHMXSNT.js} +11 -11
  78. package/chunks/{chunk-FPACXT7T.js → chunk-MTJVHQDP.js} +534 -164
  79. package/chunks/chunk-NDOC6M5S.js +481 -0
  80. package/chunks/{chunk-HGNSRCRB.js → chunk-NL4C3H6C.js} +1 -1
  81. package/chunks/{chunk-GZCJS5WH.js → chunk-O2VBQ3Y2.js} +2 -2
  82. package/chunks/{chunk-UN3C6GOR.js → chunk-PPFWEV7G.js} +10 -108
  83. package/chunks/{chunk-RS4HRC75.js → chunk-QI2CFVRF.js} +85 -8
  84. package/chunks/{chunk-XU5P23GN.js → chunk-QLDPRILK.js} +3 -3
  85. package/chunks/chunk-QYUE6W3T.js +123 -0
  86. package/chunks/{chunk-USGMPVOY.js → chunk-R3LHDWF2.js} +21 -12
  87. package/chunks/{chunk-BNXANYLH.js → chunk-RD6YJJJ6.js} +81 -1
  88. package/chunks/{chunk-PXFFKNCO.js → chunk-RIP623NO.js} +4877 -2469
  89. package/chunks/{chunk-XKBP7M7A.js → chunk-RYBSUGOR.js} +142 -30
  90. package/chunks/{chunk-BG4BIP7F.js → chunk-SBBN4BWR.js} +4 -2
  91. package/chunks/{chunk-T2VDEFUU.js → chunk-SKQZZVAV.js} +2 -2
  92. package/chunks/{chunk-5R4SBCX6.js → chunk-SL5MOGQH.js} +3 -3
  93. package/chunks/chunk-SMXULRAN.js +37 -0
  94. package/chunks/{chunk-WA5OJGFL.js → chunk-SS6WJMQK.js} +363 -76
  95. package/chunks/{chunk-UAARVVBI.js → chunk-TNWFHGN6.js} +1 -1
  96. package/chunks/{chunk-I2RFAW6Q.js → chunk-TT6Q3EN4.js} +7 -5
  97. package/chunks/chunk-UAKXW3DN.js +30 -0
  98. package/chunks/{chunk-C4K3FEQ2.js → chunk-UX4SGCGN.js} +32 -3
  99. package/chunks/{chunk-J6AW7O5D.js → chunk-WHDQZHRU.js} +2 -2
  100. package/chunks/{chunk-WGAEWQTF.js → chunk-WN6K47NR.js} +1 -2
  101. package/chunks/{chunk-UAARJR2G.js → chunk-WQT5SOI6.js} +2 -2
  102. package/chunks/{chunk-VYFMN7C6.js → chunk-WUMVIRTN.js} +225 -37
  103. package/chunks/{chunk-R36VMVEP.js → chunk-XJMKOTVV.js} +5 -5
  104. package/chunks/{chunk-TXVGVZYR.js → chunk-XJYUPHRC.js} +3 -3
  105. package/chunks/{chunk-2JD55C6G.js → chunk-Y6YMRS3U.js} +2 -2
  106. package/chunks/{chunk-LLFFKXZZ.js → chunk-YALKC62D.js} +56 -29
  107. package/chunks/{chunk-GYZQA2FO.js → chunk-YLZJCUH6.js} +1 -1
  108. package/chunks/chunk-YTFBURQD.js +313 -0
  109. package/chunks/{chunk-KBXLIVWQ.js → chunk-ZFPRYHWR.js} +2 -2
  110. package/chunks/{chunk-X6EDWN44.js → chunk-ZP6UKOPB.js} +1 -1
  111. package/chunks/{computer-use-6BBRNT6S.js → computer-use-LF2S6LUZ.js} +103 -49
  112. package/chunks/{contextCommand-UJAJ6N57.js → contextCommand-VPX5UG55.js} +26 -25
  113. package/chunks/{cron-create-4KQE6YLH.js → cron-create-SKEY55RG.js} +4 -4
  114. package/chunks/{cron-delete-THME66UP.js → cron-delete-I3NAT32Z.js} +6 -6
  115. package/chunks/{cron-list-7A54SJ5N.js → cron-list-6XRRL6TH.js} +5 -5
  116. package/chunks/{daemon-status-provider-CSL3BUOY.js → daemon-status-provider-5JAWZS4V.js} +34 -34
  117. package/chunks/{de-ACHALDED.js → de-EOW5PVHF.js} +1 -0
  118. package/chunks/{dist-BD27IA3L.js → dist-4FCNM6KJ.js} +2 -2
  119. package/chunks/{dist-OD2FY543.js → dist-O3H4PABL.js} +2 -2
  120. package/chunks/{dist-BOOH5JWN.js → dist-SCAAUWPS.js} +18 -4
  121. package/chunks/{dist-QHJRBCMP.js → dist-UKPWQJCL.js} +44 -2
  122. package/chunks/{dist-QFFZWACU.js → dist-VD7HXTML.js} +20 -9
  123. package/chunks/{earlyInputCapture-X6KMCSHD.js → earlyInputCapture-7FRQMU4P.js} +25 -24
  124. package/chunks/{edit-7J6WXARF.js → edit-REKJDIRL.js} +68 -27
  125. package/chunks/{en-NCUBOJOY.js → en-HPWEJBTR.js} +8 -0
  126. package/chunks/{enter-worktree-KULCKJPJ.js → enter-worktree-GBKUDCD3.js} +24 -23
  127. package/chunks/{enterPlanMode-H2CIOLMH.js → enterPlanMode-WB3Y4FGT.js} +24 -23
  128. package/chunks/{errors-6G2JYR54.js → errors-2XJDYO3M.js} +26 -25
  129. package/chunks/{exit-worktree-ECBWBVC5.js → exit-worktree-KKC7O2ZV.js} +24 -23
  130. package/chunks/{exitPlanMode-DQV56GTW.js → exitPlanMode-7HMS3TF7.js} +24 -23
  131. package/chunks/{fast-path-35JJFS3C.js → fast-path-XVNIYWGG.js} +4 -4
  132. package/chunks/{fast-path-settings-TSVI53EB.js → fast-path-settings-UQLRFDQP.js} +3 -2
  133. package/chunks/{fr-GVKZ27MF.js → fr-BN5NKSAC.js} +1 -0
  134. package/chunks/{gemini-NDTG7WAX.js → gemini-U5TPU3IQ.js} +210 -104
  135. package/chunks/{geminiContentGenerator-XTG6SFLA.js → geminiContentGenerator-ZVWRHXOO.js} +4 -4
  136. package/chunks/{glob-SJ2JBZK4.js → glob-FEJWIH2W.js} +24 -23
  137. package/chunks/{grep-BRMWFEWR.js → grep-KMP25IIA.js} +24 -23
  138. package/chunks/{headlessSafetyWarnings-LJ6FJX77.js → headlessSafetyWarnings-5DEDET4M.js} +24 -23
  139. package/chunks/{initializer-P5AXF7PV.js → initializer-FJTACLOH.js} +31 -28
  140. package/chunks/{ja-FKZ2WZ4D.js → ja-7DEUB2TS.js} +1 -0
  141. package/chunks/{keychain-token-storage-CSYMNRPP.js → keychain-token-storage-YLMDLKXT.js} +2 -2
  142. package/chunks/{list-6COK34BP.js → list-SCQXYJUW.js} +32 -29
  143. package/chunks/{loadedSettingsAdapter-XIUTN245.js → loadedSettingsAdapter-P6KPNAG7.js} +30 -27
  144. package/chunks/{loop-wakeup-33GPXJLA.js → loop-wakeup-FYEQEJUA.js} +7 -7
  145. package/chunks/{ls-BYQY7RVV.js → ls-R5WP4BGZ.js} +4 -4
  146. package/chunks/{lsp-X54RO4IV.js → lsp-GSICJMMW.js} +2 -2
  147. package/chunks/{monitor-DH7KFSJV.js → monitor-JU3HHHVY.js} +24 -23
  148. package/chunks/nonInteractiveCli-IZEKUHU3.js +100 -0
  149. package/chunks/{notebook-edit-D4R4ZLMA.js → notebook-edit-YHY3Z2QQ.js} +52 -23
  150. package/chunks/{openaiContentGenerator-F74IPQ6E.js → openaiContentGenerator-4WUVA3Q2.js} +13 -12
  151. package/chunks/{pt-SY5NCFGR.js → pt-TNZRNLQB.js} +1 -0
  152. package/chunks/{qwenContentGenerator-ATTK5P4D.js → qwenContentGenerator-MVYYR44B.js} +26 -25
  153. package/chunks/{qwenOAuth2-K4AASPCV.js → qwenOAuth2-6HNGHALT.js} +5 -4
  154. package/chunks/{read-file-767G23OY.js → read-file-NABEO2X4.js} +8 -8
  155. package/chunks/{read-mcp-resource-I5HCZJ6X.js → read-mcp-resource-DQQW7H7T.js} +2 -2
  156. package/chunks/{ripGrep-4OMMGSWX.js → ripGrep-YXLK6UTX.js} +24 -23
  157. package/chunks/{ru-FWNXJG4F.js → ru-NIAUBKCN.js} +1 -0
  158. package/chunks/{run-qwen-serve-REKSTYRA.js → run-qwen-serve-4B5QBMLQ.js} +144 -41
  159. package/chunks/{scheduler-UNTFDQLG.js → scheduler-XAKIYBDL.js} +24 -23
  160. package/chunks/{send-message-2DAFXEYP.js → send-message-EE4TWKVU.js} +2 -2
  161. package/chunks/{serve-KZ56QB5S.js → serve-4RXVLUKD.js} +30 -28
  162. package/chunks/{server-BV5TZUMU.js → server-7PA5QGIA.js} +11037 -8747
  163. package/chunks/{session-OIBXFSGD.js → session-WNVWRYAH.js} +194 -57
  164. package/chunks/{settings-WJTCBIRA.js → settings-YJH32TFF.js} +30 -27
  165. package/chunks/{shell-WC52IBHW.js → shell-YFLABOS5.js} +24 -23
  166. package/chunks/{skill-U7F7JR4M.js → skill-N3J7FUAY.js} +38 -11
  167. package/chunks/{spawnChannel-EI2E5BCW.js → spawnChannel-D6WVMFZJ.js} +26 -25
  168. package/chunks/{src-4F6FBZFI.js → src-IU5GDBEH.js} +88 -28
  169. package/chunks/{startInteractiveUI-SFRVB3CE.js → startInteractiveUI-QIPQTRT4.js} +2784 -2474
  170. package/chunks/{syntheticOutput-PPS3HDVA.js → syntheticOutput-T5YHQ6S2.js} +3 -3
  171. package/chunks/{task-create-OUYCA553.js → task-create-BLY7RHXX.js} +6 -6
  172. package/chunks/{task-list-WAX7I2IA.js → task-list-3QUYNVYR.js} +5 -5
  173. package/chunks/{task-stop-CAIL6FNH.js → task-stop-U4RATK2V.js} +2 -2
  174. package/chunks/{task-update-AHEO5OUT.js → task-update-U54O7KJX.js} +6 -6
  175. package/chunks/{team-create-3WC7CIIW.js → team-create-TP4CLLM3.js} +24 -23
  176. package/chunks/{team-delete-HGHFG23B.js → team-delete-LKBYPASD.js} +5 -5
  177. package/chunks/{theme-manager-DICFCT3P.js → theme-manager-N2TBIBZT.js} +25 -24
  178. package/chunks/{todoWrite-IFBMN3FH.js → todoWrite-OYXKTVYN.js} +4 -4
  179. package/chunks/{tool-search-L5K7HLER.js → tool-search-GBBSICYB.js} +101 -16
  180. package/chunks/trustedFolders-F7TBU5CD.js +76 -0
  181. package/chunks/types-QX5C3CHJ.js +12 -0
  182. package/chunks/{validateNonInterActiveAuth-GCH4Z6KI.js → validateNonInterActiveAuth-EQDQPSMI.js} +55 -50
  183. package/chunks/{web-fetch-B5IIQ5TT.js → web-fetch-PCVCML2X.js} +29 -15
  184. package/chunks/{workflow-OB3AND7I.js → workflow-ANJ4FYBK.js} +32 -30
  185. package/chunks/{workspace-providers-status-ZIR5EPOO.js → workspace-providers-status-462QQKQM.js} +32 -29
  186. package/chunks/workspace-service-VTG4G6CW.js +75 -0
  187. package/chunks/{write-file-SEXBNDZM.js → write-file-3P3WMQQW.js} +63 -27
  188. package/chunks/{zh-RBEGQVQT.js → zh-5EUYXASN.js} +8 -0
  189. package/chunks/{zh-TW-QGAVRXT3.js → zh-TW-TR3XYGE5.js} +8 -0
  190. package/cli-entry.js +20 -9
  191. package/cli.js +6 -6
  192. package/locales/ca.js +2 -0
  193. package/locales/de.js +2 -0
  194. package/locales/en.js +14 -0
  195. package/locales/fr.js +2 -0
  196. package/locales/ja.js +1 -0
  197. package/locales/pt.js +2 -0
  198. package/locales/ru.js +2 -0
  199. package/locales/zh-TW.js +12 -0
  200. package/locales/zh.js +12 -0
  201. package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +35 -0
  202. package/node_modules/@qwen-code/audio-capture/dist/index.js +48 -0
  203. package/node_modules/@qwen-code/audio-capture/dist/index.js.map +1 -0
  204. package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +7 -0
  205. package/node_modules/@qwen-code/audio-capture/dist/platform.js +18 -0
  206. package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +1 -0
  207. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +21 -0
  208. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +58 -0
  209. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +5 -0
  210. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +84 -0
  211. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +19 -0
  212. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +6 -0
  213. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +207 -0
  214. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +7 -0
  215. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +43 -0
  216. package/node_modules/@qwen-code/audio-capture/package.json +30 -0
  217. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  218. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  219. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
  220. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
  221. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  222. package/package.json +18 -6
  223. package/patches/chrome-devtools-mcp+1.4.0.patch +31 -0
  224. package/postinstall.js +50 -0
  225. package/web-shell/assets/{arc-D_ae_Y9k.js → arc-DIemsO_F.js} +1 -1
  226. package/web-shell/assets/{architectureDiagram-3BPJPVTR-BMLRjppa.js → architectureDiagram-3BPJPVTR-CTlUvIQv.js} +1 -1
  227. package/web-shell/assets/{blockDiagram-GPEHLZMM-qVDQC8KL.js → blockDiagram-GPEHLZMM-DG0jmIZK.js} +1 -1
  228. package/web-shell/assets/{c4Diagram-AAUBKEIU-CxWS6MBd.js → c4Diagram-AAUBKEIU-WljDBi55.js} +1 -1
  229. package/web-shell/assets/channel-CbzRbdpA.js +1 -0
  230. package/web-shell/assets/{chunk-2J33WTMH-BtNuY5Yp.js → chunk-2J33WTMH-8nc6onr2.js} +1 -1
  231. package/web-shell/assets/{chunk-4BX2VUAB-BU-x368d.js → chunk-4BX2VUAB-EopXix8Z.js} +1 -1
  232. package/web-shell/assets/{chunk-55IACEB6-DRgTLvBu.js → chunk-55IACEB6-BE4Jz3N3.js} +1 -1
  233. package/web-shell/assets/{chunk-727SXJPM-D2aElv7q.js → chunk-727SXJPM-C_eErgDN.js} +1 -1
  234. package/web-shell/assets/{chunk-AQP2D5EJ-BwHCMRQ0.js → chunk-AQP2D5EJ-DFtVW-Is.js} +1 -1
  235. package/web-shell/assets/{chunk-FMBD7UC4-BMyPH-ku.js → chunk-FMBD7UC4-CJPyxIg9.js} +1 -1
  236. package/web-shell/assets/{chunk-ND2GUHAM-BNKTstUf.js → chunk-ND2GUHAM-Bk-xgj6M.js} +1 -1
  237. package/web-shell/assets/{chunk-QZHKN3VN-gD3vsFId.js → chunk-QZHKN3VN-p3Y4yaFB.js} +1 -1
  238. package/web-shell/assets/classDiagram-4FO5ZUOK-BFdyQ52h.js +1 -0
  239. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BFdyQ52h.js +1 -0
  240. package/web-shell/assets/{cose-bilkent-S5V4N54A-BG9FAsXE.js → cose-bilkent-S5V4N54A-BCMO6Js3.js} +1 -1
  241. package/web-shell/assets/{dagre-BM42HDAG-Cy1sR7om.js → dagre-BM42HDAG-DUMrwASf.js} +1 -1
  242. package/web-shell/assets/default-aEtf0G7-.svg +1 -0
  243. package/web-shell/assets/{diagram-2AECGRRQ-Bxi1I_Vu.js → diagram-2AECGRRQ-C5d7qJbL.js} +1 -1
  244. package/web-shell/assets/{diagram-5GNKFQAL-BGCJjO6y.js → diagram-5GNKFQAL-CjLzMhbT.js} +1 -1
  245. package/web-shell/assets/{diagram-KO2AKTUF-CMTeLXp7.js → diagram-KO2AKTUF-RCoNWeAm.js} +1 -1
  246. package/web-shell/assets/{diagram-LMA3HP47-BN1wyAGh.js → diagram-LMA3HP47-KThXjaNV.js} +1 -1
  247. package/web-shell/assets/{diagram-OG6HWLK6-UYSG_zcp.js → diagram-OG6HWLK6-DKsC2BWz.js} +1 -1
  248. package/web-shell/assets/{erDiagram-TEJ5UH35-DqXL08lw.js → erDiagram-TEJ5UH35-DJ2ukmq0.js} +1 -1
  249. package/web-shell/assets/{flowDiagram-I6XJVG4X-BPJ9SFji.js → flowDiagram-I6XJVG4X-zzqaARRX.js} +1 -1
  250. package/web-shell/assets/{ganttDiagram-6RSMTGT7-BEd9Pnms.js → ganttDiagram-6RSMTGT7-kFUg-gqT.js} +1 -1
  251. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-DrNRH3oi.js → gitGraphDiagram-PVQCEYII-C6JnMVzD.js} +1 -1
  252. package/web-shell/assets/index-B3XUm7dw.js +713 -0
  253. package/web-shell/assets/index-CHmzAWys.css +5 -0
  254. package/web-shell/assets/{infoDiagram-5YYISTIA-CFYBrkVI.js → infoDiagram-5YYISTIA-XqPVhp89.js} +1 -1
  255. package/web-shell/assets/insert-DmRbh9Rv.svg +1 -0
  256. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-Dxsddth7.js → ishikawaDiagram-YF4QCWOH-D2k8sGpf.js} +1 -1
  257. package/web-shell/assets/{journeyDiagram-JHISSGLW-DxaDK80t.js → journeyDiagram-JHISSGLW-CQEST1GE.js} +1 -1
  258. package/web-shell/assets/{kanban-definition-UN3LZRKU-Q0jQCOct.js → kanban-definition-UN3LZRKU-DZ7kqVBC.js} +1 -1
  259. package/web-shell/assets/{linear-DGGM2kcP.js → linear-B6C_6q_E.js} +1 -1
  260. package/web-shell/assets/{mermaid.core-ByoxnWut.js → mermaid.core-CsyNP1qt.js} +5 -5
  261. package/web-shell/assets/{mindmap-definition-RKZ34NQL-C0ZseHsi.js → mindmap-definition-RKZ34NQL-B1VDIzJq.js} +1 -1
  262. package/web-shell/assets/{pieDiagram-4H26LBE5-MQXNhl5A.js → pieDiagram-4H26LBE5-DN0E7Jwu.js} +1 -1
  263. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DIR4ee2A.js → quadrantDiagram-W4KKPZXB-UKTQdHKm.js} +1 -1
  264. package/web-shell/assets/queue-DWpnpFgW.svg +1 -0
  265. package/web-shell/assets/{requirementDiagram-4Y6WPE33-BTR0UdYQ.js → requirementDiagram-4Y6WPE33-BRGceQvN.js} +1 -1
  266. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-sfnhMELN.js → sankeyDiagram-5OEKKPKP-2DDyu41v.js} +1 -1
  267. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DXczHOHH.js → sequenceDiagram-3UESZ5HK-CT5iE8ZU.js} +1 -1
  268. package/web-shell/assets/{stateDiagram-AJRCARHV-DdE_KQFH.js → stateDiagram-AJRCARHV-CqMQ_s4G.js} +1 -1
  269. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CamhV5pM.js +1 -0
  270. package/web-shell/assets/{timeline-definition-PNZ67QCA-DIc61uE8.js → timeline-definition-PNZ67QCA-Di37QSZU.js} +1 -1
  271. package/web-shell/assets/{vennDiagram-CIIHVFJN-BF7ODmxB.js → vennDiagram-CIIHVFJN-DCXvpz5S.js} +1 -1
  272. package/web-shell/assets/{wardley-L42UT6IY-3pc1MEaw.js → wardley-L42UT6IY-CpUCk6OX.js} +1 -1
  273. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-9jnPcZuP.js → wardleyDiagram-YWT4CUSO-D01pVEBg.js} +1 -1
  274. package/web-shell/assets/{xychartDiagram-2RQKCTM6-DcthaZK6.js → xychartDiagram-2RQKCTM6-DOu5JDoz.js} +1 -1
  275. package/web-shell/index.html +2 -2
  276. package/chunks/chunk-B6HQGTYR.js +0 -410
  277. package/chunks/chunk-R2BXK7SX.js +0 -13
  278. package/chunks/chunk-RKIZXJMB.js +0 -13
  279. package/chunks/nonInteractiveCli-7575LBXP.js +0 -91
  280. package/chunks/workspace-service-OM5D4OI2.js +0 -60
  281. package/web-shell/assets/channel-DYPNiTww.js +0 -1
  282. package/web-shell/assets/classDiagram-4FO5ZUOK-p_g25Tni.js +0 -1
  283. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-p_g25Tni.js +0 -1
  284. package/web-shell/assets/index-CpOXWDPh.js +0 -714
  285. package/web-shell/assets/index-oVK7qhre.css +0 -5
  286. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BHUSEndU.js +0 -1
@@ -0,0 +1,347 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import * as path from 'node:path';
8
+ import { tildeifyPath } from '../../../utils/paths.js';
9
+ import {
10
+ LOOP_TASK_FILE_MAX_BYTES,
11
+ readLoopTaskFile,
12
+ type LoopTaskFileSource,
13
+ } from './loop-task-file.js';
14
+
15
+ /**
16
+ * Fire-time resolver for `.qwen/loop.md`-driven loops.
17
+ *
18
+ * A `/loop` whose scheduled prompt is one of these sentinels re-reads loop.md
19
+ * on every fire and gets either the FULL task block (first delivery, or whenever
20
+ * the file changed) or a one-line SHORT reminder (unchanged) — so the task list
21
+ * is paid for once into the cached message-prefix and later ticks stay cheap.
22
+ *
23
+ * Divergence from the upstream design this mirrors: the `lastContent` cache is
24
+ * held per Session instance (not a module singleton) so it scopes to one
25
+ * conversation and resets cleanly with that conversation's context (compaction).
26
+ * Change-detection is full content equality, not mtime/hash, so edit and
27
+ * delete→recreate both re-expand for free.
28
+ */
29
+
30
+ export const LOOP_SENTINEL_CRON = '<<loop.md>>';
31
+ export const LOOP_SENTINEL_DYNAMIC = '<<loop.md-dynamic>>';
32
+
33
+ export type LoopMode = 'cron' | 'dynamic';
34
+
35
+ export interface LoopTickResolverDeps {
36
+ /** Pass `config.getWorkingDir()` — loop.md is resolved against the cwd. */
37
+ projectRoot: string;
38
+ /** Home-candidate confinement root: `$QWEN_HOME` when set, else `$HOME`. */
39
+ homeDir: string;
40
+ /**
41
+ * QWEN_HOME-aware global dir holding the home `loop.md` (`Storage.getGlobalQwenDir()`).
42
+ * Omitted → defaults to `<homeDir>/.qwen` inside readLoopTaskFile.
43
+ */
44
+ homeQwenDir?: string;
45
+ /**
46
+ * Pass `() => config.isTrustedFolder()`. Re-evaluated on every `resolve()`,
47
+ * never captured once: `isTrustedFolder()` is not process-stable in IDE
48
+ * sessions (a workspace-trust update can flip it), and a trusted→untrusted
49
+ * flip must immediately stop reading the repo-controlled project
50
+ * `.qwen/loop.md` (the user-owned `~/.qwen/loop.md` still is read).
51
+ */
52
+ allowProjectFile: () => boolean;
53
+ }
54
+
55
+ export interface LoopTickResult {
56
+ /** Text to deliver to the model in place of the sentinel prompt. */
57
+ modelText: string;
58
+ /** True when the full task block was delivered (vs a short reminder). */
59
+ full: boolean;
60
+ /** Non-absolute label for the matched candidate (e.g. "project loop.md"),
61
+ * when present — safe for logs/UI that must not leak the absolute path, and
62
+ * doubles as the "a loop.md was found" flag for callers. */
63
+ sourceLabel?: string;
64
+ /** True ONLY for buildTransientErrorTick: a loop.md exists but could not be
65
+ * read THIS tick (a transient EACCES/EIO or editor/AV lock), as distinct from
66
+ * the genuinely-absent no-op (where this stays false). Lets the caller's echo
67
+ * say "temporarily unavailable" instead of "not present". Carries no errno or
68
+ * path — those stay in the modelText note and LOCAL debug logs only. */
69
+ transientError?: boolean;
70
+ }
71
+
72
+ const TRUNCATION_WARNING = `> WARNING: loop.md was truncated to ${LOOP_TASK_FILE_MAX_BYTES} bytes. Keep the task list concise.`;
73
+
74
+ const INTRO =
75
+ 'The user configured a loop-tasks file. Work through the tasks defined below; these are the instructions for this tick and every subsequent tick (the reminder on later fires refers back to this message).';
76
+
77
+ // Mode-specific pacing guidance. Appended to BOTH the full block and the short
78
+ // reminder — the no-op/re-arm instruction applies on every tick.
79
+ const PACING_SUFFIX: Record<LoopMode, string> = {
80
+ cron: 'The recurring cron fires the next tick automatically — do not call LoopWakeup from this tick.',
81
+ dynamic: `You scheduled this tick via LoopWakeup (not a recurring cron). To keep the loop alive, call LoopWakeup again at the end of this turn with prompt set to the literal sentinel \`${LOOP_SENTINEL_DYNAMIC}\` — otherwise the loop ends after this tick.`,
82
+ };
83
+
84
+ // Preamble for the UNCHANGED-tick reminder, which points back to the full block
85
+ // delivered on an earlier fire. NOT used on the first/changed full delivery,
86
+ // where the block is present in THIS message — there is no "earlier" to refer
87
+ // back to, so claiming the contents were established earlier would contradict
88
+ // the INTRO that sits right above them.
89
+ const SHORT_REMINDER_PREAMBLE =
90
+ 'Work the tasks from the loop.md contents established earlier in this conversation. If you cannot find them, treat this as a no-op tick.';
91
+
92
+ /**
93
+ * The single H1 for every tick variant (full block, short reminder, absent), so
94
+ * they share one heading style and the dynamic-pacing suffix lives in one place.
95
+ * `sourceLabel` (set only on a full-block delivery) is a relative label like
96
+ * "project loop.md", never the absolute path — so the resolved file location
97
+ * isn't leaked to the model/API provider.
98
+ */
99
+ function tickHeading(
100
+ mode: LoopMode,
101
+ opts: { sourceLabel?: string; absent?: boolean; unavailable?: boolean } = {},
102
+ ): string {
103
+ // `unavailable` (transient read failure) is distinct from `absent`: the file
104
+ // exists but couldn't be read THIS tick, so the heading must not claim it's gone.
105
+ const subject = opts.unavailable
106
+ ? 'loop.md unavailable'
107
+ : opts.absent
108
+ ? 'loop.md absent'
109
+ : opts.sourceLabel
110
+ ? `loop.md tasks from ${opts.sourceLabel}`
111
+ : 'loop.md tasks';
112
+ const base = `# /loop tick — ${subject}`;
113
+ return mode === 'dynamic' ? `${base} (dynamic pacing)` : base;
114
+ }
115
+
116
+ /** Model-safe relative label per source — exhaustive, so a new loop.md
117
+ * candidate added to readLoopTaskFile won't compile until it gets a label
118
+ * (rather than silently mislabelling it). */
119
+ const SOURCE_LABELS: Record<LoopTaskFileSource, string> = {
120
+ project: 'project loop.md',
121
+ home: 'home loop.md',
122
+ };
123
+
124
+ // Per-mode tail of the absent reminder. The shared prefix (built in absentBody)
125
+ // names the candidate location(s) actually checked; only this no-op/re-arm
126
+ // guidance differs by mode.
127
+ const ABSENT_TAIL: Record<LoopMode, string> = {
128
+ cron: 'Treat this as a no-op tick; the recurring cron fires the next tick automatically.',
129
+ dynamic: `Treat this as a no-op tick. To pick it up if it is recreated, call LoopWakeup again with prompt set to the literal sentinel \`${LOOP_SENTINEL_DYNAMIC}\` — otherwise the loop ends after this tick.`,
130
+ };
131
+
132
+ // Body of the absent reminder — the H1 is supplied by tickHeading() so the
133
+ // absent tick shares the same heading style as the full block and reminder.
134
+ // `locations` is LoopTickResolver.absentLocations(): the candidate path(s)
135
+ // ACTUALLY checked this tick (the project candidate is omitted on an untrusted
136
+ // folder), with a QWEN_HOME-aware home label that is never a raw absolute path.
137
+ function absentBody(mode: LoopMode, locations: string): string {
138
+ return `loop.md is not currently present at ${locations}. ${ABSENT_TAIL[mode]}`;
139
+ }
140
+
141
+ /** Detect whether a scheduled prompt is a loop.md sentinel, and which mode. */
142
+ export function detectLoopSentinel(prompt: string): LoopMode | null {
143
+ const trimmed = prompt.trim();
144
+ if (trimmed === LOOP_SENTINEL_DYNAMIC) {
145
+ return 'dynamic';
146
+ }
147
+ if (trimmed === LOOP_SENTINEL_CRON) {
148
+ return 'cron';
149
+ }
150
+ return null;
151
+ }
152
+
153
+ /** Trim a truncated body back to its last full line before the warning tail. */
154
+ function cutToLastNewline(content: string): string {
155
+ const cut = content.lastIndexOf('\n');
156
+ // `> 0`, not `>= 0`: when the only newline is at index 0 (or there is none),
157
+ // there is no complete line to keep, so cutting would empty the body and leave
158
+ // the INTRO promising tasks that aren't there. Keep the (truncated) content
159
+ // instead — only a genuine trailing partial line (newline at index > 0) is
160
+ // dropped so the warning never glues onto a half-line.
161
+ return cut > 0 ? content.slice(0, cut) : content;
162
+ }
163
+
164
+ export class LoopTickResolver {
165
+ // What the model has actually received. Drives full-vs-reminder detection.
166
+ #lastContent: string | null = null;
167
+ // The most recent resolve()'s content, committed to #lastContent only once
168
+ // the caller confirms it reached the model (markDelivered) — so a tick that
169
+ // is aborted between resolve() and delivery can't poison the cache into
170
+ // sending a dangling short reminder next time.
171
+ #pendingContent: string | null = null;
172
+ // Instance-scoped fs.realpath cache for the confinement boundaries, handed to
173
+ // readLoopTaskFile. Tying it to the resolver (a fresh Map per /cd rebuild,
174
+ // cleared by resetCache) keeps the per-tick perf win while staying
175
+ // invalidatable — a module-global cache would pin a stale boundary in a
176
+ // long-lived process after a /cd or symlink re-point.
177
+ readonly #realDirCache = new Map<string, Promise<string>>();
178
+
179
+ constructor(private readonly deps: LoopTickResolverDeps) {}
180
+
181
+ /** Forget the delivered content so the next fire re-delivers the full block
182
+ * — called when the conversation is compacted (fresh context). */
183
+ resetCache(): void {
184
+ this.#lastContent = null;
185
+ this.#pendingContent = null;
186
+ // A reset may follow a /cd or symlink change, so drop the cached boundary
187
+ // realpaths too and re-resolve them on the next tick.
188
+ this.#realDirCache.clear();
189
+ }
190
+
191
+ /** Commit the last resolve()'s content once it has reached the model. */
192
+ markDelivered(): void {
193
+ if (this.#pendingContent !== null) {
194
+ this.#lastContent = this.#pendingContent;
195
+ }
196
+ }
197
+
198
+ /** MODEL-FACING label for the home loop.md location. Mirrors
199
+ * readLoopTaskFile's home candidate (`<homeQwenDir>/loop.md`) so the absent
200
+ * reminder — and the caller's sanitized resolve-error — names the location
201
+ * actually checked (QWEN_HOME-aware), but must NEVER surface a raw absolute
202
+ * path: it flows into model/API text, leaking the host's filesystem layout.
203
+ * - under $HOME → tilde-abbreviated `~/.qwen/loop.md`;
204
+ * - relocated via $QWEN_HOME → the literal `$QWEN_HOME/loop.md`, not the
205
+ * resolved dir (`tildeifyPath` only abbreviates $HOME, so it's a no-op for
206
+ * a $QWEN_HOME outside $HOME and would otherwise pass the path through);
207
+ * - any other out-of-$HOME dir → a generic placeholder, never the path.
208
+ * The real absolute path stays in LOCAL debug logs only. */
209
+ homeLoopLabel(): string {
210
+ const homeQwenDir =
211
+ this.deps.homeQwenDir ?? path.join(this.deps.homeDir, '.qwen');
212
+ const homeLoopPath = path.join(homeQwenDir, 'loop.md');
213
+
214
+ const tildeified = tildeifyPath(homeLoopPath);
215
+ if (tildeified !== homeLoopPath) {
216
+ return tildeified;
217
+ }
218
+ // Outside $HOME: tildeifyPath was a no-op. When $QWEN_HOME relocated the
219
+ // global dir (homeQwenDir is its resolved value), report the literal env-var
220
+ // name — never the absolute path. The home candidate is always
221
+ // `<homeQwenDir>/loop.md`, so swap the whole resolved dir for `$QWEN_HOME` and
222
+ // re-attach the separator + basename directly. Deriving the tail from the
223
+ // resolved path's length instead mishandles edge dirs: a trailing slash
224
+ // (`$QWEN_HOME=/x/.qwen/`) over-counts the separator, and a filesystem-root
225
+ // homeQwenDir (`$QWEN_HOME=/` → homeLoopPath `/loop.md`, dirname `/`) drops the
226
+ // leading separator — both garbling the tail into `$QWEN_HOMEloop.md`.
227
+ if (process.env['QWEN_HOME']) {
228
+ return `$QWEN_HOME${path.sep}loop.md`;
229
+ }
230
+ return 'the configured global loop.md';
231
+ }
232
+
233
+ /** The checked-candidate "where" string shared by the absent reminder and the
234
+ * caller's sanitized resolve-error. Names the project candidate ONLY when it
235
+ * was actually read (`projectChecked` — a trusted folder), so neither path can
236
+ * claim `.qwen/loop.md (project)` for an untrusted folder where the project
237
+ * file is skipped. The home label is the QWEN_HOME-aware, never-absolute
238
+ * homeLoopLabel(). Single source of truth so the two messages can't drift. */
239
+ absentLocations(projectChecked: boolean): string {
240
+ const homeLabel = this.homeLoopLabel();
241
+ return projectChecked
242
+ ? `.qwen/loop.md (project) or ${homeLabel} (home)`
243
+ : `${homeLabel} (home)`;
244
+ }
245
+
246
+ /** A model-facing no-op tick (loop.md absent, or unreadable this tick). Clears
247
+ * the change-detection caches so a later successful tick re-delivers the FULL
248
+ * block instead of a dangling short reminder pointing at a block no longer
249
+ * guaranteed to be in context — absence (and a failed read) is itself a state
250
+ * change. */
251
+ #noOpTick(modelText: string, transientError = false): LoopTickResult {
252
+ this.#pendingContent = null;
253
+ this.#lastContent = null;
254
+ return { modelText, full: false, transientError };
255
+ }
256
+
257
+ /**
258
+ * No-op tick for a transient, non-whitelisted read error (EACCES/EIO, or a
259
+ * Windows editor/AV briefly locking loop.md). Mirrors the absent tick — same
260
+ * heading + the mode's re-arm tail (ABSENT_TAIL) — so a `dynamic` loop still
261
+ * re-arms LoopWakeup and survives the hiccup instead of dying silently: its
262
+ * firing wakeup was already consumed by the scheduler, and only the
263
+ * end-of-turn re-arm keeps it alive, so a thrown turn ends the loop forever.
264
+ * `cron` callers don't use this (they re-fire on their own next interval).
265
+ * `projectChecked` is the trust captured for THIS tick (so the named candidate
266
+ * set matches what was probed); `code` is the errno only — never an absolute
267
+ * path — for a brief model-facing note.
268
+ */
269
+ buildTransientErrorTick(
270
+ mode: LoopMode,
271
+ projectChecked: boolean,
272
+ code: string,
273
+ ): LoopTickResult {
274
+ return this.#noOpTick(
275
+ // `unavailable`, not `absent`: the file exists but was unreadable this tick,
276
+ // so the heading mirrors the body instead of contradicting it.
277
+ `${tickHeading(mode, { unavailable: true })}\nloop.md at ${this.absentLocations(
278
+ projectChecked,
279
+ )} could not be read this tick (${code}). ${ABSENT_TAIL[mode]}`,
280
+ // Flag the tick as a transient read failure (file exists, unreadable this
281
+ // tick) so the caller's echo distinguishes it from a genuinely-absent file.
282
+ true,
283
+ );
284
+ }
285
+
286
+ /**
287
+ * @param allowProjectFileOverride Trust captured once by the caller for this
288
+ * tick (see LoopTickResolverDeps.allowProjectFile). Threaded in — rather than
289
+ * re-reading the getter here — so the caller's error path can name the SAME
290
+ * candidate set that was probed even if `isTrustedFolder()` flips mid-tick.
291
+ * Omitted by direct callers, who fall back to the per-tick getter.
292
+ */
293
+ async resolve(
294
+ mode: LoopMode,
295
+ allowProjectFileOverride?: boolean,
296
+ ): Promise<LoopTickResult> {
297
+ // Re-read trust per tick (see LoopTickResolverDeps.allowProjectFile): a
298
+ // resolver built while trusted must skip the project file once trust flips.
299
+ // Captured so the absent reminder reflects what was ACTUALLY checked.
300
+ const allowProjectFile =
301
+ allowProjectFileOverride ?? this.deps.allowProjectFile();
302
+ const result = await readLoopTaskFile({
303
+ projectRoot: this.deps.projectRoot,
304
+ homeDir: this.deps.homeDir,
305
+ homeQwenDir: this.deps.homeQwenDir,
306
+ allowProjectFile,
307
+ realDirCache: this.#realDirCache,
308
+ });
309
+
310
+ if (result.status === 'missing') {
311
+ // Absence is itself a state change: #noOpTick clears both caches so a
312
+ // later recreate — even with byte-identical content — re-expands the full
313
+ // block rather than sending a dangling short reminder.
314
+ return this.#noOpTick(
315
+ `${tickHeading(mode, { absent: true })}\n${absentBody(mode, this.absentLocations(allowProjectFile))}`,
316
+ );
317
+ }
318
+
319
+ const content = result.truncated
320
+ ? `${cutToLastNewline(result.content)}\n${TRUNCATION_WARNING}`
321
+ : result.content;
322
+ this.#pendingContent = content;
323
+
324
+ // Label by which candidate matched, never result.path (the absolute path),
325
+ // which would leak the OS username / dir layout to the API provider and to
326
+ // debug logs. The label alone is enough for the caller's UI and presence
327
+ // check, so the absolute path is not surfaced on the result at all.
328
+ const sourceLabel = SOURCE_LABELS[result.source];
329
+
330
+ if (this.#lastContent === content) {
331
+ return {
332
+ modelText: `${tickHeading(mode)}\n${SHORT_REMINDER_PREAMBLE} ${PACING_SUFFIX[mode]}`,
333
+ full: false,
334
+ sourceLabel,
335
+ };
336
+ }
337
+
338
+ // First/changed full delivery: INTRO + the block itself, then only the
339
+ // pacing suffix — no "established earlier" preamble, which would contradict
340
+ // the block sitting right here in this same message.
341
+ return {
342
+ modelText: `${tickHeading(mode, { sourceLabel })}\n${INTRO}\n${content}\n${PACING_SUFFIX[mode]}`,
343
+ full: true,
344
+ sourceLabel,
345
+ };
346
+ }
347
+ }
@@ -47,20 +47,20 @@ Use this index to locate the right document for the user's question. Load only t
47
47
 
48
48
  ### Features
49
49
 
50
- | Topic | Doc Path |
51
- | ------------------------------------------- | ---------------------------------- |
52
- | Approval mode (plan/default/auto_edit/yolo) | `docs/features/approval-mode.md` |
53
- | Auto mode (AI-driven approval) | `docs/features/auto-mode.md` |
54
- | Hooks (lifecycle hooks) | `docs/features/hooks.md` |
55
- | MCP (Model Context Protocol) | `docs/features/mcp.md` |
56
- | Memory | `docs/features/memory.md` |
57
- | Skills system | `docs/features/skills.md` |
58
- | Sub-agents | `docs/features/sub-agents.md` |
59
- | Sandbox / security | `docs/features/sandbox.md` |
60
- | Slash commands | `docs/features/commands.md` |
61
- | Headless / non-interactive mode | `docs/features/headless.md` |
62
- | LSP integration | `docs/features/lsp.md` |
63
- | Token caching | `docs/features/token-caching.md` |
50
+ | Topic | Doc Path |
51
+ | ------------------------------------------- | --------------------------------------- |
52
+ | Approval mode (plan/default/auto_edit/yolo) | `docs/features/approval-mode.md` |
53
+ | Auto mode (AI-driven approval) | `docs/features/auto-mode.md` |
54
+ | Hooks (lifecycle hooks) | `docs/features/hooks.md` |
55
+ | MCP (Model Context Protocol) | `docs/features/mcp.md` |
56
+ | Memory | `docs/features/memory.md` |
57
+ | Skills system | `docs/features/skills.md` |
58
+ | Sub-agents | `docs/features/sub-agents.md` |
59
+ | Sandbox / security | `docs/features/sandbox.md` |
60
+ | Slash commands | `docs/features/commands.md` |
61
+ | Headless / non-interactive mode | `docs/features/headless.md` |
62
+ | LSP integration | `docs/features/lsp.md` |
63
+ | Token caching | `docs/features/token-caching.md` |
64
64
  | Language / i18n | `docs/features/language.md` |
65
65
  | Arena mode | `docs/features/arena.md` |
66
66
  | Status line | `docs/features/status-line.md` |
@@ -75,6 +75,13 @@ Use this index to locate the right document for the user's question. Load only t
75
75
  | Contextual tips | `docs/features/tips.md` |
76
76
  | Channels (Telegram/WeChat/DingTalk/etc.) | `docs/features/channels/overview.md` |
77
77
 
78
+ ### Daemon Mode
79
+
80
+ | Topic | Doc Path |
81
+ | --------------------------------- | --------------------------------- |
82
+ | qwen serve (daemon mode overview) | `docs/qwen-serve.md` |
83
+ | Local launch templates | `docs/qwen-serve-deploy-local.md` |
84
+
78
85
  ### IDE Integration
79
86
 
80
87
  | Topic | Doc Path |
@@ -111,11 +118,11 @@ When the user asks about configuration, the primary reference is `docs/configura
111
118
 
112
119
  ### Config File Locations & Priority
113
120
 
114
- | Level | Path | Description |
115
- | ------- | ------------------------------------------------------------ | -------------------------------------- |
116
- | User | `~/.qwen/settings.json` | Personal global config |
117
- | Project | `<project>/.qwen/settings.json` | Project-specific, overrides user level |
118
- | System | macOS: `/Library/Application Support/QwenCode/settings.json` | Admin-level config |
121
+ | Level | Path | Description |
122
+ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
123
+ | User | `~/.qwen/settings.json` | Personal global config |
124
+ | Project | `<project>/.qwen/settings.json` | Project-specific, overrides user level |
125
+ | System | Linux: `/etc/qwen-code/settings.json`<br>Windows: `C:\ProgramData\qwen-code\settings.json`<br>macOS: `/Library/Application Support/QwenCode/settings.json` | Admin-level config |
119
126
 
120
127
  **Priority** (highest to lowest): CLI args > env vars > system settings > project settings > user settings > defaults
121
128
 
@@ -163,11 +163,11 @@ The key concept is **Model Providers** (`modelProviders`): Qwen Code supports mu
163
163
 
164
164
  #### Supported protocols
165
165
 
166
- | Protocol | `modelProviders` key | Environment variables | Providers |
167
- | ----------------- | -------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
168
- | OpenAI-compatible | `openai` | `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_MODEL` | OpenAI, Azure OpenAI, OpenRouter, Requesty, ModelScope, Alibaba Cloud, any OpenAI-compatible endpoint |
169
- | Anthropic | `anthropic` | `ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL` | Anthropic Claude |
170
- | Google GenAI | `gemini` | `GEMINI_API_KEY`, `GEMINI_MODEL` | Google Gemini |
166
+ | Protocol | `modelProviders` key | Environment variables | Providers |
167
+ | ----------------- | -------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
168
+ | OpenAI-compatible | `openai` | `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_MODEL` | OpenAI, Azure OpenAI, OpenRouter, Requesty, ModelScope, Alibaba Cloud, any OpenAI-compatible endpoint |
169
+ | Anthropic | `anthropic` | `ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL` | Anthropic Claude |
170
+ | Google GenAI | `gemini` | `GEMINI_API_KEY`, `GEMINI_MODEL` | Google Gemini |
171
171
  | Vertex AI | `vertex-ai` | `GOOGLE_API_KEY`, `GOOGLE_MODEL` (sets `GOOGLE_GENAI_USE_VERTEXAI=true`; uses the `gemini` protocol) | Google Vertex AI |
172
172
 
173
173
  #### Step 1: Configure models and providers in `~/.qwen/settings.json`
@@ -224,13 +224,13 @@ Edit `~/.qwen/settings.json` (create it if it doesn't exist). You can mix multip
224
224
 
225
225
  **`ModelConfig` fields (each entry inside `modelProviders`):**
226
226
 
227
- | Field | Required | Description |
228
- | ------------------ | -------- | -------------------------------------------------------------------- |
229
- | `id` | Yes | Model ID sent to the API (e.g. `gpt-4o`, `claude-sonnet-4-20250514`) |
230
- | `name` | No | Display name in the `/model` picker (defaults to `id`) |
227
+ | Field | Required | Description |
228
+ | ------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
229
+ | `id` | Yes | Model ID sent to the API (e.g. `gpt-4o`, `claude-sonnet-4-20250514`) |
230
+ | `name` | No | Display name in the `/model` picker (defaults to `id`) |
231
231
  | `envKey` | No | Environment variable name for the API key (e.g. `OPENAI_API_KEY`); optional/recommended — defaults to the auth type's default env key when omitted |
232
- | `baseUrl` | No | API endpoint override (useful for proxies or custom endpoints) |
233
- | `generationConfig` | No | Fine-tune `timeout`, `maxRetries`, `samplingParams`, etc. |
232
+ | `baseUrl` | No | API endpoint override (useful for proxies or custom endpoints) |
233
+ | `generationConfig` | No | Fine-tune `timeout`, `maxRetries`, `samplingParams`, etc. |
234
234
 
235
235
  > [!note]
236
236
  >
@@ -22,12 +22,12 @@ Below are comprehensive configuration examples for different authentication type
22
22
 
23
23
  The `modelProviders` object keys must be valid `authType` values. Currently supported auth types are:
24
24
 
25
- | Auth Type | Description |
26
- | ------------ | --------------------------------------------------------------------------------------- |
27
- | `openai` | OpenAI-compatible APIs (OpenAI, Azure OpenAI, local inference servers like vLLM/Ollama) |
28
- | `anthropic` | Anthropic Claude API |
29
- | `gemini` | Google Gemini API |
30
- | `qwen-oauth` | Qwen OAuth (hard-coded, cannot be overridden in `modelProviders`) |
25
+ | Auth Type | Description |
26
+ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
27
+ | `openai` | OpenAI-compatible APIs (OpenAI, Azure OpenAI, local inference servers like vLLM/Ollama) |
28
+ | `anthropic` | Anthropic Claude API |
29
+ | `gemini` | Google Gemini API |
30
+ | `qwen-oauth` | Qwen OAuth (hard-coded, cannot be overridden in `modelProviders`) |
31
31
  | `vertex-ai` | Google Vertex AI (uses the `gemini` protocol and the `@google/genai` SDK in Vertex AI mode; selecting it sets `GOOGLE_GENAI_USE_VERTEXAI=true`) |
32
32
 
33
33
  > [!warning]
@@ -426,14 +426,14 @@ If you prefer to manually configure Coding Plan models, you can add them to your
426
426
 
427
427
  The effective auth/model/credential values are chosen per field using the following precedence (first present wins). You can combine `--auth-type` with `--model` to point directly at a provider entry; these CLI flags run before other layers.
428
428
 
429
- | Layer (highest → lowest) | authType | model | apiKey | baseUrl | apiKeyEnvKey | proxy |
430
- | -------------------------- | ----------------------------------- | ----------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------- | ---------------------- | --------------------------------- |
431
- | Programmatic overrides | `/auth` | `/auth` input | `/auth` input | `/auth` input | — | — |
432
- | Model provider selection | — | `modelProvider.id` | `env[modelProvider.envKey]` | `modelProvider.baseUrl` | `modelProvider.envKey` | — |
429
+ | Layer (highest → lowest) | authType | model | apiKey | baseUrl | apiKeyEnvKey | proxy |
430
+ | -------------------------- | ----------------------------------- | ----------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------ | ---------------------- | --------------------------------- |
431
+ | Programmatic overrides | `/auth` | `/auth` input | `/auth` input | `/auth` input | — | — |
432
+ | Model provider selection | — | `modelProvider.id` | `env[modelProvider.envKey]` | `modelProvider.baseUrl` | `modelProvider.envKey` | — |
433
433
  | CLI arguments | `--auth-type` | `--model` | `--openai-api-key` (or provider-specific equivalents) | `--openai-base-url` (or provider-specific equivalents) | — | — |
434
- | Environment variables | — | Provider-specific mapping (e.g. `OPENAI_MODEL`) | Provider-specific mapping (e.g. `OPENAI_API_KEY`) | Provider-specific mapping (e.g. `OPENAI_BASE_URL`) | — | — |
435
- | Settings (`settings.json`) | `security.auth.selectedType` | `model.name` | `security.auth.apiKey` | `security.auth.baseUrl` | — | — |
436
- | Default / computed | Falls back to `AuthType.QWEN_OAUTH` | Built-in default (OpenAI ⇒ `qwen3.5-plus`) | — | — | — | `Config.getProxy()` if configured |
434
+ | Environment variables | — | Provider-specific mapping (e.g. `OPENAI_MODEL`) | Provider-specific mapping (e.g. `OPENAI_API_KEY`) | Provider-specific mapping (e.g. `OPENAI_BASE_URL`) | — | — |
435
+ | Settings (`settings.json`) | `security.auth.selectedType` | `model.name` | `security.auth.apiKey` | `security.auth.baseUrl` | — | — |
436
+ | Default / computed | Falls back to `AuthType.QWEN_OAUTH` | Built-in default (OpenAI ⇒ `qwen3.5-plus`) | — | — | — | `Config.getProxy()` if configured |
437
437
 
438
438
  \*When present, CLI auth flags override settings. Otherwise, `security.auth.selectedType` or the implicit default determine the auth type. Qwen OAuth and OpenAI are the only auth types surfaced without extra configuration.
439
439