openfox 2.0.58 → 2.0.60

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 (40) hide show
  1. package/dist/agent-defaults/explorer.agent.md +4 -0
  2. package/dist/{branch.api-5DMEAIBI.js → branch.api-LAN42BA5.js} +3 -2
  3. package/dist/{chat-handler-W5D5LKKU.js → chat-handler-MBR6ZQTX.js} +7 -7
  4. package/dist/{chunk-LAWUUAN7.js → chunk-3JRYK5UG.js} +323 -80
  5. package/dist/{chunk-YMEZFRY2.js → chunk-43UFGATL.js} +5 -5
  6. package/dist/{chunk-BIWVYBIE.js → chunk-BGTEIA2S.js} +4 -3
  7. package/dist/{chunk-UDZNMYWN.js → chunk-DEWNWF2P.js} +519 -280
  8. package/dist/{chunk-CFLGVCYT.js → chunk-DOJKA4XO.js} +20 -9
  9. package/dist/{chunk-55VITQP3.js → chunk-MTBQQ5DN.js} +9 -9
  10. package/dist/{chunk-XR2XC7WM.js → chunk-NY6IGGKZ.js} +3 -3
  11. package/dist/{chunk-ADOXTORQ.js → chunk-PK2RMVMB.js} +2 -2
  12. package/dist/{chunk-CDRQJDSJ.js → chunk-WNSAJCWT.js} +3 -2
  13. package/dist/cli/dev.js +2 -2
  14. package/dist/cli/index.js +2 -2
  15. package/dist/{config-C2YDEF3N.js → config-GMQUPNBY.js} +2 -2
  16. package/dist/{manager-CZOVNTSN.js → manager-344C5JLZ.js} +3 -3
  17. package/dist/{orchestrator-Q47D6JXG.js → orchestrator-PIZJ42J2.js} +7 -7
  18. package/dist/package.json +4 -2
  19. package/dist/{permissions-QLHZUEGW.js → permissions-CGEK3DGZ.js} +21 -17
  20. package/dist/{processor-2YJ33KUH.js → processor-PKKTNKWY.js} +7 -7
  21. package/dist/{project-creator-7RBHP6K6.js → project-creator-IDW7RACH.js} +4 -4
  22. package/dist/{protocol-PSKVUhdN.d.ts → protocol-J7khRG62.d.ts} +2 -0
  23. package/dist/{provider-SNXYPSPH.js → provider-LBYBC5AG.js} +3 -3
  24. package/dist/{pwa-M6QZ52ZO.js → pwa-T6JRAYJB.js} +11 -10
  25. package/dist/{serve-LOPGRMFP.js → serve-GKS55Y2C.js} +9 -9
  26. package/dist/server/index.d.ts +1 -1
  27. package/dist/server/index.js +8 -8
  28. package/dist/{server-XUDZRBD3.js → server-LMH7ZH5X.js} +8 -8
  29. package/dist/{service-YYJ5Y7CN.js → service-6DL3MJZD.js} +7 -5
  30. package/dist/{settings-X43DCM55.js → settings-2TQA7VTP.js} +2 -2
  31. package/dist/shared/index.d.ts +2 -2
  32. package/dist/skill-defaults/{browser.skill.md → browser/SKILL.md} +5 -3
  33. package/dist/{store-NS2RMRA7.js → store-FXTCHBI4.js} +2 -2
  34. package/dist/{tools-YJLXW3QS.js → tools-WGAZKL56.js} +6 -6
  35. package/dist/web/assets/index-C0YKw2cD.js +302 -0
  36. package/dist/web/assets/{index-DjfRXOO7.css → index-D4bVx84a.css} +1 -1
  37. package/dist/web/index.html +2 -2
  38. package/dist/web/sw.js +1 -1
  39. package/package.json +4 -2
  40. package/dist/web/assets/index-Dqqp_j-f.js +0 -302
@@ -21,12 +21,13 @@ import {
21
21
  tokenFromPassword,
22
22
  verifyPassword,
23
23
  workflowExists
24
- } from "./chunk-CFLGVCYT.js";
24
+ } from "./chunk-DOJKA4XO.js";
25
25
  import {
26
26
  agentExists,
27
27
  createToolRegistry,
28
28
  deleteAgent,
29
29
  deleteItemFromDir,
30
+ deleteOwnedSkill,
30
31
  deleteProjectAgent,
31
32
  deleteProjectSkill,
32
33
  deleteSkill,
@@ -43,6 +44,7 @@ import {
43
44
  loadAllAgents,
44
45
  loadAllAgentsDefault,
45
46
  loadAllSkills,
47
+ loadAllSkillsWithDiagnostics,
46
48
  loadDefaultAgents,
47
49
  loadDefaultSkills,
48
50
  loadItemsFromDir,
@@ -57,15 +59,18 @@ import {
57
59
  saveSkill,
58
60
  saveSkillToProject,
59
61
  setMcpConfigMode,
62
+ setMcpConfigPath,
60
63
  setMcpManagerForTools,
61
64
  setMcpTools,
62
65
  setNotifyMcpServersChanged,
63
- skillExists
64
- } from "./chunk-LAWUUAN7.js";
66
+ setSkillEnabled,
67
+ skillExists,
68
+ updateOwnedSkill
69
+ } from "./chunk-3JRYK5UG.js";
65
70
  import {
66
71
  getPathSeparator,
67
72
  isAbsolutePath
68
- } from "./chunk-BIWVYBIE.js";
73
+ } from "./chunk-BGTEIA2S.js";
69
74
  import {
70
75
  createMcpTools
71
76
  } from "./chunk-NWO6GRYE.js";
@@ -75,6 +80,11 @@ import {
75
80
  import {
76
81
  EventEmitter
77
82
  } from "./chunk-EU3WWTFH.js";
83
+ import {
84
+ deleteSetting,
85
+ getSetting,
86
+ setSetting
87
+ } from "./chunk-WNSAJCWT.js";
78
88
  import {
79
89
  getProject
80
90
  } from "./chunk-YQ3SOPBI.js";
@@ -149,8 +159,8 @@ import express from "express";
149
159
  import cors from "cors";
150
160
  import { createServer as createHttpServer } from "http";
151
161
  import { fileURLToPath as fileURLToPath5 } from "url";
152
- import { dirname as dirname5, resolve as resolve3, join as join5 } from "path";
153
- import { readFile } from "fs/promises";
162
+ import { dirname as dirname6, resolve as resolve4, join as join7 } from "path";
163
+ import { readFile as readFile2 } from "fs/promises";
154
164
  import { createServer as createViteServer } from "vite";
155
165
 
156
166
  // src/server/llm/mock.ts
@@ -1425,12 +1435,12 @@ var McpManager = class {
1425
1435
  this.onServersChanged = options?.onServersChanged;
1426
1436
  this.onToolsDiscovered = options?.onToolsDiscovered;
1427
1437
  }
1428
- async addServer(name, config4) {
1438
+ async addServer(name, config3) {
1429
1439
  if (this.servers.has(name)) {
1430
1440
  throw new Error(`MCP server '${name}' already exists`);
1431
1441
  }
1432
- const state = { name, config: config4, status: "disconnected", tools: [], estimatedTokens: 0 };
1433
- this.servers.set(name, { config: config4, client: void 0, transport: null, state });
1442
+ const state = { name, config: config3, status: "disconnected", tools: [], estimatedTokens: 0 };
1443
+ this.servers.set(name, { config: config3, client: void 0, transport: null, state });
1434
1444
  await this.connectServer(name);
1435
1445
  }
1436
1446
  removeServer(name) {
@@ -1677,10 +1687,10 @@ var LspServer = class {
1677
1687
  // Pending diagnostic waiters
1678
1688
  pendingDiagnostics = /* @__PURE__ */ new Map();
1679
1689
  commandPath;
1680
- constructor(config4, workdir, commandPath) {
1681
- this.config = config4;
1690
+ constructor(config3, workdir, commandPath) {
1691
+ this.config = config3;
1682
1692
  this.workdir = workdir;
1683
- this.commandPath = commandPath ?? config4.serverCommand;
1693
+ this.commandPath = commandPath ?? config3.serverCommand;
1684
1694
  }
1685
1695
  // ============================================================================
1686
1696
  // Lifecycle
@@ -1698,7 +1708,8 @@ var LspServer = class {
1698
1708
  ...process.env,
1699
1709
  HOME: process.env["HOME"],
1700
1710
  PATH: process.env["PATH"]
1701
- }
1711
+ },
1712
+ windowsHide: true
1702
1713
  });
1703
1714
  if (!this.process.stdin || !this.process.stdout) {
1704
1715
  throw new Error("Failed to get stdio streams from language server process");
@@ -1912,19 +1923,19 @@ var LspServer = class {
1912
1923
  */
1913
1924
  async getDiagnosticsWithWait(path, timeoutMs = DIAGNOSTIC_WAIT_MS) {
1914
1925
  if (this.openDocuments.has(path)) {
1915
- return new Promise((resolve4) => {
1926
+ return new Promise((resolve5) => {
1916
1927
  const existing = this.diagnostics.get(path);
1917
1928
  if (existing !== void 0) {
1918
1929
  setTimeout(() => {
1919
- resolve4(this.diagnostics.get(path) ?? []);
1930
+ resolve5(this.diagnostics.get(path) ?? []);
1920
1931
  }, 100);
1921
1932
  return;
1922
1933
  }
1923
1934
  const timeout = setTimeout(() => {
1924
1935
  this.pendingDiagnostics.delete(path);
1925
- resolve4(this.diagnostics.get(path) ?? []);
1936
+ resolve5(this.diagnostics.get(path) ?? []);
1926
1937
  }, timeoutMs);
1927
- this.pendingDiagnostics.set(path, { resolve: resolve4, timeout });
1938
+ this.pendingDiagnostics.set(path, { resolve: resolve5, timeout });
1928
1939
  });
1929
1940
  }
1930
1941
  return this.diagnostics.get(path) ?? [];
@@ -2236,8 +2247,8 @@ var LspManager = class {
2236
2247
  // ============================================================================
2237
2248
  // Server Management
2238
2249
  // ============================================================================
2239
- async getOrCreateServer(config4) {
2240
- const langId = config4.id;
2250
+ async getOrCreateServer(config3) {
2251
+ const langId = config3.id;
2241
2252
  const existing = this.servers.get(langId);
2242
2253
  if (existing?.isRunning()) {
2243
2254
  return existing;
@@ -2249,7 +2260,7 @@ var LspManager = class {
2249
2260
  if (pending) {
2250
2261
  return pending;
2251
2262
  }
2252
- const promise = this.startServer(config4);
2263
+ const promise = this.startServer(config3);
2253
2264
  this.serverPromises.set(langId, promise);
2254
2265
  try {
2255
2266
  const server = await promise;
@@ -2258,19 +2269,19 @@ var LspManager = class {
2258
2269
  this.serverPromises.delete(langId);
2259
2270
  }
2260
2271
  }
2261
- async startServer(config4) {
2262
- const langId = config4.id;
2263
- const commandPath = await which(config4.serverCommand, this.workdir);
2272
+ async startServer(config3) {
2273
+ const langId = config3.id;
2274
+ const commandPath = await which(config3.serverCommand, this.workdir);
2264
2275
  if (!commandPath) {
2265
2276
  logger.warn("LSP server not installed, skipping", {
2266
2277
  language: langId,
2267
- command: config4.serverCommand,
2278
+ command: config3.serverCommand,
2268
2279
  sessionId: this.sessionId
2269
2280
  });
2270
2281
  this.unavailableServers.add(langId);
2271
2282
  return null;
2272
2283
  }
2273
- const server = new LspServer(config4, this.workdir, commandPath);
2284
+ const server = new LspServer(config3, this.workdir, commandPath);
2274
2285
  try {
2275
2286
  await server.start();
2276
2287
  this.servers.set(langId, server);
@@ -2290,11 +2301,11 @@ var LspManager = class {
2290
2301
  }
2291
2302
  }
2292
2303
  async getServerForFile(path) {
2293
- const config4 = detectLanguage(path);
2294
- if (!config4) {
2304
+ const config3 = detectLanguage(path);
2305
+ if (!config3) {
2295
2306
  return null;
2296
2307
  }
2297
- return this.getOrCreateServer(config4);
2308
+ return this.getOrCreateServer(config3);
2298
2309
  }
2299
2310
  // ============================================================================
2300
2311
  // Public Interface
@@ -2325,11 +2336,11 @@ var LspManager = class {
2325
2336
  * Get current diagnostics for a file without triggering a change.
2326
2337
  */
2327
2338
  getDiagnostics(path) {
2328
- const config4 = detectLanguage(path);
2329
- if (!config4) {
2339
+ const config3 = detectLanguage(path);
2340
+ if (!config3) {
2330
2341
  return [];
2331
2342
  }
2332
- const server = this.servers.get(config4.id);
2343
+ const server = this.servers.get(config3.id);
2333
2344
  if (!server?.isRunning()) {
2334
2345
  return [];
2335
2346
  }
@@ -2340,11 +2351,11 @@ var LspManager = class {
2340
2351
  * Returns true if we have or can start a server for this file type.
2341
2352
  */
2342
2353
  isAvailableFor(path) {
2343
- const config4 = detectLanguage(path);
2344
- if (!config4) {
2354
+ const config3 = detectLanguage(path);
2355
+ if (!config3) {
2345
2356
  return false;
2346
2357
  }
2347
- if (this.unavailableServers.has(config4.id)) {
2358
+ if (this.unavailableServers.has(config3.id)) {
2348
2359
  return false;
2349
2360
  }
2350
2361
  return true;
@@ -2355,13 +2366,13 @@ var LspManager = class {
2355
2366
  * to avoid spamming the user on every edit.
2356
2367
  */
2357
2368
  getInstallHint(path) {
2358
- const config4 = detectLanguage(path);
2359
- if (!config4?.installHint) {
2369
+ const config3 = detectLanguage(path);
2370
+ if (!config3?.installHint) {
2360
2371
  return null;
2361
2372
  }
2362
- if (this.unavailableServers.has(config4.id) && !this.dismissedHints.has(config4.id)) {
2363
- this.dismissedHints.add(config4.id);
2364
- return config4.installHint;
2373
+ if (this.unavailableServers.has(config3.id) && !this.dismissedHints.has(config3.id)) {
2374
+ this.dismissedHints.add(config3.id);
2375
+ return config3.installHint;
2365
2376
  }
2366
2377
  return null;
2367
2378
  }
@@ -3241,9 +3252,77 @@ var SessionManager = class {
3241
3252
  }
3242
3253
  };
3243
3254
 
3255
+ // src/server/routes/skills.ts
3256
+ import { Router as Router2 } from "express";
3257
+ import multer from "multer";
3258
+ import { access as access2, mkdir as mkdir2, realpath, stat } from "fs/promises";
3259
+ import { constants as constants2 } from "fs";
3260
+ import { homedir } from "os";
3261
+ import { isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "path";
3262
+
3263
+ // src/server/skills/installer.ts
3264
+ import { randomUUID } from "crypto";
3265
+ import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
3266
+ import { dirname as dirname3, isAbsolute, join as join2 } from "path";
3267
+ import matter from "gray-matter";
3268
+ var SkillInstallError = class extends Error {
3269
+ constructor(message, status) {
3270
+ super(message);
3271
+ this.status = status;
3272
+ }
3273
+ };
3274
+ function validateRelativePath(path) {
3275
+ if (!path || isAbsolute(path) || path.includes("\\") || path.includes("\0") || path.split("/").some((part) => !part || part === "." || part === "..")) {
3276
+ throw new SkillInstallError(`Invalid package path: ${path}`, 400);
3277
+ }
3278
+ }
3279
+ function validatePackageName(name) {
3280
+ if (!name || name.includes("/") || name.includes("\\") || name === "." || name === ".." || name.includes("\0")) {
3281
+ throw new SkillInstallError("Invalid package name", 400);
3282
+ }
3283
+ }
3284
+ async function installSkillPackage(libraryDir, packageName, files) {
3285
+ validatePackageName(packageName);
3286
+ if (!files.length || files.length > 1e3) throw new SkillInstallError("Package must contain 1-1000 files", 400);
3287
+ if (!files.some((file) => file.path === "SKILL.md")) throw new SkillInstallError("Package must contain SKILL.md", 400);
3288
+ let totalBytes = 0;
3289
+ const paths = /* @__PURE__ */ new Set();
3290
+ for (const file of files) {
3291
+ validateRelativePath(file.path);
3292
+ if (paths.has(file.path)) throw new SkillInstallError(`Duplicate package path: ${file.path}`, 400);
3293
+ paths.add(file.path);
3294
+ if (file.content.byteLength > 25 * 1024 * 1024) throw new SkillInstallError("Package file exceeds 25 MiB", 413);
3295
+ totalBytes += file.content.byteLength;
3296
+ }
3297
+ if (totalBytes > 50 * 1024 * 1024) throw new SkillInstallError("Package exceeds 50 MiB", 413);
3298
+ const destination = join2(libraryDir, packageName);
3299
+ if (await pathExists(destination)) throw new SkillInstallError("A package with this name already exists", 409);
3300
+ const staging = join2(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
3301
+ try {
3302
+ await mkdir(staging, { recursive: false });
3303
+ for (const file of files) {
3304
+ const target = join2(staging, file.path);
3305
+ await mkdir(dirname3(target), { recursive: true });
3306
+ await writeFile(target, file.content);
3307
+ }
3308
+ const parsed = matter(await readFile(join2(staging, "SKILL.md"), "utf-8"));
3309
+ const name = typeof parsed.data["name"] === "string" ? parsed.data["name"].trim() : "";
3310
+ const description = typeof parsed.data["description"] === "string" ? parsed.data["description"].trim() : "";
3311
+ if (!name || !description || !parsed.content.trim()) {
3312
+ throw new SkillInstallError("SKILL.md requires name, description, and instructions", 400);
3313
+ }
3314
+ if (await pathExists(destination)) throw new SkillInstallError("A package with this name already exists", 409);
3315
+ await rename(staging, destination);
3316
+ return { id: name, path: destination };
3317
+ } catch (error) {
3318
+ await rm(staging, { recursive: true, force: true });
3319
+ throw error;
3320
+ }
3321
+ }
3322
+
3244
3323
  // src/server/routes/crud-helpers.ts
3245
3324
  import { Router } from "express";
3246
- import { join as join2 } from "path";
3325
+ import { join as join3 } from "path";
3247
3326
  function computeOverrideIds(defaults, userItems) {
3248
3327
  return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
3249
3328
  }
@@ -3255,34 +3334,34 @@ function validateNameIdPrompt(body) {
3255
3334
  return null;
3256
3335
  }
3257
3336
  function getProjectItemPath(projectDir, dirName, id, ext) {
3258
- return join2(projectDir, ".openfox", dirName, `${id}${ext}`);
3337
+ return join3(projectDir, ".openfox", dirName, `${id}${ext}`);
3259
3338
  }
3260
3339
  async function isProjectItem(projectDir, dirName, id, ext) {
3261
3340
  if (!projectDir) return false;
3262
3341
  return pathExists(getProjectItemPath(projectDir, dirName, id, ext));
3263
3342
  }
3264
- function createCrudRoutes(config4, configDir, projectDir) {
3343
+ function createCrudRoutes(config3, configDir, projectDir) {
3265
3344
  const router = Router();
3266
3345
  router.get("/", async (_req, res) => {
3267
3346
  const [defaults, userItems, projectItems] = await Promise.all([
3268
- config4.loadDefaults(),
3269
- config4.loadUser(configDir),
3270
- projectDir ? config4.loadProject(projectDir) : []
3347
+ config3.loadDefaults(),
3348
+ config3.loadUser(configDir),
3349
+ projectDir ? config3.loadProject(projectDir) : []
3271
3350
  ]);
3272
3351
  const userOverrideIds = computeOverrideIds(defaults, userItems);
3273
3352
  const projectOverrideIds = computeOverrideIds(defaults, projectItems);
3274
- const extra = config4.extraGetData ? await config4.extraGetData() : {};
3353
+ const extra = config3.extraGetData ? await config3.extraGetData() : {};
3275
3354
  res.json({
3276
- defaults: defaults.map(config4.mapToResponse),
3277
- userItems: userItems.map(config4.mapToResponse),
3278
- projectItems: projectItems.map(config4.mapToResponse),
3355
+ defaults: defaults.map(config3.mapToResponse),
3356
+ userItems: userItems.map(config3.mapToResponse),
3357
+ projectItems: projectItems.map(config3.mapToResponse),
3279
3358
  overrideIds: [...userOverrideIds, ...projectOverrideIds],
3280
3359
  ...extra
3281
3360
  });
3282
3361
  });
3283
3362
  router.get("/defaults/:id", async (req, res) => {
3284
3363
  const { id } = req.params;
3285
- const allDefaults = await config4.loadDefaults();
3364
+ const allDefaults = await config3.loadDefaults();
3286
3365
  const item = allDefaults.find((d) => d.metadata.id === id);
3287
3366
  if (!item) {
3288
3367
  return res.status(404).json({ error: "Default not found" });
@@ -3290,13 +3369,13 @@ function createCrudRoutes(config4, configDir, projectDir) {
3290
3369
  res.json(item);
3291
3370
  });
3292
3371
  router.get("/default-ids", async (_req, res) => {
3293
- const ids = config4.getDefaultIds ? await config4.getDefaultIds() : [];
3372
+ const ids = config3.getDefaultIds ? await config3.getDefaultIds() : [];
3294
3373
  res.json({ ids });
3295
3374
  });
3296
3375
  router.get("/:id", async (req, res) => {
3297
3376
  const { id } = req.params;
3298
- const items = await config4.loadAll(configDir, projectDir);
3299
- const item = config4.findById(id, items);
3377
+ const items = await config3.loadAll(configDir, projectDir);
3378
+ const item = config3.findById(id, items);
3300
3379
  if (!item) {
3301
3380
  return res.status(404).json({ error: "Not found" });
3302
3381
  }
@@ -3305,7 +3384,7 @@ function createCrudRoutes(config4, configDir, projectDir) {
3305
3384
  router.post("/", async (req, res) => {
3306
3385
  const body = req.body;
3307
3386
  const meta = body["metadata"];
3308
- const customError = config4.validateCreate?.(body);
3387
+ const customError = config3.validateCreate?.(body);
3309
3388
  if (!meta?.["id"] || customError) {
3310
3389
  return res.status(400).json({ error: customError ?? "Missing required fields" });
3311
3390
  }
@@ -3314,21 +3393,21 @@ function createCrudRoutes(config4, configDir, projectDir) {
3314
3393
  if (destination === "project" && !projectDir) {
3315
3394
  return res.status(400).json({ error: "No project directory configured" });
3316
3395
  }
3317
- const exists = await config4.exists(configDir, id, projectDir);
3396
+ const exists = await config3.exists(configDir, id, projectDir);
3318
3397
  if (exists) {
3319
3398
  return res.status(409).json({ error: "An item with this ID already exists" });
3320
3399
  }
3321
3400
  if (destination === "project") {
3322
- await config4.saveToProject(projectDir, body);
3401
+ await config3.saveToProject(projectDir, body);
3323
3402
  } else {
3324
- await config4.save(configDir, body);
3403
+ await config3.save(configDir, body);
3325
3404
  }
3326
3405
  res.status(201).json(body);
3327
3406
  });
3328
3407
  router.put("/:id", async (req, res) => {
3329
3408
  const { id } = req.params;
3330
- const items = await config4.loadAll(configDir, projectDir);
3331
- const existing = config4.findById(id, items);
3409
+ const items = await config3.loadAll(configDir, projectDir);
3410
+ const existing = config3.findById(id, items);
3332
3411
  if (!existing) {
3333
3412
  return res.status(404).json({ error: "Not found" });
3334
3413
  }
@@ -3339,29 +3418,29 @@ function createCrudRoutes(config4, configDir, projectDir) {
3339
3418
  ...body,
3340
3419
  metadata: { ...existing.metadata, ...meta, id }
3341
3420
  };
3342
- const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
3421
+ const isProject = await isProjectItem(projectDir, config3.dirName, id, config3.ext);
3343
3422
  if (isProject) {
3344
- await config4.saveToProject(projectDir, updated);
3423
+ await config3.saveToProject(projectDir, updated);
3345
3424
  } else {
3346
- await config4.save(configDir, updated);
3425
+ await config3.save(configDir, updated);
3347
3426
  }
3348
3427
  res.json(updated);
3349
3428
  });
3350
3429
  router.delete("/:id", async (req, res) => {
3351
3430
  const { id } = req.params;
3352
- const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
3431
+ const isProject = await isProjectItem(projectDir, config3.dirName, id, config3.ext);
3353
3432
  if (isProject) {
3354
- const result2 = await config4.deleteProject(projectDir, id);
3433
+ const result2 = await config3.deleteProject(projectDir, id);
3355
3434
  if (!result2.success) {
3356
3435
  return res.status(500).json({ error: "Failed to delete project item" });
3357
3436
  }
3358
3437
  return res.json({ success: true });
3359
3438
  }
3360
- const isDefault = await config4.isDefault(id);
3439
+ const isDefault = await config3.isDefault(id);
3361
3440
  if (isDefault) {
3362
3441
  return res.status(403).json({ error: "Cannot delete built-in defaults" });
3363
3442
  }
3364
- const result = await config4.delete(configDir, id);
3443
+ const result = await config3.delete(configDir, id);
3365
3444
  if (!result.success) {
3366
3445
  return res.status(403).json({ error: result.reason ?? "Cannot delete this item" });
3367
3446
  }
@@ -3369,8 +3448,8 @@ function createCrudRoutes(config4, configDir, projectDir) {
3369
3448
  });
3370
3449
  router.post("/:id/duplicate", async (req, res) => {
3371
3450
  const { id } = req.params;
3372
- const items = await config4.loadAll(configDir, projectDir);
3373
- const source = config4.findById(id, items);
3451
+ const items = await config3.loadAll(configDir, projectDir);
3452
+ const source = config3.findById(id, items);
3374
3453
  if (!source) {
3375
3454
  return res.status(404).json({ error: "Not found" });
3376
3455
  }
@@ -3382,56 +3461,195 @@ function createCrudRoutes(config4, configDir, projectDir) {
3382
3461
  const destination = req.body.destination ?? "user";
3383
3462
  if (destination === "project") {
3384
3463
  if (!projectDir) return res.status(400).json({ error: "No project directory configured" });
3385
- await config4.saveToProject(projectDir, duplicated);
3464
+ await config3.saveToProject(projectDir, duplicated);
3386
3465
  } else {
3387
- await config4.save(configDir, duplicated);
3466
+ await config3.save(configDir, duplicated);
3388
3467
  }
3389
3468
  res.status(201).json(duplicated);
3390
3469
  });
3391
- config4.extraRoutes?.(router);
3470
+ config3.extraRoutes?.(router);
3392
3471
  return router;
3393
3472
  }
3394
3473
 
3395
3474
  // src/server/routes/skills.ts
3396
- var config = {
3397
- dirName: "skills",
3398
- ext: ".skill.md",
3399
- loadDefaults: loadDefaultSkills,
3400
- loadUser: loadUserSkills,
3401
- loadProject: loadProjectSkills,
3402
- loadAll: loadAllSkills,
3403
- findById: findSkillById,
3404
- save: saveSkill,
3405
- saveToProject: saveSkillToProject,
3406
- delete: deleteSkill,
3407
- deleteProject: deleteProjectSkill,
3408
- exists: skillExists,
3409
- isDefault: isDefaultSkill,
3410
- getDefaultIds: getDefaultSkillIds,
3411
- validateCreate: validateNameIdPrompt,
3412
- mapToResponse: (s) => ({
3413
- ...s.metadata,
3414
- enabled: isSkillEnabled(s.metadata.id)
3415
- })
3416
- };
3475
+ var SKILL_DIRECTORIES_SETTING = "skills.directories";
3476
+ var upload = multer({
3477
+ storage: multer.memoryStorage(),
3478
+ limits: { files: 1e3, fileSize: 25 * 1024 * 1024, fields: 4 }
3479
+ });
3480
+ function expandHome(path) {
3481
+ if (path === "~") return homedir();
3482
+ return path.startsWith("~/") ? join4(homedir(), path.slice(2)) : path;
3483
+ }
3484
+ function configuredDirectory() {
3485
+ const raw = getSetting(SKILL_DIRECTORIES_SETTING);
3486
+ if (!raw) return null;
3487
+ try {
3488
+ const parsed = JSON.parse(raw);
3489
+ return Array.isArray(parsed) && typeof parsed[0] === "string" ? parsed[0] : null;
3490
+ } catch {
3491
+ return null;
3492
+ }
3493
+ }
3494
+ function defaultLibrary(configDir) {
3495
+ const path = resolve2(configDir, "skills");
3496
+ return { configuredPath: path, resolvedPath: path, available: true, custom: false };
3497
+ }
3498
+ async function resolveLibrary(path) {
3499
+ const expanded = expandHome(path);
3500
+ if (!isAbsolute2(expanded)) throw new Error("Selected path must be absolute");
3501
+ const absolute = resolve2(expanded);
3502
+ const info = await stat(absolute);
3503
+ if (!info.isDirectory()) throw new Error("Selected path is not a directory");
3504
+ await access2(absolute, constants2.R_OK);
3505
+ return { configuredPath: path, resolvedPath: await realpath(absolute) };
3506
+ }
3507
+ function mapToResponse(skill) {
3508
+ const source = skill.source ?? "global-openfox";
3509
+ return {
3510
+ ...skill.metadata,
3511
+ enabled: isSkillEnabled(skill.metadata.id),
3512
+ source,
3513
+ path: skill.entrypoint ?? null,
3514
+ legacy: skill.legacy ?? true,
3515
+ readOnly: source === "bundled" || (source === "global-shared" || source === "selected" || source === "project-shared") && (skill.legacy ?? true),
3516
+ warnings: skill.warnings ?? []
3517
+ };
3518
+ }
3519
+ function validateSkillCreate(body) {
3520
+ const baseError = validateNameIdPrompt(body);
3521
+ if (baseError) return baseError;
3522
+ const metadata = body["metadata"];
3523
+ if (typeof metadata["description"] !== "string" || !metadata["description"].trim()) {
3524
+ return "Missing required field: metadata.description";
3525
+ }
3526
+ return null;
3527
+ }
3528
+ function createConfig(configDir, projectDir) {
3529
+ return {
3530
+ dirName: "skills",
3531
+ ext: ".skill.md",
3532
+ loadDefaults: loadDefaultSkills,
3533
+ loadUser: loadUserSkills,
3534
+ loadProject: loadProjectSkills,
3535
+ loadAll: loadAllSkills,
3536
+ findById: findSkillById,
3537
+ save: saveSkill,
3538
+ saveToProject: saveSkillToProject,
3539
+ delete: deleteSkill,
3540
+ deleteProject: deleteProjectSkill,
3541
+ exists: skillExists,
3542
+ isDefault: isDefaultSkill,
3543
+ getDefaultIds: getDefaultSkillIds,
3544
+ validateCreate: validateSkillCreate,
3545
+ mapToResponse,
3546
+ extraGetData: async () => {
3547
+ const discovery = await loadAllSkillsWithDiagnostics(configDir, projectDir);
3548
+ const items = discovery.skills;
3549
+ const configured = configuredDirectory();
3550
+ let selectedDirectory = configured ? { configuredPath: configured, resolvedPath: null, available: false, custom: true } : defaultLibrary(configDir);
3551
+ const diagnostics = [];
3552
+ if (configured) {
3553
+ try {
3554
+ selectedDirectory = { ...await resolveLibrary(configured), available: true, custom: true };
3555
+ } catch {
3556
+ diagnostics.push(`Selected skills directory is unavailable: ${configured}`);
3557
+ }
3558
+ }
3559
+ return {
3560
+ items: items.map(mapToResponse),
3561
+ selectedDirectory,
3562
+ diagnostics: [...diagnostics, ...discovery.diagnostics, ...items.flatMap((skill) => skill.warnings ?? [])]
3563
+ };
3564
+ }
3565
+ };
3566
+ }
3417
3567
  function createSkillRoutes(configDir, projectDir) {
3418
- return createCrudRoutes(config, configDir, projectDir);
3568
+ const router = Router2();
3569
+ router.put("/library", async (req, res) => {
3570
+ const path = req.body.path;
3571
+ if (typeof path !== "string" || !path.trim()) return res.status(400).json({ error: "path is required" });
3572
+ try {
3573
+ const selected = await resolveLibrary(path);
3574
+ setSetting(SKILL_DIRECTORIES_SETTING, JSON.stringify([path]));
3575
+ res.json(selected);
3576
+ } catch (error) {
3577
+ res.status(400).json({ error: error instanceof Error ? error.message : "Cannot use directory" });
3578
+ }
3579
+ });
3580
+ router.delete("/library", (_req, res) => {
3581
+ deleteSetting(SKILL_DIRECTORIES_SETTING);
3582
+ res.json({ success: true });
3583
+ });
3584
+ router.post("/install", (req, res) => {
3585
+ upload.array("files", 1e3)(req, res, async (uploadError) => {
3586
+ if (uploadError) return res.status(413).json({ error: uploadError.message });
3587
+ try {
3588
+ const configured = configuredDirectory();
3589
+ const library = configured ? await resolveLibrary(configured) : defaultLibrary(configDir);
3590
+ await mkdir2(library.resolvedPath, { recursive: true });
3591
+ const packageName = String(req.body["packageName"] ?? "");
3592
+ const paths = JSON.parse(String(req.body["paths"] ?? "[]"));
3593
+ const files = req.files;
3594
+ if (!Array.isArray(paths) || paths.length !== files.length || paths.some((path) => typeof path !== "string")) {
3595
+ return res.status(400).json({ error: "File path manifest does not match upload" });
3596
+ }
3597
+ const totalBytes = files.reduce((total, file) => total + file.size, 0);
3598
+ if (totalBytes > 50 * 1024 * 1024) return res.status(413).json({ error: "Package exceeds 50 MiB" });
3599
+ const installed = await installSkillPackage(
3600
+ library.resolvedPath,
3601
+ packageName,
3602
+ files.map((file, index) => ({ path: paths[index], content: file.buffer }))
3603
+ );
3604
+ res.status(201).json(installed);
3605
+ } catch (error) {
3606
+ const status = error instanceof SkillInstallError ? error.status : 400;
3607
+ res.status(status).json({ error: error instanceof Error ? error.message : "Install failed" });
3608
+ }
3609
+ });
3610
+ });
3611
+ router.post("/:id/toggle", async (req, res) => {
3612
+ const skills = await loadAllSkills(configDir, projectDir);
3613
+ const existing = findSkillById(req.params["id"], skills);
3614
+ if (!existing) return res.status(404).json({ error: "Not found" });
3615
+ const enabled = !isSkillEnabled(existing.metadata.id);
3616
+ setSkillEnabled(existing.metadata.id, enabled);
3617
+ res.json({ enabled });
3618
+ });
3619
+ router.put("/:id", async (req, res) => {
3620
+ const skills = await loadAllSkills(configDir, projectDir);
3621
+ const existing = findSkillById(req.params["id"], skills);
3622
+ if (!existing) return res.status(404).json({ error: "Not found" });
3623
+ const updated = await updateOwnedSkill(existing, req.body);
3624
+ if (!updated) return res.status(403).json({ error: "This skill is read-only" });
3625
+ res.json(updated);
3626
+ });
3627
+ router.delete("/:id", async (req, res) => {
3628
+ const skills = await loadAllSkills(configDir, projectDir);
3629
+ const existing = findSkillById(req.params["id"], skills);
3630
+ if (!existing) return res.status(404).json({ error: "Not found" });
3631
+ const result = await deleteOwnedSkill(existing);
3632
+ if (!result.success) return res.status(403).json({ error: result.reason ?? "Cannot delete this skill" });
3633
+ res.json({ success: true });
3634
+ });
3635
+ router.use(createCrudRoutes(createConfig(configDir, projectDir), configDir, projectDir));
3636
+ return router;
3419
3637
  }
3420
3638
 
3421
3639
  // src/server/commands/registry.ts
3422
- import { writeFile, mkdir, unlink } from "fs/promises";
3423
- import { join as join3, dirname as dirname3 } from "path";
3640
+ import { writeFile as writeFile2, mkdir as mkdir3, unlink } from "fs/promises";
3641
+ import { join as join5, dirname as dirname4 } from "path";
3424
3642
  import { fileURLToPath as fileURLToPath4 } from "url";
3425
- import matter from "gray-matter";
3426
- var __bundleDir = dirname3(fileURLToPath4(import.meta.url));
3427
- var DEFAULTS_DIR = join3(__bundleDir, "defaults");
3428
- var DEFAULTS_DIR_ALT = join3(__bundleDir, "command-defaults");
3643
+ import matter2 from "gray-matter";
3644
+ var __bundleDir = dirname4(fileURLToPath4(import.meta.url));
3645
+ var DEFAULTS_DIR = join5(__bundleDir, "defaults");
3646
+ var DEFAULTS_DIR_ALT = join5(__bundleDir, "command-defaults");
3429
3647
  var COMMAND_EXTENSION = ".command.md";
3430
3648
  function getCommandsDir(configDir) {
3431
- return join3(configDir, "commands");
3649
+ return join5(configDir, "commands");
3432
3650
  }
3433
3651
  function getProjectCommandsDir(projectDir) {
3434
- return join3(projectDir, ".openfox", "commands");
3652
+ return join5(projectDir, ".openfox", "commands");
3435
3653
  }
3436
3654
  async function loadDefaultCommands() {
3437
3655
  let defaults = await loadItemsFromDir(DEFAULTS_DIR, {
@@ -3488,26 +3706,26 @@ function findCommandById(commandId, commands) {
3488
3706
  return commands.find((c) => c.metadata.id === commandId);
3489
3707
  }
3490
3708
  async function commandExists(configDir, commandId, projectDir) {
3491
- if (await pathExists(join3(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
3492
- if (projectDir && await pathExists(join3(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
3709
+ if (await pathExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
3710
+ if (projectDir && await pathExists(join5(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
3493
3711
  return true;
3494
3712
  return false;
3495
3713
  }
3496
3714
  async function saveCommand(configDir, command) {
3497
3715
  const commandsDir = getCommandsDir(configDir);
3498
3716
  if (!await pathExists(commandsDir)) {
3499
- await mkdir(commandsDir, { recursive: true });
3717
+ await mkdir3(commandsDir, { recursive: true });
3500
3718
  }
3501
- const filePath = join3(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
3502
- const content = matter.stringify(command.prompt, command.metadata);
3503
- await writeFile(filePath, content, "utf-8");
3719
+ const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
3720
+ const content = matter2.stringify(command.prompt, command.metadata);
3721
+ await writeFile2(filePath, content, "utf-8");
3504
3722
  }
3505
3723
  async function saveCommandToProject(projectDir, command) {
3506
3724
  await saveItemToDir(
3507
3725
  getProjectCommandsDir(projectDir),
3508
3726
  command,
3509
3727
  COMMAND_EXTENSION,
3510
- (c) => matter.stringify(c.prompt, c.metadata)
3728
+ (c) => matter2.stringify(c.prompt, c.metadata)
3511
3729
  );
3512
3730
  }
3513
3731
  async function deleteProjectCommand(projectDir, commandId) {
@@ -3518,7 +3736,7 @@ async function deleteCommand(configDir, commandId) {
3518
3736
  if (isDefault) {
3519
3737
  return { success: false, reason: "Cannot delete built-in defaults" };
3520
3738
  }
3521
- const filePath = join3(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3739
+ const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3522
3740
  try {
3523
3741
  await unlink(filePath);
3524
3742
  return { success: true };
@@ -3528,7 +3746,7 @@ async function deleteCommand(configDir, commandId) {
3528
3746
  }
3529
3747
 
3530
3748
  // src/server/routes/commands.ts
3531
- var config2 = {
3749
+ var config = {
3532
3750
  dirName: "commands",
3533
3751
  ext: ".command.md",
3534
3752
  loadDefaults: loadDefaultCommands,
@@ -3547,11 +3765,11 @@ var config2 = {
3547
3765
  mapToResponse: (c) => c.metadata
3548
3766
  };
3549
3767
  function createCommandRoutes(configDir, projectDir) {
3550
- return createCrudRoutes(config2, configDir, projectDir);
3768
+ return createCrudRoutes(config, configDir, projectDir);
3551
3769
  }
3552
3770
 
3553
3771
  // src/server/routes/agents.ts
3554
- var config3 = {
3772
+ var config2 = {
3555
3773
  dirName: "agents",
3556
3774
  ext: ".agent.md",
3557
3775
  loadDefaults: loadDefaultAgents,
@@ -3574,12 +3792,12 @@ var config3 = {
3574
3792
  mapToResponse: (a) => a.metadata
3575
3793
  };
3576
3794
  function createAgentRoutes(configDir, projectDir) {
3577
- return createCrudRoutes(config3, configDir, projectDir);
3795
+ return createCrudRoutes(config2, configDir, projectDir);
3578
3796
  }
3579
3797
 
3580
3798
  // src/server/routes/workflows.ts
3581
3799
  import "express";
3582
- function createWorkflowRoutes(configDir, config4, projectDir) {
3800
+ function createWorkflowRoutes(configDir, config3, projectDir) {
3583
3801
  const crudConfig = {
3584
3802
  dirName: "workflows",
3585
3803
  ext: ".workflow.json",
@@ -3608,7 +3826,7 @@ function createWorkflowRoutes(configDir, config4, projectDir) {
3608
3826
  subGroups: subGroups.length > 0 ? subGroups : void 0
3609
3827
  };
3610
3828
  },
3611
- extraGetData: () => Promise.resolve({ activeWorkflowId: config4.activeWorkflowId ?? "default" }),
3829
+ extraGetData: () => Promise.resolve({ activeWorkflowId: config3.activeWorkflowId ?? "default" }),
3612
3830
  extraRoutes: (router) => {
3613
3831
  router.get("/template-variables", (_req, res) => {
3614
3832
  res.json({ variables: TEMPLATE_VARIABLES });
@@ -3619,19 +3837,19 @@ function createWorkflowRoutes(configDir, config4, projectDir) {
3619
3837
  }
3620
3838
 
3621
3839
  // src/server/routes/dev-server.ts
3622
- import { Router as Router3 } from "express";
3840
+ import { Router as Router4 } from "express";
3623
3841
  function createDevServerRoutes() {
3624
- const router = Router3();
3842
+ const router = Router4();
3625
3843
  router.get("/", async (req, res) => {
3626
3844
  const workdir = req.query["workdir"];
3627
3845
  if (!workdir) return res.status(400).json({ error: "workdir required" });
3628
3846
  const status = devServerManager.getStatus(workdir);
3629
3847
  if (!status.config) {
3630
- const config4 = await devServerManager.loadConfig(workdir);
3631
- if (config4) {
3632
- status.config = config4;
3633
- status.url = config4.url;
3634
- status.hotReload = config4.hotReload;
3848
+ const config3 = await devServerManager.loadConfig(workdir);
3849
+ if (config3) {
3850
+ status.config = config3;
3851
+ status.url = config3.url;
3852
+ status.hotReload = config3.hotReload;
3635
3853
  }
3636
3854
  }
3637
3855
  res.json(status);
@@ -3677,8 +3895,8 @@ function createDevServerRoutes() {
3677
3895
  router.get("/config", async (req, res) => {
3678
3896
  const workdir = req.query["workdir"];
3679
3897
  if (!workdir) return res.status(400).json({ error: "workdir required" });
3680
- const config4 = await devServerManager.loadConfig(workdir);
3681
- res.json({ config: config4 });
3898
+ const config3 = await devServerManager.loadConfig(workdir);
3899
+ res.json({ config: config3 });
3682
3900
  });
3683
3901
  router.post("/config", async (req, res) => {
3684
3902
  const workdir = req.query["workdir"];
@@ -3688,9 +3906,9 @@ function createDevServerRoutes() {
3688
3906
  return res.status(400).json({ error: "command and url are required" });
3689
3907
  }
3690
3908
  try {
3691
- const config4 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
3692
- await devServerManager.saveConfig(workdir, config4);
3693
- res.json({ config: config4 });
3909
+ const config3 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
3910
+ await devServerManager.saveConfig(workdir, config3);
3911
+ res.json({ config: config3 });
3694
3912
  } catch (err) {
3695
3913
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
3696
3914
  }
@@ -3699,9 +3917,9 @@ function createDevServerRoutes() {
3699
3917
  }
3700
3918
 
3701
3919
  // src/server/routes/terminals.ts
3702
- import { Router as Router4 } from "express";
3920
+ import { Router as Router5 } from "express";
3703
3921
  function createTerminalRoutes() {
3704
- const router = Router4();
3922
+ const router = Router5();
3705
3923
  router.get("/", (req, res) => {
3706
3924
  const projectId = req.query["projectId"];
3707
3925
  const sessions = projectId ? terminalManager.getByProject(projectId) : [];
@@ -3740,22 +3958,22 @@ function createTerminalRoutes() {
3740
3958
  }
3741
3959
 
3742
3960
  // src/server/routes/directories.ts
3743
- import { Router as Router5 } from "express";
3961
+ import { Router as Router6 } from "express";
3744
3962
  import { readdir } from "fs/promises";
3745
- import { resolve as resolve2, join as join4, dirname as dirname4, basename as basename2 } from "path";
3963
+ import { resolve as resolve3, join as join6, dirname as dirname5, basename as basename2 } from "path";
3746
3964
  function createDirectoryRoutes() {
3747
- const router = Router5();
3965
+ const router = Router6();
3748
3966
  const DEFAULT_BASE_PATH = process.cwd();
3749
3967
  router.get("/", async (req, res) => {
3750
3968
  const path = req.query["path"] || DEFAULT_BASE_PATH;
3751
3969
  try {
3752
- const resolvedPath = resolve2(path);
3970
+ const resolvedPath = resolve3(path);
3753
3971
  const entries = await readdir(resolvedPath, { withFileTypes: true });
3754
3972
  const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
3755
3973
  name: entry.name,
3756
- path: join4(resolvedPath, entry.name)
3974
+ path: join6(resolvedPath, entry.name)
3757
3975
  })).sort((a, b) => a.name.localeCompare(b.name));
3758
- const parent = dirname4(resolvedPath);
3976
+ const parent = dirname5(resolvedPath);
3759
3977
  const hasParent = parent !== resolvedPath;
3760
3978
  res.json({
3761
3979
  current: resolvedPath,
@@ -3777,10 +3995,10 @@ function createDirectoryRoutes() {
3777
3995
  }
3778
3996
 
3779
3997
  // src/server/routes/file-search.ts
3780
- import { Router as Router6 } from "express";
3998
+ import { Router as Router7 } from "express";
3781
3999
  import fg from "fast-glob";
3782
4000
  function createFileSearchRoutes() {
3783
- const router = Router6();
4001
+ const router = Router7();
3784
4002
  router.get("/", async (req, res) => {
3785
4003
  const query = req.query["q"] || "";
3786
4004
  const workdir = req.query["workdir"] || process.cwd();
@@ -3856,11 +4074,11 @@ function fuzzyScore(filePath, query) {
3856
4074
  }
3857
4075
 
3858
4076
  // src/server/routes/auto-update.ts
3859
- import { Router as Router7 } from "express";
4077
+ import { Router as Router8 } from "express";
3860
4078
  import { spawn as spawn2 } from "child_process";
3861
4079
 
3862
4080
  // src/constants.ts
3863
- var VERSION = "2.0.58";
4081
+ var VERSION = "2.0.60";
3864
4082
 
3865
4083
  // src/server/routes/auto-update.ts
3866
4084
  var updateInProgress = false;
@@ -3878,14 +4096,15 @@ async function checkAuth(req, opts) {
3878
4096
  return true;
3879
4097
  }
3880
4098
  function createAutoUpdateRoutes(options = {}) {
3881
- const router = Router7();
4099
+ const router = Router8();
3882
4100
  router.get("/check", async (_req, res) => {
3883
4101
  const isService = isRunningAsService();
3884
4102
  const current = VERSION;
3885
4103
  try {
3886
- const latest = await new Promise((resolve4, reject) => {
4104
+ const latest = await new Promise((resolve5, reject) => {
3887
4105
  const child = spawn2("npm", ["view", "openfox", "version"], {
3888
- stdio: ["ignore", "pipe", "pipe"]
4106
+ stdio: ["ignore", "pipe", "pipe"],
4107
+ windowsHide: true
3889
4108
  });
3890
4109
  let stdout = "";
3891
4110
  child.stdout?.on("data", (data) => {
@@ -3893,7 +4112,7 @@ function createAutoUpdateRoutes(options = {}) {
3893
4112
  });
3894
4113
  child.on("close", (code) => {
3895
4114
  if (code === 0) {
3896
- resolve4(stdout.trim());
4115
+ resolve5(stdout.trim());
3897
4116
  } else {
3898
4117
  reject(new Error(`npm view exited with code ${code}`));
3899
4118
  }
@@ -3923,7 +4142,8 @@ function createAutoUpdateRoutes(options = {}) {
3923
4142
  try {
3924
4143
  const isService = isRunningAsService();
3925
4144
  const child = spawn2("bash", ["-c", "openfox update"], {
3926
- stdio: ["ignore", "pipe", "pipe"]
4145
+ stdio: ["ignore", "pipe", "pipe"],
4146
+ windowsHide: true
3927
4147
  });
3928
4148
  let stdout = "";
3929
4149
  let stderr = "";
@@ -3936,9 +4156,9 @@ function createAutoUpdateRoutes(options = {}) {
3936
4156
  const timeout = setTimeout(() => {
3937
4157
  child.kill();
3938
4158
  }, UPDATE_TIMEOUT);
3939
- const exitCode = await new Promise((resolve4) => {
3940
- child.on("close", resolve4);
3941
- child.on("error", () => resolve4(1));
4159
+ const exitCode = await new Promise((resolve5) => {
4160
+ child.on("close", resolve5);
4161
+ child.on("error", () => resolve5(1));
3942
4162
  });
3943
4163
  clearTimeout(timeout);
3944
4164
  if (exitCode === 0) {
@@ -3963,7 +4183,8 @@ function createAutoUpdateRoutes(options = {}) {
3963
4183
  try {
3964
4184
  const child = spawn2("bash", ["-c", "openfox service restart"], {
3965
4185
  detached: true,
3966
- stdio: "ignore"
4186
+ stdio: "ignore",
4187
+ windowsHide: true
3967
4188
  });
3968
4189
  child.unref();
3969
4190
  res.json({ success: true });
@@ -3975,15 +4196,15 @@ function createAutoUpdateRoutes(options = {}) {
3975
4196
  }
3976
4197
 
3977
4198
  // src/server/index.ts
3978
- var __dirname3 = dirname5(fileURLToPath5(import.meta.url));
3979
- async function createServerHandle(config4) {
3980
- setRuntimeConfig(config4);
3981
- setLogLevel(config4.logging?.level ?? void 0, config4.mode);
4199
+ var __dirname3 = dirname6(fileURLToPath5(import.meta.url));
4200
+ async function createServerHandle(config3) {
4201
+ setRuntimeConfig(config3);
4202
+ setLogLevel(config3.logging?.level ?? void 0, config3.mode);
3982
4203
  await loadServerAuthConfig();
3983
- const db = initDatabase(config4);
4204
+ const db = initDatabase(config3);
3984
4205
  initEventStore(db);
3985
- const configDir = getGlobalConfigDir(config4.mode ?? "production");
3986
- const providerManager = createProviderManager(config4);
4206
+ const configDir = getGlobalConfigDir(config3.mode ?? "production");
4207
+ const providerManager = createProviderManager(config3);
3987
4208
  const sessionManager = new SessionManager(providerManager);
3988
4209
  devServerManager.setSessionManager(sessionManager);
3989
4210
  const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
@@ -3994,24 +4215,24 @@ async function createServerHandle(config4) {
3994
4215
  }
3995
4216
  async function initLLM() {
3996
4217
  const llmClient = getLLMClient();
3997
- const backend = config4.llm.backend;
4218
+ const backend = config3.llm.backend;
3998
4219
  llmClient.setBackend(backend);
3999
4220
  if (!useMock) {
4000
4221
  logger.info("Using configured LLM backend", { backend: getBackendDisplayName(backend) });
4001
4222
  }
4002
- const detected = await detectModel(config4.llm.baseUrl);
4003
- if (detected && !config4.defaultModelSelection) {
4223
+ const detected = await detectModel(config3.llm.baseUrl);
4224
+ if (detected && !config3.defaultModelSelection) {
4004
4225
  llmClient.setModel(detected);
4005
4226
  if (!useMock) {
4006
4227
  logger.info("Auto-detected LLM model", { model: detected, backend: getBackendDisplayName(backend) });
4007
4228
  }
4008
- } else if (detected && config4.defaultModelSelection) {
4229
+ } else if (detected && config3.defaultModelSelection) {
4009
4230
  if (!useMock) {
4010
- logger.debug("Skipping auto-detect, using configured model", { model: config4.llm.model });
4231
+ logger.debug("Skipping auto-detect, using configured model", { model: config3.llm.model });
4011
4232
  }
4012
4233
  } else {
4013
4234
  if (!useMock) {
4014
- logger.warn("Could not auto-detect model, using config", { model: config4.llm.model });
4235
+ logger.warn("Could not auto-detect model, using config", { model: config3.llm.model });
4015
4236
  }
4016
4237
  }
4017
4238
  const activeProvider = providerManager.getActiveProvider();
@@ -4031,15 +4252,15 @@ async function createServerHandle(config4) {
4031
4252
  const mcpManager = new McpManager({
4032
4253
  onToolsDiscovered: async (name, tools) => {
4033
4254
  try {
4034
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-C2YDEF3N.js");
4035
- const mode = config4.mode ?? "production";
4036
- const globalConfig = await loadGlobalConfig(mode);
4255
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
4256
+ const mode = config3.mode ?? "production";
4257
+ const globalConfig = await loadGlobalConfig(mode, config3.globalConfigPath);
4037
4258
  const mcpServers2 = {
4038
4259
  ...globalConfig.mcpServers ?? {}
4039
4260
  };
4040
4261
  if (mcpServers2[name]) {
4041
4262
  mcpServers2[name] = { ...mcpServers2[name], cachedTools: tools };
4042
- await saveGlobalConfig(mode, { ...globalConfig, mcpServers: mcpServers2 });
4263
+ await saveGlobalConfig(mode, { ...globalConfig, mcpServers: mcpServers2 }, config3.globalConfigPath);
4043
4264
  }
4044
4265
  } catch (err) {
4045
4266
  logger.warn("Failed to persist MCP tool cache", { name, error: String(err) });
@@ -4047,8 +4268,9 @@ async function createServerHandle(config4) {
4047
4268
  }
4048
4269
  });
4049
4270
  setMcpManagerForTools(mcpManager);
4050
- setMcpConfigMode(config4.mode ?? "production");
4051
- const mcpServers = config4.mcpServers ?? {};
4271
+ setMcpConfigMode(config3.mode ?? "production");
4272
+ setMcpConfigPath(config3.globalConfigPath);
4273
+ const mcpServers = config3.mcpServers ?? {};
4052
4274
  Promise.all(
4053
4275
  Object.entries(mcpServers).map(
4054
4276
  ([name, serverConfig]) => mcpManager.addServer(name, serverConfig).catch((err) => {
@@ -4061,7 +4283,7 @@ async function createServerHandle(config4) {
4061
4283
  setMcpTools(mcpTools);
4062
4284
  logger.info("MCP tools registered", { count: mcpTools.length });
4063
4285
  }
4064
- const { signalMcpReady } = await import("./server-XUDZRBD3.js");
4286
+ const { signalMcpReady } = await import("./server-LMH7ZH5X.js");
4065
4287
  signalMcpReady();
4066
4288
  });
4067
4289
  const app = express();
@@ -4132,7 +4354,7 @@ async function createServerHandle(config4) {
4132
4354
  if (!name || !workdir) {
4133
4355
  return res.status(400).json({ error: "name and workdir are required" });
4134
4356
  }
4135
- const { createDirectoryWithGit } = await import("./project-creator-7RBHP6K6.js");
4357
+ const { createDirectoryWithGit } = await import("./project-creator-IDW7RACH.js");
4136
4358
  try {
4137
4359
  const project = await createDirectoryWithGit(name, workdir);
4138
4360
  res.status(201).json({ project });
@@ -4150,7 +4372,7 @@ async function createServerHandle(config4) {
4150
4372
  if (!targetPath) {
4151
4373
  return res.status(400).json({ error: "path is required" });
4152
4374
  }
4153
- const { checkPermissions } = await import("./permissions-QLHZUEGW.js");
4375
+ const { checkPermissions } = await import("./permissions-CGEK3DGZ.js");
4154
4376
  const result = await checkPermissions(targetPath);
4155
4377
  if (result.success) {
4156
4378
  res.json(result);
@@ -4167,7 +4389,7 @@ async function createServerHandle(config4) {
4167
4389
  if (!["group", "ownership", "join_group", "join_group_and_group"].includes(action)) {
4168
4390
  return res.status(400).json({ error: 'action must be "group", "ownership", "join_group", or "join_group_and_group"' });
4169
4391
  }
4170
- const { fixPermissions } = await import("./permissions-QLHZUEGW.js");
4392
+ const { fixPermissions } = await import("./permissions-CGEK3DGZ.js");
4171
4393
  const result = await fixPermissions(targetPath, action);
4172
4394
  if (result.success) {
4173
4395
  res.json(result);
@@ -4247,14 +4469,14 @@ async function createServerHandle(config4) {
4247
4469
  if (!project) {
4248
4470
  return res.status(404).json({ error: "Project not found" });
4249
4471
  }
4250
- const { providerId, model } = parseDefaultModelSelection(config4.defaultModelSelection);
4472
+ const { providerId, model } = parseDefaultModelSelection(config3.defaultModelSelection);
4251
4473
  const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
4252
4474
  res.status(201).json({ session });
4253
4475
  });
4254
4476
  app.get("/api/sessions/:id", async (req, res) => {
4255
4477
  const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4256
4478
  const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
4257
- const { getPendingQuestionsForSession } = await import("./tools-YJLXW3QS.js");
4479
+ const { getPendingQuestionsForSession } = await import("./tools-WGAZKL56.js");
4258
4480
  const session = sessionManager.getSession(req.params.id);
4259
4481
  if (!session) {
4260
4482
  return res.status(404).json({ error: "Session not found" });
@@ -4273,8 +4495,8 @@ async function createServerHandle(config4) {
4273
4495
  if (!session) {
4274
4496
  return res.status(404).json({ error: "Session not found" });
4275
4497
  }
4276
- const { stopSessionExecution } = await import("./chat-handler-W5D5LKKU.js");
4277
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-YJLXW3QS.js");
4498
+ const { stopSessionExecution } = await import("./chat-handler-MBR6ZQTX.js");
4499
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WGAZKL56.js");
4278
4500
  sessionManager.clearMessageQueue(sessionId);
4279
4501
  stopSessionExecution(sessionId, sessionManager);
4280
4502
  abortSession(sessionId);
@@ -4327,12 +4549,12 @@ async function createServerHandle(config4) {
4327
4549
  if (!result.success) {
4328
4550
  return res.status(500).json({ error: result.error ?? "Failed to set default model" });
4329
4551
  }
4330
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-C2YDEF3N.js");
4331
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
4552
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
4553
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4332
4554
  const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model);
4333
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
4334
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
4335
- res.json({ success: true, defaultModelSelection: config4.defaultModelSelection });
4555
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4556
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
4557
+ res.json({ success: true, defaultModelSelection: config3.defaultModelSelection });
4336
4558
  });
4337
4559
  app.put("/api/sessions/:id/criteria", async (req, res) => {
4338
4560
  const sessionId = req.params.id;
@@ -4428,7 +4650,7 @@ async function createServerHandle(config4) {
4428
4650
  if (!callId || approved === void 0) {
4429
4651
  return res.status(400).json({ error: "callId and approved are required" });
4430
4652
  }
4431
- const { providePathConfirmation } = await import("./tools-YJLXW3QS.js");
4653
+ const { providePathConfirmation } = await import("./tools-WGAZKL56.js");
4432
4654
  const result = providePathConfirmation(callId, approved, alwaysAllow);
4433
4655
  if (!result.found) {
4434
4656
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -4436,7 +4658,7 @@ async function createServerHandle(config4) {
4436
4658
  const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4437
4659
  const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-2BGFLV5J.js");
4438
4660
  const { createSessionStateMessage } = await import("./protocol-CTNE3ANP.js");
4439
- const { getPendingQuestionsForSession } = await import("./tools-YJLXW3QS.js");
4661
+ const { getPendingQuestionsForSession } = await import("./tools-WGAZKL56.js");
4440
4662
  const eventStore = getEventStore2();
4441
4663
  const events = eventStore.getEvents(sessionId);
4442
4664
  const messages = buildMessagesFromStoredEvents(events);
@@ -4457,7 +4679,7 @@ async function createServerHandle(config4) {
4457
4679
  if (!skip && typeof answer !== "string") {
4458
4680
  return res.status(400).json({ error: "answer is required when not skipping" });
4459
4681
  }
4460
- const { provideAnswer } = await import("./tools-YJLXW3QS.js");
4682
+ const { provideAnswer } = await import("./tools-WGAZKL56.js");
4461
4683
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
4462
4684
  if (!found) {
4463
4685
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -4485,8 +4707,8 @@ async function createServerHandle(config4) {
4485
4707
  if (!session) {
4486
4708
  return res.status(404).json({ error: "Session not found" });
4487
4709
  }
4488
- const { getSetting, SETTINGS_KEYS } = await import("./settings-X43DCM55.js");
4489
- if (getSetting(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
4710
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-2TQA7VTP.js");
4711
+ if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
4490
4712
  return res.json({ success: false, reason: "disabled" });
4491
4713
  }
4492
4714
  if (session.messages.length > 0) {
@@ -4517,7 +4739,7 @@ async function createServerHandle(config4) {
4517
4739
  backend: activeProvider?.backend ?? llmClient.getBackend(),
4518
4740
  model: llmClient.getModel()
4519
4741
  };
4520
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-Q47D6JXG.js");
4742
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-PIZJ42J2.js");
4521
4743
  runAgentTurn(
4522
4744
  {
4523
4745
  sessionManager,
@@ -4555,8 +4777,8 @@ async function createServerHandle(config4) {
4555
4777
  if (!session) {
4556
4778
  return res.status(404).json({ error: "Session not found" });
4557
4779
  }
4558
- const { stopSessionExecution } = await import("./chat-handler-W5D5LKKU.js");
4559
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-YJLXW3QS.js");
4780
+ const { stopSessionExecution } = await import("./chat-handler-MBR6ZQTX.js");
4781
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WGAZKL56.js");
4560
4782
  const queuedMessages = sessionManager.getQueueState(sessionId);
4561
4783
  sessionManager.clearMessageQueue(sessionId);
4562
4784
  stopSessionExecution(sessionId, sessionManager);
@@ -4636,7 +4858,7 @@ async function createServerHandle(config4) {
4636
4858
  res.json({ accepted: true });
4637
4859
  });
4638
4860
  app.get("/api/settings", async (req, res) => {
4639
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4861
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4640
4862
  const keysParam = req.query["keys"];
4641
4863
  if (!keysParam) {
4642
4864
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -4644,30 +4866,30 @@ async function createServerHandle(config4) {
4644
4866
  const keys = keysParam.split(",").map((k) => k.trim());
4645
4867
  const result = {};
4646
4868
  for (const key of keys) {
4647
- result[key] = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? "";
4869
+ result[key] = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? "";
4648
4870
  }
4649
4871
  res.json(result);
4650
4872
  });
4651
4873
  app.get("/api/settings/:key", async (req, res) => {
4652
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4874
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4653
4875
  const key = req.params.key;
4654
- const value = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4876
+ const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4655
4877
  res.json({ key, value });
4656
4878
  });
4657
4879
  app.get("/api/settings/:key", async (req, res) => {
4658
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4880
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4659
4881
  const key = req.params.key;
4660
- const value = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4882
+ const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4661
4883
  res.json({ key, value });
4662
4884
  });
4663
4885
  app.put("/api/settings/:key", async (req, res) => {
4664
- const { setSetting } = await import("./settings-X43DCM55.js");
4886
+ const { setSetting: setSetting2 } = await import("./settings-2TQA7VTP.js");
4665
4887
  const key = req.params.key;
4666
4888
  const { value } = req.body;
4667
4889
  if (value === void 0) {
4668
4890
  return res.status(400).json({ error: "value is required" });
4669
4891
  }
4670
- setSetting(key, value);
4892
+ setSetting2(key, value);
4671
4893
  res.json({ key, value });
4672
4894
  });
4673
4895
  app.get("/api/config", async (_req, res) => {
@@ -4676,8 +4898,8 @@ async function createServerHandle(config4) {
4676
4898
  let visionFallback;
4677
4899
  let globalWorkdir;
4678
4900
  try {
4679
- const { loadGlobalConfig, getVisionFallback } = await import("./config-C2YDEF3N.js");
4680
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
4901
+ const { loadGlobalConfig, getVisionFallback } = await import("./config-GMQUPNBY.js");
4902
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4681
4903
  const fallback = getVisionFallback(globalConfig);
4682
4904
  if (fallback) {
4683
4905
  visionFallback = {
@@ -4695,13 +4917,13 @@ async function createServerHandle(config4) {
4695
4917
  version: VERSION,
4696
4918
  model: llmClient.getModel(),
4697
4919
  maxContext: providerManager.getCurrentModelContext(),
4698
- llmUrl: activeProvider?.url ?? config4.llm.baseUrl,
4920
+ llmUrl: activeProvider?.url ?? config3.llm.baseUrl,
4699
4921
  llmStatus: getLlmStatus(),
4700
4922
  backend: llmClient.getBackend(),
4701
- workdir: globalWorkdir ?? config4.workdir,
4923
+ workdir: globalWorkdir ?? config3.workdir,
4702
4924
  providers: providerManager.getProviders(),
4703
4925
  activeProviderId: providerManager.getActiveProviderId(),
4704
- defaultModelSelection: config4.defaultModelSelection,
4926
+ defaultModelSelection: config3.defaultModelSelection,
4705
4927
  visionFallback
4706
4928
  });
4707
4929
  });
@@ -4710,7 +4932,7 @@ async function createServerHandle(config4) {
4710
4932
  const currentModel = providerManager.getCurrentModel();
4711
4933
  if (currentModel === "auto") {
4712
4934
  const activeProvider = providerManager.getActiveProvider();
4713
- const baseUrl = activeProvider?.url ?? config4.llm.baseUrl;
4935
+ const baseUrl = activeProvider?.url ?? config3.llm.baseUrl;
4714
4936
  const detected = await detectModel(baseUrl);
4715
4937
  if (detected) {
4716
4938
  llmClient.setModel(detected);
@@ -4899,8 +5121,8 @@ async function createServerHandle(config4) {
4899
5121
  return res.status(400).json({ error: "name, url, and backend are required" });
4900
5122
  }
4901
5123
  try {
4902
- const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-C2YDEF3N.js");
4903
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5124
+ const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
5125
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4904
5126
  const providerBackend = backend;
4905
5127
  const providerModels = modelConfigs?.length ? buildModelConfigs(modelConfigs) : model ? [{ id: model, contextWindow: 2e5, source: "user" }] : [];
4906
5128
  const configWithProvider = addProvider(globalConfig, {
@@ -4919,9 +5141,9 @@ async function createServerHandle(config4) {
4919
5141
  configWithProvider.providers[configWithProvider.providers.length - 1].id,
4920
5142
  firstModelId
4921
5143
  );
4922
- await saveGlobalConfig(config4.mode ?? "production", finalConfig);
5144
+ await saveGlobalConfig(config3.mode ?? "production", finalConfig, config3.globalConfigPath);
4923
5145
  providerManager.setProviders(finalConfig.providers, finalConfig.defaultModelSelection ?? void 0);
4924
- config4.defaultModelSelection = finalConfig.defaultModelSelection;
5146
+ config3.defaultModelSelection = finalConfig.defaultModelSelection;
4925
5147
  const newProvider = finalConfig.providers[finalConfig.providers.length - 1];
4926
5148
  res.status(201).json({
4927
5149
  success: true,
@@ -4937,14 +5159,14 @@ async function createServerHandle(config4) {
4937
5159
  app.post("/api/init/config", async (req, res) => {
4938
5160
  const { workdir, visionFallback } = req.body;
4939
5161
  try {
4940
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-C2YDEF3N.js");
4941
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5162
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5163
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4942
5164
  const updatedConfig = {
4943
5165
  ...globalConfig,
4944
5166
  workspace: workdir ? { workdir } : globalConfig.workspace,
4945
5167
  visionFallback: visionFallback ?? globalConfig.visionFallback
4946
5168
  };
4947
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5169
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4948
5170
  res.json({ success: true });
4949
5171
  } catch (error) {
4950
5172
  res.status(500).json({
@@ -4965,20 +5187,20 @@ async function createServerHandle(config4) {
4965
5187
  });
4966
5188
  app.delete("/api/providers/:id", async (req, res) => {
4967
5189
  const { id } = req.params;
4968
- const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-C2YDEF3N.js");
4969
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5190
+ const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-GMQUPNBY.js");
5191
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4970
5192
  const updatedConfig = removeProvider(globalConfig, id);
4971
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5193
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4972
5194
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
4973
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5195
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
4974
5196
  res.json({ success: true });
4975
5197
  });
4976
5198
  app.patch("/api/providers/:id", async (req, res) => {
4977
5199
  const { id } = req.params;
4978
5200
  const { isLocal } = req.body;
4979
5201
  try {
4980
- const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-C2YDEF3N.js");
4981
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5202
+ const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-GMQUPNBY.js");
5203
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4982
5204
  const provider = globalConfig.providers.find((p) => p.id === id);
4983
5205
  if (!provider) {
4984
5206
  return res.status(404).json({ error: "Provider not found" });
@@ -4986,9 +5208,9 @@ async function createServerHandle(config4) {
4986
5208
  const updates = {};
4987
5209
  if (isLocal !== void 0) updates["isLocal"] = isLocal;
4988
5210
  const updatedConfig = updateProvider(globalConfig, id, updates);
4989
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5211
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4990
5212
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
4991
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5213
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
4992
5214
  res.json({ success: true, provider: updatedConfig.providers.find((p) => p.id === id) });
4993
5215
  } catch (error) {
4994
5216
  res.status(500).json({ error: error instanceof Error ? error.message : "Failed to update provider" });
@@ -5006,8 +5228,8 @@ async function createServerHandle(config4) {
5006
5228
  models: modelConfigs
5007
5229
  } = req.body;
5008
5230
  try {
5009
- const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-C2YDEF3N.js");
5010
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5231
+ const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-GMQUPNBY.js");
5232
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5011
5233
  const provider = globalConfig.providers.find((p) => p.id === id);
5012
5234
  if (!provider) {
5013
5235
  return res.status(404).json({ error: "Provider not found" });
@@ -5023,9 +5245,9 @@ async function createServerHandle(config4) {
5023
5245
  updates["models"] = buildModelConfigs(modelConfigs);
5024
5246
  }
5025
5247
  const updatedConfig = updateProvider(globalConfig, id, updates);
5026
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5248
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
5027
5249
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
5028
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5250
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
5029
5251
  res.json({ success: true, provider: updatedConfig.providers.find((p) => p.id === id) });
5030
5252
  } catch (error) {
5031
5253
  res.status(500).json({ error: error instanceof Error ? error.message : "Failed to update provider" });
@@ -5044,10 +5266,10 @@ async function createServerHandle(config4) {
5044
5266
  return res.status(400).json({ error: result.error });
5045
5267
  }
5046
5268
  const llmClient = getLLMClient();
5047
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-C2YDEF3N.js");
5048
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5269
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
5270
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5049
5271
  const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
5050
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5272
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
5051
5273
  res.json({
5052
5274
  success: true,
5053
5275
  activeProviderId: id,
@@ -5071,7 +5293,7 @@ async function createServerHandle(config4) {
5071
5293
  });
5072
5294
  async function rebuildMcpTools() {
5073
5295
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
5074
- const { setMcpTools: setMcpTools2 } = await import("./tools-YJLXW3QS.js");
5296
+ const { setMcpTools: setMcpTools2 } = await import("./tools-WGAZKL56.js");
5075
5297
  const mcpTools = createMcpTools2(mcpManager);
5076
5298
  setMcpTools2(mcpTools);
5077
5299
  }
@@ -5133,13 +5355,17 @@ async function createServerHandle(config4) {
5133
5355
  };
5134
5356
  await mcpManager.addServer(name, serverCfg);
5135
5357
  const server = mcpManager.getServer(name);
5136
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-C2YDEF3N.js");
5137
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5358
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5359
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5138
5360
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {}, [name]: serverCfg };
5139
- await saveGlobalConfig(config4.mode ?? "production", {
5140
- ...globalConfig,
5141
- mcpServers: updatedMcpServers
5142
- });
5361
+ await saveGlobalConfig(
5362
+ config3.mode ?? "production",
5363
+ {
5364
+ ...globalConfig,
5365
+ mcpServers: updatedMcpServers
5366
+ },
5367
+ config3.globalConfigPath
5368
+ );
5143
5369
  await rebuildMcpTools();
5144
5370
  if (server) {
5145
5371
  const sessions = sessionManager.listSessions();
@@ -5159,14 +5385,18 @@ async function createServerHandle(config4) {
5159
5385
  return res.status(404).json({ error: `MCP server '${name}' not found` });
5160
5386
  }
5161
5387
  mcpManager.removeServer(name);
5162
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-C2YDEF3N.js");
5163
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5388
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5389
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5164
5390
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {} };
5165
5391
  delete updatedMcpServers[name];
5166
- await saveGlobalConfig(config4.mode ?? "production", {
5167
- ...globalConfig,
5168
- mcpServers: updatedMcpServers
5169
- });
5392
+ await saveGlobalConfig(
5393
+ config3.mode ?? "production",
5394
+ {
5395
+ ...globalConfig,
5396
+ mcpServers: updatedMcpServers
5397
+ },
5398
+ config3.globalConfigPath
5399
+ );
5170
5400
  await rebuildMcpTools();
5171
5401
  const sessions = sessionManager.listSessions();
5172
5402
  for (const s of sessions) {
@@ -5184,18 +5414,22 @@ async function createServerHandle(config4) {
5184
5414
  await mcpManager.setToolEnabled(name, toolName, enabled);
5185
5415
  const server = mcpManager.getServer(name);
5186
5416
  if (server) {
5187
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-C2YDEF3N.js");
5188
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5417
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5418
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5189
5419
  const mcpServers2 = { ...globalConfig.mcpServers ?? {} };
5190
5420
  const serverCfg = mcpServers2[name];
5191
5421
  if (serverCfg) {
5192
5422
  const disabledTools = server.tools.filter((t) => !t.enabled).map((t) => t.name);
5193
5423
  const cfg = { ...serverCfg, ...disabledTools.length > 0 ? { disabledTools } : { disabledTools: void 0 } };
5194
5424
  mcpServers2[name] = cfg;
5195
- await saveGlobalConfig(config4.mode ?? "production", {
5196
- ...globalConfig,
5197
- mcpServers: mcpServers2
5198
- });
5425
+ await saveGlobalConfig(
5426
+ config3.mode ?? "production",
5427
+ {
5428
+ ...globalConfig,
5429
+ mcpServers: mcpServers2
5430
+ },
5431
+ config3.globalConfigPath
5432
+ );
5199
5433
  }
5200
5434
  }
5201
5435
  await rebuildMcpTools();
@@ -5208,11 +5442,11 @@ async function createServerHandle(config4) {
5208
5442
  res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
5209
5443
  }
5210
5444
  });
5211
- const projectDir = config4.workdir;
5445
+ const projectDir = config3.workdir;
5212
5446
  app.use("/api/skills", createSkillRoutes(configDir, projectDir));
5213
5447
  app.use("/api/commands", createCommandRoutes(configDir, projectDir));
5214
5448
  app.use("/api/agents", createAgentRoutes(configDir, projectDir));
5215
- app.use("/api/workflows", createWorkflowRoutes(configDir, config4, projectDir));
5449
+ app.use("/api/workflows", createWorkflowRoutes(configDir, config3, projectDir));
5216
5450
  app.use("/api/dev-server", createDevServerRoutes());
5217
5451
  app.use("/api/terminals", createTerminalRoutes());
5218
5452
  app.use(
@@ -5230,13 +5464,13 @@ async function createServerHandle(config4) {
5230
5464
  })
5231
5465
  );
5232
5466
  app.get("/api/sessions/:id/background-processes", async (req, res) => {
5233
- const { getSessionProcesses } = await import("./manager-CZOVNTSN.js");
5467
+ const { getSessionProcesses } = await import("./manager-344C5JLZ.js");
5234
5468
  const sessionId = req.params.id;
5235
5469
  const processes = getSessionProcesses(sessionId);
5236
5470
  res.json({ processes });
5237
5471
  });
5238
5472
  app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
5239
- const { stopProcess } = await import("./manager-CZOVNTSN.js");
5473
+ const { stopProcess } = await import("./manager-344C5JLZ.js");
5240
5474
  const sessionId = req.params.id;
5241
5475
  const processId = req.params.processId;
5242
5476
  const session = sessionManager.getSession(sessionId);
@@ -5250,20 +5484,20 @@ async function createServerHandle(config4) {
5250
5484
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to stop process" });
5251
5485
  }
5252
5486
  });
5253
- const { getCurrentBranch } = await import("./branch.api-5DMEAIBI.js");
5487
+ const { getCurrentBranch } = await import("./branch.api-LAN42BA5.js");
5254
5488
  app.get("/api/branch", async (req, res) => {
5255
5489
  await getCurrentBranch(req, res);
5256
5490
  });
5257
5491
  app.use("/api/directories", createDirectoryRoutes());
5258
5492
  app.use("/api/files", createFileSearchRoutes());
5259
- const webDir = resolve3(__dirname3, "../../web");
5260
- const isDev = config4.mode === "development";
5493
+ const webDir = resolve4(__dirname3, "../../web");
5494
+ const isDev = config3.mode === "development";
5261
5495
  let viteServer;
5262
5496
  if (isDev) {
5263
5497
  logger.info("Dev mode: using Vite middleware");
5264
5498
  viteServer = await createViteServer({
5265
5499
  root: webDir,
5266
- configFile: resolve3(__dirname3, "../../web/vite.config.ts"),
5500
+ configFile: resolve4(__dirname3, "../../web/vite.config.ts"),
5267
5501
  server: { middlewareMode: true },
5268
5502
  appType: "spa",
5269
5503
  logLevel: "warn"
@@ -5283,7 +5517,7 @@ async function createServerHandle(config4) {
5283
5517
  }
5284
5518
  });
5285
5519
  app.get("/fox.svg", (_req, res) => {
5286
- readFile(join5(webDir, "fox.svg")).then((content) => {
5520
+ readFile2(join7(webDir, "fox.svg")).then((content) => {
5287
5521
  res.set("Content-Type", "image/svg+xml");
5288
5522
  res.send(content);
5289
5523
  }).catch(() => {
@@ -5292,7 +5526,7 @@ async function createServerHandle(config4) {
5292
5526
  });
5293
5527
  app.use(
5294
5528
  "/sounds",
5295
- express.static(join5(webDir, "public", "sounds"), {
5529
+ express.static(join7(webDir, "public", "sounds"), {
5296
5530
  setHeaders: (res) => {
5297
5531
  res.set("Content-Type", "audio/mpeg");
5298
5532
  }
@@ -5301,24 +5535,24 @@ async function createServerHandle(config4) {
5301
5535
  app.use("/__inspect__.js", (_req, res) => {
5302
5536
  res.set("Access-Control-Allow-Origin", "*");
5303
5537
  res.set("Content-Type", "application/javascript");
5304
- readFile(join5(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5538
+ readFile2(join7(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5305
5539
  });
5306
5540
  app.get("/*path", (req, res) => {
5307
5541
  if (req.path.startsWith("/api/")) {
5308
5542
  return;
5309
5543
  }
5310
- readFile(join5(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
5544
+ readFile2(join7(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
5311
5545
  logger.error("Error serving index.html", { error: err });
5312
5546
  res.status(500).send("Server error");
5313
5547
  });
5314
5548
  });
5315
- logger.info("Vite middleware ready", { port: config4.server.port });
5549
+ logger.info("Vite middleware ready", { port: config3.server.port });
5316
5550
  }
5317
5551
  if (!isDev) {
5318
- const distWebDir = resolve3(__dirname3, "web");
5552
+ const distWebDir = resolve4(__dirname3, "web");
5319
5553
  app.use(
5320
5554
  "/assets",
5321
- express.static(join5(distWebDir, "assets"), {
5555
+ express.static(join7(distWebDir, "assets"), {
5322
5556
  setHeaders: (res, filepath) => {
5323
5557
  if (filepath.endsWith(".css")) {
5324
5558
  res.set("Content-Type", "text/css");
@@ -5326,11 +5560,11 @@ async function createServerHandle(config4) {
5326
5560
  }
5327
5561
  })
5328
5562
  );
5329
- app.use("/manifest.webmanifest", express.static(join5(distWebDir, "manifest.webmanifest")));
5330
- app.use("/registerSW.js", express.static(join5(distWebDir, "registerSW.js")));
5331
- app.use("/sw.js", express.static(join5(distWebDir, "sw.js")));
5563
+ app.use("/manifest.webmanifest", express.static(join7(distWebDir, "manifest.webmanifest")));
5564
+ app.use("/registerSW.js", express.static(join7(distWebDir, "registerSW.js")));
5565
+ app.use("/sw.js", express.static(join7(distWebDir, "sw.js")));
5332
5566
  app.get("/fox.svg", (_req, res) => {
5333
- readFile(join5(distWebDir, "fox.svg")).then((content) => {
5567
+ readFile2(join7(distWebDir, "fox.svg")).then((content) => {
5334
5568
  res.set("Content-Type", "image/svg+xml");
5335
5569
  res.send(content);
5336
5570
  }).catch(() => {
@@ -5339,7 +5573,7 @@ async function createServerHandle(config4) {
5339
5573
  });
5340
5574
  app.use(
5341
5575
  "/sounds",
5342
- express.static(join5(distWebDir, "sounds"), {
5576
+ express.static(join7(distWebDir, "sounds"), {
5343
5577
  setHeaders: (res) => {
5344
5578
  res.set("Content-Type", "audio/mpeg");
5345
5579
  }
@@ -5348,10 +5582,10 @@ async function createServerHandle(config4) {
5348
5582
  app.use("/__inspect__.js", (_req, res) => {
5349
5583
  res.set("Access-Control-Allow-Origin", "*");
5350
5584
  res.set("Content-Type", "application/javascript");
5351
- readFile(join5(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5585
+ readFile2(join7(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5352
5586
  });
5353
5587
  app.get("/", (_req, res) => {
5354
- readFile(join5(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5588
+ readFile2(join7(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5355
5589
  res.status(404).send("Web UI not built. Run `npm run build:web`");
5356
5590
  });
5357
5591
  });
@@ -5359,7 +5593,7 @@ async function createServerHandle(config4) {
5359
5593
  if (req.path.startsWith("/api/") || req.path.startsWith("/assets/") || req.path.startsWith("/sounds/") || req.path.startsWith("/manifest.webmanifest") || req.path.startsWith("/registerSW.js") || req.path.startsWith("/sw.js") || req.path === "/fox.svg") {
5360
5594
  return;
5361
5595
  }
5362
- readFile(join5(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5596
+ readFile2(join7(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5363
5597
  res.status(404).send("Web UI not built");
5364
5598
  });
5365
5599
  });
@@ -5367,7 +5601,7 @@ async function createServerHandle(config4) {
5367
5601
  const httpServer = createHttpServer(app);
5368
5602
  const wssExports = createWebSocketServer(
5369
5603
  httpServer,
5370
- config4,
5604
+ config3,
5371
5605
  getLLMClient,
5372
5606
  () => providerManager.getActiveProvider(),
5373
5607
  sessionManager,
@@ -5379,7 +5613,7 @@ async function createServerHandle(config4) {
5379
5613
  const state = sessionManager.getContextState(sessionId);
5380
5614
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
5381
5615
  });
5382
- const { QueueProcessor } = await import("./processor-2YJ33KUH.js");
5616
+ const { QueueProcessor } = await import("./processor-PKKTNKWY.js");
5383
5617
  const queueProcessor = new QueueProcessor({
5384
5618
  sessionManager,
5385
5619
  providerManager,
@@ -5400,42 +5634,47 @@ async function createServerHandle(config4) {
5400
5634
  };
5401
5635
  return {
5402
5636
  httpServer,
5403
- ctx: { config: config4, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
5404
- start: (port) => new Promise((resolve4, reject) => {
5405
- const listenPort = port ?? config4.server.port;
5406
- const host = config4.server.host;
5637
+ ctx: { config: config3, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
5638
+ start: (port) => new Promise((resolve5, reject) => {
5639
+ const listenPort = port ?? config3.server.port;
5640
+ const host = config3.server.host;
5407
5641
  httpServer.listen(listenPort, host, () => {
5408
5642
  const addr = httpServer.address();
5409
5643
  const actualPort = typeof addr === "object" && addr ? addr.port : listenPort;
5410
5644
  const client = getLLMClient();
5411
5645
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
5412
5646
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
5413
- logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config4.llm.baseUrl}`);
5414
- resolve4({ port: actualPort });
5647
+ logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config3.llm.baseUrl}`);
5648
+ resolve5({ port: actualPort });
5415
5649
  });
5416
5650
  httpServer.on("error", reject);
5417
5651
  }),
5418
- close: () => new Promise((resolve4) => {
5652
+ close: () => new Promise((resolve5) => {
5419
5653
  logger.info("Shutting down...");
5420
5654
  void (async () => {
5421
5655
  await devServerManager.stopAll();
5422
5656
  await mcpManager.disconnectAll();
5423
5657
  const { stopAllInspectProxies } = await import("./inspect-proxy-BV25JERQ.js");
5424
5658
  stopAllInspectProxies();
5425
- const { cleanupAllProcesses } = await import("./store-NS2RMRA7.js");
5659
+ const { cleanupAllProcesses } = await import("./store-FXTCHBI4.js");
5426
5660
  cleanupAllProcesses();
5427
5661
  viteServer?.close();
5662
+ if (config3.globalConfigPath) {
5663
+ const { unlink: unlink2 } = await import("fs/promises");
5664
+ unlink2(config3.globalConfigPath).catch(() => {
5665
+ });
5666
+ }
5428
5667
  for (const client of wss.clients) {
5429
5668
  client.terminate();
5430
5669
  }
5431
5670
  wss.close();
5432
- httpServer.close(() => resolve4());
5671
+ httpServer.close(() => resolve5());
5433
5672
  })();
5434
5673
  })
5435
5674
  };
5436
5675
  }
5437
- async function createServer(config4) {
5438
- const handle = await createServerHandle(config4);
5676
+ async function createServer(config3) {
5677
+ const handle = await createServerHandle(config3);
5439
5678
  await handle.start();
5440
5679
  const shutdown = () => {
5441
5680
  const forceExitTimer = setTimeout(() => {
@@ -5454,4 +5693,4 @@ export {
5454
5693
  createServerHandle,
5455
5694
  createServer
5456
5695
  };
5457
- //# sourceMappingURL=chunk-UDZNMYWN.js.map
5696
+ //# sourceMappingURL=chunk-DEWNWF2P.js.map