openfox 2.0.134 → 2.0.135

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 (43) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/CHANGELOG.md +18 -0
  3. package/dist/{chat-handler-YCZE2XEJ.js → chat-handler-WGDFMOOD.js} +9 -9
  4. package/dist/{chunk-YOPXAI2W.js → chunk-4R5GV7RW.js} +6 -6
  5. package/dist/{chunk-7HGBJFIJ.js → chunk-5H5NRWHA.js} +4 -4
  6. package/dist/{chunk-5IXCCMFU.js → chunk-BIZFY3QP.js} +197 -68
  7. package/dist/{chunk-J5HOUEPE.js → chunk-ESZQTFQP.js} +9 -9
  8. package/dist/{chunk-ZTBKMVV6.js → chunk-F2MOHHXB.js} +14 -1
  9. package/dist/{chunk-M4J2L4VH.js → chunk-GP3CLMPQ.js} +10 -10
  10. package/dist/{chunk-YLVOU7T7.js → chunk-I5ODJKYM.js} +2 -2
  11. package/dist/{chunk-MRE4OYKI.js → chunk-IAT2LBIX.js} +3 -3
  12. package/dist/{chunk-FAQDLL2X.js → chunk-NFEZATSN.js} +3 -3
  13. package/dist/{chunk-CSYOWFPU.js → chunk-QZOV4OVN.js} +26 -2
  14. package/dist/{chunk-QDARWVQ2.js → chunk-S67WIWUG.js} +2 -2
  15. package/dist/{chunk-BZND27IB.js → chunk-UKIUQAQZ.js} +2 -2
  16. package/dist/{chunk-QICVOQNX.js → chunk-VHLD6PCZ.js} +5 -5
  17. package/dist/chunk-WY3PWHWY.js +7 -0
  18. package/dist/cli/dev.js +1 -1
  19. package/dist/cli/index.js +1 -1
  20. package/dist/{compactor-PD6DQ4NY.js → compactor-454UEIEX.js} +4 -4
  21. package/dist/{dynamic-context-WKEXQCTK.js → dynamic-context-LKC6JYLQ.js} +4 -4
  22. package/dist/{events-3WSNI7XC.js → events-335XAKFK.js} +3 -3
  23. package/dist/export-import-3WMRLO4A.js +137 -0
  24. package/dist/{launch-FJ65HRV4.js → launch-GJ7EHQRI.js} +9 -9
  25. package/dist/{orchestrator-OT66EDXO.js → orchestrator-JGJWTRO5.js} +8 -8
  26. package/dist/package.json +1 -1
  27. package/dist/{path-security-5CFMMULR.js → path-security-4LROI7F4.js} +4 -4
  28. package/dist/{processor-CHMHMMIE.js → processor-MSQP63ML.js} +8 -8
  29. package/dist/{serve-HSDVY37K.js → serve-CW5C3CBZ.js} +14 -14
  30. package/dist/server/index.d.ts +15 -0
  31. package/dist/server/index.js +13 -13
  32. package/dist/{server-3UVLECD5.js → server-ZHEB7XS2.js} +12 -12
  33. package/dist/{session-overrides-Y5B4XQPU.js → session-overrides-LYW5PJ3R.js} +3 -3
  34. package/dist/{sessions-IGINPPBP.js → sessions-AOK3AGHY.js} +4 -2
  35. package/dist/{tools-WWIWD3O7.js → tools-E63MOJBO.js} +6 -6
  36. package/dist/{update-Q6SH7UP2.js → update-XVXNSSDK.js} +2 -2
  37. package/dist/web/assets/{index-Y300llHY.css → index-Bg_Z8i3F.css} +1 -1
  38. package/dist/web/assets/index-wTFCxQAw.js +313 -0
  39. package/dist/web/index.html +2 -2
  40. package/dist/web/sw.js +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-QTLYD2FF.js +0 -7
  43. package/dist/web/assets/index-C48qmBAI.js +0 -313
@@ -24,10 +24,10 @@ import {
24
24
  terminalManager,
25
25
  tokenFromPassword,
26
26
  verifyPassword
27
- } from "./chunk-M4J2L4VH.js";
27
+ } from "./chunk-GP3CLMPQ.js";
28
28
  import {
29
29
  TEMPLATE_VARIABLES
30
- } from "./chunk-7HGBJFIJ.js";
30
+ } from "./chunk-5H5NRWHA.js";
31
31
  import {
32
32
  createToolRegistry,
33
33
  devServerManager,
@@ -42,7 +42,7 @@ import {
42
42
  setMcpManagerForTools,
43
43
  setMcpTools,
44
44
  setNotifyMcpServersChanged
45
- } from "./chunk-J5HOUEPE.js";
45
+ } from "./chunk-ESZQTFQP.js";
46
46
  import {
47
47
  checkoutBranchFromSharedSource,
48
48
  deleteWorkspace,
@@ -92,7 +92,7 @@ import {
92
92
  import {
93
93
  getSessionDisabledServers,
94
94
  setSessionDisabledServers
95
- } from "./chunk-QDARWVQ2.js";
95
+ } from "./chunk-S67WIWUG.js";
96
96
  import {
97
97
  createMcpTools
98
98
  } from "./chunk-JE7LW7Y6.js";
@@ -128,7 +128,7 @@ import {
128
128
  import {
129
129
  getPendingConfirmationsBySession,
130
130
  providePathConfirmation
131
- } from "./chunk-YLVOU7T7.js";
131
+ } from "./chunk-I5ODJKYM.js";
132
132
  import {
133
133
  combineEventsWithSnapshot,
134
134
  emitAssistantMessageStart,
@@ -146,7 +146,7 @@ import {
146
146
  getEventStore,
147
147
  getSessionState,
148
148
  initEventStore
149
- } from "./chunk-CSYOWFPU.js";
149
+ } from "./chunk-QZOV4OVN.js";
150
150
  import {
151
151
  buildMessagesFromStoredEvents
152
152
  } from "./chunk-MEEUXRFL.js";
@@ -163,6 +163,7 @@ import {
163
163
  listSessions,
164
164
  listSessionsByProject,
165
165
  listSessionsLimited,
166
+ setSessionMessageCount,
166
167
  toggleFavorite,
167
168
  updateSessionBranch,
168
169
  updateSessionCachedPrompt,
@@ -175,7 +176,7 @@ import {
175
176
  updateSessionRunning,
176
177
  updateSessionWorkdir,
177
178
  updateWorkflowExecutionStatus
178
- } from "./chunk-ZTBKMVV6.js";
179
+ } from "./chunk-F2MOHHXB.js";
179
180
  import {
180
181
  agentExists,
181
182
  deleteAgent,
@@ -216,7 +217,7 @@ import {
216
217
  } from "./chunk-YNMP647F.js";
217
218
  import {
218
219
  VERSION
219
- } from "./chunk-QTLYD2FF.js";
220
+ } from "./chunk-WY3PWHWY.js";
220
221
  import {
221
222
  deleteProject,
222
223
  getProject,
@@ -3096,6 +3097,94 @@ var SessionManager = class {
3096
3097
  this.emit({ type: "session_updated", session: this.requireSession(newSession.id) });
3097
3098
  return this.requireSession(newSession.id);
3098
3099
  }
3100
+ /**
3101
+ * Import a session from an export document into a target project.
3102
+ *
3103
+ * The cached layout (system prompt, tools, hash) is restored verbatim so the
3104
+ * provider-side prefix cache stays valid, and the event history is replayed
3105
+ * as-is. Drift between the original environment's cached layout and the
3106
+ * target environment (system prompt, tools) is announced via injected
3107
+ * <system-reminder> messages, followed by an import marker reminder.
3108
+ *
3109
+ * @param projectId - Target project (the session is created there)
3110
+ * @param rawPayload - Exported session document (validated)
3111
+ * @returns The imported session
3112
+ * @throws Error for invalid payloads or unknown project
3113
+ */
3114
+ async importSession(projectId, rawPayload) {
3115
+ const { parseSessionExport, IMPORTED_SESSION_REMINDER, SESSION_EXPORT_VERSION } = await import("./export-import-3WMRLO4A.js");
3116
+ const { injectContextDriftReminders, getToolSetFingerprint } = await import("./dynamic-context-LKC6JYLQ.js");
3117
+ const { loadAllAgentsDefault: loadAllAgentsDefault2, resolveDefaultAgentId } = await import("./registry-BEIR7Y5G.js");
3118
+ const payload = parseSessionExport(rawPayload);
3119
+ if (payload.version !== SESSION_EXPORT_VERSION) {
3120
+ throw new Error(`Unsupported session export version: ${payload.version}`);
3121
+ }
3122
+ const project = getProject(projectId);
3123
+ if (!project) {
3124
+ throw new Error(`Project not found: ${projectId}`);
3125
+ }
3126
+ if (!payload.events.some((event) => event.type === "session.initialized")) {
3127
+ throw new Error("Invalid session export: missing session.initialized event");
3128
+ }
3129
+ const providers = this.providerManager.getProviders();
3130
+ const providerId = payload.session.providerId ?? null;
3131
+ const providerModel = payload.session.providerModel ?? null;
3132
+ let resolvedProviderId = null;
3133
+ let resolvedProviderModel = null;
3134
+ if (providerId && providers.some((p) => p.id === providerId)) {
3135
+ resolvedProviderId = providerId;
3136
+ resolvedProviderModel = providerModel;
3137
+ } else if (providerId && payload.source?.providerBackend && payload.source.providerUrl) {
3138
+ const normalizeUrl = (url) => url.replace(/\/+$/, "");
3139
+ const sourceBackend = payload.source.providerBackend;
3140
+ const sourceUrl = normalizeUrl(payload.source.providerUrl);
3141
+ const urlMatch = providers.find(
3142
+ (p) => p.backend === sourceBackend && p.url !== void 0 && normalizeUrl(p.url) === sourceUrl && providerModel !== null && p.models.some((m) => m.id === providerModel || m.apiModelId === providerModel)
3143
+ );
3144
+ if (urlMatch) {
3145
+ resolvedProviderId = urlMatch.id;
3146
+ resolvedProviderModel = providerModel;
3147
+ }
3148
+ }
3149
+ const session = createSession(
3150
+ projectId,
3151
+ project.workdir,
3152
+ payload.session.title,
3153
+ resolvedProviderId,
3154
+ resolvedProviderModel
3155
+ );
3156
+ const eventStore = getEventStore();
3157
+ eventStore.importEvents(session.id, payload.events);
3158
+ const agents = await loadAllAgentsDefault2(project.workdir);
3159
+ const restoredMode = getSessionState(session.id)?.mode ?? session.mode;
3160
+ if (!agents.some((agent) => agent.metadata.id === restoredMode)) {
3161
+ this.setMode(session.id, resolveDefaultAgentId(projectId));
3162
+ }
3163
+ if (payload.cachedLayout) {
3164
+ updateSessionCachedPrompt(
3165
+ session.id,
3166
+ payload.cachedLayout.systemPrompt,
3167
+ payload.cachedLayout.tools,
3168
+ payload.cachedLayout.hash,
3169
+ payload.cachedLayout.promptHash
3170
+ );
3171
+ this.setAnnouncedPromptHash(session.id, payload.cachedLayout.promptHash ?? payload.cachedLayout.hash);
3172
+ this.setAnnouncedToolFingerprint(session.id, getToolSetFingerprint(payload.cachedLayout.tools));
3173
+ this.markWarmedUp(session.id);
3174
+ }
3175
+ await injectContextDriftReminders(this, session.id);
3176
+ emitUserMessage(session.id, IMPORTED_SESSION_REMINDER, {
3177
+ isSystemGenerated: true,
3178
+ messageKind: "auto-prompt",
3179
+ metadata: { type: "session-import", name: "Session Imported", color: "#6b7280", kind: "reminder" }
3180
+ });
3181
+ const state = getSessionState(session.id);
3182
+ if (state) {
3183
+ setSessionMessageCount(session.id, state.messages.length);
3184
+ }
3185
+ this.emit({ type: "session_created", session: this.requireSession(session.id) });
3186
+ return this.requireSession(session.id);
3187
+ }
3099
3188
  /**
3100
3189
  * Get a session by ID. Returns null if not found.
3101
3190
  * Session state is derived from EventStore.
@@ -6957,7 +7046,7 @@ function detectWsl() {
6957
7046
  // src/server/index.ts
6958
7047
  var __dirname3 = dirname7(fileURLToPath6(import.meta.url));
6959
7048
  async function announceContextDrift(sessionManager, sessionIds) {
6960
- const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-WKEXQCTK.js");
7049
+ const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-LKC6JYLQ.js");
6961
7050
  await injectContextDriftRemindersForSessions(sessionManager, sessionIds);
6962
7051
  }
6963
7052
  async function createServerHandle(config3) {
@@ -7064,7 +7153,7 @@ async function createServerHandle(config3) {
7064
7153
  toolRegistry = createToolRegistry();
7065
7154
  logger.info("MCP tools registered", { count: mcpTools.length });
7066
7155
  }
7067
- const { signalMcpReady } = await import("./server-3UVLECD5.js");
7156
+ const { signalMcpReady } = await import("./server-ZHEB7XS2.js");
7068
7157
  signalMcpReady();
7069
7158
  });
7070
7159
  const app = express();
@@ -7281,7 +7370,7 @@ async function createServerHandle(config3) {
7281
7370
  app.use("/api", sessionFavoriteRouter);
7282
7371
  const { createTasksService } = await import("./service-XIUNS5XV.js");
7283
7372
  const { registerTaskRoutes } = await import("./tasks-3JJWJJ3X.js");
7284
- const { setTasksService } = await import("./tools-WWIWD3O7.js");
7373
+ const { setTasksService } = await import("./tools-E63MOJBO.js");
7285
7374
  const tasksService = createTasksService({
7286
7375
  sessionManager,
7287
7376
  config: config3,
@@ -7313,7 +7402,7 @@ async function createServerHandle(config3) {
7313
7402
  }
7314
7403
  try {
7315
7404
  await checkoutBranch(project.workdir, branch);
7316
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7405
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
7317
7406
  const allSessions = sessionManager.listSessions();
7318
7407
  for (const s of allSessions) {
7319
7408
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -7349,7 +7438,7 @@ async function createServerHandle(config3) {
7349
7438
  );
7350
7439
  }
7351
7440
  await createBranch(project.workdir, name, sb);
7352
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7441
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
7353
7442
  const allSessions = sessionManager.listSessions();
7354
7443
  for (const s of allSessions) {
7355
7444
  if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
@@ -7381,7 +7470,7 @@ async function createServerHandle(config3) {
7381
7470
  if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
7382
7471
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
7383
7472
  const { checkoutBranch, validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
7384
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7473
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
7385
7474
  try {
7386
7475
  await validateRef2(effectiveWorkdir, branch);
7387
7476
  await checkoutBranch(effectiveWorkdir, branch);
@@ -7424,7 +7513,7 @@ All file and git operations should use this branch.
7424
7513
  if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
7425
7514
  const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
7426
7515
  const { validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
7427
- const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-IGINPPBP.js");
7516
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
7428
7517
  try {
7429
7518
  await validateRef2(effectiveWorkdir, name);
7430
7519
  if (sourceBranch) {
@@ -7479,8 +7568,8 @@ All file and git operations should use this branch.
7479
7568
  res.json({ workspaces: workspacesList });
7480
7569
  });
7481
7570
  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");
7571
+ const { getRecentUserPromptsForSession } = await import("./events-335XAKFK.js");
7572
+ const { getPendingConfirmationsBySession: getPendingConfirmationsBySession2 } = await import("./path-security-4LROI7F4.js");
7484
7573
  const projectId = req.query["projectId"];
7485
7574
  const rawLimit = req.query["limit"];
7486
7575
  const offset = parseInt(req.query["offset"]) || 0;
@@ -7516,6 +7605,31 @@ All file and git operations should use this branch.
7516
7605
  app.get("/api/sessions/home", (_req, res) => {
7517
7606
  res.json({ sessions: sessionManager.listHomeSessions() });
7518
7607
  });
7608
+ function buildSessionCreatedMessage(session) {
7609
+ return {
7610
+ type: "session.created",
7611
+ sessionId: session.id,
7612
+ payload: {
7613
+ session: {
7614
+ id: session.id,
7615
+ projectId: session.projectId,
7616
+ title: session.metadata.title,
7617
+ workdir: session.workdir,
7618
+ workspace: session.workspace,
7619
+ mode: session.mode,
7620
+ phase: session.phase,
7621
+ isRunning: session.isRunning,
7622
+ providerId: session.providerId,
7623
+ providerModel: session.providerModel,
7624
+ createdAt: session.createdAt,
7625
+ updatedAt: session.updatedAt,
7626
+ criteriaCount: session.criteria.length,
7627
+ criteriaCompleted: session.criteria.filter((c) => c.status.type === "passed").length,
7628
+ messageCount: session.messageCount ?? session.messages.length
7629
+ }
7630
+ }
7631
+ };
7632
+ }
7519
7633
  app.post("/api/sessions", async (req, res) => {
7520
7634
  const { projectId, title } = req.body;
7521
7635
  if (!projectId) {
@@ -7535,34 +7649,12 @@ All file and git operations should use this branch.
7535
7649
  disabledServers = mcpManager.getAllServers().filter((s) => s.config.disabled).map((s) => s.name);
7536
7650
  }
7537
7651
  if (disabledServers.length > 0) {
7538
- const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-Y5B4XQPU.js");
7652
+ const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-LYW5PJ3R.js");
7539
7653
  setSessionDisabledServers2(session.id, disabledServers);
7540
7654
  }
7541
7655
  } catch {
7542
7656
  }
7543
- wssExports.broadcastForProject(projectId, session.id, {
7544
- type: "session.created",
7545
- sessionId: session.id,
7546
- payload: {
7547
- session: {
7548
- id: session.id,
7549
- projectId: session.projectId,
7550
- title: session.metadata.title,
7551
- workdir: session.workdir,
7552
- workspace: session.workspace,
7553
- mode: session.mode,
7554
- phase: session.phase,
7555
- isRunning: session.isRunning,
7556
- providerId: session.providerId,
7557
- providerModel: session.providerModel,
7558
- createdAt: session.createdAt,
7559
- updatedAt: session.updatedAt,
7560
- criteriaCount: session.criteria.length,
7561
- criteriaCompleted: session.criteria.filter((c) => c.status.type === "passed").length,
7562
- messageCount: session.messageCount ?? session.messages.length
7563
- }
7564
- }
7565
- });
7657
+ wssExports.broadcastForProject(projectId, session.id, buildSessionCreatedMessage(session));
7566
7658
  res.status(201).json({ session: toClientSession(session) });
7567
7659
  });
7568
7660
  app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
@@ -7608,9 +7700,9 @@ All file and git operations should use this branch.
7608
7700
  }
7609
7701
  });
7610
7702
  app.get("/api/sessions/:id", async (req, res) => {
7611
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-3WSNI7XC.js");
7703
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-335XAKFK.js");
7612
7704
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
7613
- const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-WWIWD3O7.js");
7705
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
7614
7706
  const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7615
7707
  const session = sessionManager.getSession(req.params.id);
7616
7708
  if (!session) {
@@ -7639,8 +7731,8 @@ All file and git operations should use this branch.
7639
7731
  });
7640
7732
  app.get("/api/sessions/:id/status", async (req, res) => {
7641
7733
  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");
7734
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
7735
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-335XAKFK.js");
7644
7736
  const { foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
7645
7737
  const sessionId = req.params["id"];
7646
7738
  if (!sessionId) {
@@ -7671,8 +7763,8 @@ All file and git operations should use this branch.
7671
7763
  if (!session) {
7672
7764
  return res.status(404).json({ error: "Session not found" });
7673
7765
  }
7674
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
7675
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
7766
+ const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
7767
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
7676
7768
  sessionManager.clearMessageQueue(sessionId);
7677
7769
  stopSessionExecution(sessionId, sessionManager);
7678
7770
  abortSession(sessionId);
@@ -7701,7 +7793,7 @@ All file and git operations should use this branch.
7701
7793
  res.json({ success: true });
7702
7794
  });
7703
7795
  app.post("/api/sessions/:id/provider", async (req, res) => {
7704
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7796
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
7705
7797
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7706
7798
  const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7707
7799
  const sessionId = req.params.id;
@@ -7731,7 +7823,7 @@ All file and git operations should use this branch.
7731
7823
  res.json({ session: toClientSession(updatedSession), messages, hiddenCount, contextState });
7732
7824
  });
7733
7825
  app.delete("/api/sessions/:id/provider", async (req, res) => {
7734
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7826
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
7735
7827
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7736
7828
  const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7737
7829
  const sessionId = req.params.id;
@@ -7863,7 +7955,7 @@ All file and git operations should use this branch.
7863
7955
  res.json({ success: true });
7864
7956
  });
7865
7957
  app.put("/api/sessions/:id/mode", async (req, res) => {
7866
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-3WSNI7XC.js");
7958
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
7867
7959
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
7868
7960
  const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7869
7961
  const sessionId = req.params.id;
@@ -7925,7 +8017,7 @@ All file and git operations should use this branch.
7925
8017
  setSessionDisabledServers(sessionId, disabledServers);
7926
8018
  const messages = session.messages ?? [];
7927
8019
  if (messages.length === 0) {
7928
- const { applyDynamicContext } = await import("./dynamic-context-WKEXQCTK.js");
8020
+ const { applyDynamicContext } = await import("./dynamic-context-LKC6JYLQ.js");
7929
8021
  const modelName = session.providerModel ?? providerManager.getCurrentModel();
7930
8022
  await applyDynamicContext(sessionManager, sessionId, modelName);
7931
8023
  } else {
@@ -7959,7 +8051,7 @@ All file and git operations should use this branch.
7959
8051
  if (alwaysAllow !== void 0 && typeof alwaysAllow !== "boolean") {
7960
8052
  return res.status(400).json({ error: "alwaysAllow must be a boolean if provided" });
7961
8053
  }
7962
- const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-WWIWD3O7.js");
8054
+ const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-E63MOJBO.js");
7963
8055
  const pendingSessionId = getConfirmationSessionId(callId);
7964
8056
  if (!pendingSessionId) {
7965
8057
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
@@ -7971,10 +8063,10 @@ All file and git operations should use this branch.
7971
8063
  if (!result.found) {
7972
8064
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
7973
8065
  }
7974
- const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-3WSNI7XC.js");
8066
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-335XAKFK.js");
7975
8067
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
7976
8068
  const { createSessionStateMessage } = await import("./protocol-XO4ZROAU.js");
7977
- const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-WWIWD3O7.js");
8069
+ const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
7978
8070
  const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
7979
8071
  const eventStore = getEventStore2();
7980
8072
  const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
@@ -8012,7 +8104,7 @@ All file and git operations should use this branch.
8012
8104
  if (!skip && typeof answer !== "string") {
8013
8105
  return res.status(400).json({ error: "answer is required when not skipping" });
8014
8106
  }
8015
- const { provideAnswer: provideAnswer2 } = await import("./tools-WWIWD3O7.js");
8107
+ const { provideAnswer: provideAnswer2 } = await import("./tools-E63MOJBO.js");
8016
8108
  const found = provideAnswer2(callId, answer ?? "", skip ?? false);
8017
8109
  if (!found) {
8018
8110
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -8078,7 +8170,7 @@ All file and git operations should use this branch.
8078
8170
  backend: activeProvider?.backend ?? llmClient.getBackend(),
8079
8171
  model: llmClient.getModel()
8080
8172
  };
8081
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-OT66EDXO.js");
8173
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-JGJWTRO5.js");
8082
8174
  runAgentTurn(
8083
8175
  {
8084
8176
  sessionManager,
@@ -8116,15 +8208,15 @@ All file and git operations should use this branch.
8116
8208
  if (!session) {
8117
8209
  return res.status(404).json({ error: "Session not found" });
8118
8210
  }
8119
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
8120
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
8211
+ const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
8212
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
8121
8213
  const queuedMessages = sessionManager.getQueueState(sessionId);
8122
8214
  sessionManager.clearMessageQueue(sessionId);
8123
8215
  stopSessionExecution(sessionId, sessionManager);
8124
8216
  abortSession(sessionId);
8125
8217
  cancelQuestionsForSession(sessionId, "Session stopped by user");
8126
8218
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
8127
- const eventStore = (await import("./events-3WSNI7XC.js")).getEventStore();
8219
+ const eventStore = (await import("./events-335XAKFK.js")).getEventStore();
8128
8220
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
8129
8221
  res.json({ success: true, queuedMessages });
8130
8222
  });
@@ -8138,7 +8230,7 @@ All file and git operations should use this branch.
8138
8230
  if (typeof messageIndex !== "number" || messageIndex < 0) {
8139
8231
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
8140
8232
  }
8141
- const { truncateSessionMessages } = await import("./events-3WSNI7XC.js");
8233
+ const { truncateSessionMessages } = await import("./events-335XAKFK.js");
8142
8234
  truncateSessionMessages(sessionId, messageIndex);
8143
8235
  res.json({ success: true });
8144
8236
  });
@@ -8158,7 +8250,7 @@ All file and git operations should use this branch.
8158
8250
  if (attachments !== void 0 && !Array.isArray(attachments)) {
8159
8251
  return res.status(400).json({ error: "attachments must be an array if provided" });
8160
8252
  }
8161
- const { getEventStore: getEventStore2 } = await import("./events-3WSNI7XC.js");
8253
+ const { getEventStore: getEventStore2 } = await import("./events-335XAKFK.js");
8162
8254
  const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
8163
8255
  const eventStore = getEventStore2();
8164
8256
  const events = eventStore.getEvents(sessionId);
@@ -8171,7 +8263,7 @@ All file and git operations should use this branch.
8171
8263
  if (msg.role !== "user" || msg.isSystemGenerated) {
8172
8264
  return res.status(400).json({ error: "Can only replay user messages" });
8173
8265
  }
8174
- const { truncateSessionMessages } = await import("./events-3WSNI7XC.js");
8266
+ const { truncateSessionMessages } = await import("./events-335XAKFK.js");
8175
8267
  truncateSessionMessages(sessionId, msgIndex - 1);
8176
8268
  sessionManager.queueMessage(
8177
8269
  sessionId,
@@ -8206,6 +8298,43 @@ All file and git operations should use this branch.
8206
8298
  return res.status(500).json({ error: message });
8207
8299
  }
8208
8300
  });
8301
+ app.get("/api/sessions/:id/export", async (req, res) => {
8302
+ const sessionId = req.params.id;
8303
+ const session = sessionManager.getSession(sessionId);
8304
+ if (!session) {
8305
+ return res.status(404).json({ error: "Session not found" });
8306
+ }
8307
+ try {
8308
+ const { buildSessionExport } = await import("./export-import-3WMRLO4A.js");
8309
+ const payload = buildSessionExport(sessionManager, sessionId);
8310
+ const filename = `${(payload.session.title ?? "session").replace(/[^a-zA-Z0-9-_]/g, "_")}.openfox-session.json`;
8311
+ res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
8312
+ return res.json(payload);
8313
+ } catch (err) {
8314
+ const message = err instanceof Error ? err.message : String(err);
8315
+ return res.status(500).json({ error: message });
8316
+ }
8317
+ });
8318
+ app.post("/api/sessions/import", async (req, res) => {
8319
+ const { projectId, payload } = req.body;
8320
+ if (typeof projectId !== "string" || !projectId) {
8321
+ return res.status(400).json({ error: "projectId is required" });
8322
+ }
8323
+ if (payload === void 0 || payload === null) {
8324
+ return res.status(400).json({ error: "payload is required" });
8325
+ }
8326
+ try {
8327
+ const newSession = await sessionManager.importSession(projectId, payload);
8328
+ wssExports.broadcastForProject(projectId, newSession.id, buildSessionCreatedMessage(newSession));
8329
+ return res.status(201).json({ session: toClientSession(newSession) });
8330
+ } catch (err) {
8331
+ const message = err instanceof Error ? err.message : String(err);
8332
+ if (message.includes("Project not found")) {
8333
+ return res.status(404).json({ error: message });
8334
+ }
8335
+ return res.status(400).json({ error: message });
8336
+ }
8337
+ });
8209
8338
  app.post("/api/sessions/:id/chat", async (req, res) => {
8210
8339
  const sessionId = req.params.id;
8211
8340
  const session = sessionManager.getSession(sessionId);
@@ -8990,7 +9119,7 @@ All file and git operations should use this branch.
8990
9119
  });
8991
9120
  async function rebuildMcpTools() {
8992
9121
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-FJAFLDZA.js");
8993
- const { setMcpTools: setMcpTools2 } = await import("./tools-WWIWD3O7.js");
9122
+ const { setMcpTools: setMcpTools2 } = await import("./tools-E63MOJBO.js");
8994
9123
  const mcpTools = createMcpTools2(mcpManager);
8995
9124
  setMcpTools2(mcpTools);
8996
9125
  toolRegistry = createToolRegistry();
@@ -9566,7 +9695,7 @@ All file and git operations should use this branch.
9566
9695
  );
9567
9696
  const wss = wssExports.wss;
9568
9697
  deferTasksBroadcast = (projectId, payload) => wssExports.broadcastForProject(projectId, "", { type: "tasks.update", payload });
9569
- const { launchWorkflowRun, abortRunnerRun } = await import("./launch-FJ65HRV4.js");
9698
+ const { launchWorkflowRun, abortRunnerRun } = await import("./launch-GJ7EHQRI.js");
9570
9699
  deferTasksLaunchWorkflow = (sessionId, launch) => {
9571
9700
  const effective = sessionManager.resolveEffectiveProviderModel(sessionId);
9572
9701
  let llmClient = getLLMClient();
@@ -9611,7 +9740,7 @@ All file and git operations should use this branch.
9611
9740
  const state = sessionManager.getContextState(sessionId);
9612
9741
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
9613
9742
  });
9614
- const { QueueProcessor } = await import("./processor-CHMHMMIE.js");
9743
+ const { QueueProcessor } = await import("./processor-MSQP63ML.js");
9615
9744
  const queueProcessor = new QueueProcessor({
9616
9745
  sessionManager,
9617
9746
  providerManager,
@@ -9653,8 +9782,8 @@ All file and git operations should use this branch.
9653
9782
  launchWorkflow: (sessionId, launch) => deferTasksLaunchWorkflow(sessionId, launch),
9654
9783
  stopSession: (sessionId) => {
9655
9784
  void (async () => {
9656
- const { stopSessionExecution } = await import("./chat-handler-YCZE2XEJ.js");
9657
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-WWIWD3O7.js");
9785
+ const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
9786
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
9658
9787
  sessionManager.clearMessageQueue(sessionId);
9659
9788
  stopSessionExecution(sessionId, sessionManager);
9660
9789
  abortSession(sessionId);
@@ -9775,4 +9904,4 @@ export {
9775
9904
  createServerHandle,
9776
9905
  createServer
9777
9906
  };
9778
- //# sourceMappingURL=chunk-5IXCCMFU.js.map
9907
+ //# sourceMappingURL=chunk-BIZFY3QP.js.map
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-OZWHRBDY.js";
12
12
  import {
13
13
  getSessionDisabledServers
14
- } from "./chunk-QDARWVQ2.js";
14
+ } from "./chunk-S67WIWUG.js";
15
15
  import {
16
16
  TurnMetrics,
17
17
  clearLLMFailure,
@@ -77,12 +77,12 @@ import {
77
77
  registerPathConfirmation,
78
78
  requestPathAccess,
79
79
  resolveRelativeTraversals
80
- } from "./chunk-YLVOU7T7.js";
80
+ } from "./chunk-I5ODJKYM.js";
81
81
  import {
82
82
  getCurrentContextWindowId,
83
83
  getCurrentWindowMessageOptions,
84
84
  getEventStore
85
- } from "./chunk-CSYOWFPU.js";
85
+ } from "./chunk-QZOV4OVN.js";
86
86
  import {
87
87
  buildContextMessagesFromEventHistory,
88
88
  foldContextState,
@@ -2335,7 +2335,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
2335
2335
  currentMaxTokensOverride = void 0;
2336
2336
  if (!compacting) {
2337
2337
  const contextState = sessionManager.getContextState(sessionId);
2338
- const { shouldCompact, appendCompactionPrompt } = await import("./compactor-PD6DQ4NY.js");
2338
+ const { shouldCompact, appendCompactionPrompt } = await import("./compactor-454UEIEX.js");
2339
2339
  if (shouldCompact(
2340
2340
  contextState.currentTokens,
2341
2341
  contextState.maxTokens,
@@ -3374,7 +3374,7 @@ var callSubAgentTool = {
3374
3374
  };
3375
3375
  }
3376
3376
  try {
3377
- const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-WWIWD3O7.js");
3377
+ const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-E63MOJBO.js");
3378
3378
  const toolRegistry = getToolRegistryForAgent2(agentDef);
3379
3379
  const turnMetrics = new TurnMetrics();
3380
3380
  const result = await executeSubAgent({
@@ -4478,11 +4478,11 @@ var mcpConfigTool = createTool(
4478
4478
  async function notifyContextChanged(sessionId) {
4479
4479
  context.sessionManager.setDynamicContextChanged(sessionId, true);
4480
4480
  mcpNotifyChanged?.(sessionId);
4481
- const { injectContextDriftReminders } = await import("./dynamic-context-WKEXQCTK.js");
4481
+ const { injectContextDriftReminders } = await import("./dynamic-context-LKC6JYLQ.js");
4482
4482
  await injectContextDriftReminders(context.sessionManager, sessionId);
4483
4483
  }
4484
4484
  async function rebuildTools() {
4485
- const { setMcpTools: setMcpTools2 } = await import("./tools-WWIWD3O7.js");
4485
+ const { setMcpTools: setMcpTools2 } = await import("./tools-E63MOJBO.js");
4486
4486
  const mcpTools = createMcpTools(mcpManagerForTools);
4487
4487
  setMcpTools2(mcpTools);
4488
4488
  }
@@ -4491,7 +4491,7 @@ var mcpConfigTool = createTool(
4491
4491
  if (servers.length === 0) {
4492
4492
  return helpers.success(serverT({ en: "No MCP servers configured.", fr: "Aucun serveur MCP configur\xE9." }));
4493
4493
  }
4494
- const { getSessionDisabledServers: getSessionDisabledServers2 } = await import("./session-overrides-Y5B4XQPU.js");
4494
+ const { getSessionDisabledServers: getSessionDisabledServers2 } = await import("./session-overrides-LYW5PJ3R.js");
4495
4495
  const disabledForSession = new Set(context.sessionId ? getSessionDisabledServers2(context.sessionId) : []);
4496
4496
  const visibleServers = servers.filter((server) => !disabledForSession.has(server.name));
4497
4497
  if (visibleServers.length === 0) {
@@ -5615,4 +5615,4 @@ export {
5615
5615
  getToolRegistryForAgent,
5616
5616
  createToolRegistry
5617
5617
  };
5618
- //# sourceMappingURL=chunk-J5HOUEPE.js.map
5618
+ //# sourceMappingURL=chunk-ESZQTFQP.js.map
@@ -240,6 +240,18 @@ function updateSessionMessageCount(id, delta) {
240
240
  } catch {
241
241
  }
242
242
  }
243
+ function setSessionMessageCount(id, count) {
244
+ try {
245
+ const db = getDatabase();
246
+ const now = (/* @__PURE__ */ new Date()).toISOString();
247
+ db.prepare(
248
+ `
249
+ UPDATE sessions SET message_count = ?, updated_at = ? WHERE id = ?
250
+ `
251
+ ).run(count, now, id);
252
+ } catch {
253
+ }
254
+ }
243
255
  function getSessionMessageCount(id) {
244
256
  try {
245
257
  const db = getDatabase();
@@ -456,6 +468,7 @@ export {
456
468
  updateSessionCachedPrompt,
457
469
  getSessionCachedPrompt,
458
470
  updateSessionMessageCount,
471
+ setSessionMessageCount,
459
472
  getSessionMessageCount,
460
473
  listSessions,
461
474
  listSessionsByProject,
@@ -471,4 +484,4 @@ export {
471
484
  getLatestWorkflowExecution,
472
485
  clearWorkflowExecution
473
486
  };
474
- //# sourceMappingURL=chunk-ZTBKMVV6.js.map
487
+ //# sourceMappingURL=chunk-F2MOHHXB.js.map