@mmmbuto/qwen-code-termux 0.16.1-termux → 0.18.0-termux

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 (185) hide show
  1. package/README.md +79 -109
  2. package/bundled/new-app/SKILL.md +22 -0
  3. package/bundled/qc-helper/SKILL.md +29 -24
  4. package/bundled/qc-helper/docs/_meta.ts +1 -0
  5. package/bundled/qc-helper/docs/configuration/_meta.ts +0 -3
  6. package/bundled/qc-helper/docs/configuration/settings.md +37 -31
  7. package/bundled/qc-helper/docs/configuration/themes.md +39 -0
  8. package/bundled/qc-helper/docs/features/_meta.ts +1 -3
  9. package/bundled/qc-helper/docs/features/approval-mode.md +35 -35
  10. package/bundled/qc-helper/docs/features/auto-mode.md +54 -9
  11. package/bundled/qc-helper/docs/features/channels/_meta.ts +1 -0
  12. package/bundled/qc-helper/docs/features/channels/feishu.md +170 -0
  13. package/bundled/qc-helper/docs/features/commands.md +115 -35
  14. package/bundled/qc-helper/docs/features/followup-suggestions.md +2 -2
  15. package/bundled/qc-helper/docs/features/headless.md +32 -0
  16. package/bundled/qc-helper/docs/features/markdown-rendering.md +21 -1
  17. package/bundled/qc-helper/docs/features/memory.md +22 -5
  18. package/bundled/qc-helper/docs/features/scheduled-tasks.md +1 -1
  19. package/bundled/qc-helper/docs/features/status-line.md +168 -32
  20. package/bundled/qc-helper/docs/features/sub-agents.md +60 -0
  21. package/bundled/qc-helper/docs/features/worktree.md +345 -0
  22. package/bundled/qc-helper/docs/overview.md +4 -4
  23. package/bundled/qc-helper/docs/quickstart.md +4 -4
  24. package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +221 -0
  25. package/bundled/qc-helper/docs/qwen-serve.md +234 -24
  26. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +16 -0
  27. package/bundled/qc-helper/docs/support/Uninstall.md +19 -1
  28. package/bundled/qc-helper/docs/support/troubleshooting.md +2 -1
  29. package/bundled/simplify/SKILL.md +123 -0
  30. package/chunks/agent-IDS4HMOX.js +56 -0
  31. package/chunks/agent-headless-5Q2EUSPS.js +50 -0
  32. package/chunks/{anthropicContentGenerator-SSGKR6DO.js → anthropicContentGenerator-2HBRNQ3B.js} +52 -9
  33. package/chunks/{askUserQuestion-PJWUUXKN.js → askUserQuestion-75TDJVK2.js} +45 -3
  34. package/chunks/{ca-UZ7BANMN.js → ca-BARBRL6N.js} +89 -5
  35. package/chunks/{chunk-GGNTZ2NH.js → chunk-2Y5SYSD3.js} +368 -597
  36. package/chunks/{chunk-2LA2TREA.js → chunk-3AA2DK35.js} +1448 -207
  37. package/chunks/{chunk-I2V5WXHJ.js → chunk-3AUHFMSK.js} +80 -38
  38. package/chunks/chunk-3DHXZ6EV.js +241 -0
  39. package/chunks/{chunk-PR4T27R7.js → chunk-3HTIVKZE.js} +42 -8
  40. package/chunks/chunk-3HX5LZ6R.js +1798 -0
  41. package/chunks/chunk-3PJXIDKI.js +2517 -0
  42. package/chunks/{chunk-MYAKAFEC.js → chunk-55ZMG67I.js} +7451 -3517
  43. package/chunks/{chunk-66CXYE4B.js → chunk-5IFG2VC4.js} +293 -242
  44. package/chunks/chunk-64WXLC72.js +98 -0
  45. package/chunks/{chunk-C6WMLUNB.js → chunk-72LDN5PP.js} +1 -1
  46. package/chunks/{chunk-F23NCRJ2.js → chunk-A7B4ISQP.js} +1 -1
  47. package/chunks/chunk-B7HXHOHU.js +393 -0
  48. package/chunks/{chunk-XEGHDASV.js → chunk-D3RHSPAS.js} +435 -540
  49. package/chunks/{chunk-XKS5KBFJ.js → chunk-EYENRK4D.js} +694 -384
  50. package/chunks/chunk-H6BD2ELD.js +36 -0
  51. package/chunks/{chunk-XP27SJMH.js → chunk-HR7SV7AY.js} +79 -48
  52. package/chunks/{chunk-D5NTAHYL.js → chunk-IDX6COTE.js} +7 -2
  53. package/chunks/{chunk-SHT4VJWU.js → chunk-IWKSG2AR.js} +2 -2
  54. package/chunks/chunk-J37FGIOA.js +1623 -0
  55. package/chunks/chunk-J5MDQKJL.js +2230 -0
  56. package/chunks/{chunk-USE2VQ5P.js → chunk-JTQAQBTV.js} +21 -0
  57. package/chunks/{chunk-NCTLV2NB.js → chunk-KQJMQJPI.js} +1 -1
  58. package/chunks/{chunk-5FBA5XC2.js → chunk-KRIHGKNA.js} +1 -1
  59. package/chunks/chunk-LD2XBG6Z.js +102 -0
  60. package/chunks/{chunk-MAY32HXD.js → chunk-M6VTDSVR.js} +3 -1
  61. package/chunks/chunk-MRO43B25.js +30 -0
  62. package/chunks/{chunk-N4WOREMD.js → chunk-NVFMZBX2.js} +43 -3
  63. package/chunks/chunk-OHEGWO4L.js +264 -0
  64. package/chunks/{chunk-K6O2NBMF.js → chunk-OQ7NJIY7.js} +4604 -6397
  65. package/chunks/chunk-QQDPRDVW.js +25 -0
  66. package/chunks/{chunk-KXZ4TJB4.js → chunk-SEGYWKIH.js} +1 -1
  67. package/chunks/chunk-SKBPNJEW.js +45 -0
  68. package/chunks/{chunk-4AOCVI6J.js → chunk-SNGELLWX.js} +52 -6
  69. package/chunks/{chunk-3OCRHZA3.js → chunk-TD4OPI4T.js} +56742 -44104
  70. package/chunks/{chunk-DQ4QTG7E.js → chunk-VV4F63BD.js} +11 -11
  71. package/chunks/chunk-XBY7E2FX.js +605 -0
  72. package/chunks/{chunk-JKMBWLFB.js → chunk-YILFYI5W.js} +48 -26
  73. package/chunks/chunk-YOGAOMYB.js +159 -0
  74. package/chunks/{chunk-QWSRH265.js → chunk-Z2Z3GUXZ.js} +777 -776
  75. package/chunks/{chunk-SDHRQFOS.js → chunk-ZTZ4DDQE.js} +2 -2
  76. package/chunks/computer-use-W2TYQNEE.js +825 -0
  77. package/chunks/contextCommand-6FGX3A7J.js +52 -0
  78. package/chunks/{cron-create-3ZBBN7WB.js → cron-create-APL5LU6I.js} +3 -3
  79. package/chunks/{cron-delete-NAGKKIIG.js → cron-delete-4SBJSCN4.js} +3 -3
  80. package/chunks/{cron-list-PAGRXNAI.js → cron-list-2AMGOMVO.js} +3 -3
  81. package/chunks/{de-V4IE2OOZ.js → de-YGKK2BC4.js} +89 -5
  82. package/chunks/{devtools-TWVXEJQB.js → devtools-FM6GJPYG.js} +2 -1
  83. package/chunks/{dist-4L54HRX2.js → dist-4LXD6L6X.js} +24 -5
  84. package/chunks/dist-H6ONXVLG.js +94146 -0
  85. package/chunks/{dist-XKWIWPWQ.js → dist-KAZ3SEBX.js} +1083 -3856
  86. package/chunks/{dist-BXDUQ2QY.js → dist-PK7DFCAW.js} +1 -1
  87. package/chunks/{edit-NVO3FOAK.js → edit-ZCEZC264.js} +30 -22
  88. package/chunks/{en-HGJ2SPLM.js → en-DHGYHIHX.js} +127 -6
  89. package/chunks/{enter-worktree-UEBG4WFC.js → enter-worktree-BBHCFCHG.js} +30 -20
  90. package/chunks/enterPlanMode-3M6KTD3B.js +158 -0
  91. package/chunks/{exit-worktree-UZ3MAQZN.js → exit-worktree-73YPIEQO.js} +27 -19
  92. package/chunks/exitPlanMode-TYZM6BAE.js +703 -0
  93. package/chunks/{fr-CJULI7ZX.js → fr-JXBKPJKQ.js} +89 -5
  94. package/chunks/{geminiContentGenerator-3UZFXGNT.js → geminiContentGenerator-7N2V3VW2.js} +8 -6
  95. package/chunks/{getMachineId-bsd-JXOSIJV2.js → getMachineId-bsd-4CASPIU4.js} +4 -4
  96. package/chunks/{getMachineId-darwin-TE4QRR42.js → getMachineId-darwin-HPQPEMZR.js} +4 -4
  97. package/chunks/{getMachineId-linux-S3OL52XK.js → getMachineId-linux-AUARKYHL.js} +3 -3
  98. package/chunks/{getMachineId-unsupported-DWUSBAPX.js → getMachineId-unsupported-S32ZDA2T.js} +3 -3
  99. package/chunks/{getMachineId-win-AAC5P3AP.js → getMachineId-win-4EFLHYIJ.js} +4 -4
  100. package/chunks/{glob-KNHSFFFG.js → glob-5XBCPQ2A.js} +27 -19
  101. package/chunks/{grep-LACWDZW4.js → grep-VIUU3A7X.js} +30 -19
  102. package/chunks/{ja-L7CHRQEW.js → ja-TGPZSP2B.js} +89 -5
  103. package/chunks/{keychain-token-storage-335UOLJ6.js → keychain-token-storage-6IU6ORQN.js} +3 -3
  104. package/chunks/{ls-AGXQOKSG.js → ls-JRGYIGLY.js} +4 -4
  105. package/chunks/{lsp-UDMUHNPA.js → lsp-SHMKFOAC.js} +3 -3
  106. package/chunks/{monitor-ETKWPJEH.js → monitor-6R4LIJL5.js} +40 -25
  107. package/chunks/{multipart-parser-3QWGTLK3.js → multipart-parser-AJ4WASWR.js} +2 -2
  108. package/chunks/{notebook-edit-QJJLPNYT.js → notebook-edit-5E7ULDVQ.js} +28 -20
  109. package/chunks/{openaiContentGenerator-CNNN424U.js → openaiContentGenerator-ZVHFKM3O.js} +17 -14
  110. package/chunks/{pt-M6JULLEQ.js → pt-TIBG6BIO.js} +89 -5
  111. package/chunks/{qwenContentGenerator-BOLCGK3R.js → qwenContentGenerator-B2VTVSPJ.js} +31 -23
  112. package/chunks/{qwenOAuth2-EEJGROP7.js → qwenOAuth2-2KCKWDCF.js} +6 -4
  113. package/chunks/read-file-GIT7BCDR.js +27 -0
  114. package/chunks/ripGrep-MWKFVYMS.js +48 -0
  115. package/chunks/{ru-QILM4HBC.js → ru-JBCHCK4L.js} +89 -5
  116. package/chunks/scheduler-5VOOYGBH.js +308 -0
  117. package/chunks/send-message-4QNWQJF4.js +244 -0
  118. package/chunks/{serve-OLSI7WSR.js → serve-MN6HZBWN.js} +14262 -7414
  119. package/chunks/shell-NQZQGFM2.js +56 -0
  120. package/chunks/{skill-D6YRHTTI.js → skill-WCFW4644.js} +145 -119
  121. package/chunks/{src-TMOD5X6F.js → src-7XL4G4DC.js} +88 -46
  122. package/chunks/{src-4QH4FZ6I.js → src-IHA6DTUV.js} +452 -62
  123. package/chunks/{syntheticOutput-5PVFDDJ4.js → syntheticOutput-YTYS2ZMQ.js} +4 -4
  124. package/chunks/task-create-MPORPYN6.js +19 -0
  125. package/chunks/task-list-R2YDYPZT.js +151 -0
  126. package/chunks/{task-stop-AJKPSR6R.js → task-stop-SYWJYBCM.js} +3 -3
  127. package/chunks/task-update-E4NSLKMQ.js +408 -0
  128. package/chunks/team-create-7R7KA5IP.js +314 -0
  129. package/chunks/team-delete-25OIWUPN.js +116 -0
  130. package/chunks/{todoWrite-VLAUG4CA.js → todoWrite-4YHMIF4X.js} +16 -5
  131. package/chunks/{tool-search-MZGHUUKD.js → tool-search-YBRVZCLI.js} +29 -11
  132. package/chunks/{tts-notification-K3X7X7MN.js → tts-notification-7SOEMQK4.js} +5 -4
  133. package/chunks/{web-fetch-OILB464A.js → web-fetch-MFIRHIHI.js} +5 -5
  134. package/chunks/workflow-5RIKVCIE.js +960 -0
  135. package/chunks/{write-file-BIQAA57V.js → write-file-DMQTJZOM.js} +32 -24
  136. package/chunks/{zh-PWL2NKY3.js → zh-7H5OQC4I.js} +135 -11
  137. package/chunks/{zh-TW-S3YGWICZ.js → zh-TW-P4IDHD3M.js} +128 -11
  138. package/cli.js +45402 -20570
  139. package/examples/agent/agents/diary.md +86 -0
  140. package/examples/agent/qwen-extension.json +5 -0
  141. package/examples/commands/commands/fs/grep-code.md +3 -0
  142. package/examples/commands/qwen-extension.json +5 -0
  143. package/examples/context/QWEN.md +8 -0
  144. package/examples/context/qwen-extension.json +5 -0
  145. package/examples/mcp-server/example.ts +60 -0
  146. package/examples/mcp-server/package.json +18 -0
  147. package/examples/mcp-server/qwen-extension.json +12 -0
  148. package/examples/mcp-server/tsconfig.json +13 -0
  149. package/examples/skills/qwen-extension.json +5 -0
  150. package/examples/skills/skills/synonyms/SKILL.md +48 -0
  151. package/examples/starter/QWEN.md +30 -0
  152. package/examples/starter/README.md +59 -0
  153. package/examples/starter/agents/diary.md +86 -0
  154. package/examples/starter/commands/writing/polish.md +13 -0
  155. package/examples/starter/example.ts +64 -0
  156. package/examples/starter/package.json +18 -0
  157. package/examples/starter/qwen-extension.json +12 -0
  158. package/examples/starter/skills/synonyms/SKILL.md +48 -0
  159. package/examples/starter/tsconfig.json +13 -0
  160. package/fzfWorker.js +1083 -0
  161. package/locales/ca.js +118 -5
  162. package/locales/de.js +117 -5
  163. package/locales/en.js +169 -7
  164. package/locales/fr.js +119 -5
  165. package/locales/ja.js +114 -5
  166. package/locales/pt.js +117 -5
  167. package/locales/ru.js +116 -5
  168. package/locales/zh-TW.js +161 -12
  169. package/locales/zh.js +169 -12
  170. package/package.json +4 -2
  171. package/scripts/postinstall.cjs +2 -1
  172. package/bundled/qc-helper/docs/features/checkpointing.md +0 -77
  173. package/chunks/agent-7ZN3CRHR.js +0 -48
  174. package/chunks/chunk-6PCB2DEF.js +0 -434
  175. package/chunks/chunk-EM6ETG2K.js +0 -60
  176. package/chunks/chunk-G7YTSRES.js +0 -150
  177. package/chunks/contextCommand-7IBASARL.js +0 -44
  178. package/chunks/exitPlanMode-PZAMWIRW.js +0 -227
  179. package/chunks/multipart-parser-IXGBIOIN.js +0 -384
  180. package/chunks/read-file-CCUEUFG2.js +0 -24
  181. package/chunks/ripGrep-TADOH2HK.js +0 -40
  182. package/chunks/send-message-YL44UZFC.js +0 -151
  183. package/chunks/shell-7KKKC5G7.js +0 -48
  184. package/chunks/src-IPWIHNMI.js +0 -1406
  185. package/chunks/undici-F6ZOXSS5.js +0 -8
@@ -2,11 +2,17 @@
2
2
  "use strict";
3
3
  import {
4
4
  formatFetchErrorForUser
5
- } from "./chunk-KXZ4TJB4.js";
5
+ } from "./chunk-SEGYWKIH.js";
6
+ import {
7
+ combineAbortSignals
8
+ } from "./chunk-64WXLC72.js";
9
+ import {
10
+ atomicWriteFile
11
+ } from "./chunk-B7HXHOHU.js";
6
12
  import {
7
13
  Storage,
8
14
  createDebugLogger
9
- } from "./chunk-XP27SJMH.js";
15
+ } from "./chunk-HR7SV7AY.js";
10
16
  import {
11
17
  init_esbuild_shims
12
18
  } from "./chunk-A4BMJM77.js";
@@ -17,546 +23,294 @@ import {
17
23
  // packages/core/src/qwen/qwenOAuth2.ts
18
24
  init_esbuild_shims();
19
25
  import crypto from "crypto";
20
- import path3 from "node:path";
21
- import { promises as fs7 } from "node:fs";
22
-
23
- // node_modules/open/index.js
24
- init_esbuild_shims();
25
- import process7 from "node:process";
26
- import { Buffer } from "node:buffer";
27
- import path from "node:path";
28
- import { fileURLToPath } from "node:url";
29
- import { promisify as promisify5 } from "node:util";
30
- import childProcess from "node:child_process";
31
- import fs5, { constants as fsConstants2 } from "node:fs/promises";
32
-
33
- // node_modules/wsl-utils/index.js
34
- init_esbuild_shims();
35
- import process3 from "node:process";
36
- import fs4, { constants as fsConstants } from "node:fs/promises";
37
-
38
- // node_modules/is-wsl/index.js
39
- init_esbuild_shims();
40
- import process2 from "node:process";
41
- import os from "node:os";
42
- import fs3 from "node:fs";
26
+ import path2 from "node:path";
27
+ import { promises as fs2 } from "node:fs";
28
+ import { EventEmitter } from "events";
29
+ import { randomUUID as randomUUID2 } from "node:crypto";
43
30
 
44
- // node_modules/is-inside-container/index.js
31
+ // packages/core/src/utils/secure-browser-launcher.ts
45
32
  init_esbuild_shims();
46
- import fs2 from "node:fs";
33
+ import { execFile, spawn } from "node:child_process";
34
+ import { promisify } from "node:util";
35
+ import { platform } from "node:os";
36
+ import { resolve } from "node:path";
37
+ import { URL, fileURLToPath } from "node:url";
47
38
 
48
- // node_modules/is-docker/index.js
39
+ // packages/core/src/utils/browser.ts
49
40
  init_esbuild_shims();
50
- import fs from "node:fs";
51
- var isDockerCached;
52
- function hasDockerEnv() {
53
- try {
54
- fs.statSync("/.dockerenv");
55
- return true;
56
- } catch {
57
- return false;
58
- }
41
+ var browserBlocklist = ["www-browser"];
42
+ function isBrowserCommandBlocked(command) {
43
+ const commandName = command.replace(/\\/g, "/").split("/").pop();
44
+ return !!commandName && browserBlocklist.includes(commandName);
59
45
  }
60
- __name(hasDockerEnv, "hasDockerEnv");
61
- function hasDockerCGroup() {
62
- try {
63
- return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
64
- } catch {
46
+ __name(isBrowserCommandBlocked, "isBrowserCommandBlocked");
47
+ function shouldAttemptBrowserLaunch(options = {}) {
48
+ const browserEnv = process.env["BROWSER"]?.trim();
49
+ const browserCommand = browserEnv?.match(/^\S+/)?.[0];
50
+ if (!options.ignoreBrowserBlocklist && process.platform !== "win32" && browserCommand && isBrowserCommandBlocked(browserCommand)) {
65
51
  return false;
66
52
  }
67
- }
68
- __name(hasDockerCGroup, "hasDockerCGroup");
69
- function isDocker() {
70
- if (isDockerCached === void 0) {
71
- isDockerCached = hasDockerEnv() || hasDockerCGroup();
72
- }
73
- return isDockerCached;
74
- }
75
- __name(isDocker, "isDocker");
76
-
77
- // node_modules/is-inside-container/index.js
78
- var cachedResult;
79
- var hasContainerEnv = /* @__PURE__ */ __name(() => {
80
- try {
81
- fs2.statSync("/run/.containerenv");
82
- return true;
83
- } catch {
53
+ if (process.env["CI"] || process.env["DEBIAN_FRONTEND"] === "noninteractive") {
84
54
  return false;
85
55
  }
86
- }, "hasContainerEnv");
87
- function isInsideContainer() {
88
- if (cachedResult === void 0) {
89
- cachedResult = hasContainerEnv() || isDocker();
90
- }
91
- return cachedResult;
92
- }
93
- __name(isInsideContainer, "isInsideContainer");
94
-
95
- // node_modules/is-wsl/index.js
96
- var isWsl = /* @__PURE__ */ __name(() => {
97
- if (process2.platform !== "linux") {
98
- return false;
99
- }
100
- if (os.release().toLowerCase().includes("microsoft")) {
101
- if (isInsideContainer()) {
56
+ const isSSH = !!process.env["SSH_CONNECTION"];
57
+ if (process.platform === "linux") {
58
+ const displayVariables = ["DISPLAY", "WAYLAND_DISPLAY", "MIR_SOCKET"];
59
+ const hasDisplay = displayVariables.some((v) => !!process.env[v]);
60
+ if (!hasDisplay) {
102
61
  return false;
103
62
  }
104
- return true;
105
63
  }
106
- try {
107
- return fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
108
- } catch {
64
+ if (isSSH && process.platform !== "linux") {
109
65
  return false;
110
66
  }
111
- }, "isWsl");
112
- var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
113
-
114
- // node_modules/wsl-utils/index.js
115
- var wslDrivesMountPoint = /* @__PURE__ */ (() => {
116
- const defaultMountPoint = "/mnt/";
117
- let mountPoint;
118
- return async function() {
119
- if (mountPoint) {
120
- return mountPoint;
121
- }
122
- const configFilePath = "/etc/wsl.conf";
123
- let isConfigFileExists = false;
124
- try {
125
- await fs4.access(configFilePath, fsConstants.F_OK);
126
- isConfigFileExists = true;
127
- } catch {
128
- }
129
- if (!isConfigFileExists) {
130
- return defaultMountPoint;
131
- }
132
- const configContent = await fs4.readFile(configFilePath, { encoding: "utf8" });
133
- const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
134
- if (!configMountPoint) {
135
- return defaultMountPoint;
136
- }
137
- mountPoint = configMountPoint.groups.mountPoint.trim();
138
- mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
139
- return mountPoint;
140
- };
141
- })();
142
- var powerShellPathFromWsl = /* @__PURE__ */ __name(async () => {
143
- const mountPoint = await wslDrivesMountPoint();
144
- return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
145
- }, "powerShellPathFromWsl");
146
- var powerShellPath = /* @__PURE__ */ __name(async () => {
147
- if (is_wsl_default) {
148
- return powerShellPathFromWsl();
149
- }
150
- return `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
151
- }, "powerShellPath");
152
-
153
- // node_modules/define-lazy-prop/index.js
154
- init_esbuild_shims();
155
- function defineLazyProperty(object, propertyName, valueGetter) {
156
- const define = /* @__PURE__ */ __name((value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true }), "define");
157
- Object.defineProperty(object, propertyName, {
158
- configurable: true,
159
- enumerable: true,
160
- get() {
161
- const result = valueGetter();
162
- define(result);
163
- return result;
164
- },
165
- set(value) {
166
- define(value);
167
- }
168
- });
169
- return object;
67
+ return true;
170
68
  }
171
- __name(defineLazyProperty, "defineLazyProperty");
172
-
173
- // node_modules/default-browser/index.js
174
- init_esbuild_shims();
175
- import { promisify as promisify4 } from "node:util";
176
- import process6 from "node:process";
177
- import { execFile as execFile4 } from "node:child_process";
69
+ __name(shouldAttemptBrowserLaunch, "shouldAttemptBrowserLaunch");
178
70
 
179
- // node_modules/default-browser-id/index.js
180
- init_esbuild_shims();
181
- import { promisify } from "node:util";
182
- import process4 from "node:process";
183
- import { execFile } from "node:child_process";
71
+ // packages/core/src/utils/secure-browser-launcher.ts
184
72
  var execFileAsync = promisify(execFile);
185
- async function defaultBrowserId() {
186
- if (process4.platform !== "darwin") {
187
- throw new Error("macOS only");
73
+ function validateUrl(url, { allowFile = false, allowedFilePaths } = {}) {
74
+ let parsedUrl;
75
+ try {
76
+ parsedUrl = new URL(url);
77
+ } catch (_error) {
78
+ throw new Error(`Invalid URL: ${url}`);
188
79
  }
189
- const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
190
- const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
191
- return match?.groups.id ?? "com.apple.Safari";
192
- }
193
- __name(defaultBrowserId, "defaultBrowserId");
194
-
195
- // node_modules/bundle-name/index.js
196
- init_esbuild_shims();
197
-
198
- // node_modules/run-applescript/index.js
199
- init_esbuild_shims();
200
- import process5 from "node:process";
201
- import { promisify as promisify2 } from "node:util";
202
- import { execFile as execFile2, execFileSync } from "node:child_process";
203
- var execFileAsync2 = promisify2(execFile2);
204
- async function runAppleScript(script, { humanReadableOutput = true } = {}) {
205
- if (process5.platform !== "darwin") {
206
- throw new Error("macOS only");
207
- }
208
- const outputArguments = humanReadableOutput ? [] : ["-ss"];
209
- const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments]);
210
- return stdout.trim();
211
- }
212
- __name(runAppleScript, "runAppleScript");
213
-
214
- // node_modules/bundle-name/index.js
215
- async function bundleName(bundleId) {
216
- return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
217
- tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
218
- }
219
- __name(bundleName, "bundleName");
220
-
221
- // node_modules/default-browser/windows.js
222
- init_esbuild_shims();
223
- import { promisify as promisify3 } from "node:util";
224
- import { execFile as execFile3 } from "node:child_process";
225
- var execFileAsync3 = promisify3(execFile3);
226
- var windowsBrowserProgIds = {
227
- AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
228
- MSEdgeDHTML: { name: "Edge", id: "com.microsoft.edge" },
229
- // On macOS, it's "com.microsoft.edgemac"
230
- MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
231
- // Newer Edge/Win10 releases
232
- "IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" },
233
- FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
234
- ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
235
- BraveHTML: { name: "Brave", id: "com.brave.Browser" },
236
- BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
237
- BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" }
238
- };
239
- var UnknownBrowserError = class extends Error {
240
- static {
241
- __name(this, "UnknownBrowserError");
80
+ const allowedProtocols = allowFile ? ["http:", "https:", "file:"] : ["http:", "https:"];
81
+ if (!allowedProtocols.includes(parsedUrl.protocol)) {
82
+ throw new Error(
83
+ `Unsafe protocol: ${parsedUrl.protocol}. Only ${allowedProtocols.join(
84
+ ", "
85
+ )} are allowed.`
86
+ );
87
+ }
88
+ if (parsedUrl.protocol === "file:" && allowFile) {
89
+ if (!allowedFilePaths?.length) {
90
+ throw new Error("allowedFilePaths is required when allowFile is true");
91
+ }
92
+ const requestedPath = resolve(fileURLToPath(parsedUrl));
93
+ const allowed = allowedFilePaths.map((filePath) => resolve(filePath));
94
+ if (!allowed.includes(requestedPath)) {
95
+ throw new Error("File URL is not in the allowed file set");
96
+ }
97
+ }
98
+ if (/[\r\n\x00-\x1f]/.test(url)) {
99
+ throw new Error("URL contains invalid characters");
242
100
  }
243
- };
244
- async function defaultBrowser(_execFileAsync = execFileAsync3) {
245
- const { stdout } = await _execFileAsync("reg", [
246
- "QUERY",
247
- " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
248
- "/v",
249
- "ProgId"
250
- ]);
251
- const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
252
- if (!match) {
253
- throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
254
- }
255
- const { id } = match.groups;
256
- const browser = windowsBrowserProgIds[id];
257
- if (!browser) {
258
- throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
259
- }
260
- return browser;
261
- }
262
- __name(defaultBrowser, "defaultBrowser");
263
-
264
- // node_modules/default-browser/index.js
265
- var execFileAsync4 = promisify4(execFile4);
266
- var titleize = /* @__PURE__ */ __name((string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase()), "titleize");
267
- async function defaultBrowser2() {
268
- if (process6.platform === "darwin") {
269
- const id = await defaultBrowserId();
270
- const name = await bundleName(id);
271
- return { name, id };
272
- }
273
- if (process6.platform === "linux") {
274
- const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
275
- const id = stdout.trim();
276
- const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
277
- return { name, id };
278
- }
279
- if (process6.platform === "win32") {
280
- return defaultBrowser();
281
- }
282
- throw new Error("Only macOS, Linux, and Windows are supported");
283
- }
284
- __name(defaultBrowser2, "defaultBrowser");
285
-
286
- // node_modules/open/index.js
287
- var execFile5 = promisify5(childProcess.execFile);
288
- var __dirname = path.dirname(fileURLToPath(import.meta.url));
289
- var localXdgOpenPath = path.join(__dirname, "xdg-open");
290
- var { platform, arch } = process7;
291
- async function getWindowsDefaultBrowserFromWsl() {
292
- const powershellPath = await powerShellPath();
293
- const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
294
- const encodedCommand = Buffer.from(rawCommand, "utf16le").toString("base64");
295
- const { stdout } = await execFile5(
296
- powershellPath,
297
- [
298
- "-NoProfile",
299
- "-NonInteractive",
300
- "-ExecutionPolicy",
301
- "Bypass",
302
- "-EncodedCommand",
303
- encodedCommand
304
- ],
305
- { encoding: "utf8" }
306
- );
307
- const progId = stdout.trim();
308
- const browserMap = {
309
- ChromeHTML: "com.google.chrome",
310
- BraveHTML: "com.brave.Browser",
311
- MSEdgeHTM: "com.microsoft.edge",
312
- FirefoxURL: "org.mozilla.firefox"
313
- };
314
- return browserMap[progId] ? { id: browserMap[progId] } : {};
315
101
  }
316
- __name(getWindowsDefaultBrowserFromWsl, "getWindowsDefaultBrowserFromWsl");
317
- var pTryEach = /* @__PURE__ */ __name(async (array, mapper) => {
318
- let latestError;
319
- for (const item of array) {
102
+ __name(validateUrl, "validateUrl");
103
+ async function openBrowserSecurely(url, browserOptions = {}) {
104
+ validateUrl(url, browserOptions);
105
+ const platformName = platform();
106
+ let command;
107
+ let args;
108
+ const browserEnv = process.env["BROWSER"]?.trim();
109
+ const browserCommand = platformName === "win32" ? void 0 : buildBrowserCommand(browserEnv, url);
110
+ if (browserCommand) {
320
111
  try {
321
- return await mapper(item);
322
- } catch (error) {
323
- latestError = error;
112
+ await launchDetached(browserCommand.command, browserCommand.args);
113
+ return;
114
+ } catch (_error) {
115
+ console.warn(
116
+ `Failed to open BROWSER command ${browserCommand.command}: ${formatLaunchError(
117
+ _error
118
+ )}. Falling back to the platform browser opener.`
119
+ );
324
120
  }
325
121
  }
326
- throw latestError;
327
- }, "pTryEach");
328
- var baseOpen = /* @__PURE__ */ __name(async (options) => {
329
- options = {
330
- wait: false,
331
- background: false,
332
- newInstance: false,
333
- allowNonzeroExitCode: false,
334
- ...options
122
+ if (!shouldAttemptBrowserLaunch({ ignoreBrowserBlocklist: true })) {
123
+ console.warn(
124
+ `Browser launch is not available in this environment. Please open this URL manually: ${url}`
125
+ );
126
+ return;
127
+ }
128
+ {
129
+ switch (platformName) {
130
+ case "darwin":
131
+ command = "open";
132
+ args = [url];
133
+ break;
134
+ case "win32":
135
+ command = "powershell.exe";
136
+ args = [
137
+ "-NoProfile",
138
+ "-NonInteractive",
139
+ "-WindowStyle",
140
+ "Hidden",
141
+ "-Command",
142
+ `Start-Process '${url.replace(/'/g, "''")}'`
143
+ ];
144
+ break;
145
+ case "linux":
146
+ case "freebsd":
147
+ case "openbsd":
148
+ command = "xdg-open";
149
+ args = [url];
150
+ break;
151
+ default:
152
+ throw new Error(`Unsupported platform: ${platformName}`);
153
+ }
154
+ }
155
+ const execOptions = {
156
+ // Don't inherit parent's environment to avoid potential issues
157
+ env: {
158
+ ...process.env,
159
+ // Ensure we're not in a shell that might interpret special characters
160
+ SHELL: void 0
161
+ },
162
+ // Detach the browser process so it doesn't block
163
+ detached: true,
164
+ stdio: "ignore"
335
165
  };
336
- if (Array.isArray(options.app)) {
337
- return pTryEach(options.app, (singleApp) => baseOpen({
338
- ...options,
339
- app: singleApp
340
- }));
341
- }
342
- let { name: app, arguments: appArguments = [] } = options.app ?? {};
343
- appArguments = [...appArguments];
344
- if (Array.isArray(app)) {
345
- return pTryEach(app, (appName) => baseOpen({
346
- ...options,
347
- app: {
348
- name: appName,
349
- arguments: appArguments
350
- }
351
- }));
352
- }
353
- if (app === "browser" || app === "browserPrivate") {
354
- const ids = {
355
- "com.google.chrome": "chrome",
356
- "google-chrome.desktop": "chrome",
357
- "com.brave.Browser": "brave",
358
- "org.mozilla.firefox": "firefox",
359
- "firefox.desktop": "firefox",
360
- "com.microsoft.msedge": "edge",
361
- "com.microsoft.edge": "edge",
362
- "com.microsoft.edgemac": "edge",
363
- "microsoft-edge.desktop": "edge"
364
- };
365
- const flags = {
366
- chrome: "--incognito",
367
- brave: "--incognito",
368
- firefox: "--private-window",
369
- edge: "--inPrivate"
370
- };
371
- const browser = is_wsl_default ? await getWindowsDefaultBrowserFromWsl() : await defaultBrowser2();
372
- if (browser.id in ids) {
373
- const browserName = ids[browser.id];
374
- if (app === "browserPrivate") {
375
- appArguments.push(flags[browserName]);
376
- }
377
- return baseOpen({
378
- ...options,
379
- app: {
380
- name: apps[browserName],
381
- arguments: appArguments
166
+ try {
167
+ await execFileAsync(command, args, execOptions);
168
+ } catch (_error) {
169
+ if ((platformName === "linux" || platformName === "freebsd" || platformName === "openbsd") && command === "xdg-open") {
170
+ const fallbackCommands = [
171
+ { command: "gnome-open", detached: false },
172
+ { command: "kde-open", detached: false },
173
+ { command: "firefox", detached: true },
174
+ { command: "chromium", detached: true },
175
+ { command: "google-chrome", detached: true },
176
+ { command: "microsoft-edge", detached: true }
177
+ ];
178
+ for (const { command: fallbackCommand, detached } of fallbackCommands) {
179
+ try {
180
+ if (detached) {
181
+ await launchDetached(fallbackCommand, [url]);
182
+ } else {
183
+ await execFileAsync(fallbackCommand, [url], execOptions);
184
+ }
185
+ return;
186
+ } catch {
187
+ continue;
382
188
  }
383
- });
189
+ }
384
190
  }
385
- throw new Error(`${browser.name} is not supported as a default browser`);
191
+ console.warn(
192
+ `Failed to open browser automatically. Please open this URL manually: ${url}`
193
+ );
194
+ return;
386
195
  }
387
- let command;
388
- const cliArguments = [];
389
- const childProcessOptions = {};
390
- if (platform === "darwin") {
391
- command = "open";
392
- if (options.wait) {
393
- cliArguments.push("--wait-apps");
394
- }
395
- if (options.background) {
396
- cliArguments.push("--background");
397
- }
398
- if (options.newInstance) {
399
- cliArguments.push("--new");
400
- }
401
- if (app) {
402
- cliArguments.push("-a", app);
403
- }
404
- } else if (platform === "win32" || is_wsl_default && !isInsideContainer() && !app) {
405
- command = await powerShellPath();
406
- cliArguments.push(
407
- "-NoProfile",
408
- "-NonInteractive",
409
- "-ExecutionPolicy",
410
- "Bypass",
411
- "-EncodedCommand"
196
+ }
197
+ __name(openBrowserSecurely, "openBrowserSecurely");
198
+ async function launchDetached(command, args) {
199
+ const spawnOptions = {
200
+ env: {
201
+ ...process.env,
202
+ SHELL: void 0
203
+ },
204
+ detached: true,
205
+ stdio: "ignore"
206
+ };
207
+ await new Promise((resolve2, reject) => {
208
+ const child = spawn(command, args, spawnOptions);
209
+ let settled = false;
210
+ child.once("error", (error) => {
211
+ if (settled) {
212
+ return;
213
+ }
214
+ settled = true;
215
+ reject(error);
216
+ });
217
+ child.once("spawn", () => {
218
+ if (settled) {
219
+ return;
220
+ }
221
+ settled = true;
222
+ child.unref();
223
+ resolve2();
224
+ });
225
+ });
226
+ }
227
+ __name(launchDetached, "launchDetached");
228
+ function formatLaunchError(error) {
229
+ return error instanceof Error ? error.message : String(error);
230
+ }
231
+ __name(formatLaunchError, "formatLaunchError");
232
+ function buildBrowserCommand(browserEnv, url) {
233
+ if (!browserEnv) {
234
+ return void 0;
235
+ }
236
+ const browserCommand = parseBrowserCommand(browserEnv);
237
+ if (!browserCommand) {
238
+ console.warn(
239
+ "Invalid BROWSER environment variable, falling back to platform default."
412
240
  );
413
- if (!is_wsl_default) {
414
- childProcessOptions.windowsVerbatimArguments = true;
415
- }
416
- const encodedArguments = ["Start"];
417
- if (options.wait) {
418
- encodedArguments.push("-Wait");
241
+ return void 0;
242
+ }
243
+ if (isBrowserCommandBlocked(browserCommand.command)) {
244
+ return void 0;
245
+ }
246
+ let usedPlaceholder = false;
247
+ const args = browserCommand.args.map((arg) => {
248
+ if (!arg.includes("%s")) {
249
+ return arg;
419
250
  }
420
- if (app) {
421
- encodedArguments.push(`"\`"${app}\`""`);
422
- if (options.target) {
423
- appArguments.push(options.target);
251
+ usedPlaceholder = true;
252
+ return arg.replace(/%s/g, () => url);
253
+ });
254
+ if (!usedPlaceholder) {
255
+ args.push(url);
256
+ }
257
+ return { command: browserCommand.command, args };
258
+ }
259
+ __name(buildBrowserCommand, "buildBrowserCommand");
260
+ function parseBrowserCommand(browserEnv) {
261
+ const parts = [];
262
+ let current = "";
263
+ let quote;
264
+ for (const char of browserEnv) {
265
+ if (quote) {
266
+ if (char === quote) {
267
+ quote = void 0;
268
+ } else {
269
+ current += char;
424
270
  }
425
- } else if (options.target) {
426
- encodedArguments.push(`"${options.target}"`);
271
+ continue;
427
272
  }
428
- if (appArguments.length > 0) {
429
- appArguments = appArguments.map((argument) => `"\`"${argument}\`""`);
430
- encodedArguments.push("-ArgumentList", appArguments.join(","));
273
+ if (char === '"' || char === "'") {
274
+ quote = char;
275
+ continue;
431
276
  }
432
- options.target = Buffer.from(encodedArguments.join(" "), "utf16le").toString("base64");
433
- } else {
434
- if (app) {
435
- command = app;
436
- } else {
437
- const isBundled = !__dirname || __dirname === "/";
438
- let exeLocalXdgOpen = false;
439
- try {
440
- await fs5.access(localXdgOpenPath, fsConstants2.X_OK);
441
- exeLocalXdgOpen = true;
442
- } catch {
277
+ if (/\s/.test(char)) {
278
+ if (current) {
279
+ parts.push(current);
280
+ current = "";
443
281
  }
444
- const useSystemXdgOpen = process7.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
445
- command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
446
- }
447
- if (appArguments.length > 0) {
448
- cliArguments.push(...appArguments);
282
+ continue;
449
283
  }
450
- if (!options.wait) {
451
- childProcessOptions.stdio = "ignore";
452
- childProcessOptions.detached = true;
453
- }
454
- }
455
- if (platform === "darwin" && appArguments.length > 0) {
456
- cliArguments.push("--args", ...appArguments);
457
- }
458
- if (options.target) {
459
- cliArguments.push(options.target);
284
+ current += char;
460
285
  }
461
- const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
462
- if (options.wait) {
463
- return new Promise((resolve, reject) => {
464
- subprocess.once("error", reject);
465
- subprocess.once("close", (exitCode) => {
466
- if (!options.allowNonzeroExitCode && exitCode > 0) {
467
- reject(new Error(`Exited with code ${exitCode}`));
468
- return;
469
- }
470
- resolve(subprocess);
471
- });
472
- });
473
- }
474
- subprocess.unref();
475
- return subprocess;
476
- }, "baseOpen");
477
- var open = /* @__PURE__ */ __name((target, options) => {
478
- if (typeof target !== "string") {
479
- throw new TypeError("Expected a `target`");
286
+ if (quote) {
287
+ return void 0;
480
288
  }
481
- return baseOpen({
482
- ...options,
483
- target
484
- });
485
- }, "open");
486
- function detectArchBinary(binary) {
487
- if (typeof binary === "string" || Array.isArray(binary)) {
488
- return binary;
289
+ if (current) {
290
+ parts.push(current);
489
291
  }
490
- const { [arch]: archBinary } = binary;
491
- if (!archBinary) {
492
- throw new Error(`${arch} is not supported`);
292
+ const [command, ...args] = parts;
293
+ if (!command) {
294
+ return void 0;
493
295
  }
494
- return archBinary;
296
+ return { command, args };
495
297
  }
496
- __name(detectArchBinary, "detectArchBinary");
497
- function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
498
- if (wsl && is_wsl_default) {
499
- return detectArchBinary(wsl);
500
- }
501
- if (!platformBinary) {
502
- throw new Error(`${platform} is not supported`);
503
- }
504
- return detectArchBinary(platformBinary);
298
+ __name(parseBrowserCommand, "parseBrowserCommand");
299
+ function shouldLaunchBrowser() {
300
+ return shouldAttemptBrowserLaunch();
505
301
  }
506
- __name(detectPlatformBinary, "detectPlatformBinary");
507
- var apps = {};
508
- defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
509
- darwin: "google chrome",
510
- win32: "chrome",
511
- linux: ["google-chrome", "google-chrome-stable", "chromium"]
512
- }, {
513
- wsl: {
514
- ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
515
- x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
516
- }
517
- }));
518
- defineLazyProperty(apps, "brave", () => detectPlatformBinary({
519
- darwin: "brave browser",
520
- win32: "brave",
521
- linux: ["brave-browser", "brave"]
522
- }, {
523
- wsl: {
524
- ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
525
- x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
526
- }
527
- }));
528
- defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
529
- darwin: "firefox",
530
- win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
531
- linux: "firefox"
532
- }, {
533
- wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
534
- }));
535
- defineLazyProperty(apps, "edge", () => detectPlatformBinary({
536
- darwin: "microsoft edge",
537
- win32: "msedge",
538
- linux: ["microsoft-edge", "microsoft-edge-dev"]
539
- }, {
540
- wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
541
- }));
542
- defineLazyProperty(apps, "browser", () => "browser");
543
- defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
544
- var open_default = open;
545
-
546
- // packages/core/src/qwen/qwenOAuth2.ts
547
- import { EventEmitter } from "events";
548
- import { randomUUID as randomUUID2 } from "node:crypto";
302
+ __name(shouldLaunchBrowser, "shouldLaunchBrowser");
549
303
 
550
304
  // packages/core/src/qwen/sharedTokenManager.ts
551
305
  init_esbuild_shims();
552
- import path2 from "node:path";
553
- import { promises as fs6, unlinkSync } from "node:fs";
306
+ import path from "node:path";
307
+ import { promises as fs, unlinkSync } from "node:fs";
554
308
  import { randomUUID } from "node:crypto";
555
309
  var debugLogger = createDebugLogger("QWEN_OAUTH");
556
310
  var QWEN_CREDENTIAL_FILENAME = "oauth_creds.json";
557
311
  var QWEN_LOCK_FILENAME = "oauth_creds.lock";
558
312
  var TOKEN_REFRESH_BUFFER_MS = 30 * 1e3;
559
- var LOCK_TIMEOUT_MS = 1e4;
313
+ var LOCK_TIMEOUT_MS = 35e3;
560
314
  var CACHE_CHECK_INTERVAL_MS = 5e3;
561
315
  var DEFAULT_LOCK_CONFIG = {
562
316
  maxAttempts: 20,
@@ -763,7 +517,7 @@ var SharedTokenManager = class _SharedTokenManager {
763
517
  try {
764
518
  const filePath = this.getCredentialFilePath();
765
519
  const stats = await this.withTimeout(
766
- fs6.stat(filePath),
520
+ fs.stat(filePath),
767
521
  3e3,
768
522
  "File operation"
769
523
  );
@@ -790,7 +544,7 @@ var SharedTokenManager = class _SharedTokenManager {
790
544
  async forceFileCheck(qwenClient) {
791
545
  try {
792
546
  const filePath = this.getCredentialFilePath();
793
- const stats = await fs6.stat(filePath);
547
+ const stats = await fs.stat(filePath);
794
548
  const fileModTime = stats.mtimeMs;
795
549
  if (fileModTime > this.memoryCache.fileModTime) {
796
550
  await this.reloadCredentialsFromFile(qwenClient);
@@ -815,7 +569,7 @@ var SharedTokenManager = class _SharedTokenManager {
815
569
  async reloadCredentialsFromFile(qwenClient) {
816
570
  try {
817
571
  const filePath = this.getCredentialFilePath();
818
- const content = await fs6.readFile(filePath, "utf-8");
572
+ const content = await fs.readFile(filePath, "utf-8");
819
573
  const parsedData = JSON.parse(content);
820
574
  const credentials = validateCredentials(parsedData);
821
575
  const previousCredentials = this.memoryCache.credentials;
@@ -943,11 +697,10 @@ var SharedTokenManager = class _SharedTokenManager {
943
697
  */
944
698
  async saveCredentialsToFile(credentials) {
945
699
  const filePath = this.getCredentialFilePath();
946
- const dirPath = path2.dirname(filePath);
947
- const tempPath = `${filePath}.tmp.${randomUUID()}`;
700
+ const dirPath = path.dirname(filePath);
948
701
  try {
949
702
  await this.withTimeout(
950
- fs6.mkdir(dirPath, { recursive: true, mode: 448 }),
703
+ fs.mkdir(dirPath, { recursive: true, mode: 448 }),
951
704
  5e3,
952
705
  "File operation"
953
706
  );
@@ -960,27 +713,18 @@ var SharedTokenManager = class _SharedTokenManager {
960
713
  }
961
714
  const credString = JSON.stringify(credentials, null, 2);
962
715
  try {
963
- await this.withTimeout(
964
- fs6.writeFile(tempPath, credString, { mode: 384 }),
965
- 5e3,
966
- "File operation"
967
- );
968
- await this.withTimeout(
969
- fs6.rename(tempPath, filePath),
970
- 5e3,
971
- "File operation"
972
- );
716
+ await atomicWriteFile(filePath, credString, {
717
+ mode: 384,
718
+ forceMode: true,
719
+ noFollow: true
720
+ });
973
721
  const stats = await this.withTimeout(
974
- fs6.stat(filePath),
722
+ fs.stat(filePath),
975
723
  5e3,
976
724
  "File operation"
977
725
  );
978
726
  this.memoryCache.fileModTime = stats.mtimeMs;
979
727
  } catch (error) {
980
- try {
981
- await this.withTimeout(fs6.unlink(tempPath), 1e3, "File operation");
982
- } catch (_cleanupError) {
983
- }
984
728
  throw new TokenManagerError(
985
729
  "FILE_ACCESS_ERROR" /* FILE_ACCESS_ERROR */,
986
730
  `Failed to write credentials file: ${error instanceof Error ? error.message : String(error)}`,
@@ -1006,7 +750,7 @@ var SharedTokenManager = class _SharedTokenManager {
1006
750
  * @returns The absolute path to the credentials file
1007
751
  */
1008
752
  getCredentialFilePath() {
1009
- return path2.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME);
753
+ return path.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME);
1010
754
  }
1011
755
  /**
1012
756
  * Get the full path to the lock file
@@ -1014,7 +758,7 @@ var SharedTokenManager = class _SharedTokenManager {
1014
758
  * @returns The absolute path to the lock file
1015
759
  */
1016
760
  getLockFilePath() {
1017
- return path2.join(Storage.getGlobalQwenDir(), QWEN_LOCK_FILENAME);
761
+ return path.join(Storage.getGlobalQwenDir(), QWEN_LOCK_FILENAME);
1018
762
  }
1019
763
  /**
1020
764
  * Acquire a file lock to prevent other processes from refreshing tokens simultaneously
@@ -1028,18 +772,18 @@ var SharedTokenManager = class _SharedTokenManager {
1028
772
  let currentInterval = attemptInterval;
1029
773
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
1030
774
  try {
1031
- await fs6.writeFile(lockPath, lockId, { flag: "wx" });
775
+ await fs.writeFile(lockPath, lockId, { flag: "wx" });
1032
776
  return;
1033
777
  } catch (error) {
1034
778
  if (error.code === "EEXIST") {
1035
779
  try {
1036
- const stats = await fs6.stat(lockPath);
780
+ const stats = await fs.stat(lockPath);
1037
781
  const lockAge = Date.now() - stats.mtimeMs;
1038
782
  if (lockAge > LOCK_TIMEOUT_MS) {
1039
783
  const tempPath = `${lockPath}.stale.${randomUUID()}`;
1040
784
  try {
1041
- await fs6.rename(lockPath, tempPath);
1042
- await fs6.unlink(tempPath);
785
+ await fs.rename(lockPath, tempPath);
786
+ await fs.unlink(tempPath);
1043
787
  debugLogger.warn(
1044
788
  `Removed stale lock file: ${lockPath} (age: ${lockAge}ms)`
1045
789
  );
@@ -1055,7 +799,7 @@ var SharedTokenManager = class _SharedTokenManager {
1055
799
  `Failed to stat lock file ${lockPath}: ${statError instanceof Error ? statError.message : String(statError)}`
1056
800
  );
1057
801
  }
1058
- await new Promise((resolve) => setTimeout(resolve, currentInterval));
802
+ await new Promise((resolve2) => setTimeout(resolve2, currentInterval));
1059
803
  currentInterval = Math.min(currentInterval * 1.5, maxInterval);
1060
804
  } else {
1061
805
  throw new TokenManagerError(
@@ -1078,7 +822,7 @@ var SharedTokenManager = class _SharedTokenManager {
1078
822
  */
1079
823
  async releaseLock(lockPath) {
1080
824
  try {
1081
- await fs6.unlink(lockPath);
825
+ await fs.unlink(lockPath);
1082
826
  } catch (error) {
1083
827
  if (error.code !== "ENOENT") {
1084
828
  debugLogger.warn(
@@ -1171,6 +915,7 @@ var QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`;
1171
915
  var QWEN_OAUTH_CLIENT_ID = "f0304373b74a44d2b584a3fb70ca9e56";
1172
916
  var QWEN_OAUTH_SCOPE = "openid profile email model.completion";
1173
917
  var QWEN_OAUTH_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
918
+ var QWEN_OAUTH_REFRESH_TIMEOUT_MS = 3e4;
1174
919
  var QWEN_CREDENTIAL_FILENAME2 = "oauth_creds.json";
1175
920
  function generateCodeVerifier() {
1176
921
  return crypto.randomBytes(32).toString("base64url");
@@ -1192,6 +937,16 @@ function objectToUrlEncoded(data) {
1192
937
  return Object.keys(data).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join("&");
1193
938
  }
1194
939
  __name(objectToUrlEncoded, "objectToUrlEncoded");
940
+ function createTokenRefreshNetworkError(error, timedOut) {
941
+ const prefix = timedOut ? "Token refresh timeout" : "Token refresh failed";
942
+ return new Error(
943
+ `${prefix}: ${formatFetchErrorForUser(error, {
944
+ url: QWEN_OAUTH_TOKEN_ENDPOINT
945
+ })}`,
946
+ { cause: error }
947
+ );
948
+ }
949
+ __name(createTokenRefreshNetworkError, "createTokenRefreshNetworkError");
1195
950
  var CredentialsClearRequiredError = class extends Error {
1196
951
  constructor(message, originalError) {
1197
952
  super(message);
@@ -1369,59 +1124,78 @@ var QwenOAuth2Client = class {
1369
1124
  refresh_token: this.credentials.refresh_token,
1370
1125
  client_id: QWEN_OAUTH_CLIENT_ID
1371
1126
  };
1372
- const response = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
1373
- method: "POST",
1374
- headers: {
1375
- "Content-Type": "application/x-www-form-urlencoded",
1376
- Accept: "application/json"
1377
- },
1378
- body: objectToUrlEncoded(bodyData)
1127
+ const { signal, cleanup } = combineAbortSignals([], {
1128
+ timeoutMs: QWEN_OAUTH_REFRESH_TIMEOUT_MS
1379
1129
  });
1380
- if (!response.ok) {
1381
- const errorData = await response.text();
1382
- if (response.status === 400 || response.status === 401) {
1383
- await clearQwenCredentials();
1384
- throw new CredentialsClearRequiredError(
1385
- "Refresh token expired or invalid. Please use '/auth' to re-authenticate.",
1386
- { status: response.status, response: errorData }
1130
+ debugLogger2.debug("Refreshing access token...");
1131
+ try {
1132
+ let response;
1133
+ try {
1134
+ response = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
1135
+ method: "POST",
1136
+ headers: {
1137
+ "Content-Type": "application/x-www-form-urlencoded",
1138
+ Accept: "application/json"
1139
+ },
1140
+ body: objectToUrlEncoded(bodyData),
1141
+ signal
1142
+ });
1143
+ } catch (error) {
1144
+ throw createTokenRefreshNetworkError(error, signal.aborted);
1145
+ }
1146
+ if (!response.ok) {
1147
+ let errorData;
1148
+ try {
1149
+ errorData = await response.text();
1150
+ } catch (error) {
1151
+ throw createTokenRefreshNetworkError(error, signal.aborted);
1152
+ }
1153
+ if (response.status === 400 || response.status === 401) {
1154
+ await clearQwenCredentials();
1155
+ throw new CredentialsClearRequiredError(
1156
+ "Refresh token expired or invalid. Please use '/auth' to re-authenticate.",
1157
+ { status: response.status, response: errorData }
1158
+ );
1159
+ }
1160
+ throw new Error(
1161
+ `Token refresh failed: ${response.status} ${response.statusText}. Response: ${errorData}`
1387
1162
  );
1388
1163
  }
1389
- throw new Error(
1390
- `Token refresh failed: ${response.status} ${response.statusText}. Response: ${errorData}`
1391
- );
1392
- }
1393
- let responseText;
1394
- try {
1395
- responseText = await response.text();
1396
- } catch {
1397
- responseText = "";
1398
- }
1399
- let responseData;
1400
- try {
1401
- responseData = JSON.parse(responseText);
1402
- } catch {
1403
- throw new Error(
1404
- `Qwen OAuth refresh returned invalid JSON: ${responseText || "(empty response body)"}`
1405
- );
1406
- }
1407
- if (isErrorResponse(responseData)) {
1408
- const errorData = responseData;
1409
- throw new Error(
1410
- `Token refresh failed: ${errorData?.error || "Unknown error"} - ${errorData?.error_description || "No details provided"}`
1411
- );
1164
+ let responseText;
1165
+ try {
1166
+ responseText = await response.text();
1167
+ } catch (error) {
1168
+ throw createTokenRefreshNetworkError(error, signal.aborted);
1169
+ }
1170
+ let responseData;
1171
+ try {
1172
+ responseData = JSON.parse(responseText);
1173
+ } catch {
1174
+ throw new Error(
1175
+ `Qwen OAuth refresh returned invalid JSON: ${responseText || "(empty response body)"}`
1176
+ );
1177
+ }
1178
+ if (isErrorResponse(responseData)) {
1179
+ const errorData = responseData;
1180
+ throw new Error(
1181
+ `Token refresh failed: ${errorData?.error || "Unknown error"} - ${errorData?.error_description || "No details provided"}`
1182
+ );
1183
+ }
1184
+ const tokenData = responseData;
1185
+ const tokens = {
1186
+ access_token: tokenData.access_token,
1187
+ token_type: tokenData.token_type,
1188
+ // Use new refresh token if provided, otherwise preserve existing one
1189
+ refresh_token: tokenData.refresh_token || this.credentials.refresh_token,
1190
+ resource_url: tokenData.resource_url,
1191
+ // Include resource_url if provided
1192
+ expiry_date: Date.now() + tokenData.expires_in * 1e3
1193
+ };
1194
+ this.setCredentials(tokens);
1195
+ return responseData;
1196
+ } finally {
1197
+ cleanup();
1412
1198
  }
1413
- const tokenData = responseData;
1414
- const tokens = {
1415
- access_token: tokenData.access_token,
1416
- token_type: tokenData.token_type,
1417
- // Use new refresh token if provided, otherwise preserve existing one
1418
- refresh_token: tokenData.refresh_token || this.credentials.refresh_token,
1419
- resource_url: tokenData.resource_url,
1420
- // Include resource_url if provided
1421
- expiry_date: Date.now() + tokenData.expires_in * 1e3
1422
- };
1423
- this.setCredentials(tokens);
1424
- return responseData;
1425
1199
  }
1426
1200
  };
1427
1201
  var QwenOAuth2Event = /* @__PURE__ */ ((QwenOAuth2Event2) => {
@@ -1579,19 +1353,8 @@ async function authWithQwenDeviceFlow(client, config) {
1579
1353
  qwenOAuth2Events.emit("auth-progress" /* AuthProgress */, status, message);
1580
1354
  }, "emitAuthProgress");
1581
1355
  const launchBrowser = /* @__PURE__ */ __name(async (url) => {
1582
- let childProcess2;
1583
1356
  try {
1584
- childProcess2 = await open_default(url);
1585
- if (childProcess2 && typeof childProcess2.on === "function") {
1586
- childProcess2.on("error", (err) => {
1587
- debugLogger2.warn(`Browser launch process error: ${err.message}`);
1588
- debugLogger2.info(`Please open this URL manually: ${url}`);
1589
- });
1590
- } else {
1591
- debugLogger2.debug(
1592
- "open() did not return a valid child process object."
1593
- );
1594
- }
1357
+ await openBrowserSecurely(url);
1595
1358
  } catch (err) {
1596
1359
  const errorMessage = err instanceof Error ? err.message : String(err);
1597
1360
  debugLogger2.warn(`Failed to open browser automatically: ${errorMessage}`);
@@ -1671,19 +1434,19 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`
1671
1434
  "polling",
1672
1435
  `Polling... (attempt ${attempt + 1}/${maxAttempts})`
1673
1436
  );
1674
- await new Promise((resolve) => {
1437
+ await new Promise((resolve2) => {
1675
1438
  const checkInterval = 100;
1676
1439
  let elapsedTime = 0;
1677
1440
  const intervalId = setInterval(() => {
1678
1441
  elapsedTime += checkInterval;
1679
1442
  if (isCancelled) {
1680
1443
  clearInterval(intervalId);
1681
- resolve();
1444
+ resolve2();
1682
1445
  return;
1683
1446
  }
1684
1447
  if (elapsedTime >= pollInterval) {
1685
1448
  clearInterval(intervalId);
1686
- resolve();
1449
+ resolve2();
1687
1450
  return;
1688
1451
  }
1689
1452
  }, checkInterval);
@@ -1729,7 +1492,7 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`
1729
1492
  }
1730
1493
  const message = `Error polling for token: ${errorMessage}`;
1731
1494
  emitAuthProgress("error", message);
1732
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
1495
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
1733
1496
  }
1734
1497
  }
1735
1498
  const timeoutMessage = "Authorization timeout, please restart the process.";
@@ -1751,16 +1514,16 @@ var QWEN_CREDENTIAL_FILE_MODE = 384;
1751
1514
  async function cacheQwenCredentials(credentials, opts) {
1752
1515
  const filePath = getQwenCachedCredentialPath();
1753
1516
  try {
1754
- await fs7.mkdir(path3.dirname(filePath), { recursive: true });
1517
+ await fs2.mkdir(path2.dirname(filePath), { recursive: true });
1755
1518
  const credString = JSON.stringify(credentials, null, 2);
1756
1519
  const tempPath = `${filePath}.tmp.${process.pid}.${randomUUID2()}`;
1757
1520
  try {
1758
- await fs7.writeFile(tempPath, credString, {
1521
+ await fs2.writeFile(tempPath, credString, {
1759
1522
  mode: QWEN_CREDENTIAL_FILE_MODE,
1760
1523
  ...opts?.signal ? { signal: opts.signal } : {}
1761
1524
  });
1762
1525
  try {
1763
- await fs7.chmod(tempPath, QWEN_CREDENTIAL_FILE_MODE);
1526
+ await fs2.chmod(tempPath, QWEN_CREDENTIAL_FILE_MODE);
1764
1527
  } catch (chmodErr) {
1765
1528
  if (process.platform !== "win32") {
1766
1529
  throw new Error(
@@ -1771,10 +1534,10 @@ async function cacheQwenCredentials(credentials, opts) {
1771
1534
  `cacheQwenCredentials: chmod 0o${QWEN_CREDENTIAL_FILE_MODE.toString(8)} on Windows temp file ${tempPath} failed; relying on NTFS ACL: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}`
1772
1535
  );
1773
1536
  }
1774
- await fs7.rename(tempPath, filePath);
1537
+ await fs2.rename(tempPath, filePath);
1775
1538
  } catch (writeErr) {
1776
1539
  try {
1777
- await fs7.unlink(tempPath);
1540
+ await fs2.unlink(tempPath);
1778
1541
  } catch {
1779
1542
  }
1780
1543
  throw writeErr;
@@ -1795,7 +1558,7 @@ async function cacheQwenCredentials(credentials, opts) {
1795
1558
  );
1796
1559
  }
1797
1560
  throw new Error(
1798
- `Failed to cache credentials: error when creating folder \`${path3.dirname(filePath)}\` and writing to \`${filePath}\`. ${errorMessage}. Please check permissions.`
1561
+ `Failed to cache credentials: error when creating folder \`${path2.dirname(filePath)}\` and writing to \`${filePath}\`. ${errorMessage}. Please check permissions.`
1799
1562
  );
1800
1563
  }
1801
1564
  }
@@ -1803,7 +1566,7 @@ __name(cacheQwenCredentials, "cacheQwenCredentials");
1803
1566
  async function clearQwenCredentials() {
1804
1567
  try {
1805
1568
  const filePath = getQwenCachedCredentialPath();
1806
- await fs7.unlink(filePath);
1569
+ await fs2.unlink(filePath);
1807
1570
  debugLogger2.debug("Cached Qwen credentials cleared successfully.");
1808
1571
  } catch (error) {
1809
1572
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -1822,13 +1585,16 @@ async function clearQwenCredentials() {
1822
1585
  }
1823
1586
  __name(clearQwenCredentials, "clearQwenCredentials");
1824
1587
  function getQwenCachedCredentialPath() {
1825
- return path3.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME2);
1588
+ return path2.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME2);
1826
1589
  }
1827
1590
  __name(getQwenCachedCredentialPath, "getQwenCachedCredentialPath");
1828
1591
  var clearCachedCredentialFile = clearQwenCredentials;
1829
1592
 
1830
1593
  export {
1831
- open_default,
1594
+ isBrowserCommandBlocked,
1595
+ shouldAttemptBrowserLaunch,
1596
+ openBrowserSecurely,
1597
+ shouldLaunchBrowser,
1832
1598
  SharedTokenManager,
1833
1599
  generateCodeVerifier,
1834
1600
  generateCodeChallenge,
@@ -1848,6 +1614,11 @@ export {
1848
1614
  clearQwenCredentials,
1849
1615
  clearCachedCredentialFile
1850
1616
  };
1617
+ /**
1618
+ * @license
1619
+ * Copyright 2025 Google LLC
1620
+ * SPDX-License-Identifier: Apache-2.0
1621
+ */
1851
1622
  /**
1852
1623
  * @license
1853
1624
  * Copyright 2025 Qwen