openfox 2.0.71 → 2.0.73
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/dist/agent-defaults/builder.agent.md +1 -1
- package/dist/agent-defaults/planner.agent.md +1 -1
- package/dist/{chat-handler-IKLQ3ZUN.js → chat-handler-LK5RUAGO.js} +15 -15
- package/dist/{chunk-NEL2REUM.js → chunk-2DCJERYX.js} +4 -4
- package/dist/{chunk-TFDK6VSG.js → chunk-6XKM25OT.js} +13 -13
- package/dist/{chunk-TQGGMWS6.js → chunk-CHPRGEY5.js} +3 -3
- package/dist/{chunk-C3VLGVSQ.js → chunk-DJASQ2ZB.js} +11 -2
- package/dist/{chunk-4QBDV6LX.js → chunk-E5LLEO3C.js} +2 -2
- package/dist/{chunk-OLXHRPAD.js → chunk-EYXDM2FY.js} +243 -285
- package/dist/{chunk-Y4YESMVA.js → chunk-GMF36EZ3.js} +81 -92
- package/dist/{chunk-GMXKJGJ2.js → chunk-I4RWK2L2.js} +8 -4
- package/dist/{chunk-6V7DU7ID.js → chunk-KKRLQH6F.js} +3 -3
- package/dist/chunk-NE7OWIIO.js +7 -0
- package/dist/{chunk-F4PMNP7S.js → chunk-NOU2QIL5.js} +3 -2
- package/dist/{chunk-X7OCC37J.js → chunk-O2BE7KVQ.js} +8 -8
- package/dist/{chunk-PVUBCGAT.js → chunk-PYB2UEC3.js} +10 -4
- package/dist/{chunk-XUPKS5FL.js → chunk-QNKXZH3Z.js} +2 -2
- package/dist/{chunk-X5DOUA3Z.js → chunk-S7O77CVO.js} +2 -2
- package/dist/{chunk-Z42YTK3O.js → chunk-TK4BZIXA.js} +34 -23
- package/dist/{chunk-KXVFHMSM.js → chunk-UV3EMWL4.js} +2 -2
- package/dist/chunk-X2Y3AJPP.js +216 -0
- package/dist/{chunk-RKD2FML3.js → chunk-XWBNYU2L.js} +2 -2
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{compactor-MXXF5WQR.js → compactor-4UKYWC5F.js} +8 -8
- package/dist/{events-CDQ4HASP.js → events-AEQ6GQXI.js} +4 -4
- package/dist/{folding-V2K34EGN.js → folding-ONH3D4OK.js} +2 -2
- package/dist/{inspect-proxy-OVEFBJ26.js → inspect-proxy-PHVZBZUO.js} +4 -4
- package/dist/{manager-EHIQCIUP.js → manager-24C2AXVF.js} +5 -5
- package/dist/{orchestrator-YGCZZNNV.js → orchestrator-RTZVMWQV.js} +14 -14
- package/dist/package.json +1 -1
- package/dist/{platform-AB3GIEGO.js → platform-XQ7BS3KQ.js} +4 -4
- package/dist/{processor-K6UPVMIP.js → processor-3O26I7DO.js} +15 -15
- package/dist/{project-creator-EMGRSPYS.js → project-creator-FQRBN3RG.js} +3 -3
- package/dist/{projects-7HSBZY2D.js → projects-LHRNCUGW.js} +3 -3
- package/dist/{protocol-CTNE3ANP.js → protocol-4QFU7WAI.js} +2 -2
- package/dist/{protocol-DIhV-tAc.d.ts → protocol-DGQWVFcP.d.ts} +1 -1
- package/dist/provider/index.d.ts +4 -4
- package/dist/{serve-5IOKFKGL.js → serve-I6K7A7RL.js} +18 -18
- package/dist/server/index.d.ts +12 -22
- package/dist/server/index.js +17 -17
- package/dist/{server-T5QDCUBN.js → server-G2J4RAXL.js} +16 -16
- package/dist/{settings-6ZPWOBWL.js → settings-PFXRYXZU.js} +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/{tools-K3SNGBI2.js → tools-X52DFUS6.js} +13 -13
- package/dist/{types-BsfYpEai.d.ts → types-C4cG9CtC.d.ts} +3 -2
- package/dist/{types-CBC6lLqc.d.ts → types-DSZhFA8O.d.ts} +1 -1
- package/dist/{update-734IDLKT.js → update-RJB4GPHE.js} +2 -2
- package/dist/web/assets/index-C7SW16F7.js +305 -0
- package/dist/web/assets/{index-BVTG7SRG.css → index-CmechlaK.css} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/dist/workspace-ET3FHZYN.js +32 -0
- package/package.json +1 -1
- package/dist/chunk-7NMOWPNY.js +0 -7
- package/dist/chunk-VLV3XWZS.js +0 -191
- package/dist/web/assets/index-HTzupfR0.js +0 -305
- package/dist/worktree-6U45P63P.js +0 -30
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
tokenFromPassword,
|
|
22
22
|
verifyPassword,
|
|
23
23
|
workflowExists
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-TK4BZIXA.js";
|
|
25
25
|
import {
|
|
26
26
|
agentExists,
|
|
27
27
|
createToolRegistry,
|
|
@@ -66,11 +66,18 @@ import {
|
|
|
66
66
|
setSkillEnabled,
|
|
67
67
|
skillExists,
|
|
68
68
|
updateOwnedSkill
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-GMF36EZ3.js";
|
|
70
70
|
import {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
deleteWorkspace,
|
|
72
|
+
ensureWorkspace,
|
|
73
|
+
getCommitsBehind,
|
|
74
|
+
getGitBranch,
|
|
75
|
+
getWorkspacesDir,
|
|
76
|
+
loadWorkspaceConfig,
|
|
77
|
+
runGit,
|
|
78
|
+
saveWorkspaceConfig,
|
|
79
|
+
workspaceExists
|
|
80
|
+
} from "./chunk-X2Y3AJPP.js";
|
|
74
81
|
import {
|
|
75
82
|
EventEmitter
|
|
76
83
|
} from "./chunk-EU3WWTFH.js";
|
|
@@ -78,16 +85,16 @@ import {
|
|
|
78
85
|
ALWAYS_ALLOWED,
|
|
79
86
|
ALWAYS_ALLOWED_FOR_SUBAGENTS,
|
|
80
87
|
TOP_LEVEL_ONLY_TOOLS
|
|
81
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-XWBNYU2L.js";
|
|
82
89
|
import {
|
|
83
90
|
getProject
|
|
84
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-UV3EMWL4.js";
|
|
85
92
|
import {
|
|
86
93
|
createMcpTools
|
|
87
94
|
} from "./chunk-NWO6GRYE.js";
|
|
88
95
|
import {
|
|
89
96
|
VERSION
|
|
90
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-NE7OWIIO.js";
|
|
91
98
|
import {
|
|
92
99
|
createSession,
|
|
93
100
|
deleteSession,
|
|
@@ -115,22 +122,22 @@ import {
|
|
|
115
122
|
updateSessionProvider,
|
|
116
123
|
updateSessionRunning,
|
|
117
124
|
updateSessionWorkdir
|
|
118
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-6XKM25OT.js";
|
|
119
126
|
import {
|
|
120
127
|
createContextStateMessage
|
|
121
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-NOU2QIL5.js";
|
|
122
129
|
import {
|
|
123
130
|
getPathSeparator,
|
|
124
131
|
isAbsolutePath
|
|
125
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-S7O77CVO.js";
|
|
126
133
|
import {
|
|
127
134
|
deleteSetting,
|
|
128
135
|
getSetting,
|
|
129
136
|
setSetting
|
|
130
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-QNKXZH3Z.js";
|
|
131
138
|
import {
|
|
132
139
|
initDatabase
|
|
133
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-I4RWK2L2.js";
|
|
134
141
|
import {
|
|
135
142
|
createProviderManager,
|
|
136
143
|
detectModel,
|
|
@@ -165,8 +172,8 @@ import express from "express";
|
|
|
165
172
|
import cors from "cors";
|
|
166
173
|
import { createServer as createHttpServer } from "http";
|
|
167
174
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
168
|
-
import { dirname as dirname8, resolve as resolve7, join as
|
|
169
|
-
import { readFile as
|
|
175
|
+
import { dirname as dirname8, resolve as resolve7, join as join9 } from "path";
|
|
176
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
170
177
|
import { createServer as createViteServer } from "vite";
|
|
171
178
|
|
|
172
179
|
// src/server/llm/mock.ts
|
|
@@ -1607,34 +1614,8 @@ var McpManager = class {
|
|
|
1607
1614
|
}
|
|
1608
1615
|
};
|
|
1609
1616
|
|
|
1610
|
-
// src/server/
|
|
1611
|
-
import {
|
|
1612
|
-
import { resolve, join } from "path";
|
|
1613
|
-
var CONFIG_FILENAME = ".openfox/worktree.json";
|
|
1614
|
-
function getConfigPath(workdir) {
|
|
1615
|
-
return join(resolve(workdir), CONFIG_FILENAME);
|
|
1616
|
-
}
|
|
1617
|
-
async function loadWorktreeConfig(workdir) {
|
|
1618
|
-
try {
|
|
1619
|
-
const configPath = getConfigPath(workdir);
|
|
1620
|
-
const raw = await readFile(configPath, "utf-8");
|
|
1621
|
-
const parsed = JSON.parse(raw);
|
|
1622
|
-
if (!parsed.ignoredAssets) return null;
|
|
1623
|
-
return {
|
|
1624
|
-
ignoredAssets: parsed.ignoredAssets,
|
|
1625
|
-
overrides: parsed.overrides ?? void 0
|
|
1626
|
-
};
|
|
1627
|
-
} catch {
|
|
1628
|
-
return null;
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
async function saveWorktreeConfig(workdir, config3) {
|
|
1632
|
-
const resolved = resolve(workdir);
|
|
1633
|
-
const dirPath = join(resolved, ".openfox");
|
|
1634
|
-
await mkdir(dirPath, { recursive: true });
|
|
1635
|
-
const configPath = getConfigPath(workdir);
|
|
1636
|
-
await writeFile(configPath, JSON.stringify(config3, null, 2) + "\n", "utf-8");
|
|
1637
|
-
}
|
|
1617
|
+
// src/server/session/manager.ts
|
|
1618
|
+
import { resolve as resolve2 } from "path";
|
|
1638
1619
|
|
|
1639
1620
|
// src/server/lsp/server.ts
|
|
1640
1621
|
import { spawn } from "child_process";
|
|
@@ -2193,14 +2174,14 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
2193
2174
|
|
|
2194
2175
|
// src/server/utils/which.ts
|
|
2195
2176
|
import { access, constants } from "fs/promises";
|
|
2196
|
-
import { join
|
|
2177
|
+
import { join, dirname } from "path";
|
|
2197
2178
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2198
2179
|
var __dirname = dirname(fileURLToPath2(import.meta.url));
|
|
2199
2180
|
function getBundledBinPaths() {
|
|
2200
2181
|
const paths = [];
|
|
2201
|
-
paths.push(
|
|
2202
|
-
paths.push(
|
|
2203
|
-
paths.push(
|
|
2182
|
+
paths.push(join(process.cwd(), "node_modules", ".bin"));
|
|
2183
|
+
paths.push(join(__dirname, "..", "..", "..", "node_modules", ".bin"));
|
|
2184
|
+
paths.push(join(__dirname, "..", "..", "..", "..", "node_modules", ".bin"));
|
|
2204
2185
|
return paths;
|
|
2205
2186
|
}
|
|
2206
2187
|
async function existsExecutable(path) {
|
|
@@ -2219,7 +2200,7 @@ function candidateNames(command) {
|
|
|
2219
2200
|
}
|
|
2220
2201
|
async function findInDir(dir, command) {
|
|
2221
2202
|
for (const name of candidateNames(command)) {
|
|
2222
|
-
const fullPath =
|
|
2203
|
+
const fullPath = join(dir, name);
|
|
2223
2204
|
if (await existsExecutable(fullPath)) {
|
|
2224
2205
|
return fullPath;
|
|
2225
2206
|
}
|
|
@@ -2240,7 +2221,7 @@ async function which(command, workdir) {
|
|
|
2240
2221
|
}
|
|
2241
2222
|
}
|
|
2242
2223
|
if (workdir) {
|
|
2243
|
-
const found = await findInDir(
|
|
2224
|
+
const found = await findInDir(join(workdir, "node_modules", ".bin"), command);
|
|
2244
2225
|
if (found) {
|
|
2245
2226
|
return found;
|
|
2246
2227
|
}
|
|
@@ -2261,9 +2242,9 @@ async function which(command, workdir) {
|
|
|
2261
2242
|
import { extname as extname2, basename } from "path";
|
|
2262
2243
|
import { readFileSync } from "fs";
|
|
2263
2244
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2264
|
-
import { dirname as dirname2, resolve
|
|
2245
|
+
import { dirname as dirname2, resolve } from "path";
|
|
2265
2246
|
var __dirname2 = dirname2(fileURLToPath3(import.meta.url));
|
|
2266
|
-
var languagesJson = JSON.parse(readFileSync(
|
|
2247
|
+
var languagesJson = JSON.parse(readFileSync(resolve(__dirname2, "languages.json"), "utf-8"));
|
|
2267
2248
|
var LANGUAGES = languagesJson;
|
|
2268
2249
|
var extensionToLanguage = /* @__PURE__ */ new Map();
|
|
2269
2250
|
for (const lang of LANGUAGES) {
|
|
@@ -2606,7 +2587,7 @@ var SessionManager = class {
|
|
|
2606
2587
|
* Create a new session. Emits session.initialized event.
|
|
2607
2588
|
* Note: maxTokens is no longer stored in the session - it comes from the current model config
|
|
2608
2589
|
*/
|
|
2609
|
-
createSession(projectId, title, providerId, providerModel,
|
|
2590
|
+
createSession(projectId, title, providerId, providerModel, workspace) {
|
|
2610
2591
|
const project = getProject(projectId);
|
|
2611
2592
|
if (!project) {
|
|
2612
2593
|
throw new Error(`Project not found: ${projectId}`);
|
|
@@ -2616,9 +2597,9 @@ var SessionManager = class {
|
|
|
2616
2597
|
const existingSessions = listSessionsByProject(projectId, 1e3, 0);
|
|
2617
2598
|
sessionTitle = `Session ${existingSessions.sessions.length + 1}`;
|
|
2618
2599
|
}
|
|
2619
|
-
const effectiveWorkdir =
|
|
2600
|
+
const effectiveWorkdir = workspace ?? project.workdir;
|
|
2620
2601
|
logger.debug("Creating session", { projectId, workdir: effectiveWorkdir, title: sessionTitle });
|
|
2621
|
-
const dbSession = createSession(projectId, effectiveWorkdir, sessionTitle, providerId, providerModel,
|
|
2602
|
+
const dbSession = createSession(projectId, effectiveWorkdir, sessionTitle, providerId, providerModel, workspace);
|
|
2622
2603
|
const contextWindowId = crypto.randomUUID();
|
|
2623
2604
|
emitSessionInitialized(dbSession.id, projectId, effectiveWorkdir, contextWindowId, sessionTitle);
|
|
2624
2605
|
const session = this.buildSessionFromDb(dbSession);
|
|
@@ -3218,71 +3199,70 @@ var SessionManager = class {
|
|
|
3218
3199
|
// ============================================================================
|
|
3219
3200
|
/**
|
|
3220
3201
|
* Get the LSP manager for a session.
|
|
3221
|
-
* Uses
|
|
3202
|
+
* Uses workspace path when active, otherwise the project workdir.
|
|
3222
3203
|
*/
|
|
3223
3204
|
getLspManager(sessionId) {
|
|
3224
3205
|
const session = this.requireSession(sessionId);
|
|
3225
|
-
const effectiveWorkdir = session.
|
|
3206
|
+
const effectiveWorkdir = session.workspace ?? session.workdir;
|
|
3226
3207
|
return getLspManager(sessionId, effectiveWorkdir);
|
|
3227
3208
|
}
|
|
3228
3209
|
// ============================================================================
|
|
3229
|
-
//
|
|
3210
|
+
// Workspace Lifecycle
|
|
3230
3211
|
// ============================================================================
|
|
3231
3212
|
/**
|
|
3232
|
-
*
|
|
3233
|
-
*
|
|
3234
|
-
*
|
|
3235
|
-
* Restarts LSP to pick up the new workdir.
|
|
3236
|
-
* Injects a system reminder to inform the agent about the worktree.
|
|
3213
|
+
* Switch to a workspace. Target can be "original" (project root) or a workspace name.
|
|
3214
|
+
* If the workspace doesn't exist yet, it's created first.
|
|
3215
|
+
* Emits a single type of event — switching is always "opening" a workspace.
|
|
3237
3216
|
*/
|
|
3238
|
-
async
|
|
3217
|
+
async switchWorkspace(sessionId, target, branch) {
|
|
3239
3218
|
const session = this.requireSession(sessionId);
|
|
3240
3219
|
const project = getProject(session.projectId);
|
|
3241
3220
|
if (!project) throw new Error(`Project not found: ${session.projectId}`);
|
|
3242
|
-
if (
|
|
3243
|
-
|
|
3244
|
-
const
|
|
3245
|
-
if (
|
|
3246
|
-
|
|
3221
|
+
if (target === "original" && !session.workspace) return session;
|
|
3222
|
+
if (target !== "original" && session.workspace?.endsWith(`/${target}`)) return session;
|
|
3223
|
+
const previousPath = session.workspace;
|
|
3224
|
+
if (previousPath) {
|
|
3225
|
+
try {
|
|
3226
|
+
await devServerManager.stop(previousPath);
|
|
3227
|
+
} catch (err) {
|
|
3228
|
+
logger.error("Error stopping dev server for workspace switch", {
|
|
3229
|
+
sessionId,
|
|
3230
|
+
workspace: previousPath,
|
|
3231
|
+
error: err
|
|
3232
|
+
});
|
|
3233
|
+
}
|
|
3247
3234
|
}
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3235
|
+
if (target === "original") {
|
|
3236
|
+
updateSessionWorkdir(sessionId, project.workdir, null);
|
|
3237
|
+
} else {
|
|
3238
|
+
const exists = await workspaceExists(project.name, target);
|
|
3239
|
+
if (!exists) {
|
|
3240
|
+
await ensureWorkspace(project.workdir, target, project.name, branch);
|
|
3241
|
+
}
|
|
3242
|
+
const wsPath = resolve2(getWorkspacesDir(project.name), target);
|
|
3243
|
+
updateSessionWorkdir(sessionId, project.workdir, wsPath);
|
|
3253
3244
|
}
|
|
3254
|
-
const reminderContent = `<system-reminder>
|
|
3255
|
-
This session is now operating in a git worktree at ${result.path}.
|
|
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: name }
|
|
3264
|
-
});
|
|
3265
|
-
const updated = this.requireSession(sessionId);
|
|
3266
|
-
this.emit({ type: "session_updated", session: updated });
|
|
3267
|
-
return updated;
|
|
3268
|
-
}
|
|
3269
|
-
/**
|
|
3270
|
-
* Attach session to an existing worktree by path.
|
|
3271
|
-
* Sets session.worktree to the given path without creating a new worktree.
|
|
3272
|
-
* Restarts LSP to pick up the new workdir.
|
|
3273
|
-
*/
|
|
3274
|
-
async attachSessionWorktree(sessionId, wtPath) {
|
|
3275
|
-
const session = this.requireSession(sessionId);
|
|
3276
|
-
if (session.worktree) throw new Error("Session already has a worktree");
|
|
3277
|
-
updateSessionWorkdir(sessionId, session.workdir, wtPath);
|
|
3278
3245
|
try {
|
|
3279
3246
|
await shutdownLspManager(sessionId);
|
|
3280
3247
|
} catch (err) {
|
|
3281
|
-
logger.error("Error shutting down LSP for
|
|
3248
|
+
logger.error("Error shutting down LSP for workspace switch", { sessionId, error: err });
|
|
3249
|
+
}
|
|
3250
|
+
const effectiveWorkdir = target === "original" ? project.workdir : resolve2(getWorkspacesDir(project.name), target);
|
|
3251
|
+
const actualBranch = await getGitBranch(effectiveWorkdir);
|
|
3252
|
+
let stalenessHint = "";
|
|
3253
|
+
if (target !== "original" && actualBranch) {
|
|
3254
|
+
await runGit(effectiveWorkdir, ["fetch", "origin", "--no-tags", "--quiet"]).catch(() => {
|
|
3255
|
+
});
|
|
3256
|
+
const behind = await getCommitsBehind(effectiveWorkdir, actualBranch);
|
|
3257
|
+
if (behind !== null && behind > 0) {
|
|
3258
|
+
const plural = behind === 1 ? "" : "s";
|
|
3259
|
+
stalenessHint = `
|
|
3260
|
+
(${behind} commit${plural} behind ${actualBranch} on main workspace \u2014 run \`git pull\` to sync)`;
|
|
3261
|
+
}
|
|
3282
3262
|
}
|
|
3283
|
-
const
|
|
3263
|
+
const wsLabel = target === "original" ? "original" : target;
|
|
3284
3264
|
const reminderContent = `<system-reminder>
|
|
3285
|
-
This session is now operating in
|
|
3265
|
+
This session is now operating in workspace "${wsLabel}" on branch "${actualBranch ?? "unknown"}" at ${effectiveWorkdir}.${stalenessHint}
|
|
3286
3266
|
All file and git operations should use this directory.
|
|
3287
3267
|
</system-reminder>`;
|
|
3288
3268
|
this.addMessage(sessionId, {
|
|
@@ -3290,47 +3270,33 @@ All file and git operations should use this directory.
|
|
|
3290
3270
|
content: reminderContent,
|
|
3291
3271
|
isSystemGenerated: true,
|
|
3292
3272
|
messageKind: "auto-prompt",
|
|
3293
|
-
metadata: {
|
|
3273
|
+
metadata: {
|
|
3274
|
+
type: "workspace",
|
|
3275
|
+
name: "Workspace",
|
|
3276
|
+
color: "#22c55e",
|
|
3277
|
+
kind: "definition",
|
|
3278
|
+
workspaceName: wsLabel,
|
|
3279
|
+
...actualBranch ? { branchName: actualBranch } : {}
|
|
3280
|
+
}
|
|
3294
3281
|
});
|
|
3295
3282
|
const updated = this.requireSession(sessionId);
|
|
3296
3283
|
this.emit({ type: "session_updated", session: updated });
|
|
3297
3284
|
return updated;
|
|
3298
3285
|
}
|
|
3299
3286
|
/**
|
|
3300
|
-
*
|
|
3301
|
-
*
|
|
3302
|
-
* Restarts LSP to pick up the original workdir.
|
|
3303
|
-
* Injects a system reminder to inform the agent the worktree is closed.
|
|
3287
|
+
* Delete a workspace by name. If the session is currently in that workspace,
|
|
3288
|
+
* switches to original first. Throws if target is "original".
|
|
3304
3289
|
*/
|
|
3305
|
-
async
|
|
3290
|
+
async deleteWorkspace(sessionId, target) {
|
|
3291
|
+
if (target === "original") throw new Error("Cannot delete the original workspace");
|
|
3306
3292
|
const session = this.requireSession(sessionId);
|
|
3307
|
-
if (!session.worktree) throw new Error("Session does not have a worktree");
|
|
3308
3293
|
const project = getProject(session.projectId);
|
|
3309
3294
|
if (!project) throw new Error(`Project not found: ${session.projectId}`);
|
|
3310
|
-
const
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
await devServerManager.stop(closedPath);
|
|
3314
|
-
} catch (err) {
|
|
3315
|
-
logger.error("Error stopping dev server for worktree close", { sessionId, worktree: closedPath, error: err });
|
|
3295
|
+
const currentWsName = session.workspace?.split("/").pop();
|
|
3296
|
+
if (currentWsName === target) {
|
|
3297
|
+
await this.switchWorkspace(sessionId, "original");
|
|
3316
3298
|
}
|
|
3317
|
-
|
|
3318
|
-
try {
|
|
3319
|
-
await shutdownLspManager(sessionId);
|
|
3320
|
-
} catch (err) {
|
|
3321
|
-
logger.error("Error shutting down LSP for worktree close", { sessionId, error: err });
|
|
3322
|
-
}
|
|
3323
|
-
const reminderContent = `<system-reminder>
|
|
3324
|
-
The worktree at ${closedPath} has been closed.
|
|
3325
|
-
Operating in the original project directory at ${project.workdir}.
|
|
3326
|
-
</system-reminder>`;
|
|
3327
|
-
this.addMessage(sessionId, {
|
|
3328
|
-
role: "user",
|
|
3329
|
-
content: reminderContent,
|
|
3330
|
-
isSystemGenerated: true,
|
|
3331
|
-
messageKind: "auto-prompt",
|
|
3332
|
-
metadata: { type: "worktree", name: "Worktree", color: "#ef4444", kind: "reminder", branchName }
|
|
3333
|
-
});
|
|
3299
|
+
await deleteWorkspace(project.name, target);
|
|
3334
3300
|
const updated = this.requireSession(sessionId);
|
|
3335
3301
|
this.emit({ type: "session_updated", session: updated });
|
|
3336
3302
|
return updated;
|
|
@@ -3436,15 +3402,15 @@ Operating in the original project directory at ${project.workdir}.
|
|
|
3436
3402
|
// src/server/routes/skills.ts
|
|
3437
3403
|
import { Router as Router2 } from "express";
|
|
3438
3404
|
import multer from "multer";
|
|
3439
|
-
import { access as access2, mkdir as
|
|
3405
|
+
import { access as access2, mkdir as mkdir2, realpath, stat } from "fs/promises";
|
|
3440
3406
|
import { constants as constants2 } from "fs";
|
|
3441
3407
|
import { homedir } from "os";
|
|
3442
|
-
import { isAbsolute as isAbsolute2, join as
|
|
3408
|
+
import { isAbsolute as isAbsolute2, join as join4, resolve as resolve3 } from "path";
|
|
3443
3409
|
|
|
3444
3410
|
// src/server/skills/installer.ts
|
|
3445
3411
|
import { randomUUID } from "crypto";
|
|
3446
|
-
import { mkdir
|
|
3447
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
3412
|
+
import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
|
|
3413
|
+
import { dirname as dirname3, isAbsolute, join as join2 } from "path";
|
|
3448
3414
|
import matter from "gray-matter";
|
|
3449
3415
|
var SkillInstallError = class extends Error {
|
|
3450
3416
|
constructor(message, status) {
|
|
@@ -3476,17 +3442,17 @@ async function installSkillPackage(libraryDir, packageName, files) {
|
|
|
3476
3442
|
totalBytes += file.content.byteLength;
|
|
3477
3443
|
}
|
|
3478
3444
|
if (totalBytes > 50 * 1024 * 1024) throw new SkillInstallError("Package exceeds 50 MiB", 413);
|
|
3479
|
-
const destination =
|
|
3445
|
+
const destination = join2(libraryDir, packageName);
|
|
3480
3446
|
if (await pathExists(destination)) throw new SkillInstallError("A package with this name already exists", 409);
|
|
3481
|
-
const staging =
|
|
3447
|
+
const staging = join2(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
|
|
3482
3448
|
try {
|
|
3483
|
-
await
|
|
3449
|
+
await mkdir(staging, { recursive: false });
|
|
3484
3450
|
for (const file of files) {
|
|
3485
|
-
const target =
|
|
3486
|
-
await
|
|
3487
|
-
await
|
|
3451
|
+
const target = join2(staging, file.path);
|
|
3452
|
+
await mkdir(dirname3(target), { recursive: true });
|
|
3453
|
+
await writeFile(target, file.content);
|
|
3488
3454
|
}
|
|
3489
|
-
const parsed = matter(await
|
|
3455
|
+
const parsed = matter(await readFile(join2(staging, "SKILL.md"), "utf-8"));
|
|
3490
3456
|
const name = typeof parsed.data["name"] === "string" ? parsed.data["name"].trim() : "";
|
|
3491
3457
|
const description = typeof parsed.data["description"] === "string" ? parsed.data["description"].trim() : "";
|
|
3492
3458
|
if (!name || !description || !parsed.content.trim()) {
|
|
@@ -3503,7 +3469,7 @@ async function installSkillPackage(libraryDir, packageName, files) {
|
|
|
3503
3469
|
|
|
3504
3470
|
// src/server/routes/crud-helpers.ts
|
|
3505
3471
|
import { Router } from "express";
|
|
3506
|
-
import { join as
|
|
3472
|
+
import { join as join3 } from "path";
|
|
3507
3473
|
function computeOverrideIds(defaults, userItems) {
|
|
3508
3474
|
return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
|
|
3509
3475
|
}
|
|
@@ -3515,7 +3481,7 @@ function validateNameIdPrompt(body) {
|
|
|
3515
3481
|
return null;
|
|
3516
3482
|
}
|
|
3517
3483
|
function getProjectItemPath(projectDir, dirName, id, ext) {
|
|
3518
|
-
return
|
|
3484
|
+
return join3(projectDir, ".openfox", dirName, `${id}${ext}`);
|
|
3519
3485
|
}
|
|
3520
3486
|
async function isProjectItem(projectDir, dirName, id, ext) {
|
|
3521
3487
|
if (!projectDir) return false;
|
|
@@ -3660,7 +3626,7 @@ var upload = multer({
|
|
|
3660
3626
|
});
|
|
3661
3627
|
function expandHome(path) {
|
|
3662
3628
|
if (path === "~") return homedir();
|
|
3663
|
-
return path.startsWith("~/") ?
|
|
3629
|
+
return path.startsWith("~/") ? join4(homedir(), path.slice(2)) : path;
|
|
3664
3630
|
}
|
|
3665
3631
|
function configuredDirectory() {
|
|
3666
3632
|
const raw = getSetting(SKILL_DIRECTORIES_SETTING);
|
|
@@ -3768,7 +3734,7 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
3768
3734
|
try {
|
|
3769
3735
|
const configured = configuredDirectory();
|
|
3770
3736
|
const library = configured ? await resolveLibrary(configured) : defaultLibrary(configDir);
|
|
3771
|
-
await
|
|
3737
|
+
await mkdir2(library.resolvedPath, { recursive: true });
|
|
3772
3738
|
const packageName = String(req.body["packageName"] ?? "");
|
|
3773
3739
|
const paths = JSON.parse(String(req.body["paths"] ?? "[]"));
|
|
3774
3740
|
const files = req.files;
|
|
@@ -3818,19 +3784,19 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
3818
3784
|
}
|
|
3819
3785
|
|
|
3820
3786
|
// src/server/commands/registry.ts
|
|
3821
|
-
import { writeFile as
|
|
3822
|
-
import { join as
|
|
3787
|
+
import { writeFile as writeFile2, mkdir as mkdir3, unlink } from "fs/promises";
|
|
3788
|
+
import { join as join5, dirname as dirname4 } from "path";
|
|
3823
3789
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3824
3790
|
import matter2 from "gray-matter";
|
|
3825
3791
|
var __bundleDir = dirname4(fileURLToPath4(import.meta.url));
|
|
3826
|
-
var DEFAULTS_DIR =
|
|
3827
|
-
var DEFAULTS_DIR_ALT =
|
|
3792
|
+
var DEFAULTS_DIR = join5(__bundleDir, "defaults");
|
|
3793
|
+
var DEFAULTS_DIR_ALT = join5(__bundleDir, "command-defaults");
|
|
3828
3794
|
var COMMAND_EXTENSION = ".command.md";
|
|
3829
3795
|
function getCommandsDir(configDir) {
|
|
3830
|
-
return
|
|
3796
|
+
return join5(configDir, "commands");
|
|
3831
3797
|
}
|
|
3832
3798
|
function getProjectCommandsDir(projectDir) {
|
|
3833
|
-
return
|
|
3799
|
+
return join5(projectDir, ".openfox", "commands");
|
|
3834
3800
|
}
|
|
3835
3801
|
async function loadDefaultCommands() {
|
|
3836
3802
|
let defaults = await loadItemsFromDir(DEFAULTS_DIR, {
|
|
@@ -3887,19 +3853,19 @@ function findCommandById(commandId, commands) {
|
|
|
3887
3853
|
return commands.find((c) => c.metadata.id === commandId);
|
|
3888
3854
|
}
|
|
3889
3855
|
async function commandExists(configDir, commandId, projectDir) {
|
|
3890
|
-
if (await pathExists(
|
|
3891
|
-
if (projectDir && await pathExists(
|
|
3856
|
+
if (await pathExists(join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`))) return true;
|
|
3857
|
+
if (projectDir && await pathExists(join5(getProjectCommandsDir(projectDir), `${commandId}${COMMAND_EXTENSION}`)))
|
|
3892
3858
|
return true;
|
|
3893
3859
|
return false;
|
|
3894
3860
|
}
|
|
3895
3861
|
async function saveCommand(configDir, command) {
|
|
3896
3862
|
const commandsDir = getCommandsDir(configDir);
|
|
3897
3863
|
if (!await pathExists(commandsDir)) {
|
|
3898
|
-
await
|
|
3864
|
+
await mkdir3(commandsDir, { recursive: true });
|
|
3899
3865
|
}
|
|
3900
|
-
const filePath =
|
|
3866
|
+
const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
|
|
3901
3867
|
const content = matter2.stringify(command.prompt, command.metadata);
|
|
3902
|
-
await
|
|
3868
|
+
await writeFile2(filePath, content, "utf-8");
|
|
3903
3869
|
}
|
|
3904
3870
|
async function saveCommandToProject(projectDir, command) {
|
|
3905
3871
|
await saveItemToDir(
|
|
@@ -3917,7 +3883,7 @@ async function deleteCommand(configDir, commandId) {
|
|
|
3917
3883
|
if (isDefault) {
|
|
3918
3884
|
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
3919
3885
|
}
|
|
3920
|
-
const filePath =
|
|
3886
|
+
const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
|
|
3921
3887
|
try {
|
|
3922
3888
|
await unlink(filePath);
|
|
3923
3889
|
return { success: true };
|
|
@@ -4097,26 +4063,26 @@ function createDevServerRoutes() {
|
|
|
4097
4063
|
return router;
|
|
4098
4064
|
}
|
|
4099
4065
|
|
|
4100
|
-
// src/server/routes/
|
|
4066
|
+
// src/server/routes/workspace-config.ts
|
|
4101
4067
|
import { Router as Router5 } from "express";
|
|
4102
|
-
function
|
|
4068
|
+
function createWorkspaceConfigRoutes() {
|
|
4103
4069
|
const router = Router5();
|
|
4104
4070
|
router.get("/config", async (req, res) => {
|
|
4105
4071
|
const workdir = req.query["workdir"];
|
|
4106
4072
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
4107
|
-
const config3 = await
|
|
4073
|
+
const config3 = await loadWorkspaceConfig(workdir);
|
|
4108
4074
|
res.json({ config: config3 });
|
|
4109
4075
|
});
|
|
4110
4076
|
router.post("/config", async (req, res) => {
|
|
4111
4077
|
const workdir = req.query["workdir"];
|
|
4112
4078
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
4113
|
-
const {
|
|
4114
|
-
if (!
|
|
4115
|
-
return res.status(400).json({ error: "
|
|
4079
|
+
const { setup } = req.body;
|
|
4080
|
+
if (!Array.isArray(setup)) {
|
|
4081
|
+
return res.status(400).json({ error: "setup must be an array of strings" });
|
|
4116
4082
|
}
|
|
4117
4083
|
try {
|
|
4118
|
-
const config3 = {
|
|
4119
|
-
await
|
|
4084
|
+
const config3 = { setup };
|
|
4085
|
+
await saveWorkspaceConfig(workdir, config3);
|
|
4120
4086
|
res.json({ config: config3 });
|
|
4121
4087
|
} catch (err) {
|
|
4122
4088
|
res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
|
|
@@ -4169,7 +4135,7 @@ function createTerminalRoutes() {
|
|
|
4169
4135
|
// src/server/routes/directories.ts
|
|
4170
4136
|
import { Router as Router7 } from "express";
|
|
4171
4137
|
import { readdir } from "fs/promises";
|
|
4172
|
-
import { resolve as resolve4, join as
|
|
4138
|
+
import { resolve as resolve4, join as join6, dirname as dirname5, basename as basename2 } from "path";
|
|
4173
4139
|
function createDirectoryRoutes() {
|
|
4174
4140
|
const router = Router7();
|
|
4175
4141
|
const DEFAULT_BASE_PATH = process.cwd();
|
|
@@ -4180,7 +4146,7 @@ function createDirectoryRoutes() {
|
|
|
4180
4146
|
const entries = await readdir(resolvedPath, { withFileTypes: true });
|
|
4181
4147
|
const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
4182
4148
|
name: entry.name,
|
|
4183
|
-
path:
|
|
4149
|
+
path: join6(resolvedPath, entry.name)
|
|
4184
4150
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
4185
4151
|
const parent = dirname5(resolvedPath);
|
|
4186
4152
|
const hasParent = parent !== resolvedPath;
|
|
@@ -4537,8 +4503,8 @@ var ProviderRegistry = class {
|
|
|
4537
4503
|
};
|
|
4538
4504
|
|
|
4539
4505
|
// src/server/providers/plugins/loader.ts
|
|
4540
|
-
import { readdir as readdir2, readFile as
|
|
4541
|
-
import { dirname as dirname6, join as
|
|
4506
|
+
import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
4507
|
+
import { dirname as dirname6, join as join7, resolve as resolve5 } from "path";
|
|
4542
4508
|
import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
|
|
4543
4509
|
async function packageDirectories(root) {
|
|
4544
4510
|
let entries;
|
|
@@ -4549,13 +4515,13 @@ async function packageDirectories(root) {
|
|
|
4549
4515
|
}
|
|
4550
4516
|
const directories = [];
|
|
4551
4517
|
for (const entry of entries) {
|
|
4552
|
-
const entryPath =
|
|
4518
|
+
const entryPath = join7(root, entry.name);
|
|
4553
4519
|
const isDirectory = entry.isDirectory() || entry.isSymbolicLink() && (await stat2(entryPath).catch(() => void 0))?.isDirectory();
|
|
4554
4520
|
if (!isDirectory) continue;
|
|
4555
4521
|
if (entry.name.startsWith("@")) {
|
|
4556
4522
|
const scoped = await readdir2(entryPath, { withFileTypes: true }).catch(() => []);
|
|
4557
4523
|
for (const child of scoped) {
|
|
4558
|
-
const childPath =
|
|
4524
|
+
const childPath = join7(entryPath, child.name);
|
|
4559
4525
|
const childIsDirectory = child.isDirectory() || child.isSymbolicLink() && (await stat2(childPath).catch(() => void 0))?.isDirectory();
|
|
4560
4526
|
if (childIsDirectory) directories.push(childPath);
|
|
4561
4527
|
}
|
|
@@ -4568,8 +4534,8 @@ async function packageDirectories(root) {
|
|
|
4568
4534
|
async function loadProviderPlugins(options) {
|
|
4569
4535
|
const moduleDirectory = dirname6(fileURLToPath5(import.meta.url));
|
|
4570
4536
|
const roots = [
|
|
4571
|
-
|
|
4572
|
-
|
|
4537
|
+
join7(options.configDirectory, "plugins"),
|
|
4538
|
+
join7(options.cwd ?? process.cwd(), "node_modules"),
|
|
4573
4539
|
resolve5(moduleDirectory, "node_modules"),
|
|
4574
4540
|
resolve5(moduleDirectory, "../../../../node_modules")
|
|
4575
4541
|
];
|
|
@@ -4577,10 +4543,10 @@ async function loadProviderPlugins(options) {
|
|
|
4577
4543
|
const diagnostics = [];
|
|
4578
4544
|
for (const root of roots) {
|
|
4579
4545
|
for (const packageDir of await packageDirectories(root)) {
|
|
4580
|
-
const manifestPath =
|
|
4546
|
+
const manifestPath = join7(packageDir, "package.json");
|
|
4581
4547
|
let manifest;
|
|
4582
4548
|
try {
|
|
4583
|
-
manifest = JSON.parse(await
|
|
4549
|
+
manifest = JSON.parse(await readFile2(manifestPath, "utf8"));
|
|
4584
4550
|
} catch {
|
|
4585
4551
|
continue;
|
|
4586
4552
|
}
|
|
@@ -4618,7 +4584,7 @@ async function loadProviderPlugins(options) {
|
|
|
4618
4584
|
}
|
|
4619
4585
|
};
|
|
4620
4586
|
try {
|
|
4621
|
-
const module = await import(pathToFileURL(
|
|
4587
|
+
const module = await import(pathToFileURL(join7(packageDir, plugin)).href);
|
|
4622
4588
|
if (typeof module.register !== "function") throw new Error("Plugin does not export register(registry)");
|
|
4623
4589
|
await module.register(trackingRegistry);
|
|
4624
4590
|
diagnostic.loaded = true;
|
|
@@ -4633,9 +4599,9 @@ async function loadProviderPlugins(options) {
|
|
|
4633
4599
|
// src/server/routes/plugins.ts
|
|
4634
4600
|
import { Router as Router11 } from "express";
|
|
4635
4601
|
import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL2 } from "url";
|
|
4636
|
-
import { dirname as dirname7, resolve as resolve6, join as
|
|
4602
|
+
import { dirname as dirname7, resolve as resolve6, join as join8 } from "path";
|
|
4637
4603
|
import { existsSync } from "fs";
|
|
4638
|
-
import { readFile as
|
|
4604
|
+
import { readFile as readFile3, readdir as readdir3, rm as rm2, rename as rename2 } from "fs/promises";
|
|
4639
4605
|
import { platform } from "os";
|
|
4640
4606
|
import { execFile } from "child_process";
|
|
4641
4607
|
import { promisify } from "util";
|
|
@@ -4665,7 +4631,7 @@ function createPluginRoutes(options) {
|
|
|
4665
4631
|
if (!existsSync(registryPath)) {
|
|
4666
4632
|
registryPath = resolve6(moduleDir, "../../../plugins-registry.json");
|
|
4667
4633
|
}
|
|
4668
|
-
const data = JSON.parse(await
|
|
4634
|
+
const data = JSON.parse(await readFile3(registryPath, "utf8"));
|
|
4669
4635
|
registryCache = { data, ts: now };
|
|
4670
4636
|
res.json({ plugins: data });
|
|
4671
4637
|
} catch (err) {
|
|
@@ -4686,9 +4652,9 @@ function createPluginRoutes(options) {
|
|
|
4686
4652
|
if (!/^[a-zA-Z0-9_-]+$/.test(repoName)) {
|
|
4687
4653
|
return res.status(400).json({ error: "Invalid repository name" });
|
|
4688
4654
|
}
|
|
4689
|
-
const pluginsDir =
|
|
4690
|
-
const targetDir =
|
|
4691
|
-
const tmpDir =
|
|
4655
|
+
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
4656
|
+
const targetDir = join8(pluginsDir, repoName);
|
|
4657
|
+
const tmpDir = join8(pluginsDir, `.${repoName}-tmp-${Date.now()}`);
|
|
4692
4658
|
try {
|
|
4693
4659
|
await execFileP("mkdir", ["-p", pluginsDir], { timeout: 5e3 });
|
|
4694
4660
|
} catch {
|
|
@@ -4719,7 +4685,7 @@ function createPluginRoutes(options) {
|
|
|
4719
4685
|
}
|
|
4720
4686
|
if (!loadError) {
|
|
4721
4687
|
try {
|
|
4722
|
-
const manifest = JSON.parse(await
|
|
4688
|
+
const manifest = JSON.parse(await readFile3(join8(targetDir, "package.json"), "utf8"));
|
|
4723
4689
|
const pluginEntry = manifest.openfox?.plugin;
|
|
4724
4690
|
const apiVersion = manifest.openfox?.apiVersion;
|
|
4725
4691
|
if (!pluginEntry || !manifest.name) {
|
|
@@ -4727,7 +4693,7 @@ function createPluginRoutes(options) {
|
|
|
4727
4693
|
} else if (apiVersion !== 1) {
|
|
4728
4694
|
loadError = `Unsupported plugin API version: ${String(apiVersion)}`;
|
|
4729
4695
|
} else {
|
|
4730
|
-
const mod = await import(pathToFileURL2(
|
|
4696
|
+
const mod = await import(pathToFileURL2(join8(targetDir, pluginEntry)).href);
|
|
4731
4697
|
if (typeof mod.register !== "function") {
|
|
4732
4698
|
loadError = "Plugin does not export register(registry)";
|
|
4733
4699
|
} else {
|
|
@@ -4776,16 +4742,16 @@ function createPluginRoutes(options) {
|
|
|
4776
4742
|
}
|
|
4777
4743
|
});
|
|
4778
4744
|
router.get("/installed", async (_req, res) => {
|
|
4779
|
-
const pluginsDir =
|
|
4745
|
+
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
4780
4746
|
try {
|
|
4781
4747
|
const entries = await readdir3(pluginsDir, { withFileTypes: true });
|
|
4782
4748
|
const installed = [];
|
|
4783
4749
|
for (const entry of entries) {
|
|
4784
4750
|
if (!entry.isDirectory()) continue;
|
|
4785
|
-
const pkgPath =
|
|
4751
|
+
const pkgPath = join8(pluginsDir, entry.name, "package.json");
|
|
4786
4752
|
let version = null;
|
|
4787
4753
|
try {
|
|
4788
|
-
const pkg = JSON.parse(await
|
|
4754
|
+
const pkg = JSON.parse(await readFile3(pkgPath, "utf8"));
|
|
4789
4755
|
version = pkg.version ?? null;
|
|
4790
4756
|
} catch {
|
|
4791
4757
|
}
|
|
@@ -4797,13 +4763,13 @@ function createPluginRoutes(options) {
|
|
|
4797
4763
|
}
|
|
4798
4764
|
});
|
|
4799
4765
|
router.get("/open-folder", async (_req, res) => {
|
|
4800
|
-
const pluginsDir =
|
|
4766
|
+
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
4801
4767
|
await openFolder(pluginsDir, res);
|
|
4802
4768
|
});
|
|
4803
4769
|
router.get("/:name/open-folder", async (req, res) => {
|
|
4804
4770
|
const name = req.params.name;
|
|
4805
4771
|
if (!/^[a-zA-Z0-9_-]+$/.test(name)) return res.status(400).json({ error: "Invalid plugin name" });
|
|
4806
|
-
const targetDir =
|
|
4772
|
+
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
4807
4773
|
await openFolder(targetDir, res);
|
|
4808
4774
|
});
|
|
4809
4775
|
router.delete("/:name", async (req, res) => {
|
|
@@ -4811,7 +4777,7 @@ function createPluginRoutes(options) {
|
|
|
4811
4777
|
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
4812
4778
|
return res.status(400).json({ error: "Invalid plugin name" });
|
|
4813
4779
|
}
|
|
4814
|
-
const targetDir =
|
|
4780
|
+
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
4815
4781
|
try {
|
|
4816
4782
|
await rm2(targetDir, { recursive: true, force: true });
|
|
4817
4783
|
for (let i = pluginDiagnostics.length - 1; i >= 0; i--) {
|
|
@@ -4923,7 +4889,7 @@ async function createServerHandle(config3) {
|
|
|
4923
4889
|
setMcpTools(mcpTools);
|
|
4924
4890
|
logger.info("MCP tools registered", { count: mcpTools.length });
|
|
4925
4891
|
}
|
|
4926
|
-
const { signalMcpReady } = await import("./server-
|
|
4892
|
+
const { signalMcpReady } = await import("./server-G2J4RAXL.js");
|
|
4927
4893
|
signalMcpReady();
|
|
4928
4894
|
});
|
|
4929
4895
|
const app = express();
|
|
@@ -4985,7 +4951,7 @@ async function createServerHandle(config3) {
|
|
|
4985
4951
|
res.json({ tools });
|
|
4986
4952
|
});
|
|
4987
4953
|
app.get("/api/projects", async (_req, res) => {
|
|
4988
|
-
const { listProjects } = await import("./projects-
|
|
4954
|
+
const { listProjects } = await import("./projects-LHRNCUGW.js");
|
|
4989
4955
|
const projects = listProjects();
|
|
4990
4956
|
res.json({ projects });
|
|
4991
4957
|
});
|
|
@@ -4994,7 +4960,7 @@ async function createServerHandle(config3) {
|
|
|
4994
4960
|
if (!name || !workdir) {
|
|
4995
4961
|
return res.status(400).json({ error: "name and workdir are required" });
|
|
4996
4962
|
}
|
|
4997
|
-
const { createDirectoryWithGit } = await import("./project-creator-
|
|
4963
|
+
const { createDirectoryWithGit } = await import("./project-creator-FQRBN3RG.js");
|
|
4998
4964
|
try {
|
|
4999
4965
|
const project = await createDirectoryWithGit(name, workdir);
|
|
5000
4966
|
res.status(201).json({ project });
|
|
@@ -5039,7 +5005,7 @@ async function createServerHandle(config3) {
|
|
|
5039
5005
|
}
|
|
5040
5006
|
});
|
|
5041
5007
|
app.get("/api/projects/:id", async (req, res) => {
|
|
5042
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5008
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5043
5009
|
const project = getProject2(req.params.id);
|
|
5044
5010
|
if (!project) {
|
|
5045
5011
|
return res.status(404).json({ error: "Project not found" });
|
|
@@ -5047,7 +5013,7 @@ async function createServerHandle(config3) {
|
|
|
5047
5013
|
res.json({ project });
|
|
5048
5014
|
});
|
|
5049
5015
|
app.put("/api/projects/:id", async (req, res) => {
|
|
5050
|
-
const { updateProject } = await import("./projects-
|
|
5016
|
+
const { updateProject } = await import("./projects-LHRNCUGW.js");
|
|
5051
5017
|
const { name, customInstructions, dangerLevel } = req.body;
|
|
5052
5018
|
const updates = {};
|
|
5053
5019
|
if (name !== void 0) updates.name = name;
|
|
@@ -5060,7 +5026,7 @@ async function createServerHandle(config3) {
|
|
|
5060
5026
|
res.json({ project: updated });
|
|
5061
5027
|
});
|
|
5062
5028
|
app.delete("/api/projects/:id", async (req, res) => {
|
|
5063
|
-
const { getProject: getProject2, deleteProject } = await import("./projects-
|
|
5029
|
+
const { getProject: getProject2, deleteProject } = await import("./projects-LHRNCUGW.js");
|
|
5064
5030
|
const project = getProject2(req.params.id);
|
|
5065
5031
|
if (!project) {
|
|
5066
5032
|
return res.status(404).json({ error: "Project not found" });
|
|
@@ -5069,7 +5035,7 @@ async function createServerHandle(config3) {
|
|
|
5069
5035
|
res.json({ success: true });
|
|
5070
5036
|
});
|
|
5071
5037
|
app.put("/api/projects/:id/star", async (req, res) => {
|
|
5072
|
-
const { toggleStar } = await import("./projects-
|
|
5038
|
+
const { toggleStar } = await import("./projects-LHRNCUGW.js");
|
|
5073
5039
|
const { isStarred } = req.body;
|
|
5074
5040
|
if (typeof isStarred !== "boolean") {
|
|
5075
5041
|
return res.status(400).json({ error: "isStarred is required and must be a boolean" });
|
|
@@ -5081,20 +5047,20 @@ async function createServerHandle(config3) {
|
|
|
5081
5047
|
res.json({ project });
|
|
5082
5048
|
});
|
|
5083
5049
|
app.get("/api/projects/:id/branches", async (req, res) => {
|
|
5084
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5050
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5085
5051
|
const project = getProject2(req.params.id);
|
|
5086
5052
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5087
|
-
const { listBranches } = await import("./
|
|
5053
|
+
const { listBranches } = await import("./workspace-ET3FHZYN.js");
|
|
5088
5054
|
const branches = await listBranches(project.workdir);
|
|
5089
5055
|
res.json({ branches });
|
|
5090
5056
|
});
|
|
5091
5057
|
app.post("/api/projects/:id/checkout", async (req, res) => {
|
|
5092
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5058
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5093
5059
|
const project = getProject2(req.params.id);
|
|
5094
5060
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5095
5061
|
const { branch } = req.body;
|
|
5096
5062
|
if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
|
|
5097
|
-
const { checkoutBranch } = await import("./
|
|
5063
|
+
const { checkoutBranch } = await import("./workspace-ET3FHZYN.js");
|
|
5098
5064
|
try {
|
|
5099
5065
|
await checkoutBranch(project.workdir, branch);
|
|
5100
5066
|
res.json({ branch });
|
|
@@ -5103,12 +5069,12 @@ async function createServerHandle(config3) {
|
|
|
5103
5069
|
}
|
|
5104
5070
|
});
|
|
5105
5071
|
app.post("/api/projects/:id/checkout-new", async (req, res) => {
|
|
5106
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5072
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5107
5073
|
const project = getProject2(req.params.id);
|
|
5108
5074
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5109
5075
|
const { name } = req.body;
|
|
5110
5076
|
if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
|
|
5111
|
-
const { createBranch } = await import("./
|
|
5077
|
+
const { createBranch } = await import("./workspace-ET3FHZYN.js");
|
|
5112
5078
|
try {
|
|
5113
5079
|
await createBranch(project.workdir, name);
|
|
5114
5080
|
res.json({ branch: name });
|
|
@@ -5116,17 +5082,17 @@ async function createServerHandle(config3) {
|
|
|
5116
5082
|
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create branch" });
|
|
5117
5083
|
}
|
|
5118
5084
|
});
|
|
5119
|
-
app.get("/api/projects/:id/
|
|
5120
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5085
|
+
app.get("/api/projects/:id/workspaces", async (req, res) => {
|
|
5086
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5121
5087
|
const project = getProject2(req.params.id);
|
|
5122
5088
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5123
|
-
const {
|
|
5124
|
-
const all = await
|
|
5125
|
-
const
|
|
5126
|
-
res.json({
|
|
5089
|
+
const { listWorkspaces } = await import("./workspace-ET3FHZYN.js");
|
|
5090
|
+
const all = await listWorkspaces(project.name);
|
|
5091
|
+
const workspacesList = all.filter((ws) => ws.path !== project.workdir);
|
|
5092
|
+
res.json({ workspaces: workspacesList });
|
|
5127
5093
|
});
|
|
5128
5094
|
app.get("/api/sessions", async (req, res) => {
|
|
5129
|
-
const { getRecentUserPromptsForSession } = await import("./events-
|
|
5095
|
+
const { getRecentUserPromptsForSession } = await import("./events-AEQ6GQXI.js");
|
|
5130
5096
|
const projectId = req.query["projectId"];
|
|
5131
5097
|
const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
|
|
5132
5098
|
const offset = parseInt(req.query["offset"]) || 0;
|
|
@@ -5158,44 +5124,34 @@ async function createServerHandle(config3) {
|
|
|
5158
5124
|
const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
|
|
5159
5125
|
res.status(201).json({ session });
|
|
5160
5126
|
});
|
|
5161
|
-
app.post("/api/sessions/:id/
|
|
5127
|
+
app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
|
|
5162
5128
|
const session = sessionManager.getSession(req.params.id);
|
|
5163
5129
|
if (!session) return res.status(404).json({ error: "Session not found" });
|
|
5164
|
-
const {
|
|
5165
|
-
if (!
|
|
5130
|
+
const { target, branch } = req.body;
|
|
5131
|
+
if (!target || typeof target !== "string") return res.status(400).json({ error: "target is required" });
|
|
5166
5132
|
try {
|
|
5167
|
-
const updated = await sessionManager.
|
|
5133
|
+
const updated = await sessionManager.switchWorkspace(req.params.id, target, branch);
|
|
5168
5134
|
res.json({ session: updated });
|
|
5169
5135
|
} catch (err) {
|
|
5170
|
-
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to
|
|
5136
|
+
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to switch workspace" });
|
|
5171
5137
|
}
|
|
5172
5138
|
});
|
|
5173
|
-
app.post("/api/sessions/:id/
|
|
5139
|
+
app.post("/api/sessions/:id/delete-workspace", async (req, res) => {
|
|
5174
5140
|
const session = sessionManager.getSession(req.params.id);
|
|
5175
5141
|
if (!session) return res.status(404).json({ error: "Session not found" });
|
|
5142
|
+
const { target } = req.body;
|
|
5143
|
+
if (!target || typeof target !== "string") return res.status(400).json({ error: "target is required" });
|
|
5176
5144
|
try {
|
|
5177
|
-
const updated = await sessionManager.
|
|
5145
|
+
const updated = await sessionManager.deleteWorkspace(req.params.id, target);
|
|
5178
5146
|
res.json({ session: updated });
|
|
5179
5147
|
} catch (err) {
|
|
5180
|
-
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to
|
|
5181
|
-
}
|
|
5182
|
-
});
|
|
5183
|
-
app.post("/api/sessions/:id/attach-worktree", async (req, res) => {
|
|
5184
|
-
const session = sessionManager.getSession(req.params.id);
|
|
5185
|
-
if (!session) return res.status(404).json({ error: "Session not found" });
|
|
5186
|
-
const { path } = req.body;
|
|
5187
|
-
if (!path || typeof path !== "string") return res.status(400).json({ error: "path is required" });
|
|
5188
|
-
try {
|
|
5189
|
-
const updated = await sessionManager.attachSessionWorktree(req.params.id, path);
|
|
5190
|
-
res.json({ session: updated });
|
|
5191
|
-
} catch (err) {
|
|
5192
|
-
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to attach worktree" });
|
|
5148
|
+
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to delete workspace" });
|
|
5193
5149
|
}
|
|
5194
5150
|
});
|
|
5195
5151
|
app.get("/api/sessions/:id", async (req, res) => {
|
|
5196
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5197
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5198
|
-
const { getPendingQuestionsForSession } = await import("./tools-
|
|
5152
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5153
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5154
|
+
const { getPendingQuestionsForSession } = await import("./tools-X52DFUS6.js");
|
|
5199
5155
|
const session = sessionManager.getSession(req.params.id);
|
|
5200
5156
|
if (!session) {
|
|
5201
5157
|
return res.status(404).json({ error: "Session not found" });
|
|
@@ -5214,8 +5170,8 @@ async function createServerHandle(config3) {
|
|
|
5214
5170
|
if (!session) {
|
|
5215
5171
|
return res.status(404).json({ error: "Session not found" });
|
|
5216
5172
|
}
|
|
5217
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5218
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
5173
|
+
const { stopSessionExecution } = await import("./chat-handler-LK5RUAGO.js");
|
|
5174
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-X52DFUS6.js");
|
|
5219
5175
|
sessionManager.clearMessageQueue(sessionId);
|
|
5220
5176
|
stopSessionExecution(sessionId, sessionManager);
|
|
5221
5177
|
abortSession(sessionId);
|
|
@@ -5234,8 +5190,8 @@ async function createServerHandle(config3) {
|
|
|
5234
5190
|
res.json({ success: true });
|
|
5235
5191
|
});
|
|
5236
5192
|
app.post("/api/sessions/:id/provider", async (req, res) => {
|
|
5237
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5238
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5193
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5194
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5239
5195
|
const sessionId = req.params.id;
|
|
5240
5196
|
const session = sessionManager.getSession(sessionId);
|
|
5241
5197
|
if (!session) {
|
|
@@ -5334,18 +5290,20 @@ async function createServerHandle(config3) {
|
|
|
5334
5290
|
return res.status(400).json({ error: `entries[${i}].status must be a string` });
|
|
5335
5291
|
}
|
|
5336
5292
|
}
|
|
5337
|
-
const mapped = entries.map(
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5293
|
+
const mapped = entries.map(
|
|
5294
|
+
(c, i) => ({
|
|
5295
|
+
...c,
|
|
5296
|
+
id: c.id != null ? String(c.id) : String(i),
|
|
5297
|
+
description: c.description ?? "",
|
|
5298
|
+
status: c.status ?? "open"
|
|
5299
|
+
})
|
|
5300
|
+
);
|
|
5343
5301
|
sessionManager.setMetadataEntries(sessionId, key, mapped);
|
|
5344
5302
|
res.json({ success: true });
|
|
5345
5303
|
});
|
|
5346
5304
|
app.put("/api/sessions/:id/mode", async (req, res) => {
|
|
5347
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5348
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5305
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5306
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5349
5307
|
const sessionId = req.params.id;
|
|
5350
5308
|
const session = sessionManager.getSession(sessionId);
|
|
5351
5309
|
if (!session) {
|
|
@@ -5401,15 +5359,15 @@ async function createServerHandle(config3) {
|
|
|
5401
5359
|
if (!callId || approved === void 0) {
|
|
5402
5360
|
return res.status(400).json({ error: "callId and approved are required" });
|
|
5403
5361
|
}
|
|
5404
|
-
const { providePathConfirmation } = await import("./tools-
|
|
5362
|
+
const { providePathConfirmation } = await import("./tools-X52DFUS6.js");
|
|
5405
5363
|
const result = providePathConfirmation(callId, approved, alwaysAllow);
|
|
5406
5364
|
if (!result.found) {
|
|
5407
5365
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
5408
5366
|
}
|
|
5409
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5410
|
-
const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-
|
|
5411
|
-
const { createSessionStateMessage } = await import("./protocol-
|
|
5412
|
-
const { getPendingQuestionsForSession } = await import("./tools-
|
|
5367
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5368
|
+
const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-ONH3D4OK.js");
|
|
5369
|
+
const { createSessionStateMessage } = await import("./protocol-4QFU7WAI.js");
|
|
5370
|
+
const { getPendingQuestionsForSession } = await import("./tools-X52DFUS6.js");
|
|
5413
5371
|
const eventStore = getEventStore2();
|
|
5414
5372
|
const events = eventStore.getEvents(sessionId);
|
|
5415
5373
|
const messages = buildMessagesFromStoredEvents(events);
|
|
@@ -5430,7 +5388,7 @@ async function createServerHandle(config3) {
|
|
|
5430
5388
|
if (!skip && typeof answer !== "string") {
|
|
5431
5389
|
return res.status(400).json({ error: "answer is required when not skipping" });
|
|
5432
5390
|
}
|
|
5433
|
-
const { provideAnswer } = await import("./tools-
|
|
5391
|
+
const { provideAnswer } = await import("./tools-X52DFUS6.js");
|
|
5434
5392
|
const found = provideAnswer(callId, answer ?? "", skip ?? false);
|
|
5435
5393
|
if (!found) {
|
|
5436
5394
|
return res.status(404).json({ error: "No pending question with that ID" });
|
|
@@ -5458,7 +5416,7 @@ async function createServerHandle(config3) {
|
|
|
5458
5416
|
if (!session) {
|
|
5459
5417
|
return res.status(404).json({ error: "Session not found" });
|
|
5460
5418
|
}
|
|
5461
|
-
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-
|
|
5419
|
+
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-PFXRYXZU.js");
|
|
5462
5420
|
if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
|
|
5463
5421
|
return res.json({ success: false, reason: "disabled" });
|
|
5464
5422
|
}
|
|
@@ -5490,7 +5448,7 @@ async function createServerHandle(config3) {
|
|
|
5490
5448
|
backend: activeProvider?.backend ?? llmClient.getBackend(),
|
|
5491
5449
|
model: llmClient.getModel()
|
|
5492
5450
|
};
|
|
5493
|
-
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-
|
|
5451
|
+
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-RTZVMWQV.js");
|
|
5494
5452
|
runAgentTurn(
|
|
5495
5453
|
{
|
|
5496
5454
|
sessionManager,
|
|
@@ -5528,15 +5486,15 @@ async function createServerHandle(config3) {
|
|
|
5528
5486
|
if (!session) {
|
|
5529
5487
|
return res.status(404).json({ error: "Session not found" });
|
|
5530
5488
|
}
|
|
5531
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5532
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
5489
|
+
const { stopSessionExecution } = await import("./chat-handler-LK5RUAGO.js");
|
|
5490
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-X52DFUS6.js");
|
|
5533
5491
|
const queuedMessages = sessionManager.getQueueState(sessionId);
|
|
5534
5492
|
sessionManager.clearMessageQueue(sessionId);
|
|
5535
5493
|
stopSessionExecution(sessionId, sessionManager);
|
|
5536
5494
|
abortSession(sessionId);
|
|
5537
5495
|
cancelQuestionsForSession(sessionId, "Session stopped by user");
|
|
5538
5496
|
cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
|
|
5539
|
-
const eventStore = (await import("./events-
|
|
5497
|
+
const eventStore = (await import("./events-AEQ6GQXI.js")).getEventStore();
|
|
5540
5498
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
5541
5499
|
res.json({ success: true, queuedMessages });
|
|
5542
5500
|
});
|
|
@@ -5550,7 +5508,7 @@ async function createServerHandle(config3) {
|
|
|
5550
5508
|
if (typeof messageIndex !== "number" || messageIndex < 0) {
|
|
5551
5509
|
return res.status(400).json({ error: "messageIndex must be a non-negative number" });
|
|
5552
5510
|
}
|
|
5553
|
-
const { truncateSessionMessages } = await import("./events-
|
|
5511
|
+
const { truncateSessionMessages } = await import("./events-AEQ6GQXI.js");
|
|
5554
5512
|
truncateSessionMessages(sessionId, messageIndex);
|
|
5555
5513
|
res.json({ success: true });
|
|
5556
5514
|
});
|
|
@@ -5564,8 +5522,8 @@ async function createServerHandle(config3) {
|
|
|
5564
5522
|
if (typeof messageId !== "string" || !messageId) {
|
|
5565
5523
|
return res.status(400).json({ error: "messageId is required" });
|
|
5566
5524
|
}
|
|
5567
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5568
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5525
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5526
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5569
5527
|
const eventStore = getEventStore2();
|
|
5570
5528
|
const events = eventStore.getEvents(sessionId);
|
|
5571
5529
|
const messages = buildMessagesFromStoredEvents(events);
|
|
@@ -5577,7 +5535,7 @@ async function createServerHandle(config3) {
|
|
|
5577
5535
|
if (msg.role !== "user" || msg.isSystemGenerated) {
|
|
5578
5536
|
return res.status(400).json({ error: "Can only replay user messages" });
|
|
5579
5537
|
}
|
|
5580
|
-
const { truncateSessionMessages } = await import("./events-
|
|
5538
|
+
const { truncateSessionMessages } = await import("./events-AEQ6GQXI.js");
|
|
5581
5539
|
truncateSessionMessages(sessionId, msgIndex - 1);
|
|
5582
5540
|
sessionManager.queueMessage(sessionId, "asap", msg.content, msg.attachments, msg.messageKind);
|
|
5583
5541
|
res.json({ success: true });
|
|
@@ -5609,7 +5567,7 @@ async function createServerHandle(config3) {
|
|
|
5609
5567
|
res.json({ accepted: true });
|
|
5610
5568
|
});
|
|
5611
5569
|
app.get("/api/settings", async (req, res) => {
|
|
5612
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5570
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5613
5571
|
const keysParam = req.query["keys"];
|
|
5614
5572
|
if (!keysParam) {
|
|
5615
5573
|
return res.status(400).json({ error: "keys query parameter is required" });
|
|
@@ -5622,19 +5580,19 @@ async function createServerHandle(config3) {
|
|
|
5622
5580
|
res.json(result);
|
|
5623
5581
|
});
|
|
5624
5582
|
app.get("/api/settings/:key", async (req, res) => {
|
|
5625
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5583
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5626
5584
|
const key = req.params.key;
|
|
5627
5585
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
5628
5586
|
res.json({ key, value });
|
|
5629
5587
|
});
|
|
5630
5588
|
app.get("/api/settings/:key", async (req, res) => {
|
|
5631
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5589
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5632
5590
|
const key = req.params.key;
|
|
5633
5591
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
5634
5592
|
res.json({ key, value });
|
|
5635
5593
|
});
|
|
5636
5594
|
app.put("/api/settings/:key", async (req, res) => {
|
|
5637
|
-
const { setSetting: setSetting2 } = await import("./settings-
|
|
5595
|
+
const { setSetting: setSetting2 } = await import("./settings-PFXRYXZU.js");
|
|
5638
5596
|
const key = req.params.key;
|
|
5639
5597
|
const { value } = req.body;
|
|
5640
5598
|
if (value === void 0) {
|
|
@@ -5661,7 +5619,7 @@ async function createServerHandle(config3) {
|
|
|
5661
5619
|
}
|
|
5662
5620
|
});
|
|
5663
5621
|
app.get("/api/tools/shells", async (_req, res) => {
|
|
5664
|
-
const { listAvailableShells } = await import("./platform-
|
|
5622
|
+
const { listAvailableShells } = await import("./platform-XQ7BS3KQ.js");
|
|
5665
5623
|
res.json({ shells: listAvailableShells() });
|
|
5666
5624
|
});
|
|
5667
5625
|
app.get("/api/config", async (_req, res) => {
|
|
@@ -6152,7 +6110,7 @@ async function createServerHandle(config3) {
|
|
|
6152
6110
|
});
|
|
6153
6111
|
async function rebuildMcpTools() {
|
|
6154
6112
|
const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
|
|
6155
|
-
const { setMcpTools: setMcpTools2 } = await import("./tools-
|
|
6113
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-X52DFUS6.js");
|
|
6156
6114
|
const mcpTools = createMcpTools2(mcpManager);
|
|
6157
6115
|
setMcpTools2(mcpTools);
|
|
6158
6116
|
}
|
|
@@ -6370,7 +6328,7 @@ async function createServerHandle(config3) {
|
|
|
6370
6328
|
app.use("/api/agents", createAgentRoutes(configDir, projectDir));
|
|
6371
6329
|
app.use("/api/workflows", createWorkflowRoutes(configDir, config3, projectDir));
|
|
6372
6330
|
app.use("/api/dev-server", createDevServerRoutes());
|
|
6373
|
-
app.use("/api/
|
|
6331
|
+
app.use("/api/workspace", createWorkspaceConfigRoutes());
|
|
6374
6332
|
app.use("/api/terminals", createTerminalRoutes());
|
|
6375
6333
|
app.use(
|
|
6376
6334
|
"/api/auto-update",
|
|
@@ -6387,13 +6345,13 @@ async function createServerHandle(config3) {
|
|
|
6387
6345
|
})
|
|
6388
6346
|
);
|
|
6389
6347
|
app.get("/api/sessions/:id/background-processes", async (req, res) => {
|
|
6390
|
-
const { getSessionProcesses } = await import("./manager-
|
|
6348
|
+
const { getSessionProcesses } = await import("./manager-24C2AXVF.js");
|
|
6391
6349
|
const sessionId = req.params.id;
|
|
6392
6350
|
const processes = getSessionProcesses(sessionId);
|
|
6393
6351
|
res.json({ processes });
|
|
6394
6352
|
});
|
|
6395
6353
|
app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
|
|
6396
|
-
const { stopProcess } = await import("./manager-
|
|
6354
|
+
const { stopProcess } = await import("./manager-24C2AXVF.js");
|
|
6397
6355
|
const sessionId = req.params.id;
|
|
6398
6356
|
const processId = req.params.processId;
|
|
6399
6357
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -6440,7 +6398,7 @@ async function createServerHandle(config3) {
|
|
|
6440
6398
|
}
|
|
6441
6399
|
});
|
|
6442
6400
|
app.get("/fox.svg", (_req, res) => {
|
|
6443
|
-
|
|
6401
|
+
readFile4(join9(webDir, "fox.svg")).then((content) => {
|
|
6444
6402
|
res.set("Content-Type", "image/svg+xml");
|
|
6445
6403
|
res.send(content);
|
|
6446
6404
|
}).catch(() => {
|
|
@@ -6449,7 +6407,7 @@ async function createServerHandle(config3) {
|
|
|
6449
6407
|
});
|
|
6450
6408
|
app.use(
|
|
6451
6409
|
"/sounds",
|
|
6452
|
-
express.static(
|
|
6410
|
+
express.static(join9(webDir, "public", "sounds"), {
|
|
6453
6411
|
setHeaders: (res) => {
|
|
6454
6412
|
res.set("Content-Type", "audio/mpeg");
|
|
6455
6413
|
}
|
|
@@ -6458,13 +6416,13 @@ async function createServerHandle(config3) {
|
|
|
6458
6416
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6459
6417
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6460
6418
|
res.set("Content-Type", "application/javascript");
|
|
6461
|
-
|
|
6419
|
+
readFile4(join9(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6462
6420
|
});
|
|
6463
6421
|
app.get("/*path", (req, res) => {
|
|
6464
6422
|
if (req.path.startsWith("/api/")) {
|
|
6465
6423
|
return;
|
|
6466
6424
|
}
|
|
6467
|
-
|
|
6425
|
+
readFile4(join9(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
|
|
6468
6426
|
logger.error("Error serving index.html", { error: err });
|
|
6469
6427
|
res.status(500).send("Server error");
|
|
6470
6428
|
});
|
|
@@ -6475,7 +6433,7 @@ async function createServerHandle(config3) {
|
|
|
6475
6433
|
const distWebDir = resolve7(__dirname3, "web");
|
|
6476
6434
|
app.use(
|
|
6477
6435
|
"/assets",
|
|
6478
|
-
express.static(
|
|
6436
|
+
express.static(join9(distWebDir, "assets"), {
|
|
6479
6437
|
setHeaders: (res, filepath) => {
|
|
6480
6438
|
if (filepath.endsWith(".css")) {
|
|
6481
6439
|
res.set("Content-Type", "text/css");
|
|
@@ -6483,11 +6441,11 @@ async function createServerHandle(config3) {
|
|
|
6483
6441
|
}
|
|
6484
6442
|
})
|
|
6485
6443
|
);
|
|
6486
|
-
app.use("/manifest.webmanifest", express.static(
|
|
6487
|
-
app.use("/registerSW.js", express.static(
|
|
6488
|
-
app.use("/sw.js", express.static(
|
|
6444
|
+
app.use("/manifest.webmanifest", express.static(join9(distWebDir, "manifest.webmanifest")));
|
|
6445
|
+
app.use("/registerSW.js", express.static(join9(distWebDir, "registerSW.js")));
|
|
6446
|
+
app.use("/sw.js", express.static(join9(distWebDir, "sw.js")));
|
|
6489
6447
|
app.get("/fox.svg", (_req, res) => {
|
|
6490
|
-
|
|
6448
|
+
readFile4(join9(distWebDir, "fox.svg")).then((content) => {
|
|
6491
6449
|
res.set("Content-Type", "image/svg+xml");
|
|
6492
6450
|
res.send(content);
|
|
6493
6451
|
}).catch(() => {
|
|
@@ -6496,7 +6454,7 @@ async function createServerHandle(config3) {
|
|
|
6496
6454
|
});
|
|
6497
6455
|
app.use(
|
|
6498
6456
|
"/sounds",
|
|
6499
|
-
express.static(
|
|
6457
|
+
express.static(join9(distWebDir, "sounds"), {
|
|
6500
6458
|
setHeaders: (res) => {
|
|
6501
6459
|
res.set("Content-Type", "audio/mpeg");
|
|
6502
6460
|
}
|
|
@@ -6505,10 +6463,10 @@ async function createServerHandle(config3) {
|
|
|
6505
6463
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6506
6464
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6507
6465
|
res.set("Content-Type", "application/javascript");
|
|
6508
|
-
|
|
6466
|
+
readFile4(join9(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6509
6467
|
});
|
|
6510
6468
|
app.get("/", (_req, res) => {
|
|
6511
|
-
|
|
6469
|
+
readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6512
6470
|
res.status(404).send("Web UI not built. Run `npm run build:web`");
|
|
6513
6471
|
});
|
|
6514
6472
|
});
|
|
@@ -6516,7 +6474,7 @@ async function createServerHandle(config3) {
|
|
|
6516
6474
|
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") {
|
|
6517
6475
|
return;
|
|
6518
6476
|
}
|
|
6519
|
-
|
|
6477
|
+
readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6520
6478
|
res.status(404).send("Web UI not built");
|
|
6521
6479
|
});
|
|
6522
6480
|
});
|
|
@@ -6536,7 +6494,7 @@ async function createServerHandle(config3) {
|
|
|
6536
6494
|
const state = sessionManager.getContextState(sessionId);
|
|
6537
6495
|
wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
|
|
6538
6496
|
});
|
|
6539
|
-
const { QueueProcessor } = await import("./processor-
|
|
6497
|
+
const { QueueProcessor } = await import("./processor-3O26I7DO.js");
|
|
6540
6498
|
const queueProcessor = new QueueProcessor({
|
|
6541
6499
|
sessionManager,
|
|
6542
6500
|
providerManager,
|
|
@@ -6578,7 +6536,7 @@ async function createServerHandle(config3) {
|
|
|
6578
6536
|
void (async () => {
|
|
6579
6537
|
await devServerManager.stopAll();
|
|
6580
6538
|
await mcpManager.disconnectAll();
|
|
6581
|
-
const { stopAllInspectProxies } = await import("./inspect-proxy-
|
|
6539
|
+
const { stopAllInspectProxies } = await import("./inspect-proxy-PHVZBZUO.js");
|
|
6582
6540
|
stopAllInspectProxies();
|
|
6583
6541
|
const { cleanupAllProcesses } = await import("./store-SARB6V2N.js");
|
|
6584
6542
|
cleanupAllProcesses();
|
|
@@ -6616,4 +6574,4 @@ export {
|
|
|
6616
6574
|
createServerHandle,
|
|
6617
6575
|
createServer
|
|
6618
6576
|
};
|
|
6619
|
-
//# sourceMappingURL=chunk-
|
|
6577
|
+
//# sourceMappingURL=chunk-EYXDM2FY.js.map
|