openfox 2.0.70 → 2.0.72
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/{chat-handler-K3DWIGHG.js → chat-handler-LK5RUAGO.js} +19 -19
- package/dist/{chunk-64GN6OPR.js → chunk-2DCJERYX.js} +8 -8
- package/dist/chunk-2M6JM7OR.js +7 -0
- package/dist/{chunk-XDWV5CYV.js → chunk-4LBSC4R3.js} +15 -20
- package/dist/{chunk-TFDK6VSG.js → chunk-6XKM25OT.js} +13 -13
- package/dist/{chunk-E4POUD2M.js → chunk-6XOA2WPU.js} +2 -2
- package/dist/{chunk-YQ3MEZJL.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-JHGKXQBO.js → chunk-EZK7CGJ7.js} +87 -30
- package/dist/{chunk-ZZ5JPVBT.js → chunk-FILRB5QX.js} +259 -300
- package/dist/{chunk-PVWAE43V.js → chunk-GMF36EZ3.js} +123 -106
- package/dist/{chunk-GMXKJGJ2.js → chunk-I4RWK2L2.js} +8 -4
- package/dist/{chunk-PK2RMVMB.js → chunk-I72ACQ6R.js} +19 -18
- package/dist/{chunk-F4PMNP7S.js → chunk-NOU2QIL5.js} +3 -2
- package/dist/{chunk-UTSSFPYA.js → chunk-O2BE7KVQ.js} +8 -8
- package/dist/{chunk-7OW6X764.js → chunk-OHGQILRF.js} +15 -4
- package/dist/{chunk-TFCHWMOJ.js → chunk-PYB2UEC3.js} +11 -5
- package/dist/{chunk-XUPKS5FL.js → chunk-QNKXZH3Z.js} +2 -2
- package/dist/{chunk-X5DOUA3Z.js → chunk-S7O77CVO.js} +2 -2
- package/dist/{chunk-46OR4W3L.js → chunk-TK4BZIXA.js} +45 -31
- package/dist/{chunk-KXVFHMSM.js → chunk-UV3EMWL4.js} +2 -2
- package/dist/chunk-X2Y3AJPP.js +216 -0
- package/dist/{chunk-QFSDJIUS.js → chunk-XWBNYU2L.js} +3 -3
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{client-63U5CTPE.js → client-SC6X65GY.js} +3 -3
- package/dist/{client-pure-XHH4RRLB.js → client-pure-NMLDKRDN.js} +6 -4
- package/dist/{compactor-IPMMFFHM.js → compactor-4UKYWC5F.js} +9 -9
- 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-JXYRGR6B.js → manager-24C2AXVF.js} +6 -6
- package/dist/{orchestrator-PUV4WG77.js → orchestrator-RTZVMWQV.js} +18 -18
- package/dist/package.json +2 -2
- package/dist/{platform-AB3GIEGO.js → platform-XQ7BS3KQ.js} +4 -4
- package/dist/{processor-O2QW27BD.js → processor-3O26I7DO.js} +19 -19
- 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/{provider-IBIWR4AI.js → provider-OJUCZ5RN.js} +4 -4
- package/dist/{provider-manager-7C3JVOLW.js → provider-manager-MAKXSL6L.js} +4 -4
- package/dist/{pwa-T6JRAYJB.js → pwa-SEWCVKZX.js} +7 -8
- package/dist/{serve-NOHD22CT.js → serve-6PSAQ2YH.js} +26 -24
- package/dist/server/index.d.ts +12 -22
- package/dist/server/index.js +23 -22
- package/dist/server-G2J4RAXL.js +38 -0
- package/dist/{service-6DL3MJZD.js → service-2PW2V25M.js} +6 -1
- package/dist/{settings-6ZPWOBWL.js → settings-PFXRYXZU.js} +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/{store-FXTCHBI4.js → store-SARB6V2N.js} +2 -2
- package/dist/{tools-CALGWIV2.js → tools-X52DFUS6.js} +17 -17
- 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-I2M2RG4Q.js +40 -0
- 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 +2 -2
- package/dist/chunk-VLV3XWZS.js +0 -191
- package/dist/cli/update.sh +0 -16
- package/dist/server-RLNPHLY2.js +0 -38
- package/dist/web/assets/index-CtWMMQ_X.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,22 +66,35 @@ import {
|
|
|
66
66
|
setSkillEnabled,
|
|
67
67
|
skillExists,
|
|
68
68
|
updateOwnedSkill
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-GMF36EZ3.js";
|
|
70
|
+
import {
|
|
71
|
+
deleteWorkspace,
|
|
72
|
+
ensureWorkspace,
|
|
73
|
+
getCommitsBehind,
|
|
74
|
+
getGitBranch,
|
|
75
|
+
getWorkspacesDir,
|
|
76
|
+
loadWorkspaceConfig,
|
|
77
|
+
runGit,
|
|
78
|
+
saveWorkspaceConfig,
|
|
79
|
+
workspaceExists
|
|
80
|
+
} from "./chunk-X2Y3AJPP.js";
|
|
81
|
+
import {
|
|
82
|
+
EventEmitter
|
|
83
|
+
} from "./chunk-EU3WWTFH.js";
|
|
70
84
|
import {
|
|
71
85
|
ALWAYS_ALLOWED,
|
|
72
86
|
ALWAYS_ALLOWED_FOR_SUBAGENTS,
|
|
73
87
|
TOP_LEVEL_ONLY_TOOLS
|
|
74
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-XWBNYU2L.js";
|
|
75
89
|
import {
|
|
76
90
|
getProject
|
|
77
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-UV3EMWL4.js";
|
|
78
92
|
import {
|
|
79
93
|
createMcpTools
|
|
80
94
|
} from "./chunk-NWO6GRYE.js";
|
|
81
95
|
import {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
} from "./chunk-VLV3XWZS.js";
|
|
96
|
+
VERSION
|
|
97
|
+
} from "./chunk-2M6JM7OR.js";
|
|
85
98
|
import {
|
|
86
99
|
createSession,
|
|
87
100
|
deleteSession,
|
|
@@ -109,31 +122,28 @@ import {
|
|
|
109
122
|
updateSessionProvider,
|
|
110
123
|
updateSessionRunning,
|
|
111
124
|
updateSessionWorkdir
|
|
112
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-6XKM25OT.js";
|
|
113
126
|
import {
|
|
114
127
|
createContextStateMessage
|
|
115
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-NOU2QIL5.js";
|
|
116
129
|
import {
|
|
117
130
|
getPathSeparator,
|
|
118
131
|
isAbsolutePath
|
|
119
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-S7O77CVO.js";
|
|
120
133
|
import {
|
|
121
134
|
deleteSetting,
|
|
122
135
|
getSetting,
|
|
123
136
|
setSetting
|
|
124
|
-
} from "./chunk-
|
|
137
|
+
} from "./chunk-QNKXZH3Z.js";
|
|
125
138
|
import {
|
|
126
139
|
initDatabase
|
|
127
|
-
} from "./chunk-
|
|
128
|
-
import {
|
|
129
|
-
EventEmitter
|
|
130
|
-
} from "./chunk-EU3WWTFH.js";
|
|
140
|
+
} from "./chunk-I4RWK2L2.js";
|
|
131
141
|
import {
|
|
132
142
|
createProviderManager,
|
|
133
143
|
detectModel,
|
|
134
144
|
getLlmStatus,
|
|
135
145
|
parseDefaultModelSelection
|
|
136
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-OHGQILRF.js";
|
|
137
147
|
import {
|
|
138
148
|
getModelProfile
|
|
139
149
|
} from "./chunk-V4IE7HJY.js";
|
|
@@ -162,8 +172,8 @@ import express from "express";
|
|
|
162
172
|
import cors from "cors";
|
|
163
173
|
import { createServer as createHttpServer } from "http";
|
|
164
174
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
165
|
-
import { dirname as dirname8, resolve as resolve7, join as
|
|
166
|
-
import { readFile as
|
|
175
|
+
import { dirname as dirname8, resolve as resolve7, join as join9 } from "path";
|
|
176
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
167
177
|
import { createServer as createViteServer } from "vite";
|
|
168
178
|
|
|
169
179
|
// src/server/llm/mock.ts
|
|
@@ -1604,34 +1614,8 @@ var McpManager = class {
|
|
|
1604
1614
|
}
|
|
1605
1615
|
};
|
|
1606
1616
|
|
|
1607
|
-
// src/server/
|
|
1608
|
-
import {
|
|
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
|
-
}
|
|
1617
|
+
// src/server/session/manager.ts
|
|
1618
|
+
import { resolve as resolve2 } from "path";
|
|
1635
1619
|
|
|
1636
1620
|
// src/server/lsp/server.ts
|
|
1637
1621
|
import { spawn } from "child_process";
|
|
@@ -2190,14 +2174,14 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
2190
2174
|
|
|
2191
2175
|
// src/server/utils/which.ts
|
|
2192
2176
|
import { access, constants } from "fs/promises";
|
|
2193
|
-
import { join
|
|
2177
|
+
import { join, dirname } from "path";
|
|
2194
2178
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2195
2179
|
var __dirname = dirname(fileURLToPath2(import.meta.url));
|
|
2196
2180
|
function getBundledBinPaths() {
|
|
2197
2181
|
const paths = [];
|
|
2198
|
-
paths.push(
|
|
2199
|
-
paths.push(
|
|
2200
|
-
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"));
|
|
2201
2185
|
return paths;
|
|
2202
2186
|
}
|
|
2203
2187
|
async function existsExecutable(path) {
|
|
@@ -2216,7 +2200,7 @@ function candidateNames(command) {
|
|
|
2216
2200
|
}
|
|
2217
2201
|
async function findInDir(dir, command) {
|
|
2218
2202
|
for (const name of candidateNames(command)) {
|
|
2219
|
-
const fullPath =
|
|
2203
|
+
const fullPath = join(dir, name);
|
|
2220
2204
|
if (await existsExecutable(fullPath)) {
|
|
2221
2205
|
return fullPath;
|
|
2222
2206
|
}
|
|
@@ -2237,7 +2221,7 @@ async function which(command, workdir) {
|
|
|
2237
2221
|
}
|
|
2238
2222
|
}
|
|
2239
2223
|
if (workdir) {
|
|
2240
|
-
const found = await findInDir(
|
|
2224
|
+
const found = await findInDir(join(workdir, "node_modules", ".bin"), command);
|
|
2241
2225
|
if (found) {
|
|
2242
2226
|
return found;
|
|
2243
2227
|
}
|
|
@@ -2258,9 +2242,9 @@ async function which(command, workdir) {
|
|
|
2258
2242
|
import { extname as extname2, basename } from "path";
|
|
2259
2243
|
import { readFileSync } from "fs";
|
|
2260
2244
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2261
|
-
import { dirname as dirname2, resolve
|
|
2245
|
+
import { dirname as dirname2, resolve } from "path";
|
|
2262
2246
|
var __dirname2 = dirname2(fileURLToPath3(import.meta.url));
|
|
2263
|
-
var languagesJson = JSON.parse(readFileSync(
|
|
2247
|
+
var languagesJson = JSON.parse(readFileSync(resolve(__dirname2, "languages.json"), "utf-8"));
|
|
2264
2248
|
var LANGUAGES = languagesJson;
|
|
2265
2249
|
var extensionToLanguage = /* @__PURE__ */ new Map();
|
|
2266
2250
|
for (const lang of LANGUAGES) {
|
|
@@ -2603,7 +2587,7 @@ var SessionManager = class {
|
|
|
2603
2587
|
* Create a new session. Emits session.initialized event.
|
|
2604
2588
|
* Note: maxTokens is no longer stored in the session - it comes from the current model config
|
|
2605
2589
|
*/
|
|
2606
|
-
createSession(projectId, title, providerId, providerModel,
|
|
2590
|
+
createSession(projectId, title, providerId, providerModel, workspace) {
|
|
2607
2591
|
const project = getProject(projectId);
|
|
2608
2592
|
if (!project) {
|
|
2609
2593
|
throw new Error(`Project not found: ${projectId}`);
|
|
@@ -2613,9 +2597,9 @@ var SessionManager = class {
|
|
|
2613
2597
|
const existingSessions = listSessionsByProject(projectId, 1e3, 0);
|
|
2614
2598
|
sessionTitle = `Session ${existingSessions.sessions.length + 1}`;
|
|
2615
2599
|
}
|
|
2616
|
-
const effectiveWorkdir =
|
|
2600
|
+
const effectiveWorkdir = workspace ?? project.workdir;
|
|
2617
2601
|
logger.debug("Creating session", { projectId, workdir: effectiveWorkdir, title: sessionTitle });
|
|
2618
|
-
const dbSession = createSession(projectId, effectiveWorkdir, sessionTitle, providerId, providerModel,
|
|
2602
|
+
const dbSession = createSession(projectId, effectiveWorkdir, sessionTitle, providerId, providerModel, workspace);
|
|
2619
2603
|
const contextWindowId = crypto.randomUUID();
|
|
2620
2604
|
emitSessionInitialized(dbSession.id, projectId, effectiveWorkdir, contextWindowId, sessionTitle);
|
|
2621
2605
|
const session = this.buildSessionFromDb(dbSession);
|
|
@@ -3215,71 +3199,70 @@ var SessionManager = class {
|
|
|
3215
3199
|
// ============================================================================
|
|
3216
3200
|
/**
|
|
3217
3201
|
* Get the LSP manager for a session.
|
|
3218
|
-
* Uses
|
|
3202
|
+
* Uses workspace path when active, otherwise the project workdir.
|
|
3219
3203
|
*/
|
|
3220
3204
|
getLspManager(sessionId) {
|
|
3221
3205
|
const session = this.requireSession(sessionId);
|
|
3222
|
-
const effectiveWorkdir = session.
|
|
3206
|
+
const effectiveWorkdir = session.workspace ?? session.workdir;
|
|
3223
3207
|
return getLspManager(sessionId, effectiveWorkdir);
|
|
3224
3208
|
}
|
|
3225
3209
|
// ============================================================================
|
|
3226
|
-
//
|
|
3210
|
+
// Workspace Lifecycle
|
|
3227
3211
|
// ============================================================================
|
|
3228
3212
|
/**
|
|
3229
|
-
*
|
|
3230
|
-
*
|
|
3231
|
-
*
|
|
3232
|
-
* Restarts LSP to pick up the new workdir.
|
|
3233
|
-
* 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.
|
|
3234
3216
|
*/
|
|
3235
|
-
async
|
|
3217
|
+
async switchWorkspace(sessionId, target, branch) {
|
|
3236
3218
|
const session = this.requireSession(sessionId);
|
|
3237
3219
|
const project = getProject(session.projectId);
|
|
3238
3220
|
if (!project) throw new Error(`Project not found: ${session.projectId}`);
|
|
3239
|
-
if (
|
|
3240
|
-
|
|
3241
|
-
const
|
|
3242
|
-
if (
|
|
3243
|
-
|
|
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
|
+
}
|
|
3244
3234
|
}
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
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);
|
|
3250
3244
|
}
|
|
3251
|
-
const reminderContent = `<system-reminder>
|
|
3252
|
-
This session is now operating in a git worktree at ${result.path}.
|
|
3253
|
-
All file and git operations should use this directory.
|
|
3254
|
-
</system-reminder>`;
|
|
3255
|
-
this.addMessage(sessionId, {
|
|
3256
|
-
role: "user",
|
|
3257
|
-
content: reminderContent,
|
|
3258
|
-
isSystemGenerated: true,
|
|
3259
|
-
messageKind: "auto-prompt",
|
|
3260
|
-
metadata: { type: "worktree", name: "Worktree", color: "#22c55e", kind: "definition", branchName: name }
|
|
3261
|
-
});
|
|
3262
|
-
const updated = this.requireSession(sessionId);
|
|
3263
|
-
this.emit({ type: "session_updated", session: updated });
|
|
3264
|
-
return updated;
|
|
3265
|
-
}
|
|
3266
|
-
/**
|
|
3267
|
-
* Attach session to an existing worktree by path.
|
|
3268
|
-
* Sets session.worktree to the given path without creating a new worktree.
|
|
3269
|
-
* Restarts LSP to pick up the new workdir.
|
|
3270
|
-
*/
|
|
3271
|
-
async attachSessionWorktree(sessionId, wtPath) {
|
|
3272
|
-
const session = this.requireSession(sessionId);
|
|
3273
|
-
if (session.worktree) throw new Error("Session already has a worktree");
|
|
3274
|
-
updateSessionWorkdir(sessionId, session.workdir, wtPath);
|
|
3275
3245
|
try {
|
|
3276
3246
|
await shutdownLspManager(sessionId);
|
|
3277
3247
|
} catch (err) {
|
|
3278
|
-
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
|
+
}
|
|
3279
3262
|
}
|
|
3280
|
-
const
|
|
3263
|
+
const wsLabel = target === "original" ? "original" : target;
|
|
3281
3264
|
const reminderContent = `<system-reminder>
|
|
3282
|
-
This session is now operating in
|
|
3265
|
+
This session is now operating in workspace "${wsLabel}" on branch "${actualBranch ?? "unknown"}" at ${effectiveWorkdir}.${stalenessHint}
|
|
3283
3266
|
All file and git operations should use this directory.
|
|
3284
3267
|
</system-reminder>`;
|
|
3285
3268
|
this.addMessage(sessionId, {
|
|
@@ -3287,47 +3270,33 @@ All file and git operations should use this directory.
|
|
|
3287
3270
|
content: reminderContent,
|
|
3288
3271
|
isSystemGenerated: true,
|
|
3289
3272
|
messageKind: "auto-prompt",
|
|
3290
|
-
metadata: {
|
|
3273
|
+
metadata: {
|
|
3274
|
+
type: "workspace",
|
|
3275
|
+
name: "Workspace",
|
|
3276
|
+
color: "#22c55e",
|
|
3277
|
+
kind: "definition",
|
|
3278
|
+
workspaceName: wsLabel,
|
|
3279
|
+
...actualBranch ? { branchName: actualBranch } : {}
|
|
3280
|
+
}
|
|
3291
3281
|
});
|
|
3292
3282
|
const updated = this.requireSession(sessionId);
|
|
3293
3283
|
this.emit({ type: "session_updated", session: updated });
|
|
3294
3284
|
return updated;
|
|
3295
3285
|
}
|
|
3296
3286
|
/**
|
|
3297
|
-
*
|
|
3298
|
-
*
|
|
3299
|
-
* Restarts LSP to pick up the original workdir.
|
|
3300
|
-
* 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".
|
|
3301
3289
|
*/
|
|
3302
|
-
async
|
|
3290
|
+
async deleteWorkspace(sessionId, target) {
|
|
3291
|
+
if (target === "original") throw new Error("Cannot delete the original workspace");
|
|
3303
3292
|
const session = this.requireSession(sessionId);
|
|
3304
|
-
if (!session.worktree) throw new Error("Session does not have a worktree");
|
|
3305
3293
|
const project = getProject(session.projectId);
|
|
3306
3294
|
if (!project) throw new Error(`Project not found: ${session.projectId}`);
|
|
3307
|
-
const
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
await devServerManager.stop(closedPath);
|
|
3311
|
-
} catch (err) {
|
|
3312
|
-
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");
|
|
3313
3298
|
}
|
|
3314
|
-
|
|
3315
|
-
try {
|
|
3316
|
-
await shutdownLspManager(sessionId);
|
|
3317
|
-
} catch (err) {
|
|
3318
|
-
logger.error("Error shutting down LSP for worktree close", { sessionId, error: err });
|
|
3319
|
-
}
|
|
3320
|
-
const reminderContent = `<system-reminder>
|
|
3321
|
-
The worktree at ${closedPath} has been closed.
|
|
3322
|
-
Operating in the original project directory at ${project.workdir}.
|
|
3323
|
-
</system-reminder>`;
|
|
3324
|
-
this.addMessage(sessionId, {
|
|
3325
|
-
role: "user",
|
|
3326
|
-
content: reminderContent,
|
|
3327
|
-
isSystemGenerated: true,
|
|
3328
|
-
messageKind: "auto-prompt",
|
|
3329
|
-
metadata: { type: "worktree", name: "Worktree", color: "#ef4444", kind: "reminder", branchName }
|
|
3330
|
-
});
|
|
3299
|
+
await deleteWorkspace(project.name, target);
|
|
3331
3300
|
const updated = this.requireSession(sessionId);
|
|
3332
3301
|
this.emit({ type: "session_updated", session: updated });
|
|
3333
3302
|
return updated;
|
|
@@ -3433,15 +3402,15 @@ Operating in the original project directory at ${project.workdir}.
|
|
|
3433
3402
|
// src/server/routes/skills.ts
|
|
3434
3403
|
import { Router as Router2 } from "express";
|
|
3435
3404
|
import multer from "multer";
|
|
3436
|
-
import { access as access2, mkdir as
|
|
3405
|
+
import { access as access2, mkdir as mkdir2, realpath, stat } from "fs/promises";
|
|
3437
3406
|
import { constants as constants2 } from "fs";
|
|
3438
3407
|
import { homedir } from "os";
|
|
3439
|
-
import { isAbsolute as isAbsolute2, join as
|
|
3408
|
+
import { isAbsolute as isAbsolute2, join as join4, resolve as resolve3 } from "path";
|
|
3440
3409
|
|
|
3441
3410
|
// src/server/skills/installer.ts
|
|
3442
3411
|
import { randomUUID } from "crypto";
|
|
3443
|
-
import { mkdir
|
|
3444
|
-
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";
|
|
3445
3414
|
import matter from "gray-matter";
|
|
3446
3415
|
var SkillInstallError = class extends Error {
|
|
3447
3416
|
constructor(message, status) {
|
|
@@ -3473,17 +3442,17 @@ async function installSkillPackage(libraryDir, packageName, files) {
|
|
|
3473
3442
|
totalBytes += file.content.byteLength;
|
|
3474
3443
|
}
|
|
3475
3444
|
if (totalBytes > 50 * 1024 * 1024) throw new SkillInstallError("Package exceeds 50 MiB", 413);
|
|
3476
|
-
const destination =
|
|
3445
|
+
const destination = join2(libraryDir, packageName);
|
|
3477
3446
|
if (await pathExists(destination)) throw new SkillInstallError("A package with this name already exists", 409);
|
|
3478
|
-
const staging =
|
|
3447
|
+
const staging = join2(libraryDir, `.${packageName}.openfox-upload-${randomUUID()}`);
|
|
3479
3448
|
try {
|
|
3480
|
-
await
|
|
3449
|
+
await mkdir(staging, { recursive: false });
|
|
3481
3450
|
for (const file of files) {
|
|
3482
|
-
const target =
|
|
3483
|
-
await
|
|
3484
|
-
await
|
|
3451
|
+
const target = join2(staging, file.path);
|
|
3452
|
+
await mkdir(dirname3(target), { recursive: true });
|
|
3453
|
+
await writeFile(target, file.content);
|
|
3485
3454
|
}
|
|
3486
|
-
const parsed = matter(await
|
|
3455
|
+
const parsed = matter(await readFile(join2(staging, "SKILL.md"), "utf-8"));
|
|
3487
3456
|
const name = typeof parsed.data["name"] === "string" ? parsed.data["name"].trim() : "";
|
|
3488
3457
|
const description = typeof parsed.data["description"] === "string" ? parsed.data["description"].trim() : "";
|
|
3489
3458
|
if (!name || !description || !parsed.content.trim()) {
|
|
@@ -3500,7 +3469,7 @@ async function installSkillPackage(libraryDir, packageName, files) {
|
|
|
3500
3469
|
|
|
3501
3470
|
// src/server/routes/crud-helpers.ts
|
|
3502
3471
|
import { Router } from "express";
|
|
3503
|
-
import { join as
|
|
3472
|
+
import { join as join3 } from "path";
|
|
3504
3473
|
function computeOverrideIds(defaults, userItems) {
|
|
3505
3474
|
return userItems.filter((u) => defaults.some((d) => d.metadata.id === u.metadata.id)).map((u) => u.metadata.id);
|
|
3506
3475
|
}
|
|
@@ -3512,7 +3481,7 @@ function validateNameIdPrompt(body) {
|
|
|
3512
3481
|
return null;
|
|
3513
3482
|
}
|
|
3514
3483
|
function getProjectItemPath(projectDir, dirName, id, ext) {
|
|
3515
|
-
return
|
|
3484
|
+
return join3(projectDir, ".openfox", dirName, `${id}${ext}`);
|
|
3516
3485
|
}
|
|
3517
3486
|
async function isProjectItem(projectDir, dirName, id, ext) {
|
|
3518
3487
|
if (!projectDir) return false;
|
|
@@ -3657,7 +3626,7 @@ var upload = multer({
|
|
|
3657
3626
|
});
|
|
3658
3627
|
function expandHome(path) {
|
|
3659
3628
|
if (path === "~") return homedir();
|
|
3660
|
-
return path.startsWith("~/") ?
|
|
3629
|
+
return path.startsWith("~/") ? join4(homedir(), path.slice(2)) : path;
|
|
3661
3630
|
}
|
|
3662
3631
|
function configuredDirectory() {
|
|
3663
3632
|
const raw = getSetting(SKILL_DIRECTORIES_SETTING);
|
|
@@ -3765,7 +3734,7 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
3765
3734
|
try {
|
|
3766
3735
|
const configured = configuredDirectory();
|
|
3767
3736
|
const library = configured ? await resolveLibrary(configured) : defaultLibrary(configDir);
|
|
3768
|
-
await
|
|
3737
|
+
await mkdir2(library.resolvedPath, { recursive: true });
|
|
3769
3738
|
const packageName = String(req.body["packageName"] ?? "");
|
|
3770
3739
|
const paths = JSON.parse(String(req.body["paths"] ?? "[]"));
|
|
3771
3740
|
const files = req.files;
|
|
@@ -3815,19 +3784,19 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
3815
3784
|
}
|
|
3816
3785
|
|
|
3817
3786
|
// src/server/commands/registry.ts
|
|
3818
|
-
import { writeFile as
|
|
3819
|
-
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";
|
|
3820
3789
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3821
3790
|
import matter2 from "gray-matter";
|
|
3822
3791
|
var __bundleDir = dirname4(fileURLToPath4(import.meta.url));
|
|
3823
|
-
var DEFAULTS_DIR =
|
|
3824
|
-
var DEFAULTS_DIR_ALT =
|
|
3792
|
+
var DEFAULTS_DIR = join5(__bundleDir, "defaults");
|
|
3793
|
+
var DEFAULTS_DIR_ALT = join5(__bundleDir, "command-defaults");
|
|
3825
3794
|
var COMMAND_EXTENSION = ".command.md";
|
|
3826
3795
|
function getCommandsDir(configDir) {
|
|
3827
|
-
return
|
|
3796
|
+
return join5(configDir, "commands");
|
|
3828
3797
|
}
|
|
3829
3798
|
function getProjectCommandsDir(projectDir) {
|
|
3830
|
-
return
|
|
3799
|
+
return join5(projectDir, ".openfox", "commands");
|
|
3831
3800
|
}
|
|
3832
3801
|
async function loadDefaultCommands() {
|
|
3833
3802
|
let defaults = await loadItemsFromDir(DEFAULTS_DIR, {
|
|
@@ -3884,19 +3853,19 @@ function findCommandById(commandId, commands) {
|
|
|
3884
3853
|
return commands.find((c) => c.metadata.id === commandId);
|
|
3885
3854
|
}
|
|
3886
3855
|
async function commandExists(configDir, commandId, projectDir) {
|
|
3887
|
-
if (await pathExists(
|
|
3888
|
-
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}`)))
|
|
3889
3858
|
return true;
|
|
3890
3859
|
return false;
|
|
3891
3860
|
}
|
|
3892
3861
|
async function saveCommand(configDir, command) {
|
|
3893
3862
|
const commandsDir = getCommandsDir(configDir);
|
|
3894
3863
|
if (!await pathExists(commandsDir)) {
|
|
3895
|
-
await
|
|
3864
|
+
await mkdir3(commandsDir, { recursive: true });
|
|
3896
3865
|
}
|
|
3897
|
-
const filePath =
|
|
3866
|
+
const filePath = join5(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`);
|
|
3898
3867
|
const content = matter2.stringify(command.prompt, command.metadata);
|
|
3899
|
-
await
|
|
3868
|
+
await writeFile2(filePath, content, "utf-8");
|
|
3900
3869
|
}
|
|
3901
3870
|
async function saveCommandToProject(projectDir, command) {
|
|
3902
3871
|
await saveItemToDir(
|
|
@@ -3914,7 +3883,7 @@ async function deleteCommand(configDir, commandId) {
|
|
|
3914
3883
|
if (isDefault) {
|
|
3915
3884
|
return { success: false, reason: "Cannot delete built-in defaults" };
|
|
3916
3885
|
}
|
|
3917
|
-
const filePath =
|
|
3886
|
+
const filePath = join5(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`);
|
|
3918
3887
|
try {
|
|
3919
3888
|
await unlink(filePath);
|
|
3920
3889
|
return { success: true };
|
|
@@ -4094,26 +4063,26 @@ function createDevServerRoutes() {
|
|
|
4094
4063
|
return router;
|
|
4095
4064
|
}
|
|
4096
4065
|
|
|
4097
|
-
// src/server/routes/
|
|
4066
|
+
// src/server/routes/workspace-config.ts
|
|
4098
4067
|
import { Router as Router5 } from "express";
|
|
4099
|
-
function
|
|
4068
|
+
function createWorkspaceConfigRoutes() {
|
|
4100
4069
|
const router = Router5();
|
|
4101
4070
|
router.get("/config", async (req, res) => {
|
|
4102
4071
|
const workdir = req.query["workdir"];
|
|
4103
4072
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
4104
|
-
const config3 = await
|
|
4073
|
+
const config3 = await loadWorkspaceConfig(workdir);
|
|
4105
4074
|
res.json({ config: config3 });
|
|
4106
4075
|
});
|
|
4107
4076
|
router.post("/config", async (req, res) => {
|
|
4108
4077
|
const workdir = req.query["workdir"];
|
|
4109
4078
|
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
4110
|
-
const {
|
|
4111
|
-
if (!
|
|
4112
|
-
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" });
|
|
4113
4082
|
}
|
|
4114
4083
|
try {
|
|
4115
|
-
const config3 = {
|
|
4116
|
-
await
|
|
4084
|
+
const config3 = { setup };
|
|
4085
|
+
await saveWorkspaceConfig(workdir, config3);
|
|
4117
4086
|
res.json({ config: config3 });
|
|
4118
4087
|
} catch (err) {
|
|
4119
4088
|
res.status(500).json({ error: err instanceof Error ? err.message : "Failed to save config" });
|
|
@@ -4166,7 +4135,7 @@ function createTerminalRoutes() {
|
|
|
4166
4135
|
// src/server/routes/directories.ts
|
|
4167
4136
|
import { Router as Router7 } from "express";
|
|
4168
4137
|
import { readdir } from "fs/promises";
|
|
4169
|
-
import { resolve as resolve4, join as
|
|
4138
|
+
import { resolve as resolve4, join as join6, dirname as dirname5, basename as basename2 } from "path";
|
|
4170
4139
|
function createDirectoryRoutes() {
|
|
4171
4140
|
const router = Router7();
|
|
4172
4141
|
const DEFAULT_BASE_PATH = process.cwd();
|
|
@@ -4177,7 +4146,7 @@ function createDirectoryRoutes() {
|
|
|
4177
4146
|
const entries = await readdir(resolvedPath, { withFileTypes: true });
|
|
4178
4147
|
const directories = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
4179
4148
|
name: entry.name,
|
|
4180
|
-
path:
|
|
4149
|
+
path: join6(resolvedPath, entry.name)
|
|
4181
4150
|
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
4182
4151
|
const parent = dirname5(resolvedPath);
|
|
4183
4152
|
const hasParent = parent !== resolvedPath;
|
|
@@ -4282,11 +4251,6 @@ function fuzzyScore(filePath, query) {
|
|
|
4282
4251
|
// src/server/routes/auto-update.ts
|
|
4283
4252
|
import { Router as Router9 } from "express";
|
|
4284
4253
|
import { spawn as spawn2 } from "child_process";
|
|
4285
|
-
|
|
4286
|
-
// src/constants.ts
|
|
4287
|
-
var VERSION = "2.0.70";
|
|
4288
|
-
|
|
4289
|
-
// src/server/routes/auto-update.ts
|
|
4290
4254
|
var updateInProgress = false;
|
|
4291
4255
|
function isRunningAsService() {
|
|
4292
4256
|
return process.env["OPENFOX_SERVICE"] === "true";
|
|
@@ -4308,8 +4272,10 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
4308
4272
|
const current = VERSION;
|
|
4309
4273
|
try {
|
|
4310
4274
|
const latest = await new Promise((resolve8, reject) => {
|
|
4311
|
-
const
|
|
4275
|
+
const win = process.platform === "win32";
|
|
4276
|
+
const child = spawn2(win ? "npm view openfox version" : "npm", win ? [] : ["view", "openfox", "version"], {
|
|
4312
4277
|
stdio: ["ignore", "pipe", "pipe"],
|
|
4278
|
+
shell: win,
|
|
4313
4279
|
windowsHide: true
|
|
4314
4280
|
});
|
|
4315
4281
|
let stdout = "";
|
|
@@ -4347,8 +4313,9 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
4347
4313
|
updateInProgress = true;
|
|
4348
4314
|
try {
|
|
4349
4315
|
const isService = isRunningAsService();
|
|
4350
|
-
const child = spawn2("
|
|
4316
|
+
const child = spawn2("openfox update", {
|
|
4351
4317
|
stdio: ["ignore", "pipe", "pipe"],
|
|
4318
|
+
shell: true,
|
|
4352
4319
|
windowsHide: true
|
|
4353
4320
|
});
|
|
4354
4321
|
let stdout = "";
|
|
@@ -4387,9 +4354,10 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
4387
4354
|
return;
|
|
4388
4355
|
}
|
|
4389
4356
|
try {
|
|
4390
|
-
const child = spawn2("
|
|
4357
|
+
const child = spawn2("openfox service restart", {
|
|
4391
4358
|
detached: true,
|
|
4392
4359
|
stdio: "ignore",
|
|
4360
|
+
shell: true,
|
|
4393
4361
|
windowsHide: true
|
|
4394
4362
|
});
|
|
4395
4363
|
child.unref();
|
|
@@ -4535,8 +4503,8 @@ var ProviderRegistry = class {
|
|
|
4535
4503
|
};
|
|
4536
4504
|
|
|
4537
4505
|
// src/server/providers/plugins/loader.ts
|
|
4538
|
-
import { readdir as readdir2, readFile as
|
|
4539
|
-
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";
|
|
4540
4508
|
import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
|
|
4541
4509
|
async function packageDirectories(root) {
|
|
4542
4510
|
let entries;
|
|
@@ -4547,13 +4515,13 @@ async function packageDirectories(root) {
|
|
|
4547
4515
|
}
|
|
4548
4516
|
const directories = [];
|
|
4549
4517
|
for (const entry of entries) {
|
|
4550
|
-
const entryPath =
|
|
4518
|
+
const entryPath = join7(root, entry.name);
|
|
4551
4519
|
const isDirectory = entry.isDirectory() || entry.isSymbolicLink() && (await stat2(entryPath).catch(() => void 0))?.isDirectory();
|
|
4552
4520
|
if (!isDirectory) continue;
|
|
4553
4521
|
if (entry.name.startsWith("@")) {
|
|
4554
4522
|
const scoped = await readdir2(entryPath, { withFileTypes: true }).catch(() => []);
|
|
4555
4523
|
for (const child of scoped) {
|
|
4556
|
-
const childPath =
|
|
4524
|
+
const childPath = join7(entryPath, child.name);
|
|
4557
4525
|
const childIsDirectory = child.isDirectory() || child.isSymbolicLink() && (await stat2(childPath).catch(() => void 0))?.isDirectory();
|
|
4558
4526
|
if (childIsDirectory) directories.push(childPath);
|
|
4559
4527
|
}
|
|
@@ -4566,8 +4534,8 @@ async function packageDirectories(root) {
|
|
|
4566
4534
|
async function loadProviderPlugins(options) {
|
|
4567
4535
|
const moduleDirectory = dirname6(fileURLToPath5(import.meta.url));
|
|
4568
4536
|
const roots = [
|
|
4569
|
-
|
|
4570
|
-
|
|
4537
|
+
join7(options.configDirectory, "plugins"),
|
|
4538
|
+
join7(options.cwd ?? process.cwd(), "node_modules"),
|
|
4571
4539
|
resolve5(moduleDirectory, "node_modules"),
|
|
4572
4540
|
resolve5(moduleDirectory, "../../../../node_modules")
|
|
4573
4541
|
];
|
|
@@ -4575,10 +4543,10 @@ async function loadProviderPlugins(options) {
|
|
|
4575
4543
|
const diagnostics = [];
|
|
4576
4544
|
for (const root of roots) {
|
|
4577
4545
|
for (const packageDir of await packageDirectories(root)) {
|
|
4578
|
-
const manifestPath =
|
|
4546
|
+
const manifestPath = join7(packageDir, "package.json");
|
|
4579
4547
|
let manifest;
|
|
4580
4548
|
try {
|
|
4581
|
-
manifest = JSON.parse(await
|
|
4549
|
+
manifest = JSON.parse(await readFile2(manifestPath, "utf8"));
|
|
4582
4550
|
} catch {
|
|
4583
4551
|
continue;
|
|
4584
4552
|
}
|
|
@@ -4616,7 +4584,7 @@ async function loadProviderPlugins(options) {
|
|
|
4616
4584
|
}
|
|
4617
4585
|
};
|
|
4618
4586
|
try {
|
|
4619
|
-
const module = await import(pathToFileURL(
|
|
4587
|
+
const module = await import(pathToFileURL(join7(packageDir, plugin)).href);
|
|
4620
4588
|
if (typeof module.register !== "function") throw new Error("Plugin does not export register(registry)");
|
|
4621
4589
|
await module.register(trackingRegistry);
|
|
4622
4590
|
diagnostic.loaded = true;
|
|
@@ -4631,9 +4599,9 @@ async function loadProviderPlugins(options) {
|
|
|
4631
4599
|
// src/server/routes/plugins.ts
|
|
4632
4600
|
import { Router as Router11 } from "express";
|
|
4633
4601
|
import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL2 } from "url";
|
|
4634
|
-
import { dirname as dirname7, resolve as resolve6, join as
|
|
4602
|
+
import { dirname as dirname7, resolve as resolve6, join as join8 } from "path";
|
|
4635
4603
|
import { existsSync } from "fs";
|
|
4636
|
-
import { readFile as
|
|
4604
|
+
import { readFile as readFile3, readdir as readdir3, rm as rm2, rename as rename2 } from "fs/promises";
|
|
4637
4605
|
import { platform } from "os";
|
|
4638
4606
|
import { execFile } from "child_process";
|
|
4639
4607
|
import { promisify } from "util";
|
|
@@ -4663,7 +4631,7 @@ function createPluginRoutes(options) {
|
|
|
4663
4631
|
if (!existsSync(registryPath)) {
|
|
4664
4632
|
registryPath = resolve6(moduleDir, "../../../plugins-registry.json");
|
|
4665
4633
|
}
|
|
4666
|
-
const data = JSON.parse(await
|
|
4634
|
+
const data = JSON.parse(await readFile3(registryPath, "utf8"));
|
|
4667
4635
|
registryCache = { data, ts: now };
|
|
4668
4636
|
res.json({ plugins: data });
|
|
4669
4637
|
} catch (err) {
|
|
@@ -4684,9 +4652,9 @@ function createPluginRoutes(options) {
|
|
|
4684
4652
|
if (!/^[a-zA-Z0-9_-]+$/.test(repoName)) {
|
|
4685
4653
|
return res.status(400).json({ error: "Invalid repository name" });
|
|
4686
4654
|
}
|
|
4687
|
-
const pluginsDir =
|
|
4688
|
-
const targetDir =
|
|
4689
|
-
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()}`);
|
|
4690
4658
|
try {
|
|
4691
4659
|
await execFileP("mkdir", ["-p", pluginsDir], { timeout: 5e3 });
|
|
4692
4660
|
} catch {
|
|
@@ -4717,7 +4685,7 @@ function createPluginRoutes(options) {
|
|
|
4717
4685
|
}
|
|
4718
4686
|
if (!loadError) {
|
|
4719
4687
|
try {
|
|
4720
|
-
const manifest = JSON.parse(await
|
|
4688
|
+
const manifest = JSON.parse(await readFile3(join8(targetDir, "package.json"), "utf8"));
|
|
4721
4689
|
const pluginEntry = manifest.openfox?.plugin;
|
|
4722
4690
|
const apiVersion = manifest.openfox?.apiVersion;
|
|
4723
4691
|
if (!pluginEntry || !manifest.name) {
|
|
@@ -4725,7 +4693,7 @@ function createPluginRoutes(options) {
|
|
|
4725
4693
|
} else if (apiVersion !== 1) {
|
|
4726
4694
|
loadError = `Unsupported plugin API version: ${String(apiVersion)}`;
|
|
4727
4695
|
} else {
|
|
4728
|
-
const mod = await import(pathToFileURL2(
|
|
4696
|
+
const mod = await import(pathToFileURL2(join8(targetDir, pluginEntry)).href);
|
|
4729
4697
|
if (typeof mod.register !== "function") {
|
|
4730
4698
|
loadError = "Plugin does not export register(registry)";
|
|
4731
4699
|
} else {
|
|
@@ -4774,16 +4742,16 @@ function createPluginRoutes(options) {
|
|
|
4774
4742
|
}
|
|
4775
4743
|
});
|
|
4776
4744
|
router.get("/installed", async (_req, res) => {
|
|
4777
|
-
const pluginsDir =
|
|
4745
|
+
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
4778
4746
|
try {
|
|
4779
4747
|
const entries = await readdir3(pluginsDir, { withFileTypes: true });
|
|
4780
4748
|
const installed = [];
|
|
4781
4749
|
for (const entry of entries) {
|
|
4782
4750
|
if (!entry.isDirectory()) continue;
|
|
4783
|
-
const pkgPath =
|
|
4751
|
+
const pkgPath = join8(pluginsDir, entry.name, "package.json");
|
|
4784
4752
|
let version = null;
|
|
4785
4753
|
try {
|
|
4786
|
-
const pkg = JSON.parse(await
|
|
4754
|
+
const pkg = JSON.parse(await readFile3(pkgPath, "utf8"));
|
|
4787
4755
|
version = pkg.version ?? null;
|
|
4788
4756
|
} catch {
|
|
4789
4757
|
}
|
|
@@ -4795,13 +4763,13 @@ function createPluginRoutes(options) {
|
|
|
4795
4763
|
}
|
|
4796
4764
|
});
|
|
4797
4765
|
router.get("/open-folder", async (_req, res) => {
|
|
4798
|
-
const pluginsDir =
|
|
4766
|
+
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
4799
4767
|
await openFolder(pluginsDir, res);
|
|
4800
4768
|
});
|
|
4801
4769
|
router.get("/:name/open-folder", async (req, res) => {
|
|
4802
4770
|
const name = req.params.name;
|
|
4803
4771
|
if (!/^[a-zA-Z0-9_-]+$/.test(name)) return res.status(400).json({ error: "Invalid plugin name" });
|
|
4804
|
-
const targetDir =
|
|
4772
|
+
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
4805
4773
|
await openFolder(targetDir, res);
|
|
4806
4774
|
});
|
|
4807
4775
|
router.delete("/:name", async (req, res) => {
|
|
@@ -4809,7 +4777,7 @@ function createPluginRoutes(options) {
|
|
|
4809
4777
|
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
4810
4778
|
return res.status(400).json({ error: "Invalid plugin name" });
|
|
4811
4779
|
}
|
|
4812
|
-
const targetDir =
|
|
4780
|
+
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
4813
4781
|
try {
|
|
4814
4782
|
await rm2(targetDir, { recursive: true, force: true });
|
|
4815
4783
|
for (let i = pluginDiagnostics.length - 1; i >= 0; i--) {
|
|
@@ -4921,7 +4889,7 @@ async function createServerHandle(config3) {
|
|
|
4921
4889
|
setMcpTools(mcpTools);
|
|
4922
4890
|
logger.info("MCP tools registered", { count: mcpTools.length });
|
|
4923
4891
|
}
|
|
4924
|
-
const { signalMcpReady } = await import("./server-
|
|
4892
|
+
const { signalMcpReady } = await import("./server-G2J4RAXL.js");
|
|
4925
4893
|
signalMcpReady();
|
|
4926
4894
|
});
|
|
4927
4895
|
const app = express();
|
|
@@ -4983,7 +4951,7 @@ async function createServerHandle(config3) {
|
|
|
4983
4951
|
res.json({ tools });
|
|
4984
4952
|
});
|
|
4985
4953
|
app.get("/api/projects", async (_req, res) => {
|
|
4986
|
-
const { listProjects } = await import("./projects-
|
|
4954
|
+
const { listProjects } = await import("./projects-LHRNCUGW.js");
|
|
4987
4955
|
const projects = listProjects();
|
|
4988
4956
|
res.json({ projects });
|
|
4989
4957
|
});
|
|
@@ -4992,7 +4960,7 @@ async function createServerHandle(config3) {
|
|
|
4992
4960
|
if (!name || !workdir) {
|
|
4993
4961
|
return res.status(400).json({ error: "name and workdir are required" });
|
|
4994
4962
|
}
|
|
4995
|
-
const { createDirectoryWithGit } = await import("./project-creator-
|
|
4963
|
+
const { createDirectoryWithGit } = await import("./project-creator-FQRBN3RG.js");
|
|
4996
4964
|
try {
|
|
4997
4965
|
const project = await createDirectoryWithGit(name, workdir);
|
|
4998
4966
|
res.status(201).json({ project });
|
|
@@ -5037,7 +5005,7 @@ async function createServerHandle(config3) {
|
|
|
5037
5005
|
}
|
|
5038
5006
|
});
|
|
5039
5007
|
app.get("/api/projects/:id", async (req, res) => {
|
|
5040
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5008
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5041
5009
|
const project = getProject2(req.params.id);
|
|
5042
5010
|
if (!project) {
|
|
5043
5011
|
return res.status(404).json({ error: "Project not found" });
|
|
@@ -5045,7 +5013,7 @@ async function createServerHandle(config3) {
|
|
|
5045
5013
|
res.json({ project });
|
|
5046
5014
|
});
|
|
5047
5015
|
app.put("/api/projects/:id", async (req, res) => {
|
|
5048
|
-
const { updateProject } = await import("./projects-
|
|
5016
|
+
const { updateProject } = await import("./projects-LHRNCUGW.js");
|
|
5049
5017
|
const { name, customInstructions, dangerLevel } = req.body;
|
|
5050
5018
|
const updates = {};
|
|
5051
5019
|
if (name !== void 0) updates.name = name;
|
|
@@ -5058,7 +5026,7 @@ async function createServerHandle(config3) {
|
|
|
5058
5026
|
res.json({ project: updated });
|
|
5059
5027
|
});
|
|
5060
5028
|
app.delete("/api/projects/:id", async (req, res) => {
|
|
5061
|
-
const { getProject: getProject2, deleteProject } = await import("./projects-
|
|
5029
|
+
const { getProject: getProject2, deleteProject } = await import("./projects-LHRNCUGW.js");
|
|
5062
5030
|
const project = getProject2(req.params.id);
|
|
5063
5031
|
if (!project) {
|
|
5064
5032
|
return res.status(404).json({ error: "Project not found" });
|
|
@@ -5067,7 +5035,7 @@ async function createServerHandle(config3) {
|
|
|
5067
5035
|
res.json({ success: true });
|
|
5068
5036
|
});
|
|
5069
5037
|
app.put("/api/projects/:id/star", async (req, res) => {
|
|
5070
|
-
const { toggleStar } = await import("./projects-
|
|
5038
|
+
const { toggleStar } = await import("./projects-LHRNCUGW.js");
|
|
5071
5039
|
const { isStarred } = req.body;
|
|
5072
5040
|
if (typeof isStarred !== "boolean") {
|
|
5073
5041
|
return res.status(400).json({ error: "isStarred is required and must be a boolean" });
|
|
@@ -5079,20 +5047,20 @@ async function createServerHandle(config3) {
|
|
|
5079
5047
|
res.json({ project });
|
|
5080
5048
|
});
|
|
5081
5049
|
app.get("/api/projects/:id/branches", async (req, res) => {
|
|
5082
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5050
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5083
5051
|
const project = getProject2(req.params.id);
|
|
5084
5052
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5085
|
-
const { listBranches } = await import("./
|
|
5053
|
+
const { listBranches } = await import("./workspace-ET3FHZYN.js");
|
|
5086
5054
|
const branches = await listBranches(project.workdir);
|
|
5087
5055
|
res.json({ branches });
|
|
5088
5056
|
});
|
|
5089
5057
|
app.post("/api/projects/:id/checkout", async (req, res) => {
|
|
5090
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5058
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5091
5059
|
const project = getProject2(req.params.id);
|
|
5092
5060
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5093
5061
|
const { branch } = req.body;
|
|
5094
5062
|
if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
|
|
5095
|
-
const { checkoutBranch } = await import("./
|
|
5063
|
+
const { checkoutBranch } = await import("./workspace-ET3FHZYN.js");
|
|
5096
5064
|
try {
|
|
5097
5065
|
await checkoutBranch(project.workdir, branch);
|
|
5098
5066
|
res.json({ branch });
|
|
@@ -5101,12 +5069,12 @@ async function createServerHandle(config3) {
|
|
|
5101
5069
|
}
|
|
5102
5070
|
});
|
|
5103
5071
|
app.post("/api/projects/:id/checkout-new", async (req, res) => {
|
|
5104
|
-
const { getProject: getProject2 } = await import("./projects-
|
|
5072
|
+
const { getProject: getProject2 } = await import("./projects-LHRNCUGW.js");
|
|
5105
5073
|
const project = getProject2(req.params.id);
|
|
5106
5074
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5107
5075
|
const { name } = req.body;
|
|
5108
5076
|
if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
|
|
5109
|
-
const { createBranch } = await import("./
|
|
5077
|
+
const { createBranch } = await import("./workspace-ET3FHZYN.js");
|
|
5110
5078
|
try {
|
|
5111
5079
|
await createBranch(project.workdir, name);
|
|
5112
5080
|
res.json({ branch: name });
|
|
@@ -5114,17 +5082,17 @@ async function createServerHandle(config3) {
|
|
|
5114
5082
|
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to create branch" });
|
|
5115
5083
|
}
|
|
5116
5084
|
});
|
|
5117
|
-
app.get("/api/projects/:id/
|
|
5118
|
-
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");
|
|
5119
5087
|
const project = getProject2(req.params.id);
|
|
5120
5088
|
if (!project) return res.status(404).json({ error: "Project not found" });
|
|
5121
|
-
const {
|
|
5122
|
-
const all = await
|
|
5123
|
-
const
|
|
5124
|
-
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 });
|
|
5125
5093
|
});
|
|
5126
5094
|
app.get("/api/sessions", async (req, res) => {
|
|
5127
|
-
const { getRecentUserPromptsForSession } = await import("./events-
|
|
5095
|
+
const { getRecentUserPromptsForSession } = await import("./events-AEQ6GQXI.js");
|
|
5128
5096
|
const projectId = req.query["projectId"];
|
|
5129
5097
|
const limit = Math.min(parseInt(req.query["limit"]) || 20, 100);
|
|
5130
5098
|
const offset = parseInt(req.query["offset"]) || 0;
|
|
@@ -5156,44 +5124,34 @@ async function createServerHandle(config3) {
|
|
|
5156
5124
|
const session = sessionManager.createSession(projectId, title, providerId ?? null, model ?? null);
|
|
5157
5125
|
res.status(201).json({ session });
|
|
5158
5126
|
});
|
|
5159
|
-
app.post("/api/sessions/:id/
|
|
5127
|
+
app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
|
|
5160
5128
|
const session = sessionManager.getSession(req.params.id);
|
|
5161
5129
|
if (!session) return res.status(404).json({ error: "Session not found" });
|
|
5162
|
-
const {
|
|
5163
|
-
if (!
|
|
5130
|
+
const { target, branch } = req.body;
|
|
5131
|
+
if (!target || typeof target !== "string") return res.status(400).json({ error: "target is required" });
|
|
5164
5132
|
try {
|
|
5165
|
-
const updated = await sessionManager.
|
|
5133
|
+
const updated = await sessionManager.switchWorkspace(req.params.id, target, branch);
|
|
5166
5134
|
res.json({ session: updated });
|
|
5167
5135
|
} catch (err) {
|
|
5168
|
-
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" });
|
|
5169
5137
|
}
|
|
5170
5138
|
});
|
|
5171
|
-
app.post("/api/sessions/:id/
|
|
5139
|
+
app.post("/api/sessions/:id/delete-workspace", async (req, res) => {
|
|
5172
5140
|
const session = sessionManager.getSession(req.params.id);
|
|
5173
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" });
|
|
5174
5144
|
try {
|
|
5175
|
-
const updated = await sessionManager.
|
|
5145
|
+
const updated = await sessionManager.deleteWorkspace(req.params.id, target);
|
|
5176
5146
|
res.json({ session: updated });
|
|
5177
5147
|
} catch (err) {
|
|
5178
|
-
res.status(400).json({ error: err instanceof Error ? err.message : "Failed to
|
|
5179
|
-
}
|
|
5180
|
-
});
|
|
5181
|
-
app.post("/api/sessions/:id/attach-worktree", async (req, res) => {
|
|
5182
|
-
const session = sessionManager.getSession(req.params.id);
|
|
5183
|
-
if (!session) return res.status(404).json({ error: "Session not found" });
|
|
5184
|
-
const { path } = req.body;
|
|
5185
|
-
if (!path || typeof path !== "string") return res.status(400).json({ error: "path is required" });
|
|
5186
|
-
try {
|
|
5187
|
-
const updated = await sessionManager.attachSessionWorktree(req.params.id, path);
|
|
5188
|
-
res.json({ session: updated });
|
|
5189
|
-
} catch (err) {
|
|
5190
|
-
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" });
|
|
5191
5149
|
}
|
|
5192
5150
|
});
|
|
5193
5151
|
app.get("/api/sessions/:id", async (req, res) => {
|
|
5194
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5195
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5196
|
-
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");
|
|
5197
5155
|
const session = sessionManager.getSession(req.params.id);
|
|
5198
5156
|
if (!session) {
|
|
5199
5157
|
return res.status(404).json({ error: "Session not found" });
|
|
@@ -5212,8 +5170,8 @@ async function createServerHandle(config3) {
|
|
|
5212
5170
|
if (!session) {
|
|
5213
5171
|
return res.status(404).json({ error: "Session not found" });
|
|
5214
5172
|
}
|
|
5215
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5216
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
5173
|
+
const { stopSessionExecution } = await import("./chat-handler-LK5RUAGO.js");
|
|
5174
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-X52DFUS6.js");
|
|
5217
5175
|
sessionManager.clearMessageQueue(sessionId);
|
|
5218
5176
|
stopSessionExecution(sessionId, sessionManager);
|
|
5219
5177
|
abortSession(sessionId);
|
|
@@ -5232,8 +5190,8 @@ async function createServerHandle(config3) {
|
|
|
5232
5190
|
res.json({ success: true });
|
|
5233
5191
|
});
|
|
5234
5192
|
app.post("/api/sessions/:id/provider", async (req, res) => {
|
|
5235
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5236
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5193
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5194
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5237
5195
|
const sessionId = req.params.id;
|
|
5238
5196
|
const session = sessionManager.getSession(sessionId);
|
|
5239
5197
|
if (!session) {
|
|
@@ -5332,18 +5290,20 @@ async function createServerHandle(config3) {
|
|
|
5332
5290
|
return res.status(400).json({ error: `entries[${i}].status must be a string` });
|
|
5333
5291
|
}
|
|
5334
5292
|
}
|
|
5335
|
-
const mapped = entries.map(
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
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
|
+
);
|
|
5341
5301
|
sessionManager.setMetadataEntries(sessionId, key, mapped);
|
|
5342
5302
|
res.json({ success: true });
|
|
5343
5303
|
});
|
|
5344
5304
|
app.put("/api/sessions/:id/mode", async (req, res) => {
|
|
5345
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5346
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5305
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5306
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5347
5307
|
const sessionId = req.params.id;
|
|
5348
5308
|
const session = sessionManager.getSession(sessionId);
|
|
5349
5309
|
if (!session) {
|
|
@@ -5399,15 +5359,15 @@ async function createServerHandle(config3) {
|
|
|
5399
5359
|
if (!callId || approved === void 0) {
|
|
5400
5360
|
return res.status(400).json({ error: "callId and approved are required" });
|
|
5401
5361
|
}
|
|
5402
|
-
const { providePathConfirmation } = await import("./tools-
|
|
5362
|
+
const { providePathConfirmation } = await import("./tools-X52DFUS6.js");
|
|
5403
5363
|
const result = providePathConfirmation(callId, approved, alwaysAllow);
|
|
5404
5364
|
if (!result.found) {
|
|
5405
5365
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
5406
5366
|
}
|
|
5407
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5408
|
-
const { buildMessagesFromStoredEvents, foldPendingConfirmations } = await import("./folding-
|
|
5409
|
-
const { createSessionStateMessage } = await import("./protocol-
|
|
5410
|
-
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");
|
|
5411
5371
|
const eventStore = getEventStore2();
|
|
5412
5372
|
const events = eventStore.getEvents(sessionId);
|
|
5413
5373
|
const messages = buildMessagesFromStoredEvents(events);
|
|
@@ -5428,7 +5388,7 @@ async function createServerHandle(config3) {
|
|
|
5428
5388
|
if (!skip && typeof answer !== "string") {
|
|
5429
5389
|
return res.status(400).json({ error: "answer is required when not skipping" });
|
|
5430
5390
|
}
|
|
5431
|
-
const { provideAnswer } = await import("./tools-
|
|
5391
|
+
const { provideAnswer } = await import("./tools-X52DFUS6.js");
|
|
5432
5392
|
const found = provideAnswer(callId, answer ?? "", skip ?? false);
|
|
5433
5393
|
if (!found) {
|
|
5434
5394
|
return res.status(404).json({ error: "No pending question with that ID" });
|
|
@@ -5456,7 +5416,7 @@ async function createServerHandle(config3) {
|
|
|
5456
5416
|
if (!session) {
|
|
5457
5417
|
return res.status(404).json({ error: "Session not found" });
|
|
5458
5418
|
}
|
|
5459
|
-
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-
|
|
5419
|
+
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-PFXRYXZU.js");
|
|
5460
5420
|
if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
|
|
5461
5421
|
return res.json({ success: false, reason: "disabled" });
|
|
5462
5422
|
}
|
|
@@ -5488,7 +5448,7 @@ async function createServerHandle(config3) {
|
|
|
5488
5448
|
backend: activeProvider?.backend ?? llmClient.getBackend(),
|
|
5489
5449
|
model: llmClient.getModel()
|
|
5490
5450
|
};
|
|
5491
|
-
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-
|
|
5451
|
+
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-RTZVMWQV.js");
|
|
5492
5452
|
runAgentTurn(
|
|
5493
5453
|
{
|
|
5494
5454
|
sessionManager,
|
|
@@ -5526,15 +5486,15 @@ async function createServerHandle(config3) {
|
|
|
5526
5486
|
if (!session) {
|
|
5527
5487
|
return res.status(404).json({ error: "Session not found" });
|
|
5528
5488
|
}
|
|
5529
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
5530
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
5489
|
+
const { stopSessionExecution } = await import("./chat-handler-LK5RUAGO.js");
|
|
5490
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-X52DFUS6.js");
|
|
5531
5491
|
const queuedMessages = sessionManager.getQueueState(sessionId);
|
|
5532
5492
|
sessionManager.clearMessageQueue(sessionId);
|
|
5533
5493
|
stopSessionExecution(sessionId, sessionManager);
|
|
5534
5494
|
abortSession(sessionId);
|
|
5535
5495
|
cancelQuestionsForSession(sessionId, "Session stopped by user");
|
|
5536
5496
|
cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
|
|
5537
|
-
const eventStore = (await import("./events-
|
|
5497
|
+
const eventStore = (await import("./events-AEQ6GQXI.js")).getEventStore();
|
|
5538
5498
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
5539
5499
|
res.json({ success: true, queuedMessages });
|
|
5540
5500
|
});
|
|
@@ -5548,7 +5508,7 @@ async function createServerHandle(config3) {
|
|
|
5548
5508
|
if (typeof messageIndex !== "number" || messageIndex < 0) {
|
|
5549
5509
|
return res.status(400).json({ error: "messageIndex must be a non-negative number" });
|
|
5550
5510
|
}
|
|
5551
|
-
const { truncateSessionMessages } = await import("./events-
|
|
5511
|
+
const { truncateSessionMessages } = await import("./events-AEQ6GQXI.js");
|
|
5552
5512
|
truncateSessionMessages(sessionId, messageIndex);
|
|
5553
5513
|
res.json({ success: true });
|
|
5554
5514
|
});
|
|
@@ -5562,8 +5522,8 @@ async function createServerHandle(config3) {
|
|
|
5562
5522
|
if (typeof messageId !== "string" || !messageId) {
|
|
5563
5523
|
return res.status(400).json({ error: "messageId is required" });
|
|
5564
5524
|
}
|
|
5565
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
5566
|
-
const { buildMessagesFromStoredEvents } = await import("./folding-
|
|
5525
|
+
const { getEventStore: getEventStore2 } = await import("./events-AEQ6GQXI.js");
|
|
5526
|
+
const { buildMessagesFromStoredEvents } = await import("./folding-ONH3D4OK.js");
|
|
5567
5527
|
const eventStore = getEventStore2();
|
|
5568
5528
|
const events = eventStore.getEvents(sessionId);
|
|
5569
5529
|
const messages = buildMessagesFromStoredEvents(events);
|
|
@@ -5575,7 +5535,7 @@ async function createServerHandle(config3) {
|
|
|
5575
5535
|
if (msg.role !== "user" || msg.isSystemGenerated) {
|
|
5576
5536
|
return res.status(400).json({ error: "Can only replay user messages" });
|
|
5577
5537
|
}
|
|
5578
|
-
const { truncateSessionMessages } = await import("./events-
|
|
5538
|
+
const { truncateSessionMessages } = await import("./events-AEQ6GQXI.js");
|
|
5579
5539
|
truncateSessionMessages(sessionId, msgIndex - 1);
|
|
5580
5540
|
sessionManager.queueMessage(sessionId, "asap", msg.content, msg.attachments, msg.messageKind);
|
|
5581
5541
|
res.json({ success: true });
|
|
@@ -5607,7 +5567,7 @@ async function createServerHandle(config3) {
|
|
|
5607
5567
|
res.json({ accepted: true });
|
|
5608
5568
|
});
|
|
5609
5569
|
app.get("/api/settings", async (req, res) => {
|
|
5610
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5570
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5611
5571
|
const keysParam = req.query["keys"];
|
|
5612
5572
|
if (!keysParam) {
|
|
5613
5573
|
return res.status(400).json({ error: "keys query parameter is required" });
|
|
@@ -5620,19 +5580,19 @@ async function createServerHandle(config3) {
|
|
|
5620
5580
|
res.json(result);
|
|
5621
5581
|
});
|
|
5622
5582
|
app.get("/api/settings/:key", async (req, res) => {
|
|
5623
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5583
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5624
5584
|
const key = req.params.key;
|
|
5625
5585
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
5626
5586
|
res.json({ key, value });
|
|
5627
5587
|
});
|
|
5628
5588
|
app.get("/api/settings/:key", async (req, res) => {
|
|
5629
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
5589
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-PFXRYXZU.js");
|
|
5630
5590
|
const key = req.params.key;
|
|
5631
5591
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
5632
5592
|
res.json({ key, value });
|
|
5633
5593
|
});
|
|
5634
5594
|
app.put("/api/settings/:key", async (req, res) => {
|
|
5635
|
-
const { setSetting: setSetting2 } = await import("./settings-
|
|
5595
|
+
const { setSetting: setSetting2 } = await import("./settings-PFXRYXZU.js");
|
|
5636
5596
|
const key = req.params.key;
|
|
5637
5597
|
const { value } = req.body;
|
|
5638
5598
|
if (value === void 0) {
|
|
@@ -5659,7 +5619,7 @@ async function createServerHandle(config3) {
|
|
|
5659
5619
|
}
|
|
5660
5620
|
});
|
|
5661
5621
|
app.get("/api/tools/shells", async (_req, res) => {
|
|
5662
|
-
const { listAvailableShells } = await import("./platform-
|
|
5622
|
+
const { listAvailableShells } = await import("./platform-XQ7BS3KQ.js");
|
|
5663
5623
|
res.json({ shells: listAvailableShells() });
|
|
5664
5624
|
});
|
|
5665
5625
|
app.get("/api/config", async (_req, res) => {
|
|
@@ -5821,7 +5781,7 @@ async function createServerHandle(config3) {
|
|
|
5821
5781
|
const backend = req.query["backend"];
|
|
5822
5782
|
if (!url) return res.status(400).json({ error: "url is required" });
|
|
5823
5783
|
try {
|
|
5824
|
-
const { fetchModelsWithContext } = await import("./provider-manager-
|
|
5784
|
+
const { fetchModelsWithContext } = await import("./provider-manager-MAKXSL6L.js");
|
|
5825
5785
|
const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
|
|
5826
5786
|
const models = await fetchModelsWithContext(
|
|
5827
5787
|
url,
|
|
@@ -5891,7 +5851,7 @@ async function createServerHandle(config3) {
|
|
|
5891
5851
|
}
|
|
5892
5852
|
const { getModelProfile: getModelProfile2 } = await import("./profiles-5J7F4BML.js");
|
|
5893
5853
|
const { getBackendCapabilities } = await import("./backend-P3GHHLHJ.js");
|
|
5894
|
-
const { buildNonStreamingCreateParams } = await import("./client-pure-
|
|
5854
|
+
const { buildNonStreamingCreateParams } = await import("./client-pure-NMLDKRDN.js");
|
|
5895
5855
|
const { OpenAIHttpClient } = await import("./http-client-PIWB7BXK.js");
|
|
5896
5856
|
const { ensureVersionPrefix } = await import("./url-utils-SAJP7AEX.js");
|
|
5897
5857
|
const profile = getModelProfile2(model);
|
|
@@ -6150,7 +6110,7 @@ async function createServerHandle(config3) {
|
|
|
6150
6110
|
});
|
|
6151
6111
|
async function rebuildMcpTools() {
|
|
6152
6112
|
const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-MOGEI6TP.js");
|
|
6153
|
-
const { setMcpTools: setMcpTools2 } = await import("./tools-
|
|
6113
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-X52DFUS6.js");
|
|
6154
6114
|
const mcpTools = createMcpTools2(mcpManager);
|
|
6155
6115
|
setMcpTools2(mcpTools);
|
|
6156
6116
|
}
|
|
@@ -6368,7 +6328,7 @@ async function createServerHandle(config3) {
|
|
|
6368
6328
|
app.use("/api/agents", createAgentRoutes(configDir, projectDir));
|
|
6369
6329
|
app.use("/api/workflows", createWorkflowRoutes(configDir, config3, projectDir));
|
|
6370
6330
|
app.use("/api/dev-server", createDevServerRoutes());
|
|
6371
|
-
app.use("/api/
|
|
6331
|
+
app.use("/api/workspace", createWorkspaceConfigRoutes());
|
|
6372
6332
|
app.use("/api/terminals", createTerminalRoutes());
|
|
6373
6333
|
app.use(
|
|
6374
6334
|
"/api/auto-update",
|
|
@@ -6385,13 +6345,13 @@ async function createServerHandle(config3) {
|
|
|
6385
6345
|
})
|
|
6386
6346
|
);
|
|
6387
6347
|
app.get("/api/sessions/:id/background-processes", async (req, res) => {
|
|
6388
|
-
const { getSessionProcesses } = await import("./manager-
|
|
6348
|
+
const { getSessionProcesses } = await import("./manager-24C2AXVF.js");
|
|
6389
6349
|
const sessionId = req.params.id;
|
|
6390
6350
|
const processes = getSessionProcesses(sessionId);
|
|
6391
6351
|
res.json({ processes });
|
|
6392
6352
|
});
|
|
6393
6353
|
app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
|
|
6394
|
-
const { stopProcess } = await import("./manager-
|
|
6354
|
+
const { stopProcess } = await import("./manager-24C2AXVF.js");
|
|
6395
6355
|
const sessionId = req.params.id;
|
|
6396
6356
|
const processId = req.params.processId;
|
|
6397
6357
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -6438,7 +6398,7 @@ async function createServerHandle(config3) {
|
|
|
6438
6398
|
}
|
|
6439
6399
|
});
|
|
6440
6400
|
app.get("/fox.svg", (_req, res) => {
|
|
6441
|
-
|
|
6401
|
+
readFile4(join9(webDir, "fox.svg")).then((content) => {
|
|
6442
6402
|
res.set("Content-Type", "image/svg+xml");
|
|
6443
6403
|
res.send(content);
|
|
6444
6404
|
}).catch(() => {
|
|
@@ -6447,7 +6407,7 @@ async function createServerHandle(config3) {
|
|
|
6447
6407
|
});
|
|
6448
6408
|
app.use(
|
|
6449
6409
|
"/sounds",
|
|
6450
|
-
express.static(
|
|
6410
|
+
express.static(join9(webDir, "public", "sounds"), {
|
|
6451
6411
|
setHeaders: (res) => {
|
|
6452
6412
|
res.set("Content-Type", "audio/mpeg");
|
|
6453
6413
|
}
|
|
@@ -6456,13 +6416,13 @@ async function createServerHandle(config3) {
|
|
|
6456
6416
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6457
6417
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6458
6418
|
res.set("Content-Type", "application/javascript");
|
|
6459
|
-
|
|
6419
|
+
readFile4(join9(webDir, "public", "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6460
6420
|
});
|
|
6461
6421
|
app.get("/*path", (req, res) => {
|
|
6462
6422
|
if (req.path.startsWith("/api/")) {
|
|
6463
6423
|
return;
|
|
6464
6424
|
}
|
|
6465
|
-
|
|
6425
|
+
readFile4(join9(webDir, "index.html"), "utf-8").then((indexHtml) => viteServer.transformIndexHtml(req.originalUrl, indexHtml)).then((transformed) => res.send(transformed)).catch((err) => {
|
|
6466
6426
|
logger.error("Error serving index.html", { error: err });
|
|
6467
6427
|
res.status(500).send("Server error");
|
|
6468
6428
|
});
|
|
@@ -6473,7 +6433,7 @@ async function createServerHandle(config3) {
|
|
|
6473
6433
|
const distWebDir = resolve7(__dirname3, "web");
|
|
6474
6434
|
app.use(
|
|
6475
6435
|
"/assets",
|
|
6476
|
-
express.static(
|
|
6436
|
+
express.static(join9(distWebDir, "assets"), {
|
|
6477
6437
|
setHeaders: (res, filepath) => {
|
|
6478
6438
|
if (filepath.endsWith(".css")) {
|
|
6479
6439
|
res.set("Content-Type", "text/css");
|
|
@@ -6481,11 +6441,11 @@ async function createServerHandle(config3) {
|
|
|
6481
6441
|
}
|
|
6482
6442
|
})
|
|
6483
6443
|
);
|
|
6484
|
-
app.use("/manifest.webmanifest", express.static(
|
|
6485
|
-
app.use("/registerSW.js", express.static(
|
|
6486
|
-
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")));
|
|
6487
6447
|
app.get("/fox.svg", (_req, res) => {
|
|
6488
|
-
|
|
6448
|
+
readFile4(join9(distWebDir, "fox.svg")).then((content) => {
|
|
6489
6449
|
res.set("Content-Type", "image/svg+xml");
|
|
6490
6450
|
res.send(content);
|
|
6491
6451
|
}).catch(() => {
|
|
@@ -6494,7 +6454,7 @@ async function createServerHandle(config3) {
|
|
|
6494
6454
|
});
|
|
6495
6455
|
app.use(
|
|
6496
6456
|
"/sounds",
|
|
6497
|
-
express.static(
|
|
6457
|
+
express.static(join9(distWebDir, "sounds"), {
|
|
6498
6458
|
setHeaders: (res) => {
|
|
6499
6459
|
res.set("Content-Type", "audio/mpeg");
|
|
6500
6460
|
}
|
|
@@ -6503,10 +6463,10 @@ async function createServerHandle(config3) {
|
|
|
6503
6463
|
app.use("/__inspect__.js", (_req, res) => {
|
|
6504
6464
|
res.set("Access-Control-Allow-Origin", "*");
|
|
6505
6465
|
res.set("Content-Type", "application/javascript");
|
|
6506
|
-
|
|
6466
|
+
readFile4(join9(distWebDir, "__inspect__.js")).then((content) => res.send(content)).catch(() => res.status(404).send("Not found"));
|
|
6507
6467
|
});
|
|
6508
6468
|
app.get("/", (_req, res) => {
|
|
6509
|
-
|
|
6469
|
+
readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6510
6470
|
res.status(404).send("Web UI not built. Run `npm run build:web`");
|
|
6511
6471
|
});
|
|
6512
6472
|
});
|
|
@@ -6514,7 +6474,7 @@ async function createServerHandle(config3) {
|
|
|
6514
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") {
|
|
6515
6475
|
return;
|
|
6516
6476
|
}
|
|
6517
|
-
|
|
6477
|
+
readFile4(join9(distWebDir, "index.html"), "utf-8").then((content) => res.send(content)).catch(() => {
|
|
6518
6478
|
res.status(404).send("Web UI not built");
|
|
6519
6479
|
});
|
|
6520
6480
|
});
|
|
@@ -6534,7 +6494,7 @@ async function createServerHandle(config3) {
|
|
|
6534
6494
|
const state = sessionManager.getContextState(sessionId);
|
|
6535
6495
|
wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
|
|
6536
6496
|
});
|
|
6537
|
-
const { QueueProcessor } = await import("./processor-
|
|
6497
|
+
const { QueueProcessor } = await import("./processor-3O26I7DO.js");
|
|
6538
6498
|
const queueProcessor = new QueueProcessor({
|
|
6539
6499
|
sessionManager,
|
|
6540
6500
|
providerManager,
|
|
@@ -6576,9 +6536,9 @@ async function createServerHandle(config3) {
|
|
|
6576
6536
|
void (async () => {
|
|
6577
6537
|
await devServerManager.stopAll();
|
|
6578
6538
|
await mcpManager.disconnectAll();
|
|
6579
|
-
const { stopAllInspectProxies } = await import("./inspect-proxy-
|
|
6539
|
+
const { stopAllInspectProxies } = await import("./inspect-proxy-PHVZBZUO.js");
|
|
6580
6540
|
stopAllInspectProxies();
|
|
6581
|
-
const { cleanupAllProcesses } = await import("./store-
|
|
6541
|
+
const { cleanupAllProcesses } = await import("./store-SARB6V2N.js");
|
|
6582
6542
|
cleanupAllProcesses();
|
|
6583
6543
|
viteServer?.close();
|
|
6584
6544
|
if (config3.globalConfigPath) {
|
|
@@ -6611,8 +6571,7 @@ async function createServer(config3) {
|
|
|
6611
6571
|
}
|
|
6612
6572
|
|
|
6613
6573
|
export {
|
|
6614
|
-
VERSION,
|
|
6615
6574
|
createServerHandle,
|
|
6616
6575
|
createServer
|
|
6617
6576
|
};
|
|
6618
|
-
//# sourceMappingURL=chunk-
|
|
6577
|
+
//# sourceMappingURL=chunk-FILRB5QX.js.map
|