@pixelbyte-software/pixcode 1.30.2 → 1.31.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 (202) hide show
  1. package/LICENSE +718 -718
  2. package/README.de.md +248 -248
  3. package/README.ja.md +240 -240
  4. package/README.ko.md +240 -240
  5. package/README.md +295 -285
  6. package/README.ru.md +248 -248
  7. package/README.tr.md +250 -250
  8. package/README.zh-CN.md +240 -240
  9. package/dist/api-docs.html +879 -879
  10. package/dist/assets/index-BRRJ47XQ.css +32 -0
  11. package/dist/assets/index-EQohwyiC.js +837 -0
  12. package/dist/clear-cache.html +85 -85
  13. package/dist/convert-icons.md +52 -52
  14. package/dist/favicon.png +0 -0
  15. package/dist/favicon.svg +7 -8
  16. package/dist/generate-icons.js +48 -48
  17. package/dist/icons/codex-white.svg +3 -3
  18. package/dist/icons/codex.svg +3 -3
  19. package/dist/icons/cursor-white.svg +11 -11
  20. package/dist/icons/icon-128x128.png +0 -0
  21. package/dist/icons/icon-128x128.svg +9 -12
  22. package/dist/icons/icon-144x144.png +0 -0
  23. package/dist/icons/icon-144x144.svg +9 -12
  24. package/dist/icons/icon-152x152.png +0 -0
  25. package/dist/icons/icon-152x152.svg +9 -12
  26. package/dist/icons/icon-192x192.png +0 -0
  27. package/dist/icons/icon-192x192.svg +9 -12
  28. package/dist/icons/icon-384x384.png +0 -0
  29. package/dist/icons/icon-384x384.svg +9 -12
  30. package/dist/icons/icon-512x512.png +0 -0
  31. package/dist/icons/icon-512x512.svg +9 -12
  32. package/dist/icons/icon-72x72.png +0 -0
  33. package/dist/icons/icon-72x72.svg +9 -12
  34. package/dist/icons/icon-96x96.png +0 -0
  35. package/dist/icons/icon-96x96.svg +9 -12
  36. package/dist/icons/icon-template.svg +9 -12
  37. package/dist/icons/qwen-ai-icon.png +0 -0
  38. package/dist/index.html +59 -49
  39. package/dist/logo.png +0 -0
  40. package/dist/logo.svg +11 -16
  41. package/dist/manifest.json +60 -60
  42. package/dist/sw.js +124 -124
  43. package/dist-server/server/cli.js +100 -97
  44. package/dist-server/server/cli.js.map +1 -1
  45. package/dist-server/server/daemon/manager.js +33 -33
  46. package/dist-server/server/daemon-manager.js +62 -62
  47. package/dist-server/server/database/db.js +114 -22
  48. package/dist-server/server/database/db.js.map +1 -1
  49. package/dist-server/server/database/schema.js +122 -89
  50. package/dist-server/server/database/schema.js.map +1 -1
  51. package/dist-server/server/gemini-cli.js +6 -1
  52. package/dist-server/server/gemini-cli.js.map +1 -1
  53. package/dist-server/server/index.js +234 -64
  54. package/dist-server/server/index.js.map +1 -1
  55. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +29 -2
  56. package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
  57. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js +22 -2
  58. package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js.map +1 -1
  59. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +2 -2
  60. package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -1
  61. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +14 -2
  62. package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -1
  63. package/dist-server/server/modules/providers/list/qwen/qwen-auth.provider.js +132 -0
  64. package/dist-server/server/modules/providers/list/qwen/qwen-auth.provider.js.map +1 -0
  65. package/dist-server/server/modules/providers/list/qwen/qwen-mcp.provider.js +87 -0
  66. package/dist-server/server/modules/providers/list/qwen/qwen-mcp.provider.js.map +1 -0
  67. package/dist-server/server/modules/providers/list/qwen/qwen-sessions.provider.js +201 -0
  68. package/dist-server/server/modules/providers/list/qwen/qwen-sessions.provider.js.map +1 -0
  69. package/dist-server/server/modules/providers/list/qwen/qwen.provider.js +19 -0
  70. package/dist-server/server/modules/providers/list/qwen/qwen.provider.js.map +1 -0
  71. package/dist-server/server/modules/providers/provider.registry.js +2 -0
  72. package/dist-server/server/modules/providers/provider.registry.js.map +1 -1
  73. package/dist-server/server/modules/providers/provider.routes.js +310 -1
  74. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  75. package/dist-server/server/projects.js +197 -6
  76. package/dist-server/server/projects.js.map +1 -1
  77. package/dist-server/server/qwen-code-cli.js +350 -0
  78. package/dist-server/server/qwen-code-cli.js.map +1 -0
  79. package/dist-server/server/qwen-response-handler.js +70 -0
  80. package/dist-server/server/qwen-response-handler.js.map +1 -0
  81. package/dist-server/server/routes/commands.js +25 -25
  82. package/dist-server/server/routes/git.js +17 -17
  83. package/dist-server/server/routes/network.js +116 -0
  84. package/dist-server/server/routes/network.js.map +1 -0
  85. package/dist-server/server/routes/projects.js +43 -0
  86. package/dist-server/server/routes/projects.js.map +1 -1
  87. package/dist-server/server/routes/qwen.js +23 -0
  88. package/dist-server/server/routes/qwen.js.map +1 -0
  89. package/dist-server/server/routes/taskmaster.js +419 -419
  90. package/dist-server/server/routes/telegram.js +119 -0
  91. package/dist-server/server/routes/telegram.js.map +1 -0
  92. package/dist-server/server/services/external-access.js +228 -0
  93. package/dist-server/server/services/external-access.js.map +1 -0
  94. package/dist-server/server/services/install-jobs.js +394 -0
  95. package/dist-server/server/services/install-jobs.js.map +1 -0
  96. package/dist-server/server/services/notification-orchestrator.js +19 -5
  97. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  98. package/dist-server/server/services/provider-credentials.js +154 -0
  99. package/dist-server/server/services/provider-credentials.js.map +1 -0
  100. package/dist-server/server/services/provider-models.js +218 -0
  101. package/dist-server/server/services/provider-models.js.map +1 -0
  102. package/dist-server/server/services/telegram/bot.js +259 -0
  103. package/dist-server/server/services/telegram/bot.js.map +1 -0
  104. package/dist-server/server/services/telegram/translations.js +160 -0
  105. package/dist-server/server/services/telegram/translations.js.map +1 -0
  106. package/dist-server/server/utils/port-access.js +196 -0
  107. package/dist-server/server/utils/port-access.js.map +1 -0
  108. package/dist-server/shared/modelConstants.js +18 -0
  109. package/dist-server/shared/modelConstants.js.map +1 -1
  110. package/package.json +177 -168
  111. package/scripts/fix-node-pty.js +67 -67
  112. package/server/claude-sdk.js +834 -834
  113. package/server/cli.js +940 -937
  114. package/server/constants/config.js +4 -4
  115. package/server/cursor-cli.js +342 -342
  116. package/server/daemon/manager.js +564 -564
  117. package/server/daemon-manager.js +920 -920
  118. package/server/database/db.js +696 -593
  119. package/server/database/schema.js +138 -102
  120. package/server/gemini-cli.js +475 -469
  121. package/server/gemini-response-handler.js +79 -79
  122. package/server/index.js +2730 -2556
  123. package/server/load-env.js +34 -34
  124. package/server/middleware/auth.js +132 -132
  125. package/server/modules/providers/list/claude/claude-auth.provider.ts +145 -123
  126. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  127. package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
  128. package/server/modules/providers/list/claude/claude.provider.ts +15 -15
  129. package/server/modules/providers/list/codex/codex-auth.provider.ts +115 -100
  130. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  131. package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
  132. package/server/modules/providers/list/codex/codex.provider.ts +15 -15
  133. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
  134. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  135. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
  136. package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
  137. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +163 -151
  138. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
  139. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
  140. package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
  141. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -0
  142. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -0
  143. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +218 -0
  144. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -0
  145. package/server/modules/providers/provider.registry.ts +38 -36
  146. package/server/modules/providers/provider.routes.ts +583 -217
  147. package/server/modules/providers/services/mcp.service.ts +94 -94
  148. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  149. package/server/modules/providers/services/sessions.service.ts +45 -45
  150. package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
  151. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  152. package/server/modules/providers/tests/mcp.test.ts +293 -293
  153. package/server/openai-codex.js +426 -426
  154. package/server/projects.js +2993 -2792
  155. package/server/qwen-code-cli.js +392 -0
  156. package/server/qwen-response-handler.js +73 -0
  157. package/server/routes/agent.js +1245 -1245
  158. package/server/routes/auth.js +134 -134
  159. package/server/routes/codex.js +19 -19
  160. package/server/routes/commands.js +554 -554
  161. package/server/routes/cursor.js +52 -52
  162. package/server/routes/gemini.js +24 -24
  163. package/server/routes/git.js +1488 -1488
  164. package/server/routes/mcp-utils.js +31 -31
  165. package/server/routes/messages.js +61 -61
  166. package/server/routes/network.js +128 -0
  167. package/server/routes/plugins.js +307 -307
  168. package/server/routes/projects.js +675 -627
  169. package/server/routes/qwen.js +27 -0
  170. package/server/routes/settings.js +286 -286
  171. package/server/routes/taskmaster.js +1471 -1471
  172. package/server/routes/telegram.js +125 -0
  173. package/server/routes/user.js +123 -123
  174. package/server/services/external-access.js +240 -0
  175. package/server/services/install-jobs.js +410 -0
  176. package/server/services/notification-orchestrator.js +242 -227
  177. package/server/services/provider-credentials.js +151 -0
  178. package/server/services/provider-models.js +225 -0
  179. package/server/services/telegram/bot.js +280 -0
  180. package/server/services/telegram/translations.js +170 -0
  181. package/server/services/vapid-keys.js +35 -35
  182. package/server/sessionManager.js +225 -225
  183. package/server/shared/interfaces.ts +54 -54
  184. package/server/shared/types.ts +172 -172
  185. package/server/shared/utils.ts +193 -193
  186. package/server/tsconfig.json +36 -36
  187. package/server/utils/colors.js +21 -21
  188. package/server/utils/commandParser.js +303 -303
  189. package/server/utils/frontmatter.js +18 -18
  190. package/server/utils/gitConfig.js +34 -34
  191. package/server/utils/mcp-detector.js +147 -147
  192. package/server/utils/plugin-loader.js +457 -457
  193. package/server/utils/plugin-process-manager.js +184 -184
  194. package/server/utils/port-access.js +209 -0
  195. package/server/utils/runtime-paths.js +37 -37
  196. package/server/utils/taskmaster-websocket.js +128 -128
  197. package/server/utils/url-detection.js +71 -71
  198. package/server/vite-daemon.js +78 -78
  199. package/shared/modelConstants.js +117 -97
  200. package/shared/networkHosts.js +22 -22
  201. package/dist/assets/index-C2c9QNwK.css +0 -32
  202. package/dist/assets/index-DyXDZED-.js +0 -1277
@@ -1,7 +1,55 @@
1
1
  import express from 'express';
2
2
  import { providerAuthService } from '../../modules/providers/services/provider-auth.service.js';
3
3
  import { providerMcpService } from '../../modules/providers/services/mcp.service.js';
4
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5
+ // @ts-ignore — plain-JS service, typed via inference
6
+ import { applyProviderCredentialsToEnv, listProviderCredentialSummaries, setProviderCredentials, PROVIDER_ENV_VARS, } from '../../services/provider-credentials.js';
7
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
8
+ // @ts-ignore — plain-JS service
9
+ import { getProviderModels, clearProviderModelCache } from '../../services/provider-models.js';
10
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
+ // @ts-ignore — plain-JS service
12
+ import { createInstallJob, getInstallJob, cancelInstallJob, snapshotDonePayload, } from '../../services/install-jobs.js';
13
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
14
+ // @ts-ignore — plain-JS shared module
15
+ import { CLAUDE_MODELS, CODEX_MODELS, GEMINI_MODELS, QWEN_MODELS, CURSOR_MODELS, } from '../../../shared/modelConstants.js';
16
+ const STATIC_MODELS_BY_PROVIDER = {
17
+ claude: CLAUDE_MODELS.OPTIONS,
18
+ codex: CODEX_MODELS.OPTIONS,
19
+ cursor: CURSOR_MODELS.OPTIONS,
20
+ gemini: GEMINI_MODELS.OPTIONS,
21
+ qwen: QWEN_MODELS.OPTIONS,
22
+ };
4
23
  import { AppError, asyncHandler, createApiSuccessResponse } from '../../shared/utils.js';
24
+ import http from 'node:http';
25
+ /**
26
+ * npm-global install command per provider. Used by POST
27
+ * /api/providers/:p/install to run the install directly from Pixcode so
28
+ * users don't have to drop into a shell just to get a CLI on the host.
29
+ * Cursor uses its own install script, not npm.
30
+ */
31
+ /**
32
+ * npm package name per provider. The in-app installer drops these into
33
+ * ~/.pixcode/cli-bin/ as LOCAL deps (no -g, no sudo). A sibling string
34
+ * for display ("npm install -g …") is surfaced in the UI so users who
35
+ * prefer to install manually still see a recognizable command.
36
+ */
37
+ const PROVIDER_INSTALL_PACKAGES = {
38
+ claude: '@anthropic-ai/claude-code',
39
+ codex: '@openai/codex',
40
+ gemini: '@google/gemini-cli',
41
+ qwen: '@qwen-code/qwen-code',
42
+ // Cursor ships via a bash script hosted at cursor.com; safer to ask
43
+ // users to run it themselves than to pipe-to-bash from our server.
44
+ cursor: null,
45
+ };
46
+ const PROVIDER_INSTALL_COMMANDS = {
47
+ claude: 'npm install -g @anthropic-ai/claude-code',
48
+ codex: 'npm install -g @openai/codex',
49
+ gemini: 'npm install -g @google/gemini-cli',
50
+ qwen: 'npm install -g @qwen-code/qwen-code',
51
+ cursor: null,
52
+ };
5
53
  const router = express.Router();
6
54
  const readPathParam = (value, name) => {
7
55
  if (typeof value === 'string') {
@@ -99,7 +147,11 @@ const parseMcpUpsertPayload = (payload) => {
99
147
  };
100
148
  const parseProvider = (value) => {
101
149
  const normalized = normalizeProviderParam(value);
102
- if (normalized === 'claude' || normalized === 'codex' || normalized === 'cursor' || normalized === 'gemini') {
150
+ if (normalized === 'claude' ||
151
+ normalized === 'codex' ||
152
+ normalized === 'cursor' ||
153
+ normalized === 'gemini' ||
154
+ normalized === 'qwen') {
103
155
  return normalized;
104
156
  }
105
157
  throw new AppError(`Unsupported provider "${normalized}".`, {
@@ -141,6 +193,263 @@ router.delete('/:provider/mcp/servers/:name', asyncHandler(async (req, res) => {
141
193
  });
142
194
  res.json(createApiSuccessResponse(result));
143
195
  }));
196
+ /**
197
+ * GET /api/providers/credentials
198
+ * Summary for every provider (hasKey + baseUrl + updatedAt). Used by the
199
+ * Settings UI to pre-fill the "API Key" tab.
200
+ */
201
+ router.get('/credentials', asyncHandler(async (_req, res) => {
202
+ const summaries = await listProviderCredentialSummaries();
203
+ res.json(createApiSuccessResponse(summaries));
204
+ }));
205
+ /**
206
+ * POST /api/providers/:provider/auth/api-key
207
+ * Body: { apiKey: string, baseUrl?: string }. Stores the credentials in
208
+ * ~/.pixcode/provider-credentials.json and applies them to process.env
209
+ * so the next CLI spawn/SDK call picks them up. Empty apiKey clears.
210
+ */
211
+ router.post('/:provider/auth/api-key', asyncHandler(async (req, res) => {
212
+ const provider = parseProvider(req.params.provider);
213
+ if (!(provider in PROVIDER_ENV_VARS)) {
214
+ throw new AppError(`Provider "${provider}" does not accept API-key auth.`, {
215
+ code: 'PROVIDER_NO_API_KEY',
216
+ statusCode: 400,
217
+ });
218
+ }
219
+ const body = (req.body ?? {});
220
+ const apiKey = typeof body.apiKey === 'string' ? body.apiKey : '';
221
+ const baseUrl = typeof body.baseUrl === 'string' ? body.baseUrl : '';
222
+ await setProviderCredentials(provider, { apiKey, baseUrl });
223
+ await applyProviderCredentialsToEnv(provider);
224
+ res.json(createApiSuccessResponse({ provider, stored: Boolean(apiKey.trim()) }));
225
+ }));
226
+ /**
227
+ * POST /api/providers/:provider/oauth-paste
228
+ * Body: { callbackUrl: string }.
229
+ *
230
+ * When the CLI starts an OAuth flow it spins up a local HTTP server on
231
+ * 127.0.0.1:<PORT> and expects the OAuth provider to redirect the user's
232
+ * browser to `http://127.0.0.1:<PORT>/callback?code=...`. On remote VPS
233
+ * setups that redirect hits the user's laptop localhost (which has nothing
234
+ * listening), not the server running the CLI. This endpoint is the escape
235
+ * hatch: the user copies the dead callback URL from their browser and
236
+ * posts it here; we parse out the port + code and forward the original
237
+ * GET to the VPS-side 127.0.0.1:PORT so the CLI's local handler completes
238
+ * the token exchange.
239
+ */
240
+ router.post('/:provider/oauth-paste', asyncHandler(async (req, res) => {
241
+ parseProvider(req.params.provider); // validate id but we don't use it further
242
+ const body = (req.body ?? {});
243
+ const raw = typeof body.callbackUrl === 'string' ? body.callbackUrl.trim() : '';
244
+ if (!raw) {
245
+ throw new AppError('callbackUrl is required.', {
246
+ code: 'OAUTH_PASTE_URL_REQUIRED',
247
+ statusCode: 400,
248
+ });
249
+ }
250
+ let parsed;
251
+ try {
252
+ parsed = new URL(raw);
253
+ }
254
+ catch {
255
+ throw new AppError('callbackUrl must be a valid URL.', {
256
+ code: 'OAUTH_PASTE_URL_INVALID',
257
+ statusCode: 400,
258
+ });
259
+ }
260
+ // Accept localhost / 127.0.0.1 callbacks — reject anything else so we
261
+ // never proxy arbitrary outbound requests on behalf of a user.
262
+ const host = parsed.hostname;
263
+ if (host !== '127.0.0.1' && host !== 'localhost' && host !== '::1') {
264
+ throw new AppError('Only local CLI callback URLs are accepted.', {
265
+ code: 'OAUTH_PASTE_URL_NOT_LOCAL',
266
+ statusCode: 400,
267
+ });
268
+ }
269
+ const port = Number(parsed.port);
270
+ if (!port || port < 1 || port > 65535) {
271
+ throw new AppError('Callback URL must include the CLI callback port.', {
272
+ code: 'OAUTH_PASTE_PORT_INVALID',
273
+ statusCode: 400,
274
+ });
275
+ }
276
+ const pathAndQuery = parsed.pathname + parsed.search;
277
+ await new Promise((resolve, reject) => {
278
+ const forwardReq = http.request({
279
+ host: '127.0.0.1',
280
+ port,
281
+ method: 'GET',
282
+ path: pathAndQuery,
283
+ timeout: 10000,
284
+ }, (forwardRes) => {
285
+ forwardRes.resume(); // drain
286
+ forwardRes.on('end', () => resolve());
287
+ });
288
+ forwardReq.on('timeout', () => {
289
+ forwardReq.destroy(new Error('CLI callback server did not respond within 10s'));
290
+ });
291
+ forwardReq.on('error', (err) => reject(err));
292
+ forwardReq.end();
293
+ });
294
+ res.json(createApiSuccessResponse({ forwarded: true, port }));
295
+ }));
296
+ /**
297
+ * GET /api/providers/:provider/models?refresh=1
298
+ * Merged model catalog: hardcoded defaults + live API discovery when an
299
+ * API key is configured. Ships a stable baseline so dropdowns never sit
300
+ * empty, then overlays whatever the upstream API reports so users get
301
+ * new models without a Pixcode release. 6-hour cache; pass `refresh=1`
302
+ * to force an upstream hit.
303
+ */
304
+ router.get('/:provider/models', asyncHandler(async (req, res) => {
305
+ const provider = parseProvider(req.params.provider);
306
+ const forceRefresh = String(req.query.refresh || '').toLowerCase() === '1';
307
+ const result = await getProviderModels(provider, {
308
+ forceRefresh,
309
+ staticList: STATIC_MODELS_BY_PROVIDER[provider] ?? [],
310
+ });
311
+ res.json(createApiSuccessResponse(result));
312
+ }));
313
+ router.delete('/:provider/models/cache', asyncHandler(async (req, res) => {
314
+ const provider = parseProvider(req.params.provider);
315
+ await clearProviderModelCache(provider);
316
+ res.json(createApiSuccessResponse({ cleared: true, provider }));
317
+ }));
318
+ /**
319
+ * POST /api/providers/:provider/install
320
+ * Kicks off the install in the background and immediately returns
321
+ * `{ jobId }`. The actual log stream is fetched separately via
322
+ * GET /install/:jobId/stream (EventSource). This split solves the
323
+ * "Client disconnected before install finished" class of errors,
324
+ * where a single long-lived POST SSE would get torn down by dev
325
+ * proxies, service-worker reloads, or Vite HMR and short-circuit
326
+ * an in-flight install. The child now outlives the request.
327
+ */
328
+ router.post('/:provider/install', asyncHandler(async (req, res) => {
329
+ const parsed = parseProvider(req.params.provider);
330
+ const packageName = PROVIDER_INSTALL_PACKAGES[parsed];
331
+ const installCmd = PROVIDER_INSTALL_COMMANDS[parsed];
332
+ if (!packageName || !installCmd) {
333
+ throw new AppError(`${parsed} cannot be installed automatically — please follow the documented install steps.`, { code: 'PROVIDER_NOT_AUTO_INSTALLABLE', statusCode: 400 });
334
+ }
335
+ const job = createInstallJob({ provider: parsed, installCmd, packageName });
336
+ res.json(createApiSuccessResponse({
337
+ jobId: job.id,
338
+ provider: parsed,
339
+ installCmd,
340
+ startedAt: job.startedAt,
341
+ }));
342
+ }));
343
+ /**
344
+ * GET /api/providers/:provider/install/:jobId/stream
345
+ * SSE endpoint (EventSource-friendly). Replays every buffered log line
346
+ * to the new subscriber, then forwards live stdout/stderr until the
347
+ * child exits. Clients can reconnect freely — reconnects replay from
348
+ * the start, so you never miss output, even if the browser dropped
349
+ * the previous connection while npm was mid-download.
350
+ *
351
+ * EventSource can't set custom headers, so this endpoint also accepts
352
+ * ?token=... as a fallback auth channel (same pattern the search
353
+ * endpoint uses).
354
+ */
355
+ router.get('/:provider/install/:jobId/stream', asyncHandler(async (req, res) => {
356
+ const parsed = parseProvider(req.params.provider);
357
+ const jobId = readPathParam(req.params.jobId, 'jobId');
358
+ const job = getInstallJob(jobId);
359
+ if (!job || job.provider !== parsed) {
360
+ throw new AppError('Install job not found or already expired.', {
361
+ code: 'INSTALL_JOB_NOT_FOUND',
362
+ statusCode: 404,
363
+ });
364
+ }
365
+ res.setHeader('Content-Type', 'text/event-stream');
366
+ res.setHeader('Cache-Control', 'no-cache, no-transform');
367
+ res.setHeader('Connection', 'keep-alive');
368
+ res.setHeader('X-Accel-Buffering', 'no');
369
+ if (typeof res.flushHeaders === 'function')
370
+ res.flushHeaders();
371
+ try {
372
+ res.socket?.setNoDelay?.(true);
373
+ }
374
+ catch { /* noop */ }
375
+ let closed = false;
376
+ const write = (event, payload) => {
377
+ if (closed)
378
+ return;
379
+ try {
380
+ res.write(`event: ${event}\n`);
381
+ res.write(`data: ${JSON.stringify(payload)}\n\n`);
382
+ }
383
+ catch { /* socket gone */ }
384
+ };
385
+ // Immediate primer + heartbeat, same as before — keeps intermediary
386
+ // proxies from treating the connection as idle.
387
+ try {
388
+ res.write(': start\n\n');
389
+ }
390
+ catch { /* noop */ }
391
+ const heartbeat = setInterval(() => {
392
+ if (closed)
393
+ return;
394
+ try {
395
+ res.write(': ping\n\n');
396
+ }
397
+ catch { /* noop */ }
398
+ }, 5000);
399
+ // Replay the buffered transcript first so late subscribers see
400
+ // every line npm has already produced.
401
+ for (const entry of job.logs) {
402
+ write('log', { stream: entry.stream, chunk: entry.chunk });
403
+ }
404
+ const onLog = (entry) => {
405
+ write('log', { stream: entry.stream, chunk: entry.chunk });
406
+ };
407
+ const onDone = (payload) => {
408
+ write('done', payload);
409
+ cleanup();
410
+ try {
411
+ res.end();
412
+ }
413
+ catch { /* noop */ }
414
+ };
415
+ const cleanup = () => {
416
+ if (closed)
417
+ return;
418
+ closed = true;
419
+ clearInterval(heartbeat);
420
+ job.emitter.off('log', onLog);
421
+ job.emitter.off('done', onDone);
422
+ };
423
+ if (job.status !== 'running') {
424
+ // Job already finished — replay the terminal done frame and exit.
425
+ write('done', snapshotDonePayload(job));
426
+ cleanup();
427
+ try {
428
+ res.end();
429
+ }
430
+ catch { /* noop */ }
431
+ return;
432
+ }
433
+ job.emitter.on('log', onLog);
434
+ job.emitter.once('done', onDone);
435
+ req.on('close', () => {
436
+ // Client walked away. DO NOT cancel the install — detaching is fine.
437
+ cleanup();
438
+ });
439
+ }));
440
+ router.delete('/:provider/install/:jobId', asyncHandler(async (req, res) => {
441
+ const parsed = parseProvider(req.params.provider);
442
+ const jobId = readPathParam(req.params.jobId, 'jobId');
443
+ const job = getInstallJob(jobId);
444
+ if (!job || job.provider !== parsed) {
445
+ throw new AppError('Install job not found.', {
446
+ code: 'INSTALL_JOB_NOT_FOUND',
447
+ statusCode: 404,
448
+ });
449
+ }
450
+ const cancelled = cancelInstallJob(jobId);
451
+ res.json(createApiSuccessResponse({ cancelled }));
452
+ }));
144
453
  router.post('/mcp/servers/global', asyncHandler(async (req, res) => {
145
454
  const payload = parseMcpUpsertPayload(req.body);
146
455
  if (payload.scope === 'local') {
@@ -1 +1 @@
1
- {"version":3,"file":"provider.routes.js","sourceRoot":"","sources":["../../../../server/modules/providers/provider.routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.routes.js","sourceRoot":"","sources":["../../../../server/modules/providers/provider.routes.ts"],"names":[],"mappings":"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"}
@@ -240,6 +240,47 @@ function areStringArraysEqual(first, second) {
240
240
  }
241
241
  return first.every((value, index) => value === second[index]);
242
242
  }
243
+ // Qwen Code mirrors Gemini CLI's on-disk layout (~/.qwen/tmp/<projectDir>/
244
+ // with a `.project_root` file + `chats/*.json`), because Qwen is a fork of
245
+ // Gemini CLI. The listing / session / message helpers below duplicate the
246
+ // Gemini ones rather than sharing a parametric implementation, keeping
247
+ // provider-specific logic discoverable in one place.
248
+ async function listQwenCliProjectEntries() {
249
+ const qwenTmpDir = path.join(os.homedir(), '.qwen', 'tmp');
250
+ try {
251
+ await fs.access(qwenTmpDir);
252
+ }
253
+ catch {
254
+ return [];
255
+ }
256
+ let projectDirs;
257
+ try {
258
+ projectDirs = await fs.readdir(qwenTmpDir);
259
+ }
260
+ catch {
261
+ return [];
262
+ }
263
+ const entries = [];
264
+ for (const projectDir of projectDirs) {
265
+ const projectRootFile = path.join(qwenTmpDir, projectDir, '.project_root');
266
+ let projectRoot;
267
+ try {
268
+ projectRoot = (await fs.readFile(projectRootFile, 'utf8')).trim();
269
+ }
270
+ catch {
271
+ continue;
272
+ }
273
+ const normalizedProjectRoot = normalizeComparablePath(projectRoot);
274
+ if (!normalizedProjectRoot)
275
+ continue;
276
+ entries.push({
277
+ projectDir,
278
+ projectRoot: path.resolve(projectRoot),
279
+ normalizedProjectRoot,
280
+ });
281
+ }
282
+ return entries;
283
+ }
243
284
  async function listGeminiCliProjectEntries() {
244
285
  const geminiTmpDir = path.join(os.homedir(), '.gemini', 'tmp');
245
286
  try {
@@ -294,7 +335,7 @@ function addDiscoveredProject(discoveredProjectsByPath, projectPath, provider) {
294
335
  }
295
336
  discoveredProjectsByPath.get(normalizedProjectPath).providers.add(provider);
296
337
  }
297
- async function discoverProjectsFromHistory(codexSessionsIndexRef = null, geminiCliProjectsRef = null) {
338
+ async function discoverProjectsFromHistory(codexSessionsIndexRef = null, geminiCliProjectsRef = null, qwenCliProjectsRef = null) {
298
339
  const discoveredProjectsByPath = new Map();
299
340
  if (codexSessionsIndexRef && !codexSessionsIndexRef.sessionsByProject) {
300
341
  codexSessionsIndexRef.sessionsByProject = await buildCodexSessionsIndex();
@@ -314,6 +355,13 @@ async function discoverProjectsFromHistory(codexSessionsIndexRef = null, geminiC
314
355
  for (const entry of geminiCliEntries) {
315
356
  addDiscoveredProject(discoveredProjectsByPath, entry.projectRoot, 'gemini');
316
357
  }
358
+ if (qwenCliProjectsRef && !qwenCliProjectsRef.entries) {
359
+ qwenCliProjectsRef.entries = await listQwenCliProjectEntries();
360
+ }
361
+ const qwenCliEntries = qwenCliProjectsRef?.entries || await listQwenCliProjectEntries();
362
+ for (const entry of qwenCliEntries) {
363
+ addDiscoveredProject(discoveredProjectsByPath, entry.projectRoot, 'qwen');
364
+ }
317
365
  for (const session of sessionManager.sessions.values()) {
318
366
  if (session?.projectPath) {
319
367
  addDiscoveredProject(discoveredProjectsByPath, session.projectPath, 'gemini');
@@ -355,8 +403,8 @@ function mergeDiscoveredProjectsIntoConfig(config, discoveredProjects) {
355
403
  }
356
404
  return { config: nextConfig, changed };
357
405
  }
358
- async function syncAutoDiscoveredProjects(config, codexSessionsIndexRef = null, geminiCliProjectsRef = null) {
359
- const discoveredProjects = await discoverProjectsFromHistory(codexSessionsIndexRef, geminiCliProjectsRef);
406
+ async function syncAutoDiscoveredProjects(config, codexSessionsIndexRef = null, geminiCliProjectsRef = null, qwenCliProjectsRef = null) {
407
+ const discoveredProjects = await discoverProjectsFromHistory(codexSessionsIndexRef, geminiCliProjectsRef, qwenCliProjectsRef);
360
408
  if (discoveredProjects.length === 0) {
361
409
  return config;
362
410
  }
@@ -518,11 +566,12 @@ async function getProjects(progressCallback = null) {
518
566
  const existingProjects = new Set();
519
567
  const codexSessionsIndexRef = { sessionsByProject: null };
520
568
  const geminiCliProjectsRef = { entries: null };
569
+ const qwenCliProjectsRef = { entries: null };
521
570
  let totalProjects = 0;
522
571
  let processedProjects = 0;
523
572
  let directories = [];
524
573
  try {
525
- config = await syncAutoDiscoveredProjects(config, codexSessionsIndexRef, geminiCliProjectsRef);
574
+ config = await syncAutoDiscoveredProjects(config, codexSessionsIndexRef, geminiCliProjectsRef, qwenCliProjectsRef);
526
575
  }
527
576
  catch (error) {
528
577
  console.warn('Failed to sync auto-discovered projects:', error.message);
@@ -576,6 +625,7 @@ async function getProjects(progressCallback = null) {
576
625
  detectedAt: projectConfig.detectedAt || null,
577
626
  sessions: [],
578
627
  geminiSessions: [],
628
+ qwenSessions: [],
579
629
  sessionMeta: {
580
630
  hasMore: false,
581
631
  total: 0
@@ -629,6 +679,21 @@ async function getProjects(progressCallback = null) {
629
679
  project.geminiSessions = [];
630
680
  }
631
681
  applyCustomSessionNames(project.geminiSessions, 'gemini');
682
+ try {
683
+ // Qwen Code sessions — sourced purely from ~/.qwen/tmp since the adapter
684
+ // uses its own session IDs. Mirrors the Gemini branch above; sessionManager
685
+ // handles both Gemini and Qwen live sessions so UI continuations land in
686
+ // the right place regardless of provider.
687
+ const qwenCliSessions = await getQwenCliSessions(actualProjectDir, {
688
+ qwenCliProjectsRef,
689
+ });
690
+ project.qwenSessions = qwenCliSessions;
691
+ }
692
+ catch (e) {
693
+ console.warn(`Could not load Qwen Code sessions for project ${entry.name}:`, e.message);
694
+ project.qwenSessions = [];
695
+ }
696
+ applyCustomSessionNames(project.qwenSessions, 'qwen');
632
697
  try {
633
698
  const taskMasterResult = await detectTaskMasterFolder(actualProjectDir);
634
699
  project.taskmaster = {
@@ -687,6 +752,7 @@ async function getProjects(progressCallback = null) {
687
752
  detectedAt: projectConfig.detectedAt || null,
688
753
  sessions: [],
689
754
  geminiSessions: [],
755
+ qwenSessions: [],
690
756
  sessionMeta: {
691
757
  hasMore: false,
692
758
  total: 0
@@ -710,6 +776,15 @@ async function getProjects(progressCallback = null) {
710
776
  console.warn(`Could not load Codex sessions for tracked project ${projectName}:`, e.message);
711
777
  }
712
778
  applyCustomSessionNames(project.codexSessions, 'codex');
779
+ try {
780
+ project.qwenSessions = await getQwenCliSessions(actualProjectDir, {
781
+ qwenCliProjectsRef,
782
+ });
783
+ }
784
+ catch (e) {
785
+ console.warn(`Could not load Qwen Code sessions for tracked project ${projectName}:`, e.message);
786
+ }
787
+ applyCustomSessionNames(project.qwenSessions, 'qwen');
713
788
  try {
714
789
  const uiSessions = sessionManager.getProjectSessions(actualProjectDir) || [];
715
790
  const cliSessions = await getGeminiCliSessions(actualProjectDir, {
@@ -1866,6 +1941,7 @@ async function searchConversations(query, limit = 50, onProjectResult = null, si
1866
1941
  let config = await loadProjectConfig();
1867
1942
  const codexSessionsIndexRef = { sessionsByProject: null };
1868
1943
  const geminiCliProjectsRef = { entries: null };
1944
+ const qwenCliProjectsRef = { entries: null };
1869
1945
  const results = [];
1870
1946
  let totalMatches = 0;
1871
1947
  const words = safeQuery.toLowerCase().split(/\s+/).filter(w => w.length > 0);
@@ -1944,7 +2020,7 @@ async function searchConversations(query, limit = 50, onProjectResult = null, si
1944
2020
  return { snippet, highlights: merged };
1945
2021
  };
1946
2022
  try {
1947
- config = await syncAutoDiscoveredProjects(config, codexSessionsIndexRef, geminiCliProjectsRef);
2023
+ config = await syncAutoDiscoveredProjects(config, codexSessionsIndexRef, geminiCliProjectsRef, qwenCliProjectsRef);
1948
2024
  }
1949
2025
  catch (error) {
1950
2026
  console.warn('Failed to sync auto-discovered projects for search:', error.message);
@@ -2377,6 +2453,121 @@ async function searchGeminiSessionsForProject(projectPath, projectResult, allWor
2377
2453
  }
2378
2454
  }
2379
2455
  }
2456
+ // Qwen Code session listing — same chats/*.json payload Gemini emits since
2457
+ // Qwen is a Gemini CLI fork. Kept as its own function (instead of a shared
2458
+ // parametric helper) so future Qwen-specific protocol drift has one
2459
+ // obvious place to land.
2460
+ async function getQwenCliSessions(projectPath, options = {}) {
2461
+ const { qwenCliProjectsRef = null } = options;
2462
+ const normalizedProjectPath = normalizeComparablePath(projectPath);
2463
+ if (!normalizedProjectPath)
2464
+ return [];
2465
+ const sessions = [];
2466
+ const qwenTmpDir = path.join(os.homedir(), '.qwen', 'tmp');
2467
+ if (qwenCliProjectsRef && !qwenCliProjectsRef.entries) {
2468
+ qwenCliProjectsRef.entries = await listQwenCliProjectEntries();
2469
+ }
2470
+ const qwenCliEntries = qwenCliProjectsRef?.entries || await listQwenCliProjectEntries();
2471
+ for (const entry of qwenCliEntries) {
2472
+ if (entry.normalizedProjectRoot !== normalizedProjectPath)
2473
+ continue;
2474
+ const projectDir = entry.projectDir;
2475
+ const chatsDir = path.join(qwenTmpDir, projectDir, 'chats');
2476
+ let chatFiles;
2477
+ try {
2478
+ chatFiles = await fs.readdir(chatsDir);
2479
+ }
2480
+ catch {
2481
+ continue;
2482
+ }
2483
+ for (const chatFile of chatFiles) {
2484
+ if (!chatFile.endsWith('.json'))
2485
+ continue;
2486
+ try {
2487
+ const filePath = path.join(chatsDir, chatFile);
2488
+ const data = await fs.readFile(filePath, 'utf8');
2489
+ const session = JSON.parse(data);
2490
+ if (!session.messages || !Array.isArray(session.messages))
2491
+ continue;
2492
+ const sessionId = session.sessionId || chatFile.replace('.json', '');
2493
+ const firstUserMsg = session.messages.find(m => m.type === 'user');
2494
+ let summary = 'Qwen Code Session';
2495
+ if (firstUserMsg) {
2496
+ const text = Array.isArray(firstUserMsg.content)
2497
+ ? firstUserMsg.content.filter(p => p.text).map(p => p.text).join(' ')
2498
+ : (typeof firstUserMsg.content === 'string' ? firstUserMsg.content : '');
2499
+ if (text) {
2500
+ summary = text.length > 50 ? text.substring(0, 50) + '...' : text;
2501
+ }
2502
+ }
2503
+ sessions.push({
2504
+ id: sessionId,
2505
+ summary,
2506
+ messageCount: session.messages.length,
2507
+ lastActivity: session.lastUpdated || session.startTime || null,
2508
+ provider: 'qwen'
2509
+ });
2510
+ }
2511
+ catch {
2512
+ continue;
2513
+ }
2514
+ }
2515
+ }
2516
+ return sessions.sort((a, b) => new Date(b.lastActivity || 0) - new Date(a.lastActivity || 0));
2517
+ }
2518
+ async function getQwenCliSessionMessages(sessionId) {
2519
+ const qwenTmpDir = path.join(os.homedir(), '.qwen', 'tmp');
2520
+ let projectDirs;
2521
+ try {
2522
+ projectDirs = await fs.readdir(qwenTmpDir);
2523
+ }
2524
+ catch {
2525
+ return [];
2526
+ }
2527
+ for (const projectDir of projectDirs) {
2528
+ const chatsDir = path.join(qwenTmpDir, projectDir, 'chats');
2529
+ let chatFiles;
2530
+ try {
2531
+ chatFiles = await fs.readdir(chatsDir);
2532
+ }
2533
+ catch {
2534
+ continue;
2535
+ }
2536
+ for (const chatFile of chatFiles) {
2537
+ if (!chatFile.endsWith('.json'))
2538
+ continue;
2539
+ try {
2540
+ const filePath = path.join(chatsDir, chatFile);
2541
+ const data = await fs.readFile(filePath, 'utf8');
2542
+ const session = JSON.parse(data);
2543
+ const fileSessionId = session.sessionId || chatFile.replace('.json', '');
2544
+ if (fileSessionId !== sessionId)
2545
+ continue;
2546
+ return (session.messages || []).map(msg => {
2547
+ const role = msg.type === 'user' ? 'user'
2548
+ : (msg.type === 'qwen' || msg.type === 'assistant') ? 'assistant'
2549
+ : msg.type;
2550
+ let content = '';
2551
+ if (typeof msg.content === 'string') {
2552
+ content = msg.content;
2553
+ }
2554
+ else if (Array.isArray(msg.content)) {
2555
+ content = msg.content.filter(p => p.text).map(p => p.text).join('\n');
2556
+ }
2557
+ return {
2558
+ type: 'message',
2559
+ message: { role, content },
2560
+ timestamp: msg.timestamp || null
2561
+ };
2562
+ });
2563
+ }
2564
+ catch {
2565
+ continue;
2566
+ }
2567
+ }
2568
+ }
2569
+ return [];
2570
+ }
2380
2571
  async function getGeminiCliSessions(projectPath, options = {}) {
2381
2572
  const { geminiCliProjectsRef = null } = options;
2382
2573
  const normalizedProjectPath = normalizeComparablePath(projectPath);
@@ -2488,5 +2679,5 @@ async function getGeminiCliSessionMessages(sessionId) {
2488
2679
  }
2489
2680
  return [];
2490
2681
  }
2491
- export { getProjects, getSessions, getSessionMessages, parseJsonlSessions, renameProject, deleteSession, isProjectEmpty, deleteProject, addProjectManually, loadProjectConfig, saveProjectConfig, extractProjectDirectory, clearProjectDirectoryCache, getCodexSessions, getCodexSessionMessages, deleteCodexSession, getGeminiCliSessions, getGeminiCliSessionMessages, searchConversations };
2682
+ export { getProjects, getSessions, getSessionMessages, parseJsonlSessions, renameProject, deleteSession, isProjectEmpty, deleteProject, addProjectManually, loadProjectConfig, saveProjectConfig, extractProjectDirectory, clearProjectDirectoryCache, getCodexSessions, getCodexSessionMessages, deleteCodexSession, getGeminiCliSessions, getGeminiCliSessionMessages, getQwenCliSessions, getQwenCliSessionMessages, searchConversations };
2492
2683
  //# sourceMappingURL=projects.js.map