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.
- package/README.md +1 -0
- package/dist/agent-defaults/builder.agent.md +1 -1
- package/dist/agent-defaults/code-reviewer.agent.md +0 -1
- package/dist/agent-defaults/explorer.agent.md +0 -1
- package/dist/agent-defaults/planner.agent.md +1 -1
- package/dist/{branch.api-LAN42BA5.js → branch.api-3YJSWOZG.js} +5 -1
- package/dist/{chat-handler-MC3XZ3OV.js → chat-handler-72DFHK5K.js} +16 -13
- package/dist/{chunk-Z6H7SFQR.js → chunk-2GRUQN2B.js} +435 -170
- package/dist/{chunk-LBGHZLLH.js → chunk-4QBDV6LX.js} +17 -14
- package/dist/{chunk-RYIREJAW.js → chunk-5EO6SEGV.js} +2 -2
- package/dist/{chunk-N4K3PNOS.js → chunk-B6JUWVTK.js} +95 -29
- package/dist/{chunk-QBYQ7KDX.js → chunk-B7WGOK7G.js} +16 -15
- package/dist/{chunk-Z6W4YHJB.js → chunk-BL5LOLVA.js} +17 -1
- package/dist/{chunk-TMUBLQFC.js → chunk-C3VLGVSQ.js} +3 -3
- package/dist/{chunk-ZPIZLTWU.js → chunk-GMXKJGJ2.js} +5 -1
- package/dist/{chunk-YQ3SOPBI.js → chunk-KXVFHMSM.js} +2 -2
- package/dist/{chunk-4UYKN6JU.js → chunk-MQHMT5WF.js} +3 -3
- package/dist/{chunk-VWPY2KWH.js → chunk-PYRH4G2J.js} +9 -35
- package/dist/{chunk-BGTEIA2S.js → chunk-TFCHWMOJ.js} +23 -30
- package/dist/{chunk-AIJE3RYH.js → chunk-TFDK6VSG.js} +33 -7
- package/dist/{chunk-X5YCWKNS.js → chunk-TJO4QFDQ.js} +59 -86
- package/dist/{chunk-QJ5FH5DP.js → chunk-TMHWQYWE.js} +4 -4
- package/dist/chunk-VLV3XWZS.js +191 -0
- package/dist/chunk-WGMJCFCE.js +14 -0
- package/dist/chunk-X5DOUA3Z.js +66 -0
- package/dist/{chunk-PXJ4NOP4.js → chunk-XUPKS5FL.js} +6 -4
- package/dist/{chunk-UEIQKG5P.js → chunk-YU6DZAVA.js} +303 -360
- package/dist/{chunk-OESYKZCM.js → chunk-ZLON3JTI.js} +3 -3
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{client-LAKW7TA5.js → client-BUX62J2K.js} +3 -3
- package/dist/{client-pure-DO3S675T.js → client-pure-U6ZYUPJQ.js} +6 -4
- package/dist/{compactor-I3N56PSJ.js → compactor-74CZVUWI.js} +9 -7
- package/dist/{events-52XADT6Y.js → events-CDQ4HASP.js} +4 -4
- package/dist/{folding-2BGFLV5J.js → folding-V2K34EGN.js} +2 -2
- package/dist/{inspect-proxy-BV25JERQ.js → inspect-proxy-OVEFBJ26.js} +4 -4
- package/dist/{manager-344C5JLZ.js → manager-JXYRGR6B.js} +6 -2
- package/dist/{orchestrator-IYJRQQKB.js → orchestrator-FEMPJOZD.js} +15 -14
- package/dist/package.json +2 -1
- package/dist/platform-AB3GIEGO.js +21 -0
- package/dist/{processor-LUXKVIED.js → processor-QB3NMRMO.js} +16 -13
- package/dist/{project-creator-IDW7RACH.js → project-creator-EMGRSPYS.js} +18 -5
- package/dist/{projects-BY227WT2.js → projects-7HSBZY2D.js} +3 -3
- package/dist/{protocol-Cq66hdDX.d.ts → protocol-42f_Png6.d.ts} +1 -1
- package/dist/provider/index.d.ts +4 -4
- package/dist/{provider-GYOW4OWQ.js → provider-BDH6JGZB.js} +4 -4
- package/dist/{provider-manager-HRHNF73A.js → provider-manager-D3KIOD5E.js} +4 -4
- package/dist/{serve-ZRTWVOL2.js → serve-32FAA4FX.js} +20 -17
- package/dist/server/index.d.ts +26 -8
- package/dist/server/index.js +19 -16
- package/dist/server-OYE7GERR.js +37 -0
- package/dist/{settings-JA4XUR3W.js → settings-6ZPWOBWL.js} +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/{tools-ZZM36DAZ.js → tools-INWP6FGV.js} +14 -11
- package/dist/{types-CDZakn7f.d.ts → types-apiMd7Df.d.ts} +1 -1
- package/dist/{types-akHmgvBk.d.ts → types-vezAEt_y.d.ts} +3 -1
- package/dist/web/assets/{index-Dc05znz4.css → index-BELeAs12.css} +1 -1
- package/dist/web/assets/index-C3n65CNu.js +303 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/worktree-6U45P63P.js +30 -0
- package/package.json +2 -1
- package/dist/server-PXXGMFBT.js +0 -34
- 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-
|
|
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-
|
|
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-
|
|
74
|
+
} from "./chunk-TJO4QFDQ.js";
|
|
75
75
|
import {
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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
|
|
161
|
-
import { readFile as
|
|
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((
|
|
1958
|
+
return new Promise((resolve7) => {
|
|
1925
1959
|
const existing = this.diagnostics.get(path);
|
|
1926
1960
|
if (existing !== void 0) {
|
|
1927
1961
|
setTimeout(() => {
|
|
1928
|
-
|
|
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
|
-
|
|
1968
|
+
resolve7(this.diagnostics.get(path) ?? []);
|
|
1935
1969
|
}, timeoutMs);
|
|
1936
|
-
this.pendingDiagnostics.set(path, { resolve:
|
|
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(
|
|
2153
|
-
paths.push(
|
|
2154
|
-
paths.push(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
2556
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
3247
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
3451
|
+
const staging = join3(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
|
|
3299
3452
|
try {
|
|
3300
|
-
await
|
|
3453
|
+
await mkdir2(staging, { recursive: false });
|
|
3301
3454
|
for (const file of files) {
|
|
3302
|
-
const target =
|
|
3303
|
-
await
|
|
3304
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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("~/") ?
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
3639
|
-
import { join as
|
|
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 =
|
|
3644
|
-
var DEFAULTS_DIR_ALT =
|
|
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
|
|
3800
|
+
return join6(configDir, "commands");
|
|
3648
3801
|
}
|
|
3649
3802
|
function getProjectCommandsDir(projectDir) {
|
|
3650
|
-
return
|
|
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(
|
|
3708
|
-
if (projectDir && await pathExists(
|
|
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
|
|
3868
|
+
await mkdir4(commandsDir, { recursive: true });
|
|
3716
3869
|
}
|
|
3717
|
-
const filePath =
|
|
3870
|
+
const filePath = join6(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
|
|
3718
3871
|
const content = matter2.stringify(command.prompt, command.metadata);
|
|
3719
|
-
await
|
|
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 =
|
|
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/
|
|
4070
|
+
// src/server/routes/worktree-config.ts
|
|
3918
4071
|
import { Router as Router5 } from "express";
|
|
3919
|
-
function
|
|
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
|
|
4140
|
+
import { Router as Router7 } from "express";
|
|
3960
4141
|
import { readdir } from "fs/promises";
|
|
3961
|
-
import { resolve as
|
|
4142
|
+
import { resolve as resolve4, join as join7, dirname as dirname5, basename as basename2 } from "path";
|
|
3962
4143
|
function createDirectoryRoutes() {
|
|
3963
|
-
const router =
|
|
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 =
|
|
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:
|
|
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
|
|
4177
|
+
import { Router as Router8 } from "express";
|
|
3997
4178
|
import fg from "fast-glob";
|
|
3998
4179
|
function createFileSearchRoutes() {
|
|
3999
|
-
const router =
|
|
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
|
|
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.
|
|
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 =
|
|
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((
|
|
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
|
-
|
|
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((
|
|
4158
|
-
child.on("close",
|
|
4159
|
-
child.on("error", () =>
|
|
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
|
|
4378
|
+
import { Router as Router10 } from "express";
|
|
4198
4379
|
function createProviderAuthRoutes(config3, providerManager, registry) {
|
|
4199
|
-
const router =
|
|
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
|
|
4329
|
-
import { dirname as dirname6, join as
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
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 =
|
|
4549
|
+
const manifestPath = join8(packageDir, "package.json");
|
|
4369
4550
|
let manifest;
|
|
4370
4551
|
try {
|
|
4371
|
-
manifest = JSON.parse(await
|
|
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(
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
4711
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
4712
|
-
const { getPendingQuestionsForSession } = await import("./tools-
|
|
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-
|
|
4732
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
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-
|
|
4752
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
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-
|
|
4830
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
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-
|
|
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-
|
|
4892
|
-
const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
5014
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
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-
|
|
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-
|
|
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-
|
|
5050
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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((
|
|
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", () =>
|
|
5138
|
-
proc.on("close", (code) =>
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
6153
|
+
const distWebDir = resolve6(__dirname3, "web");
|
|
5889
6154
|
app.use(
|
|
5890
6155
|
"/assets",
|
|
5891
|
-
express.static(
|
|
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(
|
|
5900
|
-
app.use("/registerSW.js", express.static(
|
|
5901
|
-
app.use("/sw.js", express.static(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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((
|
|
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
|
-
|
|
6250
|
+
resolve7({ port: actualPort });
|
|
5986
6251
|
});
|
|
5987
6252
|
httpServer.on("error", reject);
|
|
5988
6253
|
}),
|
|
5989
|
-
close: () => new Promise((
|
|
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-
|
|
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(() =>
|
|
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-
|
|
6298
|
+
//# sourceMappingURL=chunk-2GRUQN2B.js.map
|