openfox 2.0.59 → 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.
@@ -21,12 +21,13 @@ import {
21
21
  tokenFromPassword,
22
22
  verifyPassword,
23
23
  workflowExists
24
- } from "./chunk-5MDIKIMG.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,
@@ -61,8 +63,10 @@ import {
61
63
  setMcpManagerForTools,
62
64
  setMcpTools,
63
65
  setNotifyMcpServersChanged,
64
- skillExists
65
- } from "./chunk-FRU2X3IZ.js";
66
+ setSkillEnabled,
67
+ skillExists,
68
+ updateOwnedSkill
69
+ } from "./chunk-3JRYK5UG.js";
66
70
  import {
67
71
  getPathSeparator,
68
72
  isAbsolutePath
@@ -76,6 +80,11 @@ import {
76
80
  import {
77
81
  EventEmitter
78
82
  } from "./chunk-EU3WWTFH.js";
83
+ import {
84
+ deleteSetting,
85
+ getSetting,
86
+ setSetting
87
+ } from "./chunk-WNSAJCWT.js";
79
88
  import {
80
89
  getProject
81
90
  } from "./chunk-YQ3SOPBI.js";
@@ -150,8 +159,8 @@ import express from "express";
150
159
  import cors from "cors";
151
160
  import { createServer as createHttpServer } from "http";
152
161
  import { fileURLToPath as fileURLToPath5 } from "url";
153
- import { dirname as dirname5, resolve as resolve3, join as join5 } from "path";
154
- 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";
155
164
  import { createServer as createViteServer } from "vite";
156
165
 
157
166
  // src/server/llm/mock.ts
@@ -1426,12 +1435,12 @@ var McpManager = class {
1426
1435
  this.onServersChanged = options?.onServersChanged;
1427
1436
  this.onToolsDiscovered = options?.onToolsDiscovered;
1428
1437
  }
1429
- async addServer(name, config4) {
1438
+ async addServer(name, config3) {
1430
1439
  if (this.servers.has(name)) {
1431
1440
  throw new Error(`MCP server '${name}' already exists`);
1432
1441
  }
1433
- const state = { name, config: config4, status: "disconnected", tools: [], estimatedTokens: 0 };
1434
- 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 });
1435
1444
  await this.connectServer(name);
1436
1445
  }
1437
1446
  removeServer(name) {
@@ -1678,10 +1687,10 @@ var LspServer = class {
1678
1687
  // Pending diagnostic waiters
1679
1688
  pendingDiagnostics = /* @__PURE__ */ new Map();
1680
1689
  commandPath;
1681
- constructor(config4, workdir, commandPath) {
1682
- this.config = config4;
1690
+ constructor(config3, workdir, commandPath) {
1691
+ this.config = config3;
1683
1692
  this.workdir = workdir;
1684
- this.commandPath = commandPath ?? config4.serverCommand;
1693
+ this.commandPath = commandPath ?? config3.serverCommand;
1685
1694
  }
1686
1695
  // ============================================================================
1687
1696
  // Lifecycle
@@ -1914,19 +1923,19 @@ var LspServer = class {
1914
1923
  */
1915
1924
  async getDiagnosticsWithWait(path, timeoutMs = DIAGNOSTIC_WAIT_MS) {
1916
1925
  if (this.openDocuments.has(path)) {
1917
- return new Promise((resolve4) => {
1926
+ return new Promise((resolve5) => {
1918
1927
  const existing = this.diagnostics.get(path);
1919
1928
  if (existing !== void 0) {
1920
1929
  setTimeout(() => {
1921
- resolve4(this.diagnostics.get(path) ?? []);
1930
+ resolve5(this.diagnostics.get(path) ?? []);
1922
1931
  }, 100);
1923
1932
  return;
1924
1933
  }
1925
1934
  const timeout = setTimeout(() => {
1926
1935
  this.pendingDiagnostics.delete(path);
1927
- resolve4(this.diagnostics.get(path) ?? []);
1936
+ resolve5(this.diagnostics.get(path) ?? []);
1928
1937
  }, timeoutMs);
1929
- this.pendingDiagnostics.set(path, { resolve: resolve4, timeout });
1938
+ this.pendingDiagnostics.set(path, { resolve: resolve5, timeout });
1930
1939
  });
1931
1940
  }
1932
1941
  return this.diagnostics.get(path) ?? [];
@@ -2238,8 +2247,8 @@ var LspManager = class {
2238
2247
  // ============================================================================
2239
2248
  // Server Management
2240
2249
  // ============================================================================
2241
- async getOrCreateServer(config4) {
2242
- const langId = config4.id;
2250
+ async getOrCreateServer(config3) {
2251
+ const langId = config3.id;
2243
2252
  const existing = this.servers.get(langId);
2244
2253
  if (existing?.isRunning()) {
2245
2254
  return existing;
@@ -2251,7 +2260,7 @@ var LspManager = class {
2251
2260
  if (pending) {
2252
2261
  return pending;
2253
2262
  }
2254
- const promise = this.startServer(config4);
2263
+ const promise = this.startServer(config3);
2255
2264
  this.serverPromises.set(langId, promise);
2256
2265
  try {
2257
2266
  const server = await promise;
@@ -2260,19 +2269,19 @@ var LspManager = class {
2260
2269
  this.serverPromises.delete(langId);
2261
2270
  }
2262
2271
  }
2263
- async startServer(config4) {
2264
- const langId = config4.id;
2265
- 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);
2266
2275
  if (!commandPath) {
2267
2276
  logger.warn("LSP server not installed, skipping", {
2268
2277
  language: langId,
2269
- command: config4.serverCommand,
2278
+ command: config3.serverCommand,
2270
2279
  sessionId: this.sessionId
2271
2280
  });
2272
2281
  this.unavailableServers.add(langId);
2273
2282
  return null;
2274
2283
  }
2275
- const server = new LspServer(config4, this.workdir, commandPath);
2284
+ const server = new LspServer(config3, this.workdir, commandPath);
2276
2285
  try {
2277
2286
  await server.start();
2278
2287
  this.servers.set(langId, server);
@@ -2292,11 +2301,11 @@ var LspManager = class {
2292
2301
  }
2293
2302
  }
2294
2303
  async getServerForFile(path) {
2295
- const config4 = detectLanguage(path);
2296
- if (!config4) {
2304
+ const config3 = detectLanguage(path);
2305
+ if (!config3) {
2297
2306
  return null;
2298
2307
  }
2299
- return this.getOrCreateServer(config4);
2308
+ return this.getOrCreateServer(config3);
2300
2309
  }
2301
2310
  // ============================================================================
2302
2311
  // Public Interface
@@ -2327,11 +2336,11 @@ var LspManager = class {
2327
2336
  * Get current diagnostics for a file without triggering a change.
2328
2337
  */
2329
2338
  getDiagnostics(path) {
2330
- const config4 = detectLanguage(path);
2331
- if (!config4) {
2339
+ const config3 = detectLanguage(path);
2340
+ if (!config3) {
2332
2341
  return [];
2333
2342
  }
2334
- const server = this.servers.get(config4.id);
2343
+ const server = this.servers.get(config3.id);
2335
2344
  if (!server?.isRunning()) {
2336
2345
  return [];
2337
2346
  }
@@ -2342,11 +2351,11 @@ var LspManager = class {
2342
2351
  * Returns true if we have or can start a server for this file type.
2343
2352
  */
2344
2353
  isAvailableFor(path) {
2345
- const config4 = detectLanguage(path);
2346
- if (!config4) {
2354
+ const config3 = detectLanguage(path);
2355
+ if (!config3) {
2347
2356
  return false;
2348
2357
  }
2349
- if (this.unavailableServers.has(config4.id)) {
2358
+ if (this.unavailableServers.has(config3.id)) {
2350
2359
  return false;
2351
2360
  }
2352
2361
  return true;
@@ -2357,13 +2366,13 @@ var LspManager = class {
2357
2366
  * to avoid spamming the user on every edit.
2358
2367
  */
2359
2368
  getInstallHint(path) {
2360
- const config4 = detectLanguage(path);
2361
- if (!config4?.installHint) {
2369
+ const config3 = detectLanguage(path);
2370
+ if (!config3?.installHint) {
2362
2371
  return null;
2363
2372
  }
2364
- if (this.unavailableServers.has(config4.id) && !this.dismissedHints.has(config4.id)) {
2365
- this.dismissedHints.add(config4.id);
2366
- 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;
2367
2376
  }
2368
2377
  return null;
2369
2378
  }
@@ -3243,9 +3252,77 @@ var SessionManager = class {
3243
3252
  }
3244
3253
  };
3245
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
+
3246
3323
  // src/server/routes/crud-helpers.ts
3247
3324
  import { Router } from "express";
3248
- import { join as join2 } from "path";
3325
+ import { join as join3 } from "path";
3249
3326
  function computeOverrideIds(defaults, userItems) {
3250
3327
  return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
3251
3328
  }
@@ -3257,34 +3334,34 @@ function validateNameIdPrompt(body) {
3257
3334
  return null;
3258
3335
  }
3259
3336
  function getProjectItemPath(projectDir, dirName, id, ext) {
3260
- return join2(projectDir, ".openfox", dirName, `${id}${ext}`);
3337
+ return join3(projectDir, ".openfox", dirName, `${id}${ext}`);
3261
3338
  }
3262
3339
  async function isProjectItem(projectDir, dirName, id, ext) {
3263
3340
  if (!projectDir) return false;
3264
3341
  return pathExists(getProjectItemPath(projectDir, dirName, id, ext));
3265
3342
  }
3266
- function createCrudRoutes(config4, configDir, projectDir) {
3343
+ function createCrudRoutes(config3, configDir, projectDir) {
3267
3344
  const router = Router();
3268
3345
  router.get("/", async (_req, res) => {
3269
3346
  const [defaults, userItems, projectItems] = await Promise.all([
3270
- config4.loadDefaults(),
3271
- config4.loadUser(configDir),
3272
- projectDir ? config4.loadProject(projectDir) : []
3347
+ config3.loadDefaults(),
3348
+ config3.loadUser(configDir),
3349
+ projectDir ? config3.loadProject(projectDir) : []
3273
3350
  ]);
3274
3351
  const userOverrideIds = computeOverrideIds(defaults, userItems);
3275
3352
  const projectOverrideIds = computeOverrideIds(defaults, projectItems);
3276
- const extra = config4.extraGetData ? await config4.extraGetData() : {};
3353
+ const extra = config3.extraGetData ? await config3.extraGetData() : {};
3277
3354
  res.json({
3278
- defaults: defaults.map(config4.mapToResponse),
3279
- userItems: userItems.map(config4.mapToResponse),
3280
- projectItems: projectItems.map(config4.mapToResponse),
3355
+ defaults: defaults.map(config3.mapToResponse),
3356
+ userItems: userItems.map(config3.mapToResponse),
3357
+ projectItems: projectItems.map(config3.mapToResponse),
3281
3358
  overrideIds: [...userOverrideIds, ...projectOverrideIds],
3282
3359
  ...extra
3283
3360
  });
3284
3361
  });
3285
3362
  router.get("/defaults/:id", async (req, res) => {
3286
3363
  const { id } = req.params;
3287
- const allDefaults = await config4.loadDefaults();
3364
+ const allDefaults = await config3.loadDefaults();
3288
3365
  const item = allDefaults.find((d) => d.metadata.id === id);
3289
3366
  if (!item) {
3290
3367
  return res.status(404).json({ error: "Default not found" });
@@ -3292,13 +3369,13 @@ function createCrudRoutes(config4, configDir, projectDir) {
3292
3369
  res.json(item);
3293
3370
  });
3294
3371
  router.get("/default-ids", async (_req, res) => {
3295
- const ids = config4.getDefaultIds ? await config4.getDefaultIds() : [];
3372
+ const ids = config3.getDefaultIds ? await config3.getDefaultIds() : [];
3296
3373
  res.json({ ids });
3297
3374
  });
3298
3375
  router.get("/:id", async (req, res) => {
3299
3376
  const { id } = req.params;
3300
- const items = await config4.loadAll(configDir, projectDir);
3301
- const item = config4.findById(id, items);
3377
+ const items = await config3.loadAll(configDir, projectDir);
3378
+ const item = config3.findById(id, items);
3302
3379
  if (!item) {
3303
3380
  return res.status(404).json({ error: "Not found" });
3304
3381
  }
@@ -3307,7 +3384,7 @@ function createCrudRoutes(config4, configDir, projectDir) {
3307
3384
  router.post("/", async (req, res) => {
3308
3385
  const body = req.body;
3309
3386
  const meta = body["metadata"];
3310
- const customError = config4.validateCreate?.(body);
3387
+ const customError = config3.validateCreate?.(body);
3311
3388
  if (!meta?.["id"] || customError) {
3312
3389
  return res.status(400).json({ error: customError ?? "Missing required fields" });
3313
3390
  }
@@ -3316,21 +3393,21 @@ function createCrudRoutes(config4, configDir, projectDir) {
3316
3393
  if (destination === "project" && !projectDir) {
3317
3394
  return res.status(400).json({ error: "No project directory configured" });
3318
3395
  }
3319
- const exists = await config4.exists(configDir, id, projectDir);
3396
+ const exists = await config3.exists(configDir, id, projectDir);
3320
3397
  if (exists) {
3321
3398
  return res.status(409).json({ error: "An item with this ID already exists" });
3322
3399
  }
3323
3400
  if (destination === "project") {
3324
- await config4.saveToProject(projectDir, body);
3401
+ await config3.saveToProject(projectDir, body);
3325
3402
  } else {
3326
- await config4.save(configDir, body);
3403
+ await config3.save(configDir, body);
3327
3404
  }
3328
3405
  res.status(201).json(body);
3329
3406
  });
3330
3407
  router.put("/:id", async (req, res) => {
3331
3408
  const { id } = req.params;
3332
- const items = await config4.loadAll(configDir, projectDir);
3333
- const existing = config4.findById(id, items);
3409
+ const items = await config3.loadAll(configDir, projectDir);
3410
+ const existing = config3.findById(id, items);
3334
3411
  if (!existing) {
3335
3412
  return res.status(404).json({ error: "Not found" });
3336
3413
  }
@@ -3341,29 +3418,29 @@ function createCrudRoutes(config4, configDir, projectDir) {
3341
3418
  ...body,
3342
3419
  metadata: { ...existing.metadata, ...meta, id }
3343
3420
  };
3344
- const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
3421
+ const isProject = await isProjectItem(projectDir, config3.dirName, id, config3.ext);
3345
3422
  if (isProject) {
3346
- await config4.saveToProject(projectDir, updated);
3423
+ await config3.saveToProject(projectDir, updated);
3347
3424
  } else {
3348
- await config4.save(configDir, updated);
3425
+ await config3.save(configDir, updated);
3349
3426
  }
3350
3427
  res.json(updated);
3351
3428
  });
3352
3429
  router.delete("/:id", async (req, res) => {
3353
3430
  const { id } = req.params;
3354
- const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
3431
+ const isProject = await isProjectItem(projectDir, config3.dirName, id, config3.ext);
3355
3432
  if (isProject) {
3356
- const result2 = await config4.deleteProject(projectDir, id);
3433
+ const result2 = await config3.deleteProject(projectDir, id);
3357
3434
  if (!result2.success) {
3358
3435
  return res.status(500).json({ error: "Failed to delete project item" });
3359
3436
  }
3360
3437
  return res.json({ success: true });
3361
3438
  }
3362
- const isDefault = await config4.isDefault(id);
3439
+ const isDefault = await config3.isDefault(id);
3363
3440
  if (isDefault) {
3364
3441
  return res.status(403).json({ error: "Cannot delete built-in defaults" });
3365
3442
  }
3366
- const result = await config4.delete(configDir, id);
3443
+ const result = await config3.delete(configDir, id);
3367
3444
  if (!result.success) {
3368
3445
  return res.status(403).json({ error: result.reason ?? "Cannot delete this item" });
3369
3446
  }
@@ -3371,8 +3448,8 @@ function createCrudRoutes(config4, configDir, projectDir) {
3371
3448
  });
3372
3449
  router.post("/:id/duplicate", async (req, res) => {
3373
3450
  const { id } = req.params;
3374
- const items = await config4.loadAll(configDir, projectDir);
3375
- const source = config4.findById(id, items);
3451
+ const items = await config3.loadAll(configDir, projectDir);
3452
+ const source = config3.findById(id, items);
3376
3453
  if (!source) {
3377
3454
  return res.status(404).json({ error: "Not found" });
3378
3455
  }
@@ -3384,56 +3461,195 @@ function createCrudRoutes(config4, configDir, projectDir) {
3384
3461
  const destination = req.body.destination ?? "user";
3385
3462
  if (destination === "project") {
3386
3463
  if (!projectDir) return res.status(400).json({ error: "No project directory configured" });
3387
- await config4.saveToProject(projectDir, duplicated);
3464
+ await config3.saveToProject(projectDir, duplicated);
3388
3465
  } else {
3389
- await config4.save(configDir, duplicated);
3466
+ await config3.save(configDir, duplicated);
3390
3467
  }
3391
3468
  res.status(201).json(duplicated);
3392
3469
  });
3393
- config4.extraRoutes?.(router);
3470
+ config3.extraRoutes?.(router);
3394
3471
  return router;
3395
3472
  }
3396
3473
 
3397
3474
  // src/server/routes/skills.ts
3398
- var config = {
3399
- dirName: "skills",
3400
- ext: ".skill.md",
3401
- loadDefaults: loadDefaultSkills,
3402
- loadUser: loadUserSkills,
3403
- loadProject: loadProjectSkills,
3404
- loadAll: loadAllSkills,
3405
- findById: findSkillById,
3406
- save: saveSkill,
3407
- saveToProject: saveSkillToProject,
3408
- delete: deleteSkill,
3409
- deleteProject: deleteProjectSkill,
3410
- exists: skillExists,
3411
- isDefault: isDefaultSkill,
3412
- getDefaultIds: getDefaultSkillIds,
3413
- validateCreate: validateNameIdPrompt,
3414
- mapToResponse: (s) => ({
3415
- ...s.metadata,
3416
- enabled: isSkillEnabled(s.metadata.id)
3417
- })
3418
- };
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
+ }
3419
3567
  function createSkillRoutes(configDir, projectDir) {
3420
- 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;
3421
3637
  }
3422
3638
 
3423
3639
  // src/server/commands/registry.ts
3424
- import { writeFile, mkdir, unlink } from "fs/promises";
3425
- 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";
3426
3642
  import { fileURLToPath as fileURLToPath4 } from "url";
3427
- import matter from "gray-matter";
3428
- var __bundleDir = dirname3(fileURLToPath4(import.meta.url));
3429
- var DEFAULTS_DIR = join3(__bundleDir, "defaults");
3430
- 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");
3431
3647
  var COMMAND_EXTENSION = ".command.md";
3432
3648
  function getCommandsDir(configDir) {
3433
- return join3(configDir, "commands");
3649
+ return join5(configDir, "commands");
3434
3650
  }
3435
3651
  function getProjectCommandsDir(projectDir) {
3436
- return join3(projectDir, ".openfox", "commands");
3652
+ return join5(projectDir, ".openfox", "commands");
3437
3653
  }
3438
3654
  async function loadDefaultCommands() {
3439
3655
  let defaults = await loadItemsFromDir(DEFAULTS_DIR, {
@@ -3490,26 +3706,26 @@ function findCommandById(commandId, commands) {
3490
3706
  return commands.find((c) => c.metadata.id === commandId);
3491
3707
  }
3492
3708
  async function commandExists(configDir, commandId, projectDir) {
3493
- if (await pathExists(join3(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
3494
- 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}`)))
3495
3711
  return true;
3496
3712
  return false;
3497
3713
  }
3498
3714
  async function saveCommand(configDir, command) {
3499
3715
  const commandsDir = getCommandsDir(configDir);
3500
3716
  if (!await pathExists(commandsDir)) {
3501
- await mkdir(commandsDir, { recursive: true });
3717
+ await mkdir3(commandsDir, { recursive: true });
3502
3718
  }
3503
- const filePath = join3(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
3504
- const content = matter.stringify(command.prompt, command.metadata);
3505
- 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");
3506
3722
  }
3507
3723
  async function saveCommandToProject(projectDir, command) {
3508
3724
  await saveItemToDir(
3509
3725
  getProjectCommandsDir(projectDir),
3510
3726
  command,
3511
3727
  COMMAND_EXTENSION,
3512
- (c) => matter.stringify(c.prompt, c.metadata)
3728
+ (c) => matter2.stringify(c.prompt, c.metadata)
3513
3729
  );
3514
3730
  }
3515
3731
  async function deleteProjectCommand(projectDir, commandId) {
@@ -3520,7 +3736,7 @@ async function deleteCommand(configDir, commandId) {
3520
3736
  if (isDefault) {
3521
3737
  return { success: false, reason: "Cannot delete built-in defaults" };
3522
3738
  }
3523
- const filePath = join3(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3739
+ const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3524
3740
  try {
3525
3741
  await unlink(filePath);
3526
3742
  return { success: true };
@@ -3530,7 +3746,7 @@ async function deleteCommand(configDir, commandId) {
3530
3746
  }
3531
3747
 
3532
3748
  // src/server/routes/commands.ts
3533
- var config2 = {
3749
+ var config = {
3534
3750
  dirName: "commands",
3535
3751
  ext: ".command.md",
3536
3752
  loadDefaults: loadDefaultCommands,
@@ -3549,11 +3765,11 @@ var config2 = {
3549
3765
  mapToResponse: (c) => c.metadata
3550
3766
  };
3551
3767
  function createCommandRoutes(configDir, projectDir) {
3552
- return createCrudRoutes(config2, configDir, projectDir);
3768
+ return createCrudRoutes(config, configDir, projectDir);
3553
3769
  }
3554
3770
 
3555
3771
  // src/server/routes/agents.ts
3556
- var config3 = {
3772
+ var config2 = {
3557
3773
  dirName: "agents",
3558
3774
  ext: ".agent.md",
3559
3775
  loadDefaults: loadDefaultAgents,
@@ -3576,12 +3792,12 @@ var config3 = {
3576
3792
  mapToResponse: (a) => a.metadata
3577
3793
  };
3578
3794
  function createAgentRoutes(configDir, projectDir) {
3579
- return createCrudRoutes(config3, configDir, projectDir);
3795
+ return createCrudRoutes(config2, configDir, projectDir);
3580
3796
  }
3581
3797
 
3582
3798
  // src/server/routes/workflows.ts
3583
3799
  import "express";
3584
- function createWorkflowRoutes(configDir, config4, projectDir) {
3800
+ function createWorkflowRoutes(configDir, config3, projectDir) {
3585
3801
  const crudConfig = {
3586
3802
  dirName: "workflows",
3587
3803
  ext: ".workflow.json",
@@ -3610,7 +3826,7 @@ function createWorkflowRoutes(configDir, config4, projectDir) {
3610
3826
  subGroups: subGroups.length > 0 ? subGroups : void 0
3611
3827
  };
3612
3828
  },
3613
- extraGetData: () => Promise.resolve({ activeWorkflowId: config4.activeWorkflowId ?? "default" }),
3829
+ extraGetData: () => Promise.resolve({ activeWorkflowId: config3.activeWorkflowId ?? "default" }),
3614
3830
  extraRoutes: (router) => {
3615
3831
  router.get("/template-variables", (_req, res) => {
3616
3832
  res.json({ variables: TEMPLATE_VARIABLES });
@@ -3621,19 +3837,19 @@ function createWorkflowRoutes(configDir, config4, projectDir) {
3621
3837
  }
3622
3838
 
3623
3839
  // src/server/routes/dev-server.ts
3624
- import { Router as Router3 } from "express";
3840
+ import { Router as Router4 } from "express";
3625
3841
  function createDevServerRoutes() {
3626
- const router = Router3();
3842
+ const router = Router4();
3627
3843
  router.get("/", async (req, res) => {
3628
3844
  const workdir = req.query["workdir"];
3629
3845
  if (!workdir) return res.status(400).json({ error: "workdir required" });
3630
3846
  const status = devServerManager.getStatus(workdir);
3631
3847
  if (!status.config) {
3632
- const config4 = await devServerManager.loadConfig(workdir);
3633
- if (config4) {
3634
- status.config = config4;
3635
- status.url = config4.url;
3636
- 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;
3637
3853
  }
3638
3854
  }
3639
3855
  res.json(status);
@@ -3679,8 +3895,8 @@ function createDevServerRoutes() {
3679
3895
  router.get("/config", async (req, res) => {
3680
3896
  const workdir = req.query["workdir"];
3681
3897
  if (!workdir) return res.status(400).json({ error: "workdir required" });
3682
- const config4 = await devServerManager.loadConfig(workdir);
3683
- res.json({ config: config4 });
3898
+ const config3 = await devServerManager.loadConfig(workdir);
3899
+ res.json({ config: config3 });
3684
3900
  });
3685
3901
  router.post("/config", async (req, res) => {
3686
3902
  const workdir = req.query["workdir"];
@@ -3690,9 +3906,9 @@ function createDevServerRoutes() {
3690
3906
  return res.status(400).json({ error: "command and url are required" });
3691
3907
  }
3692
3908
  try {
3693
- const config4 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
3694
- await devServerManager.saveConfig(workdir, config4);
3695
- 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 });
3696
3912
  } catch (err) {
3697
3913
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
3698
3914
  }
@@ -3701,9 +3917,9 @@ function createDevServerRoutes() {
3701
3917
  }
3702
3918
 
3703
3919
  // src/server/routes/terminals.ts
3704
- import { Router as Router4 } from "express";
3920
+ import { Router as Router5 } from "express";
3705
3921
  function createTerminalRoutes() {
3706
- const router = Router4();
3922
+ const router = Router5();
3707
3923
  router.get("/", (req, res) => {
3708
3924
  const projectId = req.query["projectId"];
3709
3925
  const sessions = projectId ? terminalManager.getByProject(projectId) : [];
@@ -3742,22 +3958,22 @@ function createTerminalRoutes() {
3742
3958
  }
3743
3959
 
3744
3960
  // src/server/routes/directories.ts
3745
- import { Router as Router5 } from "express";
3961
+ import { Router as Router6 } from "express";
3746
3962
  import { readdir } from "fs/promises";
3747
- 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";
3748
3964
  function createDirectoryRoutes() {
3749
- const router = Router5();
3965
+ const router = Router6();
3750
3966
  const DEFAULT_BASE_PATH = process.cwd();
3751
3967
  router.get("/", async (req, res) => {
3752
3968
  const path = req.query["path"] || DEFAULT_BASE_PATH;
3753
3969
  try {
3754
- const resolvedPath = resolve2(path);
3970
+ const resolvedPath = resolve3(path);
3755
3971
  const entries = await readdir(resolvedPath, { withFileTypes: true });
3756
3972
  const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
3757
3973
  name: entry.name,
3758
- path: join4(resolvedPath, entry.name)
3974
+ path: join6(resolvedPath, entry.name)
3759
3975
  })).sort((a, b) => a.name.localeCompare(b.name));
3760
- const parent = dirname4(resolvedPath);
3976
+ const parent = dirname5(resolvedPath);
3761
3977
  const hasParent = parent !== resolvedPath;
3762
3978
  res.json({
3763
3979
  current: resolvedPath,
@@ -3779,10 +3995,10 @@ function createDirectoryRoutes() {
3779
3995
  }
3780
3996
 
3781
3997
  // src/server/routes/file-search.ts
3782
- import { Router as Router6 } from "express";
3998
+ import { Router as Router7 } from "express";
3783
3999
  import fg from "fast-glob";
3784
4000
  function createFileSearchRoutes() {
3785
- const router = Router6();
4001
+ const router = Router7();
3786
4002
  router.get("/", async (req, res) => {
3787
4003
  const query = req.query["q"] || "";
3788
4004
  const workdir = req.query["workdir"] || process.cwd();
@@ -3858,11 +4074,11 @@ function fuzzyScore(filePath, query) {
3858
4074
  }
3859
4075
 
3860
4076
  // src/server/routes/auto-update.ts
3861
- import { Router as Router7 } from "express";
4077
+ import { Router as Router8 } from "express";
3862
4078
  import { spawn as spawn2 } from "child_process";
3863
4079
 
3864
4080
  // src/constants.ts
3865
- var VERSION = "2.0.59";
4081
+ var VERSION = "2.0.60";
3866
4082
 
3867
4083
  // src/server/routes/auto-update.ts
3868
4084
  var updateInProgress = false;
@@ -3880,12 +4096,12 @@ async function checkAuth(req, opts) {
3880
4096
  return true;
3881
4097
  }
3882
4098
  function createAutoUpdateRoutes(options = {}) {
3883
- const router = Router7();
4099
+ const router = Router8();
3884
4100
  router.get("/check", async (_req, res) => {
3885
4101
  const isService = isRunningAsService();
3886
4102
  const current = VERSION;
3887
4103
  try {
3888
- const latest = await new Promise((resolve4, reject) => {
4104
+ const latest = await new Promise((resolve5, reject) => {
3889
4105
  const child = spawn2("npm", ["view", "openfox", "version"], {
3890
4106
  stdio: ["ignore", "pipe", "pipe"],
3891
4107
  windowsHide: true
@@ -3896,7 +4112,7 @@ function createAutoUpdateRoutes(options = {}) {
3896
4112
  });
3897
4113
  child.on("close", (code) => {
3898
4114
  if (code === 0) {
3899
- resolve4(stdout.trim());
4115
+ resolve5(stdout.trim());
3900
4116
  } else {
3901
4117
  reject(new Error(`npm view exited with code ${code}`));
3902
4118
  }
@@ -3940,9 +4156,9 @@ function createAutoUpdateRoutes(options = {}) {
3940
4156
  const timeout = setTimeout(() => {
3941
4157
  child.kill();
3942
4158
  }, UPDATE_TIMEOUT);
3943
- const exitCode = await new Promise((resolve4) => {
3944
- child.on("close", resolve4);
3945
- child.on("error", () => resolve4(1));
4159
+ const exitCode = await new Promise((resolve5) => {
4160
+ child.on("close", resolve5);
4161
+ child.on("error", () => resolve5(1));
3946
4162
  });
3947
4163
  clearTimeout(timeout);
3948
4164
  if (exitCode === 0) {
@@ -3980,15 +4196,15 @@ function createAutoUpdateRoutes(options = {}) {
3980
4196
  }
3981
4197
 
3982
4198
  // src/server/index.ts
3983
- var __dirname3 = dirname5(fileURLToPath5(import.meta.url));
3984
- async function createServerHandle(config4) {
3985
- setRuntimeConfig(config4);
3986
- 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);
3987
4203
  await loadServerAuthConfig();
3988
- const db = initDatabase(config4);
4204
+ const db = initDatabase(config3);
3989
4205
  initEventStore(db);
3990
- const configDir = getGlobalConfigDir(config4.mode ?? "production");
3991
- const providerManager = createProviderManager(config4);
4206
+ const configDir = getGlobalConfigDir(config3.mode ?? "production");
4207
+ const providerManager = createProviderManager(config3);
3992
4208
  const sessionManager = new SessionManager(providerManager);
3993
4209
  devServerManager.setSessionManager(sessionManager);
3994
4210
  const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
@@ -3999,24 +4215,24 @@ async function createServerHandle(config4) {
3999
4215
  }
4000
4216
  async function initLLM() {
4001
4217
  const llmClient = getLLMClient();
4002
- const backend = config4.llm.backend;
4218
+ const backend = config3.llm.backend;
4003
4219
  llmClient.setBackend(backend);
4004
4220
  if (!useMock) {
4005
4221
  logger.info("Using configured LLM backend", { backend: getBackendDisplayName(backend) });
4006
4222
  }
4007
- const detected = await detectModel(config4.llm.baseUrl);
4008
- if (detected && !config4.defaultModelSelection) {
4223
+ const detected = await detectModel(config3.llm.baseUrl);
4224
+ if (detected && !config3.defaultModelSelection) {
4009
4225
  llmClient.setModel(detected);
4010
4226
  if (!useMock) {
4011
4227
  logger.info("Auto-detected LLM model", { model: detected, backend: getBackendDisplayName(backend) });
4012
4228
  }
4013
- } else if (detected && config4.defaultModelSelection) {
4229
+ } else if (detected && config3.defaultModelSelection) {
4014
4230
  if (!useMock) {
4015
- 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 });
4016
4232
  }
4017
4233
  } else {
4018
4234
  if (!useMock) {
4019
- 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 });
4020
4236
  }
4021
4237
  }
4022
4238
  const activeProvider = providerManager.getActiveProvider();
@@ -4037,14 +4253,14 @@ async function createServerHandle(config4) {
4037
4253
  onToolsDiscovered: async (name, tools) => {
4038
4254
  try {
4039
4255
  const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
4040
- const mode = config4.mode ?? "production";
4041
- const globalConfig = await loadGlobalConfig(mode, config4.globalConfigPath);
4256
+ const mode = config3.mode ?? "production";
4257
+ const globalConfig = await loadGlobalConfig(mode, config3.globalConfigPath);
4042
4258
  const mcpServers2 = {
4043
4259
  ...globalConfig.mcpServers ?? {}
4044
4260
  };
4045
4261
  if (mcpServers2[name]) {
4046
4262
  mcpServers2[name] = { ...mcpServers2[name], cachedTools: tools };
4047
- await saveGlobalConfig(mode, { ...globalConfig, mcpServers: mcpServers2 }, config4.globalConfigPath);
4263
+ await saveGlobalConfig(mode, { ...globalConfig, mcpServers: mcpServers2 }, config3.globalConfigPath);
4048
4264
  }
4049
4265
  } catch (err) {
4050
4266
  logger.warn("Failed to persist MCP tool cache", { name, error: String(err) });
@@ -4052,9 +4268,9 @@ async function createServerHandle(config4) {
4052
4268
  }
4053
4269
  });
4054
4270
  setMcpManagerForTools(mcpManager);
4055
- setMcpConfigMode(config4.mode ?? "production");
4056
- setMcpConfigPath(config4.globalConfigPath);
4057
- const mcpServers = config4.mcpServers ?? {};
4271
+ setMcpConfigMode(config3.mode ?? "production");
4272
+ setMcpConfigPath(config3.globalConfigPath);
4273
+ const mcpServers = config3.mcpServers ?? {};
4058
4274
  Promise.all(
4059
4275
  Object.entries(mcpServers).map(
4060
4276
  ([name, serverConfig]) => mcpManager.addServer(name, serverConfig).catch((err) => {
@@ -4067,7 +4283,7 @@ async function createServerHandle(config4) {
4067
4283
  setMcpTools(mcpTools);
4068
4284
  logger.info("MCP tools registered", { count: mcpTools.length });
4069
4285
  }
4070
- const { signalMcpReady } = await import("./server-KDGQZNYQ.js");
4286
+ const { signalMcpReady } = await import("./server-LMH7ZH5X.js");
4071
4287
  signalMcpReady();
4072
4288
  });
4073
4289
  const app = express();
@@ -4253,14 +4469,14 @@ async function createServerHandle(config4) {
4253
4469
  if (!project) {
4254
4470
  return res.status(404).json({ error: "Project not found" });
4255
4471
  }
4256
- const { providerId, model } = parseDefaultModelSelection(config4.defaultModelSelection);
4472
+ const { providerId, model } = parseDefaultModelSelection(config3.defaultModelSelection);
4257
4473
  const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
4258
4474
  res.status(201).json({ session });
4259
4475
  });
4260
4476
  app.get("/api/sessions/:id", async (req, res) => {
4261
4477
  const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4262
4478
  const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
4263
- const { getPendingQuestionsForSession } = await import("./tools-FQ54IAYG.js");
4479
+ const { getPendingQuestionsForSession } = await import("./tools-WGAZKL56.js");
4264
4480
  const session = sessionManager.getSession(req.params.id);
4265
4481
  if (!session) {
4266
4482
  return res.status(404).json({ error: "Session not found" });
@@ -4279,8 +4495,8 @@ async function createServerHandle(config4) {
4279
4495
  if (!session) {
4280
4496
  return res.status(404).json({ error: "Session not found" });
4281
4497
  }
4282
- const { stopSessionExecution } = await import("./chat-handler-AS44EMQE.js");
4283
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-FQ54IAYG.js");
4498
+ const { stopSessionExecution } = await import("./chat-handler-MBR6ZQTX.js");
4499
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WGAZKL56.js");
4284
4500
  sessionManager.clearMessageQueue(sessionId);
4285
4501
  stopSessionExecution(sessionId, sessionManager);
4286
4502
  abortSession(sessionId);
@@ -4334,11 +4550,11 @@ async function createServerHandle(config4) {
4334
4550
  return res.status(500).json({ error: result.error ?? "Failed to set default model" });
4335
4551
  }
4336
4552
  const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
4337
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
4553
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4338
4554
  const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model);
4339
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
4340
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
4341
- 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 });
4342
4558
  });
4343
4559
  app.put("/api/sessions/:id/criteria", async (req, res) => {
4344
4560
  const sessionId = req.params.id;
@@ -4434,7 +4650,7 @@ async function createServerHandle(config4) {
4434
4650
  if (!callId || approved === void 0) {
4435
4651
  return res.status(400).json({ error: "callId and approved are required" });
4436
4652
  }
4437
- const { providePathConfirmation } = await import("./tools-FQ54IAYG.js");
4653
+ const { providePathConfirmation } = await import("./tools-WGAZKL56.js");
4438
4654
  const result = providePathConfirmation(callId, approved, alwaysAllow);
4439
4655
  if (!result.found) {
4440
4656
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -4442,7 +4658,7 @@ async function createServerHandle(config4) {
4442
4658
  const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4443
4659
  const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-2BGFLV5J.js");
4444
4660
  const { createSessionStateMessage } = await import("./protocol-CTNE3ANP.js");
4445
- const { getPendingQuestionsForSession } = await import("./tools-FQ54IAYG.js");
4661
+ const { getPendingQuestionsForSession } = await import("./tools-WGAZKL56.js");
4446
4662
  const eventStore = getEventStore2();
4447
4663
  const events = eventStore.getEvents(sessionId);
4448
4664
  const messages = buildMessagesFromStoredEvents(events);
@@ -4463,7 +4679,7 @@ async function createServerHandle(config4) {
4463
4679
  if (!skip && typeof answer !== "string") {
4464
4680
  return res.status(400).json({ error: "answer is required when not skipping" });
4465
4681
  }
4466
- const { provideAnswer } = await import("./tools-FQ54IAYG.js");
4682
+ const { provideAnswer } = await import("./tools-WGAZKL56.js");
4467
4683
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
4468
4684
  if (!found) {
4469
4685
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -4491,8 +4707,8 @@ async function createServerHandle(config4) {
4491
4707
  if (!session) {
4492
4708
  return res.status(404).json({ error: "Session not found" });
4493
4709
  }
4494
- const { getSetting, SETTINGS_KEYS } = await import("./settings-X43DCM55.js");
4495
- 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") {
4496
4712
  return res.json({ success: false, reason: "disabled" });
4497
4713
  }
4498
4714
  if (session.messages.length > 0) {
@@ -4523,7 +4739,7 @@ async function createServerHandle(config4) {
4523
4739
  backend: activeProvider?.backend ?? llmClient.getBackend(),
4524
4740
  model: llmClient.getModel()
4525
4741
  };
4526
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-MH7J2YVP.js");
4742
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-PIZJ42J2.js");
4527
4743
  runAgentTurn(
4528
4744
  {
4529
4745
  sessionManager,
@@ -4561,8 +4777,8 @@ async function createServerHandle(config4) {
4561
4777
  if (!session) {
4562
4778
  return res.status(404).json({ error: "Session not found" });
4563
4779
  }
4564
- const { stopSessionExecution } = await import("./chat-handler-AS44EMQE.js");
4565
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-FQ54IAYG.js");
4780
+ const { stopSessionExecution } = await import("./chat-handler-MBR6ZQTX.js");
4781
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WGAZKL56.js");
4566
4782
  const queuedMessages = sessionManager.getQueueState(sessionId);
4567
4783
  sessionManager.clearMessageQueue(sessionId);
4568
4784
  stopSessionExecution(sessionId, sessionManager);
@@ -4642,7 +4858,7 @@ async function createServerHandle(config4) {
4642
4858
  res.json({ accepted: true });
4643
4859
  });
4644
4860
  app.get("/api/settings", async (req, res) => {
4645
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4861
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4646
4862
  const keysParam = req.query["keys"];
4647
4863
  if (!keysParam) {
4648
4864
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -4650,30 +4866,30 @@ async function createServerHandle(config4) {
4650
4866
  const keys = keysParam.split(",").map((k) => k.trim());
4651
4867
  const result = {};
4652
4868
  for (const key of keys) {
4653
- result[key] = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? "";
4869
+ result[key] = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? "";
4654
4870
  }
4655
4871
  res.json(result);
4656
4872
  });
4657
4873
  app.get("/api/settings/:key", async (req, res) => {
4658
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4874
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4659
4875
  const key = req.params.key;
4660
- const value = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4876
+ const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4661
4877
  res.json({ key, value });
4662
4878
  });
4663
4879
  app.get("/api/settings/:key", async (req, res) => {
4664
- const { getSetting, SETTINGS_DEFAULTS } = await import("./settings-X43DCM55.js");
4880
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2TQA7VTP.js");
4665
4881
  const key = req.params.key;
4666
- const value = getSetting(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4882
+ const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
4667
4883
  res.json({ key, value });
4668
4884
  });
4669
4885
  app.put("/api/settings/:key", async (req, res) => {
4670
- const { setSetting } = await import("./settings-X43DCM55.js");
4886
+ const { setSetting: setSetting2 } = await import("./settings-2TQA7VTP.js");
4671
4887
  const key = req.params.key;
4672
4888
  const { value } = req.body;
4673
4889
  if (value === void 0) {
4674
4890
  return res.status(400).json({ error: "value is required" });
4675
4891
  }
4676
- setSetting(key, value);
4892
+ setSetting2(key, value);
4677
4893
  res.json({ key, value });
4678
4894
  });
4679
4895
  app.get("/api/config", async (_req, res) => {
@@ -4683,7 +4899,7 @@ async function createServerHandle(config4) {
4683
4899
  let globalWorkdir;
4684
4900
  try {
4685
4901
  const { loadGlobalConfig, getVisionFallback } = await import("./config-GMQUPNBY.js");
4686
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
4902
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4687
4903
  const fallback = getVisionFallback(globalConfig);
4688
4904
  if (fallback) {
4689
4905
  visionFallback = {
@@ -4701,13 +4917,13 @@ async function createServerHandle(config4) {
4701
4917
  version: VERSION,
4702
4918
  model: llmClient.getModel(),
4703
4919
  maxContext: providerManager.getCurrentModelContext(),
4704
- llmUrl: activeProvider?.url ?? config4.llm.baseUrl,
4920
+ llmUrl: activeProvider?.url ?? config3.llm.baseUrl,
4705
4921
  llmStatus: getLlmStatus(),
4706
4922
  backend: llmClient.getBackend(),
4707
- workdir: globalWorkdir ?? config4.workdir,
4923
+ workdir: globalWorkdir ?? config3.workdir,
4708
4924
  providers: providerManager.getProviders(),
4709
4925
  activeProviderId: providerManager.getActiveProviderId(),
4710
- defaultModelSelection: config4.defaultModelSelection,
4926
+ defaultModelSelection: config3.defaultModelSelection,
4711
4927
  visionFallback
4712
4928
  });
4713
4929
  });
@@ -4716,7 +4932,7 @@ async function createServerHandle(config4) {
4716
4932
  const currentModel = providerManager.getCurrentModel();
4717
4933
  if (currentModel === "auto") {
4718
4934
  const activeProvider = providerManager.getActiveProvider();
4719
- const baseUrl = activeProvider?.url ?? config4.llm.baseUrl;
4935
+ const baseUrl = activeProvider?.url ?? config3.llm.baseUrl;
4720
4936
  const detected = await detectModel(baseUrl);
4721
4937
  if (detected) {
4722
4938
  llmClient.setModel(detected);
@@ -4906,7 +5122,7 @@ async function createServerHandle(config4) {
4906
5122
  }
4907
5123
  try {
4908
5124
  const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
4909
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5125
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4910
5126
  const providerBackend = backend;
4911
5127
  const providerModels = modelConfigs?.length ? buildModelConfigs(modelConfigs) : model ? [{ id: model, contextWindow: 2e5, source: "user" }] : [];
4912
5128
  const configWithProvider = addProvider(globalConfig, {
@@ -4925,9 +5141,9 @@ async function createServerHandle(config4) {
4925
5141
  configWithProvider.providers[configWithProvider.providers.length - 1].id,
4926
5142
  firstModelId
4927
5143
  );
4928
- await saveGlobalConfig(config4.mode ?? "production", finalConfig, config4.globalConfigPath);
5144
+ await saveGlobalConfig(config3.mode ?? "production", finalConfig, config3.globalConfigPath);
4929
5145
  providerManager.setProviders(finalConfig.providers, finalConfig.defaultModelSelection ?? void 0);
4930
- config4.defaultModelSelection = finalConfig.defaultModelSelection;
5146
+ config3.defaultModelSelection = finalConfig.defaultModelSelection;
4931
5147
  const newProvider = finalConfig.providers[finalConfig.providers.length - 1];
4932
5148
  res.status(201).json({
4933
5149
  success: true,
@@ -4944,13 +5160,13 @@ async function createServerHandle(config4) {
4944
5160
  const { workdir, visionFallback } = req.body;
4945
5161
  try {
4946
5162
  const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
4947
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5163
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4948
5164
  const updatedConfig = {
4949
5165
  ...globalConfig,
4950
5166
  workspace: workdir ? { workdir } : globalConfig.workspace,
4951
5167
  visionFallback: visionFallback ?? globalConfig.visionFallback
4952
5168
  };
4953
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
5169
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4954
5170
  res.json({ success: true });
4955
5171
  } catch (error) {
4956
5172
  res.status(500).json({
@@ -4972,11 +5188,11 @@ async function createServerHandle(config4) {
4972
5188
  app.delete("/api/providers/:id", async (req, res) => {
4973
5189
  const { id } = req.params;
4974
5190
  const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-GMQUPNBY.js");
4975
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5191
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4976
5192
  const updatedConfig = removeProvider(globalConfig, id);
4977
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
5193
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4978
5194
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
4979
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5195
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
4980
5196
  res.json({ success: true });
4981
5197
  });
4982
5198
  app.patch("/api/providers/:id", async (req, res) => {
@@ -4984,7 +5200,7 @@ async function createServerHandle(config4) {
4984
5200
  const { isLocal } = req.body;
4985
5201
  try {
4986
5202
  const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-GMQUPNBY.js");
4987
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5203
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
4988
5204
  const provider = globalConfig.providers.find((p) => p.id === id);
4989
5205
  if (!provider) {
4990
5206
  return res.status(404).json({ error: "Provider not found" });
@@ -4992,9 +5208,9 @@ async function createServerHandle(config4) {
4992
5208
  const updates = {};
4993
5209
  if (isLocal !== void 0) updates["isLocal"] = isLocal;
4994
5210
  const updatedConfig = updateProvider(globalConfig, id, updates);
4995
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
5211
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
4996
5212
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
4997
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5213
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
4998
5214
  res.json({ success: true, provider: updatedConfig.providers.find((p) => p.id === id) });
4999
5215
  } catch (error) {
5000
5216
  res.status(500).json({ error: error instanceof Error ? error.message : "Failed to update provider" });
@@ -5013,7 +5229,7 @@ async function createServerHandle(config4) {
5013
5229
  } = req.body;
5014
5230
  try {
5015
5231
  const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-GMQUPNBY.js");
5016
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5232
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5017
5233
  const provider = globalConfig.providers.find((p) => p.id === id);
5018
5234
  if (!provider) {
5019
5235
  return res.status(404).json({ error: "Provider not found" });
@@ -5029,9 +5245,9 @@ async function createServerHandle(config4) {
5029
5245
  updates["models"] = buildModelConfigs(modelConfigs);
5030
5246
  }
5031
5247
  const updatedConfig = updateProvider(globalConfig, id, updates);
5032
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
5248
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
5033
5249
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
5034
- config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5250
+ config3.defaultModelSelection = updatedConfig.defaultModelSelection;
5035
5251
  res.json({ success: true, provider: updatedConfig.providers.find((p) => p.id === id) });
5036
5252
  } catch (error) {
5037
5253
  res.status(500).json({ error: error instanceof Error ? error.message : "Failed to update provider" });
@@ -5051,9 +5267,9 @@ async function createServerHandle(config4) {
5051
5267
  }
5052
5268
  const llmClient = getLLMClient();
5053
5269
  const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GMQUPNBY.js");
5054
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5270
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5055
5271
  const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
5056
- await saveGlobalConfig(config4.mode ?? "production", updatedConfig, config4.globalConfigPath);
5272
+ await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
5057
5273
  res.json({
5058
5274
  success: true,
5059
5275
  activeProviderId: id,
@@ -5077,7 +5293,7 @@ async function createServerHandle(config4) {
5077
5293
  });
5078
5294
  async function rebuildMcpTools() {
5079
5295
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
5080
- const { setMcpTools: setMcpTools2 } = await import("./tools-FQ54IAYG.js");
5296
+ const { setMcpTools: setMcpTools2 } = await import("./tools-WGAZKL56.js");
5081
5297
  const mcpTools = createMcpTools2(mcpManager);
5082
5298
  setMcpTools2(mcpTools);
5083
5299
  }
@@ -5140,15 +5356,15 @@ async function createServerHandle(config4) {
5140
5356
  await mcpManager.addServer(name, serverCfg);
5141
5357
  const server = mcpManager.getServer(name);
5142
5358
  const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5143
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5359
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5144
5360
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {}, [name]: serverCfg };
5145
5361
  await saveGlobalConfig(
5146
- config4.mode ?? "production",
5362
+ config3.mode ?? "production",
5147
5363
  {
5148
5364
  ...globalConfig,
5149
5365
  mcpServers: updatedMcpServers
5150
5366
  },
5151
- config4.globalConfigPath
5367
+ config3.globalConfigPath
5152
5368
  );
5153
5369
  await rebuildMcpTools();
5154
5370
  if (server) {
@@ -5170,16 +5386,16 @@ async function createServerHandle(config4) {
5170
5386
  }
5171
5387
  mcpManager.removeServer(name);
5172
5388
  const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5173
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5389
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5174
5390
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {} };
5175
5391
  delete updatedMcpServers[name];
5176
5392
  await saveGlobalConfig(
5177
- config4.mode ?? "production",
5393
+ config3.mode ?? "production",
5178
5394
  {
5179
5395
  ...globalConfig,
5180
5396
  mcpServers: updatedMcpServers
5181
5397
  },
5182
- config4.globalConfigPath
5398
+ config3.globalConfigPath
5183
5399
  );
5184
5400
  await rebuildMcpTools();
5185
5401
  const sessions = sessionManager.listSessions();
@@ -5199,7 +5415,7 @@ async function createServerHandle(config4) {
5199
5415
  const server = mcpManager.getServer(name);
5200
5416
  if (server) {
5201
5417
  const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GMQUPNBY.js");
5202
- const globalConfig = await loadGlobalConfig(config4.mode ?? "production", config4.globalConfigPath);
5418
+ const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5203
5419
  const mcpServers2 = { ...globalConfig.mcpServers ?? {} };
5204
5420
  const serverCfg = mcpServers2[name];
5205
5421
  if (serverCfg) {
@@ -5207,12 +5423,12 @@ async function createServerHandle(config4) {
5207
5423
  const cfg = { ...serverCfg, ...disabledTools.length > 0 ? { disabledTools } : { disabledTools: void 0 } };
5208
5424
  mcpServers2[name] = cfg;
5209
5425
  await saveGlobalConfig(
5210
- config4.mode ?? "production",
5426
+ config3.mode ?? "production",
5211
5427
  {
5212
5428
  ...globalConfig,
5213
5429
  mcpServers: mcpServers2
5214
5430
  },
5215
- config4.globalConfigPath
5431
+ config3.globalConfigPath
5216
5432
  );
5217
5433
  }
5218
5434
  }
@@ -5226,11 +5442,11 @@ async function createServerHandle(config4) {
5226
5442
  res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
5227
5443
  }
5228
5444
  });
5229
- const projectDir = config4.workdir;
5445
+ const projectDir = config3.workdir;
5230
5446
  app.use("/api/skills", createSkillRoutes(configDir, projectDir));
5231
5447
  app.use("/api/commands", createCommandRoutes(configDir, projectDir));
5232
5448
  app.use("/api/agents", createAgentRoutes(configDir, projectDir));
5233
- app.use("/api/workflows", createWorkflowRoutes(configDir, config4, projectDir));
5449
+ app.use("/api/workflows", createWorkflowRoutes(configDir, config3, projectDir));
5234
5450
  app.use("/api/dev-server", createDevServerRoutes());
5235
5451
  app.use("/api/terminals", createTerminalRoutes());
5236
5452
  app.use(
@@ -5274,14 +5490,14 @@ async function createServerHandle(config4) {
5274
5490
  });
5275
5491
  app.use("/api/directories", createDirectoryRoutes());
5276
5492
  app.use("/api/files", createFileSearchRoutes());
5277
- const webDir = resolve3(__dirname3, "../../web");
5278
- const isDev = config4.mode === "development";
5493
+ const webDir = resolve4(__dirname3, "../../web");
5494
+ const isDev = config3.mode === "development";
5279
5495
  let viteServer;
5280
5496
  if (isDev) {
5281
5497
  logger.info("Dev mode: using Vite middleware");
5282
5498
  viteServer = await createViteServer({
5283
5499
  root: webDir,
5284
- configFile: resolve3(__dirname3, "../../web/vite.config.ts"),
5500
+ configFile: resolve4(__dirname3, "../../web/vite.config.ts"),
5285
5501
  server: { middlewareMode: true },
5286
5502
  appType: "spa",
5287
5503
  logLevel: "warn"
@@ -5301,7 +5517,7 @@ async function createServerHandle(config4) {
5301
5517
  }
5302
5518
  });
5303
5519
  app.get("/fox.svg", (_req, res) => {
5304
- readFile(join5(webDir, "fox.svg")).then((content) => {
5520
+ readFile2(join7(webDir, "fox.svg")).then((content) => {
5305
5521
  res.set("Content-Type", "image/svg+xml");
5306
5522
  res.send(content);
5307
5523
  }).catch(() => {
@@ -5310,7 +5526,7 @@ async function createServerHandle(config4) {
5310
5526
  });
5311
5527
  app.use(
5312
5528
  "/sounds",
5313
- express.static(join5(webDir, "public", "sounds"), {
5529
+ express.static(join7(webDir, "public", "sounds"), {
5314
5530
  setHeaders: (res) => {
5315
5531
  res.set("Content-Type", "audio/mpeg");
5316
5532
  }
@@ -5319,24 +5535,24 @@ async function createServerHandle(config4) {
5319
5535
  app.use("/__inspect__.js", (_req, res) => {
5320
5536
  res.set("Access-Control-Allow-Origin", "*");
5321
5537
  res.set("Content-Type", "application/javascript");
5322
- 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"));
5323
5539
  });
5324
5540
  app.get("/*path", (req, res) => {
5325
5541
  if (req.path.startsWith("/api/")) {
5326
5542
  return;
5327
5543
  }
5328
- 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) => {
5329
5545
  logger.error("Error serving index.html", { error: err });
5330
5546
  res.status(500).send("Server error");
5331
5547
  });
5332
5548
  });
5333
- logger.info("Vite middleware ready", { port: config4.server.port });
5549
+ logger.info("Vite middleware ready", { port: config3.server.port });
5334
5550
  }
5335
5551
  if (!isDev) {
5336
- const distWebDir = resolve3(__dirname3, "web");
5552
+ const distWebDir = resolve4(__dirname3, "web");
5337
5553
  app.use(
5338
5554
  "/assets",
5339
- express.static(join5(distWebDir, "assets"), {
5555
+ express.static(join7(distWebDir, "assets"), {
5340
5556
  setHeaders: (res, filepath) => {
5341
5557
  if (filepath.endsWith(".css")) {
5342
5558
  res.set("Content-Type", "text/css");
@@ -5344,11 +5560,11 @@ async function createServerHandle(config4) {
5344
5560
  }
5345
5561
  })
5346
5562
  );
5347
- app.use("/manifest.webmanifest", express.static(join5(distWebDir, "manifest.webmanifest")));
5348
- app.use("/registerSW.js", express.static(join5(distWebDir, "registerSW.js")));
5349
- 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")));
5350
5566
  app.get("/fox.svg", (_req, res) => {
5351
- readFile(join5(distWebDir, "fox.svg")).then((content) => {
5567
+ readFile2(join7(distWebDir, "fox.svg")).then((content) => {
5352
5568
  res.set("Content-Type", "image/svg+xml");
5353
5569
  res.send(content);
5354
5570
  }).catch(() => {
@@ -5357,7 +5573,7 @@ async function createServerHandle(config4) {
5357
5573
  });
5358
5574
  app.use(
5359
5575
  "/sounds",
5360
- express.static(join5(distWebDir, "sounds"), {
5576
+ express.static(join7(distWebDir, "sounds"), {
5361
5577
  setHeaders: (res) => {
5362
5578
  res.set("Content-Type", "audio/mpeg");
5363
5579
  }
@@ -5366,10 +5582,10 @@ async function createServerHandle(config4) {
5366
5582
  app.use("/__inspect__.js", (_req, res) => {
5367
5583
  res.set("Access-Control-Allow-Origin", "*");
5368
5584
  res.set("Content-Type", "application/javascript");
5369
- 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"));
5370
5586
  });
5371
5587
  app.get("/", (_req, res) => {
5372
- 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(() => {
5373
5589
  res.status(404).send("Web UI not built. Run `npm run build:web`");
5374
5590
  });
5375
5591
  });
@@ -5377,7 +5593,7 @@ async function createServerHandle(config4) {
5377
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") {
5378
5594
  return;
5379
5595
  }
5380
- 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(() => {
5381
5597
  res.status(404).send("Web UI not built");
5382
5598
  });
5383
5599
  });
@@ -5385,7 +5601,7 @@ async function createServerHandle(config4) {
5385
5601
  const httpServer = createHttpServer(app);
5386
5602
  const wssExports = createWebSocketServer(
5387
5603
  httpServer,
5388
- config4,
5604
+ config3,
5389
5605
  getLLMClient,
5390
5606
  () => providerManager.getActiveProvider(),
5391
5607
  sessionManager,
@@ -5397,7 +5613,7 @@ async function createServerHandle(config4) {
5397
5613
  const state = sessionManager.getContextState(sessionId);
5398
5614
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
5399
5615
  });
5400
- const { QueueProcessor } = await import("./processor-34MVJZTD.js");
5616
+ const { QueueProcessor } = await import("./processor-PKKTNKWY.js");
5401
5617
  const queueProcessor = new QueueProcessor({
5402
5618
  sessionManager,
5403
5619
  providerManager,
@@ -5418,22 +5634,22 @@ async function createServerHandle(config4) {
5418
5634
  };
5419
5635
  return {
5420
5636
  httpServer,
5421
- ctx: { config: config4, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
5422
- start: (port) => new Promise((resolve4, reject) => {
5423
- const listenPort = port ?? config4.server.port;
5424
- 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;
5425
5641
  httpServer.listen(listenPort, host, () => {
5426
5642
  const addr = httpServer.address();
5427
5643
  const actualPort = typeof addr === "object" && addr ? addr.port : listenPort;
5428
5644
  const client = getLLMClient();
5429
5645
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
5430
5646
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
5431
- logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config4.llm.baseUrl}`);
5432
- resolve4({ port: actualPort });
5647
+ logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config3.llm.baseUrl}`);
5648
+ resolve5({ port: actualPort });
5433
5649
  });
5434
5650
  httpServer.on("error", reject);
5435
5651
  }),
5436
- close: () => new Promise((resolve4) => {
5652
+ close: () => new Promise((resolve5) => {
5437
5653
  logger.info("Shutting down...");
5438
5654
  void (async () => {
5439
5655
  await devServerManager.stopAll();
@@ -5443,22 +5659,22 @@ async function createServerHandle(config4) {
5443
5659
  const { cleanupAllProcesses } = await import("./store-FXTCHBI4.js");
5444
5660
  cleanupAllProcesses();
5445
5661
  viteServer?.close();
5446
- if (config4.globalConfigPath) {
5662
+ if (config3.globalConfigPath) {
5447
5663
  const { unlink: unlink2 } = await import("fs/promises");
5448
- unlink2(config4.globalConfigPath).catch(() => {
5664
+ unlink2(config3.globalConfigPath).catch(() => {
5449
5665
  });
5450
5666
  }
5451
5667
  for (const client of wss.clients) {
5452
5668
  client.terminate();
5453
5669
  }
5454
5670
  wss.close();
5455
- httpServer.close(() => resolve4());
5671
+ httpServer.close(() => resolve5());
5456
5672
  })();
5457
5673
  })
5458
5674
  };
5459
5675
  }
5460
- async function createServer(config4) {
5461
- const handle = await createServerHandle(config4);
5676
+ async function createServer(config3) {
5677
+ const handle = await createServerHandle(config3);
5462
5678
  await handle.start();
5463
5679
  const shutdown = () => {
5464
5680
  const forceExitTimer = setTimeout(() => {
@@ -5477,4 +5693,4 @@ export {
5477
5693
  createServerHandle,
5478
5694
  createServer
5479
5695
  };
5480
- //# sourceMappingURL=chunk-LQFCQ6PY.js.map
5696
+ //# sourceMappingURL=chunk-DEWNWF2P.js.map