openfox 2.0.134 → 2.0.136

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 (88) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/CHANGELOG.md +45 -0
  3. package/dist/agent-defaults/builder.agent.md +1 -0
  4. package/dist/agent-defaults/planner.agent.md +1 -0
  5. package/dist/{ask-UBIRH3SO.js → ask-46J5WYRL.js} +2 -2
  6. package/dist/{auto-config-5VSNLVNI.js → auto-config-2A7Y2WOK.js} +25 -6
  7. package/dist/{backend-NDBY3DAQ.js → backend-24FTDSHF.js} +4 -2
  8. package/dist/{chat-handler-YCZE2XEJ.js → chat-handler-SYU4HJMI.js} +30 -26
  9. package/dist/{chunk-CSYOWFPU.js → chunk-342BKOTE.js} +29 -5
  10. package/dist/{chunk-7QMWYNVF.js → chunk-4LLGI372.js} +2 -2
  11. package/dist/chunk-4SBVW4UH.js +24 -0
  12. package/dist/{chunk-FAQDLL2X.js → chunk-5YPHN5NC.js} +8 -8
  13. package/dist/{chunk-ZMK4VX7V.js → chunk-64YDOCQR.js} +53 -21
  14. package/dist/{chunk-UV6IH6HK.js → chunk-AKWJMMEJ.js} +15 -1
  15. package/dist/{chunk-ORCQ3EXQ.js → chunk-BHVR2YS5.js} +2 -2
  16. package/dist/{chunk-7HGBJFIJ.js → chunk-CPVEONNS.js} +12 -10
  17. package/dist/{chunk-QDARWVQ2.js → chunk-DG2YSWMC.js} +40 -6
  18. package/dist/{chunk-J5HOUEPE.js → chunk-EXLCFEML.js} +86 -1010
  19. package/dist/chunk-FSSUPWYO.js +336 -0
  20. package/dist/{chunk-5UQ4CKOA.js → chunk-G5GUQKLS.js} +27 -6
  21. package/dist/{chunk-M4J2L4VH.js → chunk-GP5BYQMF.js} +23 -23
  22. package/dist/{chunk-7ET46SNE.js → chunk-HEYU7FAY.js} +3 -3
  23. package/dist/{chunk-MRE4OYKI.js → chunk-MILEZY2J.js} +4 -4
  24. package/dist/{chunk-O3RCSKUH.js → chunk-MOYWDP73.js} +2 -2
  25. package/dist/{chunk-J3NMNYGM.js → chunk-N5JKVNLH.js} +2 -2
  26. package/dist/{chunk-YLVOU7T7.js → chunk-PQKLOLGC.js} +162 -6
  27. package/dist/{chunk-DWA4IE65.js → chunk-Q33DL67W.js} +2 -2
  28. package/dist/{chunk-OZWHRBDY.js → chunk-QBWJCO5K.js} +12 -29
  29. package/dist/{chunk-EUOWCVU6.js → chunk-QMU3ZY2C.js} +37 -341
  30. package/dist/{chunk-5IXCCMFU.js → chunk-QQQBNL7A.js} +350 -157
  31. package/dist/{chunk-CTWZPN7G.js → chunk-QUAEH3MP.js} +29 -1
  32. package/dist/{chunk-5UMXFLET.js → chunk-SAGDTQXD.js} +3 -3
  33. package/dist/chunk-U6FHHT2B.js +1155 -0
  34. package/dist/{chunk-YOPXAI2W.js → chunk-UL7776XB.js} +21 -21
  35. package/dist/{chunk-JURM3RPZ.js → chunk-V5AC2TV7.js} +8 -13
  36. package/dist/{chunk-BZND27IB.js → chunk-VA2TYWQR.js} +4 -4
  37. package/dist/{chunk-JE7LW7Y6.js → chunk-VIJVLLPT.js} +12 -3
  38. package/dist/{chunk-2AI7VYPN.js → chunk-VKMPR25F.js} +9 -3
  39. package/dist/chunk-VWBPQZLO.js +7 -0
  40. package/dist/{chunk-ZTBKMVV6.js → chunk-X4PVR6AW.js} +15 -2
  41. package/dist/chunk-XG3AUMPI.js +72 -0
  42. package/dist/{chunk-MEEUXRFL.js → chunk-XGG4XCKP.js} +2 -2
  43. package/dist/{chunk-QICVOQNX.js → chunk-YDPC4FLR.js} +17 -11
  44. package/dist/cli/dev.js +1 -1
  45. package/dist/cli/index.js +1 -1
  46. package/dist/client-MVI3J7SN.js +18 -0
  47. package/dist/{client-pure-FLKP6PTI.js → client-pure-YZ4IGCU4.js} +4 -2
  48. package/dist/{compactor-PD6DQ4NY.js → compactor-LBK53WAK.js} +14 -12
  49. package/dist/describe-image-4XDLSKAB.js +30 -0
  50. package/dist/{dynamic-context-WKEXQCTK.js → dynamic-context-RDBNQPPA.js} +12 -10
  51. package/dist/{events-3WSNI7XC.js → events-YTYYT3PR.js} +6 -6
  52. package/dist/export-import-GHRCOQHF.js +137 -0
  53. package/dist/{folding-H7JTX6KI.js → folding-3MMOPS4W.js} +4 -4
  54. package/dist/{http-client-A445WYZU.js → http-client-C6UYWVWZ.js} +3 -3
  55. package/dist/launch-YZ46OEFP.js +58 -0
  56. package/dist/{manager-ZACEUL5P.js → manager-FSPRJCYT.js} +4 -4
  57. package/dist/{model-catalog-2PCKTYGW.js → model-catalog-Y5MA5OZP.js} +2 -2
  58. package/dist/{orchestrator-OT66EDXO.js → orchestrator-6QGQ55NT.js} +29 -25
  59. package/dist/package.json +1 -1
  60. package/dist/{path-security-5CFMMULR.js → path-security-EC4Z2ZZG.js} +8 -8
  61. package/dist/{platform-XPMZKAUB.js → platform-KPKYBU54.js} +3 -3
  62. package/dist/{processor-CHMHMMIE.js → processor-B2RV7MVC.js} +29 -25
  63. package/dist/{provider-JWUNG2TD.js → provider-SOC6Z25R.js} +10 -8
  64. package/dist/{provider-manager-2KKZ37XJ.js → provider-manager-Y53SVVQ3.js} +10 -8
  65. package/dist/{registry-BEIR7Y5G.js → registry-FMDMGIUB.js} +3 -3
  66. package/dist/{serve-HSDVY37K.js → serve-EWA5HXC7.js} +41 -32
  67. package/dist/server/index.d.ts +16 -0
  68. package/dist/server/index.js +34 -30
  69. package/dist/server-ZAPAB3FS.js +61 -0
  70. package/dist/{service-XIUNS5XV.js → service-NKLQH647.js} +12 -9
  71. package/dist/{session-overrides-Y5B4XQPU.js → session-overrides-ANQBKV74.js} +11 -7
  72. package/dist/{sessions-IGINPPBP.js → sessions-GLYACE5R.js} +6 -4
  73. package/dist/{settings-ZJPM6PQV.js → settings-WH6BVQCP.js} +4 -2
  74. package/dist/{tasks-3JJWJJ3X.js → tasks-GPM3JAE6.js} +14 -10
  75. package/dist/tool-adapter-ZY4FC4C4.js +9 -0
  76. package/dist/{tools-WWIWD3O7.js → tools-EJOABHVO.js} +27 -23
  77. package/dist/{update-Q6SH7UP2.js → update-IPHJMRQZ.js} +2 -2
  78. package/dist/web/assets/index-CfFwerN2.js +313 -0
  79. package/dist/web/assets/{index-Y300llHY.css → index-ChJjYovg.css} +1 -1
  80. package/dist/web/index.html +2 -2
  81. package/dist/web/sw.js +1 -1
  82. package/package.json +1 -1
  83. package/dist/chunk-QTLYD2FF.js +0 -7
  84. package/dist/client-VVYOWXRR.js +0 -16
  85. package/dist/launch-FJ65HRV4.js +0 -54
  86. package/dist/server-3UVLECD5.js +0 -57
  87. package/dist/tool-adapter-FJAFLDZA.js +0 -8
  88. package/dist/web/assets/index-C48qmBAI.js +0 -313
@@ -1,3 +1,15 @@
1
+ import {
2
+ createWebSocketServer,
3
+ currentSessionToken,
4
+ getAuthConfig,
5
+ hasPassword,
6
+ isValidToken,
7
+ loadServerAuthConfig,
8
+ requiresAuth,
9
+ terminalManager,
10
+ tokenFromPassword,
11
+ verifyPassword
12
+ } from "./chunk-GP5BYQMF.js";
1
13
  import {
2
14
  projectSessionStatus
3
15
  } from "./chunk-T3S5MTMD.js";
@@ -13,21 +25,9 @@ import {
13
25
  setMcpOAuthStoreMode,
14
26
  setMcpOAuthStorePath
15
27
  } from "./chunk-IJ53Y77N.js";
16
- import {
17
- createWebSocketServer,
18
- currentSessionToken,
19
- getAuthConfig,
20
- hasPassword,
21
- isValidToken,
22
- loadServerAuthConfig,
23
- requiresAuth,
24
- terminalManager,
25
- tokenFromPassword,
26
- verifyPassword
27
- } from "./chunk-M4J2L4VH.js";
28
28
  import {
29
29
  TEMPLATE_VARIABLES
30
- } from "./chunk-7HGBJFIJ.js";
30
+ } from "./chunk-CPVEONNS.js";
31
31
  import {
32
32
  createToolRegistry,
33
33
  devServerManager,
@@ -42,7 +42,26 @@ import {
42
42
  setMcpManagerForTools,
43
43
  setMcpTools,
44
44
  setNotifyMcpServersChanged
45
- } from "./chunk-J5HOUEPE.js";
45
+ } from "./chunk-EXLCFEML.js";
46
+ import {
47
+ deleteOwnedSkill,
48
+ deleteProjectSkill,
49
+ deleteSkill,
50
+ findSkillById,
51
+ getDefaultSkillIds,
52
+ isDefaultSkill,
53
+ isSkillEnabled,
54
+ loadAllSkills,
55
+ loadAllSkillsWithDiagnostics,
56
+ loadDefaultSkills,
57
+ loadProjectSkills,
58
+ loadUserSkills,
59
+ saveSkill,
60
+ saveSkillToProject,
61
+ setSkillEnabled,
62
+ skillExists,
63
+ updateOwnedSkill
64
+ } from "./chunk-Q33DL67W.js";
46
65
  import {
47
66
  checkoutBranchFromSharedSource,
48
67
  deleteWorkspace,
@@ -86,49 +105,35 @@ import {
86
105
  saveCommandToProject,
87
106
  saveWorkflow,
88
107
  saveWorkflowToProject,
89
- serverT,
90
108
  workflowExists
91
- } from "./chunk-OZWHRBDY.js";
109
+ } from "./chunk-QBWJCO5K.js";
92
110
  import {
111
+ clearSessionOverrides,
112
+ computeDisabledServersForProject,
93
113
  getSessionDisabledServers,
114
+ initSessionMcpOverrides,
94
115
  setSessionDisabledServers
95
- } from "./chunk-QDARWVQ2.js";
116
+ } from "./chunk-DG2YSWMC.js";
96
117
  import {
97
- createMcpTools
98
- } from "./chunk-JE7LW7Y6.js";
99
- import {
100
- deleteOwnedSkill,
101
- deleteProjectSkill,
102
- deleteSkill,
103
- findSkillById,
104
- getDefaultSkillIds,
105
- isDefaultSkill,
106
- isSkillEnabled,
107
- loadAllSkills,
108
- loadAllSkillsWithDiagnostics,
109
- loadDefaultSkills,
110
- loadProjectSkills,
111
- loadUserSkills,
112
- saveSkill,
113
- saveSkillToProject,
114
- setSkillEnabled,
115
- skillExists,
116
- updateOwnedSkill
117
- } from "./chunk-DWA4IE65.js";
118
+ serverT
119
+ } from "./chunk-4SBVW4UH.js";
118
120
  import {
119
121
  ALWAYS_ALLOWED,
120
122
  ALWAYS_ALLOWED_FOR_SUBAGENTS,
121
123
  TOP_LEVEL_ONLY_TOOLS
122
- } from "./chunk-7QMWYNVF.js";
124
+ } from "./chunk-4LLGI372.js";
125
+ import {
126
+ createMcpTools
127
+ } from "./chunk-VIJVLLPT.js";
123
128
  import {
124
129
  EventEmitter,
125
130
  getPendingQuestionsForSession,
126
131
  provideAnswer
127
- } from "./chunk-JURM3RPZ.js";
132
+ } from "./chunk-V5AC2TV7.js";
128
133
  import {
129
134
  getPendingConfirmationsBySession,
130
135
  providePathConfirmation
131
- } from "./chunk-YLVOU7T7.js";
136
+ } from "./chunk-PQKLOLGC.js";
132
137
  import {
133
138
  combineEventsWithSnapshot,
134
139
  emitAssistantMessageStart,
@@ -146,10 +151,10 @@ import {
146
151
  getEventStore,
147
152
  getSessionState,
148
153
  initEventStore
149
- } from "./chunk-CSYOWFPU.js";
154
+ } from "./chunk-342BKOTE.js";
150
155
  import {
151
156
  buildMessagesFromStoredEvents
152
- } from "./chunk-MEEUXRFL.js";
157
+ } from "./chunk-XGG4XCKP.js";
153
158
  import {
154
159
  clearWorkflowExecution,
155
160
  createSession,
@@ -163,6 +168,7 @@ import {
163
168
  listSessions,
164
169
  listSessionsByProject,
165
170
  listSessionsLimited,
171
+ setSessionMessageCount,
166
172
  toggleFavorite,
167
173
  updateSessionBranch,
168
174
  updateSessionCachedPrompt,
@@ -175,7 +181,7 @@ import {
175
181
  updateSessionRunning,
176
182
  updateSessionWorkdir,
177
183
  updateWorkflowExecutionStatus
178
- } from "./chunk-ZTBKMVV6.js";
184
+ } from "./chunk-X4PVR6AW.js";
179
185
  import {
180
186
  agentExists,
181
187
  deleteAgent,
@@ -192,7 +198,7 @@ import {
192
198
  saveAgent,
193
199
  saveAgentToProject,
194
200
  setRuntimeConfig
195
- } from "./chunk-ORCQ3EXQ.js";
201
+ } from "./chunk-BHVR2YS5.js";
196
202
  import {
197
203
  findFileByInternalId,
198
204
  pathExists
@@ -204,19 +210,19 @@ import {
204
210
  import {
205
211
  getPathSeparator,
206
212
  isAbsolutePath
207
- } from "./chunk-O3RCSKUH.js";
213
+ } from "./chunk-MOYWDP73.js";
208
214
  import {
209
215
  createProviderManager,
210
216
  detectModel,
211
217
  getLlmStatus,
212
218
  parseDefaultModelSelection
213
- } from "./chunk-5UQ4CKOA.js";
219
+ } from "./chunk-G5GUQKLS.js";
214
220
  import {
215
221
  buildOpenFoxMcpBootstrap
216
222
  } from "./chunk-YNMP647F.js";
217
223
  import {
218
224
  VERSION
219
- } from "./chunk-QTLYD2FF.js";
225
+ } from "./chunk-VWBPQZLO.js";
220
226
  import {
221
227
  deleteProject,
222
228
  getProject,
@@ -229,25 +235,29 @@ import {
229
235
  import {
230
236
  detectBackendFromUrl,
231
237
  getBackendDisplayName
232
- } from "./chunk-UV6IH6HK.js";
238
+ } from "./chunk-AKWJMMEJ.js";
233
239
  import {
234
240
  buildModelsUrl
235
241
  } from "./chunk-HNCM3D7Y.js";
242
+ import {
243
+ sanitizeToolSchema
244
+ } from "./chunk-XG3AUMPI.js";
236
245
  import {
237
246
  SessionNotFoundError,
238
247
  WorkspaceInUseError
239
- } from "./chunk-J3NMNYGM.js";
248
+ } from "./chunk-N5JKVNLH.js";
240
249
  import {
241
250
  deleteSetting,
242
251
  getSetting,
243
252
  setSetting
244
- } from "./chunk-CTWZPN7G.js";
253
+ } from "./chunk-QUAEH3MP.js";
245
254
  import {
246
255
  initDatabase
247
256
  } from "./chunk-JU757HVI.js";
248
257
  import {
258
+ isReasoningEffortValidForModel,
249
259
  isReasoningEffortValue
250
- } from "./chunk-2AI7VYPN.js";
260
+ } from "./chunk-VKMPR25F.js";
251
261
  import {
252
262
  logger,
253
263
  setLogLevel
@@ -1734,7 +1744,7 @@ var McpManager = class {
1734
1744
  function: {
1735
1745
  name: `${entry.state.name}_${tool.name}`,
1736
1746
  description: tool.description ?? "",
1737
- parameters: tool.inputSchema
1747
+ parameters: sanitizeToolSchema(tool.inputSchema)
1738
1748
  }
1739
1749
  });
1740
1750
  }
@@ -2825,6 +2835,9 @@ var SessionManager = class {
2825
2835
  announcedPromptHashStore = /* @__PURE__ */ new Map();
2826
2836
  announcedToolFingerprintStore = /* @__PURE__ */ new Map();
2827
2837
  warmedUpSessions = /* @__PURE__ */ new Set();
2838
+ // Sessions already warned about an unresolvable provider — getContextState runs on every
2839
+ // turn, and the warning is only worth one line per session.
2840
+ unknownProviderWarned = /* @__PURE__ */ new Set();
2828
2841
  switchLocks = /* @__PURE__ */ new Map();
2829
2842
  workspaceCreationLocks = /* @__PURE__ */ new Map();
2830
2843
  constructor(providerManager) {
@@ -3009,6 +3022,10 @@ var SessionManager = class {
3009
3022
  const contextWindowId = crypto.randomUUID();
3010
3023
  emitSessionInitialized(dbSession.id, projectId, effectiveWorkdir, contextWindowId, sessionTitle);
3011
3024
  const session = this.buildSessionFromDb(dbSession);
3025
+ try {
3026
+ initSessionMcpOverrides(session.id, projectId, project.mcpOverrides);
3027
+ } catch {
3028
+ }
3012
3029
  getGitBranch(effectiveWorkdir).then((branch) => {
3013
3030
  if (branch) {
3014
3031
  updateSessionBranch(session.id, branch);
@@ -3093,9 +3110,101 @@ var SessionManager = class {
3093
3110
  updateSessionCachedPrompt(newSession.id, cached2.systemPrompt, cached2.tools, cached2.hash, cached2.promptHash);
3094
3111
  this.markWarmedUp(newSession.id);
3095
3112
  }
3113
+ const parentDisabledServers = getSessionDisabledServers(originalSessionId);
3114
+ if (parentDisabledServers.length > 0) {
3115
+ setSessionDisabledServers(newSession.id, parentDisabledServers);
3116
+ }
3096
3117
  this.emit({ type: "session_updated", session: this.requireSession(newSession.id) });
3097
3118
  return this.requireSession(newSession.id);
3098
3119
  }
3120
+ /**
3121
+ * Import a session from an export document into a target project.
3122
+ *
3123
+ * The cached layout (system prompt, tools, hash) is restored verbatim so the
3124
+ * provider-side prefix cache stays valid, and the event history is replayed
3125
+ * as-is. Drift between the original environment's cached layout and the
3126
+ * target environment (system prompt, tools) is announced via injected
3127
+ * <system-reminder> messages, followed by an import marker reminder.
3128
+ *
3129
+ * @param projectId - Target project (the session is created there)
3130
+ * @param rawPayload - Exported session document (validated)
3131
+ * @returns The imported session
3132
+ * @throws Error for invalid payloads or unknown project
3133
+ */
3134
+ async importSession(projectId, rawPayload) {
3135
+ const { parseSessionExport, IMPORTED_SESSION_REMINDER, SESSION_EXPORT_VERSION } = await import("./export-import-GHRCOQHF.js");
3136
+ const { injectContextDriftReminders, getToolSetFingerprint } = await import("./dynamic-context-RDBNQPPA.js");
3137
+ const { loadAllAgentsDefault: loadAllAgentsDefault2, resolveDefaultAgentId } = await import("./registry-FMDMGIUB.js");
3138
+ const payload = parseSessionExport(rawPayload);
3139
+ if (payload.version !== SESSION_EXPORT_VERSION) {
3140
+ throw new Error(`Unsupported session export version: ${payload.version}`);
3141
+ }
3142
+ const project = getProject(projectId);
3143
+ if (!project) {
3144
+ throw new Error(`Project not found: ${projectId}`);
3145
+ }
3146
+ if (!payload.events.some((event) => event.type === "session.initialized")) {
3147
+ throw new Error("Invalid session export: missing session.initialized event");
3148
+ }
3149
+ const providers = this.providerManager.getProviders();
3150
+ const providerId = payload.session.providerId ?? null;
3151
+ const providerModel = payload.session.providerModel ?? null;
3152
+ let resolvedProviderId = null;
3153
+ let resolvedProviderModel = null;
3154
+ if (providerId && providers.some((p) => p.id === providerId)) {
3155
+ resolvedProviderId = providerId;
3156
+ resolvedProviderModel = providerModel;
3157
+ } else if (providerId && payload.source?.providerBackend && payload.source.providerUrl) {
3158
+ const normalizeUrl = (url) => url.replace(/\/+$/, "");
3159
+ const sourceBackend = payload.source.providerBackend;
3160
+ const sourceUrl = normalizeUrl(payload.source.providerUrl);
3161
+ const urlMatch = providers.find(
3162
+ (p) => p.backend === sourceBackend && p.url !== void 0 && normalizeUrl(p.url) === sourceUrl && providerModel !== null && p.models.some((m) => m.id === providerModel || m.apiModelId === providerModel)
3163
+ );
3164
+ if (urlMatch) {
3165
+ resolvedProviderId = urlMatch.id;
3166
+ resolvedProviderModel = providerModel;
3167
+ }
3168
+ }
3169
+ const session = createSession(
3170
+ projectId,
3171
+ project.workdir,
3172
+ payload.session.title,
3173
+ resolvedProviderId,
3174
+ resolvedProviderModel
3175
+ );
3176
+ const eventStore = getEventStore();
3177
+ eventStore.importEvents(session.id, payload.events);
3178
+ const agents = await loadAllAgentsDefault2(project.workdir);
3179
+ const restoredMode = getSessionState(session.id)?.mode ?? session.mode;
3180
+ if (!agents.some((agent) => agent.metadata.id === restoredMode)) {
3181
+ this.setMode(session.id, resolveDefaultAgentId(projectId));
3182
+ }
3183
+ if (payload.cachedLayout) {
3184
+ updateSessionCachedPrompt(
3185
+ session.id,
3186
+ payload.cachedLayout.systemPrompt,
3187
+ payload.cachedLayout.tools,
3188
+ payload.cachedLayout.hash,
3189
+ payload.cachedLayout.promptHash
3190
+ );
3191
+ this.setAnnouncedPromptHash(session.id, payload.cachedLayout.promptHash ?? payload.cachedLayout.hash);
3192
+ this.setAnnouncedToolFingerprint(session.id, getToolSetFingerprint(payload.cachedLayout.tools));
3193
+ this.markWarmedUp(session.id);
3194
+ }
3195
+ await injectContextDriftReminders(this, session.id);
3196
+ emitUserMessage(session.id, IMPORTED_SESSION_REMINDER, {
3197
+ isSystemGenerated: true,
3198
+ messageKind: "auto-prompt",
3199
+ metadata: { type: "session-import", name: "Session Imported", color: "#6b7280", kind: "reminder" }
3200
+ });
3201
+ const state = getSessionState(session.id);
3202
+ if (state) {
3203
+ setSessionMessageCount(session.id, state.messages.length);
3204
+ }
3205
+ this.emit({ type: "session_created", session: this.requireSession(session.id) });
3206
+ return this.requireSession(session.id);
3207
+ }
3099
3208
  /**
3100
3209
  * Get a session by ID. Returns null if not found.
3101
3210
  * Session state is derived from EventStore.
@@ -3162,6 +3271,8 @@ var SessionManager = class {
3162
3271
  this.warmedUpSessions.delete(id);
3163
3272
  this.announcedPromptHashStore.delete(id);
3164
3273
  this.announcedToolFingerprintStore.delete(id);
3274
+ this.unknownProviderWarned.delete(id);
3275
+ clearSessionOverrides(id);
3165
3276
  deleteSession(id);
3166
3277
  if (this.activeSessionId === id) {
3167
3278
  this.activeSessionId = null;
@@ -3274,6 +3385,7 @@ var SessionManager = class {
3274
3385
  if (providerId === null || providerManual === true) {
3275
3386
  this.clearSessionPinnedEffort(sessionId);
3276
3387
  }
3388
+ this.unknownProviderWarned.delete(sessionId);
3277
3389
  const updatedSession = this.requireSession(sessionId);
3278
3390
  this.emit({ type: "session_updated", session: updatedSession });
3279
3391
  return updatedSession;
@@ -3940,7 +4052,21 @@ var SessionManager = class {
3940
4052
  getContextState(sessionId) {
3941
4053
  const providerManager = this.providerManager;
3942
4054
  const { providerId, model } = this.resolveEffectiveProviderModel(sessionId);
3943
- const maxTokens = providerId && model ? this.resolveModelContext(providerId, model) ?? providerManager.getCurrentModelContext() : providerManager.getCurrentModelContext();
4055
+ let maxTokens = providerManager.getCurrentModelContext();
4056
+ if (providerId && model) {
4057
+ const resolved = this.resolveModelContext(providerId, model);
4058
+ if (resolved !== void 0) {
4059
+ maxTokens = resolved;
4060
+ } else {
4061
+ if (!this.unknownProviderWarned.has(sessionId)) {
4062
+ this.unknownProviderWarned.add(sessionId);
4063
+ logger.warn("Session references an unknown provider, falling back to the global context window", {
4064
+ sessionId,
4065
+ providerId
4066
+ });
4067
+ }
4068
+ }
4069
+ }
3944
4070
  const state = getSessionState(sessionId, maxTokens);
3945
4071
  const dynamicContextChanged = this.getDynamicContextChanged(sessionId);
3946
4072
  const debugDump = this.debugDumpStore.get(sessionId);
@@ -4302,6 +4428,25 @@ All file and git operations should use this directory.${commitHint}
4302
4428
  }
4303
4429
  };
4304
4430
 
4431
+ // src/server/session/provider-reconcile.ts
4432
+ function clearSessionProviderWhere(isDangling) {
4433
+ let cleared = 0;
4434
+ for (const session of listSessions()) {
4435
+ if (session.providerId && isDangling(session.providerId)) {
4436
+ updateSessionProvider(session.id, null, null);
4437
+ cleared++;
4438
+ }
4439
+ }
4440
+ return cleared;
4441
+ }
4442
+ function clearSessionsForDeletedProvider(providerId) {
4443
+ return clearSessionProviderWhere((pinned) => pinned === providerId);
4444
+ }
4445
+ function reconcileSessionProviders(configuredProviderIds) {
4446
+ const configured = new Set(configuredProviderIds);
4447
+ return clearSessionProviderWhere((pinned) => !configured.has(pinned));
4448
+ }
4449
+
4305
4450
  // src/server/routes/skills.ts
4306
4451
  import { Router as Router2 } from "express";
4307
4452
  import multer from "multer";
@@ -5954,10 +6099,11 @@ function createWorkspaceConfigRoutes(sessionManager) {
5954
6099
  if (mcpOverrides !== void 0) {
5955
6100
  const project = getProjectByWorkdir(workdir);
5956
6101
  if (project) {
6102
+ const overridesObj = Object.keys(mcpOverrides).length > 0 ? mcpOverrides : null;
5957
6103
  updateProject(project.id, {
5958
- mcpOverrides: Object.keys(mcpOverrides).length > 0 ? mcpOverrides : null
6104
+ mcpOverrides: overridesObj
5959
6105
  });
5960
- const disabledServers = Object.entries(mcpOverrides).filter(([, override]) => override.disabled).map(([name]) => name);
6106
+ const disabledServers = computeDisabledServersForProject(overridesObj);
5961
6107
  const allSessions = sessionManager.listSessions();
5962
6108
  for (const s of allSessions) {
5963
6109
  if (s.projectId === project.id) {
@@ -6957,7 +7103,7 @@ function detectWsl() {
6957
7103
  // src/server/index.ts
6958
7104
  var __dirname3 = dirname7(fileURLToPath6(import.meta.url));
6959
7105
  async function announceContextDrift(sessionManager, sessionIds) {
6960
- const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-WKEXQCTK.js");
7106
+ const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-RDBNQPPA.js");
6961
7107
  await injectContextDriftRemindersForSessions(sessionManager, sessionIds);
6962
7108
  }
6963
7109
  async function createServerHandle(config3) {
@@ -6981,6 +7127,10 @@ async function createServerHandle(config3) {
6981
7127
  }
6982
7128
  config3.providers = providerAdapters.resolveProviders(config3.providers ?? []);
6983
7129
  const providerManager = createProviderManager(config3, { adapters: providerAdapters });
7130
+ const repairedSessions = reconcileSessionProviders(providerManager.getProviders().map((p) => p.id));
7131
+ if (repairedSessions > 0) {
7132
+ logger.warn("Cleared unknown provider from sessions", { sessions: repairedSessions });
7133
+ }
6984
7134
  const sessionManager = new SessionManager(providerManager);
6985
7135
  devServerManager.setSessionManager(sessionManager);
6986
7136
  const useMock = process.env["OPENFOX_MOCK_LLM"] === "true";
@@ -7046,6 +7196,10 @@ async function createServerHandle(config3) {
7046
7196
  }
7047
7197
  });
7048
7198
  setMcpManagerForTools(mcpManager);
7199
+ const { setGlobalMcpServersProvider } = await import("./session-overrides-ANQBKV74.js");
7200
+ setGlobalMcpServersProvider(
7201
+ () => mcpManager.getAllServers().map((s) => ({ name: s.name, disabled: s.config.disabled }))
7202
+ );
7049
7203
  setMcpConfigMode(config3.mode ?? "production");
7050
7204
  setMcpConfigPath(config3.globalConfigPath);
7051
7205
  setMcpOAuthStoreMode(config3.mode ?? "production");
@@ -7064,7 +7218,7 @@ async function createServerHandle(config3) {
7064
7218
  toolRegistry = createToolRegistry();
7065
7219
  logger.info("MCP tools registered", { count: mcpTools.length });
7066
7220
  }
7067
- const { signalMcpReady } = await import("./server-3UVLECD5.js");
7221
+ const { signalMcpReady } = await import("./server-ZAPAB3FS.js");
7068
7222
  signalMcpReady();
7069
7223
  });
7070
7224
  const app = express();
@@ -7279,9 +7433,9 @@ async function createServerHandle(config3) {
7279
7433
  const sessionFavoriteRouter = express.Router();
7280
7434
  registerSessionFavoriteRoute(sessionFavoriteRouter, sessionManager);
7281
7435
  app.use("/api", sessionFavoriteRouter);
7282
- const { createTasksService } = await import("./service-XIUNS5XV.js");
7283
- const { registerTaskRoutes } = await import("./tasks-3JJWJJ3X.js");
7284
- const { setTasksService } = await import("./tools-WWIWD3O7.js");
7436
+ const { createTasksService } = await import("./service-NKLQH647.js");
7437
+ const { registerTaskRoutes } = await import("./tasks-GPM3JAE6.js");
7438
+ const { setTasksService } = await import("./tools-EJOABHVO.js");
7285
7439
  const tasksService = createTasksService({
7286
7440
  sessionManager,
7287
7441
  config: config3,
@@ -7313,7 +7467,7 @@ async function createServerHandle(config3) {
7313
7467
  }
7314
7468
  try {
7315
7469
  await checkoutBranch(project.workdir, branch);
7316
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7470
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-GLYACE5R.js");
7317
7471
  const allSessions = sessionManager.listSessions();
7318
7472
  for (const s of allSessions) {
7319
7473
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -7349,7 +7503,7 @@ async function createServerHandle(config3) {
7349
7503
  );
7350
7504
  }
7351
7505
  await createBranch(project.workdir, name, sb);
7352
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7506
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-GLYACE5R.js");
7353
7507
  const allSessions = sessionManager.listSessions();
7354
7508
  for (const s of allSessions) {
7355
7509
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -7381,7 +7535,7 @@ async function createServerHandle(config3) {
7381
7535
  if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
7382
7536
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
7383
7537
  const { checkoutBranch, validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
7384
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7538
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-GLYACE5R.js");
7385
7539
  try {
7386
7540
  await validateRef2(effectiveWorkdir, branch);
7387
7541
  await checkoutBranch(effectiveWorkdir, branch);
@@ -7424,7 +7578,7 @@ All file and git operations should use this branch.
7424
7578
  if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
7425
7579
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
7426
7580
  const { validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
7427
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7581
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-GLYACE5R.js");
7428
7582
  try {
7429
7583
  await validateRef2(effectiveWorkdir, name);
7430
7584
  if (sourceBranch) {
@@ -7479,8 +7633,8 @@ All file and git operations should use this branch.
7479
7633
  res.json({ workspaces: workspacesList });
7480
7634
  });
7481
7635
  app.get("/api/sessions", async (req, res) => {
7482
- const { getRecentUserPromptsForSession } = await import("./events-3WSNI7XC.js");
7483
- const { getPendingConfirmationsBySession: getPendingConfirmationsBySession2 } = await import("./path-security-5CFMMULR.js");
7636
+ const { getRecentUserPromptsForSession } = await import("./events-YTYYT3PR.js");
7637
+ const { getPendingConfirmationsBySession: getPendingConfirmationsBySession2 } = await import("./path-security-EC4Z2ZZG.js");
7484
7638
  const projectId = req.query["projectId"];
7485
7639
  const rawLimit = req.query["limit"];
7486
7640
  const offset = parseInt(req.query["offset"]) || 0;
@@ -7516,31 +7670,8 @@ All file and git operations should use this branch.
7516
7670
  app.get("/api/sessions/home", (_req, res) => {
7517
7671
  res.json({ sessions: sessionManager.listHomeSessions() });
7518
7672
  });
7519
- app.post("/api/sessions", async (req, res) => {
7520
- const { projectId, title } = req.body;
7521
- if (!projectId) {
7522
- return res.status(400).json({ error: "projectId is required" });
7523
- }
7524
- const project = sessionManager.getProject(projectId);
7525
- if (!project) {
7526
- return res.status(404).json({ error: "Project not found" });
7527
- }
7528
- const { providerId, model } = parseDefaultModelSelection(config3.defaultModelSelection);
7529
- const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
7530
- try {
7531
- let disabledServers = [];
7532
- if (project.mcpOverrides) {
7533
- disabledServers = Object.entries(project.mcpOverrides).filter(([, override]) => override.disabled).map(([name]) => name);
7534
- } else {
7535
- disabledServers = mcpManager.getAllServers().filter((s) => s.config.disabled).map((s) => s.name);
7536
- }
7537
- if (disabledServers.length > 0) {
7538
- const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-Y5B4XQPU.js");
7539
- setSessionDisabledServers2(session.id, disabledServers);
7540
- }
7541
- } catch {
7542
- }
7543
- wssExports.broadcastForProject(projectId, session.id, {
7673
+ function buildSessionCreatedMessage(session) {
7674
+ return {
7544
7675
  type: "session.created",
7545
7676
  sessionId: session.id,
7546
7677
  payload: {
@@ -7562,7 +7693,20 @@ All file and git operations should use this branch.
7562
7693
  messageCount: session.messageCount ?? session.messages.length
7563
7694
  }
7564
7695
  }
7565
- });
7696
+ };
7697
+ }
7698
+ app.post("/api/sessions", async (req, res) => {
7699
+ const { projectId, title } = req.body;
7700
+ if (!projectId) {
7701
+ return res.status(400).json({ error: "projectId is required" });
7702
+ }
7703
+ const project = sessionManager.getProject(projectId);
7704
+ if (!project) {
7705
+ return res.status(404).json({ error: "Project not found" });
7706
+ }
7707
+ const { providerId, model } = parseDefaultModelSelection(config3.defaultModelSelection);
7708
+ const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
7709
+ wssExports.broadcastForProject(projectId, session.id, buildSessionCreatedMessage(session));
7566
7710
  res.status(201).json({ session: toClientSession(session) });
7567
7711
  });
7568
7712
  app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
@@ -7608,10 +7752,10 @@ All file and git operations should use this branch.
7608
7752
  }
7609
7753
  });
7610
7754
  app.get("/api/sessions/:id", async (req, res) => {
7611
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-3WSNI7XC.js");
7612
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
7613
- const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-WWIWD3O7.js");
7614
- const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7755
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-YTYYT3PR.js");
7756
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-3MMOPS4W.js");
7757
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-EJOABHVO.js");
7758
+ const { getMaxVisibleItems } = await import("./settings-WH6BVQCP.js");
7615
7759
  const session = sessionManager.getSession(req.params.id);
7616
7760
  if (!session) {
7617
7761
  return res.status(404).json({ error: "Session not found" });
@@ -7639,9 +7783,9 @@ All file and git operations should use this branch.
7639
7783
  });
7640
7784
  app.get("/api/sessions/:id/status", async (req, res) => {
7641
7785
  const { projectSessionStatus: projectSessionStatus2 } = await import("./session-status-UFO5IFI7.js");
7642
- const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-WWIWD3O7.js");
7643
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-3WSNI7XC.js");
7644
- const { foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
7786
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-EJOABHVO.js");
7787
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-YTYYT3PR.js");
7788
+ const { foldPendingConfirmations } = await import("./folding-3MMOPS4W.js");
7645
7789
  const sessionId = req.params["id"];
7646
7790
  if (!sessionId) {
7647
7791
  return res.status(400).json({ error: "Session id is required" });
@@ -7671,8 +7815,8 @@ All file and git operations should use this branch.
7671
7815
  if (!session) {
7672
7816
  return res.status(404).json({ error: "Session not found" });
7673
7817
  }
7674
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
7675
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
7818
+ const { stopSessionExecution } = await import("./chat-handler-SYU4HJMI.js");
7819
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-EJOABHVO.js");
7676
7820
  sessionManager.clearMessageQueue(sessionId);
7677
7821
  stopSessionExecution(sessionId, sessionManager);
7678
7822
  abortSession(sessionId);
@@ -7701,9 +7845,9 @@ All file and git operations should use this branch.
7701
7845
  res.json({ success: true });
7702
7846
  });
7703
7847
  app.post("/api/sessions/:id/provider", async (req, res) => {
7704
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7705
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7706
- const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7848
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-YTYYT3PR.js");
7849
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-3MMOPS4W.js");
7850
+ const { getMaxVisibleItems } = await import("./settings-WH6BVQCP.js");
7707
7851
  const sessionId = req.params.id;
7708
7852
  const session = sessionManager.getSession(sessionId);
7709
7853
  if (!session) {
@@ -7713,10 +7857,11 @@ All file and git operations should use this branch.
7713
7857
  if (!providerId) {
7714
7858
  return res.status(400).json({ error: "providerId is required" });
7715
7859
  }
7716
- if (reasoningEffort !== void 0 && reasoningEffort !== null && !isReasoningEffortValue(reasoningEffort)) {
7860
+ const provider = providerManager.getProviders().find((p) => p.id === providerId);
7861
+ const targetModel = provider?.models.find((m) => m.id === model);
7862
+ if (reasoningEffort !== void 0 && reasoningEffort !== null && !isReasoningEffortValidForModel(reasoningEffort, targetModel)) {
7717
7863
  return res.status(400).json({ error: `Unsupported reasoningEffort: ${reasoningEffort}` });
7718
7864
  }
7719
- const provider = providerManager.getProviders().find((p) => p.id === providerId);
7720
7865
  const resolvedModel = model ?? provider?.models?.[0]?.id ?? "auto";
7721
7866
  sessionManager.setSessionProvider(sessionId, providerId, resolvedModel, true, reasoningEffort);
7722
7867
  sessionManager.setSessionProviderActive(sessionId, true);
@@ -7731,9 +7876,9 @@ All file and git operations should use this branch.
7731
7876
  res.json({ session: toClientSession(updatedSession), messages, hiddenCount, contextState });
7732
7877
  });
7733
7878
  app.delete("/api/sessions/:id/provider", async (req, res) => {
7734
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7735
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7736
- const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7879
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-YTYYT3PR.js");
7880
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-3MMOPS4W.js");
7881
+ const { getMaxVisibleItems } = await import("./settings-WH6BVQCP.js");
7737
7882
  const sessionId = req.params.id;
7738
7883
  const session = sessionManager.getSession(sessionId);
7739
7884
  if (!session) {
@@ -7757,7 +7902,9 @@ All file and git operations should use this branch.
7757
7902
  return res.status(404).json({ error: "Session not found" });
7758
7903
  }
7759
7904
  const { effort } = req.body;
7760
- if (!effort || !isReasoningEffortValue(effort)) {
7905
+ const sessionModel = session.providerModel;
7906
+ const targetModel = providerManager.getProviders().flatMap((p) => p.models).find((m) => m.id === sessionModel);
7907
+ if (!effort || !isReasoningEffortValidForModel(effort, targetModel)) {
7761
7908
  return res.status(400).json({ error: `Unsupported reasoningEffort: ${effort}` });
7762
7909
  }
7763
7910
  const updated = sessionManager.setSessionPinnedEffort(sessionId, effort);
@@ -7863,9 +8010,9 @@ All file and git operations should use this branch.
7863
8010
  res.json({ success: true });
7864
8011
  });
7865
8012
  app.put("/api/sessions/:id/mode", async (req, res) => {
7866
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7867
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7868
- const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
8013
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-YTYYT3PR.js");
8014
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-3MMOPS4W.js");
8015
+ const { getMaxVisibleItems } = await import("./settings-WH6BVQCP.js");
7869
8016
  const sessionId = req.params.id;
7870
8017
  const session = sessionManager.getSession(sessionId);
7871
8018
  if (!session) {
@@ -7925,7 +8072,7 @@ All file and git operations should use this branch.
7925
8072
  setSessionDisabledServers(sessionId, disabledServers);
7926
8073
  const messages = session.messages ?? [];
7927
8074
  if (messages.length === 0) {
7928
- const { applyDynamicContext } = await import("./dynamic-context-WKEXQCTK.js");
8075
+ const { applyDynamicContext } = await import("./dynamic-context-RDBNQPPA.js");
7929
8076
  const modelName = session.providerModel ?? providerManager.getCurrentModel();
7930
8077
  await applyDynamicContext(sessionManager, sessionId, modelName);
7931
8078
  } else {
@@ -7959,7 +8106,7 @@ All file and git operations should use this branch.
7959
8106
  if (alwaysAllow !== void 0 && typeof alwaysAllow !== "boolean") {
7960
8107
  return res.status(400).json({ error: "alwaysAllow must be a boolean if provided" });
7961
8108
  }
7962
- const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-WWIWD3O7.js");
8109
+ const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-EJOABHVO.js");
7963
8110
  const pendingSessionId = getConfirmationSessionId(callId);
7964
8111
  if (!pendingSessionId) {
7965
8112
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -7971,11 +8118,11 @@ All file and git operations should use this branch.
7971
8118
  if (!result.found) {
7972
8119
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
7973
8120
  }
7974
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-3WSNI7XC.js");
7975
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
8121
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-YTYYT3PR.js");
8122
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-3MMOPS4W.js");
7976
8123
  const { createSessionStateMessage } = await import("./protocol-XO4ZROAU.js");
7977
- const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-WWIWD3O7.js");
7978
- const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
8124
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-EJOABHVO.js");
8125
+ const { getMaxVisibleItems } = await import("./settings-WH6BVQCP.js");
7979
8126
  const eventStore = getEventStore2();
7980
8127
  const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
7981
8128
  const events = combineEvents(sessionId, snapshot, eventsSinceSnapshot);
@@ -8012,7 +8159,7 @@ All file and git operations should use this branch.
8012
8159
  if (!skip && typeof answer !== "string") {
8013
8160
  return res.status(400).json({ error: "answer is required when not skipping" });
8014
8161
  }
8015
- const { provideAnswer: provideAnswer2 } = await import("./tools-WWIWD3O7.js");
8162
+ const { provideAnswer: provideAnswer2 } = await import("./tools-EJOABHVO.js");
8016
8163
  const found = provideAnswer2(callId, answer ?? "", skip ?? false);
8017
8164
  if (!found) {
8018
8165
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -8045,7 +8192,7 @@ All file and git operations should use this branch.
8045
8192
  if (!session) {
8046
8193
  return res.status(404).json({ error: "Session not found" });
8047
8194
  }
8048
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
8195
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-WH6BVQCP.js");
8049
8196
  if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
8050
8197
  return res.json({ success: false, reason: "disabled" });
8051
8198
  }
@@ -8078,7 +8225,7 @@ All file and git operations should use this branch.
8078
8225
  backend: activeProvider?.backend ?? llmClient.getBackend(),
8079
8226
  model: llmClient.getModel()
8080
8227
  };
8081
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-OT66EDXO.js");
8228
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-6QGQ55NT.js");
8082
8229
  runAgentTurn(
8083
8230
  {
8084
8231
  sessionManager,
@@ -8116,15 +8263,15 @@ All file and git operations should use this branch.
8116
8263
  if (!session) {
8117
8264
  return res.status(404).json({ error: "Session not found" });
8118
8265
  }
8119
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
8120
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
8266
+ const { stopSessionExecution } = await import("./chat-handler-SYU4HJMI.js");
8267
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-EJOABHVO.js");
8121
8268
  const queuedMessages = sessionManager.getQueueState(sessionId);
8122
8269
  sessionManager.clearMessageQueue(sessionId);
8123
8270
  stopSessionExecution(sessionId, sessionManager);
8124
8271
  abortSession(sessionId);
8125
8272
  cancelQuestionsForSession(sessionId, "Session stopped by user");
8126
8273
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
8127
- const eventStore = (await import("./events-3WSNI7XC.js")).getEventStore();
8274
+ const eventStore = (await import("./events-YTYYT3PR.js")).getEventStore();
8128
8275
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
8129
8276
  res.json({ success: true, queuedMessages });
8130
8277
  });
@@ -8138,7 +8285,7 @@ All file and git operations should use this branch.
8138
8285
  if (typeof messageIndex !== "number" || messageIndex < 0) {
8139
8286
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
8140
8287
  }
8141
- const { truncateSessionMessages } = await import("./events-3WSNI7XC.js");
8288
+ const { truncateSessionMessages } = await import("./events-YTYYT3PR.js");
8142
8289
  truncateSessionMessages(sessionId, messageIndex);
8143
8290
  res.json({ success: true });
8144
8291
  });
@@ -8158,8 +8305,8 @@ All file and git operations should use this branch.
8158
8305
  if (attachments !== void 0 && !Array.isArray(attachments)) {
8159
8306
  return res.status(400).json({ error: "attachments must be an array if provided" });
8160
8307
  }
8161
- const { getEventStore: getEventStore2 } = await import("./events-3WSNI7XC.js");
8162
- const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
8308
+ const { getEventStore: getEventStore2 } = await import("./events-YTYYT3PR.js");
8309
+ const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-3MMOPS4W.js");
8163
8310
  const eventStore = getEventStore2();
8164
8311
  const events = eventStore.getEvents(sessionId);
8165
8312
  const { messages } = buildMessagesFromStoredEvents2(events);
@@ -8171,7 +8318,7 @@ All file and git operations should use this branch.
8171
8318
  if (msg.role !== "user" || msg.isSystemGenerated) {
8172
8319
  return res.status(400).json({ error: "Can only replay user messages" });
8173
8320
  }
8174
- const { truncateSessionMessages } = await import("./events-3WSNI7XC.js");
8321
+ const { truncateSessionMessages } = await import("./events-YTYYT3PR.js");
8175
8322
  truncateSessionMessages(sessionId, msgIndex - 1);
8176
8323
  sessionManager.queueMessage(
8177
8324
  sessionId,
@@ -8206,6 +8353,43 @@ All file and git operations should use this branch.
8206
8353
  return res.status(500).json({ error: message });
8207
8354
  }
8208
8355
  });
8356
+ app.get("/api/sessions/:id/export", async (req, res) => {
8357
+ const sessionId = req.params.id;
8358
+ const session = sessionManager.getSession(sessionId);
8359
+ if (!session) {
8360
+ return res.status(404).json({ error: "Session not found" });
8361
+ }
8362
+ try {
8363
+ const { buildSessionExport } = await import("./export-import-GHRCOQHF.js");
8364
+ const payload = buildSessionExport(sessionManager, sessionId);
8365
+ const filename = `${(payload.session.title ?? "session").replace(/[^a-zA-Z0-9-_]/g, "_")}.openfox-session.json`;
8366
+ res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
8367
+ return res.json(payload);
8368
+ } catch (err) {
8369
+ const message = err instanceof Error ? err.message : String(err);
8370
+ return res.status(500).json({ error: message });
8371
+ }
8372
+ });
8373
+ app.post("/api/sessions/import", async (req, res) => {
8374
+ const { projectId, payload } = req.body;
8375
+ if (typeof projectId !== "string" || !projectId) {
8376
+ return res.status(400).json({ error: "projectId is required" });
8377
+ }
8378
+ if (payload === void 0 || payload === null) {
8379
+ return res.status(400).json({ error: "payload is required" });
8380
+ }
8381
+ try {
8382
+ const newSession = await sessionManager.importSession(projectId, payload);
8383
+ wssExports.broadcastForProject(projectId, newSession.id, buildSessionCreatedMessage(newSession));
8384
+ return res.status(201).json({ session: toClientSession(newSession) });
8385
+ } catch (err) {
8386
+ const message = err instanceof Error ? err.message : String(err);
8387
+ if (message.includes("Project not found")) {
8388
+ return res.status(404).json({ error: message });
8389
+ }
8390
+ return res.status(400).json({ error: message });
8391
+ }
8392
+ });
8209
8393
  app.post("/api/sessions/:id/chat", async (req, res) => {
8210
8394
  const sessionId = req.params.id;
8211
8395
  const session = sessionManager.getSession(sessionId);
@@ -8233,7 +8417,7 @@ All file and git operations should use this branch.
8233
8417
  res.json({ accepted: true });
8234
8418
  });
8235
8419
  app.get("/api/settings", async (req, res) => {
8236
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
8420
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-WH6BVQCP.js");
8237
8421
  const keysParam = req.query["keys"];
8238
8422
  if (!keysParam) {
8239
8423
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -8246,19 +8430,19 @@ All file and git operations should use this branch.
8246
8430
  res.json(result);
8247
8431
  });
8248
8432
  app.get("/api/settings/:key", async (req, res) => {
8249
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
8433
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-WH6BVQCP.js");
8250
8434
  const key = req.params.key;
8251
8435
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
8252
8436
  res.json({ key, value });
8253
8437
  });
8254
8438
  app.get("/api/settings/:key", async (req, res) => {
8255
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
8439
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-WH6BVQCP.js");
8256
8440
  const key = req.params.key;
8257
8441
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
8258
8442
  res.json({ key, value });
8259
8443
  });
8260
8444
  app.put("/api/settings/:key", async (req, res) => {
8261
- const { setSetting: setSetting2 } = await import("./settings-ZJPM6PQV.js");
8445
+ const { setSetting: setSetting2 } = await import("./settings-WH6BVQCP.js");
8262
8446
  const key = req.params.key;
8263
8447
  const { value } = req.body;
8264
8448
  if (value === void 0) {
@@ -8285,7 +8469,7 @@ All file and git operations should use this branch.
8285
8469
  }
8286
8470
  });
8287
8471
  app.get("/api/tools/shells", async (_req, res) => {
8288
- const { listAvailableShells } = await import("./platform-XPMZKAUB.js");
8472
+ const { listAvailableShells } = await import("./platform-KPKYBU54.js");
8289
8473
  res.json({ shells: listAvailableShells() });
8290
8474
  });
8291
8475
  app.get("/api/config", async (_req, res) => {
@@ -8323,7 +8507,7 @@ All file and git operations should use this branch.
8323
8507
  defaultModelSelection: config3.defaultModelSelection,
8324
8508
  visionFallback,
8325
8509
  platform: platformInfo,
8326
- locale: (await import("./settings-ZJPM6PQV.js")).getSetting("display.locale") ?? "automatic"
8510
+ locale: (await import("./settings-WH6BVQCP.js")).getSetting("display.locale") ?? "automatic"
8327
8511
  });
8328
8512
  });
8329
8513
  app.post("/api/model/refresh", async (_req, res) => {
@@ -8379,7 +8563,7 @@ All file and git operations should use this branch.
8379
8563
  }));
8380
8564
  }
8381
8565
  app.post("/api/proxy/test", async (_req, res) => {
8382
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
8566
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-WH6BVQCP.js");
8383
8567
  const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
8384
8568
  if (!proxyUrl) {
8385
8569
  return res.status(400).json({ success: false, error: "No proxy URL configured" });
@@ -8471,7 +8655,7 @@ All file and git operations should use this branch.
8471
8655
  }
8472
8656
  });
8473
8657
  app.post("/api/proxy/test", async (_req, res) => {
8474
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
8658
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-WH6BVQCP.js");
8475
8659
  const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
8476
8660
  if (!proxyUrl) {
8477
8661
  return res.status(400).json({ success: false, error: "No proxy URL configured" });
@@ -8498,9 +8682,9 @@ All file and git operations should use this branch.
8498
8682
  const backend = req.query["backend"];
8499
8683
  if (!url) return res.status(400).json({ error: "url is required" });
8500
8684
  try {
8501
- const { fetchModelsWithContext } = await import("./provider-manager-2KKZ37XJ.js");
8685
+ const { fetchModelsWithContext } = await import("./provider-manager-Y53SVVQ3.js");
8502
8686
  const { getModelProfile: getModelProfile2 } = await import("./profiles-EBCVFYG7.js");
8503
- const { getCatalogEntry } = await import("./model-catalog-2PCKTYGW.js");
8687
+ const { getCatalogEntry } = await import("./model-catalog-Y5MA5OZP.js");
8504
8688
  const models = await fetchModelsWithContext(
8505
8689
  url,
8506
8690
  apiKey,
@@ -8538,7 +8722,7 @@ All file and git operations should use this branch.
8538
8722
  if (!url) return res.status(400).json({ error: "url is required" });
8539
8723
  if (!models?.length) return res.status(400).json({ error: "models is required" });
8540
8724
  try {
8541
- const { autoConfig } = await import("./auto-config-5VSNLVNI.js");
8725
+ const { autoConfig } = await import("./auto-config-2A7Y2WOK.js");
8542
8726
  const result = await autoConfig({
8543
8727
  url,
8544
8728
  ...apiKey ? { apiKey } : {},
@@ -8571,9 +8755,9 @@ All file and git operations should use this branch.
8571
8755
  return res.json({ success: true, message: { content: response2.content }, raw: response2 });
8572
8756
  }
8573
8757
  const { getModelProfile: getModelProfile2 } = await import("./profiles-EBCVFYG7.js");
8574
- const { getBackendCapabilities } = await import("./backend-NDBY3DAQ.js");
8575
- const { buildNonStreamingCreateParams } = await import("./client-pure-FLKP6PTI.js");
8576
- const { OpenAIHttpClient } = await import("./http-client-A445WYZU.js");
8758
+ const { getBackendCapabilities } = await import("./backend-24FTDSHF.js");
8759
+ const { buildNonStreamingCreateParams } = await import("./client-pure-YZ4IGCU4.js");
8760
+ const { OpenAIHttpClient } = await import("./http-client-C6UYWVWZ.js");
8577
8761
  const { ensureVersionPrefix } = await import("./url-utils-C5BM7NF7.js");
8578
8762
  const profile = getModelProfile2(model);
8579
8763
  const capabilities = getBackendCapabilities(backend || "unknown");
@@ -8846,6 +9030,12 @@ All file and git operations should use this branch.
8846
9030
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
8847
9031
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
8848
9032
  config3.defaultModelSelection = updatedConfig.defaultModelSelection;
9033
+ const clearedSessions = clearSessionsForDeletedProvider(id);
9034
+ if (clearedSessions > 0) {
9035
+ logger.info("Cleared provider from sessions of deleted provider", { providerId: id, sessions: clearedSessions });
9036
+ }
9037
+ const { pruneFavoriteModels } = await import("./settings-WH6BVQCP.js");
9038
+ pruneFavoriteModels(updatedConfig.providers);
8849
9039
  res.json({ success: true });
8850
9040
  });
8851
9041
  app.patch("/api/providers/:id", async (req, res) => {
@@ -8907,6 +9097,8 @@ All file and git operations should use this branch.
8907
9097
  await saveGlobalConfig(config3.mode ?? "production", updatedConfig, config3.globalConfigPath);
8908
9098
  providerManager.setProviders(updatedConfig.providers, updatedConfig.defaultModelSelection ?? void 0);
8909
9099
  config3.defaultModelSelection = updatedConfig.defaultModelSelection;
9100
+ const { pruneFavoriteModels } = await import("./settings-WH6BVQCP.js");
9101
+ pruneFavoriteModels(updatedConfig.providers);
8910
9102
  res.json({ success: true, provider: updatedConfig.providers.find((p) => p.id === id) });
8911
9103
  } catch (error) {
8912
9104
  res.status(500).json({ error: error instanceof Error ? error.message : "Failed to update provider" });
@@ -8920,9 +9112,6 @@ All file and git operations should use this branch.
8920
9112
  app.put("/api/providers/:id/models/:modelId/settings", async (req, res) => {
8921
9113
  const { id, modelId } = req.params;
8922
9114
  const { thinkingLevel, thinkingEnabled } = req.body;
8923
- if (thinkingLevel !== void 0 && !isReasoningEffortValue(thinkingLevel)) {
8924
- return res.status(400).json({ error: `Invalid reasoning effort '${thinkingLevel}'` });
8925
- }
8926
9115
  if (thinkingEnabled !== void 0 && typeof thinkingEnabled !== "boolean") {
8927
9116
  return res.status(400).json({ error: "thinkingEnabled must be a boolean" });
8928
9117
  }
@@ -8934,9 +9123,13 @@ All file and git operations should use this branch.
8934
9123
  return res.status(404).json({ error: "Provider not found" });
8935
9124
  }
8936
9125
  const models = provider.models ?? [];
8937
- if (!models.some((m) => m.id === modelId)) {
9126
+ const targetModel = models.find((m) => m.id === modelId);
9127
+ if (!targetModel) {
8938
9128
  return res.status(404).json({ error: "Model not found" });
8939
9129
  }
9130
+ if (thinkingLevel !== void 0 && !isReasoningEffortValidForModel(thinkingLevel, targetModel)) {
9131
+ return res.status(400).json({ error: `Invalid reasoning effort '${thinkingLevel}'` });
9132
+ }
8940
9133
  const updatedModels = models.map(
8941
9134
  (m) => m.id === modelId ? {
8942
9135
  ...m,
@@ -8989,8 +9182,8 @@ All file and git operations should use this branch.
8989
9182
  });
8990
9183
  });
8991
9184
  async function rebuildMcpTools() {
8992
- const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-FJAFLDZA.js");
8993
- const { setMcpTools: setMcpTools2 } = await import("./tools-WWIWD3O7.js");
9185
+ const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-ZY4FC4C4.js");
9186
+ const { setMcpTools: setMcpTools2 } = await import("./tools-EJOABHVO.js");
8994
9187
  const mcpTools = createMcpTools2(mcpManager);
8995
9188
  setMcpTools2(mcpTools);
8996
9189
  toolRegistry = createToolRegistry();
@@ -9420,13 +9613,13 @@ All file and git operations should use this branch.
9420
9613
  })
9421
9614
  );
9422
9615
  app.get("/api/sessions/:id/background-processes", async (req, res) => {
9423
- const { getSessionProcesses } = await import("./manager-ZACEUL5P.js");
9616
+ const { getSessionProcesses } = await import("./manager-FSPRJCYT.js");
9424
9617
  const sessionId = req.params.id;
9425
9618
  const processes = getSessionProcesses(sessionId);
9426
9619
  res.json({ processes });
9427
9620
  });
9428
9621
  app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
9429
- const { stopProcess } = await import("./manager-ZACEUL5P.js");
9622
+ const { stopProcess } = await import("./manager-FSPRJCYT.js");
9430
9623
  const sessionId = req.params.id;
9431
9624
  const processId = req.params.processId;
9432
9625
  const session = sessionManager.getSession(sessionId);
@@ -9566,7 +9759,7 @@ All file and git operations should use this branch.
9566
9759
  );
9567
9760
  const wss = wssExports.wss;
9568
9761
  deferTasksBroadcast = (projectId, payload) => wssExports.broadcastForProject(projectId, "", { type: "tasks.update", payload });
9569
- const { launchWorkflowRun, abortRunnerRun } = await import("./launch-FJ65HRV4.js");
9762
+ const { launchWorkflowRun, abortRunnerRun } = await import("./launch-YZ46OEFP.js");
9570
9763
  deferTasksLaunchWorkflow = (sessionId, launch) => {
9571
9764
  const effective = sessionManager.resolveEffectiveProviderModel(sessionId);
9572
9765
  let llmClient = getLLMClient();
@@ -9611,7 +9804,7 @@ All file and git operations should use this branch.
9611
9804
  const state = sessionManager.getContextState(sessionId);
9612
9805
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
9613
9806
  });
9614
- const { QueueProcessor } = await import("./processor-CHMHMMIE.js");
9807
+ const { QueueProcessor } = await import("./processor-B2RV7MVC.js");
9615
9808
  const queueProcessor = new QueueProcessor({
9616
9809
  sessionManager,
9617
9810
  providerManager,
@@ -9653,8 +9846,8 @@ All file and git operations should use this branch.
9653
9846
  launchWorkflow: (sessionId, launch) => deferTasksLaunchWorkflow(sessionId, launch),
9654
9847
  stopSession: (sessionId) => {
9655
9848
  void (async () => {
9656
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
9657
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
9849
+ const { stopSessionExecution } = await import("./chat-handler-SYU4HJMI.js");
9850
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-EJOABHVO.js");
9658
9851
  sessionManager.clearMessageQueue(sessionId);
9659
9852
  stopSessionExecution(sessionId, sessionManager);
9660
9853
  abortSession(sessionId);
@@ -9775,4 +9968,4 @@ export {
9775
9968
  createServerHandle,
9776
9969
  createServer
9777
9970
  };
9778
- //# sourceMappingURL=chunk-5IXCCMFU.js.map
9971
+ //# sourceMappingURL=chunk-QQQBNL7A.js.map