openfox 2.0.110 → 2.0.111

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 (79) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -0
  3. package/dist/CHANGELOG.md +19 -0
  4. package/dist/{ask-CJMU6EW7.js → ask-ZYPCJKZD.js} +3 -2
  5. package/dist/{chat-handler-UZ7WTT6D.js → chat-handler-BYXZIIV3.js} +23 -22
  6. package/dist/{chunk-VJWWJEBX.js → chunk-3UILDGOO.js} +9 -9
  7. package/dist/{chunk-QRASX3HC.js → chunk-4DTV5JVI.js} +7 -7
  8. package/dist/{chunk-ZJW3KOII.js → chunk-A32COLEZ.js} +293 -98
  9. package/dist/{chunk-GNFDD6LN.js → chunk-BOSKQI62.js} +3 -3
  10. package/dist/{chunk-D6ODGTSZ.js → chunk-C372UH7N.js} +2 -1
  11. package/dist/{chunk-4ZXRERIW.js → chunk-C5NQF2K4.js} +46 -4
  12. package/dist/{chunk-3HS72YIE.js → chunk-ERYUSG5C.js} +2 -2
  13. package/dist/{chunk-PU3IPUSW.js → chunk-FFPCVN5M.js} +45 -8
  14. package/dist/{chunk-KDQJOI2I.js → chunk-FSYRANYR.js} +2 -2
  15. package/dist/chunk-GZOK3FAA.js +7 -0
  16. package/dist/chunk-IJ53Y77N.js +142 -0
  17. package/dist/{chunk-WCQOHRUX.js → chunk-JDT63SSP.js} +2 -2
  18. package/dist/{chunk-VT2X3DMC.js → chunk-JNHKKUGJ.js} +2 -2
  19. package/dist/{chunk-JAX5OEMM.js → chunk-JURM3RPZ.js} +21 -4
  20. package/dist/chunk-LCLH6ZUL.js +43 -0
  21. package/dist/{chunk-6EV7X5MP.js → chunk-N4RTAGFY.js} +2 -2
  22. package/dist/{chunk-LXYNP7LL.js → chunk-NB2D6I64.js} +221 -5
  23. package/dist/{chunk-VKWVPQJ5.js → chunk-OAN4BXEW.js} +3 -1
  24. package/dist/{chunk-4R7G5JB6.js → chunk-P45RJGOT.js} +1 -1
  25. package/dist/{chunk-E5HZKNTY.js → chunk-PCC4DBPF.js} +2 -2
  26. package/dist/{chunk-ACJNRPTO.js → chunk-QGXLZZBS.js} +29 -21
  27. package/dist/{chunk-UCYPPLVR.js → chunk-RAKPI4OE.js} +81 -70
  28. package/dist/{chunk-MM46DJJL.js → chunk-RISQXU32.js} +2 -2
  29. package/dist/{chunk-CQKRZ4WV.js → chunk-RKMP74BB.js} +4 -4
  30. package/dist/chunk-RSB4AR2A.js +108 -0
  31. package/dist/{chunk-VXKPZUCT.js → chunk-RT2A2RRL.js} +4 -2
  32. package/dist/{chunk-HK75Q3EA.js → chunk-SDGNV45R.js} +10 -10
  33. package/dist/{chunk-C5JJM72V.js → chunk-SVJFMZ2Q.js} +49 -5
  34. package/dist/{chunk-B5MH4HQ6.js → chunk-SYJMUIRC.js} +7 -3
  35. package/dist/{chunk-4HIFB7F5.js → chunk-XCK5IBO4.js} +37 -26
  36. package/dist/{chunk-5HMKLHTT.js → chunk-XWNCKIPO.js} +2 -2
  37. package/dist/{chunk-NORNB6IJ.js → chunk-Z56SEG4Z.js} +6 -6
  38. package/dist/cli/dev.js +1 -1
  39. package/dist/cli/index.js +1 -1
  40. package/dist/{client-LPNFUOPV.js → client-QNQTX5EA.js} +4 -4
  41. package/dist/{compactor-OSDLCGRC.js → compactor-X2KZ3XFU.js} +10 -9
  42. package/dist/{config-HX7FDKGJ.js → config-TW5FHQEM.js} +2 -2
  43. package/dist/{dynamic-context-WVA7HTEP.js → dynamic-context-ZRQO2FJN.js} +7 -7
  44. package/dist/{events-26J7BUSY.js → events-Y6XXQYFG.js} +7 -6
  45. package/dist/{folding-ZD4AMFNR.js → folding-Z4GNWRC3.js} +9 -6
  46. package/dist/{http-client-MQARNFY3.js → http-client-2GDKHZIG.js} +3 -3
  47. package/dist/{manager-RJH7EYIG.js → manager-HCMDFEQH.js} +4 -4
  48. package/dist/{model-overrides-BXMFIT47.js → model-overrides-O3ZYKFP7.js} +3 -3
  49. package/dist/oauth-provider-52YILVUJ.js +15 -0
  50. package/dist/oauth-store-XCFXV2VM.js +32 -0
  51. package/dist/{orchestrator-BW27C4K4.js → orchestrator-P5EUMC7E.js} +22 -21
  52. package/dist/package.json +11 -9
  53. package/dist/{path-security-AAZMH33K.js → path-security-525YLND3.js} +11 -9
  54. package/dist/{platform-EZJABX5J.js → platform-MEQUWG6U.js} +3 -3
  55. package/dist/{processor-FTCPHWBM.js → processor-UN4H4V7F.js} +22 -21
  56. package/dist/{protocol-_Gphic7p.d.ts → protocol-D6MISQyz.d.ts} +8 -3
  57. package/dist/{protocol-SPIJPOEN.js → protocol-FTHAR2YL.js} +4 -3
  58. package/dist/{provider-JS5P3HQ2.js → provider-3R4X62LW.js} +7 -7
  59. package/dist/{provider-manager-MWAIOX2A.js → provider-manager-W5N4XRE5.js} +5 -5
  60. package/dist/{registry-JJB5GXOM.js → registry-74KPZ5NV.js} +3 -3
  61. package/dist/{serve-XDZB4EJN.js → serve-V7WQKJ52.js} +32 -29
  62. package/dist/server/index.d.ts +15 -1
  63. package/dist/server/index.js +31 -28
  64. package/dist/server-7MOOJR2N.js +48 -0
  65. package/dist/{session-overrides-T47KXDDS.js → session-overrides-XH6I3COP.js} +5 -5
  66. package/dist/{sessions-YTWCOHI3.js → sessions-D772YTWL.js} +8 -4
  67. package/dist/{settings-2RZBMX5Y.js → settings-KO6DSJLD.js} +2 -2
  68. package/dist/shared/index.d.ts +1 -1
  69. package/dist/shared/index.js +1 -1
  70. package/dist/{tools-KPIYFL5A.js → tools-HTUTYMKI.js} +20 -19
  71. package/dist/{update-75QZJYKD.js → update-MWPQNSEZ.js} +2 -2
  72. package/dist/{update-server-4I6LXE5K.js → update-server-LOOXIXDW.js} +2 -2
  73. package/dist/web/assets/{index-BmjVoqQT.js → index-Dukvfqm-.js} +83 -83
  74. package/dist/web/assets/{index-CyWbbpRP.css → index-nS1p0g8O.css} +1 -1
  75. package/dist/web/index.html +2 -2
  76. package/dist/web/sw.js +1 -1
  77. package/package.json +11 -9
  78. package/dist/chunk-64374FPB.js +0 -7
  79. package/dist/server-R6DDJNF3.js +0 -47
@@ -5,13 +5,13 @@ import {
5
5
  deleteItemFromDir,
6
6
  loadItemsFromDir,
7
7
  pathExists
8
- } from "./chunk-VT2X3DMC.js";
8
+ } from "./chunk-JNHKKUGJ.js";
9
9
  import {
10
10
  SETTINGS_KEYS,
11
11
  deleteSetting,
12
12
  getSetting,
13
13
  setSetting
14
- } from "./chunk-VXKPZUCT.js";
14
+ } from "./chunk-RT2A2RRL.js";
15
15
 
16
16
  // src/server/context/instructions.ts
17
17
  import { readFile, access } from "fs/promises";
@@ -440,4 +440,4 @@ export {
440
440
  deleteSkill,
441
441
  deleteProjectSkill
442
442
  };
443
- //# sourceMappingURL=chunk-GNFDD6LN.js.map
443
+ //# sourceMappingURL=chunk-BOSKQI62.js.map
@@ -108,6 +108,7 @@ var mcpServerSchema = z.object({
108
108
  env: z.record(z.string(), z.string()).optional(),
109
109
  url: z.string().optional(),
110
110
  headers: z.record(z.string(), z.string()).optional(),
111
+ oauth: z.boolean().optional(),
111
112
  disabledTools: z.array(z.string()).optional(),
112
113
  cachedTools: z.array(cachedToolSchema).optional(),
113
114
  timeout: z.number().positive().optional(),
@@ -370,4 +371,4 @@ export {
370
371
  removeProvider,
371
372
  activateProvider
372
373
  };
373
- //# sourceMappingURL=chunk-D6ODGTSZ.js.map
374
+ //# sourceMappingURL=chunk-C372UH7N.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveDefaultAgentId
3
- } from "./chunk-VT2X3DMC.js";
3
+ } from "./chunk-JNHKKUGJ.js";
4
4
  import {
5
5
  getDatabase
6
6
  } from "./chunk-LCQ5AN6Y.js";
@@ -245,7 +245,14 @@ function listSessions() {
245
245
  return rows.map(mapSessionSummaryRow);
246
246
  }
247
247
  function listSessionsByProject(projectId, limit = 20, offset = 0) {
248
+ return listSessionsPaged(projectId, limit, offset);
249
+ }
250
+ function listSessionsLimited(limit = 20, offset = 0) {
251
+ return listSessionsPaged(null, limit, offset);
252
+ }
253
+ function listSessionsPaged(projectId, limit, offset) {
248
254
  const db = getDatabase();
255
+ const where = projectId ? "WHERE s.project_id = ?" : "";
249
256
  const rows = db.prepare(
250
257
  `
251
258
  SELECT
@@ -264,15 +271,48 @@ function listSessionsByProject(projectId, limit = 20, offset = 0) {
264
271
  s.provider_model,
265
272
  s.message_count
266
273
  FROM sessions s
267
- WHERE s.project_id = ?
274
+ ${where}
268
275
  ORDER BY s.updated_at DESC
269
276
  LIMIT ? OFFSET ?
270
277
  `
271
- ).all(projectId, limit + 1, offset);
278
+ ).all(...projectId ? [projectId] : [], limit + 1, offset);
272
279
  const hasMore = rows.length > limit;
273
280
  const sessions = rows.slice(0, limit).map(mapSessionSummaryRow);
274
281
  return { sessions, hasMore };
275
282
  }
283
+ function listHomeSessions(sessionsPerProject = 5) {
284
+ const db = getDatabase();
285
+ const rows = db.prepare(
286
+ `
287
+ SELECT
288
+ s.id,
289
+ s.project_id,
290
+ s.workdir,
291
+ s.workspace,
292
+ s.branch,
293
+ s.mode,
294
+ s.workflow_phase,
295
+ s.is_running,
296
+ s.created_at,
297
+ s.updated_at,
298
+ s.title,
299
+ s.provider_id,
300
+ s.provider_model,
301
+ s.message_count
302
+ FROM sessions s
303
+ ORDER BY s.updated_at DESC
304
+ `
305
+ ).all();
306
+ const seen = /* @__PURE__ */ new Map();
307
+ const result = [];
308
+ for (const row of rows) {
309
+ const count = seen.get(row.project_id) ?? 0;
310
+ if (count >= sessionsPerProject) continue;
311
+ seen.set(row.project_id, count + 1);
312
+ result.push(mapSessionSummaryRow(row));
313
+ }
314
+ return result;
315
+ }
276
316
  function updateSessionWorkdir(id, workdir, workspace, branch) {
277
317
  const db = getDatabase();
278
318
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -360,6 +400,8 @@ export {
360
400
  getSessionMessageCount,
361
401
  listSessions,
362
402
  listSessionsByProject,
403
+ listSessionsLimited,
404
+ listHomeSessions,
363
405
  updateSessionWorkdir,
364
406
  updateSessionBranch,
365
407
  deleteSession,
@@ -368,4 +410,4 @@ export {
368
410
  getActiveWorkflowExecution,
369
411
  clearWorkflowExecution
370
412
  };
371
- //# sourceMappingURL=chunk-4ZXRERIW.js.map
413
+ //# sourceMappingURL=chunk-C5NQF2K4.js.map
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  LLMError,
19
19
  OpenAIHttpClient
20
- } from "./chunk-E5HZKNTY.js";
20
+ } from "./chunk-PCC4DBPF.js";
21
21
  import {
22
22
  logger
23
23
  } from "./chunk-K44MW7JJ.js";
@@ -310,4 +310,4 @@ function createLLMClient(config, initialBackend = "unknown") {
310
310
  export {
311
311
  createLLMClient
312
312
  };
313
- //# sourceMappingURL=chunk-3HS72YIE.js.map
313
+ //# sourceMappingURL=chunk-ERYUSG5C.js.map
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  getEventStore
3
- } from "./chunk-LXYNP7LL.js";
3
+ } from "./chunk-NB2D6I64.js";
4
4
  import {
5
5
  createChatPathConfirmationMessage
6
- } from "./chunk-B5MH4HQ6.js";
6
+ } from "./chunk-SYJMUIRC.js";
7
+ import {
8
+ getPlatformShell
9
+ } from "./chunk-N4RTAGFY.js";
7
10
 
8
11
  // src/server/tools/path-security.ts
9
12
  import { realpath } from "fs/promises";
@@ -120,11 +123,19 @@ function looksLikeRegex(str) {
120
123
  return /[*?+[\]\\]/.test(str);
121
124
  }
122
125
  var isWindows = () => process.platform === "win32";
126
+ function usesPosixPaths() {
127
+ if (process.platform !== "win32") return true;
128
+ return /^(?:ba|z|)sh(?:\.exe)?$/i.test(win32.basename(getPlatformShell().command));
129
+ }
123
130
  function isWindowsAbsolutePath(str) {
124
131
  return /^[A-Za-z]:[\\/]/.test(str);
125
132
  }
126
133
  function normalizeExtracted(path) {
127
- return isWindowsAbsolutePath(path) ? win32.normalize(path) : posix.normalize(path);
134
+ if (isWindowsAbsolutePath(path)) return win32.normalize(path);
135
+ if (isWindows() && /^\/[A-Za-z]\//.test(path)) {
136
+ return win32.normalize(`${path[1].toUpperCase()}:\\${path.slice(3)}`);
137
+ }
138
+ return posix.normalize(path);
128
139
  }
129
140
  function isPlaceholderToken(str) {
130
141
  return str.includes("__URL__") || str.includes("__FILEURL__") || str.includes("__SED__") || str.includes("__COMMIT_MSG__");
@@ -135,6 +146,7 @@ function extractAbsolutePathsFromCommand(command) {
135
146
  }
136
147
  const paths = [];
137
148
  const home = homedir();
149
+ const posixShell = usesPosixPaths();
138
150
  let sanitized = command.replace(/https?:\/\/[^\s'"]+/g, " __URL__ ").replace(/ftp:\/\/[^\s'"]+/g, " __URL__ ");
139
151
  sanitized = sanitized.replace(/(?<!\w)s\/[^/]*\/[^/]*\/[gip]*/g, " __SED__ ");
140
152
  sanitized = sanitized.replace(/(?<!\w)s\|[^|]*\|[^|]*\|[gip]*/g, " __SED__ ");
@@ -175,7 +187,7 @@ function extractAbsolutePathsFromCommand(command) {
175
187
  if (!isSafePath(resolved)) {
176
188
  paths.push(resolved);
177
189
  }
178
- } else if (!isWindows() && content.startsWith("/")) {
190
+ } else if (posixShell && content.startsWith("/")) {
179
191
  const resolved = normalizeExtracted(content);
180
192
  if (!isSafePath(resolved)) {
181
193
  paths.push(resolved);
@@ -199,7 +211,8 @@ function extractAbsolutePathsFromCommand(command) {
199
211
  paths.push(resolved);
200
212
  }
201
213
  }
202
- } else {
214
+ }
215
+ if (posixShell) {
203
216
  const absolutePattern = /(?:^|[\s=(])(\/[^\s"'|&;<>`()]+)/g;
204
217
  while ((match = absolutePattern.exec(sanitized)) !== null) {
205
218
  const candidate = match[1];
@@ -238,9 +251,12 @@ function extractSensitivePathsFromCommand(command) {
238
251
  }
239
252
  return [...new Set(paths)];
240
253
  }
254
+ var WINDOWS_DEVICE_NAMES = /* @__PURE__ */ new Set(["nul", "con", "prn", "aux"]);
241
255
  function isSafePath(path) {
242
256
  const normalized = posix.normalize(path);
243
- return SAFE_PATHS.has(normalized);
257
+ if (SAFE_PATHS.has(normalized)) return true;
258
+ if (!isWindows()) return false;
259
+ return WINDOWS_DEVICE_NAMES.has(win32.basename(path.replace(/^\\\\[.?]\\/, "")).toLowerCase());
244
260
  }
245
261
  async function checkPathsAccess(paths, workdir, sessionId) {
246
262
  if (paths.length === 0) {
@@ -274,9 +290,30 @@ var DANGEROUS_PATTERNS = [
274
290
  /dd\s+if=/,
275
291
  /:\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;/
276
292
  ];
293
+ var WINDOWS_DANGEROUS_PATTERNS = [
294
+ /\b(?:rd|rmdir)\s+(?:\/[a-z]\s+)*\/s\b/i,
295
+ // rd /s /q <dir>
296
+ /\bdel\s+(?:\/[a-z]\s+)*\/s\b/i,
297
+ // del /f /s /q <pattern>
298
+ // The operand is a bare drive ("D:", "D:\"), never a file path — that is what
299
+ // keeps "npm run format -- C:\src\x.ts" out of the dangerous bucket.
300
+ /\bformat\s+(?:\/\S+\s+)*[a-z]:\\?(?=\s|$)/i,
301
+ // format D: / format /q D: / format /fs:NTFS D:
302
+ /\bRemove-Item\b(?=[^|;]*-Recurse\b)(?=[^|;]*-Force\b)/i,
303
+ // PowerShell recursive force delete (flag order-independent)
304
+ /\brunas\b/i,
305
+ // sudo equivalent
306
+ /\bStart-Process\b[^|;]*-Verb\s+RunAs\b/i,
307
+ // sudo equivalent (PowerShell)
308
+ /\bicacls\b[^|;]*\/grant\b[^|;]*Everyone/i,
309
+ // chmod 777 equivalent
310
+ /\bdiskpart\b/i
311
+ // raw disk write, dd/mkfs equivalent
312
+ ];
277
313
  function extractDangerousPatterns(command) {
314
+ const patterns = isWindows() ? [...DANGEROUS_PATTERNS, ...WINDOWS_DANGEROUS_PATTERNS] : DANGEROUS_PATTERNS;
278
315
  const dangerous = [];
279
- for (const pattern of DANGEROUS_PATTERNS) {
316
+ for (const pattern of patterns) {
280
317
  if (pattern.test(command)) {
281
318
  dangerous.push(pattern.source);
282
319
  }
@@ -498,4 +535,4 @@ export {
498
535
  getConfirmationSessionId,
499
536
  getPendingConfirmationsBySession
500
537
  };
501
- //# sourceMappingURL=chunk-PU3IPUSW.js.map
538
+ //# sourceMappingURL=chunk-FFPCVN5M.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createLLMClient
3
- } from "./chunk-3HS72YIE.js";
3
+ } from "./chunk-ERYUSG5C.js";
4
4
  import {
5
5
  getModelProfile
6
6
  } from "./chunk-V4IE7HJY.js";
@@ -804,4 +804,4 @@ export {
804
804
  parseDefaultModelSelection,
805
805
  createProviderManager
806
806
  };
807
- //# sourceMappingURL=chunk-KDQJOI2I.js.map
807
+ //# sourceMappingURL=chunk-FSYRANYR.js.map
@@ -0,0 +1,7 @@
1
+ // src/constants.ts
2
+ var VERSION = "2.0.111";
3
+
4
+ export {
5
+ VERSION
6
+ };
7
+ //# sourceMappingURL=chunk-GZOK3FAA.js.map
@@ -0,0 +1,142 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-K44MW7JJ.js";
4
+ import {
5
+ getGlobalConfigDir
6
+ } from "./chunk-CQGTEGKL.js";
7
+
8
+ // src/server/mcp/oauth-store.ts
9
+ import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
10
+ import { dirname, join } from "path";
11
+ var storeMode = "production";
12
+ var storePathOverride;
13
+ function setMcpOAuthStoreMode(mode) {
14
+ storeMode = mode;
15
+ }
16
+ function setMcpOAuthStorePath(path) {
17
+ storePathOverride = path;
18
+ }
19
+ function getMcpOAuthStorePath() {
20
+ return storePathOverride ?? join(getGlobalConfigDir(storeMode), "mcp-auth.json");
21
+ }
22
+ async function readStore() {
23
+ const path = getMcpOAuthStorePath();
24
+ let raw;
25
+ try {
26
+ raw = await readFile(path, "utf-8");
27
+ } catch {
28
+ return { version: 1, servers: {} };
29
+ }
30
+ try {
31
+ const parsed = JSON.parse(raw);
32
+ const servers = parsed.servers;
33
+ if (!servers || typeof servers !== "object") throw new Error("no servers object");
34
+ const kept = {};
35
+ for (const [name, entry] of Object.entries(servers)) {
36
+ if (entry && typeof entry === "object" && typeof entry.serverUrl === "string") {
37
+ kept[name] = entry;
38
+ } else {
39
+ logger.warn("Dropping an unreadable MCP OAuth entry, this server will have to authorize again", {
40
+ path,
41
+ server: name
42
+ });
43
+ }
44
+ }
45
+ return { version: 1, servers: kept };
46
+ } catch {
47
+ logger.error("The MCP OAuth store is unreadable, stored authorizations will be ignored", { path });
48
+ return { version: 1, servers: {} };
49
+ }
50
+ }
51
+ async function writeStore(store) {
52
+ const path = getMcpOAuthStorePath();
53
+ await mkdir(dirname(path), { recursive: true });
54
+ const tmpPath = `${path}.tmp`;
55
+ await writeFile(tmpPath, JSON.stringify(store, null, 2), { mode: 384 });
56
+ try {
57
+ await chmod(tmpPath, 384);
58
+ } catch {
59
+ logger.warn("Could not restrict permissions on the MCP OAuth store", { path });
60
+ }
61
+ await rename(tmpPath, path);
62
+ }
63
+ var writeQueue = Promise.resolve();
64
+ function serialize(work) {
65
+ const result = writeQueue.then(work, work);
66
+ writeQueue = result.catch(() => void 0);
67
+ return result;
68
+ }
69
+ async function mutateEntry(name, serverUrl, mutate) {
70
+ await serialize(async () => {
71
+ const store = await readStore();
72
+ const current = store.servers[name];
73
+ const base = current && current.serverUrl === serverUrl ? current : { serverUrl };
74
+ store.servers[name] = mutate(base);
75
+ await writeStore(store);
76
+ });
77
+ }
78
+ function withoutAuthorizationState(entry) {
79
+ const next = { serverUrl: entry.serverUrl };
80
+ if (entry.clientInformation) next.clientInformation = entry.clientInformation;
81
+ if (entry.tokens) next.tokens = entry.tokens;
82
+ return next;
83
+ }
84
+ async function readMcpOAuthEntry(name, serverUrl) {
85
+ const store = await readStore();
86
+ const entry = store.servers[name];
87
+ if (!entry || entry.serverUrl !== serverUrl) return void 0;
88
+ return entry;
89
+ }
90
+ async function saveMcpOAuthClientInformation(name, serverUrl, clientInformation) {
91
+ await mutateEntry(name, serverUrl, (entry) => ({ ...entry, clientInformation }));
92
+ }
93
+ async function saveMcpOAuthTokens(name, serverUrl, tokens) {
94
+ await mutateEntry(name, serverUrl, (entry) => ({ ...withoutAuthorizationState(entry), tokens }));
95
+ }
96
+ async function saveMcpOAuthCodeVerifier(name, serverUrl, codeVerifier) {
97
+ await mutateEntry(name, serverUrl, (entry) => ({ ...entry, codeVerifier }));
98
+ }
99
+ async function saveMcpOAuthState(name, serverUrl, state) {
100
+ await mutateEntry(name, serverUrl, (entry) => ({ ...entry, state }));
101
+ }
102
+ async function clearMcpOAuthTokens(name, serverUrl) {
103
+ await mutateEntry(name, serverUrl, (entry) => {
104
+ const next = withoutAuthorizationState(entry);
105
+ delete next.tokens;
106
+ return next;
107
+ });
108
+ }
109
+ async function clearMcpOAuthAuthorizationState(name, serverUrl) {
110
+ await mutateEntry(name, serverUrl, withoutAuthorizationState);
111
+ }
112
+ async function clearMcpOAuthEntry(name) {
113
+ await serialize(async () => {
114
+ const store = await readStore();
115
+ if (!(name in store.servers)) return;
116
+ delete store.servers[name];
117
+ await writeStore(store);
118
+ });
119
+ }
120
+ async function findMcpOAuthEntryByState(state) {
121
+ const store = await readStore();
122
+ for (const [name, entry] of Object.entries(store.servers)) {
123
+ if (entry.state && entry.state === state) return { name, entry };
124
+ }
125
+ return null;
126
+ }
127
+
128
+ export {
129
+ setMcpOAuthStoreMode,
130
+ setMcpOAuthStorePath,
131
+ getMcpOAuthStorePath,
132
+ readMcpOAuthEntry,
133
+ saveMcpOAuthClientInformation,
134
+ saveMcpOAuthTokens,
135
+ saveMcpOAuthCodeVerifier,
136
+ saveMcpOAuthState,
137
+ clearMcpOAuthTokens,
138
+ clearMcpOAuthAuthorizationState,
139
+ clearMcpOAuthEntry,
140
+ findMcpOAuthEntryByState
141
+ };
142
+ //# sourceMappingURL=chunk-IJ53Y77N.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  updateSessionMcpDisabledServers
3
- } from "./chunk-4ZXRERIW.js";
3
+ } from "./chunk-C5NQF2K4.js";
4
4
  import {
5
5
  getDatabase
6
6
  } from "./chunk-LCQ5AN6Y.js";
@@ -62,4 +62,4 @@ export {
62
62
  clearSessionOverrides,
63
63
  getAllSessionOverrides
64
64
  };
65
- //# sourceMappingURL=chunk-WCQOHRUX.js.map
65
+ //# sourceMappingURL=chunk-JDT63SSP.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SETTINGS_KEYS,
3
3
  getSetting
4
- } from "./chunk-VXKPZUCT.js";
4
+ } from "./chunk-RT2A2RRL.js";
5
5
  import {
6
6
  logger
7
7
  } from "./chunk-K44MW7JJ.js";
@@ -455,4 +455,4 @@ export {
455
455
  getOverrideAgentIds,
456
456
  resolveDefaultAgentId
457
457
  };
458
- //# sourceMappingURL=chunk-VT2X3DMC.js.map
458
+ //# sourceMappingURL=chunk-JNHKKUGJ.js.map
@@ -1,3 +1,7 @@
1
+ import {
2
+ normalizeAskOptions
3
+ } from "./chunk-LCLH6ZUL.js";
4
+
1
5
  // src/server/utils/async.ts
2
6
  function createDeferred() {
3
7
  let resolve;
@@ -56,8 +60,21 @@ var askUserTool = {
56
60
  },
57
61
  options: {
58
62
  type: "array",
59
- items: { type: "string" },
60
- description: "Options for choice-type questions"
63
+ description: "Options for choice-type questions. Each entry may be a plain string or an object {value, label, description?} (or legacy {label, description?}). The server normalizes everything to {value, label, description?}.",
64
+ items: {
65
+ oneOf: [
66
+ { type: "string" },
67
+ {
68
+ type: "object",
69
+ properties: {
70
+ value: { type: "string" },
71
+ label: { type: "string" },
72
+ description: { type: "string" }
73
+ },
74
+ required: ["label"]
75
+ }
76
+ ]
77
+ }
61
78
  }
62
79
  },
63
80
  required: ["question"]
@@ -67,7 +84,7 @@ var askUserTool = {
67
84
  async execute(args, context) {
68
85
  const question = args["question"];
69
86
  const type = args["type"] ?? "text";
70
- const options = args["options"];
87
+ const options = normalizeAskOptions(args["options"]);
71
88
  const callId = context.toolCallId ?? crypto.randomUUID();
72
89
  const deferred = createDeferred();
73
90
  void deferred.promise.catch(() => {
@@ -156,4 +173,4 @@ export {
156
173
  awaitAnswer,
157
174
  getPendingQuestionsForSession
158
175
  };
159
- //# sourceMappingURL=chunk-JAX5OEMM.js.map
176
+ //# sourceMappingURL=chunk-JURM3RPZ.js.map
@@ -0,0 +1,43 @@
1
+ // src/shared/ask-options.ts
2
+ function normalizeAskOptions(raw) {
3
+ if (raw == null) return void 0;
4
+ if (typeof raw === "string") {
5
+ const parts = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
6
+ return parts.length > 0 ? parts.map((label) => ({ value: label, label })) : void 0;
7
+ }
8
+ if (!Array.isArray(raw)) return void 0;
9
+ const out = [];
10
+ for (const item of raw) {
11
+ if (typeof item === "string") {
12
+ const trimmed = item.trim();
13
+ if (trimmed.length > 0) {
14
+ out.push({ value: trimmed, label: trimmed });
15
+ }
16
+ continue;
17
+ }
18
+ if (item != null && typeof item === "object") {
19
+ const obj = item;
20
+ const labelRaw = obj["label"];
21
+ const valueRaw = obj["value"];
22
+ if (typeof labelRaw === "string" && labelRaw.trim().length > 0) {
23
+ const label = labelRaw.trim();
24
+ const value = typeof valueRaw === "string" && valueRaw.length > 0 ? valueRaw : label;
25
+ const descRaw = obj["description"];
26
+ const opt = {
27
+ value,
28
+ label
29
+ };
30
+ if (typeof descRaw === "string" && descRaw.length > 0) {
31
+ opt.description = descRaw;
32
+ }
33
+ out.push(opt);
34
+ }
35
+ }
36
+ }
37
+ return out.length > 0 ? out : void 0;
38
+ }
39
+
40
+ export {
41
+ normalizeAskOptions
42
+ };
43
+ //# sourceMappingURL=chunk-LCLH6ZUL.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SETTINGS_KEYS,
3
3
  getSetting
4
- } from "./chunk-VXKPZUCT.js";
4
+ } from "./chunk-RT2A2RRL.js";
5
5
 
6
6
  // src/server/utils/platform.ts
7
7
  import os from "os";
@@ -63,4 +63,4 @@ export {
63
63
  isWindowsPath,
64
64
  isAbsolutePath
65
65
  };
66
- //# sourceMappingURL=chunk-6EV7X5MP.js.map
66
+ //# sourceMappingURL=chunk-N4RTAGFY.js.map