openfox 1.6.91 → 1.6.92

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 (37) hide show
  1. package/dist/{auto-compaction-I4YS2BN4.js → auto-compaction-7AGIGW6F.js} +6 -6
  2. package/dist/{chat-handler-O4FNSVPI.js → chat-handler-UPAEF6HR.js} +9 -9
  3. package/dist/{chunk-UQSL65WB.js → chunk-2BS6LMIU.js} +398 -470
  4. package/dist/{chunk-HKCUSLQ5.js → chunk-2TKN2X2A.js} +3 -3
  5. package/dist/{chunk-SSGVISQU.js → chunk-7KO2BQFQ.js} +8 -7
  6. package/dist/{chunk-II4UCFTE.js → chunk-7QG6LY5Q.js} +3 -3
  7. package/dist/{chunk-CL2ZPJAG.js → chunk-ARJIHQ3S.js} +225 -138
  8. package/dist/{chunk-H5T34J3H.js → chunk-BHZL3N2F.js} +3 -3
  9. package/dist/{chunk-MOQLMPTA.js → chunk-CHICEUV6.js} +3 -3
  10. package/dist/{chunk-STUSQVXQ.js → chunk-RJIPM7CO.js} +2 -2
  11. package/dist/{chunk-B5AP3RSV.js → chunk-RW25DL5R.js} +3 -3
  12. package/dist/{chunk-A3YOBYWJ.js → chunk-WBQNIWAQ.js} +5 -5
  13. package/dist/{chunk-DF5BZBP6.js → chunk-XGJ7HDQ7.js} +2 -2
  14. package/dist/{chunk-6P5WQP6Y.js → chunk-YTPPQK55.js} +2 -2
  15. package/dist/cli/dev.js +1 -1
  16. package/dist/cli/index.js +1 -1
  17. package/dist/{config-GEDIDCBM.js → config-7XJQNOKX.js} +5 -5
  18. package/dist/{events-AQKDXJFK.js → events-K6AYMXFT.js} +3 -3
  19. package/dist/{orchestrator-LLOIG2CR.js → orchestrator-M4WINFF3.js} +7 -7
  20. package/dist/package.json +1 -1
  21. package/dist/{processor-XL5NULQN.js → processor-D4XQ5QMB.js} +5 -5
  22. package/dist/{protocol--8PKNwb_.d.ts → protocol-XRiJzlOK.d.ts} +1 -1
  23. package/dist/{provider-EV3KBC7Y.js → provider-UO5PAZQQ.js} +7 -7
  24. package/dist/{runtime-config-CBJJJGBD.js → runtime-config-CYHDAC7W.js} +2 -2
  25. package/dist/{serve-UWKYNKAO.js → serve-Z5FNJUDT.js} +11 -11
  26. package/dist/server/index.d.ts +1 -1
  27. package/dist/server/index.js +9 -9
  28. package/dist/shared/index.d.ts +2 -2
  29. package/dist/{tools-ZBAAAOUH.js → tools-NFFQWH6M.js} +6 -6
  30. package/dist/{vision-fallback-4TAGWGVS.js → vision-fallback-GZZWU7CR.js} +2 -2
  31. package/dist/web/assets/{index-CGEQK8Pf.css → index-CM0cLwa6.css} +1 -1
  32. package/dist/web/assets/index-SkaCnTiV.js +176 -0
  33. package/dist/web/index.html +2 -2
  34. package/dist/web/sw.js +1 -1
  35. package/package.json +1 -1
  36. package/dist/web/assets/index-Cb7XVDFv.js +0 -158
  37. /package/dist/web/{workbox-8c29f6e4.js → workbox-7fc22fbe.js} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  createVerifierNudgeConfig,
3
3
  runBuilderTurn,
4
4
  runChatTurn
5
- } from "./chunk-HKCUSLQ5.js";
5
+ } from "./chunk-2TKN2X2A.js";
6
6
  import {
7
7
  TurnMetrics,
8
8
  agentExists,
@@ -10,35 +10,43 @@ import {
10
10
  createMessageStartEvent,
11
11
  createToolRegistry,
12
12
  deleteAgent,
13
+ deleteItemFromDir,
14
+ deleteProjectAgent,
15
+ deleteProjectSkill,
13
16
  deleteSkill,
14
17
  devServerManager,
15
18
  executeSubAgent,
16
19
  findAgentById,
17
20
  findSkillById,
18
- getDefaultAgentContent,
19
21
  getDefaultAgentIds,
20
22
  getDefaultIds,
21
- getDefaultSkillContent,
22
23
  getDefaultSkillIds,
23
24
  getToolRegistryForAgent,
24
25
  getTopLevelAgents,
26
+ isDefaultAgent,
27
+ isDefaultSkill,
25
28
  isSkillEnabled,
29
+ jsonSerializer,
26
30
  loadAllAgents,
27
31
  loadAllAgentsDefault,
28
32
  loadAllSkills,
29
33
  loadDefaultAgents,
30
34
  loadDefaultSkills,
31
35
  loadItemsFromDir,
36
+ loadProjectAgents,
37
+ loadProjectSkills,
32
38
  loadUserAgents,
33
39
  loadUserSkills,
34
40
  pathExists,
35
41
  performManualContextCompaction,
36
42
  saveAgent,
43
+ saveAgentToProject,
44
+ saveItemToDir,
37
45
  saveSkill,
38
- setSkillEnabled,
46
+ saveSkillToProject,
39
47
  skillExists,
40
48
  spawnShellProcess
41
- } from "./chunk-CL2ZPJAG.js";
49
+ } from "./chunk-ARJIHQ3S.js";
42
50
  import {
43
51
  getProject
44
52
  } from "./chunk-ZHBL5G5X.js";
@@ -51,18 +59,18 @@ import {
51
59
  import {
52
60
  createProviderManager,
53
61
  parseDefaultModelSelection
54
- } from "./chunk-II4UCFTE.js";
62
+ } from "./chunk-7QG6LY5Q.js";
55
63
  import {
56
64
  SessionNotFoundError,
57
65
  createLLMClient,
58
66
  detectModel,
59
67
  getLlmStatus
60
- } from "./chunk-A3YOBYWJ.js";
68
+ } from "./chunk-WBQNIWAQ.js";
61
69
  import {
62
70
  detectBackend,
63
71
  getBackendDisplayName,
64
72
  getModelProfile
65
- } from "./chunk-STUSQVXQ.js";
73
+ } from "./chunk-RJIPM7CO.js";
66
74
  import {
67
75
  createSession,
68
76
  deleteSession,
@@ -88,7 +96,7 @@ import {
88
96
  updateSessionProvider,
89
97
  updateSessionRunning,
90
98
  updateSessionSummary
91
- } from "./chunk-6P5WQP6Y.js";
99
+ } from "./chunk-YTPPQK55.js";
92
100
  import {
93
101
  initDatabase
94
102
  } from "./chunk-5GVCNVKV.js";
@@ -127,7 +135,7 @@ import {
127
135
  import {
128
136
  getRuntimeConfig,
129
137
  setRuntimeConfig
130
- } from "./chunk-B5AP3RSV.js";
138
+ } from "./chunk-RW25DL5R.js";
131
139
  import {
132
140
  logger,
133
141
  setLogLevel
@@ -138,7 +146,7 @@ import express from "express";
138
146
  import cors from "cors";
139
147
  import { createServer as createHttpServer } from "http";
140
148
  import { fileURLToPath as fileURLToPath4 } from "url";
141
- import { dirname as dirname5, resolve, join as join5 } from "path";
149
+ import { dirname as dirname5, resolve, join as join6 } from "path";
142
150
  import { readFile as readFile3 } from "fs/promises";
143
151
  import { createServer as createViteServer } from "vite";
144
152
 
@@ -1532,6 +1540,9 @@ var WORKFLOW_EXTENSION = ".workflow.json";
1532
1540
  function getWorkflowsDir(configDir) {
1533
1541
  return join(configDir, "workflows");
1534
1542
  }
1543
+ function getProjectWorkflowsDir(projectDir) {
1544
+ return join(projectDir, ".openfox", "workflows");
1545
+ }
1535
1546
  async function pathExists2(path) {
1536
1547
  try {
1537
1548
  await access(path, constants.R_OK);
@@ -1576,7 +1587,10 @@ async function loadDefaultWorkflows() {
1576
1587
  async function loadUserWorkflows(configDir) {
1577
1588
  return loadWorkflowsFromDir(getWorkflowsDir(configDir));
1578
1589
  }
1579
- async function loadAllWorkflows(configDir) {
1590
+ async function loadProjectWorkflows(projectDir) {
1591
+ return loadWorkflowsFromDir(getProjectWorkflowsDir(projectDir));
1592
+ }
1593
+ async function loadAllWorkflows(configDir, projectDir) {
1580
1594
  const [defaultWorkflows, userWorkflows] = await Promise.all([loadDefaultWorkflows(), loadUserWorkflows(configDir)]);
1581
1595
  const workflowMap = /* @__PURE__ */ new Map();
1582
1596
  for (const workflow of defaultWorkflows) {
@@ -1585,8 +1599,20 @@ async function loadAllWorkflows(configDir) {
1585
1599
  for (const workflow of userWorkflows) {
1586
1600
  workflowMap.set(workflow.metadata.id, workflow);
1587
1601
  }
1602
+ if (projectDir) {
1603
+ const projectWorkflows = await loadProjectWorkflows(projectDir);
1604
+ for (const workflow of projectWorkflows) {
1605
+ workflowMap.set(workflow.metadata.id, workflow);
1606
+ }
1607
+ }
1588
1608
  return Array.from(workflowMap.values());
1589
1609
  }
1610
+ async function saveWorkflowToProject(projectDir, workflow) {
1611
+ await saveItemToDir(getProjectWorkflowsDir(projectDir), workflow, WORKFLOW_EXTENSION, jsonSerializer);
1612
+ }
1613
+ async function deleteProjectWorkflow(projectDir, workflowId) {
1614
+ return deleteItemFromDir(getProjectWorkflowsDir(projectDir), workflowId, WORKFLOW_EXTENSION);
1615
+ }
1590
1616
  async function getDefaultWorkflowIds() {
1591
1617
  for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {
1592
1618
  try {
@@ -1597,10 +1623,6 @@ async function getDefaultWorkflowIds() {
1597
1623
  }
1598
1624
  return [];
1599
1625
  }
1600
- async function getDefaultWorkflowContent(workflowId) {
1601
- const defaults = await loadDefaultWorkflows();
1602
- return defaults.find((w) => w.metadata.id === workflowId) ?? null;
1603
- }
1604
1626
  async function isDefaultWorkflow(workflowId) {
1605
1627
  const defaultIds = await getDefaultWorkflowIds();
1606
1628
  return defaultIds.includes(workflowId);
@@ -1608,9 +1630,11 @@ async function isDefaultWorkflow(workflowId) {
1608
1630
  function findWorkflowById(workflowId, workflows) {
1609
1631
  return workflows.find((p) => p.metadata.id === workflowId);
1610
1632
  }
1611
- async function workflowExists(configDir, workflowId) {
1612
- const filePath = join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`);
1613
- return pathExists2(filePath);
1633
+ async function workflowExists(configDir, workflowId, projectDir) {
1634
+ if (await pathExists2(join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`))) return true;
1635
+ if (projectDir && await pathExists2(join(getProjectWorkflowsDir(projectDir), `${workflowId}${WORKFLOW_EXTENSION}`)))
1636
+ return true;
1637
+ return false;
1614
1638
  }
1615
1639
  async function saveWorkflow(configDir, workflow) {
1616
1640
  const workflowsDir = getWorkflowsDir(configDir);
@@ -2481,7 +2505,7 @@ function processQueueAndRestartTurn(sessionManager, sessionId, drainFn, queueMod
2481
2505
  }
2482
2506
  var activeAgents = /* @__PURE__ */ new Map();
2483
2507
  var MAX_SEND_QUEUE_SIZE = 1e3;
2484
- function createWebSocketServer(httpServer, config, getLLMClient, getActiveProvider, sessionManager, providerManager) {
2508
+ function createWebSocketServer(httpServer, config4, getLLMClient, getActiveProvider, sessionManager, providerManager) {
2485
2509
  const wss = new WebSocketServer({ server: httpServer });
2486
2510
  const clients = /* @__PURE__ */ new Map();
2487
2511
  moduleClients = clients;
@@ -2508,9 +2532,9 @@ function createWebSocketServer(httpServer, config, getLLMClient, getActiveProvid
2508
2532
  }
2509
2533
  const baseUrl = provider.url.includes("/v1") ? provider.url : `${provider.url}/v1`;
2510
2534
  const sessionConfig = {
2511
- ...config,
2535
+ ...config4,
2512
2536
  llm: {
2513
- ...config.llm,
2537
+ ...config4.llm,
2514
2538
  baseUrl,
2515
2539
  model: session.providerModel,
2516
2540
  ...provider.apiKey && { apiKey: provider.apiKey }
@@ -3114,10 +3138,10 @@ var LspServer = class {
3114
3138
  // Pending diagnostic waiters
3115
3139
  pendingDiagnostics = /* @__PURE__ */ new Map();
3116
3140
  commandPath;
3117
- constructor(config, workdir, commandPath) {
3118
- this.config = config;
3141
+ constructor(config4, workdir, commandPath) {
3142
+ this.config = config4;
3119
3143
  this.workdir = workdir;
3120
- this.commandPath = commandPath ?? config.serverCommand;
3144
+ this.commandPath = commandPath ?? config4.serverCommand;
3121
3145
  }
3122
3146
  // ============================================================================
3123
3147
  // Lifecycle
@@ -3940,8 +3964,8 @@ var LspManager = class {
3940
3964
  // ============================================================================
3941
3965
  // Server Management
3942
3966
  // ============================================================================
3943
- async getOrCreateServer(config) {
3944
- const langId = config.id;
3967
+ async getOrCreateServer(config4) {
3968
+ const langId = config4.id;
3945
3969
  const existing = this.servers.get(langId);
3946
3970
  if (existing?.isRunning()) {
3947
3971
  return existing;
@@ -3953,7 +3977,7 @@ var LspManager = class {
3953
3977
  if (pending) {
3954
3978
  return pending;
3955
3979
  }
3956
- const promise = this.startServer(config);
3980
+ const promise = this.startServer(config4);
3957
3981
  this.serverPromises.set(langId, promise);
3958
3982
  try {
3959
3983
  const server = await promise;
@@ -3962,19 +3986,19 @@ var LspManager = class {
3962
3986
  this.serverPromises.delete(langId);
3963
3987
  }
3964
3988
  }
3965
- async startServer(config) {
3966
- const langId = config.id;
3967
- const commandPath = await which(config.serverCommand, this.workdir);
3989
+ async startServer(config4) {
3990
+ const langId = config4.id;
3991
+ const commandPath = await which(config4.serverCommand, this.workdir);
3968
3992
  if (!commandPath) {
3969
3993
  logger.warn("LSP server not installed, skipping", {
3970
3994
  language: langId,
3971
- command: config.serverCommand,
3995
+ command: config4.serverCommand,
3972
3996
  sessionId: this.sessionId
3973
3997
  });
3974
3998
  this.unavailableServers.add(langId);
3975
3999
  return null;
3976
4000
  }
3977
- const server = new LspServer(config, this.workdir, commandPath);
4001
+ const server = new LspServer(config4, this.workdir, commandPath);
3978
4002
  try {
3979
4003
  await server.start();
3980
4004
  this.servers.set(langId, server);
@@ -3994,11 +4018,11 @@ var LspManager = class {
3994
4018
  }
3995
4019
  }
3996
4020
  async getServerForFile(path) {
3997
- const config = detectLanguage(path);
3998
- if (!config) {
4021
+ const config4 = detectLanguage(path);
4022
+ if (!config4) {
3999
4023
  return null;
4000
4024
  }
4001
- return this.getOrCreateServer(config);
4025
+ return this.getOrCreateServer(config4);
4002
4026
  }
4003
4027
  // ============================================================================
4004
4028
  // Public Interface
@@ -4029,11 +4053,11 @@ var LspManager = class {
4029
4053
  * Get current diagnostics for a file without triggering a change.
4030
4054
  */
4031
4055
  getDiagnostics(path) {
4032
- const config = detectLanguage(path);
4033
- if (!config) {
4056
+ const config4 = detectLanguage(path);
4057
+ if (!config4) {
4034
4058
  return [];
4035
4059
  }
4036
- const server = this.servers.get(config.id);
4060
+ const server = this.servers.get(config4.id);
4037
4061
  if (!server?.isRunning()) {
4038
4062
  return [];
4039
4063
  }
@@ -4044,11 +4068,11 @@ var LspManager = class {
4044
4068
  * Returns true if we have or can start a server for this file type.
4045
4069
  */
4046
4070
  isAvailableFor(path) {
4047
- const config = detectLanguage(path);
4048
- if (!config) {
4071
+ const config4 = detectLanguage(path);
4072
+ if (!config4) {
4049
4073
  return false;
4050
4074
  }
4051
- if (this.unavailableServers.has(config.id)) {
4075
+ if (this.unavailableServers.has(config4.id)) {
4052
4076
  return false;
4053
4077
  }
4054
4078
  return true;
@@ -4836,130 +4860,197 @@ ${summary}`,
4836
4860
  }
4837
4861
  };
4838
4862
 
4839
- // src/server/routes/skills.ts
4840
- import { Router } from "express";
4841
-
4842
4863
  // src/server/routes/crud-helpers.ts
4864
+ import { Router } from "express";
4865
+ import { join as join4 } from "path";
4843
4866
  function computeOverrideIds(defaults, userItems) {
4844
4867
  return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
4845
4868
  }
4846
-
4847
- // src/server/routes/skills.ts
4848
- function createSkillRoutes(configDir) {
4869
+ var ID_REGEX = /^[a-z0-9-]+$/;
4870
+ function validateNameIdPrompt(body) {
4871
+ const meta = body["metadata"];
4872
+ if (!meta?.["name"] || !body["prompt"]) return "Missing required fields: metadata.name, prompt";
4873
+ if (meta["id"] && !ID_REGEX.test(String(meta["id"]))) return "ID must be lowercase alphanumeric with hyphens only";
4874
+ return null;
4875
+ }
4876
+ function getProjectItemPath(projectDir, dirName, id, ext) {
4877
+ return join4(projectDir, ".openfox", dirName, `${id}${ext}`);
4878
+ }
4879
+ async function isProjectItem(projectDir, dirName, id, ext) {
4880
+ if (!projectDir) return false;
4881
+ return pathExists(getProjectItemPath(projectDir, dirName, id, ext));
4882
+ }
4883
+ function createCrudRoutes(config4, configDir, projectDir) {
4849
4884
  const router = Router();
4850
4885
  router.get("/", async (_req, res) => {
4851
- const [defaults, userItems] = await Promise.all([loadDefaultSkills(), loadUserSkills(configDir)]);
4852
- const overrideIds = computeOverrideIds(defaults, userItems);
4886
+ const [defaults, userItems, projectItems] = await Promise.all([
4887
+ config4.loadDefaults(),
4888
+ config4.loadUser(configDir),
4889
+ projectDir ? config4.loadProject(projectDir) : []
4890
+ ]);
4891
+ const userOverrideIds = computeOverrideIds(defaults, userItems);
4892
+ const projectOverrideIds = computeOverrideIds(defaults, projectItems);
4893
+ const extra = config4.extraGetData ? await config4.extraGetData() : {};
4853
4894
  res.json({
4854
- defaults: defaults.map((s) => ({
4855
- ...s.metadata,
4856
- enabled: isSkillEnabled(s.metadata.id)
4857
- })),
4858
- userItems: userItems.map((s) => ({
4859
- ...s.metadata,
4860
- enabled: isSkillEnabled(s.metadata.id)
4861
- })),
4862
- overrideIds
4895
+ defaults: defaults.map(config4.mapToResponse),
4896
+ userItems: userItems.map(config4.mapToResponse),
4897
+ projectItems: projectItems.map(config4.mapToResponse),
4898
+ overrideIds: [...userOverrideIds, ...projectOverrideIds],
4899
+ ...extra
4863
4900
  });
4864
4901
  });
4865
4902
  router.get("/defaults/:id", async (req, res) => {
4866
4903
  const { id } = req.params;
4867
- const content = await getDefaultSkillContent(id);
4868
- if (!content) {
4869
- return res.status(404).json({ error: "Default skill not found" });
4904
+ const allDefaults = await config4.loadDefaults();
4905
+ const item = allDefaults.find((d) => d.metadata.id === id);
4906
+ if (!item) {
4907
+ return res.status(404).json({ error: "Default not found" });
4870
4908
  }
4871
- res.json(content);
4909
+ res.json(item);
4872
4910
  });
4873
4911
  router.get("/default-ids", async (_req, res) => {
4874
- const ids = await getDefaultSkillIds();
4912
+ const ids = config4.getDefaultIds ? await config4.getDefaultIds() : [];
4875
4913
  res.json({ ids });
4876
4914
  });
4877
- router.post("/:id/toggle", (req, res) => {
4878
- const { id } = req.params;
4879
- const currentlyEnabled = isSkillEnabled(id);
4880
- setSkillEnabled(id, !currentlyEnabled);
4881
- res.json({ id, enabled: !currentlyEnabled });
4882
- });
4883
4915
  router.get("/:id", async (req, res) => {
4884
4916
  const { id } = req.params;
4885
- const skills = await loadAllSkills(configDir);
4886
- const skill = findSkillById(id, skills);
4887
- if (!skill) {
4888
- return res.status(404).json({ error: "Skill not found" });
4917
+ const items = await config4.loadAll(configDir, projectDir);
4918
+ const item = config4.findById(id, items);
4919
+ if (!item) {
4920
+ return res.status(404).json({ error: "Not found" });
4889
4921
  }
4890
- res.json(skill);
4922
+ res.json(item);
4891
4923
  });
4892
4924
  router.post("/", async (req, res) => {
4893
4925
  const body = req.body;
4894
- if (!body.metadata?.id || !body.metadata?.name || !body.prompt) {
4895
- return res.status(400).json({ error: "Missing required fields: metadata.id, metadata.name, prompt" });
4926
+ const meta = body["metadata"];
4927
+ const customError = config4.validateCreate?.(body);
4928
+ if (!meta?.["id"] || customError) {
4929
+ return res.status(400).json({ error: customError ?? "Missing required fields" });
4896
4930
  }
4897
- if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {
4898
- return res.status(400).json({ error: "Skill ID must be lowercase alphanumeric with hyphens only" });
4931
+ const id = String(meta["id"]);
4932
+ const destination = body["destination"] ?? "user";
4933
+ if (destination === "project" && !projectDir) {
4934
+ return res.status(400).json({ error: "No project directory configured" });
4899
4935
  }
4900
- const exists = await skillExists(configDir, body.metadata.id);
4936
+ const exists = await config4.exists(configDir, id, projectDir);
4901
4937
  if (exists) {
4902
- return res.status(409).json({ error: "A skill with this ID already exists" });
4938
+ return res.status(409).json({ error: "An item with this ID already exists" });
4939
+ }
4940
+ if (destination === "project") {
4941
+ await config4.saveToProject(projectDir, body);
4942
+ } else {
4943
+ await config4.save(configDir, body);
4903
4944
  }
4904
- await saveSkill(configDir, body);
4905
4945
  res.status(201).json(body);
4906
4946
  });
4907
4947
  router.put("/:id", async (req, res) => {
4908
4948
  const { id } = req.params;
4909
- const skills = await loadAllSkills(configDir);
4910
- const existing = findSkillById(id, skills);
4949
+ const items = await config4.loadAll(configDir, projectDir);
4950
+ const existing = config4.findById(id, items);
4911
4951
  if (!existing) {
4912
- return res.status(404).json({ error: "Skill not found" });
4952
+ return res.status(404).json({ error: "Not found" });
4913
4953
  }
4914
4954
  const body = req.body;
4955
+ const meta = body["metadata"];
4915
4956
  const updated = {
4916
- metadata: { ...existing.metadata, ...body.metadata, id },
4917
- prompt: body.prompt ?? existing.prompt
4957
+ ...existing,
4958
+ ...body,
4959
+ metadata: { ...existing.metadata, ...meta, id }
4918
4960
  };
4919
- await saveSkill(configDir, updated);
4961
+ const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
4962
+ if (isProject) {
4963
+ await config4.saveToProject(projectDir, updated);
4964
+ } else {
4965
+ await config4.save(configDir, updated);
4966
+ }
4920
4967
  res.json(updated);
4921
4968
  });
4922
4969
  router.delete("/:id", async (req, res) => {
4923
4970
  const { id } = req.params;
4924
- const result = await deleteSkill(configDir, id);
4971
+ const isProject = await isProjectItem(projectDir, config4.dirName, id, config4.ext);
4972
+ if (isProject) {
4973
+ const result2 = await config4.deleteProject(projectDir, id);
4974
+ if (!result2.success) {
4975
+ return res.status(500).json({ error: "Failed to delete project item" });
4976
+ }
4977
+ return res.json({ success: true });
4978
+ }
4979
+ const isDefault = await config4.isDefault(id);
4980
+ if (isDefault) {
4981
+ return res.status(403).json({ error: "Cannot delete built-in defaults" });
4982
+ }
4983
+ const result = await config4.delete(configDir, id);
4925
4984
  if (!result.success) {
4926
- return res.status(403).json({ error: result.reason ?? "Cannot delete this skill" });
4985
+ return res.status(403).json({ error: result.reason ?? "Cannot delete this item" });
4927
4986
  }
4928
4987
  res.json({ success: true });
4929
4988
  });
4930
4989
  router.post("/:id/duplicate", async (req, res) => {
4931
4990
  const { id } = req.params;
4932
- const defaults = await loadDefaultSkills();
4933
- const userItems = await loadUserSkills(configDir);
4934
- const source = defaults.find((s) => s.metadata.id === id) ?? userItems.find((s) => s.metadata.id === id);
4991
+ const items = await config4.loadAll(configDir, projectDir);
4992
+ const source = config4.findById(id, items);
4935
4993
  if (!source) {
4936
- return res.status(404).json({ error: "Skill not found" });
4994
+ return res.status(404).json({ error: "Not found" });
4937
4995
  }
4938
4996
  const newId = `${id}-copy-${Date.now()}`;
4939
4997
  const duplicated = {
4940
- metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
4941
- prompt: source.prompt
4998
+ ...source,
4999
+ metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` }
4942
5000
  };
4943
- await saveSkill(configDir, duplicated);
5001
+ const destination = req.body.destination ?? "user";
5002
+ if (destination === "project") {
5003
+ if (!projectDir) return res.status(400).json({ error: "No project directory configured" });
5004
+ await config4.saveToProject(projectDir, duplicated);
5005
+ } else {
5006
+ await config4.save(configDir, duplicated);
5007
+ }
4944
5008
  res.status(201).json(duplicated);
4945
5009
  });
5010
+ config4.extraRoutes?.(router);
4946
5011
  return router;
4947
5012
  }
4948
5013
 
4949
- // src/server/routes/commands.ts
4950
- import { Router as Router2 } from "express";
5014
+ // src/server/routes/skills.ts
5015
+ var config = {
5016
+ dirName: "skills",
5017
+ ext: ".skill.md",
5018
+ loadDefaults: loadDefaultSkills,
5019
+ loadUser: loadUserSkills,
5020
+ loadProject: loadProjectSkills,
5021
+ loadAll: loadAllSkills,
5022
+ findById: findSkillById,
5023
+ save: saveSkill,
5024
+ saveToProject: saveSkillToProject,
5025
+ delete: deleteSkill,
5026
+ deleteProject: deleteProjectSkill,
5027
+ exists: skillExists,
5028
+ isDefault: isDefaultSkill,
5029
+ getDefaultIds: getDefaultSkillIds,
5030
+ validateCreate: validateNameIdPrompt,
5031
+ mapToResponse: (s) => ({
5032
+ ...s.metadata,
5033
+ enabled: isSkillEnabled(s.metadata.id)
5034
+ })
5035
+ };
5036
+ function createSkillRoutes(configDir, projectDir) {
5037
+ return createCrudRoutes(config, configDir, projectDir);
5038
+ }
4951
5039
 
4952
5040
  // src/server/commands/registry.ts
4953
5041
  import { writeFile as writeFile3, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
4954
- import { join as join4, dirname as dirname4 } from "path";
5042
+ import { join as join5, dirname as dirname4 } from "path";
4955
5043
  import { fileURLToPath as fileURLToPath3 } from "url";
4956
5044
  import matter from "gray-matter";
4957
5045
  var __bundleDir2 = dirname4(fileURLToPath3(import.meta.url));
4958
- var DEFAULTS_DIR2 = join4(__bundleDir2, "defaults");
4959
- var DEFAULTS_DIR_ALT2 = join4(__bundleDir2, "command-defaults");
5046
+ var DEFAULTS_DIR2 = join5(__bundleDir2, "defaults");
5047
+ var DEFAULTS_DIR_ALT2 = join5(__bundleDir2, "command-defaults");
4960
5048
  var COMMAND_EXTENSION = ".command.md";
4961
5049
  function getCommandsDir(configDir) {
4962
- return join4(configDir, "commands");
5050
+ return join5(configDir, "commands");
5051
+ }
5052
+ function getProjectCommandsDir(projectDir) {
5053
+ return join5(projectDir, ".openfox", "commands");
4963
5054
  }
4964
5055
  async function loadDefaultCommands() {
4965
5056
  let defaults = await loadItemsFromDir(DEFAULTS_DIR2, {
@@ -4980,7 +5071,13 @@ async function loadUserCommands(configDir) {
4980
5071
  logName: "command"
4981
5072
  });
4982
5073
  }
4983
- async function loadAllCommands(configDir) {
5074
+ async function loadProjectCommands(projectDir) {
5075
+ return loadItemsFromDir(getProjectCommandsDir(projectDir), {
5076
+ extension: COMMAND_EXTENSION,
5077
+ logName: "command"
5078
+ });
5079
+ }
5080
+ async function loadAllCommands(configDir, projectDir) {
4984
5081
  const [defaultCommands, userCommands] = await Promise.all([loadDefaultCommands(), loadUserCommands(configDir)]);
4985
5082
  const commandMap = /* @__PURE__ */ new Map();
4986
5083
  for (const cmd of defaultCommands) {
@@ -4989,6 +5086,12 @@ async function loadAllCommands(configDir) {
4989
5086
  for (const cmd of userCommands) {
4990
5087
  commandMap.set(cmd.metadata.id, cmd);
4991
5088
  }
5089
+ if (projectDir) {
5090
+ const projectCommands = await loadProjectCommands(projectDir);
5091
+ for (const cmd of projectCommands) {
5092
+ commandMap.set(cmd.metadata.id, cmd);
5093
+ }
5094
+ }
4992
5095
  return Array.from(commandMap.values());
4993
5096
  }
4994
5097
  async function getDefaultCommandIds() {
@@ -4996,10 +5099,6 @@ async function getDefaultCommandIds() {
4996
5099
  if (ids.length) return ids;
4997
5100
  return getDefaultIds(DEFAULTS_DIR_ALT2, COMMAND_EXTENSION);
4998
5101
  }
4999
- async function getDefaultCommandContent(commandId) {
5000
- const defaults = await loadDefaultCommands();
5001
- return defaults.find((c) => c.metadata.id === commandId) ?? null;
5002
- }
5003
5102
  async function isDefaultCommand(commandId) {
5004
5103
  const defaultIds = await getDefaultCommandIds();
5005
5104
  return defaultIds.includes(commandId);
@@ -5007,24 +5106,38 @@ async function isDefaultCommand(commandId) {
5007
5106
  function findCommandById(commandId, commands) {
5008
5107
  return commands.find((c) => c.metadata.id === commandId);
5009
5108
  }
5010
- async function commandExists(configDir, commandId) {
5011
- return pathExists(join4(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`));
5109
+ async function commandExists(configDir, commandId, projectDir) {
5110
+ if (await pathExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
5111
+ if (projectDir && await pathExists(join5(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
5112
+ return true;
5113
+ return false;
5012
5114
  }
5013
5115
  async function saveCommand(configDir, command) {
5014
5116
  const commandsDir = getCommandsDir(configDir);
5015
5117
  if (!await pathExists(commandsDir)) {
5016
5118
  await mkdir3(commandsDir, { recursive: true });
5017
5119
  }
5018
- const filePath = join4(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
5120
+ const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
5019
5121
  const content = matter.stringify(command.prompt, command.metadata);
5020
5122
  await writeFile3(filePath, content, "utf-8");
5021
5123
  }
5124
+ async function saveCommandToProject(projectDir, command) {
5125
+ await saveItemToDir(
5126
+ getProjectCommandsDir(projectDir),
5127
+ command,
5128
+ COMMAND_EXTENSION,
5129
+ (c) => matter.stringify(c.prompt, c.metadata)
5130
+ );
5131
+ }
5132
+ async function deleteProjectCommand(projectDir, commandId) {
5133
+ return deleteItemFromDir(getProjectCommandsDir(projectDir), commandId, COMMAND_EXTENSION);
5134
+ }
5022
5135
  async function deleteCommand(configDir, commandId) {
5023
5136
  const isDefault = await isDefaultCommand(commandId);
5024
5137
  if (isDefault) {
5025
5138
  return { success: false, reason: "Cannot delete built-in defaults" };
5026
5139
  }
5027
- const filePath = join4(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
5140
+ const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
5028
5141
  try {
5029
5142
  await unlink2(filePath);
5030
5143
  return { success: true };
@@ -5034,292 +5147,106 @@ async function deleteCommand(configDir, commandId) {
5034
5147
  }
5035
5148
 
5036
5149
  // src/server/routes/commands.ts
5037
- function createCommandRoutes(configDir) {
5038
- const router = Router2();
5039
- router.get("/", async (_req, res) => {
5040
- const [defaults, userItems] = await Promise.all([loadDefaultCommands(), loadUserCommands(configDir)]);
5041
- const overrideIds = computeOverrideIds(defaults, userItems);
5042
- res.json({
5043
- defaults: defaults.map((c) => c.metadata),
5044
- userItems: userItems.map((c) => c.metadata),
5045
- overrideIds
5046
- });
5047
- });
5048
- router.get("/defaults/:id", async (req, res) => {
5049
- const { id } = req.params;
5050
- const content = await getDefaultCommandContent(id);
5051
- if (!content) {
5052
- return res.status(404).json({ error: "Default command not found" });
5053
- }
5054
- res.json(content);
5055
- });
5056
- router.get("/default-ids", async (_req, res) => {
5057
- const ids = await getDefaultCommandIds();
5058
- res.json({ ids });
5059
- });
5060
- router.get("/:id", async (req, res) => {
5061
- const { id } = req.params;
5062
- const commands = await loadAllCommands(configDir);
5063
- const command = findCommandById(id, commands);
5064
- if (!command) {
5065
- return res.status(404).json({ error: "Command not found" });
5066
- }
5067
- res.json(command);
5068
- });
5069
- router.post("/", async (req, res) => {
5070
- const body = req.body;
5071
- if (!body.metadata?.id || !body.metadata?.name || !body.prompt) {
5072
- return res.status(400).json({ error: "Missing required fields: metadata.id, metadata.name, prompt" });
5073
- }
5074
- if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {
5075
- return res.status(400).json({ error: "Command ID must be lowercase alphanumeric with hyphens only" });
5076
- }
5077
- const exists = await commandExists(configDir, body.metadata.id);
5078
- if (exists) {
5079
- return res.status(409).json({ error: "A command with this ID already exists" });
5080
- }
5081
- await saveCommand(configDir, body);
5082
- res.status(201).json(body);
5083
- });
5084
- router.put("/:id", async (req, res) => {
5085
- const { id } = req.params;
5086
- const commands = await loadAllCommands(configDir);
5087
- const existing = findCommandById(id, commands);
5088
- if (!existing) {
5089
- return res.status(404).json({ error: "Command not found" });
5090
- }
5091
- const body = req.body;
5092
- const updated = {
5093
- metadata: { ...existing.metadata, ...body.metadata, id },
5094
- prompt: body.prompt ?? existing.prompt
5095
- };
5096
- await saveCommand(configDir, updated);
5097
- res.json(updated);
5098
- });
5099
- router.delete("/:id", async (req, res) => {
5100
- const { id } = req.params;
5101
- const result = await deleteCommand(configDir, id);
5102
- if (!result.success) {
5103
- return res.status(403).json({ error: result.reason ?? "Cannot delete this command" });
5104
- }
5105
- res.json({ success: true });
5106
- });
5107
- router.post("/:id/duplicate", async (req, res) => {
5108
- const { id } = req.params;
5109
- const defaults = await loadDefaultCommands();
5110
- const userItems = await loadUserCommands(configDir);
5111
- const source = defaults.find((c) => c.metadata.id === id) ?? userItems.find((c) => c.metadata.id === id);
5112
- if (!source) {
5113
- return res.status(404).json({ error: "Command not found" });
5114
- }
5115
- const newId = `${id}-copy-${Date.now()}`;
5116
- const duplicated = {
5117
- metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
5118
- prompt: source.prompt
5119
- };
5120
- await saveCommand(configDir, duplicated);
5121
- res.status(201).json(duplicated);
5122
- });
5123
- return router;
5150
+ var config2 = {
5151
+ dirName: "commands",
5152
+ ext: ".command.md",
5153
+ loadDefaults: loadDefaultCommands,
5154
+ loadUser: loadUserCommands,
5155
+ loadProject: loadProjectCommands,
5156
+ loadAll: loadAllCommands,
5157
+ findById: findCommandById,
5158
+ save: saveCommand,
5159
+ saveToProject: saveCommandToProject,
5160
+ delete: deleteCommand,
5161
+ deleteProject: deleteProjectCommand,
5162
+ exists: commandExists,
5163
+ isDefault: isDefaultCommand,
5164
+ getDefaultIds: getDefaultCommandIds,
5165
+ validateCreate: validateNameIdPrompt,
5166
+ mapToResponse: (c) => c.metadata
5167
+ };
5168
+ function createCommandRoutes(configDir, projectDir) {
5169
+ return createCrudRoutes(config2, configDir, projectDir);
5124
5170
  }
5125
5171
 
5126
5172
  // src/server/routes/agents.ts
5127
- import { Router as Router3 } from "express";
5128
- function createAgentRoutes(configDir) {
5129
- const router = Router3();
5130
- router.get("/", async (_req, res) => {
5131
- const [defaults, userItems] = await Promise.all([loadDefaultAgents(), loadUserAgents(configDir)]);
5132
- const overrideIds = computeOverrideIds(defaults, userItems);
5133
- res.json({
5134
- defaults: defaults.map((a) => a.metadata),
5135
- userItems: userItems.map((a) => a.metadata),
5136
- overrideIds
5137
- });
5138
- });
5139
- router.get("/defaults/:id", async (req, res) => {
5140
- const { id } = req.params;
5141
- const content = await getDefaultAgentContent(id);
5142
- if (!content) {
5143
- return res.status(404).json({ error: "Default agent not found" });
5144
- }
5145
- res.json(content);
5146
- });
5147
- router.get("/default-ids", async (_req, res) => {
5148
- const ids = await getDefaultAgentIds();
5149
- res.json({ ids });
5150
- });
5151
- router.get("/:id", async (req, res) => {
5152
- const { id } = req.params;
5153
- const agents = await loadAllAgents(configDir);
5154
- const agent = findAgentById(id, agents);
5155
- if (!agent) {
5156
- return res.status(404).json({ error: "Agent not found" });
5157
- }
5158
- res.json(agent);
5159
- });
5160
- router.post("/", async (req, res) => {
5161
- const body = req.body;
5162
- if (!body?.metadata?.id || !body?.prompt) {
5163
- return res.status(400).json({ error: "Missing required fields: metadata.id, prompt" });
5164
- }
5165
- const exists = await agentExists(configDir, body.metadata.id);
5166
- if (exists) {
5167
- return res.status(409).json({ error: "An agent with this ID already exists" });
5168
- }
5169
- await saveAgent(configDir, body);
5170
- res.status(201).json(body);
5171
- });
5172
- router.put("/:id", async (req, res) => {
5173
- const { id } = req.params;
5174
- if (!id) {
5175
- return res.status(400).json({ error: "Missing agent ID" });
5176
- }
5177
- const body = req.body;
5178
- const agents = await loadAllAgents(configDir);
5179
- const existing = findAgentById(id, agents);
5180
- if (!existing) {
5181
- return res.status(404).json({ error: "Agent not found" });
5182
- }
5183
- const updated = {
5184
- metadata: { ...existing.metadata, ...body.metadata, id },
5185
- prompt: body.prompt ?? existing.prompt
5186
- };
5187
- await saveAgent(configDir, updated);
5188
- res.json(updated);
5189
- });
5190
- router.delete("/:id", async (req, res) => {
5191
- const { id } = req.params;
5192
- const result = await deleteAgent(configDir, id);
5193
- if (!result.success) {
5194
- return res.status(403).json({ error: result.reason ?? "Cannot delete this agent" });
5195
- }
5196
- res.json({ success: true });
5197
- });
5198
- router.post("/:id/duplicate", async (req, res) => {
5199
- const { id } = req.params;
5200
- const defaults = await loadDefaultAgents();
5201
- const userItems = await loadUserAgents(configDir);
5202
- const source = defaults.find((a) => a.metadata.id === id) ?? userItems.find((a) => a.metadata.id === id);
5203
- if (!source) {
5204
- return res.status(404).json({ error: "Agent not found" });
5205
- }
5206
- const newId = `${id}-copy-${Date.now()}`;
5207
- const duplicated = {
5208
- metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` },
5209
- prompt: source.prompt
5210
- };
5211
- await saveAgent(configDir, duplicated);
5212
- res.status(201).json(duplicated);
5213
- });
5214
- return router;
5173
+ var config3 = {
5174
+ dirName: "agents",
5175
+ ext: ".agent.md",
5176
+ loadDefaults: loadDefaultAgents,
5177
+ loadUser: loadUserAgents,
5178
+ loadProject: loadProjectAgents,
5179
+ loadAll: loadAllAgents,
5180
+ findById: findAgentById,
5181
+ save: saveAgent,
5182
+ saveToProject: saveAgentToProject,
5183
+ delete: deleteAgent,
5184
+ deleteProject: deleteProjectAgent,
5185
+ exists: agentExists,
5186
+ isDefault: isDefaultAgent,
5187
+ getDefaultIds: getDefaultAgentIds,
5188
+ validateCreate: (body) => {
5189
+ const meta = body["metadata"];
5190
+ if (!meta?.["id"] || !body["prompt"]) return "Missing required fields: metadata.id, prompt";
5191
+ return null;
5192
+ },
5193
+ mapToResponse: (a) => a.metadata
5194
+ };
5195
+ function createAgentRoutes(configDir, projectDir) {
5196
+ return createCrudRoutes(config3, configDir, projectDir);
5215
5197
  }
5216
5198
 
5217
5199
  // src/server/routes/workflows.ts
5218
- import { Router as Router4 } from "express";
5219
- function createWorkflowRoutes(configDir, config) {
5220
- const router = Router4();
5221
- router.get("/", async (_req, res) => {
5222
- const [defaults, userItems] = await Promise.all([loadDefaultWorkflows(), loadUserWorkflows(configDir)]);
5223
- const overrideIds = computeOverrideIds(defaults, userItems);
5224
- res.json({
5225
- defaults: defaults.map((p) => ({ ...p.metadata, startCondition: p.startCondition })),
5226
- userItems: userItems.map((p) => ({ ...p.metadata, startCondition: p.startCondition })),
5227
- activeWorkflowId: config.activeWorkflowId ?? "default",
5228
- overrideIds
5229
- });
5230
- });
5231
- router.get("/template-variables", (_req, res) => {
5232
- res.json({ variables: TEMPLATE_VARIABLES });
5233
- });
5234
- router.get("/defaults/:id", async (req, res) => {
5235
- const { id } = req.params;
5236
- const content = await getDefaultWorkflowContent(id);
5237
- if (!content) {
5238
- return res.status(404).json({ error: "Default workflow not found" });
5239
- }
5240
- res.json(content);
5241
- });
5242
- router.get("/default-ids", async (_req, res) => {
5243
- const ids = await getDefaultWorkflowIds();
5244
- res.json({ ids });
5245
- });
5246
- router.get("/:id", async (req, res) => {
5247
- const { id } = req.params;
5248
- const workflows = await loadAllWorkflows(configDir);
5249
- const workflow = findWorkflowById(id, workflows);
5250
- if (!workflow) {
5251
- return res.status(404).json({ error: "Workflow not found" });
5252
- }
5253
- res.json(workflow);
5254
- });
5255
- router.post("/", async (req, res) => {
5256
- const body = req.body;
5257
- if (!body?.metadata?.id || !body?.steps?.length) {
5258
- return res.status(400).json({ error: "Missing required fields: metadata.id, steps" });
5259
- }
5260
- const exists = await workflowExists(configDir, body.metadata.id);
5261
- if (exists) {
5262
- return res.status(409).json({ error: "A workflow with this ID already exists" });
5263
- }
5264
- await saveWorkflow(configDir, body);
5265
- res.status(201).json(body);
5266
- });
5267
- router.put("/:id", async (req, res) => {
5268
- const { id } = req.params;
5269
- const workflows = await loadAllWorkflows(configDir);
5270
- const existing = findWorkflowById(id, workflows);
5271
- if (!existing) {
5272
- return res.status(404).json({ error: "Workflow not found" });
5273
- }
5274
- const body = req.body;
5275
- const updated = {
5276
- ...body,
5277
- metadata: { ...body.metadata, id }
5278
- };
5279
- await saveWorkflow(configDir, updated);
5280
- res.json(updated);
5281
- });
5282
- router.delete("/:id", async (req, res) => {
5283
- const { id } = req.params;
5284
- const result = await deleteWorkflow(configDir, id);
5285
- if (!result.success) {
5286
- return res.status(403).json({ error: result.reason ?? "Cannot delete this workflow" });
5287
- }
5288
- res.json({ success: true });
5289
- });
5290
- router.post("/:id/duplicate", async (req, res) => {
5291
- const { id } = req.params;
5292
- const defaults = await loadDefaultWorkflows();
5293
- const userItems = await loadUserWorkflows(configDir);
5294
- const source = defaults.find((w) => w.metadata.id === id) ?? userItems.find((w) => w.metadata.id === id);
5295
- if (!source) {
5296
- return res.status(404).json({ error: "Workflow not found" });
5200
+ import "express";
5201
+ function createWorkflowRoutes(configDir, config4, projectDir) {
5202
+ const crudConfig = {
5203
+ dirName: "workflows",
5204
+ ext: ".workflow.json",
5205
+ loadDefaults: loadDefaultWorkflows,
5206
+ loadUser: loadUserWorkflows,
5207
+ loadProject: loadProjectWorkflows,
5208
+ loadAll: loadAllWorkflows,
5209
+ findById: findWorkflowById,
5210
+ save: saveWorkflow,
5211
+ saveToProject: saveWorkflowToProject,
5212
+ delete: deleteWorkflow,
5213
+ deleteProject: deleteProjectWorkflow,
5214
+ exists: workflowExists,
5215
+ isDefault: isDefaultWorkflow,
5216
+ getDefaultIds: getDefaultWorkflowIds,
5217
+ validateCreate: (body) => {
5218
+ const steps = body["steps"];
5219
+ if (!Array.isArray(steps) || steps.length === 0) return "Missing required fields: metadata.id, steps";
5220
+ return null;
5221
+ },
5222
+ mapToResponse: (w) => ({
5223
+ ...w.metadata,
5224
+ startCondition: w.startCondition
5225
+ }),
5226
+ extraGetData: () => Promise.resolve({ activeWorkflowId: config4.activeWorkflowId ?? "default" }),
5227
+ extraRoutes: (router) => {
5228
+ router.get("/template-variables", (_req, res) => {
5229
+ res.json({ variables: TEMPLATE_VARIABLES });
5230
+ });
5297
5231
  }
5298
- const newId = `${id}-copy-${Date.now()}`;
5299
- const duplicated = {
5300
- ...source,
5301
- metadata: { ...source.metadata, id: newId, name: `${source.metadata.name} (copy)` }
5302
- };
5303
- await saveWorkflow(configDir, duplicated);
5304
- res.status(201).json(duplicated);
5305
- });
5306
- return router;
5232
+ };
5233
+ return createCrudRoutes(crudConfig, configDir, projectDir);
5307
5234
  }
5308
5235
 
5309
5236
  // src/server/routes/dev-server.ts
5310
- import { Router as Router5 } from "express";
5237
+ import { Router as Router3 } from "express";
5311
5238
  function createDevServerRoutes() {
5312
- const router = Router5();
5239
+ const router = Router3();
5313
5240
  router.get("/", async (req, res) => {
5314
5241
  const workdir = req.query["workdir"];
5315
5242
  if (!workdir) return res.status(400).json({ error: "workdir required" });
5316
5243
  const status = devServerManager.getStatus(workdir);
5317
5244
  if (!status.config) {
5318
- const config = await devServerManager.loadConfig(workdir);
5319
- if (config) {
5320
- status.config = config;
5321
- status.url = config.url;
5322
- status.hotReload = config.hotReload;
5245
+ const config4 = await devServerManager.loadConfig(workdir);
5246
+ if (config4) {
5247
+ status.config = config4;
5248
+ status.url = config4.url;
5249
+ status.hotReload = config4.hotReload;
5323
5250
  }
5324
5251
  }
5325
5252
  res.json(status);
@@ -5365,8 +5292,8 @@ function createDevServerRoutes() {
5365
5292
  router.get("/config", async (req, res) => {
5366
5293
  const workdir = req.query["workdir"];
5367
5294
  if (!workdir) return res.status(400).json({ error: "workdir required" });
5368
- const config = await devServerManager.loadConfig(workdir);
5369
- res.json({ config });
5295
+ const config4 = await devServerManager.loadConfig(workdir);
5296
+ res.json({ config: config4 });
5370
5297
  });
5371
5298
  router.post("/config", async (req, res) => {
5372
5299
  const workdir = req.query["workdir"];
@@ -5376,9 +5303,9 @@ function createDevServerRoutes() {
5376
5303
  return res.status(400).json({ error: "command and url are required" });
5377
5304
  }
5378
5305
  try {
5379
- const config = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
5380
- await devServerManager.saveConfig(workdir, config);
5381
- res.json({ config });
5306
+ const config4 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
5307
+ await devServerManager.saveConfig(workdir, config4);
5308
+ res.json({ config: config4 });
5382
5309
  } catch (err) {
5383
5310
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
5384
5311
  }
@@ -5387,9 +5314,9 @@ function createDevServerRoutes() {
5387
5314
  }
5388
5315
 
5389
5316
  // src/server/routes/terminals.ts
5390
- import { Router as Router6 } from "express";
5317
+ import { Router as Router4 } from "express";
5391
5318
  function createTerminalRoutes() {
5392
- const router = Router6();
5319
+ const router = Router4();
5393
5320
  router.get("/", (req, res) => {
5394
5321
  const projectId = req.query["projectId"];
5395
5322
  const sessions = projectId ? terminalManager.getByProject(projectId) : [];
@@ -5428,16 +5355,16 @@ function createTerminalRoutes() {
5428
5355
  }
5429
5356
 
5430
5357
  // src/server/routes/auto-update.ts
5431
- import { Router as Router7 } from "express";
5358
+ import { Router as Router5 } from "express";
5432
5359
  import { spawn as spawn4 } from "child_process";
5433
5360
 
5434
5361
  // src/constants.ts
5435
- var VERSION = "1.6.91";
5362
+ var VERSION = "1.6.92";
5436
5363
 
5437
5364
  // src/server/routes/auto-update.ts
5438
5365
  var updateInProgress = false;
5439
5366
  function createAutoUpdateRoutes(options = {}) {
5440
- const router = Router7();
5367
+ const router = Router5();
5441
5368
  router.get("/check", async (req, res) => {
5442
5369
  const isTest = req.query["test"] === "1";
5443
5370
  const current = VERSION;
@@ -5518,14 +5445,14 @@ function createAutoUpdateRoutes(options = {}) {
5518
5445
 
5519
5446
  // src/server/index.ts
5520
5447
  var __dirname2 = dirname5(fileURLToPath4(import.meta.url));
5521
- async function createServerHandle(config) {
5522
- setRuntimeConfig(config);
5523
- setLogLevel(config.logging?.level ?? void 0, config.mode);
5448
+ async function createServerHandle(config4) {
5449
+ setRuntimeConfig(config4);
5450
+ setLogLevel(config4.logging?.level ?? void 0, config4.mode);
5524
5451
  await loadServerAuthConfig();
5525
- const db = initDatabase(config);
5452
+ const db = initDatabase(config4);
5526
5453
  initEventStore(db);
5527
- const configDir = getGlobalConfigDir(config.mode ?? "production");
5528
- const providerManager = createProviderManager(config);
5454
+ const configDir = getGlobalConfigDir(config4.mode ?? "production");
5455
+ const providerManager = createProviderManager(config4);
5529
5456
  const sessionManager = new SessionManager(providerManager);
5530
5457
  devServerManager.setSessionManager(sessionManager);
5531
5458
  const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
@@ -5538,20 +5465,20 @@ async function createServerHandle(config) {
5538
5465
  const llmClient = getLLMClient();
5539
5466
  let backend;
5540
5467
  const useMock2 = process.env["OPENFOX_MOCK_LLM"] === "true";
5541
- if (config.llm.backend === "auto") {
5542
- backend = await detectBackend(config.llm.baseUrl, void 0, useMock2);
5468
+ if (config4.llm.backend === "auto") {
5469
+ backend = await detectBackend(config4.llm.baseUrl, void 0, useMock2);
5543
5470
  llmClient.setBackend(backend);
5544
5471
  if (!useMock2) {
5545
5472
  logger.info("Auto-detected LLM backend", { backend: getBackendDisplayName(backend) });
5546
5473
  }
5547
5474
  } else {
5548
- backend = config.llm.backend;
5475
+ backend = config4.llm.backend;
5549
5476
  llmClient.setBackend(backend);
5550
5477
  if (!useMock2) {
5551
5478
  logger.info("Using configured LLM backend", { backend: getBackendDisplayName(backend) });
5552
5479
  }
5553
5480
  }
5554
- const detected = await detectModel(config.llm.baseUrl);
5481
+ const detected = await detectModel(config4.llm.baseUrl);
5555
5482
  if (detected) {
5556
5483
  llmClient.setModel(detected);
5557
5484
  if (!useMock2) {
@@ -5559,7 +5486,7 @@ async function createServerHandle(config) {
5559
5486
  }
5560
5487
  } else {
5561
5488
  if (!useMock2) {
5562
- logger.warn("Could not auto-detect model, using config", { model: config.llm.model });
5489
+ logger.warn("Could not auto-detect model, using config", { model: config4.llm.model });
5563
5490
  }
5564
5491
  }
5565
5492
  const activeProvider = providerManager.getActiveProvider();
@@ -5729,7 +5656,7 @@ async function createServerHandle(config) {
5729
5656
  res.json({ project });
5730
5657
  });
5731
5658
  app.get("/api/sessions", async (req, res) => {
5732
- const { getRecentUserPromptsForSession } = await import("./events-AQKDXJFK.js");
5659
+ const { getRecentUserPromptsForSession } = await import("./events-K6AYMXFT.js");
5733
5660
  const projectId = req.query["projectId"];
5734
5661
  const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
5735
5662
  const offset = parseInt(req.query["offset"]) || 0;
@@ -5757,12 +5684,12 @@ async function createServerHandle(config) {
5757
5684
  if (!project) {
5758
5685
  return res.status(404).json({ error: "Project not found" });
5759
5686
  }
5760
- const { providerId, model } = parseDefaultModelSelection(config.defaultModelSelection);
5687
+ const { providerId, model } = parseDefaultModelSelection(config4.defaultModelSelection);
5761
5688
  const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
5762
5689
  res.status(201).json({ session });
5763
5690
  });
5764
5691
  app.get("/api/sessions/:id", async (req, res) => {
5765
- const { getEventStore: getEventStore2 } = await import("./events-AQKDXJFK.js");
5692
+ const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
5766
5693
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
5767
5694
  const session = sessionManager.getSession(req.params.id);
5768
5695
  if (!session) {
@@ -5793,7 +5720,7 @@ async function createServerHandle(config) {
5793
5720
  res.json({ success: true });
5794
5721
  });
5795
5722
  app.post("/api/sessions/:id/provider", async (req, res) => {
5796
- const { getEventStore: getEventStore2 } = await import("./events-AQKDXJFK.js");
5723
+ const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
5797
5724
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
5798
5725
  const sessionId = req.params.id;
5799
5726
  const session = sessionManager.getSession(sessionId);
@@ -5805,11 +5732,11 @@ async function createServerHandle(config) {
5805
5732
  return res.status(400).json({ error: "providerId is required" });
5806
5733
  }
5807
5734
  sessionManager.setSessionProvider(sessionId, providerId, model ?? "auto");
5808
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GEDIDCBM.js");
5809
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
5735
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-7XJQNOKX.js");
5736
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
5810
5737
  const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model ?? "auto");
5811
- await saveGlobalConfig(config.mode ?? "production", updatedConfig);
5812
- config.defaultModelSelection = updatedConfig.defaultModelSelection;
5738
+ await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
5739
+ config4.defaultModelSelection = updatedConfig.defaultModelSelection;
5813
5740
  const contextState = sessionManager.getContextState(sessionId);
5814
5741
  const eventStore = getEventStore2();
5815
5742
  const events = eventStore.getEvents(sessionId);
@@ -5831,7 +5758,7 @@ async function createServerHandle(config) {
5831
5758
  res.json({ success: true });
5832
5759
  });
5833
5760
  app.put("/api/sessions/:id/mode", async (req, res) => {
5834
- const { getEventStore: getEventStore2 } = await import("./events-AQKDXJFK.js");
5761
+ const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
5835
5762
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-4VHGQE6Y.js");
5836
5763
  const sessionId = req.params.id;
5837
5764
  const session = sessionManager.getSession(sessionId);
@@ -5888,12 +5815,12 @@ async function createServerHandle(config) {
5888
5815
  if (!callId || approved === void 0) {
5889
5816
  return res.status(400).json({ error: "callId and approved are required" });
5890
5817
  }
5891
- const { providePathConfirmation } = await import("./tools-ZBAAAOUH.js");
5818
+ const { providePathConfirmation } = await import("./tools-NFFQWH6M.js");
5892
5819
  const result = providePathConfirmation(callId, approved, alwaysAllow);
5893
5820
  if (!result.found) {
5894
5821
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
5895
5822
  }
5896
- const { getEventStore: getEventStore2 } = await import("./events-AQKDXJFK.js");
5823
+ const { getEventStore: getEventStore2 } = await import("./events-K6AYMXFT.js");
5897
5824
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations: foldPendingConfirmations2 } = await import("./folding-4VHGQE6Y.js");
5898
5825
  const { createSessionStateMessage: createSessionStateMessage2 } = await import("./protocol-QDSVJTRN.js");
5899
5826
  const eventStore = getEventStore2();
@@ -5912,7 +5839,7 @@ async function createServerHandle(config) {
5912
5839
  if (!callId || !answer) {
5913
5840
  return res.status(400).json({ error: "callId and answer are required" });
5914
5841
  }
5915
- const { provideAnswer: provideAnswer2 } = await import("./tools-ZBAAAOUH.js");
5842
+ const { provideAnswer: provideAnswer2 } = await import("./tools-NFFQWH6M.js");
5916
5843
  const found = provideAnswer2(callId, answer);
5917
5844
  if (!found) {
5918
5845
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -5948,14 +5875,14 @@ async function createServerHandle(config) {
5948
5875
  if (!session) {
5949
5876
  return res.status(404).json({ error: "Session not found" });
5950
5877
  }
5951
- const { stopSessionExecution } = await import("./chat-handler-O4FNSVPI.js");
5952
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-ZBAAAOUH.js");
5878
+ const { stopSessionExecution } = await import("./chat-handler-UPAEF6HR.js");
5879
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-NFFQWH6M.js");
5953
5880
  stopSessionExecution(sessionId, sessionManager);
5954
5881
  abortSession(sessionId);
5955
5882
  cancelQuestionsForSession(sessionId, "Session stopped by user");
5956
5883
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
5957
5884
  sessionManager.clearMessageQueue(sessionId);
5958
- const eventStore = (await import("./events-AQKDXJFK.js")).getEventStore();
5885
+ const eventStore = (await import("./events-K6AYMXFT.js")).getEventStore();
5959
5886
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
5960
5887
  res.json({ success: true });
5961
5888
  });
@@ -5969,7 +5896,7 @@ async function createServerHandle(config) {
5969
5896
  if (typeof messageIndex !== "number" || messageIndex < 0) {
5970
5897
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
5971
5898
  }
5972
- const { truncateSessionMessages } = await import("./events-AQKDXJFK.js");
5899
+ const { truncateSessionMessages } = await import("./events-K6AYMXFT.js");
5973
5900
  truncateSessionMessages(sessionId, messageIndex);
5974
5901
  res.json({ success: true });
5975
5902
  });
@@ -6021,8 +5948,8 @@ async function createServerHandle(config) {
6021
5948
  let visionFallback;
6022
5949
  let globalWorkdir;
6023
5950
  try {
6024
- const { loadGlobalConfig, getVisionFallback } = await import("./config-GEDIDCBM.js");
6025
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
5951
+ const { loadGlobalConfig, getVisionFallback } = await import("./config-7XJQNOKX.js");
5952
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6026
5953
  const fallback = getVisionFallback(globalConfig);
6027
5954
  if (fallback) {
6028
5955
  visionFallback = {
@@ -6039,13 +5966,13 @@ async function createServerHandle(config) {
6039
5966
  version: VERSION,
6040
5967
  model: llmClient.getModel(),
6041
5968
  maxContext: providerManager.getCurrentModelContext(),
6042
- llmUrl: activeProvider?.url ?? config.llm.baseUrl,
5969
+ llmUrl: activeProvider?.url ?? config4.llm.baseUrl,
6043
5970
  llmStatus: getLlmStatus(),
6044
5971
  backend: llmClient.getBackend(),
6045
- workdir: globalWorkdir ?? config.workdir,
5972
+ workdir: globalWorkdir ?? config4.workdir,
6046
5973
  providers: providerManager.getProviders(),
6047
5974
  activeProviderId: providerManager.getActiveProviderId(),
6048
- defaultModelSelection: config.defaultModelSelection,
5975
+ defaultModelSelection: config4.defaultModelSelection,
6049
5976
  visionFallback
6050
5977
  });
6051
5978
  });
@@ -6054,7 +5981,7 @@ async function createServerHandle(config) {
6054
5981
  const currentModel = providerManager.getCurrentModel();
6055
5982
  if (currentModel === "auto") {
6056
5983
  const activeProvider = providerManager.getActiveProvider();
6057
- const baseUrl = activeProvider?.url ?? config.llm.baseUrl;
5984
+ const baseUrl = activeProvider?.url ?? config4.llm.baseUrl;
6058
5985
  const detected = await detectModel(baseUrl);
6059
5986
  if (detected) {
6060
5987
  llmClient.setModel(detected);
@@ -6100,8 +6027,8 @@ async function createServerHandle(config) {
6100
6027
  return res.status(400).json({ error: "name, url, and backend are required" });
6101
6028
  }
6102
6029
  try {
6103
- const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-GEDIDCBM.js");
6104
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
6030
+ const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-7XJQNOKX.js");
6031
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6105
6032
  const providerBackend = backend;
6106
6033
  const configWithProvider = addProvider(globalConfig, {
6107
6034
  name,
@@ -6116,7 +6043,7 @@ async function createServerHandle(config) {
6116
6043
  configWithProvider.providers[configWithProvider.providers.length - 1].id,
6117
6044
  model ?? "auto"
6118
6045
  );
6119
- await saveGlobalConfig(config.mode ?? "production", finalConfig);
6046
+ await saveGlobalConfig(config4.mode ?? "production", finalConfig);
6120
6047
  providerManager.setProviders(finalConfig.providers, finalConfig.defaultModelSelection ?? void 0);
6121
6048
  const newProvider = finalConfig.providers[finalConfig.providers.length - 1];
6122
6049
  res.status(201).json({
@@ -6133,14 +6060,14 @@ async function createServerHandle(config) {
6133
6060
  app.post("/api/init/config", async (req, res) => {
6134
6061
  const { workdir, visionFallback } = req.body;
6135
6062
  try {
6136
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GEDIDCBM.js");
6137
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
6063
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-7XJQNOKX.js");
6064
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6138
6065
  const updatedConfig = {
6139
6066
  ...globalConfig,
6140
6067
  workspace: workdir ? { workdir } : globalConfig.workspace,
6141
6068
  visionFallback: visionFallback ?? globalConfig.visionFallback
6142
6069
  };
6143
- await saveGlobalConfig(config.mode ?? "production", updatedConfig);
6070
+ await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
6144
6071
  res.json({ success: true });
6145
6072
  } catch (error) {
6146
6073
  res.status(500).json({
@@ -6161,10 +6088,10 @@ async function createServerHandle(config) {
6161
6088
  });
6162
6089
  app.delete("/api/providers/:id", async (req, res) => {
6163
6090
  const { id } = req.params;
6164
- const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-GEDIDCBM.js");
6165
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
6091
+ const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-7XJQNOKX.js");
6092
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6166
6093
  const updatedConfig = removeProvider(globalConfig, id);
6167
- await saveGlobalConfig(config.mode ?? "production", updatedConfig);
6094
+ await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
6168
6095
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
6169
6096
  res.json({ success: true });
6170
6097
  });
@@ -6181,10 +6108,10 @@ async function createServerHandle(config) {
6181
6108
  return res.status(400).json({ error: result.error });
6182
6109
  }
6183
6110
  const llmClient = getLLMClient();
6184
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-GEDIDCBM.js");
6185
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
6111
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-7XJQNOKX.js");
6112
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6186
6113
  const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
6187
- await saveGlobalConfig(config.mode ?? "production", updatedConfig);
6114
+ await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
6188
6115
  res.json({
6189
6116
  success: true,
6190
6117
  activeProviderId: id,
@@ -6212,8 +6139,8 @@ async function createServerHandle(config) {
6212
6139
  if (!result.success) {
6213
6140
  return res.status(400).json({ error: result.error });
6214
6141
  }
6215
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-GEDIDCBM.js");
6216
- const globalConfig = await loadGlobalConfig(config.mode ?? "production");
6142
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-7XJQNOKX.js");
6143
+ const globalConfig = await loadGlobalConfig(config4.mode ?? "production");
6217
6144
  const updatedProviders = providerManager.getProviders();
6218
6145
  const updatedConfig = {
6219
6146
  ...globalConfig,
@@ -6221,7 +6148,7 @@ async function createServerHandle(config) {
6221
6148
  activeProviderId: providerManager.getActiveProviderId(),
6222
6149
  defaultModelSelection: providerManager.getActiveProviderId() ? `${providerManager.getActiveProviderId()}/${providerManager.getCurrentModel()}` : void 0
6223
6150
  };
6224
- await saveGlobalConfig(config.mode ?? "production", updatedConfig);
6151
+ await saveGlobalConfig(config4.mode ?? "production", updatedConfig);
6225
6152
  let contextState = null;
6226
6153
  const sessions = sessionManager.listSessions();
6227
6154
  if (sessions.length > 0) {
@@ -6256,10 +6183,11 @@ async function createServerHandle(config) {
6256
6183
  status: updatedProvider?.status ?? "unknown"
6257
6184
  });
6258
6185
  });
6259
- app.use("/api/skills", createSkillRoutes(configDir));
6260
- app.use("/api/commands", createCommandRoutes(configDir));
6261
- app.use("/api/agents", createAgentRoutes(configDir));
6262
- app.use("/api/workflows", createWorkflowRoutes(configDir, config));
6186
+ const projectDir = config4.workdir;
6187
+ app.use("/api/skills", createSkillRoutes(configDir, projectDir));
6188
+ app.use("/api/commands", createCommandRoutes(configDir, projectDir));
6189
+ app.use("/api/agents", createAgentRoutes(configDir, projectDir));
6190
+ app.use("/api/workflows", createWorkflowRoutes(configDir, config4, projectDir));
6263
6191
  app.use("/api/dev-server", createDevServerRoutes());
6264
6192
  app.use("/api/terminals", createTerminalRoutes());
6265
6193
  app.use(
@@ -6309,7 +6237,7 @@ async function createServerHandle(config) {
6309
6237
  const entries = await import("fs/promises").then((m) => m.readdir(resolvedPath, { withFileTypes: true }));
6310
6238
  const directories = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => ({
6311
6239
  name: entry.name,
6312
- path: join5(resolvedPath, entry.name)
6240
+ path: join6(resolvedPath, entry.name)
6313
6241
  })).sort((a, b) => a.name.localeCompare(b.name));
6314
6242
  const parent = dirname5(resolvedPath);
6315
6243
  const hasParent = parent !== resolvedPath;
@@ -6330,7 +6258,7 @@ async function createServerHandle(config) {
6330
6258
  }
6331
6259
  });
6332
6260
  const webDir = resolve(__dirname2, "../../web");
6333
- const isDev = config.mode === "development";
6261
+ const isDev = config4.mode === "development";
6334
6262
  let viteServer;
6335
6263
  if (isDev) {
6336
6264
  logger.info("Dev mode: using Vite middleware");
@@ -6356,7 +6284,7 @@ async function createServerHandle(config) {
6356
6284
  }
6357
6285
  });
6358
6286
  app.get("/fox.svg", (_req, res) => {
6359
- readFile3(join5(webDir, "fox.svg")).then((content) => {
6287
+ readFile3(join6(webDir, "fox.svg")).then((content) => {
6360
6288
  res.set("Content-Type", "image/svg+xml");
6361
6289
  res.send(content);
6362
6290
  }).catch(() => {
@@ -6365,7 +6293,7 @@ async function createServerHandle(config) {
6365
6293
  });
6366
6294
  app.use(
6367
6295
  "/sounds",
6368
- express.static(join5(webDir, "public", "sounds"), {
6296
+ express.static(join6(webDir, "public", "sounds"), {
6369
6297
  setHeaders: (res) => {
6370
6298
  res.set("Content-Type", "audio/mpeg");
6371
6299
  }
@@ -6374,24 +6302,24 @@ async function createServerHandle(config) {
6374
6302
  app.use("/__inspect__.js", (_req, res) => {
6375
6303
  res.set("Access-Control-Allow-Origin", "*");
6376
6304
  res.set("Content-Type", "application/javascript");
6377
- readFile3(join5(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6305
+ readFile3(join6(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6378
6306
  });
6379
6307
  app.get("/*path", (req, res) => {
6380
6308
  if (req.path.startsWith("/api/")) {
6381
6309
  return;
6382
6310
  }
6383
- readFile3(join5(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6311
+ readFile3(join6(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6384
6312
  logger.error("Error serving index.html", { error: err });
6385
6313
  res.status(500).send("Server error");
6386
6314
  });
6387
6315
  });
6388
- logger.info("Vite middleware ready", { port: config.server.port });
6316
+ logger.info("Vite middleware ready", { port: config4.server.port });
6389
6317
  }
6390
6318
  if (!isDev) {
6391
6319
  const distWebDir = resolve(__dirname2, "web");
6392
6320
  app.use(
6393
6321
  "/assets",
6394
- express.static(join5(distWebDir, "assets"), {
6322
+ express.static(join6(distWebDir, "assets"), {
6395
6323
  setHeaders: (res, filepath) => {
6396
6324
  if (filepath.endsWith(".css")) {
6397
6325
  res.set("Content-Type", "text/css");
@@ -6399,11 +6327,11 @@ async function createServerHandle(config) {
6399
6327
  }
6400
6328
  })
6401
6329
  );
6402
- app.use("/manifest.webmanifest", express.static(join5(distWebDir, "manifest.webmanifest")));
6403
- app.use("/registerSW.js", express.static(join5(distWebDir, "registerSW.js")));
6404
- app.use("/sw.js", express.static(join5(distWebDir, "sw.js")));
6330
+ app.use("/manifest.webmanifest", express.static(join6(distWebDir, "manifest.webmanifest")));
6331
+ app.use("/registerSW.js", express.static(join6(distWebDir, "registerSW.js")));
6332
+ app.use("/sw.js", express.static(join6(distWebDir, "sw.js")));
6405
6333
  app.get("/fox.svg", (_req, res) => {
6406
- readFile3(join5(distWebDir, "fox.svg")).then((content) => {
6334
+ readFile3(join6(distWebDir, "fox.svg")).then((content) => {
6407
6335
  res.set("Content-Type", "image/svg+xml");
6408
6336
  res.send(content);
6409
6337
  }).catch(() => {
@@ -6412,7 +6340,7 @@ async function createServerHandle(config) {
6412
6340
  });
6413
6341
  app.use(
6414
6342
  "/sounds",
6415
- express.static(join5(distWebDir, "sounds"), {
6343
+ express.static(join6(distWebDir, "sounds"), {
6416
6344
  setHeaders: (res) => {
6417
6345
  res.set("Content-Type", "audio/mpeg");
6418
6346
  }
@@ -6421,15 +6349,15 @@ async function createServerHandle(config) {
6421
6349
  app.use("/__inspect__.js", (_req, res) => {
6422
6350
  res.set("Access-Control-Allow-Origin", "*");
6423
6351
  res.set("Content-Type", "application/javascript");
6424
- readFile3(join5(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6352
+ readFile3(join6(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6425
6353
  });
6426
6354
  app.use("/__inspect__.js", (_req, res) => {
6427
6355
  res.set("Access-Control-Allow-Origin", "*");
6428
6356
  res.set("Content-Type", "application/javascript");
6429
- readFile3(join5(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6357
+ readFile3(join6(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6430
6358
  });
6431
6359
  app.get("/", (_req, res) => {
6432
- readFile3(join5(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6360
+ readFile3(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6433
6361
  res.status(404).send("Web UI not built. Run `npm run build:web`");
6434
6362
  });
6435
6363
  });
@@ -6437,7 +6365,7 @@ async function createServerHandle(config) {
6437
6365
  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") {
6438
6366
  return;
6439
6367
  }
6440
- readFile3(join5(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6368
+ readFile3(join6(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6441
6369
  res.status(404).send("Web UI not built");
6442
6370
  });
6443
6371
  });
@@ -6445,14 +6373,14 @@ async function createServerHandle(config) {
6445
6373
  const httpServer = createHttpServer(app);
6446
6374
  const wssExports = createWebSocketServer(
6447
6375
  httpServer,
6448
- config,
6376
+ config4,
6449
6377
  getLLMClient,
6450
6378
  () => providerManager.getActiveProvider(),
6451
6379
  sessionManager,
6452
6380
  providerManager
6453
6381
  );
6454
6382
  const wss = wssExports.wss;
6455
- const { QueueProcessor } = await import("./processor-XL5NULQN.js");
6383
+ const { QueueProcessor } = await import("./processor-D4XQ5QMB.js");
6456
6384
  const queueProcessor = new QueueProcessor({
6457
6385
  sessionManager,
6458
6386
  providerManager,
@@ -6471,17 +6399,17 @@ async function createServerHandle(config) {
6471
6399
  };
6472
6400
  return {
6473
6401
  httpServer,
6474
- ctx: { config, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
6402
+ ctx: { config: config4, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
6475
6403
  start: (port) => new Promise((resolve2, reject) => {
6476
- const listenPort = port ?? config.server.port;
6477
- const host = config.server.host;
6404
+ const listenPort = port ?? config4.server.port;
6405
+ const host = config4.server.host;
6478
6406
  httpServer.listen(listenPort, host, () => {
6479
6407
  const addr = httpServer.address();
6480
6408
  const actualPort = typeof addr === "object" && addr ? addr.port : listenPort;
6481
6409
  const client = getLLMClient();
6482
6410
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
6483
6411
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
6484
- logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config.llm.baseUrl}`);
6412
+ logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config4.llm.baseUrl}`);
6485
6413
  resolve2({ port: actualPort });
6486
6414
  });
6487
6415
  httpServer.on("error", reject);
@@ -6504,8 +6432,8 @@ async function createServerHandle(config) {
6504
6432
  })
6505
6433
  };
6506
6434
  }
6507
- async function createServer(config) {
6508
- const handle = await createServerHandle(config);
6435
+ async function createServer(config4) {
6436
+ const handle = await createServerHandle(config4);
6509
6437
  await handle.start();
6510
6438
  const shutdown = () => {
6511
6439
  const forceExitTimer = setTimeout(() => {
@@ -6527,4 +6455,4 @@ export {
6527
6455
  createServerHandle,
6528
6456
  createServer
6529
6457
  };
6530
- //# sourceMappingURL=chunk-UQSL65WB.js.map
6458
+ //# sourceMappingURL=chunk-2BS6LMIU.js.map