openfox 2.0.67 → 2.0.68

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 (38) hide show
  1. package/dist/{chat-handler-72DFHK5K.js → chat-handler-QFEHJBWN.js} +6 -6
  2. package/dist/{chunk-MQHMT5WF.js → chunk-32KLLK4N.js} +3 -3
  3. package/dist/{chunk-TMHWQYWE.js → chunk-64GN6OPR.js} +2 -2
  4. package/dist/{chunk-YU6DZAVA.js → chunk-6LK47TNE.js} +15 -95
  5. package/dist/{chunk-5EO6SEGV.js → chunk-7OW6X764.js} +2 -2
  6. package/dist/{chunk-B6JUWVTK.js → chunk-COWJRBV4.js} +5 -5
  7. package/dist/{chunk-2GRUQN2B.js → chunk-DWZEGLHJ.js} +251 -57
  8. package/dist/{chunk-B7WGOK7G.js → chunk-E4POUD2M.js} +2 -2
  9. package/dist/{chunk-PYRH4G2J.js → chunk-FCLCEIY4.js} +5 -5
  10. package/dist/{chunk-BL5LOLVA.js → chunk-JHGKXQBO.js} +161 -28
  11. package/dist/{chunk-TJO4QFDQ.js → chunk-QFSDJIUS.js} +2 -2
  12. package/dist/{chunk-ZLON3JTI.js → chunk-YQ3MEZJL.js} +2 -2
  13. package/dist/cli/dev.js +1 -1
  14. package/dist/cli/index.js +1 -1
  15. package/dist/{client-BUX62J2K.js → client-63U5CTPE.js} +3 -3
  16. package/dist/{client-pure-U6ZYUPJQ.js → client-pure-XHH4RRLB.js} +2 -2
  17. package/dist/{compactor-74CZVUWI.js → compactor-IPMMFFHM.js} +4 -4
  18. package/dist/{orchestrator-FEMPJOZD.js → orchestrator-GNXKJPX4.js} +5 -5
  19. package/dist/package.json +3 -2
  20. package/dist/{processor-QB3NMRMO.js → processor-TIQEQDP7.js} +6 -6
  21. package/dist/{protocol-42f_Png6.d.ts → protocol-DIhV-tAc.d.ts} +1 -1
  22. package/dist/provider/index.d.ts +4 -4
  23. package/dist/{provider-BDH6JGZB.js → provider-IBIWR4AI.js} +4 -4
  24. package/dist/{provider-manager-D3KIOD5E.js → provider-manager-7C3JVOLW.js} +4 -4
  25. package/dist/{serve-32FAA4FX.js → serve-QVVZ5SJE.js} +10 -10
  26. package/dist/server/index.d.ts +3 -3
  27. package/dist/server/index.js +9 -9
  28. package/dist/{server-OYE7GERR.js → server-ECKS2Y3R.js} +7 -7
  29. package/dist/shared/index.d.ts +3 -3
  30. package/dist/{tools-INWP6FGV.js → tools-QAEN5KHA.js} +4 -4
  31. package/dist/{types-vezAEt_y.d.ts → types-BsfYpEai.d.ts} +2 -1
  32. package/dist/{types-apiMd7Df.d.ts → types-CBC6lLqc.d.ts} +1 -1
  33. package/dist/web/assets/{index-BELeAs12.css → index-BA_65WJ5.css} +1 -1
  34. package/dist/web/assets/{index-C3n65CNu.js → index-CsZQdTAd.js} +74 -74
  35. package/dist/web/index.html +2 -2
  36. package/dist/web/sw.js +1 -1
  37. package/package.json +3 -2
  38. package/plugins-registry.json +14 -0
@@ -21,7 +21,7 @@ import {
21
21
  tokenFromPassword,
22
22
  verifyPassword,
23
23
  workflowExists
24
- } from "./chunk-B6JUWVTK.js";
24
+ } from "./chunk-COWJRBV4.js";
25
25
  import {
26
26
  agentExists,
27
27
  createToolRegistry,
@@ -66,12 +66,12 @@ import {
66
66
  setSkillEnabled,
67
67
  skillExists,
68
68
  updateOwnedSkill
69
- } from "./chunk-YU6DZAVA.js";
69
+ } from "./chunk-6LK47TNE.js";
70
70
  import {
71
71
  ALWAYS_ALLOWED,
72
72
  ALWAYS_ALLOWED_FOR_SUBAGENTS,
73
73
  TOP_LEVEL_ONLY_TOOLS
74
- } from "./chunk-TJO4QFDQ.js";
74
+ } from "./chunk-QFSDJIUS.js";
75
75
  import {
76
76
  getProject
77
77
  } from "./chunk-KXVFHMSM.js";
@@ -133,7 +133,7 @@ import {
133
133
  detectModel,
134
134
  getLlmStatus,
135
135
  parseDefaultModelSelection
136
- } from "./chunk-5EO6SEGV.js";
136
+ } from "./chunk-7OW6X764.js";
137
137
  import {
138
138
  getModelProfile
139
139
  } from "./chunk-V4IE7HJY.js";
@@ -161,9 +161,9 @@ import {
161
161
  import express from "express";
162
162
  import cors from "cors";
163
163
  import { createServer as createHttpServer } from "http";
164
- import { fileURLToPath as fileURLToPath6 } from "url";
165
- import { dirname as dirname7, resolve as resolve6, join as join9 } from "path";
166
- import { readFile as readFile4 } from "fs/promises";
164
+ import { fileURLToPath as fileURLToPath7 } from "url";
165
+ import { dirname as dirname8, resolve as resolve7, join as join10 } from "path";
166
+ import { readFile as readFile5 } from "fs/promises";
167
167
  import { createServer as createViteServer } from "vite";
168
168
 
169
169
  // src/server/llm/mock.ts
@@ -1955,19 +1955,19 @@ var LspServer = class {
1955
1955
  */
1956
1956
  async getDiagnosticsWithWait(path, timeoutMs = DIAGNOSTIC_WAIT_MS) {
1957
1957
  if (this.openDocuments.has(path)) {
1958
- return new Promise((resolve7) => {
1958
+ return new Promise((resolve8) => {
1959
1959
  const existing = this.diagnostics.get(path);
1960
1960
  if (existing !== void 0) {
1961
1961
  setTimeout(() => {
1962
- resolve7(this.diagnostics.get(path) ?? []);
1962
+ resolve8(this.diagnostics.get(path) ?? []);
1963
1963
  }, 100);
1964
1964
  return;
1965
1965
  }
1966
1966
  const timeout = setTimeout(() => {
1967
1967
  this.pendingDiagnostics.delete(path);
1968
- resolve7(this.diagnostics.get(path) ?? []);
1968
+ resolve8(this.diagnostics.get(path) ?? []);
1969
1969
  }, timeoutMs);
1970
- this.pendingDiagnostics.set(path, { resolve: resolve7, timeout });
1970
+ this.pendingDiagnostics.set(path, { resolve: resolve8, timeout });
1971
1971
  });
1972
1972
  }
1973
1973
  return this.diagnostics.get(path) ?? [];
@@ -4257,7 +4257,7 @@ import { Router as Router9 } from "express";
4257
4257
  import { spawn as spawn2 } from "child_process";
4258
4258
 
4259
4259
  // src/constants.ts
4260
- var VERSION = "2.0.67";
4260
+ var VERSION = "2.0.68";
4261
4261
 
4262
4262
  // src/server/routes/auto-update.ts
4263
4263
  var updateInProgress = false;
@@ -4280,7 +4280,7 @@ function createAutoUpdateRoutes(options = {}) {
4280
4280
  const isService = isRunningAsService();
4281
4281
  const current = VERSION;
4282
4282
  try {
4283
- const latest = await new Promise((resolve7, reject) => {
4283
+ const latest = await new Promise((resolve8, reject) => {
4284
4284
  const child = spawn2("npm", ["view", "openfox", "version"], {
4285
4285
  stdio: ["ignore", "pipe", "pipe"],
4286
4286
  windowsHide: true
@@ -4291,7 +4291,7 @@ function createAutoUpdateRoutes(options = {}) {
4291
4291
  });
4292
4292
  child.on("close", (code) => {
4293
4293
  if (code === 0) {
4294
- resolve7(stdout.trim());
4294
+ resolve8(stdout.trim());
4295
4295
  } else {
4296
4296
  reject(new Error(`npm view exited with code ${code}`));
4297
4297
  }
@@ -4335,9 +4335,9 @@ function createAutoUpdateRoutes(options = {}) {
4335
4335
  const timeout = setTimeout(() => {
4336
4336
  child.kill();
4337
4337
  }, UPDATE_TIMEOUT);
4338
- const exitCode = await new Promise((resolve7) => {
4339
- child.on("close", resolve7);
4340
- child.on("error", () => resolve7(1));
4338
+ const exitCode = await new Promise((resolve8) => {
4339
+ child.on("close", resolve8);
4340
+ child.on("error", () => resolve8(1));
4341
4341
  });
4342
4342
  clearTimeout(timeout);
4343
4343
  if (exitCode === 0) {
@@ -4500,7 +4500,9 @@ var ProviderRegistry = class {
4500
4500
  }
4501
4501
  register(map, id, value, kind) {
4502
4502
  if (!id.trim()) throw new Error(`Provider ${kind} id cannot be empty`);
4503
- if (map.has(id)) throw new Error(`Provider ${kind} already registered: ${id}`);
4503
+ if (map.has(id)) {
4504
+ map.delete(id);
4505
+ }
4504
4506
  map.set(id, value);
4505
4507
  }
4506
4508
  };
@@ -4599,8 +4601,199 @@ async function loadProviderPlugins(options) {
4599
4601
  return diagnostics;
4600
4602
  }
4601
4603
 
4604
+ // src/server/routes/plugins.ts
4605
+ import { Router as Router11 } from "express";
4606
+ import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL2 } from "url";
4607
+ import { dirname as dirname7, resolve as resolve6, join as join9 } from "path";
4608
+ import { readFile as readFile4, readdir as readdir3, rm as rm2, rename as rename2 } from "fs/promises";
4609
+ import { platform } from "os";
4610
+ import { execFile } from "child_process";
4611
+ import { promisify } from "util";
4612
+ var execFileP = promisify(execFile);
4613
+ async function openFolder(dir, res) {
4614
+ try {
4615
+ await execFileP("mkdir", ["-p", dir], { timeout: 5e3 });
4616
+ const cmd = platform() === "darwin" ? "open" : platform() === "win32" ? "explorer" : "xdg-open";
4617
+ await execFileP(cmd, [dir], { timeout: 5e3 });
4618
+ res.json({ success: true });
4619
+ } catch (err) {
4620
+ res.status(500).json({ error: err instanceof Error ? err.message : "Failed to open folder" });
4621
+ }
4622
+ }
4623
+ function createPluginRoutes(options) {
4624
+ const router = Router11();
4625
+ const { config: config3, providerAdapters, pluginDiagnostics, logger: logger2 } = options;
4626
+ let registryCache = null;
4627
+ router.get("/registry", async (_req, res) => {
4628
+ try {
4629
+ const now = Date.now();
4630
+ if (registryCache && now - registryCache.ts < 3e5) {
4631
+ return res.json({ plugins: registryCache.data });
4632
+ }
4633
+ const moduleDir = dirname7(fileURLToPath6(import.meta.url));
4634
+ const registryPath = resolve6(moduleDir, "../../../plugins-registry.json");
4635
+ const data = JSON.parse(await readFile4(registryPath, "utf8"));
4636
+ registryCache = { data, ts: now };
4637
+ res.json({ plugins: data });
4638
+ } catch (err) {
4639
+ logger2.error("Failed to load plugin registry", { error: String(err) });
4640
+ res.json({ plugins: [] });
4641
+ }
4642
+ });
4643
+ router.post("/install", async (req, res) => {
4644
+ const { githubUrl } = req.body;
4645
+ if (!githubUrl || typeof githubUrl !== "string") {
4646
+ return res.status(400).json({ error: "githubUrl is required" });
4647
+ }
4648
+ const parsed = githubUrl.match(/github\.com\/([^/]+)\/([^/]+?)(?:\/|$)/);
4649
+ if (!parsed) {
4650
+ return res.status(400).json({ error: "Invalid GitHub URL" });
4651
+ }
4652
+ const repoName = parsed[2].replace(/\.git$/, "");
4653
+ if (!/^[a-zA-Z0-9_-]+$/.test(repoName)) {
4654
+ return res.status(400).json({ error: "Invalid repository name" });
4655
+ }
4656
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4657
+ const targetDir = join9(pluginsDir, repoName);
4658
+ const tmpDir = join9(pluginsDir, `.${repoName}-tmp-${Date.now()}`);
4659
+ try {
4660
+ await execFileP("mkdir", ["-p", pluginsDir], { timeout: 5e3 });
4661
+ } catch {
4662
+ return res.status(500).json({ error: "Failed to create plugins directory" });
4663
+ }
4664
+ let gitOk = false;
4665
+ try {
4666
+ const { stdout } = await execFileP("git", ["--version"], { timeout: 5e3 });
4667
+ gitOk = stdout.includes("git version");
4668
+ } catch {
4669
+ }
4670
+ if (!gitOk) {
4671
+ return res.status(500).json({ error: "git is not installed or not found in PATH" });
4672
+ }
4673
+ try {
4674
+ const cloneUrl = githubUrl.replace(/\/$/, "") + ".git";
4675
+ await execFileP("git", ["clone", "--depth", "1", cloneUrl, tmpDir], { timeout: 6e4 });
4676
+ await rm2(targetDir, { recursive: true, force: true });
4677
+ await rename2(tmpDir, targetDir);
4678
+ let loaded = false;
4679
+ let loadError;
4680
+ try {
4681
+ await execFileP("npm", ["install", "--no-audit", "--no-fund"], { cwd: targetDir, timeout: 12e4 });
4682
+ await execFileP("npm", ["run", "build"], { cwd: targetDir, timeout: 12e4 });
4683
+ } catch (err) {
4684
+ loadError = "Failed to install/build plugin dependencies";
4685
+ logger2.error("Plugin build failed", { repoName, error: String(err) });
4686
+ }
4687
+ if (!loadError) {
4688
+ try {
4689
+ const manifest = JSON.parse(await readFile4(join9(targetDir, "package.json"), "utf8"));
4690
+ const pluginEntry = manifest.openfox?.plugin;
4691
+ const apiVersion = manifest.openfox?.apiVersion;
4692
+ if (!pluginEntry || !manifest.name) {
4693
+ loadError = "Plugin package.json is missing openfox.plugin or name field";
4694
+ } else if (apiVersion !== 1) {
4695
+ loadError = `Unsupported plugin API version: ${String(apiVersion)}`;
4696
+ } else {
4697
+ const mod = await import(pathToFileURL2(join9(targetDir, pluginEntry)).href);
4698
+ if (typeof mod.register !== "function") {
4699
+ loadError = "Plugin does not export register(registry)";
4700
+ } else {
4701
+ const diagnostic = {
4702
+ packageName: manifest.name,
4703
+ version: manifest.version,
4704
+ source: targetDir,
4705
+ loaded: false,
4706
+ authAdapters: [],
4707
+ transportAdapters: [],
4708
+ presets: []
4709
+ };
4710
+ const trackingRegistry = {
4711
+ runtime: providerAdapters.runtime,
4712
+ registerAuth(adapter) {
4713
+ providerAdapters.registerAuth(adapter);
4714
+ diagnostic.authAdapters.push(adapter.id);
4715
+ },
4716
+ registerTransport(adapter) {
4717
+ providerAdapters.registerTransport(adapter);
4718
+ diagnostic.transportAdapters.push(adapter.id);
4719
+ },
4720
+ registerPreset(preset) {
4721
+ providerAdapters.registerPreset(preset);
4722
+ diagnostic.presets.push(preset.id);
4723
+ }
4724
+ };
4725
+ await mod.register(trackingRegistry);
4726
+ diagnostic.loaded = true;
4727
+ pluginDiagnostics.push(diagnostic);
4728
+ loaded = true;
4729
+ config3.providers = providerAdapters.resolveProviders(config3.providers ?? []);
4730
+ }
4731
+ }
4732
+ } catch (err) {
4733
+ loadError = err instanceof Error ? err.message : "Failed to load plugin";
4734
+ logger2.error("Plugin runtime load failed", { repoName, error: loadError });
4735
+ }
4736
+ }
4737
+ res.json({ success: true, loaded, loadError, path: targetDir });
4738
+ } catch (err) {
4739
+ await rm2(tmpDir, { recursive: true, force: true });
4740
+ const msg = err instanceof Error ? err.message : "Clone failed";
4741
+ logger2.error("Plugin install failed", { githubUrl, error: msg });
4742
+ res.status(500).json({ error: msg });
4743
+ }
4744
+ });
4745
+ router.get("/installed", async (_req, res) => {
4746
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4747
+ try {
4748
+ const entries = await readdir3(pluginsDir, { withFileTypes: true });
4749
+ const installed = [];
4750
+ for (const entry of entries) {
4751
+ if (!entry.isDirectory()) continue;
4752
+ const pkgPath = join9(pluginsDir, entry.name, "package.json");
4753
+ let version = null;
4754
+ try {
4755
+ const pkg = JSON.parse(await readFile4(pkgPath, "utf8"));
4756
+ version = pkg.version ?? null;
4757
+ } catch {
4758
+ }
4759
+ installed.push({ name: entry.name, version });
4760
+ }
4761
+ res.json({ installed });
4762
+ } catch {
4763
+ res.json({ installed: [] });
4764
+ }
4765
+ });
4766
+ router.get("/open-folder", async (_req, res) => {
4767
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4768
+ await openFolder(pluginsDir, res);
4769
+ });
4770
+ router.get("/:name/open-folder", async (req, res) => {
4771
+ const name = req.params.name;
4772
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) return res.status(400).json({ error: "Invalid plugin name" });
4773
+ const targetDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
4774
+ await openFolder(targetDir, res);
4775
+ });
4776
+ router.delete("/:name", async (req, res) => {
4777
+ const name = req.params.name;
4778
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
4779
+ return res.status(400).json({ error: "Invalid plugin name" });
4780
+ }
4781
+ const targetDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
4782
+ try {
4783
+ await rm2(targetDir, { recursive: true, force: true });
4784
+ for (let i = pluginDiagnostics.length - 1; i >= 0; i--) {
4785
+ if (pluginDiagnostics[i].source === targetDir) pluginDiagnostics.splice(i, 1);
4786
+ }
4787
+ res.json({ success: true });
4788
+ } catch (err) {
4789
+ res.status(500).json({ error: err instanceof Error ? err.message : "Failed to remove plugin" });
4790
+ }
4791
+ });
4792
+ return router;
4793
+ }
4794
+
4602
4795
  // src/server/index.ts
4603
- var __dirname3 = dirname7(fileURLToPath6(import.meta.url));
4796
+ var __dirname3 = dirname8(fileURLToPath7(import.meta.url));
4604
4797
  async function createServerHandle(config3) {
4605
4798
  setRuntimeConfig(config3);
4606
4799
  setLogLevel(config3.logging?.level ?? void 0, config3.mode);
@@ -4697,7 +4890,7 @@ async function createServerHandle(config3) {
4697
4890
  setMcpTools(mcpTools);
4698
4891
  logger.info("MCP tools registered", { count: mcpTools.length });
4699
4892
  }
4700
- const { signalMcpReady } = await import("./server-OYE7GERR.js");
4893
+ const { signalMcpReady } = await import("./server-ECKS2Y3R.js");
4701
4894
  signalMcpReady();
4702
4895
  });
4703
4896
  const app = express();
@@ -4969,7 +5162,7 @@ async function createServerHandle(config3) {
4969
5162
  app.get("/api/sessions/:id", async (req, res) => {
4970
5163
  const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
4971
5164
  const { buildMessagesFromStoredEvents } = await import("./folding-V2K34EGN.js");
4972
- const { getPendingQuestionsForSession } = await import("./tools-INWP6FGV.js");
5165
+ const { getPendingQuestionsForSession } = await import("./tools-QAEN5KHA.js");
4973
5166
  const session = sessionManager.getSession(req.params.id);
4974
5167
  if (!session) {
4975
5168
  return res.status(404).json({ error: "Session not found" });
@@ -4988,8 +5181,8 @@ async function createServerHandle(config3) {
4988
5181
  if (!session) {
4989
5182
  return res.status(404).json({ error: "Session not found" });
4990
5183
  }
4991
- const { stopSessionExecution } = await import("./chat-handler-72DFHK5K.js");
4992
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-INWP6FGV.js");
5184
+ const { stopSessionExecution } = await import("./chat-handler-QFEHJBWN.js");
5185
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-QAEN5KHA.js");
4993
5186
  sessionManager.clearMessageQueue(sessionId);
4994
5187
  stopSessionExecution(sessionId, sessionManager);
4995
5188
  abortSession(sessionId);
@@ -5143,7 +5336,7 @@ async function createServerHandle(config3) {
5143
5336
  if (!callId || approved === void 0) {
5144
5337
  return res.status(400).json({ error: "callId and approved are required" });
5145
5338
  }
5146
- const { providePathConfirmation } = await import("./tools-INWP6FGV.js");
5339
+ const { providePathConfirmation } = await import("./tools-QAEN5KHA.js");
5147
5340
  const result = providePathConfirmation(callId, approved, alwaysAllow);
5148
5341
  if (!result.found) {
5149
5342
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -5151,7 +5344,7 @@ async function createServerHandle(config3) {
5151
5344
  const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
5152
5345
  const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-V2K34EGN.js");
5153
5346
  const { createSessionStateMessage } = await import("./protocol-CTNE3ANP.js");
5154
- const { getPendingQuestionsForSession } = await import("./tools-INWP6FGV.js");
5347
+ const { getPendingQuestionsForSession } = await import("./tools-QAEN5KHA.js");
5155
5348
  const eventStore = getEventStore2();
5156
5349
  const events = eventStore.getEvents(sessionId);
5157
5350
  const messages = buildMessagesFromStoredEvents(events);
@@ -5172,7 +5365,7 @@ async function createServerHandle(config3) {
5172
5365
  if (!skip && typeof answer !== "string") {
5173
5366
  return res.status(400).json({ error: "answer is required when not skipping" });
5174
5367
  }
5175
- const { provideAnswer } = await import("./tools-INWP6FGV.js");
5368
+ const { provideAnswer } = await import("./tools-QAEN5KHA.js");
5176
5369
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
5177
5370
  if (!found) {
5178
5371
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -5232,7 +5425,7 @@ async function createServerHandle(config3) {
5232
5425
  backend: activeProvider?.backend ?? llmClient.getBackend(),
5233
5426
  model: llmClient.getModel()
5234
5427
  };
5235
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-FEMPJOZD.js");
5428
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-GNXKJPX4.js");
5236
5429
  runAgentTurn(
5237
5430
  {
5238
5431
  sessionManager,
@@ -5270,8 +5463,8 @@ async function createServerHandle(config3) {
5270
5463
  if (!session) {
5271
5464
  return res.status(404).json({ error: "Session not found" });
5272
5465
  }
5273
- const { stopSessionExecution } = await import("./chat-handler-72DFHK5K.js");
5274
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-INWP6FGV.js");
5466
+ const { stopSessionExecution } = await import("./chat-handler-QFEHJBWN.js");
5467
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-QAEN5KHA.js");
5275
5468
  const queuedMessages = sessionManager.getQueueState(sessionId);
5276
5469
  sessionManager.clearMessageQueue(sessionId);
5277
5470
  stopSessionExecution(sessionId, sessionManager);
@@ -5388,14 +5581,14 @@ async function createServerHandle(config3) {
5388
5581
  app.get("/api/tools/rtk-check", async (_req, res) => {
5389
5582
  const { spawn: spawn3 } = await import("child_process");
5390
5583
  try {
5391
- const available = await new Promise((resolve7) => {
5584
+ const available = await new Promise((resolve8) => {
5392
5585
  const proc = spawn3("rtk", ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
5393
5586
  let out = "";
5394
5587
  proc.stdout?.on("data", (d) => {
5395
5588
  out += d.toString();
5396
5589
  });
5397
- proc.on("error", () => resolve7(false));
5398
- proc.on("close", (code) => resolve7(code === 0 && out.startsWith("rtk ")));
5590
+ proc.on("error", () => resolve8(false));
5591
+ proc.on("close", (code) => resolve8(code === 0 && out.startsWith("rtk ")));
5399
5592
  });
5400
5593
  res.json({ available });
5401
5594
  } catch {
@@ -5565,7 +5758,7 @@ async function createServerHandle(config3) {
5565
5758
  const backend = req.query["backend"];
5566
5759
  if (!url) return res.status(400).json({ error: "url is required" });
5567
5760
  try {
5568
- const { fetchModelsWithContext } = await import("./provider-manager-D3KIOD5E.js");
5761
+ const { fetchModelsWithContext } = await import("./provider-manager-7C3JVOLW.js");
5569
5762
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
5570
5763
  const models = await fetchModelsWithContext(
5571
5764
  url,
@@ -5635,7 +5828,7 @@ async function createServerHandle(config3) {
5635
5828
  }
5636
5829
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
5637
5830
  const { getBackendCapabilities } = await import("./backend-P3GHHLHJ.js");
5638
- const { buildNonStreamingCreateParams } = await import("./client-pure-U6ZYUPJQ.js");
5831
+ const { buildNonStreamingCreateParams } = await import("./client-pure-XHH4RRLB.js");
5639
5832
  const { OpenAIHttpClient } = await import("./http-client-PIWB7BXK.js");
5640
5833
  const { ensureVersionPrefix } = await import("./url-utils-SAJP7AEX.js");
5641
5834
  const profile = getModelProfile2(model);
@@ -5761,6 +5954,7 @@ async function createServerHandle(config3) {
5761
5954
  });
5762
5955
  }
5763
5956
  });
5957
+ app.use("/api/plugins", createPluginRoutes({ config: config3, providerAdapters, pluginDiagnostics, logger }));
5764
5958
  app.get("/api/plugins", (_req, res) => res.json({ plugins: pluginDiagnostics }));
5765
5959
  app.get("/api/provider-presets", (_req, res) => res.json({ presets: providerAdapters.getPresets() }));
5766
5960
  app.get(
@@ -5893,7 +6087,7 @@ async function createServerHandle(config3) {
5893
6087
  });
5894
6088
  async function rebuildMcpTools() {
5895
6089
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
5896
- const { setMcpTools: setMcpTools2 } = await import("./tools-INWP6FGV.js");
6090
+ const { setMcpTools: setMcpTools2 } = await import("./tools-QAEN5KHA.js");
5897
6091
  const mcpTools = createMcpTools2(mcpManager);
5898
6092
  setMcpTools2(mcpTools);
5899
6093
  }
@@ -6091,14 +6285,14 @@ async function createServerHandle(config3) {
6091
6285
  });
6092
6286
  app.use("/api/directories", createDirectoryRoutes());
6093
6287
  app.use("/api/files", createFileSearchRoutes());
6094
- const webDir = resolve6(__dirname3, "../../web");
6288
+ const webDir = resolve7(__dirname3, "../../web");
6095
6289
  const isDev = config3.mode === "development";
6096
6290
  let viteServer;
6097
6291
  if (isDev) {
6098
6292
  logger.info("Dev mode: using Vite middleware");
6099
6293
  viteServer = await createViteServer({
6100
6294
  root: webDir,
6101
- configFile: resolve6(__dirname3, "../../web/vite.config.ts"),
6295
+ configFile: resolve7(__dirname3, "../../web/vite.config.ts"),
6102
6296
  server: { middlewareMode: true },
6103
6297
  appType: "spa",
6104
6298
  logLevel: "warn"
@@ -6118,7 +6312,7 @@ async function createServerHandle(config3) {
6118
6312
  }
6119
6313
  });
6120
6314
  app.get("/fox.svg", (_req, res) => {
6121
- readFile4(join9(webDir, "fox.svg")).then((content) => {
6315
+ readFile5(join10(webDir, "fox.svg")).then((content) => {
6122
6316
  res.set("Content-Type", "image/svg+xml");
6123
6317
  res.send(content);
6124
6318
  }).catch(() => {
@@ -6127,7 +6321,7 @@ async function createServerHandle(config3) {
6127
6321
  });
6128
6322
  app.use(
6129
6323
  "/sounds",
6130
- express.static(join9(webDir, "public", "sounds"), {
6324
+ express.static(join10(webDir, "public", "sounds"), {
6131
6325
  setHeaders: (res) => {
6132
6326
  res.set("Content-Type", "audio/mpeg");
6133
6327
  }
@@ -6136,13 +6330,13 @@ async function createServerHandle(config3) {
6136
6330
  app.use("/__inspect__.js", (_req, res) => {
6137
6331
  res.set("Access-Control-Allow-Origin", "*");
6138
6332
  res.set("Content-Type", "application/javascript");
6139
- readFile4(join9(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6333
+ readFile5(join10(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6140
6334
  });
6141
6335
  app.get("/*path", (req, res) => {
6142
6336
  if (req.path.startsWith("/api/")) {
6143
6337
  return;
6144
6338
  }
6145
- readFile4(join9(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6339
+ readFile5(join10(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6146
6340
  logger.error("Error serving index.html", { error: err });
6147
6341
  res.status(500).send("Server error");
6148
6342
  });
@@ -6150,10 +6344,10 @@ async function createServerHandle(config3) {
6150
6344
  logger.info("Vite middleware ready", { port: config3.server.port });
6151
6345
  }
6152
6346
  if (!isDev) {
6153
- const distWebDir = resolve6(__dirname3, "web");
6347
+ const distWebDir = resolve7(__dirname3, "web");
6154
6348
  app.use(
6155
6349
  "/assets",
6156
- express.static(join9(distWebDir, "assets"), {
6350
+ express.static(join10(distWebDir, "assets"), {
6157
6351
  setHeaders: (res, filepath) => {
6158
6352
  if (filepath.endsWith(".css")) {
6159
6353
  res.set("Content-Type", "text/css");
@@ -6161,11 +6355,11 @@ async function createServerHandle(config3) {
6161
6355
  }
6162
6356
  })
6163
6357
  );
6164
- app.use("/manifest.webmanifest", express.static(join9(distWebDir, "manifest.webmanifest")));
6165
- app.use("/registerSW.js", express.static(join9(distWebDir, "registerSW.js")));
6166
- app.use("/sw.js", express.static(join9(distWebDir, "sw.js")));
6358
+ app.use("/manifest.webmanifest", express.static(join10(distWebDir, "manifest.webmanifest")));
6359
+ app.use("/registerSW.js", express.static(join10(distWebDir, "registerSW.js")));
6360
+ app.use("/sw.js", express.static(join10(distWebDir, "sw.js")));
6167
6361
  app.get("/fox.svg", (_req, res) => {
6168
- readFile4(join9(distWebDir, "fox.svg")).then((content) => {
6362
+ readFile5(join10(distWebDir, "fox.svg")).then((content) => {
6169
6363
  res.set("Content-Type", "image/svg+xml");
6170
6364
  res.send(content);
6171
6365
  }).catch(() => {
@@ -6174,7 +6368,7 @@ async function createServerHandle(config3) {
6174
6368
  });
6175
6369
  app.use(
6176
6370
  "/sounds",
6177
- express.static(join9(distWebDir, "sounds"), {
6371
+ express.static(join10(distWebDir, "sounds"), {
6178
6372
  setHeaders: (res) => {
6179
6373
  res.set("Content-Type", "audio/mpeg");
6180
6374
  }
@@ -6183,10 +6377,10 @@ async function createServerHandle(config3) {
6183
6377
  app.use("/__inspect__.js", (_req, res) => {
6184
6378
  res.set("Access-Control-Allow-Origin", "*");
6185
6379
  res.set("Content-Type", "application/javascript");
6186
- readFile4(join9(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6380
+ readFile5(join10(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6187
6381
  });
6188
6382
  app.get("/", (_req, res) => {
6189
- readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6383
+ readFile5(join10(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6190
6384
  res.status(404).send("Web UI not built. Run `npm run build:web`");
6191
6385
  });
6192
6386
  });
@@ -6194,7 +6388,7 @@ async function createServerHandle(config3) {
6194
6388
  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") {
6195
6389
  return;
6196
6390
  }
6197
- readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6391
+ readFile5(join10(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6198
6392
  res.status(404).send("Web UI not built");
6199
6393
  });
6200
6394
  });
@@ -6214,7 +6408,7 @@ async function createServerHandle(config3) {
6214
6408
  const state = sessionManager.getContextState(sessionId);
6215
6409
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
6216
6410
  });
6217
- const { QueueProcessor } = await import("./processor-QB3NMRMO.js");
6411
+ const { QueueProcessor } = await import("./processor-TIQEQDP7.js");
6218
6412
  const queueProcessor = new QueueProcessor({
6219
6413
  sessionManager,
6220
6414
  providerManager,
@@ -6237,7 +6431,7 @@ async function createServerHandle(config3) {
6237
6431
  return {
6238
6432
  httpServer,
6239
6433
  ctx: { config: config3, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
6240
- start: (port) => new Promise((resolve7, reject) => {
6434
+ start: (port) => new Promise((resolve8, reject) => {
6241
6435
  const listenPort = port ?? config3.server.port;
6242
6436
  const host = config3.server.host;
6243
6437
  httpServer.listen(listenPort, host, () => {
@@ -6247,11 +6441,11 @@ async function createServerHandle(config3) {
6247
6441
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
6248
6442
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
6249
6443
  logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config3.llm.baseUrl}`);
6250
- resolve7({ port: actualPort });
6444
+ resolve8({ port: actualPort });
6251
6445
  });
6252
6446
  httpServer.on("error", reject);
6253
6447
  }),
6254
- close: () => new Promise((resolve7) => {
6448
+ close: () => new Promise((resolve8) => {
6255
6449
  logger.info("Shutting down...");
6256
6450
  void (async () => {
6257
6451
  await devServerManager.stopAll();
@@ -6270,7 +6464,7 @@ async function createServerHandle(config3) {
6270
6464
  client.terminate();
6271
6465
  }
6272
6466
  wss.close();
6273
- httpServer.close(() => resolve7());
6467
+ httpServer.close(() => resolve8());
6274
6468
  })();
6275
6469
  })
6276
6470
  };
@@ -6295,4 +6489,4 @@ export {
6295
6489
  createServerHandle,
6296
6490
  createServer
6297
6491
  };
6298
- //# sourceMappingURL=chunk-2GRUQN2B.js.map
6492
+ //# sourceMappingURL=chunk-DWZEGLHJ.js.map
@@ -13,7 +13,7 @@ import {
13
13
  getThinking,
14
14
  mapFinishReason,
15
15
  parseToolArguments
16
- } from "./chunk-BL5LOLVA.js";
16
+ } from "./chunk-JHGKXQBO.js";
17
17
  import {
18
18
  LLMError,
19
19
  OpenAIHttpClient
@@ -265,4 +265,4 @@ function createLLMClient(config, initialBackend = "unknown") {
265
265
  export {
266
266
  createLLMClient
267
267
  };
268
- //# sourceMappingURL=chunk-B7WGOK7G.js.map
268
+ //# sourceMappingURL=chunk-E4POUD2M.js.map
@@ -10,7 +10,7 @@ import {
10
10
  loadAllAgentsDefault,
11
11
  processEventsForConversation,
12
12
  runTopLevelAgentLoop
13
- } from "./chunk-YU6DZAVA.js";
13
+ } from "./chunk-6LK47TNE.js";
14
14
  import {
15
15
  TurnMetrics,
16
16
  buildAgentReminder,
@@ -18,7 +18,7 @@ import {
18
18
  buildTopLevelSystemPrompt,
19
19
  createChatDoneEvent,
20
20
  createMessageStartEvent
21
- } from "./chunk-TJO4QFDQ.js";
21
+ } from "./chunk-QFSDJIUS.js";
22
22
  import {
23
23
  getCurrentContextWindowId,
24
24
  getCurrentWindowMessageOptions,
@@ -64,7 +64,7 @@ function resolveAgentDef(sessionManager, sessionId) {
64
64
  }
65
65
  async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
66
66
  const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
67
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-INWP6FGV.js");
67
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-QAEN5KHA.js");
68
68
  const tools = getToolRegistryForAgent2(agentDef).definitions;
69
69
  const toolFingerprint = getToolFingerprint(tools);
70
70
  const allAgents = await loadAllAgentsDefault();
@@ -77,7 +77,7 @@ async function buildCachedPrompt(sessionManager, sessionId, agentDef) {
77
77
  async function computeSessionHash(sessionManager, sessionId) {
78
78
  const { instructionContent, skills } = await loadSessionContext(sessionManager, sessionId);
79
79
  const agentDef = await resolveAgentDef(sessionManager, sessionId);
80
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-INWP6FGV.js");
80
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-QAEN5KHA.js");
81
81
  const tools = getToolRegistryForAgent2(agentDef).definitions;
82
82
  const toolFingerprint = getToolFingerprint(tools);
83
83
  return computeDynamicContextHash(instructionContent, skills, toolFingerprint);
@@ -357,4 +357,4 @@ export {
357
357
  runChatTurn,
358
358
  runAgentTurn
359
359
  };
360
- //# sourceMappingURL=chunk-PYRH4G2J.js.map
360
+ //# sourceMappingURL=chunk-FCLCEIY4.js.map