openfox 2.0.77 → 2.0.78

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 (63) hide show
  1. package/dist/{chat-handler-FNRKORKP.js → chat-handler-5ZHPYU24.js} +18 -17
  2. package/dist/{chunk-MF3UW36X.js → chunk-37WF2Z3T.js} +84 -17
  3. package/dist/{chunk-OBQPXUXI.js → chunk-5CQRB7AD.js} +2 -2
  4. package/dist/chunk-64TKWWNF.js +7 -0
  5. package/dist/{chunk-LXFLRM7M.js → chunk-6AE3JPDJ.js} +2 -2
  6. package/dist/chunk-AANVMTYU.js +327 -0
  7. package/dist/{chunk-YMFCFMMB.js → chunk-AFJLY43Z.js} +8 -3
  8. package/dist/{chunk-CI5BWHW7.js → chunk-DI4SIPFT.js} +46 -27
  9. package/dist/{chunk-XNCHOD2X.js → chunk-EHVDAVYG.js} +3 -2
  10. package/dist/{chunk-DH3SSBZN.js → chunk-EYIWUONA.js} +2 -2
  11. package/dist/{chunk-NGJ5XJ7D.js → chunk-M7EFXRDS.js} +57 -290
  12. package/dist/{chunk-4QHDQP2N.js → chunk-MTUYDBSL.js} +2 -2
  13. package/dist/{chunk-YPHLCRFP.js → chunk-NUR2B4RU.js} +3 -3
  14. package/dist/{chunk-46RORSKU.js → chunk-NZIYELSQ.js} +9 -7
  15. package/dist/{chunk-7QXRQ5ZL.js → chunk-RGUUZD5B.js} +5 -1
  16. package/dist/{chunk-YDV7RIQ6.js → chunk-SGBXBP3S.js} +143 -43
  17. package/dist/{chunk-O3NUNU4H.js → chunk-SJTG56CH.js} +5 -4
  18. package/dist/{chunk-DJASQ2ZB.js → chunk-TSVFRWSG.js} +24 -5
  19. package/dist/{chunk-3TQN25OM.js → chunk-UIU7OGHP.js} +25 -9
  20. package/dist/{chunk-BX3VJP2D.js → chunk-UMX7MMNW.js} +573 -221
  21. package/dist/{chunk-VMYDUZWI.js → chunk-VGWJFXPR.js} +23 -11
  22. package/dist/{chunk-CPTC2MD5.js → chunk-WUSWNLTV.js} +3 -3
  23. package/dist/{chunk-5GOOSZX7.js → chunk-X6BXZFO7.js} +1 -1
  24. package/dist/cli/dev.js +1 -1
  25. package/dist/cli/index.js +1 -1
  26. package/dist/{compactor-BJXFE5PL.js → compactor-G7B3V24F.js} +9 -8
  27. package/dist/{events-FLWRLM6V.js → events-KNOZX7YG.js} +7 -4
  28. package/dist/{folding-ONH3D4OK.js → folding-OPP2BVUB.js} +2 -2
  29. package/dist/{inspect-proxy-JHZV34QR.js → inspect-proxy-DRYIIH4O.js} +4 -4
  30. package/dist/{manager-OPMCSYN2.js → manager-ATWZUL3O.js} +5 -5
  31. package/dist/{orchestrator-67BZJEOO.js → orchestrator-L6LX5BV7.js} +17 -16
  32. package/dist/package.json +4 -1
  33. package/dist/{path-security-ZROWNL22.js → path-security-HUXQHEQ5.js} +10 -7
  34. package/dist/{platform-QGXO3CNR.js → platform-VBNNMTR5.js} +4 -4
  35. package/dist/{processor-BCOSEMZK.js → processor-UQX5KL56.js} +18 -17
  36. package/dist/{project-creator-C22J43BC.js → project-creator-NNUITNUI.js} +3 -3
  37. package/dist/{projects-WSVINK2C.js → projects-ZGJGICGT.js} +3 -3
  38. package/dist/{protocol-Ceapo3jt.d.ts → protocol-BXxJmsOW.d.ts} +2 -1
  39. package/dist/{protocol-EWEVW65B.js → protocol-Q7X4NEME.js} +3 -3
  40. package/dist/provider/index.d.ts +4 -4
  41. package/dist/{serve-BD44GN7N.js → serve-QWC3U5MB.js} +21 -20
  42. package/dist/server/index.d.ts +27 -4
  43. package/dist/server/index.js +20 -19
  44. package/dist/server-3XUD2NB7.js +40 -0
  45. package/dist/sessions-SFG42M4W.js +42 -0
  46. package/dist/{settings-7XDMSPIC.js → settings-6M55N4Q2.js} +5 -3
  47. package/dist/shared/index.d.ts +3 -3
  48. package/dist/shared/index.js +1 -1
  49. package/dist/{tools-T7S45DOQ.js → tools-HGKUD327.js} +23 -20
  50. package/dist/{types-DABVUbUu.d.ts → types-C308SU4B.d.ts} +2 -0
  51. package/dist/{types-pssMT-oY.d.ts → types-o07LJcLI.d.ts} +1 -1
  52. package/dist/{update-56VZOLQJ.js → update-NWZALB5M.js} +2 -2
  53. package/dist/web/assets/{index-BuUd6IgK.js → index-7_xKqeJc.js} +75 -75
  54. package/dist/web/assets/index-DRkTjPo3.css +32 -0
  55. package/dist/web/index.html +4 -4
  56. package/dist/web/manifest.webmanifest +1 -1
  57. package/dist/web/registerSW.js +1 -1
  58. package/dist/web/sw.js +1 -1
  59. package/dist/{workspace-6QTTUMMW.js → workspace-J74ZMSOJ.js} +14 -2
  60. package/package.json +4 -1
  61. package/dist/chunk-NUXS5OQB.js +0 -7
  62. package/dist/server-OLRW27DH.js +0 -39
  63. package/dist/web/assets/index-BNVBxKnB.css +0 -32
@@ -21,7 +21,7 @@ import {
21
21
  tokenFromPassword,
22
22
  verifyPassword,
23
23
  workflowExists
24
- } from "./chunk-CI5BWHW7.js";
24
+ } from "./chunk-DI4SIPFT.js";
25
25
  import {
26
26
  agentExists,
27
27
  createToolRegistry,
@@ -66,7 +66,7 @@ import {
66
66
  setSkillEnabled,
67
67
  skillExists,
68
68
  updateOwnedSkill
69
- } from "./chunk-YDV7RIQ6.js";
69
+ } from "./chunk-SGBXBP3S.js";
70
70
  import {
71
71
  createMcpTools
72
72
  } from "./chunk-NWO6GRYE.js";
@@ -74,14 +74,18 @@ import {
74
74
  deleteWorkspace,
75
75
  ensureWorkspace,
76
76
  getCommitsBehind,
77
+ getDefaultBranch,
77
78
  getGitBranch,
79
+ getGlobalDataDir,
78
80
  getWorkspacesDir,
79
81
  loadWorkspaceConfig,
82
+ resolveAndValidateSourceBranch,
80
83
  runGit,
81
84
  saveWorkspaceConfig,
85
+ validateRef,
82
86
  validateWorkspaceName,
83
87
  workspaceExists
84
- } from "./chunk-MF3UW36X.js";
88
+ } from "./chunk-37WF2Z3T.js";
85
89
  import {
86
90
  EventEmitter
87
91
  } from "./chunk-EU3WWTFH.js";
@@ -89,25 +93,23 @@ import {
89
93
  ALWAYS_ALLOWED,
90
94
  ALWAYS_ALLOWED_FOR_SUBAGENTS,
91
95
  TOP_LEVEL_ONLY_TOOLS
92
- } from "./chunk-XNCHOD2X.js";
93
- import {
94
- getProject
95
- } from "./chunk-LXFLRM7M.js";
96
+ } from "./chunk-EHVDAVYG.js";
96
97
  import {
97
98
  getPathSeparator,
98
99
  isAbsolutePath
99
- } from "./chunk-4QHDQP2N.js";
100
+ } from "./chunk-MTUYDBSL.js";
100
101
  import {
101
102
  deleteSetting,
102
103
  getSetting,
103
104
  setSetting
104
- } from "./chunk-YMFCFMMB.js";
105
+ } from "./chunk-AFJLY43Z.js";
106
+ import {
107
+ getProject
108
+ } from "./chunk-6AE3JPDJ.js";
105
109
  import {
106
110
  VERSION
107
- } from "./chunk-NUXS5OQB.js";
111
+ } from "./chunk-64TKWWNF.js";
108
112
  import {
109
- createSession,
110
- deleteSession,
111
113
  emitAssistantMessageStart,
112
114
  emitContextState,
113
115
  emitCriteriaSet,
@@ -119,26 +121,31 @@ import {
119
121
  emitSessionInitialized,
120
122
  emitUserMessage,
121
123
  getEventStore,
122
- getSession,
123
- getSessionCachedPrompt,
124
124
  getSessionState,
125
125
  initEventStore,
126
+ setRuntimeConfig
127
+ } from "./chunk-M7EFXRDS.js";
128
+ import {
129
+ createSession,
130
+ deleteSession,
131
+ getSession,
132
+ getSessionCachedPrompt,
126
133
  listSessions,
127
134
  listSessionsByProject,
128
- setRuntimeConfig,
135
+ updateSessionBranch,
129
136
  updateSessionCachedPrompt,
130
137
  updateSessionDangerLevel,
131
138
  updateSessionMetadata,
132
139
  updateSessionProvider,
133
140
  updateSessionRunning,
134
141
  updateSessionWorkdir
135
- } from "./chunk-NGJ5XJ7D.js";
142
+ } from "./chunk-AANVMTYU.js";
136
143
  import {
137
144
  initDatabase
138
- } from "./chunk-7QXRQ5ZL.js";
145
+ } from "./chunk-RGUUZD5B.js";
139
146
  import {
140
147
  createContextStateMessage
141
- } from "./chunk-O3NUNU4H.js";
148
+ } from "./chunk-SJTG56CH.js";
142
149
  import {
143
150
  createProviderManager,
144
151
  detectModel,
@@ -163,7 +170,7 @@ import {
163
170
  } from "./chunk-K44MW7JJ.js";
164
171
  import {
165
172
  createServerMessage
166
- } from "./chunk-5GOOSZX7.js";
173
+ } from "./chunk-X6BXZFO7.js";
167
174
  import {
168
175
  getGlobalConfigDir
169
176
  } from "./chunk-CQGTEGKL.js";
@@ -173,7 +180,7 @@ import express from "express";
173
180
  import cors from "cors";
174
181
  import { createServer as createHttpServer } from "http";
175
182
  import { fileURLToPath as fileURLToPath7 } from "url";
176
- import { dirname as dirname8, resolve as resolve7, join as join9 } from "path";
183
+ import { dirname as dirname8, resolve as resolve8, join as join10 } from "path";
177
184
  import { readFile as readFile4 } from "fs/promises";
178
185
  import { createServer as createViteServer } from "vite";
179
186
 
@@ -1771,8 +1778,8 @@ var LspServer = class {
1771
1778
  windowsHide: true,
1772
1779
  shell: needsShell
1773
1780
  });
1774
- await new Promise((resolve8, reject) => {
1775
- this.process.once("spawn", resolve8);
1781
+ await new Promise((resolve9, reject) => {
1782
+ this.process.once("spawn", resolve9);
1776
1783
  this.process.once("error", reject);
1777
1784
  });
1778
1785
  if (!this.process.stdin || !this.process.stdout) {
@@ -1992,19 +1999,19 @@ var LspServer = class {
1992
1999
  */
1993
2000
  async getDiagnosticsWithWait(path, timeoutMs = DIAGNOSTIC_WAIT_MS) {
1994
2001
  if (this.openDocuments.has(path)) {
1995
- return new Promise((resolve8) => {
2002
+ return new Promise((resolve9) => {
1996
2003
  const existing = this.diagnostics.get(path);
1997
2004
  if (existing !== void 0) {
1998
2005
  setTimeout(() => {
1999
- resolve8(this.diagnostics.get(path) ?? []);
2006
+ resolve9(this.diagnostics.get(path) ?? []);
2000
2007
  }, 100);
2001
2008
  return;
2002
2009
  }
2003
2010
  const timeout = setTimeout(() => {
2004
2011
  this.pendingDiagnostics.delete(path);
2005
- resolve8(this.diagnostics.get(path) ?? []);
2012
+ resolve9(this.diagnostics.get(path) ?? []);
2006
2013
  }, timeoutMs);
2007
- this.pendingDiagnostics.set(path, { resolve: resolve8, timeout });
2014
+ this.pendingDiagnostics.set(path, { resolve: resolve9, timeout });
2008
2015
  });
2009
2016
  }
2010
2017
  return this.diagnostics.get(path) ?? [];
@@ -2623,6 +2630,35 @@ var SessionManager = class {
2623
2630
  getCurrentModelContext() {
2624
2631
  return this.providerManager.getCurrentModelContext();
2625
2632
  }
2633
+ /**
2634
+ * Get the effective working directory for a session.
2635
+ * Uses workspace path when active, otherwise the project workdir.
2636
+ */
2637
+ getEffectiveWorkdir(sessionId) {
2638
+ const session = this.requireSession(sessionId);
2639
+ return session.workspace ?? session.workdir;
2640
+ }
2641
+ /**
2642
+ * Return (effectiveWorkdir, actualBranch) for a session.
2643
+ */
2644
+ async getActualBranchPair(sessionId) {
2645
+ const effectiveWorkdir = this.getEffectiveWorkdir(sessionId);
2646
+ const branch = await getGitBranch(effectiveWorkdir);
2647
+ return { workdir: effectiveWorkdir, branch };
2648
+ }
2649
+ /**
2650
+ * Check that the session's persisted branch matches the actual branch on disk.
2651
+ * If they differ (and persisted branch exists), returns a warning message.
2652
+ */
2653
+ async checkBranchConsistency(sessionId) {
2654
+ const session = this.getSession(sessionId);
2655
+ if (!session?.branch) return null;
2656
+ const actualBranch = await getGitBranch(session.workspace ?? session.workdir);
2657
+ if (actualBranch && actualBranch !== session.branch) {
2658
+ return `Branch mismatch: session expects "${session.branch}" but workspace is on "${actualBranch}". The workspace branch was changed externally.`;
2659
+ }
2660
+ return null;
2661
+ }
2626
2662
  // ============================================================================
2627
2663
  // Session Lifecycle
2628
2664
  // ============================================================================
@@ -2646,6 +2682,20 @@ var SessionManager = class {
2646
2682
  const contextWindowId = crypto.randomUUID();
2647
2683
  emitSessionInitialized(dbSession.id, projectId, effectiveWorkdir, contextWindowId, sessionTitle);
2648
2684
  const session = this.buildSessionFromDb(dbSession);
2685
+ getGitBranch(effectiveWorkdir).then((branch) => {
2686
+ if (branch) {
2687
+ updateSessionBranch(session.id, branch);
2688
+ const updatedDb = getSession(session.id);
2689
+ if (updatedDb) {
2690
+ this.emit({ type: "session_updated", session: this.buildSessionFromDb(updatedDb) });
2691
+ }
2692
+ }
2693
+ }).catch((err) => {
2694
+ logger.error("Failed to persist initial branch for session", {
2695
+ sessionId: session.id,
2696
+ error: err instanceof Error ? err.message : String(err)
2697
+ });
2698
+ });
2649
2699
  this.emit({ type: "session_created", session });
2650
2700
  return session;
2651
2701
  }
@@ -2739,6 +2789,16 @@ var SessionManager = class {
2739
2789
  this.emit({ type: "session_updated", session: updatedSession });
2740
2790
  return updatedSession;
2741
2791
  }
2792
+ /**
2793
+ * Emit session_updated for the given session.
2794
+ * Used by REST handlers after updating sibling session branches.
2795
+ */
2796
+ emitBranchChange(sessionId) {
2797
+ const session = this.getSession(sessionId);
2798
+ if (session) {
2799
+ this.emit({ type: "session_updated", session });
2800
+ }
2801
+ }
2742
2802
  /**
2743
2803
  * Change session phase. Emits phase.changed event.
2744
2804
  */
@@ -3249,6 +3309,24 @@ var SessionManager = class {
3249
3309
  const effectiveWorkdir = session.workspace ?? session.workdir;
3250
3310
  return getLspManager(sessionId, effectiveWorkdir);
3251
3311
  }
3312
+ async applyBranchIfNeeded(projectDir, projectName, workspaceName, branch, sourceBranch) {
3313
+ const wsPath = resolve2(await getWorkspacesDir(projectName, projectDir), workspaceName);
3314
+ const currentBranch = await getGitBranch(wsPath);
3315
+ if (currentBranch !== branch) {
3316
+ try {
3317
+ await validateRef(wsPath, branch);
3318
+ await runGit(wsPath, ["checkout", branch]).catch(async () => {
3319
+ const sb = sourceBranch ?? await getDefaultBranch(projectDir);
3320
+ const validated = sourceBranch ? await resolveAndValidateSourceBranch(wsPath, sourceBranch, projectDir) : sb;
3321
+ await runGit(wsPath, ["checkout", "-b", branch, validated]);
3322
+ });
3323
+ } catch (err) {
3324
+ throw new Error(
3325
+ `Failed to apply branch "${branch}" to workspace "${workspaceName}": ${err instanceof Error ? err.message : String(err)}`
3326
+ );
3327
+ }
3328
+ }
3329
+ }
3252
3330
  // ============================================================================
3253
3331
  // Workspace Lifecycle
3254
3332
  // ============================================================================
@@ -3258,44 +3336,55 @@ var SessionManager = class {
3258
3336
  * Emits a single type of event — switching is always "opening" a workspace.
3259
3337
  * Switches are serialized per-session to prevent race conditions.
3260
3338
  */
3261
- async switchWorkspace(sessionId, target, branch) {
3262
- if (target !== "original") {
3263
- validateWorkspaceName(target);
3264
- }
3339
+ async switchWorkspace(sessionId, target, branch, sourceBranch) {
3340
+ if (target !== "original") validateWorkspaceName(target);
3265
3341
  const existingLock = this.switchLocks.get(sessionId);
3266
- if (existingLock) {
3267
- await existingLock;
3268
- }
3342
+ if (existingLock) await existingLock;
3269
3343
  const lockPromise = (async () => {
3270
3344
  const session = this.requireSession(sessionId);
3271
3345
  const project = getProject(session.projectId);
3272
3346
  if (!project) throw new Error(`Project not found: ${session.projectId}`);
3273
- if (target === "original" && !session.workspace) return session;
3274
- if (target !== "original" && session.workspace?.split("/").pop() === target) return session;
3347
+ const isBranchChangeOnly = target !== "original" && session.workspace?.split("/").pop() === target && branch !== void 0;
3348
+ if (target === "original" && !session.workspace && !branch) return session;
3349
+ if (target !== "original" && session.workspace?.split("/").pop() === target && !branch) return session;
3350
+ if (isBranchChangeOnly) {
3351
+ const currentBranch = await getGitBranch(session.workspace ?? session.workdir);
3352
+ if (currentBranch === branch) return session;
3353
+ }
3275
3354
  const previousPath = session.workspace;
3276
- if (previousPath) {
3277
- try {
3278
- await devServerManager.stop(previousPath);
3279
- } catch (err) {
3280
- logger.error("Error stopping dev server for workspace switch", {
3281
- sessionId,
3282
- workspace: previousPath,
3283
- error: err
3355
+ if (previousPath && !isBranchChangeOnly) {
3356
+ const otherSessionsUsingPath = this.listSessions().filter(
3357
+ (s) => s.id !== sessionId && s.workspace === previousPath
3358
+ );
3359
+ if (otherSessionsUsingPath.length === 0) {
3360
+ try {
3361
+ await devServerManager.stop(previousPath);
3362
+ } catch (err) {
3363
+ logger.error("Error stopping dev server for workspace switch", {
3364
+ sessionId,
3365
+ workspace: previousPath,
3366
+ error: err
3367
+ });
3368
+ }
3369
+ } else {
3370
+ logger.info("Skipping dev server stop \u2014 other sessions still use path", {
3371
+ path: previousPath,
3372
+ otherSessions: otherSessionsUsingPath.map((s) => s.id)
3284
3373
  });
3285
3374
  }
3286
3375
  }
3287
3376
  if (target === "original") {
3288
3377
  updateSessionWorkdir(sessionId, project.workdir, null);
3289
- } else {
3378
+ } else if (!isBranchChangeOnly) {
3290
3379
  const createLockKey = `${project.name}:${target}`;
3291
3380
  const existingCreateLock = this.workspaceCreationLocks.get(createLockKey);
3292
- if (existingCreateLock) {
3293
- await existingCreateLock;
3294
- }
3381
+ if (existingCreateLock) await existingCreateLock;
3295
3382
  const createLockPromise = (async () => {
3296
- const exists = await workspaceExists(project.name, target);
3383
+ const exists = await workspaceExists(project.name, target, project.workdir);
3297
3384
  if (!exists) {
3298
- await ensureWorkspace(project.workdir, target, project.name, branch);
3385
+ await ensureWorkspace(project.workdir, target, project.name, branch, sourceBranch);
3386
+ } else if (branch) {
3387
+ await this.applyBranchIfNeeded(project.workdir, project.name, target, branch, sourceBranch);
3299
3388
  }
3300
3389
  })();
3301
3390
  this.workspaceCreationLocks.set(createLockKey, createLockPromise);
@@ -3304,16 +3393,31 @@ var SessionManager = class {
3304
3393
  } finally {
3305
3394
  this.workspaceCreationLocks.delete(createLockKey);
3306
3395
  }
3307
- const wsPath = resolve2(getWorkspacesDir(project.name), target);
3396
+ const wsDir = await getWorkspacesDir(project.name, project.workdir);
3397
+ const wsPath = resolve2(wsDir, target);
3308
3398
  updateSessionWorkdir(sessionId, project.workdir, wsPath);
3399
+ } else {
3400
+ await this.applyBranchIfNeeded(project.workdir, project.name, target, branch, sourceBranch);
3309
3401
  }
3310
3402
  try {
3311
3403
  await shutdownLspManager(sessionId);
3312
3404
  } catch (err) {
3313
3405
  logger.error("Error shutting down LSP for workspace switch", { sessionId, error: err });
3314
3406
  }
3315
- const effectiveWorkdir = target === "original" ? project.workdir : resolve2(getWorkspacesDir(project.name), target);
3407
+ const wsDirForBranch = await getWorkspacesDir(project.name, project.workdir);
3408
+ const effectiveWorkdir = target === "original" ? project.workdir : resolve2(wsDirForBranch, target);
3316
3409
  const actualBranch = await getGitBranch(effectiveWorkdir);
3410
+ if (actualBranch) {
3411
+ updateSessionBranch(sessionId, actualBranch);
3412
+ const otherSessionsOnWorkspace = this.listSessions().filter(
3413
+ (s) => s.id !== sessionId && s.workspace === effectiveWorkdir
3414
+ );
3415
+ for (const other of otherSessionsOnWorkspace) {
3416
+ updateSessionBranch(other.id, actualBranch);
3417
+ const updated2 = this.getSession(other.id);
3418
+ if (updated2) this.emit({ type: "session_updated", session: updated2 });
3419
+ }
3420
+ }
3317
3421
  let stalenessHint = "";
3318
3422
  if (target !== "original" && actualBranch) {
3319
3423
  await runGit(effectiveWorkdir, ["fetch", "origin", "--no-tags", "--quiet"]).catch(() => {
@@ -3350,9 +3454,7 @@ All file and git operations should use this directory.
3350
3454
  })();
3351
3455
  this.switchLocks.set(sessionId, lockPromise);
3352
3456
  lockPromise.finally(() => {
3353
- if (this.switchLocks.get(sessionId) === lockPromise) {
3354
- this.switchLocks.delete(sessionId);
3355
- }
3457
+ if (this.switchLocks.get(sessionId) === lockPromise) this.switchLocks.delete(sessionId);
3356
3458
  });
3357
3459
  return lockPromise;
3358
3460
  }
@@ -3380,12 +3482,13 @@ All file and git operations should use this directory.
3380
3482
  if (currentWsName === target) {
3381
3483
  await this.switchWorkspace(sessionId, "original");
3382
3484
  }
3383
- const effectivePath = resolve2(getWorkspacesDir(project.name), target);
3485
+ const wsDir = await getWorkspacesDir(project.name, project.workdir);
3486
+ const effectivePath = resolve2(wsDir, target);
3384
3487
  try {
3385
3488
  await devServerManager.stop(effectivePath);
3386
3489
  } catch {
3387
3490
  }
3388
- await deleteWorkspace(project.name, target);
3491
+ await deleteWorkspace(project.name, target, project.workdir);
3389
3492
  const updated = this.requireSession(sessionId);
3390
3493
  this.emit({ type: "session_updated", session: updated });
3391
3494
  return updated;
@@ -4154,6 +4257,85 @@ function createDevServerRoutes() {
4154
4257
 
4155
4258
  // src/server/routes/workspace-config.ts
4156
4259
  import { Router as Router5 } from "express";
4260
+ import { stat as stat2, mkdir as mkdir4, readdir, access as access3 } from "fs/promises";
4261
+ import { constants as constants3 } from "fs";
4262
+ import { resolve as resolve4, isAbsolute as isAbsolute3, join as join6 } from "path";
4263
+
4264
+ // src/shared/workspace.ts
4265
+ var BLOCKED_EXACT_PATHS = [
4266
+ "/",
4267
+ "/etc",
4268
+ "/bin",
4269
+ "/sbin",
4270
+ "/lib",
4271
+ "/lib64",
4272
+ "/usr",
4273
+ "/var",
4274
+ "/opt",
4275
+ "/root",
4276
+ "/run",
4277
+ "/tmp",
4278
+ "/home",
4279
+ "/mnt",
4280
+ "/media"
4281
+ ];
4282
+ var BLOCKED_VIRTUAL_FS_PREFIXES = ["/proc/", "/sys/", "/dev/", "/boot/", "/etc/", "/lost+found/"];
4283
+ function getRootDirBlockReason(path, exactPaths = BLOCKED_EXACT_PATHS, virtualFsPrefixes = BLOCKED_VIRTUAL_FS_PREFIXES) {
4284
+ if (!path) return null;
4285
+ const normalized = path.replace(/\/+$/, "") || "/";
4286
+ if (exactPaths.includes(normalized)) return "exact";
4287
+ for (const prefix of virtualFsPrefixes) {
4288
+ if (normalized.startsWith(prefix)) return "virtual_fs";
4289
+ }
4290
+ return null;
4291
+ }
4292
+
4293
+ // src/server/routes/workspace-config.ts
4294
+ async function isWritable(path) {
4295
+ try {
4296
+ await access3(path, constants3.W_OK);
4297
+ return true;
4298
+ } catch {
4299
+ return false;
4300
+ }
4301
+ }
4302
+ function resolveRootDir(rootDir, workdir) {
4303
+ return isAbsolute3(rootDir) ? rootDir : resolve4(workdir, rootDir);
4304
+ }
4305
+ async function checkDirExists(path) {
4306
+ try {
4307
+ const st = await stat2(path);
4308
+ return st.isDirectory();
4309
+ } catch {
4310
+ return false;
4311
+ }
4312
+ }
4313
+ async function validatePathWritable(path) {
4314
+ if (await isWritable(path)) return null;
4315
+ return "Workspace root directory exists but is not writable";
4316
+ }
4317
+ async function findOrphanedWorkspaces(dir) {
4318
+ const results = [];
4319
+ try {
4320
+ const entries = await readdir(dir, { withFileTypes: true });
4321
+ for (const entry of entries) {
4322
+ if (entry.isDirectory()) {
4323
+ try {
4324
+ const gitStat = await stat2(join6(dir, entry.name, ".git"));
4325
+ if (gitStat.isDirectory()) {
4326
+ results.push({ name: entry.name });
4327
+ }
4328
+ } catch {
4329
+ }
4330
+ }
4331
+ }
4332
+ } catch (err) {
4333
+ if (err?.code !== "ENOENT") {
4334
+ logger.error("Error scanning for orphaned workspaces", { dir, error: String(err) });
4335
+ }
4336
+ }
4337
+ return results;
4338
+ }
4157
4339
  function createWorkspaceConfigRoutes() {
4158
4340
  const router = Router5();
4159
4341
  router.get("/config", async (req, res) => {
@@ -4165,18 +4347,93 @@ function createWorkspaceConfigRoutes() {
4165
4347
  router.post("/config", async (req, res) => {
4166
4348
  const workdir = req.query["workdir"];
4167
4349
  if (!workdir) return res.status(400).json({ error: "workdir required" });
4168
- const { setup } = req.body;
4169
- if (!Array.isArray(setup)) {
4350
+ const { setup, rootDir } = req.body;
4351
+ if (!Array.isArray(setup) && typeof rootDir !== "string") {
4352
+ return res.status(400).json({ error: "At least one of setup or rootDir must be provided" });
4353
+ }
4354
+ if (setup !== void 0 && !Array.isArray(setup)) {
4170
4355
  return res.status(400).json({ error: "setup must be an array of strings" });
4171
4356
  }
4357
+ const config3 = {};
4358
+ if (Array.isArray(setup)) {
4359
+ config3.setup = setup;
4360
+ }
4361
+ if (typeof rootDir === "string") {
4362
+ const trimmed = rootDir.trim();
4363
+ if (trimmed) {
4364
+ const resolvedPath = resolveRootDir(trimmed, workdir);
4365
+ const displayPath = resolvedPath.replace(/\/+$/, "") || "/";
4366
+ const blockReason = getRootDirBlockReason(resolvedPath);
4367
+ if (blockReason === "exact") {
4368
+ return res.status(400).json({ error: `Cannot use "${displayPath}" directly as workspace root. Use a subdirectory instead.` });
4369
+ }
4370
+ if (blockReason === "virtual_fs") {
4371
+ return res.status(400).json({ error: `Cannot use paths under "${displayPath}" for workspaces.` });
4372
+ }
4373
+ const dirExists = await checkDirExists(resolvedPath);
4374
+ if (dirExists) {
4375
+ const writableErr = await validatePathWritable(resolvedPath);
4376
+ if (writableErr) return res.status(400).json({ error: writableErr });
4377
+ }
4378
+ config3.rootDir = trimmed;
4379
+ }
4380
+ }
4172
4381
  try {
4173
- const config3 = { setup };
4174
4382
  await saveWorkspaceConfig(workdir, config3);
4175
4383
  res.json({ config: config3 });
4176
4384
  } catch (err) {
4177
4385
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
4178
4386
  }
4179
4387
  });
4388
+ router.post("/config/validate", async (req, res) => {
4389
+ const { rootDir, workdir, projectName, createIfMissing } = req.body;
4390
+ if (!rootDir || typeof rootDir !== "string") {
4391
+ return res.status(400).json({ error: "rootDir is required" });
4392
+ }
4393
+ if (!workdir || typeof workdir !== "string") {
4394
+ return res.status(400).json({ error: "workdir is required" });
4395
+ }
4396
+ const resolvedPath = resolveRootDir(rootDir, workdir);
4397
+ const displayPath = resolvedPath.replace(/\/+$/, "") || "/";
4398
+ const blockReason = getRootDirBlockReason(resolvedPath);
4399
+ if (blockReason === "exact") {
4400
+ const suggestion = typeof projectName === "string" ? `${displayPath}/${projectName}` : void 0;
4401
+ return res.status(400).json({
4402
+ error: suggestion ? `Cannot use "${displayPath}" directly as workspace root. Use a subdirectory like "${suggestion}" instead.` : `Cannot use "${displayPath}" directly as workspace root. Use a subdirectory instead.`
4403
+ });
4404
+ }
4405
+ if (blockReason === "virtual_fs") {
4406
+ return res.status(400).json({ error: `Cannot use paths under "${displayPath}" for workspaces.` });
4407
+ }
4408
+ let dirExists = await checkDirExists(resolvedPath);
4409
+ if (dirExists) {
4410
+ const writableErr = await validatePathWritable(resolvedPath);
4411
+ if (writableErr) return res.status(400).json({ error: writableErr });
4412
+ }
4413
+ let created = false;
4414
+ if (!dirExists && createIfMissing) {
4415
+ await mkdir4(resolvedPath, { recursive: true });
4416
+ dirExists = true;
4417
+ created = true;
4418
+ }
4419
+ const workspaces = [];
4420
+ try {
4421
+ const currentConfig = await loadWorkspaceConfig(workdir);
4422
+ const previousRootDir = currentConfig?.rootDir ? resolveRootDir(currentConfig.rootDir, workdir) : null;
4423
+ if (previousRootDir && previousRootDir !== resolvedPath) {
4424
+ const orphans = await findOrphanedWorkspaces(previousRootDir);
4425
+ workspaces.push(...orphans);
4426
+ } else if (!previousRootDir && projectName && typeof projectName === "string") {
4427
+ const defaultDir = join6(getGlobalDataDir(), "workspaces", projectName);
4428
+ if (defaultDir !== resolvedPath) {
4429
+ const orphans = await findOrphanedWorkspaces(defaultDir);
4430
+ workspaces.push(...orphans);
4431
+ }
4432
+ }
4433
+ } catch {
4434
+ }
4435
+ res.json({ exists: dirExists, resolvedPath, created, workspaces });
4436
+ });
4180
4437
  return router;
4181
4438
  }
4182
4439
 
@@ -4223,19 +4480,19 @@ function createTerminalRoutes() {
4223
4480
 
4224
4481
  // src/server/routes/directories.ts
4225
4482
  import { Router as Router7 } from "express";
4226
- import { readdir } from "fs/promises";
4227
- import { resolve as resolve4, join as join6, dirname as dirname5, basename as basename2 } from "path";
4483
+ import { readdir as readdir2 } from "fs/promises";
4484
+ import { resolve as resolve5, join as join7, dirname as dirname5, basename as basename2 } from "path";
4228
4485
  function createDirectoryRoutes() {
4229
4486
  const router = Router7();
4230
4487
  const DEFAULT_BASE_PATH = process.cwd();
4231
4488
  router.get("/", async (req, res) => {
4232
4489
  const path = req.query["path"] || DEFAULT_BASE_PATH;
4233
4490
  try {
4234
- const resolvedPath = resolve4(path);
4235
- const entries = await readdir(resolvedPath, { withFileTypes: true });
4491
+ const resolvedPath = resolve5(path);
4492
+ const entries = await readdir2(resolvedPath, { withFileTypes: true });
4236
4493
  const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
4237
4494
  name: entry.name,
4238
- path: join6(resolvedPath, entry.name)
4495
+ path: join7(resolvedPath, entry.name)
4239
4496
  })).sort((a, b) => a.name.localeCompare(b.name));
4240
4497
  const parent = dirname5(resolvedPath);
4241
4498
  const hasParent = parent !== resolvedPath;
@@ -4389,7 +4646,7 @@ function isDevMode() {
4389
4646
  return process.env["NODE_ENV"] === "development";
4390
4647
  }
4391
4648
  async function getRemote() {
4392
- return new Promise((resolve8) => {
4649
+ return new Promise((resolve9) => {
4393
4650
  const child = spawn2("git", ["remote"], {
4394
4651
  stdio: ["ignore", "pipe", "pipe"],
4395
4652
  windowsHide: true
@@ -4400,23 +4657,23 @@ async function getRemote() {
4400
4657
  });
4401
4658
  child.on("close", () => {
4402
4659
  const remotes = output.trim().split("\n").map((r) => r.trim()).filter(Boolean);
4403
- if (remotes.includes("upstream")) resolve8("upstream");
4404
- else if (remotes.includes("origin")) resolve8("origin");
4405
- else resolve8("origin");
4660
+ if (remotes.includes("upstream")) resolve9("upstream");
4661
+ else if (remotes.includes("origin")) resolve9("origin");
4662
+ else resolve9("origin");
4406
4663
  });
4407
- child.on("error", () => resolve8("origin"));
4664
+ child.on("error", () => resolve9("origin"));
4408
4665
  });
4409
4666
  }
4410
4667
  async function getLatestDevelopVersion() {
4411
4668
  const remote = await getRemote();
4412
- return new Promise((resolve8) => {
4669
+ return new Promise((resolve9) => {
4413
4670
  const fetchChild = spawn2("git", ["fetch", remote, "develop", "--no-tags"], {
4414
4671
  stdio: ["ignore", "pipe", "pipe"],
4415
4672
  windowsHide: true
4416
4673
  });
4417
4674
  fetchChild.on("error", (err) => {
4418
4675
  logger.error("[auto-update] Git fetch error", { error: err.message });
4419
- resolve8("unknown");
4676
+ resolve9("unknown");
4420
4677
  });
4421
4678
  fetchChild.on("close", (code) => {
4422
4679
  if (code !== 0) {
@@ -4432,7 +4689,7 @@ async function getLatestDevelopVersion() {
4432
4689
  });
4433
4690
  tagChild.on("close", (tagCode) => {
4434
4691
  if (tagCode === 0 && tagOutput.trim()) {
4435
- resolve8(tagOutput.trim());
4692
+ resolve9(tagOutput.trim());
4436
4693
  } else {
4437
4694
  const fallbackChild = spawn2("git", ["describe", "--tags", "--abbrev=0", "develop"], {
4438
4695
  stdio: ["ignore", "pipe", "pipe"],
@@ -4444,18 +4701,18 @@ async function getLatestDevelopVersion() {
4444
4701
  });
4445
4702
  fallbackChild.on("close", (fallbackCode) => {
4446
4703
  if (fallbackCode === 0 && fallbackOutput.trim()) {
4447
- resolve8(fallbackOutput.trim());
4704
+ resolve9(fallbackOutput.trim());
4448
4705
  } else {
4449
4706
  logger.warn("[auto-update] No tags found on develop branch");
4450
- resolve8("unknown");
4707
+ resolve9("unknown");
4451
4708
  }
4452
4709
  });
4453
- fallbackChild.on("error", () => resolve8("unknown"));
4710
+ fallbackChild.on("error", () => resolve9("unknown"));
4454
4711
  }
4455
4712
  });
4456
4713
  tagChild.on("error", (err) => {
4457
4714
  logger.error("[auto-update] Git tag error", { error: err.message });
4458
- resolve8("unknown");
4715
+ resolve9("unknown");
4459
4716
  });
4460
4717
  });
4461
4718
  });
@@ -4472,7 +4729,7 @@ function createAutoUpdateRoutes(options = {}) {
4472
4729
  return;
4473
4730
  }
4474
4731
  try {
4475
- const latest = isDev ? await getLatestDevelopVersion() : await new Promise((resolve8, reject) => {
4732
+ const latest = isDev ? await getLatestDevelopVersion() : await new Promise((resolve9, reject) => {
4476
4733
  const win = process.platform === "win32";
4477
4734
  const child = spawn2(win ? "npm view openfox version" : "npm", win ? [] : ["view", "openfox", "version"], {
4478
4735
  stdio: ["ignore", "pipe", "pipe"],
@@ -4485,7 +4742,7 @@ function createAutoUpdateRoutes(options = {}) {
4485
4742
  });
4486
4743
  child.on("close", (code) => {
4487
4744
  if (code === 0) {
4488
- resolve8(stdout.trim());
4745
+ resolve9(stdout.trim());
4489
4746
  } else {
4490
4747
  reject(new Error(`npm view exited with code ${code}`));
4491
4748
  }
@@ -4500,12 +4757,13 @@ function createAutoUpdateRoutes(options = {}) {
4500
4757
  const latestVersion = latest.replace(/^v/, "");
4501
4758
  const isUpdateAvailable = currentVersion !== latestVersion;
4502
4759
  const now = Date.now();
4503
- versionCache.data = { current, latest, isUpdateAvailable, isService };
4760
+ versionCache.data = { current, latest: latestVersion, isUpdateAvailable, isService };
4504
4761
  versionCache.timestamp = now;
4505
- res.json({ current, latest, isUpdateAvailable, isService });
4762
+ res.json({ current, latest: latestVersion, isUpdateAvailable, isService });
4506
4763
  } catch (err) {
4507
4764
  logger.error("[auto-update] Error in version check", { error: err instanceof Error ? err.message : String(err) });
4508
- res.json({ current, latest: current, isUpdateAvailable: false, isService });
4765
+ const currentVersion = isDev ? current.replace(/-dev$/, "") : current;
4766
+ res.json({ current, latest: currentVersion, isUpdateAvailable: false, isService });
4509
4767
  }
4510
4768
  });
4511
4769
  router.post("/", async (req, res) => {
@@ -4536,9 +4794,9 @@ function createAutoUpdateRoutes(options = {}) {
4536
4794
  const timeout = setTimeout(() => {
4537
4795
  child.kill();
4538
4796
  }, UPDATE_TIMEOUT);
4539
- const exitCode = await new Promise((resolve8) => {
4540
- child.on("close", resolve8);
4541
- child.on("error", () => resolve8(1));
4797
+ const exitCode = await new Promise((resolve9) => {
4798
+ child.on("close", resolve9);
4799
+ child.on("error", () => resolve9(1));
4542
4800
  });
4543
4801
  clearTimeout(timeout);
4544
4802
  if (exitCode === 0) {
@@ -4710,26 +4968,26 @@ var ProviderRegistry = class {
4710
4968
  };
4711
4969
 
4712
4970
  // src/server/providers/plugins/loader.ts
4713
- import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
4714
- import { dirname as dirname6, join as join7, resolve as resolve5 } from "path";
4971
+ import { readdir as readdir3, readFile as readFile2, stat as stat3 } from "fs/promises";
4972
+ import { dirname as dirname6, join as join8, resolve as resolve6 } from "path";
4715
4973
  import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
4716
4974
  async function packageDirectories(root) {
4717
4975
  let entries;
4718
4976
  try {
4719
- entries = await readdir2(root, { withFileTypes: true });
4977
+ entries = await readdir3(root, { withFileTypes: true });
4720
4978
  } catch {
4721
4979
  return [];
4722
4980
  }
4723
4981
  const directories = [];
4724
4982
  for (const entry of entries) {
4725
- const entryPath = join7(root, entry.name);
4726
- const isDirectory = entry.isDirectory() || entry.isSymbolicLink() && (await stat2(entryPath).catch(() => void 0))?.isDirectory();
4983
+ const entryPath = join8(root, entry.name);
4984
+ const isDirectory = entry.isDirectory() || entry.isSymbolicLink() && (await stat3(entryPath).catch(() => void 0))?.isDirectory();
4727
4985
  if (!isDirectory) continue;
4728
4986
  if (entry.name.startsWith("@")) {
4729
- const scoped = await readdir2(entryPath, { withFileTypes: true }).catch(() => []);
4987
+ const scoped = await readdir3(entryPath, { withFileTypes: true }).catch(() => []);
4730
4988
  for (const child of scoped) {
4731
- const childPath = join7(entryPath, child.name);
4732
- const childIsDirectory = child.isDirectory() || child.isSymbolicLink() && (await stat2(childPath).catch(() => void 0))?.isDirectory();
4989
+ const childPath = join8(entryPath, child.name);
4990
+ const childIsDirectory = child.isDirectory() || child.isSymbolicLink() && (await stat3(childPath).catch(() => void 0))?.isDirectory();
4733
4991
  if (childIsDirectory) directories.push(childPath);
4734
4992
  }
4735
4993
  } else {
@@ -4741,16 +4999,16 @@ async function packageDirectories(root) {
4741
4999
  async function loadProviderPlugins(options) {
4742
5000
  const moduleDirectory = dirname6(fileURLToPath5(import.meta.url));
4743
5001
  const roots = [
4744
- join7(options.configDirectory, "plugins"),
4745
- join7(options.cwd ?? process.cwd(), "node_modules"),
4746
- resolve5(moduleDirectory, "node_modules"),
4747
- resolve5(moduleDirectory, "../../../../node_modules")
5002
+ join8(options.configDirectory, "plugins"),
5003
+ join8(options.cwd ?? process.cwd(), "node_modules"),
5004
+ resolve6(moduleDirectory, "node_modules"),
5005
+ resolve6(moduleDirectory, "../../../../node_modules")
4748
5006
  ];
4749
5007
  const seen = /* @__PURE__ */ new Set();
4750
5008
  const diagnostics = [];
4751
5009
  for (const root of roots) {
4752
5010
  for (const packageDir of await packageDirectories(root)) {
4753
- const manifestPath = join7(packageDir, "package.json");
5011
+ const manifestPath = join8(packageDir, "package.json");
4754
5012
  let manifest;
4755
5013
  try {
4756
5014
  manifest = JSON.parse(await readFile2(manifestPath, "utf8"));
@@ -4791,7 +5049,7 @@ async function loadProviderPlugins(options) {
4791
5049
  }
4792
5050
  };
4793
5051
  try {
4794
- const module = await import(pathToFileURL(join7(packageDir, plugin)).href);
5052
+ const module = await import(pathToFileURL(join8(packageDir, plugin)).href);
4795
5053
  if (typeof module.register !== "function") throw new Error("Plugin does not export register(registry)");
4796
5054
  await module.register(trackingRegistry);
4797
5055
  diagnostic.loaded = true;
@@ -4806,9 +5064,9 @@ async function loadProviderPlugins(options) {
4806
5064
  // src/server/routes/plugins.ts
4807
5065
  import { Router as Router11 } from "express";
4808
5066
  import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL2 } from "url";
4809
- import { dirname as dirname7, resolve as resolve6, join as join8 } from "path";
5067
+ import { dirname as dirname7, resolve as resolve7, join as join9 } from "path";
4810
5068
  import { existsSync } from "fs";
4811
- import { readFile as readFile3, readdir as readdir3, rm as rm2, rename as rename2 } from "fs/promises";
5069
+ import { readFile as readFile3, readdir as readdir4, rm as rm2, rename as rename2 } from "fs/promises";
4812
5070
  import { platform } from "os";
4813
5071
  import { execFile } from "child_process";
4814
5072
  import { promisify } from "util";
@@ -4834,9 +5092,9 @@ function createPluginRoutes(options) {
4834
5092
  return res.json({ plugins: registryCache.data });
4835
5093
  }
4836
5094
  const moduleDir = dirname7(fileURLToPath6(import.meta.url));
4837
- let registryPath = resolve6(moduleDir, "../plugins-registry.json");
5095
+ let registryPath = resolve7(moduleDir, "../plugins-registry.json");
4838
5096
  if (!existsSync(registryPath)) {
4839
- registryPath = resolve6(moduleDir, "../../../plugins-registry.json");
5097
+ registryPath = resolve7(moduleDir, "../../../plugins-registry.json");
4840
5098
  }
4841
5099
  const data = JSON.parse(await readFile3(registryPath, "utf8"));
4842
5100
  registryCache = { data, ts: now };
@@ -4859,9 +5117,9 @@ function createPluginRoutes(options) {
4859
5117
  if (!/^[a-zA-Z0-9_-]+$/.test(repoName)) {
4860
5118
  return res.status(400).json({ error: "Invalid repository name" });
4861
5119
  }
4862
- const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4863
- const targetDir = join8(pluginsDir, repoName);
4864
- const tmpDir = join8(pluginsDir, `.${repoName}-tmp-${Date.now()}`);
5120
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
5121
+ const targetDir = join9(pluginsDir, repoName);
5122
+ const tmpDir = join9(pluginsDir, `.${repoName}-tmp-${Date.now()}`);
4865
5123
  try {
4866
5124
  await execFileP("mkdir", ["-p", pluginsDir], { timeout: 5e3 });
4867
5125
  } catch {
@@ -4892,7 +5150,7 @@ function createPluginRoutes(options) {
4892
5150
  }
4893
5151
  if (!loadError) {
4894
5152
  try {
4895
- const manifest = JSON.parse(await readFile3(join8(targetDir, "package.json"), "utf8"));
5153
+ const manifest = JSON.parse(await readFile3(join9(targetDir, "package.json"), "utf8"));
4896
5154
  const pluginEntry = manifest.openfox?.plugin;
4897
5155
  const apiVersion = manifest.openfox?.apiVersion;
4898
5156
  if (!pluginEntry || !manifest.name) {
@@ -4900,7 +5158,7 @@ function createPluginRoutes(options) {
4900
5158
  } else if (apiVersion !== 1) {
4901
5159
  loadError = `Unsupported plugin API version: ${String(apiVersion)}`;
4902
5160
  } else {
4903
- const mod = await import(pathToFileURL2(join8(targetDir, pluginEntry)).href);
5161
+ const mod = await import(pathToFileURL2(join9(targetDir, pluginEntry)).href);
4904
5162
  if (typeof mod.register !== "function") {
4905
5163
  loadError = "Plugin does not export register(registry)";
4906
5164
  } else {
@@ -4949,13 +5207,13 @@ function createPluginRoutes(options) {
4949
5207
  }
4950
5208
  });
4951
5209
  router.get("/installed", async (_req, res) => {
4952
- const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
5210
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4953
5211
  try {
4954
- const entries = await readdir3(pluginsDir, { withFileTypes: true });
5212
+ const entries = await readdir4(pluginsDir, { withFileTypes: true });
4955
5213
  const installed = [];
4956
5214
  for (const entry of entries) {
4957
5215
  if (!entry.isDirectory()) continue;
4958
- const pkgPath = join8(pluginsDir, entry.name, "package.json");
5216
+ const pkgPath = join9(pluginsDir, entry.name, "package.json");
4959
5217
  let version = null;
4960
5218
  try {
4961
5219
  const pkg = JSON.parse(await readFile3(pkgPath, "utf8"));
@@ -4970,13 +5228,13 @@ function createPluginRoutes(options) {
4970
5228
  }
4971
5229
  });
4972
5230
  router.get("/open-folder", async (_req, res) => {
4973
- const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
5231
+ const pluginsDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
4974
5232
  await openFolder(pluginsDir, res);
4975
5233
  });
4976
5234
  router.get("/:name/open-folder", async (req, res) => {
4977
5235
  const name = req.params.name;
4978
5236
  if (!/^[a-zA-Z0-9_-]+$/.test(name)) return res.status(400).json({ error: "Invalid plugin name" });
4979
- const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
5237
+ const targetDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
4980
5238
  await openFolder(targetDir, res);
4981
5239
  });
4982
5240
  router.delete("/:name", async (req, res) => {
@@ -4984,7 +5242,7 @@ function createPluginRoutes(options) {
4984
5242
  if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
4985
5243
  return res.status(400).json({ error: "Invalid plugin name" });
4986
5244
  }
4987
- const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
5245
+ const targetDir = join9(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
4988
5246
  try {
4989
5247
  await rm2(targetDir, { recursive: true, force: true });
4990
5248
  for (let i = pluginDiagnostics.length - 1; i >= 0; i--) {
@@ -5144,7 +5402,7 @@ async function createServerHandle(config3) {
5144
5402
  setMcpTools(mcpTools);
5145
5403
  logger.info("MCP tools registered", { count: mcpTools.length });
5146
5404
  }
5147
- const { signalMcpReady } = await import("./server-OLRW27DH.js");
5405
+ const { signalMcpReady } = await import("./server-3XUD2NB7.js");
5148
5406
  signalMcpReady();
5149
5407
  });
5150
5408
  const app = express();
@@ -5206,7 +5464,7 @@ async function createServerHandle(config3) {
5206
5464
  res.json({ tools });
5207
5465
  });
5208
5466
  app.get("/api/projects", async (_req, res) => {
5209
- const { listProjects } = await import("./projects-WSVINK2C.js");
5467
+ const { listProjects } = await import("./projects-ZGJGICGT.js");
5210
5468
  const projects = listProjects();
5211
5469
  res.json({ projects });
5212
5470
  });
@@ -5215,7 +5473,7 @@ async function createServerHandle(config3) {
5215
5473
  if (!name || !workdir) {
5216
5474
  return res.status(400).json({ error: "name and workdir are required" });
5217
5475
  }
5218
- const { createDirectoryWithGit } = await import("./project-creator-C22J43BC.js");
5476
+ const { createDirectoryWithGit } = await import("./project-creator-NNUITNUI.js");
5219
5477
  try {
5220
5478
  const project = await createDirectoryWithGit(name, workdir);
5221
5479
  res.status(201).json({ project });
@@ -5260,7 +5518,7 @@ async function createServerHandle(config3) {
5260
5518
  }
5261
5519
  });
5262
5520
  app.get("/api/projects/:id", async (req, res) => {
5263
- const { getProject: getProject2 } = await import("./projects-WSVINK2C.js");
5521
+ const { getProject: getProject2 } = await import("./projects-ZGJGICGT.js");
5264
5522
  const project = getProject2(req.params.id);
5265
5523
  if (!project) {
5266
5524
  return res.status(404).json({ error: "Project not found" });
@@ -5268,7 +5526,7 @@ async function createServerHandle(config3) {
5268
5526
  res.json({ project });
5269
5527
  });
5270
5528
  app.put("/api/projects/:id", async (req, res) => {
5271
- const { updateProject } = await import("./projects-WSVINK2C.js");
5529
+ const { updateProject } = await import("./projects-ZGJGICGT.js");
5272
5530
  const { name, customInstructions, dangerLevel } = req.body;
5273
5531
  const updates = {};
5274
5532
  if (name !== void 0) updates.name = name;
@@ -5281,7 +5539,7 @@ async function createServerHandle(config3) {
5281
5539
  res.json({ project: updated });
5282
5540
  });
5283
5541
  app.delete("/api/projects/:id", async (req, res) => {
5284
- const { getProject: getProject2, deleteProject } = await import("./projects-WSVINK2C.js");
5542
+ const { getProject: getProject2, deleteProject } = await import("./projects-ZGJGICGT.js");
5285
5543
  const project = getProject2(req.params.id);
5286
5544
  if (!project) {
5287
5545
  return res.status(404).json({ error: "Project not found" });
@@ -5290,7 +5548,7 @@ async function createServerHandle(config3) {
5290
5548
  res.json({ success: true });
5291
5549
  });
5292
5550
  app.put("/api/projects/:id/star", async (req, res) => {
5293
- const { toggleStar } = await import("./projects-WSVINK2C.js");
5551
+ const { toggleStar } = await import("./projects-ZGJGICGT.js");
5294
5552
  const { isStarred } = req.body;
5295
5553
  if (typeof isStarred !== "boolean") {
5296
5554
  return res.status(400).json({ error: "isStarred is required and must be a boolean" });
@@ -5302,37 +5560,60 @@ async function createServerHandle(config3) {
5302
5560
  res.json({ project });
5303
5561
  });
5304
5562
  app.get("/api/projects/:id/branches", async (req, res) => {
5305
- const { getProject: getProject2 } = await import("./projects-WSVINK2C.js");
5563
+ const { getProject: getProject2 } = await import("./projects-ZGJGICGT.js");
5306
5564
  const project = getProject2(req.params.id);
5307
5565
  if (!project) return res.status(404).json({ error: "Project not found" });
5308
- const { listBranches } = await import("./workspace-6QTTUMMW.js");
5566
+ const { listBranches } = await import("./workspace-J74ZMSOJ.js");
5309
5567
  const branches = await listBranches(project.workdir);
5310
5568
  res.json({ branches });
5311
5569
  });
5312
5570
  app.post("/api/projects/:id/checkout", async (req, res) => {
5313
- const { getProject: getProject2 } = await import("./projects-WSVINK2C.js");
5571
+ const { getProject: getProject2 } = await import("./projects-ZGJGICGT.js");
5314
5572
  const project = getProject2(req.params.id);
5315
5573
  if (!project) return res.status(404).json({ error: "Project not found" });
5316
5574
  const { branch } = req.body;
5317
5575
  if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
5318
- const { checkoutBranch } = await import("./workspace-6QTTUMMW.js");
5576
+ const { checkoutBranch } = await import("./workspace-J74ZMSOJ.js");
5319
5577
  try {
5320
5578
  await checkoutBranch(project.workdir, branch);
5579
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-SFG42M4W.js");
5580
+ const allSessions = sessionManager.listSessions();
5581
+ for (const s of allSessions) {
5582
+ const effectiveWorkdir = s.workspace ?? s.workdir;
5583
+ if (effectiveWorkdir === project.workdir) {
5584
+ updateSessionBranch2(s.id, branch);
5585
+ sessionManager.emitBranchChange(s.id);
5586
+ }
5587
+ }
5321
5588
  res.json({ branch });
5322
5589
  } catch (err) {
5323
5590
  res.status(400).json({ error: err instanceof Error ? err.message : "Failed to checkout branch" });
5324
5591
  }
5325
5592
  });
5326
5593
  app.post("/api/projects/:id/checkout-new", async (req, res) => {
5327
- const { getProject: getProject2 } = await import("./projects-WSVINK2C.js");
5594
+ const { getProject: getProject2 } = await import("./projects-ZGJGICGT.js");
5328
5595
  const project = getProject2(req.params.id);
5329
5596
  if (!project) return res.status(404).json({ error: "Project not found" });
5330
- const { name } = req.body;
5597
+ const { name, sourceBranch } = req.body;
5331
5598
  if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
5332
- const { createBranch } = await import("./workspace-6QTTUMMW.js");
5599
+ const { createBranch, resolveAndValidateSourceBranch: resolveAndValidateSourceBranch2, validateRef: validateRef2 } = await import("./workspace-J74ZMSOJ.js");
5333
5600
  try {
5334
- await createBranch(project.workdir, name);
5335
- res.json({ branch: name });
5601
+ await validateRef2(project.workdir, name);
5602
+ let sb;
5603
+ if (sourceBranch) {
5604
+ sb = await resolveAndValidateSourceBranch2(project.workdir, sourceBranch, project.workdir);
5605
+ }
5606
+ await createBranch(project.workdir, name, sb);
5607
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-SFG42M4W.js");
5608
+ const allSessions = sessionManager.listSessions();
5609
+ for (const s of allSessions) {
5610
+ const effectiveWorkdir = s.workspace ?? s.workdir;
5611
+ if (effectiveWorkdir === project.workdir) {
5612
+ updateSessionBranch2(s.id, name);
5613
+ sessionManager.emitBranchChange(s.id);
5614
+ }
5615
+ }
5616
+ res.json({ branch: name, sourceBranch: sourceBranch ?? null });
5336
5617
  } catch (err) {
5337
5618
  res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create branch" });
5338
5619
  }
@@ -5341,9 +5622,13 @@ async function createServerHandle(config3) {
5341
5622
  const session = sessionManager.getSession(req.params.id);
5342
5623
  if (!session) return res.status(404).json({ error: "Session not found" });
5343
5624
  const effectiveWorkdir = session.workspace ?? session.workdir;
5344
- const { listBranches } = await import("./workspace-6QTTUMMW.js");
5345
- const branches = await listBranches(effectiveWorkdir);
5346
- res.json({ branches });
5625
+ const { listBranches, getDefaultBranch: getDefaultBranch2 } = await import("./workspace-J74ZMSOJ.js");
5626
+ const [branches, defaultBranch] = await Promise.all([
5627
+ listBranches(effectiveWorkdir),
5628
+ getDefaultBranch2(session.workdir)
5629
+ // project root, not workspace, for real upstream origin/HEAD
5630
+ ]);
5631
+ res.json({ branches, defaultBranch });
5347
5632
  });
5348
5633
  app.post("/api/sessions/:id/checkout", async (req, res) => {
5349
5634
  const session = sessionManager.getSession(req.params.id);
@@ -5351,10 +5636,21 @@ async function createServerHandle(config3) {
5351
5636
  const { branch } = req.body;
5352
5637
  if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
5353
5638
  const effectiveWorkdir = session.workspace ?? session.workdir;
5354
- const { checkoutBranch, validateRef } = await import("./workspace-6QTTUMMW.js");
5639
+ const { checkoutBranch, validateRef: validateRef2 } = await import("./workspace-J74ZMSOJ.js");
5640
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-SFG42M4W.js");
5355
5641
  try {
5356
- await validateRef(effectiveWorkdir, branch);
5642
+ await validateRef2(effectiveWorkdir, branch);
5357
5643
  await checkoutBranch(effectiveWorkdir, branch);
5644
+ updateSessionBranch2(req.params.id, branch);
5645
+ if (session.workspace) {
5646
+ const all = sessionManager.listSessions();
5647
+ for (const s of all) {
5648
+ if (s.id !== req.params.id && s.workspace === session.workspace) {
5649
+ updateSessionBranch2(s.id, branch);
5650
+ sessionManager.emitBranchChange(s.id);
5651
+ }
5652
+ }
5653
+ }
5358
5654
  res.json({ branch });
5359
5655
  } catch (err) {
5360
5656
  res.status(400).json({ error: err instanceof Error ? err.message : "Failed to checkout branch" });
@@ -5363,30 +5659,48 @@ async function createServerHandle(config3) {
5363
5659
  app.post("/api/sessions/:id/checkout-new", async (req, res) => {
5364
5660
  const session = sessionManager.getSession(req.params.id);
5365
5661
  if (!session) return res.status(404).json({ error: "Session not found" });
5366
- const { name } = req.body;
5662
+ const { name, sourceBranch } = req.body;
5367
5663
  if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
5368
5664
  const effectiveWorkdir = session.workspace ?? session.workdir;
5369
- const { createBranch, validateRef } = await import("./workspace-6QTTUMMW.js");
5665
+ const { validateRef: validateRef2 } = await import("./workspace-J74ZMSOJ.js");
5666
+ const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-SFG42M4W.js");
5370
5667
  try {
5371
- await validateRef(effectiveWorkdir, name);
5372
- await createBranch(effectiveWorkdir, name);
5373
- res.json({ branch: name });
5668
+ await validateRef2(effectiveWorkdir, name);
5669
+ if (sourceBranch) {
5670
+ const { resolveAndValidateSourceBranch: resolveAndValidateSourceBranch2, createBranch } = await import("./workspace-J74ZMSOJ.js");
5671
+ const sb = await resolveAndValidateSourceBranch2(effectiveWorkdir, sourceBranch, session.workdir);
5672
+ await createBranch(effectiveWorkdir, name, sb);
5673
+ } else {
5674
+ const { createBranch } = await import("./workspace-J74ZMSOJ.js");
5675
+ await createBranch(effectiveWorkdir, name);
5676
+ }
5677
+ updateSessionBranch2(req.params.id, name);
5678
+ if (session.workspace) {
5679
+ const all = sessionManager.listSessions();
5680
+ for (const s of all) {
5681
+ if (s.id !== req.params.id && s.workspace === session.workspace) {
5682
+ updateSessionBranch2(s.id, name);
5683
+ sessionManager.emitBranchChange(s.id);
5684
+ }
5685
+ }
5686
+ }
5687
+ res.json({ branch: name, sourceBranch: sourceBranch ?? null });
5374
5688
  } catch (err) {
5375
5689
  res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create branch" });
5376
5690
  }
5377
5691
  });
5378
5692
  app.get("/api/projects/:id/workspaces", async (req, res) => {
5379
- const { getProject: getProject2 } = await import("./projects-WSVINK2C.js");
5693
+ const { getProject: getProject2 } = await import("./projects-ZGJGICGT.js");
5380
5694
  const project = getProject2(req.params.id);
5381
5695
  if (!project) return res.status(404).json({ error: "Project not found" });
5382
- const { listWorkspaces } = await import("./workspace-6QTTUMMW.js");
5383
- const all = await listWorkspaces(project.name);
5696
+ const { listWorkspaces } = await import("./workspace-J74ZMSOJ.js");
5697
+ const all = await listWorkspaces(project.name, project.workdir);
5384
5698
  const workspacesList = all.filter((ws) => ws.path !== project.workdir);
5385
5699
  res.json({ workspaces: workspacesList });
5386
5700
  });
5387
5701
  app.get("/api/sessions", async (req, res) => {
5388
- const { getRecentUserPromptsForSession } = await import("./events-FLWRLM6V.js");
5389
- const { getPendingConfirmationsBySession } = await import("./path-security-ZROWNL22.js");
5702
+ const { getRecentUserPromptsForSession } = await import("./events-KNOZX7YG.js");
5703
+ const { getPendingConfirmationsBySession } = await import("./path-security-HUXQHEQ5.js");
5390
5704
  const projectId = req.query["projectId"];
5391
5705
  const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
5392
5706
  const offset = parseInt(req.query["offset"]) || 0;
@@ -5424,7 +5738,7 @@ async function createServerHandle(config3) {
5424
5738
  }
5425
5739
  const { providerId, model } = parseDefaultModelSelection(config3.defaultModelSelection);
5426
5740
  const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
5427
- wssExports.broadcastAll({
5741
+ wssExports.broadcastForProject(projectId, session.id, {
5428
5742
  type: "session.created",
5429
5743
  sessionId: session.id,
5430
5744
  payload: {
@@ -5452,10 +5766,10 @@ async function createServerHandle(config3) {
5452
5766
  app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
5453
5767
  const session = sessionManager.getSession(req.params.id);
5454
5768
  if (!session) return res.status(404).json({ error: "Session not found" });
5455
- const { target, branch } = req.body;
5769
+ const { target, branch, sourceBranch } = req.body;
5456
5770
  if (!target || typeof target !== "string") return res.status(400).json({ error: "target is required" });
5457
5771
  try {
5458
- const updated = await sessionManager.switchWorkspace(req.params.id, target, branch);
5772
+ const updated = await sessionManager.switchWorkspace(req.params.id, target, branch, sourceBranch);
5459
5773
  res.json({ session: updated });
5460
5774
  } catch (err) {
5461
5775
  res.status(400).json({ error: err instanceof Error ? err.message : "Failed to switch workspace" });
@@ -5474,21 +5788,32 @@ async function createServerHandle(config3) {
5474
5788
  }
5475
5789
  });
5476
5790
  app.get("/api/sessions/:id", async (req, res) => {
5477
- const { getEventStore: getEventStore2 } = await import("./events-FLWRLM6V.js");
5478
- const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-ONH3D4OK.js");
5479
- const { getPendingQuestionsForSession } = await import("./tools-T7S45DOQ.js");
5791
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot } = await import("./events-KNOZX7YG.js");
5792
+ const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-OPP2BVUB.js");
5793
+ const { getPendingQuestionsForSession } = await import("./tools-HGKUD327.js");
5794
+ const { getMaxVisibleItems } = await import("./settings-6M55N4Q2.js");
5480
5795
  const session = sessionManager.getSession(req.params.id);
5481
5796
  if (!session) {
5482
5797
  return res.status(404).json({ error: "Session not found" });
5483
5798
  }
5484
5799
  const eventStore = getEventStore2();
5485
- const events = eventStore.getEvents(req.params.id);
5486
- const messages = buildMessagesFromStoredEvents(events);
5800
+ const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(req.params.id);
5801
+ const events = combineEventsWithSnapshot(req.params.id, snapshot, eventsSinceSnapshot);
5802
+ const maxVisibleItems = req.query["full"] === "true" ? void 0 : getMaxVisibleItems() || void 0;
5803
+ const { messages, hiddenCount } = buildMessagesFromStoredEvents(events, maxVisibleItems);
5487
5804
  const contextState = sessionManager.getContextState(req.params.id);
5488
5805
  const queueState = sessionManager.getQueueState(req.params.id);
5489
5806
  const pendingQuestions = getPendingQuestionsForSession(req.params.id);
5490
5807
  const pendingConfirmations = foldPendingConfirmations(events);
5491
- res.json({ session, messages, contextState, queueState, pendingQuestions, pendingConfirmations });
5808
+ res.json({
5809
+ session,
5810
+ messages,
5811
+ hiddenCount,
5812
+ contextState,
5813
+ queueState,
5814
+ pendingQuestions,
5815
+ pendingConfirmations
5816
+ });
5492
5817
  });
5493
5818
  app.delete("/api/sessions/:id", async (req, res) => {
5494
5819
  const sessionId = req.params["id"];
@@ -5496,8 +5821,8 @@ async function createServerHandle(config3) {
5496
5821
  if (!session) {
5497
5822
  return res.status(404).json({ error: "Session not found" });
5498
5823
  }
5499
- const { stopSessionExecution } = await import("./chat-handler-FNRKORKP.js");
5500
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-T7S45DOQ.js");
5824
+ const { stopSessionExecution } = await import("./chat-handler-5ZHPYU24.js");
5825
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-HGKUD327.js");
5501
5826
  sessionManager.clearMessageQueue(sessionId);
5502
5827
  stopSessionExecution(sessionId, sessionManager);
5503
5828
  abortSession(sessionId);
@@ -5526,8 +5851,9 @@ async function createServerHandle(config3) {
5526
5851
  res.json({ success: true });
5527
5852
  });
5528
5853
  app.post("/api/sessions/:id/provider", async (req, res) => {
5529
- const { getEventStore: getEventStore2 } = await import("./events-FLWRLM6V.js");
5530
- const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
5854
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-KNOZX7YG.js");
5855
+ const { buildMessagesFromStoredEvents } = await import("./folding-OPP2BVUB.js");
5856
+ const { getMaxVisibleItems } = await import("./settings-6M55N4Q2.js");
5531
5857
  const sessionId = req.params.id;
5532
5858
  const session = sessionManager.getSession(sessionId);
5533
5859
  if (!session) {
@@ -5542,10 +5868,12 @@ async function createServerHandle(config3) {
5542
5868
  sessionManager.setSessionProvider(sessionId, providerId, resolvedModel);
5543
5869
  const contextState = sessionManager.getContextState(sessionId);
5544
5870
  const eventStore = getEventStore2();
5545
- const events = eventStore.getEvents(sessionId);
5546
- const messages = buildMessagesFromStoredEvents(events);
5871
+ const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
5872
+ const events = combineEv(sessionId, snapshot, eventsSinceSnapshot);
5873
+ const maxVisibleItems = getMaxVisibleItems();
5874
+ const { messages, hiddenCount } = buildMessagesFromStoredEvents(events, maxVisibleItems || void 0);
5547
5875
  const updatedSession = sessionManager.getSession(sessionId);
5548
- res.json({ session: updatedSession, messages, contextState });
5876
+ res.json({ session: updatedSession, messages, hiddenCount, contextState });
5549
5877
  });
5550
5878
  app.post("/api/default-model", async (req, res) => {
5551
5879
  const { providerId, model } = req.body;
@@ -5638,8 +5966,9 @@ async function createServerHandle(config3) {
5638
5966
  res.json({ success: true });
5639
5967
  });
5640
5968
  app.put("/api/sessions/:id/mode", async (req, res) => {
5641
- const { getEventStore: getEventStore2 } = await import("./events-FLWRLM6V.js");
5642
- const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
5969
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-KNOZX7YG.js");
5970
+ const { buildMessagesFromStoredEvents } = await import("./folding-OPP2BVUB.js");
5971
+ const { getMaxVisibleItems } = await import("./settings-6M55N4Q2.js");
5643
5972
  const sessionId = req.params.id;
5644
5973
  const session = sessionManager.getSession(sessionId);
5645
5974
  if (!session) {
@@ -5656,10 +5985,12 @@ async function createServerHandle(config3) {
5656
5985
  }
5657
5986
  sessionManager.setMode(sessionId, mode);
5658
5987
  const eventStore = getEventStore2();
5659
- const events = eventStore.getEvents(sessionId);
5660
- const messages = buildMessagesFromStoredEvents(events);
5988
+ const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
5989
+ const events = combineEv(sessionId, snapshot, eventsSinceSnapshot);
5990
+ const maxVisibleItems = getMaxVisibleItems();
5991
+ const { messages, hiddenCount } = buildMessagesFromStoredEvents(events, maxVisibleItems || void 0);
5661
5992
  const updatedSession = sessionManager.getSession(sessionId);
5662
- res.json({ session: updatedSession, messages });
5993
+ res.json({ session: updatedSession, messages, hiddenCount });
5663
5994
  });
5664
5995
  app.put("/api/sessions/:id/danger-level", async (req, res) => {
5665
5996
  const sessionId = req.params.id;
@@ -5692,29 +6023,50 @@ async function createServerHandle(config3) {
5692
6023
  app.post("/api/sessions/:id/confirm-path", async (req, res) => {
5693
6024
  const sessionId = req.params.id;
5694
6025
  const { callId, approved, alwaysAllow } = req.body;
5695
- if (!callId || approved === void 0) {
5696
- return res.status(400).json({ error: "callId and approved are required" });
6026
+ if (!callId || typeof approved !== "boolean") {
6027
+ return res.status(400).json({ error: "callId and approved (boolean) are required" });
6028
+ }
6029
+ if (alwaysAllow !== void 0 && typeof alwaysAllow !== "boolean") {
6030
+ return res.status(400).json({ error: "alwaysAllow must be a boolean if provided" });
6031
+ }
6032
+ const { providePathConfirmation, getConfirmationSessionId } = await import("./tools-HGKUD327.js");
6033
+ const pendingSessionId = getConfirmationSessionId(callId);
6034
+ if (!pendingSessionId) {
6035
+ return res.status(404).json({ error: "No pending path confirmation with that ID" });
6036
+ }
6037
+ if (pendingSessionId !== sessionId) {
6038
+ return res.status(403).json({ error: "Confirmation does not belong to this session" });
5697
6039
  }
5698
- const { providePathConfirmation } = await import("./tools-T7S45DOQ.js");
5699
6040
  const result = providePathConfirmation(callId, approved, alwaysAllow);
5700
6041
  if (!result.found) {
5701
6042
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
5702
6043
  }
5703
- const { getEventStore: getEventStore2 } = await import("./events-FLWRLM6V.js");
5704
- const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-ONH3D4OK.js");
5705
- const { createSessionStateMessage } = await import("./protocol-EWEVW65B.js");
5706
- const { getPendingQuestionsForSession } = await import("./tools-T7S45DOQ.js");
6044
+ const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-KNOZX7YG.js");
6045
+ const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-OPP2BVUB.js");
6046
+ const { createSessionStateMessage } = await import("./protocol-Q7X4NEME.js");
6047
+ const { getPendingQuestionsForSession } = await import("./tools-HGKUD327.js");
6048
+ const { getMaxVisibleItems } = await import("./settings-6M55N4Q2.js");
5707
6049
  const eventStore = getEventStore2();
5708
- const events = eventStore.getEvents(sessionId);
5709
- const messages = buildMessagesFromStoredEvents(events);
6050
+ const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
6051
+ const events = combineEvents(sessionId, snapshot, eventsSinceSnapshot);
6052
+ const maxVisibleItems = getMaxVisibleItems();
6053
+ const { messages, hiddenCount } = buildMessagesFromStoredEvents(events, maxVisibleItems || void 0);
5710
6054
  const pendingConfirmations = foldPendingConfirmations(events);
5711
6055
  const pendingQuestions = getPendingQuestionsForSession(sessionId);
5712
6056
  const session = sessionManager.getSession(sessionId);
5713
6057
  if (session) {
5714
- const stateMsg = createSessionStateMessage(session, messages, pendingConfirmations, pendingQuestions);
6058
+ const stateMsg = createSessionStateMessage(
6059
+ session,
6060
+ messages,
6061
+ pendingConfirmations,
6062
+ pendingQuestions,
6063
+ void 0,
6064
+ void 0,
6065
+ hiddenCount
6066
+ );
5715
6067
  wssExports.broadcastForSession(sessionId, { ...stateMsg, sessionId });
5716
6068
  }
5717
- wssExports.broadcastAll({
6069
+ wssExports.broadcastForSession(sessionId, {
5718
6070
  type: "session.confirmation_resolved",
5719
6071
  sessionId,
5720
6072
  payload: { sessionId, callId }
@@ -5729,7 +6081,7 @@ async function createServerHandle(config3) {
5729
6081
  if (!skip && typeof answer !== "string") {
5730
6082
  return res.status(400).json({ error: "answer is required when not skipping" });
5731
6083
  }
5732
- const { provideAnswer } = await import("./tools-T7S45DOQ.js");
6084
+ const { provideAnswer } = await import("./tools-HGKUD327.js");
5733
6085
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
5734
6086
  if (!found) {
5735
6087
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -5757,7 +6109,7 @@ async function createServerHandle(config3) {
5757
6109
  if (!session) {
5758
6110
  return res.status(404).json({ error: "Session not found" });
5759
6111
  }
5760
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-7XDMSPIC.js");
6112
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-6M55N4Q2.js");
5761
6113
  if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
5762
6114
  return res.json({ success: false, reason: "disabled" });
5763
6115
  }
@@ -5789,7 +6141,7 @@ async function createServerHandle(config3) {
5789
6141
  backend: activeProvider?.backend ?? llmClient.getBackend(),
5790
6142
  model: llmClient.getModel()
5791
6143
  };
5792
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-67BZJEOO.js");
6144
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-L6LX5BV7.js");
5793
6145
  runAgentTurn(
5794
6146
  {
5795
6147
  sessionManager,
@@ -5827,15 +6179,15 @@ async function createServerHandle(config3) {
5827
6179
  if (!session) {
5828
6180
  return res.status(404).json({ error: "Session not found" });
5829
6181
  }
5830
- const { stopSessionExecution } = await import("./chat-handler-FNRKORKP.js");
5831
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-T7S45DOQ.js");
6182
+ const { stopSessionExecution } = await import("./chat-handler-5ZHPYU24.js");
6183
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-HGKUD327.js");
5832
6184
  const queuedMessages = sessionManager.getQueueState(sessionId);
5833
6185
  sessionManager.clearMessageQueue(sessionId);
5834
6186
  stopSessionExecution(sessionId, sessionManager);
5835
6187
  abortSession(sessionId);
5836
6188
  cancelQuestionsForSession(sessionId, "Session stopped by user");
5837
6189
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
5838
- const eventStore = (await import("./events-FLWRLM6V.js")).getEventStore();
6190
+ const eventStore = (await import("./events-KNOZX7YG.js")).getEventStore();
5839
6191
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
5840
6192
  res.json({ success: true, queuedMessages });
5841
6193
  });
@@ -5849,7 +6201,7 @@ async function createServerHandle(config3) {
5849
6201
  if (typeof messageIndex !== "number" || messageIndex < 0) {
5850
6202
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
5851
6203
  }
5852
- const { truncateSessionMessages } = await import("./events-FLWRLM6V.js");
6204
+ const { truncateSessionMessages } = await import("./events-KNOZX7YG.js");
5853
6205
  truncateSessionMessages(sessionId, messageIndex);
5854
6206
  res.json({ success: true });
5855
6207
  });
@@ -5866,11 +6218,11 @@ async function createServerHandle(config3) {
5866
6218
  if (content !== void 0 && (typeof content !== "string" || !content.trim())) {
5867
6219
  return res.status(400).json({ error: "content must be a non-empty string if provided" });
5868
6220
  }
5869
- const { getEventStore: getEventStore2 } = await import("./events-FLWRLM6V.js");
5870
- const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
6221
+ const { getEventStore: getEventStore2 } = await import("./events-KNOZX7YG.js");
6222
+ const { buildMessagesFromStoredEvents } = await import("./folding-OPP2BVUB.js");
5871
6223
  const eventStore = getEventStore2();
5872
6224
  const events = eventStore.getEvents(sessionId);
5873
- const messages = buildMessagesFromStoredEvents(events);
6225
+ const { messages } = buildMessagesFromStoredEvents(events);
5874
6226
  const msgIndex = messages.findIndex((m) => m.id === messageId);
5875
6227
  if (msgIndex === -1) {
5876
6228
  return res.status(400).json({ error: "Message not found" });
@@ -5879,7 +6231,7 @@ async function createServerHandle(config3) {
5879
6231
  if (msg.role !== "user" || msg.isSystemGenerated) {
5880
6232
  return res.status(400).json({ error: "Can only replay user messages" });
5881
6233
  }
5882
- const { truncateSessionMessages } = await import("./events-FLWRLM6V.js");
6234
+ const { truncateSessionMessages } = await import("./events-KNOZX7YG.js");
5883
6235
  truncateSessionMessages(sessionId, msgIndex - 1);
5884
6236
  sessionManager.queueMessage(sessionId, "asap", content ?? msg.content, msg.attachments, msg.messageKind);
5885
6237
  res.json({ success: true });
@@ -5911,7 +6263,7 @@ async function createServerHandle(config3) {
5911
6263
  res.json({ accepted: true });
5912
6264
  });
5913
6265
  app.get("/api/settings", async (req, res) => {
5914
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-7XDMSPIC.js");
6266
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6M55N4Q2.js");
5915
6267
  const keysParam = req.query["keys"];
5916
6268
  if (!keysParam) {
5917
6269
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -5924,19 +6276,19 @@ async function createServerHandle(config3) {
5924
6276
  res.json(result);
5925
6277
  });
5926
6278
  app.get("/api/settings/:key", async (req, res) => {
5927
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-7XDMSPIC.js");
6279
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6M55N4Q2.js");
5928
6280
  const key = req.params.key;
5929
6281
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
5930
6282
  res.json({ key, value });
5931
6283
  });
5932
6284
  app.get("/api/settings/:key", async (req, res) => {
5933
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-7XDMSPIC.js");
6285
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6M55N4Q2.js");
5934
6286
  const key = req.params.key;
5935
6287
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
5936
6288
  res.json({ key, value });
5937
6289
  });
5938
6290
  app.put("/api/settings/:key", async (req, res) => {
5939
- const { setSetting: setSetting2 } = await import("./settings-7XDMSPIC.js");
6291
+ const { setSetting: setSetting2 } = await import("./settings-6M55N4Q2.js");
5940
6292
  const key = req.params.key;
5941
6293
  const { value } = req.body;
5942
6294
  if (value === void 0) {
@@ -5948,14 +6300,14 @@ async function createServerHandle(config3) {
5948
6300
  app.get("/api/tools/rtk-check", async (_req, res) => {
5949
6301
  const { spawn: spawn3 } = await import("child_process");
5950
6302
  try {
5951
- const available = await new Promise((resolve8) => {
6303
+ const available = await new Promise((resolve9) => {
5952
6304
  const proc = spawn3("rtk", ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
5953
6305
  let out = "";
5954
6306
  proc.stdout?.on("data", (d) => {
5955
6307
  out += d.toString();
5956
6308
  });
5957
- proc.on("error", () => resolve8(false));
5958
- proc.on("close", (code) => resolve8(code === 0 && out.startsWith("rtk ")));
6309
+ proc.on("error", () => resolve9(false));
6310
+ proc.on("close", (code) => resolve9(code === 0 && out.startsWith("rtk ")));
5959
6311
  });
5960
6312
  res.json({ available });
5961
6313
  } catch {
@@ -5963,7 +6315,7 @@ async function createServerHandle(config3) {
5963
6315
  }
5964
6316
  });
5965
6317
  app.get("/api/tools/shells", async (_req, res) => {
5966
- const { listAvailableShells } = await import("./platform-QGXO3CNR.js");
6318
+ const { listAvailableShells } = await import("./platform-VBNNMTR5.js");
5967
6319
  res.json({ shells: listAvailableShells() });
5968
6320
  });
5969
6321
  app.get("/api/config", async (_req, res) => {
@@ -6455,7 +6807,7 @@ async function createServerHandle(config3) {
6455
6807
  });
6456
6808
  async function rebuildMcpTools() {
6457
6809
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
6458
- const { setMcpTools: setMcpTools2 } = await import("./tools-T7S45DOQ.js");
6810
+ const { setMcpTools: setMcpTools2 } = await import("./tools-HGKUD327.js");
6459
6811
  const mcpTools = createMcpTools2(mcpManager);
6460
6812
  setMcpTools2(mcpTools);
6461
6813
  }
@@ -6702,13 +7054,13 @@ async function createServerHandle(config3) {
6702
7054
  })
6703
7055
  );
6704
7056
  app.get("/api/sessions/:id/background-processes", async (req, res) => {
6705
- const { getSessionProcesses } = await import("./manager-OPMCSYN2.js");
7057
+ const { getSessionProcesses } = await import("./manager-ATWZUL3O.js");
6706
7058
  const sessionId = req.params.id;
6707
7059
  const processes = getSessionProcesses(sessionId);
6708
7060
  res.json({ processes });
6709
7061
  });
6710
7062
  app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
6711
- const { stopProcess } = await import("./manager-OPMCSYN2.js");
7063
+ const { stopProcess } = await import("./manager-ATWZUL3O.js");
6712
7064
  const sessionId = req.params.id;
6713
7065
  const processId = req.params.processId;
6714
7066
  const session = sessionManager.getSession(sessionId);
@@ -6728,14 +7080,14 @@ async function createServerHandle(config3) {
6728
7080
  });
6729
7081
  app.use("/api/directories", createDirectoryRoutes());
6730
7082
  app.use("/api/files", createFileSearchRoutes());
6731
- const webDir = resolve7(__dirname3, "../../web");
7083
+ const webDir = resolve8(__dirname3, "../../web");
6732
7084
  const isDev = config3.mode === "development";
6733
7085
  let viteServer;
6734
7086
  if (isDev) {
6735
7087
  logger.info("Dev mode: using Vite middleware");
6736
7088
  viteServer = await createViteServer({
6737
7089
  root: webDir,
6738
- configFile: resolve7(__dirname3, "../../web/vite.config.ts"),
7090
+ configFile: resolve8(__dirname3, "../../web/vite.config.ts"),
6739
7091
  server: { middlewareMode: true },
6740
7092
  appType: "spa",
6741
7093
  logLevel: "warn"
@@ -6755,7 +7107,7 @@ async function createServerHandle(config3) {
6755
7107
  }
6756
7108
  });
6757
7109
  app.get("/fox.svg", (_req, res) => {
6758
- readFile4(join9(webDir, "fox.svg")).then((content) => {
7110
+ readFile4(join10(webDir, "fox.svg")).then((content) => {
6759
7111
  res.set("Content-Type", "image/svg+xml");
6760
7112
  res.send(content);
6761
7113
  }).catch(() => {
@@ -6764,7 +7116,7 @@ async function createServerHandle(config3) {
6764
7116
  });
6765
7117
  app.use(
6766
7118
  "/sounds",
6767
- express.static(join9(webDir, "public", "sounds"), {
7119
+ express.static(join10(webDir, "public", "sounds"), {
6768
7120
  setHeaders: (res) => {
6769
7121
  res.set("Content-Type", "audio/mpeg");
6770
7122
  }
@@ -6773,13 +7125,13 @@ async function createServerHandle(config3) {
6773
7125
  app.use("/__inspect__.js", (_req, res) => {
6774
7126
  res.set("Access-Control-Allow-Origin", "*");
6775
7127
  res.set("Content-Type", "application/javascript");
6776
- readFile4(join9(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
7128
+ readFile4(join10(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6777
7129
  });
6778
7130
  app.get("/*path", (req, res) => {
6779
7131
  if (req.path.startsWith("/api/")) {
6780
7132
  return;
6781
7133
  }
6782
- readFile4(join9(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
7134
+ readFile4(join10(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6783
7135
  logger.error("Error serving index.html", { error: err });
6784
7136
  res.status(500).send("Server error");
6785
7137
  });
@@ -6787,10 +7139,10 @@ async function createServerHandle(config3) {
6787
7139
  logger.info("Vite middleware ready", { port: config3.server.port });
6788
7140
  }
6789
7141
  if (!isDev) {
6790
- const distWebDir = resolve7(__dirname3, "web");
7142
+ const distWebDir = resolve8(__dirname3, "web");
6791
7143
  app.use(
6792
7144
  "/assets",
6793
- express.static(join9(distWebDir, "assets"), {
7145
+ express.static(join10(distWebDir, "assets"), {
6794
7146
  setHeaders: (res, filepath) => {
6795
7147
  if (filepath.endsWith(".css")) {
6796
7148
  res.set("Content-Type", "text/css");
@@ -6798,11 +7150,11 @@ async function createServerHandle(config3) {
6798
7150
  }
6799
7151
  })
6800
7152
  );
6801
- app.use("/manifest.webmanifest", express.static(join9(distWebDir, "manifest.webmanifest")));
6802
- app.use("/registerSW.js", express.static(join9(distWebDir, "registerSW.js")));
6803
- app.use("/sw.js", express.static(join9(distWebDir, "sw.js")));
7153
+ app.use("/manifest.webmanifest", express.static(join10(distWebDir, "manifest.webmanifest")));
7154
+ app.use("/registerSW.js", express.static(join10(distWebDir, "registerSW.js")));
7155
+ app.use("/sw.js", express.static(join10(distWebDir, "sw.js")));
6804
7156
  app.get("/fox.svg", (_req, res) => {
6805
- readFile4(join9(distWebDir, "fox.svg")).then((content) => {
7157
+ readFile4(join10(distWebDir, "fox.svg")).then((content) => {
6806
7158
  res.set("Content-Type", "image/svg+xml");
6807
7159
  res.send(content);
6808
7160
  }).catch(() => {
@@ -6811,7 +7163,7 @@ async function createServerHandle(config3) {
6811
7163
  });
6812
7164
  app.use(
6813
7165
  "/sounds",
6814
- express.static(join9(distWebDir, "sounds"), {
7166
+ express.static(join10(distWebDir, "sounds"), {
6815
7167
  setHeaders: (res) => {
6816
7168
  res.set("Content-Type", "audio/mpeg");
6817
7169
  }
@@ -6820,10 +7172,10 @@ async function createServerHandle(config3) {
6820
7172
  app.use("/__inspect__.js", (_req, res) => {
6821
7173
  res.set("Access-Control-Allow-Origin", "*");
6822
7174
  res.set("Content-Type", "application/javascript");
6823
- readFile4(join9(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
7175
+ readFile4(join10(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6824
7176
  });
6825
7177
  app.get("/", (_req, res) => {
6826
- readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
7178
+ readFile4(join10(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6827
7179
  res.status(404).send("Web UI not built. Run `npm run build:web`");
6828
7180
  });
6829
7181
  });
@@ -6831,7 +7183,7 @@ async function createServerHandle(config3) {
6831
7183
  if (req.path.startsWith("/api/") || req.path.startsWith("/assets/") || req.path.startsWith("/sounds/") || req.path.startsWith("/manifest.webmanifest") || req.path.startsWith("/registerSW.js") || req.path.startsWith("/sw.js") || req.path === "/fox.svg") {
6832
7184
  return;
6833
7185
  }
6834
- readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
7186
+ readFile4(join10(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6835
7187
  res.status(404).send("Web UI not built");
6836
7188
  });
6837
7189
  });
@@ -6851,7 +7203,7 @@ async function createServerHandle(config3) {
6851
7203
  const state = sessionManager.getContextState(sessionId);
6852
7204
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
6853
7205
  });
6854
- const { QueueProcessor } = await import("./processor-BCOSEMZK.js");
7206
+ const { QueueProcessor } = await import("./processor-UQX5KL56.js");
6855
7207
  const queueProcessor = new QueueProcessor({
6856
7208
  sessionManager,
6857
7209
  providerManager,
@@ -6874,7 +7226,7 @@ async function createServerHandle(config3) {
6874
7226
  return {
6875
7227
  httpServer,
6876
7228
  ctx: { config: config3, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
6877
- start: (port) => new Promise((resolve8, reject) => {
7229
+ start: (port) => new Promise((resolve9, reject) => {
6878
7230
  const listenPort = port ?? config3.server.port;
6879
7231
  const host = config3.server.host;
6880
7232
  httpServer.listen(listenPort, host, () => {
@@ -6884,16 +7236,16 @@ async function createServerHandle(config3) {
6884
7236
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
6885
7237
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
6886
7238
  logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config3.llm.baseUrl}`);
6887
- resolve8({ port: actualPort });
7239
+ resolve9({ port: actualPort });
6888
7240
  });
6889
7241
  httpServer.on("error", reject);
6890
7242
  }),
6891
- close: () => new Promise((resolve8) => {
7243
+ close: () => new Promise((resolve9) => {
6892
7244
  logger.info("Shutting down...");
6893
7245
  void (async () => {
6894
7246
  await devServerManager.stopAll();
6895
7247
  await mcpManager.disconnectAll();
6896
- const { stopAllInspectProxies } = await import("./inspect-proxy-JHZV34QR.js");
7248
+ const { stopAllInspectProxies } = await import("./inspect-proxy-DRYIIH4O.js");
6897
7249
  stopAllInspectProxies();
6898
7250
  const { cleanupAllProcesses } = await import("./store-SARB6V2N.js");
6899
7251
  cleanupAllProcesses();
@@ -6907,7 +7259,7 @@ async function createServerHandle(config3) {
6907
7259
  client.terminate();
6908
7260
  }
6909
7261
  wss.close();
6910
- httpServer.close(() => resolve8());
7262
+ httpServer.close(() => resolve9());
6911
7263
  })();
6912
7264
  })
6913
7265
  };
@@ -6931,4 +7283,4 @@ export {
6931
7283
  createServerHandle,
6932
7284
  createServer
6933
7285
  };
6934
- //# sourceMappingURL=chunk-BX3VJP2D.js.map
7286
+ //# sourceMappingURL=chunk-UMX7MMNW.js.map