openfox 2.0.65 → 2.0.67

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 (64) hide show
  1. package/README.md +1 -0
  2. package/dist/agent-defaults/builder.agent.md +1 -1
  3. package/dist/agent-defaults/code-reviewer.agent.md +0 -1
  4. package/dist/agent-defaults/explorer.agent.md +0 -1
  5. package/dist/agent-defaults/planner.agent.md +1 -1
  6. package/dist/{branch.api-LAN42BA5.js → branch.api-3YJSWOZG.js} +5 -1
  7. package/dist/{chat-handler-MC3XZ3OV.js → chat-handler-72DFHK5K.js} +16 -13
  8. package/dist/{chunk-Z6H7SFQR.js → chunk-2GRUQN2B.js} +435 -170
  9. package/dist/{chunk-LBGHZLLH.js → chunk-4QBDV6LX.js} +17 -14
  10. package/dist/{chunk-RYIREJAW.js → chunk-5EO6SEGV.js} +2 -2
  11. package/dist/{chunk-N4K3PNOS.js → chunk-B6JUWVTK.js} +95 -29
  12. package/dist/{chunk-QBYQ7KDX.js → chunk-B7WGOK7G.js} +16 -15
  13. package/dist/{chunk-Z6W4YHJB.js → chunk-BL5LOLVA.js} +17 -1
  14. package/dist/{chunk-TMUBLQFC.js → chunk-C3VLGVSQ.js} +3 -3
  15. package/dist/{chunk-ZPIZLTWU.js → chunk-GMXKJGJ2.js} +5 -1
  16. package/dist/{chunk-YQ3SOPBI.js → chunk-KXVFHMSM.js} +2 -2
  17. package/dist/{chunk-4UYKN6JU.js → chunk-MQHMT5WF.js} +3 -3
  18. package/dist/{chunk-VWPY2KWH.js → chunk-PYRH4G2J.js} +9 -35
  19. package/dist/{chunk-BGTEIA2S.js → chunk-TFCHWMOJ.js} +23 -30
  20. package/dist/{chunk-AIJE3RYH.js → chunk-TFDK6VSG.js} +33 -7
  21. package/dist/{chunk-X5YCWKNS.js → chunk-TJO4QFDQ.js} +59 -86
  22. package/dist/{chunk-QJ5FH5DP.js → chunk-TMHWQYWE.js} +4 -4
  23. package/dist/chunk-VLV3XWZS.js +191 -0
  24. package/dist/chunk-WGMJCFCE.js +14 -0
  25. package/dist/chunk-X5DOUA3Z.js +66 -0
  26. package/dist/{chunk-PXJ4NOP4.js → chunk-XUPKS5FL.js} +6 -4
  27. package/dist/{chunk-UEIQKG5P.js → chunk-YU6DZAVA.js} +303 -360
  28. package/dist/{chunk-OESYKZCM.js → chunk-ZLON3JTI.js} +3 -3
  29. package/dist/cli/dev.js +1 -1
  30. package/dist/cli/index.js +1 -1
  31. package/dist/{client-LAKW7TA5.js → client-BUX62J2K.js} +3 -3
  32. package/dist/{client-pure-DO3S675T.js → client-pure-U6ZYUPJQ.js} +6 -4
  33. package/dist/{compactor-I3N56PSJ.js → compactor-74CZVUWI.js} +9 -7
  34. package/dist/{events-52XADT6Y.js → events-CDQ4HASP.js} +4 -4
  35. package/dist/{folding-2BGFLV5J.js → folding-V2K34EGN.js} +2 -2
  36. package/dist/{inspect-proxy-BV25JERQ.js → inspect-proxy-OVEFBJ26.js} +4 -4
  37. package/dist/{manager-344C5JLZ.js → manager-JXYRGR6B.js} +6 -2
  38. package/dist/{orchestrator-IYJRQQKB.js → orchestrator-FEMPJOZD.js} +15 -14
  39. package/dist/package.json +2 -1
  40. package/dist/platform-AB3GIEGO.js +21 -0
  41. package/dist/{processor-LUXKVIED.js → processor-QB3NMRMO.js} +16 -13
  42. package/dist/{project-creator-IDW7RACH.js → project-creator-EMGRSPYS.js} +18 -5
  43. package/dist/{projects-BY227WT2.js → projects-7HSBZY2D.js} +3 -3
  44. package/dist/{protocol-Cq66hdDX.d.ts → protocol-42f_Png6.d.ts} +1 -1
  45. package/dist/provider/index.d.ts +4 -4
  46. package/dist/{provider-GYOW4OWQ.js → provider-BDH6JGZB.js} +4 -4
  47. package/dist/{provider-manager-HRHNF73A.js → provider-manager-D3KIOD5E.js} +4 -4
  48. package/dist/{serve-ZRTWVOL2.js → serve-32FAA4FX.js} +20 -17
  49. package/dist/server/index.d.ts +26 -8
  50. package/dist/server/index.js +19 -16
  51. package/dist/server-OYE7GERR.js +37 -0
  52. package/dist/{settings-JA4XUR3W.js → settings-6ZPWOBWL.js} +3 -3
  53. package/dist/shared/index.d.ts +3 -3
  54. package/dist/{tools-ZZM36DAZ.js → tools-INWP6FGV.js} +14 -11
  55. package/dist/{types-CDZakn7f.d.ts → types-apiMd7Df.d.ts} +1 -1
  56. package/dist/{types-akHmgvBk.d.ts → types-vezAEt_y.d.ts} +3 -1
  57. package/dist/web/assets/{index-Dc05znz4.css → index-BELeAs12.css} +1 -1
  58. package/dist/web/assets/index-C3n65CNu.js +303 -0
  59. package/dist/web/index.html +2 -2
  60. package/dist/web/sw.js +1 -1
  61. package/dist/worktree-6U45P63P.js +30 -0
  62. package/package.json +2 -1
  63. package/dist/server-PXXGMFBT.js +0 -34
  64. package/dist/web/assets/index-Bsi_le80.js +0 -303
@@ -21,7 +21,7 @@ import {
21
21
  tokenFromPassword,
22
22
  verifyPassword,
23
23
  workflowExists
24
- } from "./chunk-N4K3PNOS.js";
24
+ } from "./chunk-B6JUWVTK.js";
25
25
  import {
26
26
  agentExists,
27
27
  createToolRegistry,
@@ -66,19 +66,22 @@ import {
66
66
  setSkillEnabled,
67
67
  skillExists,
68
68
  updateOwnedSkill
69
- } from "./chunk-UEIQKG5P.js";
69
+ } from "./chunk-YU6DZAVA.js";
70
70
  import {
71
71
  ALWAYS_ALLOWED,
72
72
  ALWAYS_ALLOWED_FOR_SUBAGENTS,
73
73
  TOP_LEVEL_ONLY_TOOLS
74
- } from "./chunk-X5YCWKNS.js";
74
+ } from "./chunk-TJO4QFDQ.js";
75
75
  import {
76
- getPathSeparator,
77
- isAbsolutePath
78
- } from "./chunk-BGTEIA2S.js";
76
+ getProject
77
+ } from "./chunk-KXVFHMSM.js";
79
78
  import {
80
79
  createMcpTools
81
80
  } from "./chunk-NWO6GRYE.js";
81
+ import {
82
+ ensureWorktree,
83
+ syncIgnoredAssets
84
+ } from "./chunk-VLV3XWZS.js";
82
85
  import {
83
86
  createSession,
84
87
  deleteSession,
@@ -104,31 +107,33 @@ import {
104
107
  updateSessionDangerLevel,
105
108
  updateSessionMetadata,
106
109
  updateSessionProvider,
107
- updateSessionRunning
108
- } from "./chunk-AIJE3RYH.js";
110
+ updateSessionRunning,
111
+ updateSessionWorkdir
112
+ } from "./chunk-TFDK6VSG.js";
109
113
  import {
110
114
  createContextStateMessage
111
115
  } from "./chunk-F4PMNP7S.js";
116
+ import {
117
+ getPathSeparator,
118
+ isAbsolutePath
119
+ } from "./chunk-X5DOUA3Z.js";
112
120
  import {
113
121
  deleteSetting,
114
122
  getSetting,
115
123
  setSetting
116
- } from "./chunk-PXJ4NOP4.js";
124
+ } from "./chunk-XUPKS5FL.js";
125
+ import {
126
+ initDatabase
127
+ } from "./chunk-GMXKJGJ2.js";
117
128
  import {
118
129
  EventEmitter
119
130
  } from "./chunk-EU3WWTFH.js";
120
- import {
121
- getProject
122
- } from "./chunk-YQ3SOPBI.js";
123
- import {
124
- initDatabase
125
- } from "./chunk-ZPIZLTWU.js";
126
131
  import {
127
132
  createProviderManager,
128
133
  detectModel,
129
134
  getLlmStatus,
130
135
  parseDefaultModelSelection
131
- } from "./chunk-RYIREJAW.js";
136
+ } from "./chunk-5EO6SEGV.js";
132
137
  import {
133
138
  getModelProfile
134
139
  } from "./chunk-V4IE7HJY.js";
@@ -157,8 +162,8 @@ import express from "express";
157
162
  import cors from "cors";
158
163
  import { createServer as createHttpServer } from "http";
159
164
  import { fileURLToPath as fileURLToPath6 } from "url";
160
- import { dirname as dirname7, resolve as resolve5, join as join8 } from "path";
161
- import { readFile as readFile3 } from "fs/promises";
165
+ import { dirname as dirname7, resolve as resolve6, join as join9 } from "path";
166
+ import { readFile as readFile4 } from "fs/promises";
162
167
  import { createServer as createViteServer } from "vite";
163
168
 
164
169
  // src/server/llm/mock.ts
@@ -1599,6 +1604,35 @@ var McpManager = class {
1599
1604
  }
1600
1605
  };
1601
1606
 
1607
+ // src/server/git/worktree-config.ts
1608
+ import { readFile, writeFile, mkdir } from "fs/promises";
1609
+ import { resolve, join } from "path";
1610
+ var CONFIG_FILENAME = ".openfox/worktree.json";
1611
+ function getConfigPath(workdir) {
1612
+ return join(resolve(workdir), CONFIG_FILENAME);
1613
+ }
1614
+ async function loadWorktreeConfig(workdir) {
1615
+ try {
1616
+ const configPath = getConfigPath(workdir);
1617
+ const raw = await readFile(configPath, "utf-8");
1618
+ const parsed = JSON.parse(raw);
1619
+ if (!parsed.ignoredAssets) return null;
1620
+ return {
1621
+ ignoredAssets: parsed.ignoredAssets,
1622
+ overrides: parsed.overrides ?? void 0
1623
+ };
1624
+ } catch {
1625
+ return null;
1626
+ }
1627
+ }
1628
+ async function saveWorktreeConfig(workdir, config3) {
1629
+ const resolved = resolve(workdir);
1630
+ const dirPath = join(resolved, ".openfox");
1631
+ await mkdir(dirPath, { recursive: true });
1632
+ const configPath = getConfigPath(workdir);
1633
+ await writeFile(configPath, JSON.stringify(config3, null, 2) + "\n", "utf-8");
1634
+ }
1635
+
1602
1636
  // src/server/lsp/server.ts
1603
1637
  import { spawn } from "child_process";
1604
1638
  import { extname } from "path";
@@ -1921,19 +1955,19 @@ var LspServer = class {
1921
1955
  */
1922
1956
  async getDiagnosticsWithWait(path, timeoutMs = DIAGNOSTIC_WAIT_MS) {
1923
1957
  if (this.openDocuments.has(path)) {
1924
- return new Promise((resolve6) => {
1958
+ return new Promise((resolve7) => {
1925
1959
  const existing = this.diagnostics.get(path);
1926
1960
  if (existing !== void 0) {
1927
1961
  setTimeout(() => {
1928
- resolve6(this.diagnostics.get(path) ?? []);
1962
+ resolve7(this.diagnostics.get(path) ?? []);
1929
1963
  }, 100);
1930
1964
  return;
1931
1965
  }
1932
1966
  const timeout = setTimeout(() => {
1933
1967
  this.pendingDiagnostics.delete(path);
1934
- resolve6(this.diagnostics.get(path) ?? []);
1968
+ resolve7(this.diagnostics.get(path) ?? []);
1935
1969
  }, timeoutMs);
1936
- this.pendingDiagnostics.set(path, { resolve: resolve6, timeout });
1970
+ this.pendingDiagnostics.set(path, { resolve: resolve7, timeout });
1937
1971
  });
1938
1972
  }
1939
1973
  return this.diagnostics.get(path) ?? [];
@@ -2144,14 +2178,14 @@ import { readFileSync as readFileSync2 } from "fs";
2144
2178
 
2145
2179
  // src/server/utils/which.ts
2146
2180
  import { access, constants } from "fs/promises";
2147
- import { join, dirname } from "path";
2181
+ import { join as join2, dirname } from "path";
2148
2182
  import { fileURLToPath as fileURLToPath2 } from "url";
2149
2183
  var __dirname = dirname(fileURLToPath2(import.meta.url));
2150
2184
  function getBundledBinPaths() {
2151
2185
  const paths = [];
2152
- paths.push(join(process.cwd(), "node_modules", ".bin"));
2153
- paths.push(join(__dirname, "..", "..", "..", "node_modules", ".bin"));
2154
- paths.push(join(__dirname, "..", "..", "..", "..", "node_modules", ".bin"));
2186
+ paths.push(join2(process.cwd(), "node_modules", ".bin"));
2187
+ paths.push(join2(__dirname, "..", "..", "..", "node_modules", ".bin"));
2188
+ paths.push(join2(__dirname, "..", "..", "..", "..", "node_modules", ".bin"));
2155
2189
  return paths;
2156
2190
  }
2157
2191
  async function existsExecutable(path) {
@@ -2170,13 +2204,13 @@ async function which(command, workdir) {
2170
2204
  return null;
2171
2205
  }
2172
2206
  for (const binDir of getBundledBinPaths()) {
2173
- const fullPath = join(binDir, command);
2207
+ const fullPath = join2(binDir, command);
2174
2208
  if (await existsExecutable(fullPath)) {
2175
2209
  return fullPath;
2176
2210
  }
2177
2211
  }
2178
2212
  if (workdir) {
2179
- const projectBin = join(workdir, "node_modules", ".bin", command);
2213
+ const projectBin = join2(workdir, "node_modules", ".bin", command);
2180
2214
  if (await existsExecutable(projectBin)) {
2181
2215
  return projectBin;
2182
2216
  }
@@ -2185,7 +2219,7 @@ async function which(command, workdir) {
2185
2219
  const paths = pathEnv.split(getPathSeparator());
2186
2220
  for (const dir of paths) {
2187
2221
  if (!dir) continue;
2188
- const fullPath = join(dir, command);
2222
+ const fullPath = join2(dir, command);
2189
2223
  if (await existsExecutable(fullPath)) {
2190
2224
  return fullPath;
2191
2225
  }
@@ -2197,9 +2231,9 @@ async function which(command, workdir) {
2197
2231
  import { extname as extname2, basename } from "path";
2198
2232
  import { readFileSync } from "fs";
2199
2233
  import { fileURLToPath as fileURLToPath3 } from "url";
2200
- import { dirname as dirname2, resolve } from "path";
2234
+ import { dirname as dirname2, resolve as resolve2 } from "path";
2201
2235
  var __dirname2 = dirname2(fileURLToPath3(import.meta.url));
2202
- var languagesJson = JSON.parse(readFileSync(resolve(__dirname2, "languages.json"), "utf-8"));
2236
+ var languagesJson = JSON.parse(readFileSync(resolve2(__dirname2, "languages.json"), "utf-8"));
2203
2237
  var LANGUAGES = languagesJson;
2204
2238
  var extensionToLanguage = /* @__PURE__ */ new Map();
2205
2239
  for (const lang of LANGUAGES) {
@@ -2542,7 +2576,7 @@ var SessionManager = class {
2542
2576
  * Create a new session. Emits session.initialized event.
2543
2577
  * Note: maxTokens is no longer stored in the session - it comes from the current model config
2544
2578
  */
2545
- createSession(projectId, title, providerId, providerModel) {
2579
+ createSession(projectId, title, providerId, providerModel, worktree) {
2546
2580
  const project = getProject(projectId);
2547
2581
  if (!project) {
2548
2582
  throw new Error(`Project not found: ${projectId}`);
@@ -2552,10 +2586,11 @@ var SessionManager = class {
2552
2586
  const existingSessions = listSessionsByProject(projectId, 1e3, 0);
2553
2587
  sessionTitle = `Session ${existingSessions.sessions.length + 1}`;
2554
2588
  }
2555
- logger.debug("Creating session", { projectId, workdir: project.workdir, title: sessionTitle });
2556
- const dbSession = createSession(projectId, project.workdir, sessionTitle, providerId, providerModel);
2589
+ const effectiveWorkdir = worktree ?? project.workdir;
2590
+ logger.debug("Creating session", { projectId, workdir: effectiveWorkdir, title: sessionTitle });
2591
+ const dbSession = createSession(projectId, effectiveWorkdir, sessionTitle, providerId, providerModel, worktree);
2557
2592
  const contextWindowId = crypto.randomUUID();
2558
- emitSessionInitialized(dbSession.id, projectId, project.workdir, contextWindowId, sessionTitle);
2593
+ emitSessionInitialized(dbSession.id, projectId, effectiveWorkdir, contextWindowId, sessionTitle);
2559
2594
  const session = this.buildSessionFromDb(dbSession);
2560
2595
  this.emit({ type: "session_created", session });
2561
2596
  return session;
@@ -2750,6 +2785,7 @@ var SessionManager = class {
2750
2785
  if (message.attachments !== void 0) options.attachments = message.attachments;
2751
2786
  if (message.subAgentId !== void 0) options.subAgentId = message.subAgentId;
2752
2787
  if (message.subAgentType !== void 0) options.subAgentType = message.subAgentType;
2788
+ if (message.metadata !== void 0) options.metadata = message.metadata;
2753
2789
  const messageId = emitUserMessage(sessionId, message.content, options);
2754
2790
  const result = {
2755
2791
  id: messageId,
@@ -2763,6 +2799,7 @@ var SessionManager = class {
2763
2799
  if (message.attachments !== void 0) result.attachments = message.attachments;
2764
2800
  if (message.subAgentId !== void 0) result.subAgentId = message.subAgentId;
2765
2801
  if (message.subAgentType !== void 0) result.subAgentType = message.subAgentType;
2802
+ if (message.metadata !== void 0) result.metadata = message.metadata;
2766
2803
  this.emit({ type: "message_added", sessionId, message: result });
2767
2804
  return result;
2768
2805
  }
@@ -2902,12 +2939,6 @@ var SessionManager = class {
2902
2939
  // ============================================================================
2903
2940
  // Execution State (runtime tracking, not persisted to events)
2904
2941
  // ============================================================================
2905
- /**
2906
- * Record that a file was modified.
2907
- */
2908
- addModifiedFile(sessionId, filePath) {
2909
- logger.debug("addModifiedFile called", { sessionId, filePath });
2910
- }
2911
2942
  /**
2912
2943
  * Add a criterion. Returns the updated criteria list.
2913
2944
  */
@@ -3157,10 +3188,122 @@ var SessionManager = class {
3157
3188
  // ============================================================================
3158
3189
  /**
3159
3190
  * Get the LSP manager for a session.
3191
+ * Uses worktree path when active, otherwise the project workdir.
3160
3192
  */
3161
3193
  getLspManager(sessionId) {
3162
3194
  const session = this.requireSession(sessionId);
3163
- return getLspManager(sessionId, session.workdir);
3195
+ const effectiveWorkdir = session.worktree ?? session.workdir;
3196
+ return getLspManager(sessionId, effectiveWorkdir);
3197
+ }
3198
+ // ============================================================================
3199
+ // Worktree Lifecycle
3200
+ // ============================================================================
3201
+ /**
3202
+ * Create a git worktree for an existing session and move the session into it.
3203
+ * Keeps session.workdir as the project root (stable system prompt).
3204
+ * Sets session.worktree to the worktree path for tool execution.
3205
+ * Restarts LSP to pick up the new workdir.
3206
+ * Injects a system reminder to inform the agent about the worktree.
3207
+ */
3208
+ async createSessionWorktree(sessionId, name) {
3209
+ const session = this.requireSession(sessionId);
3210
+ const project = getProject(session.projectId);
3211
+ if (!project) throw new Error(`Project not found: ${session.projectId}`);
3212
+ if (session.worktree) throw new Error("Session already has a worktree");
3213
+ const result = await ensureWorktree(project.workdir, name);
3214
+ const wtConfig = await loadWorktreeConfig(project.workdir);
3215
+ if (wtConfig) {
3216
+ await syncIgnoredAssets(project.workdir, result.path, wtConfig);
3217
+ }
3218
+ updateSessionWorkdir(sessionId, project.workdir, result.path);
3219
+ try {
3220
+ await shutdownLspManager(sessionId);
3221
+ } catch (err) {
3222
+ logger.error("Error shutting down LSP for worktree switch", { sessionId, error: err });
3223
+ }
3224
+ const reminderContent = `<system-reminder>
3225
+ This session is now operating in a git worktree at ${result.path}.
3226
+ All file and git operations should use this directory.
3227
+ </system-reminder>`;
3228
+ this.addMessage(sessionId, {
3229
+ role: "user",
3230
+ content: reminderContent,
3231
+ isSystemGenerated: true,
3232
+ messageKind: "auto-prompt",
3233
+ metadata: { type: "worktree", name: "Worktree", color: "#22c55e", kind: "definition", branchName: name }
3234
+ });
3235
+ const updated = this.requireSession(sessionId);
3236
+ this.emit({ type: "session_updated", session: updated });
3237
+ return updated;
3238
+ }
3239
+ /**
3240
+ * Attach session to an existing worktree by path.
3241
+ * Sets session.worktree to the given path without creating a new worktree.
3242
+ * Restarts LSP to pick up the new workdir.
3243
+ */
3244
+ async attachSessionWorktree(sessionId, wtPath) {
3245
+ const session = this.requireSession(sessionId);
3246
+ if (session.worktree) throw new Error("Session already has a worktree");
3247
+ updateSessionWorkdir(sessionId, session.workdir, wtPath);
3248
+ try {
3249
+ await shutdownLspManager(sessionId);
3250
+ } catch (err) {
3251
+ logger.error("Error shutting down LSP for worktree attach", { sessionId, error: err });
3252
+ }
3253
+ const branchName = wtPath.includes("/worktrees/") ? wtPath.split("/worktrees/")[1] ?? wtPath : wtPath;
3254
+ const reminderContent = `<system-reminder>
3255
+ This session is now operating in a git worktree at ${wtPath}.
3256
+ All file and git operations should use this directory.
3257
+ </system-reminder>`;
3258
+ this.addMessage(sessionId, {
3259
+ role: "user",
3260
+ content: reminderContent,
3261
+ isSystemGenerated: true,
3262
+ messageKind: "auto-prompt",
3263
+ metadata: { type: "worktree", name: "Worktree", color: "#22c55e", kind: "definition", branchName }
3264
+ });
3265
+ const updated = this.requireSession(sessionId);
3266
+ this.emit({ type: "session_updated", session: updated });
3267
+ return updated;
3268
+ }
3269
+ /**
3270
+ * Close the worktree for a session and move it back to the project root.
3271
+ * Clears session.worktree — session.workdir stays as project root.
3272
+ * Restarts LSP to pick up the original workdir.
3273
+ * Injects a system reminder to inform the agent the worktree is closed.
3274
+ */
3275
+ async closeSessionWorktree(sessionId) {
3276
+ const session = this.requireSession(sessionId);
3277
+ if (!session.worktree) throw new Error("Session does not have a worktree");
3278
+ const project = getProject(session.projectId);
3279
+ if (!project) throw new Error(`Project not found: ${session.projectId}`);
3280
+ const closedPath = session.worktree;
3281
+ const branchName = closedPath.includes("/worktrees/") ? closedPath.split("/worktrees/")[1] ?? closedPath : closedPath;
3282
+ try {
3283
+ await devServerManager.stop(closedPath);
3284
+ } catch (err) {
3285
+ logger.error("Error stopping dev server for worktree close", { sessionId, worktree: closedPath, error: err });
3286
+ }
3287
+ updateSessionWorkdir(sessionId, project.workdir, null);
3288
+ try {
3289
+ await shutdownLspManager(sessionId);
3290
+ } catch (err) {
3291
+ logger.error("Error shutting down LSP for worktree close", { sessionId, error: err });
3292
+ }
3293
+ const reminderContent = `<system-reminder>
3294
+ The worktree at ${closedPath} has been closed.
3295
+ Operating in the original project directory at ${project.workdir}.
3296
+ </system-reminder>`;
3297
+ this.addMessage(sessionId, {
3298
+ role: "user",
3299
+ content: reminderContent,
3300
+ isSystemGenerated: true,
3301
+ messageKind: "auto-prompt",
3302
+ metadata: { type: "worktree", name: "Worktree", color: "#ef4444", kind: "reminder", branchName }
3303
+ });
3304
+ const updated = this.requireSession(sessionId);
3305
+ this.emit({ type: "session_updated", session: updated });
3306
+ return updated;
3164
3307
  }
3165
3308
  // ============================================================================
3166
3309
  // Active Session
@@ -3243,8 +3386,18 @@ var SessionManager = class {
3243
3386
  contextWindows: [],
3244
3387
  // Derived from events, not stored separately
3245
3388
  executionState: eventState.cachedSystemPrompt || cachedPrompt ? {
3246
- cachedSystemPrompt: cachedPrompt?.systemPrompt ?? eventState.cachedSystemPrompt,
3247
- dynamicContextHash: cachedPrompt?.hash ?? eventState.dynamicContextHash
3389
+ iteration: 0,
3390
+ readFiles: {},
3391
+ consecutiveFailures: 0,
3392
+ currentTokenCount: 0,
3393
+ messageCountAtLastUpdate: messages.length,
3394
+ compactionCount: 0,
3395
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
3396
+ lastActivityAt: (/* @__PURE__ */ new Date()).toISOString(),
3397
+ ...cachedPrompt?.systemPrompt ? { cachedSystemPrompt: cachedPrompt.systemPrompt } : {},
3398
+ ...eventState.cachedSystemPrompt && !cachedPrompt?.systemPrompt ? { cachedSystemPrompt: eventState.cachedSystemPrompt } : {},
3399
+ ...cachedPrompt?.hash ? { dynamicContextHash: cachedPrompt.hash } : {},
3400
+ ...eventState.dynamicContextHash && !cachedPrompt?.hash ? { dynamicContextHash: eventState.dynamicContextHash } : {}
3248
3401
  } : null
3249
3402
  };
3250
3403
  }
@@ -3253,15 +3406,15 @@ var SessionManager = class {
3253
3406
  // src/server/routes/skills.ts
3254
3407
  import { Router as Router2 } from "express";
3255
3408
  import multer from "multer";
3256
- import { access as access2, mkdir as mkdir2, realpath, stat } from "fs/promises";
3409
+ import { access as access2, mkdir as mkdir3, realpath, stat } from "fs/promises";
3257
3410
  import { constants as constants2 } from "fs";
3258
3411
  import { homedir } from "os";
3259
- import { isAbsolute as isAbsolute2, join as join4, resolve as resolve2 } from "path";
3412
+ import { isAbsolute as isAbsolute2, join as join5, resolve as resolve3 } from "path";
3260
3413
 
3261
3414
  // src/server/skills/installer.ts
3262
3415
  import { randomUUID } from "crypto";
3263
- import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
3264
- import { dirname as dirname3, isAbsolute, join as join2 } from "path";
3416
+ import { mkdir as mkdir2, readFile as readFile2, rename, rm, writeFile as writeFile2 } from "fs/promises";
3417
+ import { dirname as dirname3, isAbsolute, join as join3 } from "path";
3265
3418
  import matter from "gray-matter";
3266
3419
  var SkillInstallError = class extends Error {
3267
3420
  constructor(message, status) {
@@ -3293,17 +3446,17 @@ async function installSkillPackage(libraryDir, packageName, files) {
3293
3446
  totalBytes += file.content.byteLength;
3294
3447
  }
3295
3448
  if (totalBytes > 50 * 1024 * 1024) throw new SkillInstallError("Package exceeds 50 MiB", 413);
3296
- const destination = join2(libraryDir, packageName);
3449
+ const destination = join3(libraryDir, packageName);
3297
3450
  if (await pathExists(destination)) throw new SkillInstallError("A package with this name already exists", 409);
3298
- const staging = join2(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
3451
+ const staging = join3(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
3299
3452
  try {
3300
- await mkdir(staging, { recursive: false });
3453
+ await mkdir2(staging, { recursive: false });
3301
3454
  for (const file of files) {
3302
- const target = join2(staging, file.path);
3303
- await mkdir(dirname3(target), { recursive: true });
3304
- await writeFile(target, file.content);
3455
+ const target = join3(staging, file.path);
3456
+ await mkdir2(dirname3(target), { recursive: true });
3457
+ await writeFile2(target, file.content);
3305
3458
  }
3306
- const parsed = matter(await readFile(join2(staging, "SKILL.md"), "utf-8"));
3459
+ const parsed = matter(await readFile2(join3(staging, "SKILL.md"), "utf-8"));
3307
3460
  const name = typeof parsed.data["name"] === "string" ? parsed.data["name"].trim() : "";
3308
3461
  const description = typeof parsed.data["description"] === "string" ? parsed.data["description"].trim() : "";
3309
3462
  if (!name || !description || !parsed.content.trim()) {
@@ -3320,7 +3473,7 @@ async function installSkillPackage(libraryDir, packageName, files) {
3320
3473
 
3321
3474
  // src/server/routes/crud-helpers.ts
3322
3475
  import { Router } from "express";
3323
- import { join as join3 } from "path";
3476
+ import { join as join4 } from "path";
3324
3477
  function computeOverrideIds(defaults, userItems) {
3325
3478
  return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
3326
3479
  }
@@ -3332,7 +3485,7 @@ function validateNameIdPrompt(body) {
3332
3485
  return null;
3333
3486
  }
3334
3487
  function getProjectItemPath(projectDir, dirName, id, ext) {
3335
- return join3(projectDir, ".openfox", dirName, `${id}${ext}`);
3488
+ return join4(projectDir, ".openfox", dirName, `${id}${ext}`);
3336
3489
  }
3337
3490
  async function isProjectItem(projectDir, dirName, id, ext) {
3338
3491
  if (!projectDir) return false;
@@ -3477,7 +3630,7 @@ var upload = multer({
3477
3630
  });
3478
3631
  function expandHome(path) {
3479
3632
  if (path === "~") return homedir();
3480
- return path.startsWith("~/") ? join4(homedir(), path.slice(2)) : path;
3633
+ return path.startsWith("~/") ? join5(homedir(), path.slice(2)) : path;
3481
3634
  }
3482
3635
  function configuredDirectory() {
3483
3636
  const raw = getSetting(SKILL_DIRECTORIES_SETTING);
@@ -3490,13 +3643,13 @@ function configuredDirectory() {
3490
3643
  }
3491
3644
  }
3492
3645
  function defaultLibrary(configDir) {
3493
- const path = resolve2(configDir, "skills");
3646
+ const path = resolve3(configDir, "skills");
3494
3647
  return { configuredPath: path, resolvedPath: path, available: true, custom: false };
3495
3648
  }
3496
3649
  async function resolveLibrary(path) {
3497
3650
  const expanded = expandHome(path);
3498
3651
  if (!isAbsolute2(expanded)) throw new Error("Selected path must be absolute");
3499
- const absolute = resolve2(expanded);
3652
+ const absolute = resolve3(expanded);
3500
3653
  const info = await stat(absolute);
3501
3654
  if (!info.isDirectory()) throw new Error("Selected path is not a directory");
3502
3655
  await access2(absolute, constants2.R_OK);
@@ -3585,7 +3738,7 @@ function createSkillRoutes(configDir, projectDir) {
3585
3738
  try {
3586
3739
  const configured = configuredDirectory();
3587
3740
  const library = configured ? await resolveLibrary(configured) : defaultLibrary(configDir);
3588
- await mkdir2(library.resolvedPath, { recursive: true });
3741
+ await mkdir3(library.resolvedPath, { recursive: true });
3589
3742
  const packageName = String(req.body["packageName"] ?? "");
3590
3743
  const paths = JSON.parse(String(req.body["paths"] ?? "[]"));
3591
3744
  const files = req.files;
@@ -3635,19 +3788,19 @@ function createSkillRoutes(configDir, projectDir) {
3635
3788
  }
3636
3789
 
3637
3790
  // src/server/commands/registry.ts
3638
- import { writeFile as writeFile2, mkdir as mkdir3, unlink } from "fs/promises";
3639
- import { join as join5, dirname as dirname4 } from "path";
3791
+ import { writeFile as writeFile3, mkdir as mkdir4, unlink } from "fs/promises";
3792
+ import { join as join6, dirname as dirname4 } from "path";
3640
3793
  import { fileURLToPath as fileURLToPath4 } from "url";
3641
3794
  import matter2 from "gray-matter";
3642
3795
  var __bundleDir = dirname4(fileURLToPath4(import.meta.url));
3643
- var DEFAULTS_DIR = join5(__bundleDir, "defaults");
3644
- var DEFAULTS_DIR_ALT = join5(__bundleDir, "command-defaults");
3796
+ var DEFAULTS_DIR = join6(__bundleDir, "defaults");
3797
+ var DEFAULTS_DIR_ALT = join6(__bundleDir, "command-defaults");
3645
3798
  var COMMAND_EXTENSION = ".command.md";
3646
3799
  function getCommandsDir(configDir) {
3647
- return join5(configDir, "commands");
3800
+ return join6(configDir, "commands");
3648
3801
  }
3649
3802
  function getProjectCommandsDir(projectDir) {
3650
- return join5(projectDir, ".openfox", "commands");
3803
+ return join6(projectDir, ".openfox", "commands");
3651
3804
  }
3652
3805
  async function loadDefaultCommands() {
3653
3806
  let defaults = await loadItemsFromDir(DEFAULTS_DIR, {
@@ -3704,19 +3857,19 @@ function findCommandById(commandId, commands) {
3704
3857
  return commands.find((c) => c.metadata.id === commandId);
3705
3858
  }
3706
3859
  async function commandExists(configDir, commandId, projectDir) {
3707
- if (await pathExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
3708
- if (projectDir && await pathExists(join5(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
3860
+ if (await pathExists(join6(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
3861
+ if (projectDir && await pathExists(join6(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
3709
3862
  return true;
3710
3863
  return false;
3711
3864
  }
3712
3865
  async function saveCommand(configDir, command) {
3713
3866
  const commandsDir = getCommandsDir(configDir);
3714
3867
  if (!await pathExists(commandsDir)) {
3715
- await mkdir3(commandsDir, { recursive: true });
3868
+ await mkdir4(commandsDir, { recursive: true });
3716
3869
  }
3717
- const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
3870
+ const filePath = join6(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
3718
3871
  const content = matter2.stringify(command.prompt, command.metadata);
3719
- await writeFile2(filePath, content, "utf-8");
3872
+ await writeFile3(filePath, content, "utf-8");
3720
3873
  }
3721
3874
  async function saveCommandToProject(projectDir, command) {
3722
3875
  await saveItemToDir(
@@ -3734,7 +3887,7 @@ async function deleteCommand(configDir, commandId) {
3734
3887
  if (isDefault) {
3735
3888
  return { success: false, reason: "Cannot delete built-in defaults" };
3736
3889
  }
3737
- const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3890
+ const filePath = join6(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
3738
3891
  try {
3739
3892
  await unlink(filePath);
3740
3893
  return { success: true };
@@ -3914,10 +4067,38 @@ function createDevServerRoutes() {
3914
4067
  return router;
3915
4068
  }
3916
4069
 
3917
- // src/server/routes/terminals.ts
4070
+ // src/server/routes/worktree-config.ts
3918
4071
  import { Router as Router5 } from "express";
3919
- function createTerminalRoutes() {
4072
+ function createWorktreeConfigRoutes() {
3920
4073
  const router = Router5();
4074
+ router.get("/config", async (req, res) => {
4075
+ const workdir = req.query["workdir"];
4076
+ if (!workdir) return res.status(400).json({ error: "workdir required" });
4077
+ const config3 = await loadWorktreeConfig(workdir);
4078
+ res.json({ config: config3 });
4079
+ });
4080
+ router.post("/config", async (req, res) => {
4081
+ const workdir = req.query["workdir"];
4082
+ if (!workdir) return res.status(400).json({ error: "workdir required" });
4083
+ const { ignoredAssets, overrides } = req.body;
4084
+ if (!ignoredAssets || !["symlink", "copy", "skip"].includes(ignoredAssets)) {
4085
+ return res.status(400).json({ error: "ignoredAssets must be one of: symlink, copy, skip" });
4086
+ }
4087
+ try {
4088
+ const config3 = { ignoredAssets, overrides: overrides ?? void 0 };
4089
+ await saveWorktreeConfig(workdir, config3);
4090
+ res.json({ config: config3 });
4091
+ } catch (err) {
4092
+ res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
4093
+ }
4094
+ });
4095
+ return router;
4096
+ }
4097
+
4098
+ // src/server/routes/terminals.ts
4099
+ import { Router as Router6 } from "express";
4100
+ function createTerminalRoutes() {
4101
+ const router = Router6();
3921
4102
  router.get("/", (req, res) => {
3922
4103
  const projectId = req.query["projectId"];
3923
4104
  const sessions = projectId ? terminalManager.getByProject(projectId) : [];
@@ -3956,20 +4137,20 @@ function createTerminalRoutes() {
3956
4137
  }
3957
4138
 
3958
4139
  // src/server/routes/directories.ts
3959
- import { Router as Router6 } from "express";
4140
+ import { Router as Router7 } from "express";
3960
4141
  import { readdir } from "fs/promises";
3961
- import { resolve as resolve3, join as join6, dirname as dirname5, basename as basename2 } from "path";
4142
+ import { resolve as resolve4, join as join7, dirname as dirname5, basename as basename2 } from "path";
3962
4143
  function createDirectoryRoutes() {
3963
- const router = Router6();
4144
+ const router = Router7();
3964
4145
  const DEFAULT_BASE_PATH = process.cwd();
3965
4146
  router.get("/", async (req, res) => {
3966
4147
  const path = req.query["path"] || DEFAULT_BASE_PATH;
3967
4148
  try {
3968
- const resolvedPath = resolve3(path);
4149
+ const resolvedPath = resolve4(path);
3969
4150
  const entries = await readdir(resolvedPath, { withFileTypes: true });
3970
4151
  const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
3971
4152
  name: entry.name,
3972
- path: join6(resolvedPath, entry.name)
4153
+ path: join7(resolvedPath, entry.name)
3973
4154
  })).sort((a, b) => a.name.localeCompare(b.name));
3974
4155
  const parent = dirname5(resolvedPath);
3975
4156
  const hasParent = parent !== resolvedPath;
@@ -3993,10 +4174,10 @@ function createDirectoryRoutes() {
3993
4174
  }
3994
4175
 
3995
4176
  // src/server/routes/file-search.ts
3996
- import { Router as Router7 } from "express";
4177
+ import { Router as Router8 } from "express";
3997
4178
  import fg from "fast-glob";
3998
4179
  function createFileSearchRoutes() {
3999
- const router = Router7();
4180
+ const router = Router8();
4000
4181
  router.get("/", async (req, res) => {
4001
4182
  const query = req.query["q"] || "";
4002
4183
  const workdir = req.query["workdir"] || process.cwd();
@@ -4072,11 +4253,11 @@ function fuzzyScore(filePath, query) {
4072
4253
  }
4073
4254
 
4074
4255
  // src/server/routes/auto-update.ts
4075
- import { Router as Router8 } from "express";
4256
+ import { Router as Router9 } from "express";
4076
4257
  import { spawn as spawn2 } from "child_process";
4077
4258
 
4078
4259
  // src/constants.ts
4079
- var VERSION = "2.0.65";
4260
+ var VERSION = "2.0.67";
4080
4261
 
4081
4262
  // src/server/routes/auto-update.ts
4082
4263
  var updateInProgress = false;
@@ -4094,12 +4275,12 @@ async function checkAuth(req, opts) {
4094
4275
  return true;
4095
4276
  }
4096
4277
  function createAutoUpdateRoutes(options = {}) {
4097
- const router = Router8();
4278
+ const router = Router9();
4098
4279
  router.get("/check", async (_req, res) => {
4099
4280
  const isService = isRunningAsService();
4100
4281
  const current = VERSION;
4101
4282
  try {
4102
- const latest = await new Promise((resolve6, reject) => {
4283
+ const latest = await new Promise((resolve7, reject) => {
4103
4284
  const child = spawn2("npm", ["view", "openfox", "version"], {
4104
4285
  stdio: ["ignore", "pipe", "pipe"],
4105
4286
  windowsHide: true
@@ -4110,7 +4291,7 @@ function createAutoUpdateRoutes(options = {}) {
4110
4291
  });
4111
4292
  child.on("close", (code) => {
4112
4293
  if (code === 0) {
4113
- resolve6(stdout.trim());
4294
+ resolve7(stdout.trim());
4114
4295
  } else {
4115
4296
  reject(new Error(`npm view exited with code ${code}`));
4116
4297
  }
@@ -4154,9 +4335,9 @@ function createAutoUpdateRoutes(options = {}) {
4154
4335
  const timeout = setTimeout(() => {
4155
4336
  child.kill();
4156
4337
  }, UPDATE_TIMEOUT);
4157
- const exitCode = await new Promise((resolve6) => {
4158
- child.on("close", resolve6);
4159
- child.on("error", () => resolve6(1));
4338
+ const exitCode = await new Promise((resolve7) => {
4339
+ child.on("close", resolve7);
4340
+ child.on("error", () => resolve7(1));
4160
4341
  });
4161
4342
  clearTimeout(timeout);
4162
4343
  if (exitCode === 0) {
@@ -4194,9 +4375,9 @@ function createAutoUpdateRoutes(options = {}) {
4194
4375
  }
4195
4376
 
4196
4377
  // src/server/routes/provider-auth.ts
4197
- import { Router as Router9 } from "express";
4378
+ import { Router as Router10 } from "express";
4198
4379
  function createProviderAuthRoutes(config3, providerManager, registry) {
4199
- const router = Router9();
4380
+ const router = Router10();
4200
4381
  function resolveAuthContext(providerId, res) {
4201
4382
  const provider = providerManager.getProviders().find((item) => item.id === providerId);
4202
4383
  if (!provider) {
@@ -4325,8 +4506,8 @@ var ProviderRegistry = class {
4325
4506
  };
4326
4507
 
4327
4508
  // src/server/providers/plugins/loader.ts
4328
- import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
4329
- import { dirname as dirname6, join as join7, resolve as resolve4 } from "path";
4509
+ import { readdir as readdir2, readFile as readFile3, stat as stat2 } from "fs/promises";
4510
+ import { dirname as dirname6, join as join8, resolve as resolve5 } from "path";
4330
4511
  import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
4331
4512
  async function packageDirectories(root) {
4332
4513
  let entries;
@@ -4337,13 +4518,13 @@ async function packageDirectories(root) {
4337
4518
  }
4338
4519
  const directories = [];
4339
4520
  for (const entry of entries) {
4340
- const entryPath = join7(root, entry.name);
4521
+ const entryPath = join8(root, entry.name);
4341
4522
  const isDirectory = entry.isDirectory() || entry.isSymbolicLink() && (await stat2(entryPath).catch(() => void 0))?.isDirectory();
4342
4523
  if (!isDirectory) continue;
4343
4524
  if (entry.name.startsWith("@")) {
4344
4525
  const scoped = await readdir2(entryPath, { withFileTypes: true }).catch(() => []);
4345
4526
  for (const child of scoped) {
4346
- const childPath = join7(entryPath, child.name);
4527
+ const childPath = join8(entryPath, child.name);
4347
4528
  const childIsDirectory = child.isDirectory() || child.isSymbolicLink() && (await stat2(childPath).catch(() => void 0))?.isDirectory();
4348
4529
  if (childIsDirectory) directories.push(childPath);
4349
4530
  }
@@ -4356,19 +4537,19 @@ async function packageDirectories(root) {
4356
4537
  async function loadProviderPlugins(options) {
4357
4538
  const moduleDirectory = dirname6(fileURLToPath5(import.meta.url));
4358
4539
  const roots = [
4359
- join7(options.configDirectory, "plugins"),
4360
- join7(options.cwd ?? process.cwd(), "node_modules"),
4361
- resolve4(moduleDirectory, "node_modules"),
4362
- resolve4(moduleDirectory, "../../../../node_modules")
4540
+ join8(options.configDirectory, "plugins"),
4541
+ join8(options.cwd ?? process.cwd(), "node_modules"),
4542
+ resolve5(moduleDirectory, "node_modules"),
4543
+ resolve5(moduleDirectory, "../../../../node_modules")
4363
4544
  ];
4364
4545
  const seen = /* @__PURE__ */ new Set();
4365
4546
  const diagnostics = [];
4366
4547
  for (const root of roots) {
4367
4548
  for (const packageDir of await packageDirectories(root)) {
4368
- const manifestPath = join7(packageDir, "package.json");
4549
+ const manifestPath = join8(packageDir, "package.json");
4369
4550
  let manifest;
4370
4551
  try {
4371
- manifest = JSON.parse(await readFile2(manifestPath, "utf8"));
4552
+ manifest = JSON.parse(await readFile3(manifestPath, "utf8"));
4372
4553
  } catch {
4373
4554
  continue;
4374
4555
  }
@@ -4406,7 +4587,7 @@ async function loadProviderPlugins(options) {
4406
4587
  }
4407
4588
  };
4408
4589
  try {
4409
- const module = await import(pathToFileURL(join7(packageDir, plugin)).href);
4590
+ const module = await import(pathToFileURL(join8(packageDir, plugin)).href);
4410
4591
  if (typeof module.register !== "function") throw new Error("Plugin does not export register(registry)");
4411
4592
  await module.register(trackingRegistry);
4412
4593
  diagnostic.loaded = true;
@@ -4516,7 +4697,7 @@ async function createServerHandle(config3) {
4516
4697
  setMcpTools(mcpTools);
4517
4698
  logger.info("MCP tools registered", { count: mcpTools.length });
4518
4699
  }
4519
- const { signalMcpReady } = await import("./server-PXXGMFBT.js");
4700
+ const { signalMcpReady } = await import("./server-OYE7GERR.js");
4520
4701
  signalMcpReady();
4521
4702
  });
4522
4703
  const app = express();
@@ -4578,7 +4759,7 @@ async function createServerHandle(config3) {
4578
4759
  res.json({ tools });
4579
4760
  });
4580
4761
  app.get("/api/projects", async (_req, res) => {
4581
- const { listProjects } = await import("./projects-BY227WT2.js");
4762
+ const { listProjects } = await import("./projects-7HSBZY2D.js");
4582
4763
  const projects = listProjects();
4583
4764
  res.json({ projects });
4584
4765
  });
@@ -4587,7 +4768,7 @@ async function createServerHandle(config3) {
4587
4768
  if (!name || !workdir) {
4588
4769
  return res.status(400).json({ error: "name and workdir are required" });
4589
4770
  }
4590
- const { createDirectoryWithGit } = await import("./project-creator-IDW7RACH.js");
4771
+ const { createDirectoryWithGit } = await import("./project-creator-EMGRSPYS.js");
4591
4772
  try {
4592
4773
  const project = await createDirectoryWithGit(name, workdir);
4593
4774
  res.status(201).json({ project });
@@ -4632,7 +4813,7 @@ async function createServerHandle(config3) {
4632
4813
  }
4633
4814
  });
4634
4815
  app.get("/api/projects/:id", async (req, res) => {
4635
- const { getProject: getProject2 } = await import("./projects-BY227WT2.js");
4816
+ const { getProject: getProject2 } = await import("./projects-7HSBZY2D.js");
4636
4817
  const project = getProject2(req.params.id);
4637
4818
  if (!project) {
4638
4819
  return res.status(404).json({ error: "Project not found" });
@@ -4640,7 +4821,7 @@ async function createServerHandle(config3) {
4640
4821
  res.json({ project });
4641
4822
  });
4642
4823
  app.put("/api/projects/:id", async (req, res) => {
4643
- const { updateProject } = await import("./projects-BY227WT2.js");
4824
+ const { updateProject } = await import("./projects-7HSBZY2D.js");
4644
4825
  const { name, customInstructions, dangerLevel } = req.body;
4645
4826
  const updates = {};
4646
4827
  if (name !== void 0) updates.name = name;
@@ -4653,7 +4834,7 @@ async function createServerHandle(config3) {
4653
4834
  res.json({ project: updated });
4654
4835
  });
4655
4836
  app.delete("/api/projects/:id", async (req, res) => {
4656
- const { getProject: getProject2, deleteProject } = await import("./projects-BY227WT2.js");
4837
+ const { getProject: getProject2, deleteProject } = await import("./projects-7HSBZY2D.js");
4657
4838
  const project = getProject2(req.params.id);
4658
4839
  if (!project) {
4659
4840
  return res.status(404).json({ error: "Project not found" });
@@ -4662,7 +4843,7 @@ async function createServerHandle(config3) {
4662
4843
  res.json({ success: true });
4663
4844
  });
4664
4845
  app.put("/api/projects/:id/star", async (req, res) => {
4665
- const { toggleStar } = await import("./projects-BY227WT2.js");
4846
+ const { toggleStar } = await import("./projects-7HSBZY2D.js");
4666
4847
  const { isStarred } = req.body;
4667
4848
  if (typeof isStarred !== "boolean") {
4668
4849
  return res.status(400).json({ error: "isStarred is required and must be a boolean" });
@@ -4673,8 +4854,53 @@ async function createServerHandle(config3) {
4673
4854
  }
4674
4855
  res.json({ project });
4675
4856
  });
4857
+ app.get("/api/projects/:id/branches", async (req, res) => {
4858
+ const { getProject: getProject2 } = await import("./projects-7HSBZY2D.js");
4859
+ const project = getProject2(req.params.id);
4860
+ if (!project) return res.status(404).json({ error: "Project not found" });
4861
+ const { listBranches } = await import("./worktree-6U45P63P.js");
4862
+ const branches = await listBranches(project.workdir);
4863
+ res.json({ branches });
4864
+ });
4865
+ app.post("/api/projects/:id/checkout", async (req, res) => {
4866
+ const { getProject: getProject2 } = await import("./projects-7HSBZY2D.js");
4867
+ const project = getProject2(req.params.id);
4868
+ if (!project) return res.status(404).json({ error: "Project not found" });
4869
+ const { branch } = req.body;
4870
+ if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
4871
+ const { checkoutBranch } = await import("./worktree-6U45P63P.js");
4872
+ try {
4873
+ await checkoutBranch(project.workdir, branch);
4874
+ res.json({ branch });
4875
+ } catch (err) {
4876
+ res.status(400).json({ error: err instanceof Error ? err.message : "Failed to checkout branch" });
4877
+ }
4878
+ });
4879
+ app.post("/api/projects/:id/checkout-new", async (req, res) => {
4880
+ const { getProject: getProject2 } = await import("./projects-7HSBZY2D.js");
4881
+ const project = getProject2(req.params.id);
4882
+ if (!project) return res.status(404).json({ error: "Project not found" });
4883
+ const { name } = req.body;
4884
+ if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
4885
+ const { createBranch } = await import("./worktree-6U45P63P.js");
4886
+ try {
4887
+ await createBranch(project.workdir, name);
4888
+ res.json({ branch: name });
4889
+ } catch (err) {
4890
+ res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create branch" });
4891
+ }
4892
+ });
4893
+ app.get("/api/projects/:id/worktrees", async (req, res) => {
4894
+ const { getProject: getProject2 } = await import("./projects-7HSBZY2D.js");
4895
+ const project = getProject2(req.params.id);
4896
+ if (!project) return res.status(404).json({ error: "Project not found" });
4897
+ const { listWorktrees } = await import("./worktree-6U45P63P.js");
4898
+ const all = await listWorktrees(project.workdir);
4899
+ const worktrees = all.filter((wt) => wt.path !== project.workdir);
4900
+ res.json({ worktrees });
4901
+ });
4676
4902
  app.get("/api/sessions", async (req, res) => {
4677
- const { getRecentUserPromptsForSession } = await import("./events-52XADT6Y.js");
4903
+ const { getRecentUserPromptsForSession } = await import("./events-CDQ4HASP.js");
4678
4904
  const projectId = req.query["projectId"];
4679
4905
  const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
4680
4906
  const offset = parseInt(req.query["offset"]) || 0;
@@ -4706,10 +4932,44 @@ async function createServerHandle(config3) {
4706
4932
  const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
4707
4933
  res.status(201).json({ session });
4708
4934
  });
4935
+ app.post("/api/sessions/:id/worktree", async (req, res) => {
4936
+ const session = sessionManager.getSession(req.params.id);
4937
+ if (!session) return res.status(404).json({ error: "Session not found" });
4938
+ const { name } = req.body;
4939
+ if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
4940
+ try {
4941
+ const updated = await sessionManager.createSessionWorktree(req.params.id, name);
4942
+ res.json({ session: updated });
4943
+ } catch (err) {
4944
+ res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create worktree" });
4945
+ }
4946
+ });
4947
+ app.post("/api/sessions/:id/close-worktree", async (req, res) => {
4948
+ const session = sessionManager.getSession(req.params.id);
4949
+ if (!session) return res.status(404).json({ error: "Session not found" });
4950
+ try {
4951
+ const updated = await sessionManager.closeSessionWorktree(req.params.id);
4952
+ res.json({ session: updated });
4953
+ } catch (err) {
4954
+ res.status(400).json({ error: err instanceof Error ? err.message : "Failed to close worktree" });
4955
+ }
4956
+ });
4957
+ app.post("/api/sessions/:id/attach-worktree", async (req, res) => {
4958
+ const session = sessionManager.getSession(req.params.id);
4959
+ if (!session) return res.status(404).json({ error: "Session not found" });
4960
+ const { path } = req.body;
4961
+ if (!path || typeof path !== "string") return res.status(400).json({ error: "path is required" });
4962
+ try {
4963
+ const updated = await sessionManager.attachSessionWorktree(req.params.id, path);
4964
+ res.json({ session: updated });
4965
+ } catch (err) {
4966
+ res.status(400).json({ error: err instanceof Error ? err.message : "Failed to attach worktree" });
4967
+ }
4968
+ });
4709
4969
  app.get("/api/sessions/:id", async (req, res) => {
4710
- const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4711
- const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
4712
- const { getPendingQuestionsForSession } = await import("./tools-ZZM36DAZ.js");
4970
+ const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
4971
+ const { buildMessagesFromStoredEvents } = await import("./folding-V2K34EGN.js");
4972
+ const { getPendingQuestionsForSession } = await import("./tools-INWP6FGV.js");
4713
4973
  const session = sessionManager.getSession(req.params.id);
4714
4974
  if (!session) {
4715
4975
  return res.status(404).json({ error: "Session not found" });
@@ -4728,8 +4988,8 @@ async function createServerHandle(config3) {
4728
4988
  if (!session) {
4729
4989
  return res.status(404).json({ error: "Session not found" });
4730
4990
  }
4731
- const { stopSessionExecution } = await import("./chat-handler-MC3XZ3OV.js");
4732
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-ZZM36DAZ.js");
4991
+ const { stopSessionExecution } = await import("./chat-handler-72DFHK5K.js");
4992
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-INWP6FGV.js");
4733
4993
  sessionManager.clearMessageQueue(sessionId);
4734
4994
  stopSessionExecution(sessionId, sessionManager);
4735
4995
  abortSession(sessionId);
@@ -4748,8 +5008,8 @@ async function createServerHandle(config3) {
4748
5008
  res.json({ success: true });
4749
5009
  });
4750
5010
  app.post("/api/sessions/:id/provider", async (req, res) => {
4751
- const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4752
- const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
5011
+ const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
5012
+ const { buildMessagesFromStoredEvents } = await import("./folding-V2K34EGN.js");
4753
5013
  const sessionId = req.params.id;
4754
5014
  const session = sessionManager.getSession(sessionId);
4755
5015
  if (!session) {
@@ -4826,8 +5086,8 @@ async function createServerHandle(config3) {
4826
5086
  res.json({ success: true });
4827
5087
  });
4828
5088
  app.put("/api/sessions/:id/mode", async (req, res) => {
4829
- const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4830
- const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
5089
+ const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
5090
+ const { buildMessagesFromStoredEvents } = await import("./folding-V2K34EGN.js");
4831
5091
  const sessionId = req.params.id;
4832
5092
  const session = sessionManager.getSession(sessionId);
4833
5093
  if (!session) {
@@ -4883,15 +5143,15 @@ async function createServerHandle(config3) {
4883
5143
  if (!callId || approved === void 0) {
4884
5144
  return res.status(400).json({ error: "callId and approved are required" });
4885
5145
  }
4886
- const { providePathConfirmation } = await import("./tools-ZZM36DAZ.js");
5146
+ const { providePathConfirmation } = await import("./tools-INWP6FGV.js");
4887
5147
  const result = providePathConfirmation(callId, approved, alwaysAllow);
4888
5148
  if (!result.found) {
4889
5149
  return res.status(404).json({ error: "No pending path confirmation with that ID" });
4890
5150
  }
4891
- const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
4892
- const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-2BGFLV5J.js");
5151
+ const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
5152
+ const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-V2K34EGN.js");
4893
5153
  const { createSessionStateMessage } = await import("./protocol-CTNE3ANP.js");
4894
- const { getPendingQuestionsForSession } = await import("./tools-ZZM36DAZ.js");
5154
+ const { getPendingQuestionsForSession } = await import("./tools-INWP6FGV.js");
4895
5155
  const eventStore = getEventStore2();
4896
5156
  const events = eventStore.getEvents(sessionId);
4897
5157
  const messages = buildMessagesFromStoredEvents(events);
@@ -4912,7 +5172,7 @@ async function createServerHandle(config3) {
4912
5172
  if (!skip && typeof answer !== "string") {
4913
5173
  return res.status(400).json({ error: "answer is required when not skipping" });
4914
5174
  }
4915
- const { provideAnswer } = await import("./tools-ZZM36DAZ.js");
5175
+ const { provideAnswer } = await import("./tools-INWP6FGV.js");
4916
5176
  const found = provideAnswer(callId, answer ?? "", skip ?? false);
4917
5177
  if (!found) {
4918
5178
  return res.status(404).json({ error: "No pending question with that ID" });
@@ -4940,7 +5200,7 @@ async function createServerHandle(config3) {
4940
5200
  if (!session) {
4941
5201
  return res.status(404).json({ error: "Session not found" });
4942
5202
  }
4943
- const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-JA4XUR3W.js");
5203
+ const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-6ZPWOBWL.js");
4944
5204
  if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
4945
5205
  return res.json({ success: false, reason: "disabled" });
4946
5206
  }
@@ -4972,7 +5232,7 @@ async function createServerHandle(config3) {
4972
5232
  backend: activeProvider?.backend ?? llmClient.getBackend(),
4973
5233
  model: llmClient.getModel()
4974
5234
  };
4975
- const { runAgentTurn, TurnMetrics } = await import("./orchestrator-IYJRQQKB.js");
5235
+ const { runAgentTurn, TurnMetrics } = await import("./orchestrator-FEMPJOZD.js");
4976
5236
  runAgentTurn(
4977
5237
  {
4978
5238
  sessionManager,
@@ -5010,15 +5270,15 @@ async function createServerHandle(config3) {
5010
5270
  if (!session) {
5011
5271
  return res.status(404).json({ error: "Session not found" });
5012
5272
  }
5013
- const { stopSessionExecution } = await import("./chat-handler-MC3XZ3OV.js");
5014
- const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-ZZM36DAZ.js");
5273
+ const { stopSessionExecution } = await import("./chat-handler-72DFHK5K.js");
5274
+ const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-INWP6FGV.js");
5015
5275
  const queuedMessages = sessionManager.getQueueState(sessionId);
5016
5276
  sessionManager.clearMessageQueue(sessionId);
5017
5277
  stopSessionExecution(sessionId, sessionManager);
5018
5278
  abortSession(sessionId);
5019
5279
  cancelQuestionsForSession(sessionId, "Session stopped by user");
5020
5280
  cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
5021
- const eventStore = (await import("./events-52XADT6Y.js")).getEventStore();
5281
+ const eventStore = (await import("./events-CDQ4HASP.js")).getEventStore();
5022
5282
  eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
5023
5283
  res.json({ success: true, queuedMessages });
5024
5284
  });
@@ -5032,7 +5292,7 @@ async function createServerHandle(config3) {
5032
5292
  if (typeof messageIndex !== "number" || messageIndex < 0) {
5033
5293
  return res.status(400).json({ error: "messageIndex must be a non-negative number" });
5034
5294
  }
5035
- const { truncateSessionMessages } = await import("./events-52XADT6Y.js");
5295
+ const { truncateSessionMessages } = await import("./events-CDQ4HASP.js");
5036
5296
  truncateSessionMessages(sessionId, messageIndex);
5037
5297
  res.json({ success: true });
5038
5298
  });
@@ -5046,8 +5306,8 @@ async function createServerHandle(config3) {
5046
5306
  if (typeof messageId !== "string" || !messageId) {
5047
5307
  return res.status(400).json({ error: "messageId is required" });
5048
5308
  }
5049
- const { getEventStore: getEventStore2 } = await import("./events-52XADT6Y.js");
5050
- const { buildMessagesFromStoredEvents } = await import("./folding-2BGFLV5J.js");
5309
+ const { getEventStore: getEventStore2 } = await import("./events-CDQ4HASP.js");
5310
+ const { buildMessagesFromStoredEvents } = await import("./folding-V2K34EGN.js");
5051
5311
  const eventStore = getEventStore2();
5052
5312
  const events = eventStore.getEvents(sessionId);
5053
5313
  const messages = buildMessagesFromStoredEvents(events);
@@ -5059,7 +5319,7 @@ async function createServerHandle(config3) {
5059
5319
  if (msg.role !== "user" || msg.isSystemGenerated) {
5060
5320
  return res.status(400).json({ error: "Can only replay user messages" });
5061
5321
  }
5062
- const { truncateSessionMessages } = await import("./events-52XADT6Y.js");
5322
+ const { truncateSessionMessages } = await import("./events-CDQ4HASP.js");
5063
5323
  truncateSessionMessages(sessionId, msgIndex - 1);
5064
5324
  sessionManager.queueMessage(sessionId, "asap", msg.content, msg.attachments, msg.messageKind);
5065
5325
  res.json({ success: true });
@@ -5091,7 +5351,7 @@ async function createServerHandle(config3) {
5091
5351
  res.json({ accepted: true });
5092
5352
  });
5093
5353
  app.get("/api/settings", async (req, res) => {
5094
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-JA4XUR3W.js");
5354
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6ZPWOBWL.js");
5095
5355
  const keysParam = req.query["keys"];
5096
5356
  if (!keysParam) {
5097
5357
  return res.status(400).json({ error: "keys query parameter is required" });
@@ -5104,19 +5364,19 @@ async function createServerHandle(config3) {
5104
5364
  res.json(result);
5105
5365
  });
5106
5366
  app.get("/api/settings/:key", async (req, res) => {
5107
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-JA4XUR3W.js");
5367
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6ZPWOBWL.js");
5108
5368
  const key = req.params.key;
5109
5369
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
5110
5370
  res.json({ key, value });
5111
5371
  });
5112
5372
  app.get("/api/settings/:key", async (req, res) => {
5113
- const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-JA4XUR3W.js");
5373
+ const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-6ZPWOBWL.js");
5114
5374
  const key = req.params.key;
5115
5375
  const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
5116
5376
  res.json({ key, value });
5117
5377
  });
5118
5378
  app.put("/api/settings/:key", async (req, res) => {
5119
- const { setSetting: setSetting2 } = await import("./settings-JA4XUR3W.js");
5379
+ const { setSetting: setSetting2 } = await import("./settings-6ZPWOBWL.js");
5120
5380
  const key = req.params.key;
5121
5381
  const { value } = req.body;
5122
5382
  if (value === void 0) {
@@ -5128,20 +5388,24 @@ async function createServerHandle(config3) {
5128
5388
  app.get("/api/tools/rtk-check", async (_req, res) => {
5129
5389
  const { spawn: spawn3 } = await import("child_process");
5130
5390
  try {
5131
- const available = await new Promise((resolve6) => {
5391
+ const available = await new Promise((resolve7) => {
5132
5392
  const proc = spawn3("rtk", ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
5133
5393
  let out = "";
5134
5394
  proc.stdout?.on("data", (d) => {
5135
5395
  out += d.toString();
5136
5396
  });
5137
- proc.on("error", () => resolve6(false));
5138
- proc.on("close", (code) => resolve6(code === 0 && out.startsWith("rtk ")));
5397
+ proc.on("error", () => resolve7(false));
5398
+ proc.on("close", (code) => resolve7(code === 0 && out.startsWith("rtk ")));
5139
5399
  });
5140
5400
  res.json({ available });
5141
5401
  } catch {
5142
5402
  res.json({ available: false });
5143
5403
  }
5144
5404
  });
5405
+ app.get("/api/tools/shells", async (_req, res) => {
5406
+ const { listAvailableShells } = await import("./platform-AB3GIEGO.js");
5407
+ res.json({ shells: listAvailableShells() });
5408
+ });
5145
5409
  app.get("/api/config", async (_req, res) => {
5146
5410
  const llmClient = getLLMClient();
5147
5411
  const activeProvider = providerManager.getActiveProvider();
@@ -5301,7 +5565,7 @@ async function createServerHandle(config3) {
5301
5565
  const backend = req.query["backend"];
5302
5566
  if (!url) return res.status(400).json({ error: "url is required" });
5303
5567
  try {
5304
- const { fetchModelsWithContext } = await import("./provider-manager-HRHNF73A.js");
5568
+ const { fetchModelsWithContext } = await import("./provider-manager-D3KIOD5E.js");
5305
5569
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
5306
5570
  const models = await fetchModelsWithContext(
5307
5571
  url,
@@ -5371,7 +5635,7 @@ async function createServerHandle(config3) {
5371
5635
  }
5372
5636
  const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
5373
5637
  const { getBackendCapabilities } = await import("./backend-P3GHHLHJ.js");
5374
- const { buildNonStreamingCreateParams } = await import("./client-pure-DO3S675T.js");
5638
+ const { buildNonStreamingCreateParams } = await import("./client-pure-U6ZYUPJQ.js");
5375
5639
  const { OpenAIHttpClient } = await import("./http-client-PIWB7BXK.js");
5376
5640
  const { ensureVersionPrefix } = await import("./url-utils-SAJP7AEX.js");
5377
5641
  const profile = getModelProfile2(model);
@@ -5629,7 +5893,7 @@ async function createServerHandle(config3) {
5629
5893
  });
5630
5894
  async function rebuildMcpTools() {
5631
5895
  const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
5632
- const { setMcpTools: setMcpTools2 } = await import("./tools-ZZM36DAZ.js");
5896
+ const { setMcpTools: setMcpTools2 } = await import("./tools-INWP6FGV.js");
5633
5897
  const mcpTools = createMcpTools2(mcpManager);
5634
5898
  setMcpTools2(mcpTools);
5635
5899
  }
@@ -5784,6 +6048,7 @@ async function createServerHandle(config3) {
5784
6048
  app.use("/api/agents", createAgentRoutes(configDir, projectDir));
5785
6049
  app.use("/api/workflows", createWorkflowRoutes(configDir, config3, projectDir));
5786
6050
  app.use("/api/dev-server", createDevServerRoutes());
6051
+ app.use("/api/worktree", createWorktreeConfigRoutes());
5787
6052
  app.use("/api/terminals", createTerminalRoutes());
5788
6053
  app.use(
5789
6054
  "/api/auto-update",
@@ -5800,13 +6065,13 @@ async function createServerHandle(config3) {
5800
6065
  })
5801
6066
  );
5802
6067
  app.get("/api/sessions/:id/background-processes", async (req, res) => {
5803
- const { getSessionProcesses } = await import("./manager-344C5JLZ.js");
6068
+ const { getSessionProcesses } = await import("./manager-JXYRGR6B.js");
5804
6069
  const sessionId = req.params.id;
5805
6070
  const processes = getSessionProcesses(sessionId);
5806
6071
  res.json({ processes });
5807
6072
  });
5808
6073
  app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
5809
- const { stopProcess } = await import("./manager-344C5JLZ.js");
6074
+ const { stopProcess } = await import("./manager-JXYRGR6B.js");
5810
6075
  const sessionId = req.params.id;
5811
6076
  const processId = req.params.processId;
5812
6077
  const session = sessionManager.getSession(sessionId);
@@ -5820,20 +6085,20 @@ async function createServerHandle(config3) {
5820
6085
  res.status(500).json({ error: err instanceof Error ? err.message : "Failed to stop process" });
5821
6086
  }
5822
6087
  });
5823
- const { getCurrentBranch } = await import("./branch.api-LAN42BA5.js");
6088
+ const { getCurrentBranch } = await import("./branch.api-3YJSWOZG.js");
5824
6089
  app.get("/api/branch", async (req, res) => {
5825
6090
  await getCurrentBranch(req, res);
5826
6091
  });
5827
6092
  app.use("/api/directories", createDirectoryRoutes());
5828
6093
  app.use("/api/files", createFileSearchRoutes());
5829
- const webDir = resolve5(__dirname3, "../../web");
6094
+ const webDir = resolve6(__dirname3, "../../web");
5830
6095
  const isDev = config3.mode === "development";
5831
6096
  let viteServer;
5832
6097
  if (isDev) {
5833
6098
  logger.info("Dev mode: using Vite middleware");
5834
6099
  viteServer = await createViteServer({
5835
6100
  root: webDir,
5836
- configFile: resolve5(__dirname3, "../../web/vite.config.ts"),
6101
+ configFile: resolve6(__dirname3, "../../web/vite.config.ts"),
5837
6102
  server: { middlewareMode: true },
5838
6103
  appType: "spa",
5839
6104
  logLevel: "warn"
@@ -5853,7 +6118,7 @@ async function createServerHandle(config3) {
5853
6118
  }
5854
6119
  });
5855
6120
  app.get("/fox.svg", (_req, res) => {
5856
- readFile3(join8(webDir, "fox.svg")).then((content) => {
6121
+ readFile4(join9(webDir, "fox.svg")).then((content) => {
5857
6122
  res.set("Content-Type", "image/svg+xml");
5858
6123
  res.send(content);
5859
6124
  }).catch(() => {
@@ -5862,7 +6127,7 @@ async function createServerHandle(config3) {
5862
6127
  });
5863
6128
  app.use(
5864
6129
  "/sounds",
5865
- express.static(join8(webDir, "public", "sounds"), {
6130
+ express.static(join9(webDir, "public", "sounds"), {
5866
6131
  setHeaders: (res) => {
5867
6132
  res.set("Content-Type", "audio/mpeg");
5868
6133
  }
@@ -5871,13 +6136,13 @@ async function createServerHandle(config3) {
5871
6136
  app.use("/__inspect__.js", (_req, res) => {
5872
6137
  res.set("Access-Control-Allow-Origin", "*");
5873
6138
  res.set("Content-Type", "application/javascript");
5874
- readFile3(join8(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6139
+ readFile4(join9(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5875
6140
  });
5876
6141
  app.get("/*path", (req, res) => {
5877
6142
  if (req.path.startsWith("/api/")) {
5878
6143
  return;
5879
6144
  }
5880
- readFile3(join8(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
6145
+ readFile4(join9(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
5881
6146
  logger.error("Error serving index.html", { error: err });
5882
6147
  res.status(500).send("Server error");
5883
6148
  });
@@ -5885,10 +6150,10 @@ async function createServerHandle(config3) {
5885
6150
  logger.info("Vite middleware ready", { port: config3.server.port });
5886
6151
  }
5887
6152
  if (!isDev) {
5888
- const distWebDir = resolve5(__dirname3, "web");
6153
+ const distWebDir = resolve6(__dirname3, "web");
5889
6154
  app.use(
5890
6155
  "/assets",
5891
- express.static(join8(distWebDir, "assets"), {
6156
+ express.static(join9(distWebDir, "assets"), {
5892
6157
  setHeaders: (res, filepath) => {
5893
6158
  if (filepath.endsWith(".css")) {
5894
6159
  res.set("Content-Type", "text/css");
@@ -5896,11 +6161,11 @@ async function createServerHandle(config3) {
5896
6161
  }
5897
6162
  })
5898
6163
  );
5899
- app.use("/manifest.webmanifest", express.static(join8(distWebDir, "manifest.webmanifest")));
5900
- app.use("/registerSW.js", express.static(join8(distWebDir, "registerSW.js")));
5901
- app.use("/sw.js", express.static(join8(distWebDir, "sw.js")));
6164
+ app.use("/manifest.webmanifest", express.static(join9(distWebDir, "manifest.webmanifest")));
6165
+ app.use("/registerSW.js", express.static(join9(distWebDir, "registerSW.js")));
6166
+ app.use("/sw.js", express.static(join9(distWebDir, "sw.js")));
5902
6167
  app.get("/fox.svg", (_req, res) => {
5903
- readFile3(join8(distWebDir, "fox.svg")).then((content) => {
6168
+ readFile4(join9(distWebDir, "fox.svg")).then((content) => {
5904
6169
  res.set("Content-Type", "image/svg+xml");
5905
6170
  res.send(content);
5906
6171
  }).catch(() => {
@@ -5909,7 +6174,7 @@ async function createServerHandle(config3) {
5909
6174
  });
5910
6175
  app.use(
5911
6176
  "/sounds",
5912
- express.static(join8(distWebDir, "sounds"), {
6177
+ express.static(join9(distWebDir, "sounds"), {
5913
6178
  setHeaders: (res) => {
5914
6179
  res.set("Content-Type", "audio/mpeg");
5915
6180
  }
@@ -5918,10 +6183,10 @@ async function createServerHandle(config3) {
5918
6183
  app.use("/__inspect__.js", (_req, res) => {
5919
6184
  res.set("Access-Control-Allow-Origin", "*");
5920
6185
  res.set("Content-Type", "application/javascript");
5921
- readFile3(join8(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
6186
+ readFile4(join9(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
5922
6187
  });
5923
6188
  app.get("/", (_req, res) => {
5924
- readFile3(join8(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6189
+ readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5925
6190
  res.status(404).send("Web UI not built. Run `npm run build:web`");
5926
6191
  });
5927
6192
  });
@@ -5929,7 +6194,7 @@ async function createServerHandle(config3) {
5929
6194
  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") {
5930
6195
  return;
5931
6196
  }
5932
- readFile3(join8(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
6197
+ readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
5933
6198
  res.status(404).send("Web UI not built");
5934
6199
  });
5935
6200
  });
@@ -5949,7 +6214,7 @@ async function createServerHandle(config3) {
5949
6214
  const state = sessionManager.getContextState(sessionId);
5950
6215
  wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
5951
6216
  });
5952
- const { QueueProcessor } = await import("./processor-LUXKVIED.js");
6217
+ const { QueueProcessor } = await import("./processor-QB3NMRMO.js");
5953
6218
  const queueProcessor = new QueueProcessor({
5954
6219
  sessionManager,
5955
6220
  providerManager,
@@ -5972,7 +6237,7 @@ async function createServerHandle(config3) {
5972
6237
  return {
5973
6238
  httpServer,
5974
6239
  ctx: { config: config3, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },
5975
- start: (port) => new Promise((resolve6, reject) => {
6240
+ start: (port) => new Promise((resolve7, reject) => {
5976
6241
  const listenPort = port ?? config3.server.port;
5977
6242
  const host = config3.server.host;
5978
6243
  httpServer.listen(listenPort, host, () => {
@@ -5982,16 +6247,16 @@ async function createServerHandle(config3) {
5982
6247
  logger.info(`OpenFox server running at http://${host}:${actualPort}`);
5983
6248
  logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`);
5984
6249
  logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config3.llm.baseUrl}`);
5985
- resolve6({ port: actualPort });
6250
+ resolve7({ port: actualPort });
5986
6251
  });
5987
6252
  httpServer.on("error", reject);
5988
6253
  }),
5989
- close: () => new Promise((resolve6) => {
6254
+ close: () => new Promise((resolve7) => {
5990
6255
  logger.info("Shutting down...");
5991
6256
  void (async () => {
5992
6257
  await devServerManager.stopAll();
5993
6258
  await mcpManager.disconnectAll();
5994
- const { stopAllInspectProxies } = await import("./inspect-proxy-BV25JERQ.js");
6259
+ const { stopAllInspectProxies } = await import("./inspect-proxy-OVEFBJ26.js");
5995
6260
  stopAllInspectProxies();
5996
6261
  const { cleanupAllProcesses } = await import("./store-FXTCHBI4.js");
5997
6262
  cleanupAllProcesses();
@@ -6005,7 +6270,7 @@ async function createServerHandle(config3) {
6005
6270
  client.terminate();
6006
6271
  }
6007
6272
  wss.close();
6008
- httpServer.close(() => resolve6());
6273
+ httpServer.close(() => resolve7());
6009
6274
  })();
6010
6275
  })
6011
6276
  };
@@ -6030,4 +6295,4 @@ export {
6030
6295
  createServerHandle,
6031
6296
  createServer
6032
6297
  };
6033
- //# sourceMappingURL=chunk-Z6H7SFQR.js.map
6298
+ //# sourceMappingURL=chunk-2GRUQN2B.js.map