@qwen-code/qwen-code 0.18.0-preview.1 → 0.18.0

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 (141) hide show
  1. package/bundled/qc-helper/SKILL.md +1 -2
  2. package/bundled/qc-helper/docs/_meta.ts +1 -0
  3. package/bundled/qc-helper/docs/configuration/settings.md +20 -24
  4. package/bundled/qc-helper/docs/features/_meta.ts +0 -3
  5. package/bundled/qc-helper/docs/features/approval-mode.md +10 -14
  6. package/bundled/qc-helper/docs/features/commands.md +47 -23
  7. package/bundled/qc-helper/docs/features/followup-suggestions.md +2 -2
  8. package/bundled/qc-helper/docs/features/scheduled-tasks.md +1 -1
  9. package/bundled/qc-helper/docs/features/sub-agents.md +60 -0
  10. package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +221 -0
  11. package/bundled/qc-helper/docs/qwen-serve.md +234 -24
  12. package/chunks/{agent-SXS4NQWS.js → agent-LOTJK6AH.js} +25 -19
  13. package/chunks/agent-headless-TU3EPMYU.js +50 -0
  14. package/chunks/{anthropicContentGenerator-4QBVSFSJ.js → anthropicContentGenerator-2HBRNQ3B.js} +7 -7
  15. package/chunks/{askUserQuestion-NOOLRWCJ.js → askUserQuestion-OGCMIBQM.js} +45 -3
  16. package/chunks/{ca-WRHFBIDH.js → ca-BARBRL6N.js} +48 -1
  17. package/chunks/{chunk-JMLIPZUU.js → chunk-2Y5SYSD3.js} +361 -583
  18. package/chunks/chunk-3DHXZ6EV.js +241 -0
  19. package/chunks/{chunk-AVLOK27J.js → chunk-3HTIVKZE.js} +1 -1
  20. package/chunks/{chunk-BNESGOSJ.js → chunk-55ZMG67I.js} +1 -1
  21. package/chunks/chunk-64WXLC72.js +98 -0
  22. package/chunks/{chunk-F6FLCHCS.js → chunk-6YIUGZTC.js} +1069 -211
  23. package/chunks/{chunk-C6WMLUNB.js → chunk-72LDN5PP.js} +1 -1
  24. package/chunks/{chunk-ERREX2ES.js → chunk-7BCMOPIM.js} +64 -24
  25. package/chunks/{chunk-6VFG3EUJ.js → chunk-A7B4ISQP.js} +1 -1
  26. package/chunks/{chunk-F5ORN4YO.js → chunk-B7HXHOHU.js} +1 -1
  27. package/chunks/{chunk-5RNZ2QKF.js → chunk-BIVG75CP.js} +1 -1
  28. package/chunks/{chunk-MVX64PNU.js → chunk-EYENRK4D.js} +1 -1
  29. package/chunks/{chunk-SZOEIL6S.js → chunk-H6BD2ELD.js} +1 -0
  30. package/chunks/{chunk-SCHRFI7O.js → chunk-HLPLOD42.js} +1 -1
  31. package/chunks/{chunk-R5PDRHEF.js → chunk-HR7SV7AY.js} +68 -47
  32. package/chunks/{chunk-JSYEZAYV.js → chunk-IDX6COTE.js} +2 -2
  33. package/chunks/{chunk-6KH2Q7XN.js → chunk-IWAYOW5Q.js} +17482 -11669
  34. package/chunks/chunk-J5MDQKJL.js +2230 -0
  35. package/chunks/{chunk-USE2VQ5P.js → chunk-JTQAQBTV.js} +21 -0
  36. package/chunks/{chunk-ZW7GBCRE.js → chunk-LBP46COL.js} +1014 -163
  37. package/chunks/chunk-LD2XBG6Z.js +102 -0
  38. package/chunks/{chunk-KOA52UTF.js → chunk-LEJ42GNY.js} +14 -14
  39. package/chunks/{chunk-D46KOV3C.js → chunk-M6VTDSVR.js} +1 -1
  40. package/chunks/{chunk-SHUT5MQY.js → chunk-MFBBBTNY.js} +1 -1
  41. package/chunks/{chunk-PLYZAP4W.js → chunk-OHEGWO4L.js} +101 -23
  42. package/chunks/{chunk-NQZ33PWX.js → chunk-PL3MVCWD.js} +11 -11
  43. package/chunks/chunk-QQDPRDVW.js +25 -0
  44. package/chunks/chunk-R7ODSGTK.js +159 -0
  45. package/chunks/{chunk-GBEPNWYB.js → chunk-SEGYWKIH.js} +1 -1
  46. package/chunks/chunk-SKBPNJEW.js +45 -0
  47. package/chunks/{chunk-UABFCMPA.js → chunk-SNGELLWX.js} +3 -1
  48. package/chunks/chunk-XBY7E2FX.js +605 -0
  49. package/chunks/{chunk-G763GDO6.js → chunk-XV4HCEVI.js} +36 -3
  50. package/chunks/{chunk-WFVXF3OM.js → chunk-Z2Z3GUXZ.js} +1 -0
  51. package/chunks/{chunk-BBTV54KB.js → chunk-ZTZ4DDQE.js} +2 -2
  52. package/chunks/{computer-use-CT6MU6P3.js → computer-use-3RH2DOM6.js} +25 -19
  53. package/chunks/contextCommand-K347QT6O.js +52 -0
  54. package/chunks/{cron-create-PIPMXQN4.js → cron-create-YJL3KFWI.js} +3 -3
  55. package/chunks/{cron-delete-6Y5XIDMS.js → cron-delete-WKWSJZQA.js} +3 -3
  56. package/chunks/{cron-list-A4WNRUWZ.js → cron-list-B52XEXAZ.js} +3 -3
  57. package/chunks/{de-M5RPB2NB.js → de-YGKK2BC4.js} +48 -1
  58. package/chunks/{devtools-IXE4UP72.js → devtools-FM6GJPYG.js} +1 -1
  59. package/chunks/{dist-R2SXPG74.js → dist-4LXD6L6X.js} +2 -2
  60. package/chunks/{dist-TE5QKMGR.js → dist-H6ONXVLG.js} +1 -1
  61. package/chunks/{dist-ZMQ4TXD5.js → dist-KAZ3SEBX.js} +2 -2
  62. package/chunks/{dist-BXDUQ2QY.js → dist-PK7DFCAW.js} +1 -1
  63. package/chunks/{edit-A4YK7AIB.js → edit-KU4PJGEX.js} +26 -20
  64. package/chunks/{en-UMYKQAZE.js → en-DHGYHIHX.js} +77 -2
  65. package/chunks/{enter-worktree-VNEQINLC.js → enter-worktree-PPYIDCWI.js} +25 -19
  66. package/chunks/enterPlanMode-5CZDMCB4.js +158 -0
  67. package/chunks/{exit-worktree-AVSMXC33.js → exit-worktree-UY3CGHKC.js} +25 -19
  68. package/chunks/exitPlanMode-3DN4QNSG.js +703 -0
  69. package/chunks/{fr-MPYXXXPW.js → fr-JXBKPJKQ.js} +48 -1
  70. package/chunks/{geminiContentGenerator-CR2WGARL.js → geminiContentGenerator-7A6I2RWB.js} +7 -7
  71. package/chunks/{getMachineId-bsd-F7GNPTER.js → getMachineId-bsd-4CASPIU4.js} +1 -1
  72. package/chunks/{getMachineId-darwin-T73DJL27.js → getMachineId-darwin-HPQPEMZR.js} +1 -1
  73. package/chunks/{getMachineId-linux-MKQTFPQM.js → getMachineId-linux-AUARKYHL.js} +1 -1
  74. package/chunks/{getMachineId-unsupported-MUR5KOQE.js → getMachineId-unsupported-S32ZDA2T.js} +1 -1
  75. package/chunks/{getMachineId-win-CDYFC6ZM.js → getMachineId-win-4EFLHYIJ.js} +1 -1
  76. package/chunks/{glob-5V32KOG5.js → glob-OFNQSS52.js} +25 -19
  77. package/chunks/{grep-PUTEPBR4.js → grep-6J2MSUM5.js} +28 -19
  78. package/chunks/{ja-NFZ32AB3.js → ja-TGPZSP2B.js} +48 -1
  79. package/chunks/{keychain-token-storage-UHGOCDD6.js → keychain-token-storage-6IU6ORQN.js} +3 -3
  80. package/chunks/{ls-34DLNYCD.js → ls-V3O6A5PT.js} +4 -4
  81. package/chunks/{lsp-NCDEHH3V.js → lsp-G2OCIFUA.js} +3 -3
  82. package/chunks/{monitor-EJBR5VCR.js → monitor-FKLHV423.js} +25 -19
  83. package/chunks/{notebook-edit-DZHGPP2L.js → notebook-edit-KTBYFKWG.js} +26 -20
  84. package/chunks/{openaiContentGenerator-4QNV3CHM.js → openaiContentGenerator-L5KSWQY7.js} +15 -14
  85. package/chunks/{pt-BR43FRBA.js → pt-TIBG6BIO.js} +48 -1
  86. package/chunks/{qwenContentGenerator-3XOCEMQO.js → qwenContentGenerator-PYOXLMBW.js} +27 -21
  87. package/chunks/{qwenOAuth2-KRJT35QH.js → qwenOAuth2-2KCKWDCF.js} +6 -5
  88. package/chunks/{read-file-VZ2SQQIX.js → read-file-JQVRK4NU.js} +11 -11
  89. package/chunks/ripGrep-2L4LPNAJ.js +48 -0
  90. package/chunks/{ru-DQCW2KHD.js → ru-JBCHCK4L.js} +48 -1
  91. package/chunks/{scheduler-H32DZVDV.js → scheduler-FGNXY4JQ.js} +25 -19
  92. package/chunks/send-message-SZFWNOCL.js +244 -0
  93. package/chunks/{serve-56G4B5W6.js → serve-N2IBLA3G.js} +13592 -4979
  94. package/chunks/{shell-Q77KNP4N.js → shell-PTEG6UX4.js} +25 -19
  95. package/chunks/{skill-CLWFJYBG.js → skill-X4NTK4NH.js} +64 -113
  96. package/chunks/{src-47L2LUOU.js → src-GLLQ3R5W.js} +307 -32
  97. package/chunks/{syntheticOutput-T5SWX3YF.js → syntheticOutput-IKAY5F6X.js} +4 -4
  98. package/chunks/task-create-MQICOJFV.js +19 -0
  99. package/chunks/task-list-RIHJCH32.js +151 -0
  100. package/chunks/{task-stop-3VHAQMYM.js → task-stop-FWZRFANS.js} +3 -3
  101. package/chunks/task-update-2LHPXOYM.js +408 -0
  102. package/chunks/team-create-2E4PF4KN.js +314 -0
  103. package/chunks/team-delete-DAUDQS4J.js +116 -0
  104. package/chunks/{todoWrite-EAGJGKO5.js → todoWrite-HTUACZES.js} +5 -5
  105. package/chunks/{tool-search-Q75AYDTP.js → tool-search-KTVULRES.js} +11 -11
  106. package/chunks/{web-fetch-SS6IKK6N.js → web-fetch-CZ7LLKPE.js} +5 -5
  107. package/chunks/workflow-L2ZUUDT2.js +960 -0
  108. package/chunks/{write-file-RENGC25N.js → write-file-ZEB2JDYH.js} +26 -20
  109. package/chunks/{zh-6VFXOAR5.js → zh-7H5OQC4I.js} +82 -7
  110. package/chunks/{zh-TW-IQZ4AD5M.js → zh-TW-P4IDHD3M.js} +79 -7
  111. package/cli.js +11248 -5119
  112. package/examples/agent/qwen-extension.json +1 -0
  113. package/examples/commands/qwen-extension.json +1 -0
  114. package/examples/context/qwen-extension.json +1 -0
  115. package/examples/mcp-server/qwen-extension.json +1 -0
  116. package/examples/skills/qwen-extension.json +1 -0
  117. package/examples/starter/QWEN.md +30 -0
  118. package/examples/starter/README.md +59 -0
  119. package/examples/starter/agents/diary.md +86 -0
  120. package/examples/starter/commands/writing/polish.md +13 -0
  121. package/examples/starter/example.ts +64 -0
  122. package/examples/starter/package.json +18 -0
  123. package/examples/starter/qwen-extension.json +12 -0
  124. package/examples/starter/skills/synonyms/SKILL.md +48 -0
  125. package/examples/starter/tsconfig.json +13 -0
  126. package/fzfWorker.js +1083 -0
  127. package/locales/ca.js +51 -0
  128. package/locales/de.js +51 -0
  129. package/locales/en.js +89 -2
  130. package/locales/fr.js +53 -2
  131. package/locales/ja.js +52 -2
  132. package/locales/pt.js +52 -2
  133. package/locales/ru.js +53 -2
  134. package/locales/zh-TW.js +90 -11
  135. package/locales/zh.js +94 -11
  136. package/package.json +3 -2
  137. package/bundled/qc-helper/docs/features/checkpointing.md +0 -77
  138. package/chunks/contextCommand-YODJQYIV.js +0 -46
  139. package/chunks/exitPlanMode-5SQYVROD.js +0 -229
  140. package/chunks/ripGrep-SBIZCPOL.js +0 -42
  141. package/chunks/send-message-YYF56TS7.js +0 -151
@@ -2,14 +2,17 @@
2
2
  "use strict";
3
3
  import {
4
4
  formatFetchErrorForUser
5
- } from "./chunk-GBEPNWYB.js";
5
+ } from "./chunk-SEGYWKIH.js";
6
+ import {
7
+ combineAbortSignals
8
+ } from "./chunk-64WXLC72.js";
6
9
  import {
7
10
  atomicWriteFile
8
- } from "./chunk-F5ORN4YO.js";
11
+ } from "./chunk-B7HXHOHU.js";
9
12
  import {
10
13
  Storage,
11
14
  createDebugLogger
12
- } from "./chunk-R5PDRHEF.js";
15
+ } from "./chunk-HR7SV7AY.js";
13
16
  import {
14
17
  init_esbuild_shims
15
18
  } from "./chunk-A4BMJM77.js";
@@ -20,546 +23,294 @@ import {
20
23
  // packages/core/src/qwen/qwenOAuth2.ts
21
24
  init_esbuild_shims();
22
25
  import crypto from "crypto";
23
- import path3 from "node:path";
24
- import { promises as fs7 } from "node:fs";
25
-
26
- // node_modules/open/index.js
27
- init_esbuild_shims();
28
- import process7 from "node:process";
29
- import { Buffer } from "node:buffer";
30
- import path from "node:path";
31
- import { fileURLToPath } from "node:url";
32
- import { promisify as promisify5 } from "node:util";
33
- import childProcess from "node:child_process";
34
- import fs5, { constants as fsConstants2 } from "node:fs/promises";
35
-
36
- // node_modules/wsl-utils/index.js
37
- init_esbuild_shims();
38
- import process3 from "node:process";
39
- import fs4, { constants as fsConstants } from "node:fs/promises";
40
-
41
- // node_modules/is-wsl/index.js
42
- init_esbuild_shims();
43
- import process2 from "node:process";
44
- import os from "node:os";
45
- 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";
46
30
 
47
- // node_modules/is-inside-container/index.js
31
+ // packages/core/src/utils/secure-browser-launcher.ts
48
32
  init_esbuild_shims();
49
- 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";
50
38
 
51
- // node_modules/is-docker/index.js
39
+ // packages/core/src/utils/browser.ts
52
40
  init_esbuild_shims();
53
- import fs from "node:fs";
54
- var isDockerCached;
55
- function hasDockerEnv() {
56
- try {
57
- fs.statSync("/.dockerenv");
58
- return true;
59
- } catch {
60
- return false;
61
- }
62
- }
63
- __name(hasDockerEnv, "hasDockerEnv");
64
- function hasDockerCGroup() {
65
- try {
66
- return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
67
- } catch {
68
- return false;
69
- }
70
- }
71
- __name(hasDockerCGroup, "hasDockerCGroup");
72
- function isDocker() {
73
- if (isDockerCached === void 0) {
74
- isDockerCached = hasDockerEnv() || hasDockerCGroup();
75
- }
76
- return isDockerCached;
41
+ var browserBlocklist = ["www-browser"];
42
+ function isBrowserCommandBlocked(command) {
43
+ const commandName = command.replace(/\\/g, "/").split("/").pop();
44
+ return !!commandName && browserBlocklist.includes(commandName);
77
45
  }
78
- __name(isDocker, "isDocker");
79
-
80
- // node_modules/is-inside-container/index.js
81
- var cachedResult;
82
- var hasContainerEnv = /* @__PURE__ */ __name(() => {
83
- try {
84
- fs2.statSync("/run/.containerenv");
85
- return true;
86
- } 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)) {
87
51
  return false;
88
52
  }
89
- }, "hasContainerEnv");
90
- function isInsideContainer() {
91
- if (cachedResult === void 0) {
92
- cachedResult = hasContainerEnv() || isDocker();
93
- }
94
- return cachedResult;
95
- }
96
- __name(isInsideContainer, "isInsideContainer");
97
-
98
- // node_modules/is-wsl/index.js
99
- var isWsl = /* @__PURE__ */ __name(() => {
100
- if (process2.platform !== "linux") {
53
+ if (process.env["CI"] || process.env["DEBIAN_FRONTEND"] === "noninteractive") {
101
54
  return false;
102
55
  }
103
- if (os.release().toLowerCase().includes("microsoft")) {
104
- 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) {
105
61
  return false;
106
62
  }
107
- return true;
108
63
  }
109
- try {
110
- return fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isInsideContainer() : false;
111
- } catch {
64
+ if (isSSH && process.platform !== "linux") {
112
65
  return false;
113
66
  }
114
- }, "isWsl");
115
- var is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
116
-
117
- // node_modules/wsl-utils/index.js
118
- var wslDrivesMountPoint = /* @__PURE__ */ (() => {
119
- const defaultMountPoint = "/mnt/";
120
- let mountPoint;
121
- return async function() {
122
- if (mountPoint) {
123
- return mountPoint;
124
- }
125
- const configFilePath = "/etc/wsl.conf";
126
- let isConfigFileExists = false;
127
- try {
128
- await fs4.access(configFilePath, fsConstants.F_OK);
129
- isConfigFileExists = true;
130
- } catch {
131
- }
132
- if (!isConfigFileExists) {
133
- return defaultMountPoint;
134
- }
135
- const configContent = await fs4.readFile(configFilePath, { encoding: "utf8" });
136
- const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
137
- if (!configMountPoint) {
138
- return defaultMountPoint;
139
- }
140
- mountPoint = configMountPoint.groups.mountPoint.trim();
141
- mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
142
- return mountPoint;
143
- };
144
- })();
145
- var powerShellPathFromWsl = /* @__PURE__ */ __name(async () => {
146
- const mountPoint = await wslDrivesMountPoint();
147
- return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
148
- }, "powerShellPathFromWsl");
149
- var powerShellPath = /* @__PURE__ */ __name(async () => {
150
- if (is_wsl_default) {
151
- return powerShellPathFromWsl();
152
- }
153
- return `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
154
- }, "powerShellPath");
155
-
156
- // node_modules/define-lazy-prop/index.js
157
- init_esbuild_shims();
158
- function defineLazyProperty(object, propertyName, valueGetter) {
159
- const define = /* @__PURE__ */ __name((value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true }), "define");
160
- Object.defineProperty(object, propertyName, {
161
- configurable: true,
162
- enumerable: true,
163
- get() {
164
- const result = valueGetter();
165
- define(result);
166
- return result;
167
- },
168
- set(value) {
169
- define(value);
170
- }
171
- });
172
- return object;
67
+ return true;
173
68
  }
174
- __name(defineLazyProperty, "defineLazyProperty");
175
-
176
- // node_modules/default-browser/index.js
177
- init_esbuild_shims();
178
- import { promisify as promisify4 } from "node:util";
179
- import process6 from "node:process";
180
- import { execFile as execFile4 } from "node:child_process";
69
+ __name(shouldAttemptBrowserLaunch, "shouldAttemptBrowserLaunch");
181
70
 
182
- // node_modules/default-browser-id/index.js
183
- init_esbuild_shims();
184
- import { promisify } from "node:util";
185
- import process4 from "node:process";
186
- import { execFile } from "node:child_process";
71
+ // packages/core/src/utils/secure-browser-launcher.ts
187
72
  var execFileAsync = promisify(execFile);
188
- async function defaultBrowserId() {
189
- if (process4.platform !== "darwin") {
190
- 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}`);
191
79
  }
192
- const { stdout } = await execFileAsync("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
193
- const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
194
- return match?.groups.id ?? "com.apple.Safari";
195
- }
196
- __name(defaultBrowserId, "defaultBrowserId");
197
-
198
- // node_modules/bundle-name/index.js
199
- init_esbuild_shims();
200
-
201
- // node_modules/run-applescript/index.js
202
- init_esbuild_shims();
203
- import process5 from "node:process";
204
- import { promisify as promisify2 } from "node:util";
205
- import { execFile as execFile2, execFileSync } from "node:child_process";
206
- var execFileAsync2 = promisify2(execFile2);
207
- async function runAppleScript(script, { humanReadableOutput = true } = {}) {
208
- if (process5.platform !== "darwin") {
209
- throw new Error("macOS only");
210
- }
211
- const outputArguments = humanReadableOutput ? [] : ["-ss"];
212
- const { stdout } = await execFileAsync2("osascript", ["-e", script, outputArguments]);
213
- return stdout.trim();
214
- }
215
- __name(runAppleScript, "runAppleScript");
216
-
217
- // node_modules/bundle-name/index.js
218
- async function bundleName(bundleId) {
219
- return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
220
- tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
221
- }
222
- __name(bundleName, "bundleName");
223
-
224
- // node_modules/default-browser/windows.js
225
- init_esbuild_shims();
226
- import { promisify as promisify3 } from "node:util";
227
- import { execFile as execFile3 } from "node:child_process";
228
- var execFileAsync3 = promisify3(execFile3);
229
- var windowsBrowserProgIds = {
230
- AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
231
- MSEdgeDHTML: { name: "Edge", id: "com.microsoft.edge" },
232
- // On macOS, it's "com.microsoft.edgemac"
233
- MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
234
- // Newer Edge/Win10 releases
235
- "IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" },
236
- FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
237
- ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
238
- BraveHTML: { name: "Brave", id: "com.brave.Browser" },
239
- BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
240
- BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" }
241
- };
242
- var UnknownBrowserError = class extends Error {
243
- static {
244
- __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");
245
100
  }
246
- };
247
- async function defaultBrowser(_execFileAsync = execFileAsync3) {
248
- const { stdout } = await _execFileAsync("reg", [
249
- "QUERY",
250
- " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
251
- "/v",
252
- "ProgId"
253
- ]);
254
- const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
255
- if (!match) {
256
- throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
257
- }
258
- const { id } = match.groups;
259
- const browser = windowsBrowserProgIds[id];
260
- if (!browser) {
261
- throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
262
- }
263
- return browser;
264
- }
265
- __name(defaultBrowser, "defaultBrowser");
266
-
267
- // node_modules/default-browser/index.js
268
- var execFileAsync4 = promisify4(execFile4);
269
- var titleize = /* @__PURE__ */ __name((string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase()), "titleize");
270
- async function defaultBrowser2() {
271
- if (process6.platform === "darwin") {
272
- const id = await defaultBrowserId();
273
- const name = await bundleName(id);
274
- return { name, id };
275
- }
276
- if (process6.platform === "linux") {
277
- const { stdout } = await execFileAsync4("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
278
- const id = stdout.trim();
279
- const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
280
- return { name, id };
281
- }
282
- if (process6.platform === "win32") {
283
- return defaultBrowser();
284
- }
285
- throw new Error("Only macOS, Linux, and Windows are supported");
286
- }
287
- __name(defaultBrowser2, "defaultBrowser");
288
-
289
- // node_modules/open/index.js
290
- var execFile5 = promisify5(childProcess.execFile);
291
- var __dirname = path.dirname(fileURLToPath(import.meta.url));
292
- var localXdgOpenPath = path.join(__dirname, "xdg-open");
293
- var { platform, arch } = process7;
294
- async function getWindowsDefaultBrowserFromWsl() {
295
- const powershellPath = await powerShellPath();
296
- const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
297
- const encodedCommand = Buffer.from(rawCommand, "utf16le").toString("base64");
298
- const { stdout } = await execFile5(
299
- powershellPath,
300
- [
301
- "-NoProfile",
302
- "-NonInteractive",
303
- "-ExecutionPolicy",
304
- "Bypass",
305
- "-EncodedCommand",
306
- encodedCommand
307
- ],
308
- { encoding: "utf8" }
309
- );
310
- const progId = stdout.trim();
311
- const browserMap = {
312
- ChromeHTML: "com.google.chrome",
313
- BraveHTML: "com.brave.Browser",
314
- MSEdgeHTM: "com.microsoft.edge",
315
- FirefoxURL: "org.mozilla.firefox"
316
- };
317
- return browserMap[progId] ? { id: browserMap[progId] } : {};
318
101
  }
319
- __name(getWindowsDefaultBrowserFromWsl, "getWindowsDefaultBrowserFromWsl");
320
- var pTryEach = /* @__PURE__ */ __name(async (array, mapper) => {
321
- let latestError;
322
- 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) {
323
111
  try {
324
- return await mapper(item);
325
- } catch (error) {
326
- 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
+ );
327
120
  }
328
121
  }
329
- throw latestError;
330
- }, "pTryEach");
331
- var baseOpen = /* @__PURE__ */ __name(async (options) => {
332
- options = {
333
- wait: false,
334
- background: false,
335
- newInstance: false,
336
- allowNonzeroExitCode: false,
337
- ...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"
338
165
  };
339
- if (Array.isArray(options.app)) {
340
- return pTryEach(options.app, (singleApp) => baseOpen({
341
- ...options,
342
- app: singleApp
343
- }));
344
- }
345
- let { name: app, arguments: appArguments = [] } = options.app ?? {};
346
- appArguments = [...appArguments];
347
- if (Array.isArray(app)) {
348
- return pTryEach(app, (appName) => baseOpen({
349
- ...options,
350
- app: {
351
- name: appName,
352
- arguments: appArguments
353
- }
354
- }));
355
- }
356
- if (app === "browser" || app === "browserPrivate") {
357
- const ids = {
358
- "com.google.chrome": "chrome",
359
- "google-chrome.desktop": "chrome",
360
- "com.brave.Browser": "brave",
361
- "org.mozilla.firefox": "firefox",
362
- "firefox.desktop": "firefox",
363
- "com.microsoft.msedge": "edge",
364
- "com.microsoft.edge": "edge",
365
- "com.microsoft.edgemac": "edge",
366
- "microsoft-edge.desktop": "edge"
367
- };
368
- const flags = {
369
- chrome: "--incognito",
370
- brave: "--incognito",
371
- firefox: "--private-window",
372
- edge: "--inPrivate"
373
- };
374
- const browser = is_wsl_default ? await getWindowsDefaultBrowserFromWsl() : await defaultBrowser2();
375
- if (browser.id in ids) {
376
- const browserName = ids[browser.id];
377
- if (app === "browserPrivate") {
378
- appArguments.push(flags[browserName]);
379
- }
380
- return baseOpen({
381
- ...options,
382
- app: {
383
- name: apps[browserName],
384
- 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;
385
188
  }
386
- });
189
+ }
387
190
  }
388
- 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;
389
195
  }
390
- let command;
391
- const cliArguments = [];
392
- const childProcessOptions = {};
393
- if (platform === "darwin") {
394
- command = "open";
395
- if (options.wait) {
396
- cliArguments.push("--wait-apps");
397
- }
398
- if (options.background) {
399
- cliArguments.push("--background");
400
- }
401
- if (options.newInstance) {
402
- cliArguments.push("--new");
403
- }
404
- if (app) {
405
- cliArguments.push("-a", app);
406
- }
407
- } else if (platform === "win32" || is_wsl_default && !isInsideContainer() && !app) {
408
- command = await powerShellPath();
409
- cliArguments.push(
410
- "-NoProfile",
411
- "-NonInteractive",
412
- "-ExecutionPolicy",
413
- "Bypass",
414
- "-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."
415
240
  );
416
- if (!is_wsl_default) {
417
- childProcessOptions.windowsVerbatimArguments = true;
418
- }
419
- const encodedArguments = ["Start"];
420
- if (options.wait) {
421
- 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;
422
250
  }
423
- if (app) {
424
- encodedArguments.push(`"\`"${app}\`""`);
425
- if (options.target) {
426
- 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;
427
270
  }
428
- } else if (options.target) {
429
- encodedArguments.push(`"${options.target}"`);
271
+ continue;
430
272
  }
431
- if (appArguments.length > 0) {
432
- appArguments = appArguments.map((argument) => `"\`"${argument}\`""`);
433
- encodedArguments.push("-ArgumentList", appArguments.join(","));
273
+ if (char === '"' || char === "'") {
274
+ quote = char;
275
+ continue;
434
276
  }
435
- options.target = Buffer.from(encodedArguments.join(" "), "utf16le").toString("base64");
436
- } else {
437
- if (app) {
438
- command = app;
439
- } else {
440
- const isBundled = !__dirname || __dirname === "/";
441
- let exeLocalXdgOpen = false;
442
- try {
443
- await fs5.access(localXdgOpenPath, fsConstants2.X_OK);
444
- exeLocalXdgOpen = true;
445
- } catch {
277
+ if (/\s/.test(char)) {
278
+ if (current) {
279
+ parts.push(current);
280
+ current = "";
446
281
  }
447
- const useSystemXdgOpen = process7.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
448
- command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
449
- }
450
- if (appArguments.length > 0) {
451
- cliArguments.push(...appArguments);
452
- }
453
- if (!options.wait) {
454
- childProcessOptions.stdio = "ignore";
455
- childProcessOptions.detached = true;
282
+ continue;
456
283
  }
284
+ current += char;
457
285
  }
458
- if (platform === "darwin" && appArguments.length > 0) {
459
- cliArguments.push("--args", ...appArguments);
286
+ if (quote) {
287
+ return void 0;
460
288
  }
461
- if (options.target) {
462
- cliArguments.push(options.target);
289
+ if (current) {
290
+ parts.push(current);
463
291
  }
464
- const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
465
- if (options.wait) {
466
- return new Promise((resolve, reject) => {
467
- subprocess.once("error", reject);
468
- subprocess.once("close", (exitCode) => {
469
- if (!options.allowNonzeroExitCode && exitCode > 0) {
470
- reject(new Error(`Exited with code ${exitCode}`));
471
- return;
472
- }
473
- resolve(subprocess);
474
- });
475
- });
476
- }
477
- subprocess.unref();
478
- return subprocess;
479
- }, "baseOpen");
480
- var open = /* @__PURE__ */ __name((target, options) => {
481
- if (typeof target !== "string") {
482
- throw new TypeError("Expected a `target`");
483
- }
484
- return baseOpen({
485
- ...options,
486
- target
487
- });
488
- }, "open");
489
- function detectArchBinary(binary) {
490
- if (typeof binary === "string" || Array.isArray(binary)) {
491
- return binary;
492
- }
493
- const { [arch]: archBinary } = binary;
494
- if (!archBinary) {
495
- throw new Error(`${arch} is not supported`);
292
+ const [command, ...args] = parts;
293
+ if (!command) {
294
+ return void 0;
496
295
  }
497
- return archBinary;
296
+ return { command, args };
498
297
  }
499
- __name(detectArchBinary, "detectArchBinary");
500
- function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
501
- if (wsl && is_wsl_default) {
502
- return detectArchBinary(wsl);
503
- }
504
- if (!platformBinary) {
505
- throw new Error(`${platform} is not supported`);
506
- }
507
- return detectArchBinary(platformBinary);
298
+ __name(parseBrowserCommand, "parseBrowserCommand");
299
+ function shouldLaunchBrowser() {
300
+ return shouldAttemptBrowserLaunch();
508
301
  }
509
- __name(detectPlatformBinary, "detectPlatformBinary");
510
- var apps = {};
511
- defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
512
- darwin: "google chrome",
513
- win32: "chrome",
514
- linux: ["google-chrome", "google-chrome-stable", "chromium"]
515
- }, {
516
- wsl: {
517
- ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
518
- x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
519
- }
520
- }));
521
- defineLazyProperty(apps, "brave", () => detectPlatformBinary({
522
- darwin: "brave browser",
523
- win32: "brave",
524
- linux: ["brave-browser", "brave"]
525
- }, {
526
- wsl: {
527
- ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
528
- x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
529
- }
530
- }));
531
- defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
532
- darwin: "firefox",
533
- win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
534
- linux: "firefox"
535
- }, {
536
- wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
537
- }));
538
- defineLazyProperty(apps, "edge", () => detectPlatformBinary({
539
- darwin: "microsoft edge",
540
- win32: "msedge",
541
- linux: ["microsoft-edge", "microsoft-edge-dev"]
542
- }, {
543
- wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
544
- }));
545
- defineLazyProperty(apps, "browser", () => "browser");
546
- defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
547
- var open_default = open;
548
-
549
- // packages/core/src/qwen/qwenOAuth2.ts
550
- import { EventEmitter } from "events";
551
- import { randomUUID as randomUUID2 } from "node:crypto";
302
+ __name(shouldLaunchBrowser, "shouldLaunchBrowser");
552
303
 
553
304
  // packages/core/src/qwen/sharedTokenManager.ts
554
305
  init_esbuild_shims();
555
- import path2 from "node:path";
556
- import { promises as fs6, unlinkSync } from "node:fs";
306
+ import path from "node:path";
307
+ import { promises as fs, unlinkSync } from "node:fs";
557
308
  import { randomUUID } from "node:crypto";
558
309
  var debugLogger = createDebugLogger("QWEN_OAUTH");
559
310
  var QWEN_CREDENTIAL_FILENAME = "oauth_creds.json";
560
311
  var QWEN_LOCK_FILENAME = "oauth_creds.lock";
561
312
  var TOKEN_REFRESH_BUFFER_MS = 30 * 1e3;
562
- var LOCK_TIMEOUT_MS = 1e4;
313
+ var LOCK_TIMEOUT_MS = 35e3;
563
314
  var CACHE_CHECK_INTERVAL_MS = 5e3;
564
315
  var DEFAULT_LOCK_CONFIG = {
565
316
  maxAttempts: 20,
@@ -766,7 +517,7 @@ var SharedTokenManager = class _SharedTokenManager {
766
517
  try {
767
518
  const filePath = this.getCredentialFilePath();
768
519
  const stats = await this.withTimeout(
769
- fs6.stat(filePath),
520
+ fs.stat(filePath),
770
521
  3e3,
771
522
  "File operation"
772
523
  );
@@ -793,7 +544,7 @@ var SharedTokenManager = class _SharedTokenManager {
793
544
  async forceFileCheck(qwenClient) {
794
545
  try {
795
546
  const filePath = this.getCredentialFilePath();
796
- const stats = await fs6.stat(filePath);
547
+ const stats = await fs.stat(filePath);
797
548
  const fileModTime = stats.mtimeMs;
798
549
  if (fileModTime > this.memoryCache.fileModTime) {
799
550
  await this.reloadCredentialsFromFile(qwenClient);
@@ -818,7 +569,7 @@ var SharedTokenManager = class _SharedTokenManager {
818
569
  async reloadCredentialsFromFile(qwenClient) {
819
570
  try {
820
571
  const filePath = this.getCredentialFilePath();
821
- const content = await fs6.readFile(filePath, "utf-8");
572
+ const content = await fs.readFile(filePath, "utf-8");
822
573
  const parsedData = JSON.parse(content);
823
574
  const credentials = validateCredentials(parsedData);
824
575
  const previousCredentials = this.memoryCache.credentials;
@@ -946,10 +697,10 @@ var SharedTokenManager = class _SharedTokenManager {
946
697
  */
947
698
  async saveCredentialsToFile(credentials) {
948
699
  const filePath = this.getCredentialFilePath();
949
- const dirPath = path2.dirname(filePath);
700
+ const dirPath = path.dirname(filePath);
950
701
  try {
951
702
  await this.withTimeout(
952
- fs6.mkdir(dirPath, { recursive: true, mode: 448 }),
703
+ fs.mkdir(dirPath, { recursive: true, mode: 448 }),
953
704
  5e3,
954
705
  "File operation"
955
706
  );
@@ -968,7 +719,7 @@ var SharedTokenManager = class _SharedTokenManager {
968
719
  noFollow: true
969
720
  });
970
721
  const stats = await this.withTimeout(
971
- fs6.stat(filePath),
722
+ fs.stat(filePath),
972
723
  5e3,
973
724
  "File operation"
974
725
  );
@@ -999,7 +750,7 @@ var SharedTokenManager = class _SharedTokenManager {
999
750
  * @returns The absolute path to the credentials file
1000
751
  */
1001
752
  getCredentialFilePath() {
1002
- return path2.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME);
753
+ return path.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME);
1003
754
  }
1004
755
  /**
1005
756
  * Get the full path to the lock file
@@ -1007,7 +758,7 @@ var SharedTokenManager = class _SharedTokenManager {
1007
758
  * @returns The absolute path to the lock file
1008
759
  */
1009
760
  getLockFilePath() {
1010
- return path2.join(Storage.getGlobalQwenDir(), QWEN_LOCK_FILENAME);
761
+ return path.join(Storage.getGlobalQwenDir(), QWEN_LOCK_FILENAME);
1011
762
  }
1012
763
  /**
1013
764
  * Acquire a file lock to prevent other processes from refreshing tokens simultaneously
@@ -1021,18 +772,18 @@ var SharedTokenManager = class _SharedTokenManager {
1021
772
  let currentInterval = attemptInterval;
1022
773
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
1023
774
  try {
1024
- await fs6.writeFile(lockPath, lockId, { flag: "wx" });
775
+ await fs.writeFile(lockPath, lockId, { flag: "wx" });
1025
776
  return;
1026
777
  } catch (error) {
1027
778
  if (error.code === "EEXIST") {
1028
779
  try {
1029
- const stats = await fs6.stat(lockPath);
780
+ const stats = await fs.stat(lockPath);
1030
781
  const lockAge = Date.now() - stats.mtimeMs;
1031
782
  if (lockAge > LOCK_TIMEOUT_MS) {
1032
783
  const tempPath = `${lockPath}.stale.${randomUUID()}`;
1033
784
  try {
1034
- await fs6.rename(lockPath, tempPath);
1035
- await fs6.unlink(tempPath);
785
+ await fs.rename(lockPath, tempPath);
786
+ await fs.unlink(tempPath);
1036
787
  debugLogger.warn(
1037
788
  `Removed stale lock file: ${lockPath} (age: ${lockAge}ms)`
1038
789
  );
@@ -1048,7 +799,7 @@ var SharedTokenManager = class _SharedTokenManager {
1048
799
  `Failed to stat lock file ${lockPath}: ${statError instanceof Error ? statError.message : String(statError)}`
1049
800
  );
1050
801
  }
1051
- await new Promise((resolve) => setTimeout(resolve, currentInterval));
802
+ await new Promise((resolve2) => setTimeout(resolve2, currentInterval));
1052
803
  currentInterval = Math.min(currentInterval * 1.5, maxInterval);
1053
804
  } else {
1054
805
  throw new TokenManagerError(
@@ -1071,7 +822,7 @@ var SharedTokenManager = class _SharedTokenManager {
1071
822
  */
1072
823
  async releaseLock(lockPath) {
1073
824
  try {
1074
- await fs6.unlink(lockPath);
825
+ await fs.unlink(lockPath);
1075
826
  } catch (error) {
1076
827
  if (error.code !== "ENOENT") {
1077
828
  debugLogger.warn(
@@ -1164,6 +915,7 @@ var QWEN_OAUTH_TOKEN_ENDPOINT = `${QWEN_OAUTH_BASE_URL}/api/v1/oauth2/token`;
1164
915
  var QWEN_OAUTH_CLIENT_ID = "f0304373b74a44d2b584a3fb70ca9e56";
1165
916
  var QWEN_OAUTH_SCOPE = "openid profile email model.completion";
1166
917
  var QWEN_OAUTH_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
918
+ var QWEN_OAUTH_REFRESH_TIMEOUT_MS = 3e4;
1167
919
  var QWEN_CREDENTIAL_FILENAME2 = "oauth_creds.json";
1168
920
  function generateCodeVerifier() {
1169
921
  return crypto.randomBytes(32).toString("base64url");
@@ -1185,6 +937,16 @@ function objectToUrlEncoded(data) {
1185
937
  return Object.keys(data).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join("&");
1186
938
  }
1187
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");
1188
950
  var CredentialsClearRequiredError = class extends Error {
1189
951
  constructor(message, originalError) {
1190
952
  super(message);
@@ -1362,59 +1124,78 @@ var QwenOAuth2Client = class {
1362
1124
  refresh_token: this.credentials.refresh_token,
1363
1125
  client_id: QWEN_OAUTH_CLIENT_ID
1364
1126
  };
1365
- const response = await fetch(QWEN_OAUTH_TOKEN_ENDPOINT, {
1366
- method: "POST",
1367
- headers: {
1368
- "Content-Type": "application/x-www-form-urlencoded",
1369
- Accept: "application/json"
1370
- },
1371
- body: objectToUrlEncoded(bodyData)
1127
+ const { signal, cleanup } = combineAbortSignals([], {
1128
+ timeoutMs: QWEN_OAUTH_REFRESH_TIMEOUT_MS
1372
1129
  });
1373
- if (!response.ok) {
1374
- const errorData = await response.text();
1375
- if (response.status === 400 || response.status === 401) {
1376
- await clearQwenCredentials();
1377
- throw new CredentialsClearRequiredError(
1378
- "Refresh token expired or invalid. Please use '/auth' to re-authenticate.",
1379
- { 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}`
1380
1162
  );
1381
1163
  }
1382
- throw new Error(
1383
- `Token refresh failed: ${response.status} ${response.statusText}. Response: ${errorData}`
1384
- );
1385
- }
1386
- let responseText;
1387
- try {
1388
- responseText = await response.text();
1389
- } catch {
1390
- responseText = "";
1391
- }
1392
- let responseData;
1393
- try {
1394
- responseData = JSON.parse(responseText);
1395
- } catch {
1396
- throw new Error(
1397
- `Qwen OAuth refresh returned invalid JSON: ${responseText || "(empty response body)"}`
1398
- );
1399
- }
1400
- if (isErrorResponse(responseData)) {
1401
- const errorData = responseData;
1402
- throw new Error(
1403
- `Token refresh failed: ${errorData?.error || "Unknown error"} - ${errorData?.error_description || "No details provided"}`
1404
- );
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();
1405
1198
  }
1406
- const tokenData = responseData;
1407
- const tokens = {
1408
- access_token: tokenData.access_token,
1409
- token_type: tokenData.token_type,
1410
- // Use new refresh token if provided, otherwise preserve existing one
1411
- refresh_token: tokenData.refresh_token || this.credentials.refresh_token,
1412
- resource_url: tokenData.resource_url,
1413
- // Include resource_url if provided
1414
- expiry_date: Date.now() + tokenData.expires_in * 1e3
1415
- };
1416
- this.setCredentials(tokens);
1417
- return responseData;
1418
1199
  }
1419
1200
  };
1420
1201
  var QwenOAuth2Event = /* @__PURE__ */ ((QwenOAuth2Event2) => {
@@ -1572,19 +1353,8 @@ async function authWithQwenDeviceFlow(client, config) {
1572
1353
  qwenOAuth2Events.emit("auth-progress" /* AuthProgress */, status, message);
1573
1354
  }, "emitAuthProgress");
1574
1355
  const launchBrowser = /* @__PURE__ */ __name(async (url) => {
1575
- let childProcess2;
1576
1356
  try {
1577
- childProcess2 = await open_default(url);
1578
- if (childProcess2 && typeof childProcess2.on === "function") {
1579
- childProcess2.on("error", (err) => {
1580
- debugLogger2.warn(`Browser launch process error: ${err.message}`);
1581
- debugLogger2.info(`Please open this URL manually: ${url}`);
1582
- });
1583
- } else {
1584
- debugLogger2.debug(
1585
- "open() did not return a valid child process object."
1586
- );
1587
- }
1357
+ await openBrowserSecurely(url);
1588
1358
  } catch (err) {
1589
1359
  const errorMessage = err instanceof Error ? err.message : String(err);
1590
1360
  debugLogger2.warn(`Failed to open browser automatically: ${errorMessage}`);
@@ -1664,19 +1434,19 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`
1664
1434
  "polling",
1665
1435
  `Polling... (attempt ${attempt + 1}/${maxAttempts})`
1666
1436
  );
1667
- await new Promise((resolve) => {
1437
+ await new Promise((resolve2) => {
1668
1438
  const checkInterval = 100;
1669
1439
  let elapsedTime = 0;
1670
1440
  const intervalId = setInterval(() => {
1671
1441
  elapsedTime += checkInterval;
1672
1442
  if (isCancelled) {
1673
1443
  clearInterval(intervalId);
1674
- resolve();
1444
+ resolve2();
1675
1445
  return;
1676
1446
  }
1677
1447
  if (elapsedTime >= pollInterval) {
1678
1448
  clearInterval(intervalId);
1679
- resolve();
1449
+ resolve2();
1680
1450
  return;
1681
1451
  }
1682
1452
  }, checkInterval);
@@ -1722,7 +1492,7 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`
1722
1492
  }
1723
1493
  const message = `Error polling for token: ${errorMessage}`;
1724
1494
  emitAuthProgress("error", message);
1725
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
1495
+ await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
1726
1496
  }
1727
1497
  }
1728
1498
  const timeoutMessage = "Authorization timeout, please restart the process.";
@@ -1744,16 +1514,16 @@ var QWEN_CREDENTIAL_FILE_MODE = 384;
1744
1514
  async function cacheQwenCredentials(credentials, opts) {
1745
1515
  const filePath = getQwenCachedCredentialPath();
1746
1516
  try {
1747
- await fs7.mkdir(path3.dirname(filePath), { recursive: true });
1517
+ await fs2.mkdir(path2.dirname(filePath), { recursive: true });
1748
1518
  const credString = JSON.stringify(credentials, null, 2);
1749
1519
  const tempPath = `${filePath}.tmp.${process.pid}.${randomUUID2()}`;
1750
1520
  try {
1751
- await fs7.writeFile(tempPath, credString, {
1521
+ await fs2.writeFile(tempPath, credString, {
1752
1522
  mode: QWEN_CREDENTIAL_FILE_MODE,
1753
1523
  ...opts?.signal ? { signal: opts.signal } : {}
1754
1524
  });
1755
1525
  try {
1756
- await fs7.chmod(tempPath, QWEN_CREDENTIAL_FILE_MODE);
1526
+ await fs2.chmod(tempPath, QWEN_CREDENTIAL_FILE_MODE);
1757
1527
  } catch (chmodErr) {
1758
1528
  if (process.platform !== "win32") {
1759
1529
  throw new Error(
@@ -1764,10 +1534,10 @@ async function cacheQwenCredentials(credentials, opts) {
1764
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)}`
1765
1535
  );
1766
1536
  }
1767
- await fs7.rename(tempPath, filePath);
1537
+ await fs2.rename(tempPath, filePath);
1768
1538
  } catch (writeErr) {
1769
1539
  try {
1770
- await fs7.unlink(tempPath);
1540
+ await fs2.unlink(tempPath);
1771
1541
  } catch {
1772
1542
  }
1773
1543
  throw writeErr;
@@ -1788,7 +1558,7 @@ async function cacheQwenCredentials(credentials, opts) {
1788
1558
  );
1789
1559
  }
1790
1560
  throw new Error(
1791
- `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.`
1792
1562
  );
1793
1563
  }
1794
1564
  }
@@ -1796,7 +1566,7 @@ __name(cacheQwenCredentials, "cacheQwenCredentials");
1796
1566
  async function clearQwenCredentials() {
1797
1567
  try {
1798
1568
  const filePath = getQwenCachedCredentialPath();
1799
- await fs7.unlink(filePath);
1569
+ await fs2.unlink(filePath);
1800
1570
  debugLogger2.debug("Cached Qwen credentials cleared successfully.");
1801
1571
  } catch (error) {
1802
1572
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -1815,13 +1585,16 @@ async function clearQwenCredentials() {
1815
1585
  }
1816
1586
  __name(clearQwenCredentials, "clearQwenCredentials");
1817
1587
  function getQwenCachedCredentialPath() {
1818
- return path3.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME2);
1588
+ return path2.join(Storage.getGlobalQwenDir(), QWEN_CREDENTIAL_FILENAME2);
1819
1589
  }
1820
1590
  __name(getQwenCachedCredentialPath, "getQwenCachedCredentialPath");
1821
1591
  var clearCachedCredentialFile = clearQwenCredentials;
1822
1592
 
1823
1593
  export {
1824
- open_default,
1594
+ isBrowserCommandBlocked,
1595
+ shouldAttemptBrowserLaunch,
1596
+ openBrowserSecurely,
1597
+ shouldLaunchBrowser,
1825
1598
  SharedTokenManager,
1826
1599
  generateCodeVerifier,
1827
1600
  generateCodeChallenge,
@@ -1841,6 +1614,11 @@ export {
1841
1614
  clearQwenCredentials,
1842
1615
  clearCachedCredentialFile
1843
1616
  };
1617
+ /**
1618
+ * @license
1619
+ * Copyright 2025 Google LLC
1620
+ * SPDX-License-Identifier: Apache-2.0
1621
+ */
1844
1622
  /**
1845
1623
  * @license
1846
1624
  * Copyright 2025 Qwen