openfox 2.0.110 → 2.0.112

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 (80) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -0
  3. package/dist/CHANGELOG.md +25 -0
  4. package/dist/{ask-CJMU6EW7.js → ask-ZYPCJKZD.js} +3 -2
  5. package/dist/{chat-handler-UZ7WTT6D.js → chat-handler-BYXZIIV3.js} +23 -22
  6. package/dist/{chunk-VJWWJEBX.js → chunk-3UILDGOO.js} +9 -9
  7. package/dist/{chunk-GNFDD6LN.js → chunk-BOSKQI62.js} +3 -3
  8. package/dist/{chunk-D6ODGTSZ.js → chunk-C372UH7N.js} +2 -1
  9. package/dist/{chunk-4ZXRERIW.js → chunk-C5NQF2K4.js} +46 -4
  10. package/dist/{chunk-3HS72YIE.js → chunk-ERYUSG5C.js} +2 -2
  11. package/dist/{chunk-PU3IPUSW.js → chunk-FFPCVN5M.js} +45 -8
  12. package/dist/{chunk-KDQJOI2I.js → chunk-FSYRANYR.js} +2 -2
  13. package/dist/chunk-IJ53Y77N.js +142 -0
  14. package/dist/{chunk-ZJW3KOII.js → chunk-IYTDCPEQ.js} +293 -98
  15. package/dist/{chunk-WCQOHRUX.js → chunk-JDT63SSP.js} +2 -2
  16. package/dist/{chunk-VT2X3DMC.js → chunk-JNHKKUGJ.js} +2 -2
  17. package/dist/{chunk-JAX5OEMM.js → chunk-JURM3RPZ.js} +21 -4
  18. package/dist/chunk-LCLH6ZUL.js +43 -0
  19. package/dist/{chunk-6EV7X5MP.js → chunk-N4RTAGFY.js} +2 -2
  20. package/dist/{chunk-LXYNP7LL.js → chunk-NB2D6I64.js} +221 -5
  21. package/dist/{chunk-VKWVPQJ5.js → chunk-OAN4BXEW.js} +3 -1
  22. package/dist/{chunk-4R7G5JB6.js → chunk-P45RJGOT.js} +1 -1
  23. package/dist/chunk-P5AA7OYJ.js +7 -0
  24. package/dist/{chunk-E5HZKNTY.js → chunk-PCC4DBPF.js} +2 -2
  25. package/dist/{chunk-ACJNRPTO.js → chunk-QGXLZZBS.js} +29 -21
  26. package/dist/{chunk-UCYPPLVR.js → chunk-RAKPI4OE.js} +81 -70
  27. package/dist/{chunk-MM46DJJL.js → chunk-RISQXU32.js} +2 -2
  28. package/dist/{chunk-CQKRZ4WV.js → chunk-RKMP74BB.js} +4 -4
  29. package/dist/chunk-RSB4AR2A.js +108 -0
  30. package/dist/{chunk-VXKPZUCT.js → chunk-RT2A2RRL.js} +4 -2
  31. package/dist/{chunk-HK75Q3EA.js → chunk-SDGNV45R.js} +10 -10
  32. package/dist/{chunk-C5JJM72V.js → chunk-SVJFMZ2Q.js} +49 -5
  33. package/dist/{chunk-B5MH4HQ6.js → chunk-SYJMUIRC.js} +7 -3
  34. package/dist/{chunk-QRASX3HC.js → chunk-UAF2FOI5.js} +7 -7
  35. package/dist/{chunk-4HIFB7F5.js → chunk-XCK5IBO4.js} +37 -26
  36. package/dist/{chunk-5HMKLHTT.js → chunk-XWNCKIPO.js} +2 -2
  37. package/dist/{chunk-NORNB6IJ.js → chunk-Z56SEG4Z.js} +6 -6
  38. package/dist/cli/dev.js +1 -1
  39. package/dist/cli/index.js +1 -1
  40. package/dist/{client-LPNFUOPV.js → client-QNQTX5EA.js} +4 -4
  41. package/dist/{compactor-OSDLCGRC.js → compactor-X2KZ3XFU.js} +10 -9
  42. package/dist/{config-HX7FDKGJ.js → config-TW5FHQEM.js} +2 -2
  43. package/dist/{dynamic-context-WVA7HTEP.js → dynamic-context-ZRQO2FJN.js} +7 -7
  44. package/dist/{events-26J7BUSY.js → events-Y6XXQYFG.js} +7 -6
  45. package/dist/{folding-ZD4AMFNR.js → folding-Z4GNWRC3.js} +9 -6
  46. package/dist/{http-client-MQARNFY3.js → http-client-2GDKHZIG.js} +3 -3
  47. package/dist/{manager-RJH7EYIG.js → manager-HCMDFEQH.js} +4 -4
  48. package/dist/{model-overrides-BXMFIT47.js → model-overrides-O3ZYKFP7.js} +3 -3
  49. package/dist/oauth-provider-52YILVUJ.js +15 -0
  50. package/dist/oauth-store-XCFXV2VM.js +32 -0
  51. package/dist/{orchestrator-BW27C4K4.js → orchestrator-P5EUMC7E.js} +22 -21
  52. package/dist/package.json +13 -10
  53. package/dist/{path-security-AAZMH33K.js → path-security-525YLND3.js} +11 -9
  54. package/dist/{platform-EZJABX5J.js → platform-MEQUWG6U.js} +3 -3
  55. package/dist/{processor-FTCPHWBM.js → processor-UN4H4V7F.js} +22 -21
  56. package/dist/{protocol-_Gphic7p.d.ts → protocol-D6MISQyz.d.ts} +8 -3
  57. package/dist/{protocol-SPIJPOEN.js → protocol-FTHAR2YL.js} +4 -3
  58. package/dist/{provider-JS5P3HQ2.js → provider-3R4X62LW.js} +7 -7
  59. package/dist/{provider-manager-MWAIOX2A.js → provider-manager-W5N4XRE5.js} +5 -5
  60. package/dist/{registry-JJB5GXOM.js → registry-74KPZ5NV.js} +3 -3
  61. package/dist/{serve-XDZB4EJN.js → serve-WHFUNQ6Z.js} +32 -29
  62. package/dist/server/index.d.ts +15 -1
  63. package/dist/server/index.js +31 -28
  64. package/dist/server-7MOOJR2N.js +48 -0
  65. package/dist/{session-overrides-T47KXDDS.js → session-overrides-XH6I3COP.js} +5 -5
  66. package/dist/{sessions-YTWCOHI3.js → sessions-D772YTWL.js} +8 -4
  67. package/dist/{settings-2RZBMX5Y.js → settings-KO6DSJLD.js} +2 -2
  68. package/dist/shared/index.d.ts +1 -1
  69. package/dist/shared/index.js +1 -1
  70. package/dist/{tools-KPIYFL5A.js → tools-HTUTYMKI.js} +20 -19
  71. package/dist/{update-75QZJYKD.js → update-BRUFGGTW.js} +2 -2
  72. package/dist/{update-server-4I6LXE5K.js → update-server-LOOXIXDW.js} +2 -2
  73. package/dist/web/assets/{index-BmjVoqQT.js → index-Dukvfqm-.js} +83 -83
  74. package/dist/web/assets/{index-CyWbbpRP.css → index-nS1p0g8O.css} +1 -1
  75. package/dist/web/index.html +2 -2
  76. package/dist/web/sw.js +1 -1
  77. package/package.json +13 -10
  78. package/scripts/postinstall.mjs +8 -0
  79. package/dist/chunk-64374FPB.js +0 -7
  80. package/dist/server-R6DDJNF3.js +0 -47
@@ -1,3 +1,11 @@
1
+ import {
2
+ McpOAuthProvider,
3
+ setMcpOAuthServerPort
4
+ } from "./chunk-RSB4AR2A.js";
5
+ import {
6
+ setMcpOAuthStoreMode,
7
+ setMcpOAuthStorePath
8
+ } from "./chunk-IJ53Y77N.js";
1
9
  import {
2
10
  TEMPLATE_VARIABLES,
3
11
  createWebSocketServer,
@@ -21,7 +29,7 @@ import {
21
29
  tokenFromPassword,
22
30
  verifyPassword,
23
31
  workflowExists
24
- } from "./chunk-4HIFB7F5.js";
32
+ } from "./chunk-XCK5IBO4.js";
25
33
  import {
26
34
  openFolder
27
35
  } from "./chunk-WLJJRX22.js";
@@ -34,7 +42,7 @@ import {
34
42
  setMcpManagerForTools,
35
43
  setMcpTools,
36
44
  setNotifyMcpServersChanged
37
- } from "./chunk-UCYPPLVR.js";
45
+ } from "./chunk-RAKPI4OE.js";
38
46
  import {
39
47
  deleteOwnedSkill,
40
48
  deleteProjectSkill,
@@ -53,12 +61,12 @@ import {
53
61
  setSkillEnabled,
54
62
  skillExists,
55
63
  updateOwnedSkill
56
- } from "./chunk-GNFDD6LN.js";
64
+ } from "./chunk-BOSKQI62.js";
57
65
  import {
58
66
  ALWAYS_ALLOWED,
59
67
  ALWAYS_ALLOWED_FOR_SUBAGENTS,
60
68
  TOP_LEVEL_ONLY_TOOLS
61
- } from "./chunk-5HMKLHTT.js";
69
+ } from "./chunk-XWNCKIPO.js";
62
70
  import {
63
71
  createMcpTools
64
72
  } from "./chunk-JE7LW7Y6.js";
@@ -81,7 +89,7 @@ import {
81
89
  import {
82
90
  getSessionDisabledServers,
83
91
  setSessionDisabledServers
84
- } from "./chunk-WCQOHRUX.js";
92
+ } from "./chunk-JDT63SSP.js";
85
93
  import {
86
94
  emitAssistantMessageStart,
87
95
  emitContextState,
@@ -98,24 +106,24 @@ import {
98
106
  getEventStore,
99
107
  getSessionState,
100
108
  initEventStore
101
- } from "./chunk-LXYNP7LL.js";
109
+ } from "./chunk-NB2D6I64.js";
102
110
  import {
103
111
  createContextStateMessage,
104
112
  toClientSession
105
- } from "./chunk-B5MH4HQ6.js";
106
- import {
107
- EventEmitter
108
- } from "./chunk-JAX5OEMM.js";
113
+ } from "./chunk-SYJMUIRC.js";
109
114
  import {
110
115
  getPathSeparator,
111
116
  isAbsolutePath
112
- } from "./chunk-6EV7X5MP.js";
117
+ } from "./chunk-N4RTAGFY.js";
118
+ import {
119
+ EventEmitter
120
+ } from "./chunk-JURM3RPZ.js";
113
121
  import {
114
122
  getAgentModelOverride,
115
123
  getAgentModelOverrides,
116
124
  resolveLLMClientForAgent,
117
125
  setAgentModelOverride
118
- } from "./chunk-MM46DJJL.js";
126
+ } from "./chunk-RISQXU32.js";
119
127
  import {
120
128
  getProject,
121
129
  getProjectByWorkdir,
@@ -123,7 +131,7 @@ import {
123
131
  } from "./chunk-6FPGJR7O.js";
124
132
  import {
125
133
  VERSION
126
- } from "./chunk-64374FPB.js";
134
+ } from "./chunk-P5AA7OYJ.js";
127
135
  import {
128
136
  clearWorkflowExecution,
129
137
  createSession,
@@ -132,8 +140,10 @@ import {
132
140
  getActiveWorkflowExecution,
133
141
  getSession,
134
142
  getSessionCachedPrompt,
143
+ listHomeSessions,
135
144
  listSessions,
136
145
  listSessionsByProject,
146
+ listSessionsLimited,
137
147
  updateSessionBranch,
138
148
  updateSessionCachedPrompt,
139
149
  updateSessionDangerLevel,
@@ -143,7 +153,7 @@ import {
143
153
  updateSessionRunning,
144
154
  updateSessionWorkdir,
145
155
  updateWorkflowExecutionStatus
146
- } from "./chunk-4ZXRERIW.js";
156
+ } from "./chunk-C5NQF2K4.js";
147
157
  import {
148
158
  agentExists,
149
159
  deleteAgent,
@@ -166,13 +176,13 @@ import {
166
176
  saveAgentToProject,
167
177
  saveItemToDir,
168
178
  setRuntimeConfig
169
- } from "./chunk-VT2X3DMC.js";
179
+ } from "./chunk-JNHKKUGJ.js";
170
180
  import {
171
181
  createProviderManager,
172
182
  detectModel,
173
183
  getLlmStatus,
174
184
  parseDefaultModelSelection
175
- } from "./chunk-KDQJOI2I.js";
185
+ } from "./chunk-FSYRANYR.js";
176
186
  import {
177
187
  getModelProfile
178
188
  } from "./chunk-V4IE7HJY.js";
@@ -185,12 +195,12 @@ import {
185
195
  import {
186
196
  SessionNotFoundError,
187
197
  WorkspaceInUseError
188
- } from "./chunk-E5HZKNTY.js";
198
+ } from "./chunk-PCC4DBPF.js";
189
199
  import {
190
200
  deleteSetting,
191
201
  getSetting,
192
202
  setSetting
193
- } from "./chunk-VXKPZUCT.js";
203
+ } from "./chunk-RT2A2RRL.js";
194
204
  import {
195
205
  initDatabase
196
206
  } from "./chunk-LCQ5AN6Y.js";
@@ -200,7 +210,7 @@ import {
200
210
  } from "./chunk-K44MW7JJ.js";
201
211
  import {
202
212
  createServerMessage
203
- } from "./chunk-4R7G5JB6.js";
213
+ } from "./chunk-P45RJGOT.js";
204
214
  import {
205
215
  getGlobalConfigDir
206
216
  } from "./chunk-CQGTEGKL.js";
@@ -1471,6 +1481,12 @@ function createMockLLMClient() {
1471
1481
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1472
1482
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1473
1483
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1484
+ function withoutAuthorizationHeader(headers) {
1485
+ if (!headers) return void 0;
1486
+ const kept = Object.entries(headers).filter(([key]) => key.trim().toLowerCase() !== "authorization");
1487
+ if (kept.length === Object.keys(headers).length) return headers;
1488
+ return Object.fromEntries(kept);
1489
+ }
1474
1490
  function estimateToolTokens(toolName, description, inputSchema) {
1475
1491
  const def = {
1476
1492
  type: "function",
@@ -1519,8 +1535,12 @@ var McpManager = class {
1519
1535
  } else if (entry.config.transport === "http") {
1520
1536
  if (!entry.config.url) throw new Error("url is required for http transport");
1521
1537
  const httpOpts = {};
1522
- if (entry.config.headers) {
1523
- httpOpts.requestInit = { headers: entry.config.headers };
1538
+ const headers = entry.config.oauth ? withoutAuthorizationHeader(entry.config.headers) : entry.config.headers;
1539
+ if (headers) {
1540
+ httpOpts.requestInit = { headers };
1541
+ }
1542
+ if (entry.config.oauth) {
1543
+ httpOpts.authProvider = new McpOAuthProvider(name, entry.config.url);
1524
1544
  }
1525
1545
  transport = new StreamableHTTPClientTransport(new URL(entry.config.url), httpOpts);
1526
1546
  } else {
@@ -2917,6 +2937,13 @@ var SessionManager = class {
2917
2937
  listSessions() {
2918
2938
  return listSessions();
2919
2939
  }
2940
+ /**
2941
+ * Lightweight homepage list: the N most recently updated sessions per
2942
+ * project, summaries only (no prompt extraction, no snapshot parsing).
2943
+ */
2944
+ listHomeSessions(sessionsPerProject = 5) {
2945
+ return listHomeSessions(sessionsPerProject);
2946
+ }
2920
2947
  /**
2921
2948
  * List sessions for a project with pagination.
2922
2949
  */
@@ -2927,6 +2954,14 @@ var SessionManager = class {
2927
2954
  }
2928
2955
  return listSessionsByProject(projectId, limit, offset);
2929
2956
  }
2957
+ /**
2958
+ * Most recently updated sessions across all projects, bounded with
2959
+ * pagination. Used by the legacy global list refresh when a limit is
2960
+ * explicitly requested (the homepage itself uses listHomeSessions).
2961
+ */
2962
+ listSessionsLimited(limit = 20, offset = 0) {
2963
+ return listSessionsLimited(limit, offset);
2964
+ }
2930
2965
  /**
2931
2966
  * Delete a session and all its events.
2932
2967
  */
@@ -3820,6 +3855,7 @@ All file and git operations should use this directory.
3820
3855
  this.switchLocks.set(sessionId, lockPromise);
3821
3856
  lockPromise.finally(() => {
3822
3857
  if (this.switchLocks.get(sessionId) === lockPromise) this.switchLocks.delete(sessionId);
3858
+ }).catch(() => {
3823
3859
  });
3824
3860
  return lockPromise;
3825
3861
  }
@@ -5348,7 +5384,7 @@ function createProviderAuthRoutes(config3, providerManager, registry) {
5348
5384
  try {
5349
5385
  const { challenge, completion } = await adapter.beginLogin({ providerId: provider.id });
5350
5386
  void completion.then(async ({ credentialRef }) => {
5351
- const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-HX7FDKGJ.js");
5387
+ const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-TW5FHQEM.js");
5352
5388
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5353
5389
  const updatedConfig = updateProvider(globalConfig, provider.id, { credentialRef, authAdapter: adapter.id });
5354
5390
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
@@ -5385,7 +5421,7 @@ function createProviderAuthRoutes(config3, providerManager, registry) {
5385
5421
  const ref = provider.credentialRef ?? provider.id;
5386
5422
  await adapter.logout(ref);
5387
5423
  }
5388
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
5424
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
5389
5425
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
5390
5426
  const updatedConfig = {
5391
5427
  ...globalConfig,
@@ -5863,7 +5899,7 @@ async function createServerHandle(config3) {
5863
5899
  const mcpManager = new McpManager({
5864
5900
  onToolsDiscovered: async (name, tools) => {
5865
5901
  try {
5866
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
5902
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
5867
5903
  const mode = config3.mode ?? "production";
5868
5904
  const globalConfig = await loadGlobalConfig(mode, config3.globalConfigPath);
5869
5905
  const mcpServers2 = {
@@ -5881,6 +5917,8 @@ async function createServerHandle(config3) {
5881
5917
  setMcpManagerForTools(mcpManager);
5882
5918
  setMcpConfigMode(config3.mode ?? "production");
5883
5919
  setMcpConfigPath(config3.globalConfigPath);
5920
+ setMcpOAuthStoreMode(config3.mode ?? "production");
5921
+ setMcpOAuthStorePath(config3.globalConfigPath ? join10(dirname8(config3.globalConfigPath), "mcp-auth.json") : void 0);
5884
5922
  const mcpServers = config3.mcpServers ?? {};
5885
5923
  Promise.all(
5886
5924
  Object.entries(mcpServers).map(
@@ -5895,14 +5933,14 @@ async function createServerHandle(config3) {
5895
5933
  toolRegistry = createToolRegistry();
5896
5934
  logger.info("MCP tools registered", { count: mcpTools.length });
5897
5935
  }
5898
- const { signalMcpReady } = await import("./server-R6DDJNF3.js");
5936
+ const { signalMcpReady } = await import("./server-7MOOJR2N.js");
5899
5937
  signalMcpReady();
5900
5938
  });
5901
5939
  const app = express();
5902
5940
  app.use(cors());
5903
5941
  const authMiddleware = async (req, res, next) => {
5904
5942
  const path = req.path;
5905
- const publicPaths = ["/health", "/auth", "/auth/login", "/auto-update/check", "/changelog"];
5943
+ const publicPaths = ["/health", "/auth", "/auth/login", "/auto-update/check", "/changelog", "/mcp/oauth/callback"];
5906
5944
  if (publicPaths.includes(path)) {
5907
5945
  return next();
5908
5946
  }
@@ -6105,7 +6143,7 @@ async function createServerHandle(config3) {
6105
6143
  }
6106
6144
  try {
6107
6145
  await checkoutBranch(project.workdir, branch);
6108
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-YTWCOHI3.js");
6146
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-D772YTWL.js");
6109
6147
  const allSessions = sessionManager.listSessions();
6110
6148
  for (const s of allSessions) {
6111
6149
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -6141,7 +6179,7 @@ async function createServerHandle(config3) {
6141
6179
  );
6142
6180
  }
6143
6181
  await createBranch(project.workdir, name, sb);
6144
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-YTWCOHI3.js");
6182
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-D772YTWL.js");
6145
6183
  const allSessions = sessionManager.listSessions();
6146
6184
  for (const s of allSessions) {
6147
6185
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -6173,7 +6211,7 @@ async function createServerHandle(config3) {
6173
6211
  if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
6174
6212
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
6175
6213
  const { checkoutBranch, validateRef: validateRef2 } = await import("./workspace-YDUQZ3HC.js");
6176
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-YTWCOHI3.js");
6214
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-D772YTWL.js");
6177
6215
  try {
6178
6216
  await validateRef2(effectiveWorkdir, branch);
6179
6217
  await checkoutBranch(effectiveWorkdir, branch);
@@ -6216,7 +6254,7 @@ All file and git operations should use this branch.
6216
6254
  if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
6217
6255
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
6218
6256
  const { validateRef: validateRef2 } = await import("./workspace-YDUQZ3HC.js");
6219
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-YTWCOHI3.js");
6257
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-D772YTWL.js");
6220
6258
  try {
6221
6259
  await validateRef2(effectiveWorkdir, name);
6222
6260
  if (sourceBranch) {
@@ -6271,17 +6309,23 @@ All file and git operations should use this branch.
6271
6309
  res.json({ workspaces: workspacesList });
6272
6310
  });
6273
6311
  app.get("/api/sessions", async (req, res) => {
6274
- const { getRecentUserPromptsForSession } = await import("./events-26J7BUSY.js");
6275
- const { getPendingConfirmationsBySession } = await import("./path-security-AAZMH33K.js");
6312
+ const { getRecentUserPromptsForSession } = await import("./events-Y6XXQYFG.js");
6313
+ const { getPendingConfirmationsBySession } = await import("./path-security-525YLND3.js");
6276
6314
  const projectId = req.query["projectId"];
6277
- const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
6315
+ const rawLimit = req.query["limit"];
6278
6316
  const offset = parseInt(req.query["offset"]) || 0;
6279
6317
  let sessions;
6280
6318
  let hasMore = false;
6281
6319
  if (projectId) {
6320
+ const limit = Math.min(parseInt(rawLimit || "20") || 20, 100);
6282
6321
  const result = sessionManager.listSessionsByProject(projectId, limit, offset);
6283
6322
  sessions = result.sessions;
6284
6323
  hasMore = result.hasMore;
6324
+ } else if (rawLimit !== void 0) {
6325
+ const limit = Math.min(parseInt(rawLimit || "20") || 20, 100);
6326
+ const result = sessionManager.listSessionsLimited(limit, offset);
6327
+ sessions = result.sessions;
6328
+ hasMore = result.hasMore;
6285
6329
  } else {
6286
6330
  sessions = sessionManager.listSessions();
6287
6331
  }
@@ -6299,6 +6343,9 @@ All file and git operations should use this branch.
6299
6343
  }
6300
6344
  res.json({ sessions: sessionsWithPrompts, hasMore, pendingConfirmationsBySession });
6301
6345
  });
6346
+ app.get("/api/sessions/home", (_req, res) => {
6347
+ res.json({ sessions: sessionManager.listHomeSessions() });
6348
+ });
6302
6349
  app.post("/api/sessions", async (req, res) => {
6303
6350
  const { projectId, title } = req.body;
6304
6351
  if (!projectId) {
@@ -6318,7 +6365,7 @@ All file and git operations should use this branch.
6318
6365
  disabledServers = mcpManager.getAllServers().filter((s) => s.config.disabled).map((s) => s.name);
6319
6366
  }
6320
6367
  if (disabledServers.length > 0) {
6321
- const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-T47KXDDS.js");
6368
+ const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-XH6I3COP.js");
6322
6369
  setSessionDisabledServers2(session.id, disabledServers);
6323
6370
  }
6324
6371
  } catch {
@@ -6391,12 +6438,12 @@ All file and git operations should use this branch.
6391
6438
  }
6392
6439
  });
6393
6440
  app.get("/api/sessions/:id", async (req, res) => {
6394
- const { getEventStore: getEventStore2, combineEventsWithSnapshot } = await import("./events-26J7BUSY.js");
6395
- const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-ZD4AMFNR.js");
6396
- const { getPendingQuestionsForSession } = await import("./tools-KPIYFL5A.js");
6397
- const { getMaxVisibleItems } = await import("./settings-2RZBMX5Y.js");
6398
- const { getAgentModelOverride: getAgentModelOverride2 } = await import("./model-overrides-BXMFIT47.js");
6399
- const { updateSessionProvider: updateSessionProvider2 } = await import("./sessions-YTWCOHI3.js");
6441
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot } = await import("./events-Y6XXQYFG.js");
6442
+ const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-Z4GNWRC3.js");
6443
+ const { getPendingQuestionsForSession } = await import("./tools-HTUTYMKI.js");
6444
+ const { getMaxVisibleItems } = await import("./settings-KO6DSJLD.js");
6445
+ const { getAgentModelOverride: getAgentModelOverride2 } = await import("./model-overrides-O3ZYKFP7.js");
6446
+ const { updateSessionProvider: updateSessionProvider2 } = await import("./sessions-D772YTWL.js");
6400
6447
  let session = sessionManager.getSession(req.params.id);
6401
6448
  if (!session) {
6402
6449
  return res.status(404).json({ error: "Session not found" });
@@ -6435,8 +6482,8 @@ All file and git operations should use this branch.
6435
6482
  if (!session) {
6436
6483
  return res.status(404).json({ error: "Session not found" });
6437
6484
  }
6438
- const { stopSessionExecution } = await import("./chat-handler-UZ7WTT6D.js");
6439
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-KPIYFL5A.js");
6485
+ const { stopSessionExecution } = await import("./chat-handler-BYXZIIV3.js");
6486
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-HTUTYMKI.js");
6440
6487
  sessionManager.clearMessageQueue(sessionId);
6441
6488
  stopSessionExecution(sessionId, sessionManager);
6442
6489
  abortSession(sessionId);
@@ -6465,9 +6512,9 @@ All file and git operations should use this branch.
6465
6512
  res.json({ success: true });
6466
6513
  });
6467
6514
  app.post("/api/sessions/:id/provider", async (req, res) => {
6468
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-26J7BUSY.js");
6469
- const { buildMessagesFromStoredEvents } = await import("./folding-ZD4AMFNR.js");
6470
- const { getMaxVisibleItems } = await import("./settings-2RZBMX5Y.js");
6515
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-Y6XXQYFG.js");
6516
+ const { buildMessagesFromStoredEvents } = await import("./folding-Z4GNWRC3.js");
6517
+ const { getMaxVisibleItems } = await import("./settings-KO6DSJLD.js");
6471
6518
  const sessionId = req.params.id;
6472
6519
  const session = sessionManager.getSession(sessionId);
6473
6520
  if (!session) {
@@ -6502,7 +6549,7 @@ All file and git operations should use this branch.
6502
6549
  if (!result.success) {
6503
6550
  return res.status(500).json({ error: result.error ?? "Failed to set default model" });
6504
6551
  }
6505
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-HX7FDKGJ.js");
6552
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-TW5FHQEM.js");
6506
6553
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
6507
6554
  const updatedConfig = setDefaultModelSelection(globalConfig, providerId, model);
6508
6555
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
@@ -6580,11 +6627,11 @@ All file and git operations should use this branch.
6580
6627
  res.json({ success: true });
6581
6628
  });
6582
6629
  app.put("/api/sessions/:id/mode", async (req, res) => {
6583
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-26J7BUSY.js");
6584
- const { buildMessagesFromStoredEvents } = await import("./folding-ZD4AMFNR.js");
6585
- const { getMaxVisibleItems } = await import("./settings-2RZBMX5Y.js");
6586
- const { getAgentModelOverride: getAgentModelOverride2 } = await import("./model-overrides-BXMFIT47.js");
6587
- const { updateSessionProvider: updateSessionProvider2 } = await import("./sessions-YTWCOHI3.js");
6630
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-Y6XXQYFG.js");
6631
+ const { buildMessagesFromStoredEvents } = await import("./folding-Z4GNWRC3.js");
6632
+ const { getMaxVisibleItems } = await import("./settings-KO6DSJLD.js");
6633
+ const { getAgentModelOverride: getAgentModelOverride2 } = await import("./model-overrides-O3ZYKFP7.js");
6634
+ const { updateSessionProvider: updateSessionProvider2 } = await import("./sessions-D772YTWL.js");
6588
6635
  const sessionId = req.params.id;
6589
6636
  const session = sessionManager.getSession(sessionId);
6590
6637
  if (!session) {
@@ -6686,7 +6733,7 @@ All file and git operations should use this branch.
6686
6733
  if (alwaysAllow !== void 0 && typeof alwaysAllow !== "boolean") {
6687
6734
  return res.status(400).json({ error: "alwaysAllow must be a boolean if provided" });
6688
6735
  }
6689
- const { providePathConfirmation, getConfirmationSessionId } = await import("./tools-KPIYFL5A.js");
6736
+ const { providePathConfirmation, getConfirmationSessionId } = await import("./tools-HTUTYMKI.js");
6690
6737
  const pendingSessionId = getConfirmationSessionId(callId);
6691
6738
  if (!pendingSessionId) {
6692
6739
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -6698,11 +6745,11 @@ All file and git operations should use this branch.
6698
6745
  if (!result.found) {
6699
6746
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
6700
6747
  }
6701
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-26J7BUSY.js");
6702
- const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-ZD4AMFNR.js");
6703
- const { createSessionStateMessage } = await import("./protocol-SPIJPOEN.js");
6704
- const { getPendingQuestionsForSession } = await import("./tools-KPIYFL5A.js");
6705
- const { getMaxVisibleItems } = await import("./settings-2RZBMX5Y.js");
6748
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-Y6XXQYFG.js");
6749
+ const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-Z4GNWRC3.js");
6750
+ const { createSessionStateMessage } = await import("./protocol-FTHAR2YL.js");
6751
+ const { getPendingQuestionsForSession } = await import("./tools-HTUTYMKI.js");
6752
+ const { getMaxVisibleItems } = await import("./settings-KO6DSJLD.js");
6706
6753
  const eventStore = getEventStore2();
6707
6754
  const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
6708
6755
  const events = combineEvents(sessionId, snapshot, eventsSinceSnapshot);
@@ -6738,7 +6785,7 @@ All file and git operations should use this branch.
6738
6785
  if (!skip && typeof answer !== "string") {
6739
6786
  return res.status(400).json({ error: "answer is required when not skipping" });
6740
6787
  }
6741
- const { provideAnswer } = await import("./tools-KPIYFL5A.js");
6788
+ const { provideAnswer } = await import("./tools-HTUTYMKI.js");
6742
6789
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
6743
6790
  if (!found) {
6744
6791
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -6771,7 +6818,7 @@ All file and git operations should use this branch.
6771
6818
  if (!session) {
6772
6819
  return res.status(404).json({ error: "Session not found" });
6773
6820
  }
6774
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-2RZBMX5Y.js");
6821
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-KO6DSJLD.js");
6775
6822
  if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
6776
6823
  return res.json({ success: false, reason: "disabled" });
6777
6824
  }
@@ -6803,7 +6850,7 @@ All file and git operations should use this branch.
6803
6850
  backend: activeProvider?.backend ?? llmClient.getBackend(),
6804
6851
  model: llmClient.getModel()
6805
6852
  };
6806
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-BW27C4K4.js");
6853
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-P5EUMC7E.js");
6807
6854
  runAgentTurn(
6808
6855
  {
6809
6856
  sessionManager,
@@ -6841,15 +6888,15 @@ All file and git operations should use this branch.
6841
6888
  if (!session) {
6842
6889
  return res.status(404).json({ error: "Session not found" });
6843
6890
  }
6844
- const { stopSessionExecution } = await import("./chat-handler-UZ7WTT6D.js");
6845
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-KPIYFL5A.js");
6891
+ const { stopSessionExecution } = await import("./chat-handler-BYXZIIV3.js");
6892
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-HTUTYMKI.js");
6846
6893
  const queuedMessages = sessionManager.getQueueState(sessionId);
6847
6894
  sessionManager.clearMessageQueue(sessionId);
6848
6895
  stopSessionExecution(sessionId, sessionManager);
6849
6896
  abortSession(sessionId);
6850
6897
  cancelQuestionsForSession(sessionId, "Session stopped by user");
6851
6898
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
6852
- const eventStore = (await import("./events-26J7BUSY.js")).getEventStore();
6899
+ const eventStore = (await import("./events-Y6XXQYFG.js")).getEventStore();
6853
6900
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
6854
6901
  res.json({ success: true, queuedMessages });
6855
6902
  });
@@ -6863,7 +6910,7 @@ All file and git operations should use this branch.
6863
6910
  if (typeof messageIndex !== "number" || messageIndex < 0) {
6864
6911
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
6865
6912
  }
6866
- const { truncateSessionMessages } = await import("./events-26J7BUSY.js");
6913
+ const { truncateSessionMessages } = await import("./events-Y6XXQYFG.js");
6867
6914
  truncateSessionMessages(sessionId, messageIndex);
6868
6915
  res.json({ success: true });
6869
6916
  });
@@ -6880,8 +6927,8 @@ All file and git operations should use this branch.
6880
6927
  if (content !== void 0 && (typeof content !== "string" || !content.trim())) {
6881
6928
  return res.status(400).json({ error: "content must be a non-empty string if provided" });
6882
6929
  }
6883
- const { getEventStore: getEventStore2 } = await import("./events-26J7BUSY.js");
6884
- const { buildMessagesFromStoredEvents } = await import("./folding-ZD4AMFNR.js");
6930
+ const { getEventStore: getEventStore2 } = await import("./events-Y6XXQYFG.js");
6931
+ const { buildMessagesFromStoredEvents } = await import("./folding-Z4GNWRC3.js");
6885
6932
  const eventStore = getEventStore2();
6886
6933
  const events = eventStore.getEvents(sessionId);
6887
6934
  const { messages } = buildMessagesFromStoredEvents(events);
@@ -6893,7 +6940,7 @@ All file and git operations should use this branch.
6893
6940
  if (msg.role !== "user" || msg.isSystemGenerated) {
6894
6941
  return res.status(400).json({ error: "Can only replay user messages" });
6895
6942
  }
6896
- const { truncateSessionMessages } = await import("./events-26J7BUSY.js");
6943
+ const { truncateSessionMessages } = await import("./events-Y6XXQYFG.js");
6897
6944
  truncateSessionMessages(sessionId, msgIndex - 1);
6898
6945
  sessionManager.queueMessage(sessionId, "asap", content ?? msg.content, msg.attachments, msg.messageKind);
6899
6946
  res.json({ success: true });
@@ -6949,7 +6996,7 @@ All file and git operations should use this branch.
6949
6996
  res.json({ accepted: true });
6950
6997
  });
6951
6998
  app.get("/api/settings", async (req, res) => {
6952
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2RZBMX5Y.js");
6999
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-KO6DSJLD.js");
6953
7000
  const keysParam = req.query["keys"];
6954
7001
  if (!keysParam) {
6955
7002
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -6962,19 +7009,19 @@ All file and git operations should use this branch.
6962
7009
  res.json(result);
6963
7010
  });
6964
7011
  app.get("/api/settings/:key", async (req, res) => {
6965
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2RZBMX5Y.js");
7012
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-KO6DSJLD.js");
6966
7013
  const key = req.params.key;
6967
7014
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
6968
7015
  res.json({ key, value });
6969
7016
  });
6970
7017
  app.get("/api/settings/:key", async (req, res) => {
6971
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-2RZBMX5Y.js");
7018
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-KO6DSJLD.js");
6972
7019
  const key = req.params.key;
6973
7020
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
6974
7021
  res.json({ key, value });
6975
7022
  });
6976
7023
  app.put("/api/settings/:key", async (req, res) => {
6977
- const { setSetting: setSetting2 } = await import("./settings-2RZBMX5Y.js");
7024
+ const { setSetting: setSetting2 } = await import("./settings-KO6DSJLD.js");
6978
7025
  const key = req.params.key;
6979
7026
  const { value } = req.body;
6980
7027
  if (value === void 0) {
@@ -7001,7 +7048,7 @@ All file and git operations should use this branch.
7001
7048
  }
7002
7049
  });
7003
7050
  app.get("/api/tools/shells", async (_req, res) => {
7004
- const { listAvailableShells } = await import("./platform-EZJABX5J.js");
7051
+ const { listAvailableShells } = await import("./platform-MEQUWG6U.js");
7005
7052
  res.json({ shells: listAvailableShells() });
7006
7053
  });
7007
7054
  app.get("/api/config", async (_req, res) => {
@@ -7010,7 +7057,7 @@ All file and git operations should use this branch.
7010
7057
  let visionFallback;
7011
7058
  let globalWorkdir;
7012
7059
  try {
7013
- const { loadGlobalConfig, getVisionFallback } = await import("./config-HX7FDKGJ.js");
7060
+ const { loadGlobalConfig, getVisionFallback } = await import("./config-TW5FHQEM.js");
7014
7061
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7015
7062
  const fallback = getVisionFallback(globalConfig);
7016
7063
  if (fallback) {
@@ -7091,7 +7138,7 @@ All file and git operations should use this branch.
7091
7138
  }));
7092
7139
  }
7093
7140
  app.post("/api/proxy/test", async (_req, res) => {
7094
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-2RZBMX5Y.js");
7141
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-KO6DSJLD.js");
7095
7142
  const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
7096
7143
  if (!proxyUrl) {
7097
7144
  return res.status(400).json({ success: false, error: "No proxy URL configured" });
@@ -7183,7 +7230,7 @@ All file and git operations should use this branch.
7183
7230
  }
7184
7231
  });
7185
7232
  app.post("/api/proxy/test", async (_req, res) => {
7186
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-2RZBMX5Y.js");
7233
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-KO6DSJLD.js");
7187
7234
  const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
7188
7235
  if (!proxyUrl) {
7189
7236
  return res.status(400).json({ success: false, error: "No proxy URL configured" });
@@ -7210,7 +7257,7 @@ All file and git operations should use this branch.
7210
7257
  const backend = req.query["backend"];
7211
7258
  if (!url) return res.status(400).json({ error: "url is required" });
7212
7259
  try {
7213
- const { fetchModelsWithContext } = await import("./provider-manager-MWAIOX2A.js");
7260
+ const { fetchModelsWithContext } = await import("./provider-manager-W5N4XRE5.js");
7214
7261
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
7215
7262
  const models = await fetchModelsWithContext(
7216
7263
  url,
@@ -7281,7 +7328,7 @@ All file and git operations should use this branch.
7281
7328
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
7282
7329
  const { getBackendCapabilities } = await import("./backend-P3GHHLHJ.js");
7283
7330
  const { buildNonStreamingCreateParams } = await import("./client-pure-VFZIIK4S.js");
7284
- const { OpenAIHttpClient } = await import("./http-client-MQARNFY3.js");
7331
+ const { OpenAIHttpClient } = await import("./http-client-2GDKHZIG.js");
7285
7332
  const { ensureVersionPrefix } = await import("./url-utils-SAJP7AEX.js");
7286
7333
  const profile = getModelProfile2(model);
7287
7334
  const capabilities = getBackendCapabilities(backend || "unknown");
@@ -7351,7 +7398,7 @@ All file and git operations should use this branch.
7351
7398
  return res.status(400).json({ error: "name, url, and backend are required" });
7352
7399
  }
7353
7400
  try {
7354
- const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-HX7FDKGJ.js");
7401
+ const { loadGlobalConfig, saveGlobalConfig, addProvider, setDefaultModelSelection } = await import("./config-TW5FHQEM.js");
7355
7402
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7356
7403
  const providerBackend = backend;
7357
7404
  const providerModels = modelConfigs?.length ? buildModelConfigs(modelConfigs) : model ? [{ id: model, contextWindow: 2e5, source: "user" }] : [];
@@ -7392,7 +7439,7 @@ All file and git operations should use this branch.
7392
7439
  app.post("/api/init/config", async (req, res) => {
7393
7440
  const { workdir, visionFallback } = req.body;
7394
7441
  try {
7395
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
7442
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7396
7443
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7397
7444
  const updatedVf = visionFallback ? { ...globalConfig.visionFallback, ...visionFallback } : globalConfig.visionFallback;
7398
7445
  const updatedConfig = {
@@ -7427,7 +7474,7 @@ All file and git operations should use this branch.
7427
7474
  }
7428
7475
  const updates = parsed.data;
7429
7476
  try {
7430
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
7477
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7431
7478
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7432
7479
  const filteredUpdates = Object.fromEntries(Object.entries(updates).filter(([, v]) => v !== void 0));
7433
7480
  const updatedConfig = {
@@ -7469,8 +7516,8 @@ All file and git operations should use this branch.
7469
7516
  }
7470
7517
  const testConfig = parsed.data;
7471
7518
  try {
7472
- const { resolveVisionFallback } = await import("./config-HX7FDKGJ.js");
7473
- const { loadGlobalConfig } = await import("./config-HX7FDKGJ.js");
7519
+ const { resolveVisionFallback } = await import("./config-TW5FHQEM.js");
7520
+ const { loadGlobalConfig } = await import("./config-TW5FHQEM.js");
7474
7521
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7475
7522
  const filteredTestConfig = Object.fromEntries(Object.entries(testConfig).filter(([, v]) => v !== void 0));
7476
7523
  const testVisionFallback = {
@@ -7521,7 +7568,7 @@ All file and git operations should use this branch.
7521
7568
  });
7522
7569
  app.delete("/api/providers/:id", async (req, res) => {
7523
7570
  const { id } = req.params;
7524
- const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-HX7FDKGJ.js");
7571
+ const { loadGlobalConfig, saveGlobalConfig, removeProvider } = await import("./config-TW5FHQEM.js");
7525
7572
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7526
7573
  const updatedConfig = removeProvider(globalConfig, id);
7527
7574
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
@@ -7533,7 +7580,7 @@ All file and git operations should use this branch.
7533
7580
  const { id } = req.params;
7534
7581
  const { isLocal } = req.body;
7535
7582
  try {
7536
- const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-HX7FDKGJ.js");
7583
+ const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-TW5FHQEM.js");
7537
7584
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7538
7585
  const provider = globalConfig.providers.find((p) => p.id === id);
7539
7586
  if (!provider) {
@@ -7565,7 +7612,7 @@ All file and git operations should use this branch.
7565
7612
  transportAdapter
7566
7613
  } = req.body;
7567
7614
  try {
7568
- const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-HX7FDKGJ.js");
7615
+ const { loadGlobalConfig, saveGlobalConfig, updateProvider } = await import("./config-TW5FHQEM.js");
7569
7616
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7570
7617
  const provider = globalConfig.providers.find((p) => p.id === id);
7571
7618
  if (!provider) {
@@ -7606,7 +7653,7 @@ All file and git operations should use this branch.
7606
7653
  return res.status(400).json({ error: result.error });
7607
7654
  }
7608
7655
  const llmClient = getLLMClient();
7609
- const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-HX7FDKGJ.js");
7656
+ const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import("./config-TW5FHQEM.js");
7610
7657
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7611
7658
  const updatedConfig = setDefaultModelSelection(globalConfig, id, llmClient.getModel());
7612
7659
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
@@ -7633,7 +7680,7 @@ All file and git operations should use this branch.
7633
7680
  });
7634
7681
  async function rebuildMcpTools() {
7635
7682
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-FEAHWU5C.js");
7636
- const { setMcpTools: setMcpTools2 } = await import("./tools-KPIYFL5A.js");
7683
+ const { setMcpTools: setMcpTools2 } = await import("./tools-HTUTYMKI.js");
7637
7684
  const mcpTools = createMcpTools2(mcpManager);
7638
7685
  setMcpTools2(mcpTools);
7639
7686
  toolRegistry = createToolRegistry();
@@ -7681,7 +7728,7 @@ All file and git operations should use this branch.
7681
7728
  }
7682
7729
  });
7683
7730
  app.post("/api/mcp/servers", async (req, res) => {
7684
- const { name, transport, command, args, env, url, headers, timeout } = req.body;
7731
+ const { name, transport, command, args, env, url, headers, oauth, timeout } = req.body;
7685
7732
  if (!name) {
7686
7733
  return res.status(400).json({ error: "name is required" });
7687
7734
  }
@@ -7691,6 +7738,9 @@ All file and git operations should use this branch.
7691
7738
  if (timeout !== void 0 && (typeof timeout !== "number" || timeout <= 0)) {
7692
7739
  return res.status(400).json({ error: "timeout must be a positive number" });
7693
7740
  }
7741
+ if (oauth !== void 0 && typeof oauth !== "boolean") {
7742
+ return res.status(400).json({ error: "oauth must be a boolean" });
7743
+ }
7694
7744
  try {
7695
7745
  const resolvedTransport = transport === "http" ? "http" : "stdio";
7696
7746
  const serverCfg = {
@@ -7700,11 +7750,12 @@ All file and git operations should use this branch.
7700
7750
  ...env && Object.keys(env).length > 0 ? { env } : {},
7701
7751
  ...url ? { url } : {},
7702
7752
  ...headers && Object.keys(headers).length > 0 ? { headers } : {},
7753
+ ...oauth ? { oauth: true } : {},
7703
7754
  ...timeout !== void 0 ? { timeout } : {}
7704
7755
  };
7705
7756
  await mcpManager.addServer(name, serverCfg);
7706
7757
  const server = mcpManager.getServer(name);
7707
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
7758
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7708
7759
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7709
7760
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {}, [name]: serverCfg };
7710
7761
  await saveGlobalConfig(
@@ -7736,7 +7787,7 @@ All file and git operations should use this branch.
7736
7787
  return res.status(404).json({ error: `MCP server '${name}' not found` });
7737
7788
  }
7738
7789
  const body = req.body;
7739
- const { transport: rawTransport, command, args, env, url, headers, timeout, disabled } = body;
7790
+ const { transport: rawTransport, command, args, env, url, headers, oauth, timeout, disabled } = body;
7740
7791
  if (rawTransport !== void 0 && rawTransport !== "stdio" && rawTransport !== "http") {
7741
7792
  return res.status(400).json({ error: `Invalid transport '${String(rawTransport)}'. Must be 'stdio' or 'http'.` });
7742
7793
  }
@@ -7761,9 +7812,12 @@ All file and git operations should use this branch.
7761
7812
  if (disabled !== void 0 && typeof disabled !== "boolean") {
7762
7813
  return res.status(400).json({ error: "disabled must be a boolean" });
7763
7814
  }
7815
+ if (oauth !== void 0 && typeof oauth !== "boolean") {
7816
+ return res.status(400).json({ error: "oauth must be a boolean" });
7817
+ }
7764
7818
  try {
7765
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
7766
- const { applyMcpServerUpdate } = await import("./update-server-4I6LXE5K.js");
7819
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7820
+ const { applyMcpServerUpdate } = await import("./update-server-LOOXIXDW.js");
7767
7821
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7768
7822
  const mcpServers2 = { ...globalConfig.mcpServers ?? {} };
7769
7823
  const patch = {
@@ -7773,6 +7827,7 @@ All file and git operations should use this branch.
7773
7827
  ...env !== void 0 ? { env } : {},
7774
7828
  ...url !== void 0 ? { url } : {},
7775
7829
  ...headers !== void 0 ? { headers } : {},
7830
+ ...oauth !== void 0 ? { oauth } : {},
7776
7831
  ...timeout !== void 0 ? { timeout } : {},
7777
7832
  ...disabled !== void 0 ? { disabled } : {}
7778
7833
  };
@@ -7808,7 +7863,9 @@ All file and git operations should use this branch.
7808
7863
  return res.status(404).json({ error: `MCP server '${name}' not found` });
7809
7864
  }
7810
7865
  mcpManager.removeServer(name);
7811
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
7866
+ const { clearMcpOAuthEntry } = await import("./oauth-store-XCFXV2VM.js");
7867
+ await clearMcpOAuthEntry(name);
7868
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7812
7869
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7813
7870
  const updatedMcpServers = { ...globalConfig.mcpServers ?? {} };
7814
7871
  delete updatedMcpServers[name];
@@ -7828,6 +7885,143 @@ All file and git operations should use this branch.
7828
7885
  wssExports.broadcastAll(createServerMessage("mcp.servers.changed", { servers: mcpManager.getAllServers() }));
7829
7886
  res.json({ success: true });
7830
7887
  });
7888
+ function oauthCallbackPage(message) {
7889
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>OpenFox</title></head><body style="font-family:system-ui;padding:2rem"><p>${message}</p></body></html>`;
7890
+ }
7891
+ function parseOAuthResponse(value) {
7892
+ let params;
7893
+ try {
7894
+ params = new URL(value).searchParams;
7895
+ } catch {
7896
+ params = value.includes("code=") ? new URLSearchParams(value.replace(/^\?/, "")) : null;
7897
+ }
7898
+ if (!params) return { code: value };
7899
+ const code = params.get("code");
7900
+ const state = params.get("state");
7901
+ return { ...code ? { code } : {}, ...state ? { state } : {} };
7902
+ }
7903
+ async function applyMcpOAuthResult(name) {
7904
+ await mcpManager.connectServer(name);
7905
+ await rebuildMcpTools();
7906
+ for (const s of sessionManager.listSessions()) {
7907
+ sessionManager.setDynamicContextChanged(s.id, true);
7908
+ }
7909
+ wssExports.broadcastAll(createServerMessage("mcp.servers.changed", { servers: mcpManager.getAllServers() }));
7910
+ }
7911
+ async function completeMcpOAuth(name, serverUrl, code) {
7912
+ const { auth } = await import("@modelcontextprotocol/sdk/client/auth.js");
7913
+ const { McpOAuthProvider: McpOAuthProvider2 } = await import("./oauth-provider-52YILVUJ.js");
7914
+ const { clearMcpOAuthAuthorizationState } = await import("./oauth-store-XCFXV2VM.js");
7915
+ const provider = new McpOAuthProvider2(name, serverUrl);
7916
+ try {
7917
+ const result = await auth(provider, { serverUrl, authorizationCode: code });
7918
+ if (result !== "AUTHORIZED") {
7919
+ throw new Error("The authorization server did not return a usable grant");
7920
+ }
7921
+ } catch (error) {
7922
+ await clearMcpOAuthAuthorizationState(name, serverUrl);
7923
+ throw error;
7924
+ }
7925
+ await applyMcpOAuthResult(name);
7926
+ }
7927
+ function oauthEnabledServerUrl(name) {
7928
+ const server = mcpManager.getServer(name);
7929
+ if (!server || server.config.transport !== "http" || !server.config.oauth) return void 0;
7930
+ return server.config.url;
7931
+ }
7932
+ app.post("/api/mcp/servers/:name/oauth/start", async (req, res) => {
7933
+ const { name } = req.params;
7934
+ const server = mcpManager.getServer(name);
7935
+ if (!server) {
7936
+ return res.status(404).json({ error: `MCP server '${name}' not found` });
7937
+ }
7938
+ if (server.config.transport !== "http" || !server.config.url) {
7939
+ return res.status(400).json({ error: "OAuth is only available for http transport" });
7940
+ }
7941
+ if (!server.config.oauth) {
7942
+ return res.status(400).json({ error: `MCP server '${name}' is not configured for OAuth` });
7943
+ }
7944
+ try {
7945
+ const { auth } = await import("@modelcontextprotocol/sdk/client/auth.js");
7946
+ const { McpOAuthProvider: McpOAuthProvider2 } = await import("./oauth-provider-52YILVUJ.js");
7947
+ const provider = new McpOAuthProvider2(name, server.config.url);
7948
+ const result = await auth(provider, { serverUrl: server.config.url });
7949
+ if (result === "AUTHORIZED") {
7950
+ await applyMcpOAuthResult(name);
7951
+ return res.json({ status: "authorized" });
7952
+ }
7953
+ const authorizationUrl = provider.pendingAuthorizationUrl;
7954
+ if (!authorizationUrl) {
7955
+ return res.status(400).json({ error: "The server did not produce an authorization URL" });
7956
+ }
7957
+ res.json({ status: "redirect", authorizationUrl: authorizationUrl.toString(), redirectUri: provider.redirectUrl });
7958
+ } catch (error) {
7959
+ res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
7960
+ }
7961
+ });
7962
+ app.get("/api/mcp/oauth/callback", async (req, res) => {
7963
+ const code = typeof req.query["code"] === "string" ? req.query["code"] : "";
7964
+ const state = typeof req.query["state"] === "string" ? req.query["state"] : "";
7965
+ if (!code || !state) {
7966
+ return res.status(400).type("html").send(oauthCallbackPage("Missing authorization code or state."));
7967
+ }
7968
+ const { findMcpOAuthEntryByState } = await import("./oauth-store-XCFXV2VM.js");
7969
+ const pending = await findMcpOAuthEntryByState(state);
7970
+ if (!pending) {
7971
+ return res.status(400).type("html").send(oauthCallbackPage("No pending authorization matches this callback."));
7972
+ }
7973
+ const pendingUrl = oauthEnabledServerUrl(pending.name);
7974
+ if (!pendingUrl || pendingUrl !== pending.entry.serverUrl) {
7975
+ return res.status(400).type("html").send(oauthCallbackPage("This server is no longer configured for OAuth."));
7976
+ }
7977
+ try {
7978
+ await completeMcpOAuth(pending.name, pending.entry.serverUrl, code);
7979
+ res.type("html").send(oauthCallbackPage("Authorization complete. You can close this tab and go back to OpenFox."));
7980
+ } catch (error) {
7981
+ logger.error("MCP OAuth callback failed", { error: error instanceof Error ? error.message : String(error) });
7982
+ res.status(400).type("html").send(oauthCallbackPage("Authorization failed. See the OpenFox logs for details."));
7983
+ }
7984
+ });
7985
+ app.post("/api/mcp/servers/:name/oauth/complete", async (req, res) => {
7986
+ const { name } = req.params;
7987
+ const { response } = req.body;
7988
+ const server = mcpManager.getServer(name);
7989
+ if (!server) {
7990
+ return res.status(404).json({ error: `MCP server '${name}' not found` });
7991
+ }
7992
+ const serverUrl = oauthEnabledServerUrl(name);
7993
+ if (!serverUrl) {
7994
+ return res.status(400).json({ error: `MCP server '${name}' is not configured for OAuth` });
7995
+ }
7996
+ if (typeof response !== "string" || !response.trim()) {
7997
+ return res.status(400).json({ error: "response is required" });
7998
+ }
7999
+ const parsed = parseOAuthResponse(response.trim());
8000
+ if (!parsed.code || !parsed.state) {
8001
+ return res.status(400).json({ error: "Paste the whole callback URL, both code and state are needed" });
8002
+ }
8003
+ const { readMcpOAuthEntry } = await import("./oauth-store-XCFXV2VM.js");
8004
+ const entry = await readMcpOAuthEntry(name, serverUrl);
8005
+ if (!entry?.state || entry.state !== parsed.state) {
8006
+ return res.status(400).json({ error: "This callback does not match the pending authorization" });
8007
+ }
8008
+ try {
8009
+ await completeMcpOAuth(name, serverUrl, parsed.code);
8010
+ res.json({ server: mcpManager.getServer(name) });
8011
+ } catch (error) {
8012
+ res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
8013
+ }
8014
+ });
8015
+ app.delete("/api/mcp/servers/:name/oauth", async (req, res) => {
8016
+ const { name } = req.params;
8017
+ if (!mcpManager.getServer(name)) {
8018
+ return res.status(404).json({ error: `MCP server '${name}' not found` });
8019
+ }
8020
+ const { clearMcpOAuthEntry } = await import("./oauth-store-XCFXV2VM.js");
8021
+ await clearMcpOAuthEntry(name);
8022
+ await applyMcpOAuthResult(name);
8023
+ res.json({ success: true });
8024
+ });
7831
8025
  app.put("/api/mcp/servers/:name/tools/:toolName", async (req, res) => {
7832
8026
  const { name, toolName } = req.params;
7833
8027
  const { enabled } = req.body;
@@ -7838,7 +8032,7 @@ All file and git operations should use this branch.
7838
8032
  await mcpManager.setToolEnabled(name, toolName, enabled);
7839
8033
  const server = mcpManager.getServer(name);
7840
8034
  if (server) {
7841
- const { loadGlobalConfig, saveGlobalConfig } = await import("./config-HX7FDKGJ.js");
8035
+ const { loadGlobalConfig, saveGlobalConfig } = await import("./config-TW5FHQEM.js");
7842
8036
  const globalConfig = await loadGlobalConfig(config3.mode ?? "production", config3.globalConfigPath);
7843
8037
  const mcpServers2 = { ...globalConfig.mcpServers ?? {} };
7844
8038
  const serverCfg = mcpServers2[name];
@@ -7894,13 +8088,13 @@ All file and git operations should use this branch.
7894
8088
  })
7895
8089
  );
7896
8090
  app.get("/api/sessions/:id/background-processes", async (req, res) => {
7897
- const { getSessionProcesses } = await import("./manager-RJH7EYIG.js");
8091
+ const { getSessionProcesses } = await import("./manager-HCMDFEQH.js");
7898
8092
  const sessionId = req.params.id;
7899
8093
  const processes = getSessionProcesses(sessionId);
7900
8094
  res.json({ processes });
7901
8095
  });
7902
8096
  app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
7903
- const { stopProcess } = await import("./manager-RJH7EYIG.js");
8097
+ const { stopProcess } = await import("./manager-HCMDFEQH.js");
7904
8098
  const sessionId = req.params.id;
7905
8099
  const processId = req.params.processId;
7906
8100
  const session = sessionManager.getSession(sessionId);
@@ -8045,7 +8239,7 @@ All file and git operations should use this branch.
8045
8239
  const state = sessionManager.getContextState(sessionId);
8046
8240
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
8047
8241
  });
8048
- const { QueueProcessor } = await import("./processor-FTCPHWBM.js");
8242
+ const { QueueProcessor } = await import("./processor-UN4H4V7F.js");
8049
8243
  const queueProcessor = new QueueProcessor({
8050
8244
  sessionManager,
8051
8245
  providerManager,
@@ -8074,6 +8268,7 @@ All file and git operations should use this branch.
8074
8268
  httpServer.listen(listenPort, host, () => {
8075
8269
  const addr = httpServer.address();
8076
8270
  const actualPort = typeof addr === "object" && addr ? addr.port : listenPort;
8271
+ setMcpOAuthServerPort(actualPort);
8077
8272
  const client = getLLMClient();
8078
8273
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
8079
8274
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
@@ -8129,4 +8324,4 @@ export {
8129
8324
  createServerHandle,
8130
8325
  createServer
8131
8326
  };
8132
- //# sourceMappingURL=chunk-ZJW3KOII.js.map
8327
+ //# sourceMappingURL=chunk-IYTDCPEQ.js.map