openfox 2.0.133 → 2.0.135
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/CHANGELOG.md +30 -0
- package/dist/CHANGELOG.md +30 -0
- package/dist/{chat-handler-T47GATL5.js → chat-handler-WGDFMOOD.js} +23 -22
- package/dist/chunk-24YKXKCG.js +35 -0
- package/dist/chunk-2OMGR7LN.js +45 -0
- package/dist/{chunk-GFW2HWJ6.js → chunk-4R5GV7RW.js} +37 -16
- package/dist/{chunk-P5MSY7ZI.js → chunk-5H5NRWHA.js} +22 -17
- package/dist/{chunk-MQMPIXON.js → chunk-5UMXFLET.js} +3 -3
- package/dist/{chunk-5JWJEZJ3.js → chunk-5UQ4CKOA.js} +2 -2
- package/dist/{chunk-7JVBDBXE.js → chunk-7QMWYNVF.js} +2 -2
- package/dist/{chunk-P57IBMK4.js → chunk-AATMPL7S.js} +4 -4
- package/dist/{chunk-OUQZZEIQ.js → chunk-BIZFY3QP.js} +487 -210
- package/dist/{chunk-LQKXJPKP.js → chunk-CTWZPN7G.js} +5 -1
- package/dist/{chunk-BKMWZTNO.js → chunk-DWA4IE65.js} +14 -2
- package/dist/{chunk-HXHPKGJE.js → chunk-ESZQTFQP.js} +614 -157
- package/dist/{chunk-KWAHD2JA.js → chunk-F2MOHHXB.js} +15 -2
- package/dist/{chunk-A7CB4USC.js → chunk-GP3CLMPQ.js} +132 -45
- package/dist/{chunk-HCYSGLY2.js → chunk-HF3NDXB4.js} +1 -1
- package/dist/{chunk-Y6ZGHOKM.js → chunk-I5ODJKYM.js} +4 -4
- package/dist/{chunk-OMMPTN6X.js → chunk-IAT2LBIX.js} +69 -27
- package/dist/{chunk-6EZDW4JS.js → chunk-J3NMNYGM.js} +2 -2
- package/dist/{chunk-M5T4RDPJ.js → chunk-MEEUXRFL.js} +2 -2
- package/dist/{chunk-RRUSYVQD.js → chunk-NFEZATSN.js} +8 -8
- package/dist/{chunk-MGEYAYGU.js → chunk-O3RCSKUH.js} +2 -2
- package/dist/{chunk-ELYHHEYL.js → chunk-ORCQ3EXQ.js} +2 -2
- package/dist/{chunk-FEIRWXLX.js → chunk-OZWHRBDY.js} +64 -17
- package/dist/{chunk-FGNJMKDV.js → chunk-QZOV4OVN.js} +29 -5
- package/dist/{chunk-TACWRDDC.js → chunk-S67WIWUG.js} +2 -2
- package/dist/{chunk-ZL4IAFF3.js → chunk-UKIUQAQZ.js} +3 -3
- package/dist/{chunk-VXG3AFFY.js → chunk-VHLD6PCZ.js} +8 -8
- package/dist/chunk-WY3PWHWY.js +7 -0
- package/dist/{chunk-CLDCHOEA.js → chunk-ZMK4VX7V.js} +2 -2
- package/dist/cli/dev.js +4 -1
- package/dist/cli/index.js +4 -1
- package/dist/{client-2K6PPPJJ.js → client-VVYOWXRR.js} +4 -4
- package/dist/{compactor-OEJAA2YP.js → compactor-454UEIEX.js} +9 -9
- package/dist/{dynamic-context-NJZKAZE3.js → dynamic-context-LKC6JYLQ.js} +10 -10
- package/dist/{events-ZJPRGVL2.js → events-335XAKFK.js} +6 -6
- package/dist/export-import-3WMRLO4A.js +137 -0
- package/dist/{folding-QRZOHY2I.js → folding-H7JTX6KI.js} +4 -4
- package/dist/{http-client-P4XTKAZA.js → http-client-A445WYZU.js} +3 -3
- package/dist/{install-VA2F6X6Z.js → install-AVTFA344.js} +64 -15
- package/dist/{launch-UKXVO37B.js → launch-GJ7EHQRI.js} +23 -22
- package/dist/{manager-TMBFBCQL.js → manager-ZACEUL5P.js} +4 -4
- package/dist/{mcp-YU7AM3UV.js → mcp-SQ4DOGPT.js} +22 -9
- package/dist/{orchestrator-GX22Y5EM.js → orchestrator-JGJWTRO5.js} +22 -21
- package/dist/package.json +3 -1
- package/dist/{path-security-CBACXAMS.js → path-security-4LROI7F4.js} +10 -10
- package/dist/{platform-5LQXOZO3.js → platform-XPMZKAUB.js} +3 -3
- package/dist/{processor-V35OLKRV.js → processor-MSQP63ML.js} +22 -21
- package/dist/{project-creator-6AGQTNXB.js → project-creator-T3A4H3YV.js} +42 -29
- package/dist/{protocol-BMUoqwYH.d.ts → protocol-Nr_H1_oC.d.ts} +3 -1
- package/dist/{protocol-Y7MRKRUO.js → protocol-XO4ZROAU.js} +3 -3
- package/dist/provider/index.d.ts +4 -4
- package/dist/provider-JWUNG2TD.js +507 -0
- package/dist/{provider-manager-BO5ZBG3T.js → provider-manager-2KKZ37XJ.js} +5 -5
- package/dist/pwa-V5PFB4OQ.js +502 -0
- package/dist/{registry-CMSSZHDC.js → registry-BEIR7Y5G.js} +3 -3
- package/dist/{serve-XRVT3D7Z.js → serve-CW5C3CBZ.js} +47 -36
- package/dist/server/index.d.ts +18 -3
- package/dist/server/index.js +27 -26
- package/dist/{server-GXMZMPXI.js → server-ZHEB7XS2.js} +26 -25
- package/dist/{service-WKABQHKL.js → service-M77VWL2M.js} +97 -32
- package/dist/{service-O3LCO3TQ.js → service-XIUNS5XV.js} +7 -6
- package/dist/{session-overrides-OECQYRDK.js → session-overrides-LYW5PJ3R.js} +5 -5
- package/dist/{sessions-NMPX5ICI.js → sessions-AOK3AGHY.js} +6 -4
- package/dist/{settings-MDCRNQBY.js → settings-ZJPM6PQV.js} +2 -2
- package/dist/shared/index.d.ts +31 -4
- package/dist/shared/index.js +16 -2
- package/dist/{tasks-WOC3QUFA.js → tasks-3JJWJJ3X.js} +34 -18
- package/dist/{tools-CW6POKUL.js → tools-E63MOJBO.js} +20 -19
- package/dist/{types-CoY8Ka1C.d.ts → types-BlQjLBui.d.ts} +1 -1
- package/dist/{types-BIkpxjaj.d.ts → types-G10ho8PT.d.ts} +1 -1
- package/dist/update-XVXNSSDK.js +76 -0
- package/dist/web/assets/{index-Y300llHY.css → index-Bg_Z8i3F.css} +1 -1
- package/dist/web/assets/index-wTFCxQAw.js +313 -0
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +3 -1
- package/dist/chunk-JKGHTBEV.js +0 -7
- package/dist/provider-NWRGNGS3.js +0 -403
- package/dist/pwa-2GRFSXD7.js +0 -363
- package/dist/update-VC3Y3EOP.js +0 -49
- package/dist/web/assets/index-ATAQvBwl.js +0 -312
|
@@ -24,10 +24,10 @@ import {
|
|
|
24
24
|
terminalManager,
|
|
25
25
|
tokenFromPassword,
|
|
26
26
|
verifyPassword
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-GP3CLMPQ.js";
|
|
28
28
|
import {
|
|
29
29
|
TEMPLATE_VARIABLES
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-5H5NRWHA.js";
|
|
31
31
|
import {
|
|
32
32
|
createToolRegistry,
|
|
33
33
|
devServerManager,
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
setMcpManagerForTools,
|
|
43
43
|
setMcpTools,
|
|
44
44
|
setNotifyMcpServersChanged
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-ESZQTFQP.js";
|
|
46
46
|
import {
|
|
47
47
|
checkoutBranchFromSharedSource,
|
|
48
48
|
deleteWorkspace,
|
|
@@ -86,12 +86,13 @@ import {
|
|
|
86
86
|
saveCommandToProject,
|
|
87
87
|
saveWorkflow,
|
|
88
88
|
saveWorkflowToProject,
|
|
89
|
+
serverT,
|
|
89
90
|
workflowExists
|
|
90
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-OZWHRBDY.js";
|
|
91
92
|
import {
|
|
92
93
|
getSessionDisabledServers,
|
|
93
94
|
setSessionDisabledServers
|
|
94
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-S67WIWUG.js";
|
|
95
96
|
import {
|
|
96
97
|
createMcpTools
|
|
97
98
|
} from "./chunk-JE7LW7Y6.js";
|
|
@@ -113,12 +114,12 @@ import {
|
|
|
113
114
|
setSkillEnabled,
|
|
114
115
|
skillExists,
|
|
115
116
|
updateOwnedSkill
|
|
116
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-DWA4IE65.js";
|
|
117
118
|
import {
|
|
118
119
|
ALWAYS_ALLOWED,
|
|
119
120
|
ALWAYS_ALLOWED_FOR_SUBAGENTS,
|
|
120
121
|
TOP_LEVEL_ONLY_TOOLS
|
|
121
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-7QMWYNVF.js";
|
|
122
123
|
import {
|
|
123
124
|
EventEmitter,
|
|
124
125
|
getPendingQuestionsForSession,
|
|
@@ -127,7 +128,7 @@ import {
|
|
|
127
128
|
import {
|
|
128
129
|
getPendingConfirmationsBySession,
|
|
129
130
|
providePathConfirmation
|
|
130
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-I5ODJKYM.js";
|
|
131
132
|
import {
|
|
132
133
|
combineEventsWithSnapshot,
|
|
133
134
|
emitAssistantMessageStart,
|
|
@@ -145,10 +146,10 @@ import {
|
|
|
145
146
|
getEventStore,
|
|
146
147
|
getSessionState,
|
|
147
148
|
initEventStore
|
|
148
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-QZOV4OVN.js";
|
|
149
150
|
import {
|
|
150
151
|
buildMessagesFromStoredEvents
|
|
151
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-MEEUXRFL.js";
|
|
152
153
|
import {
|
|
153
154
|
clearWorkflowExecution,
|
|
154
155
|
createSession,
|
|
@@ -162,6 +163,7 @@ import {
|
|
|
162
163
|
listSessions,
|
|
163
164
|
listSessionsByProject,
|
|
164
165
|
listSessionsLimited,
|
|
166
|
+
setSessionMessageCount,
|
|
165
167
|
toggleFavorite,
|
|
166
168
|
updateSessionBranch,
|
|
167
169
|
updateSessionCachedPrompt,
|
|
@@ -174,7 +176,7 @@ import {
|
|
|
174
176
|
updateSessionRunning,
|
|
175
177
|
updateSessionWorkdir,
|
|
176
178
|
updateWorkflowExecutionStatus
|
|
177
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-F2MOHHXB.js";
|
|
178
180
|
import {
|
|
179
181
|
agentExists,
|
|
180
182
|
deleteAgent,
|
|
@@ -191,7 +193,7 @@ import {
|
|
|
191
193
|
saveAgent,
|
|
192
194
|
saveAgentToProject,
|
|
193
195
|
setRuntimeConfig
|
|
194
|
-
} from "./chunk-
|
|
196
|
+
} from "./chunk-ORCQ3EXQ.js";
|
|
195
197
|
import {
|
|
196
198
|
findFileByInternalId,
|
|
197
199
|
pathExists
|
|
@@ -199,23 +201,23 @@ import {
|
|
|
199
201
|
import {
|
|
200
202
|
createContextStateMessage,
|
|
201
203
|
toClientSession
|
|
202
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-AATMPL7S.js";
|
|
203
205
|
import {
|
|
204
206
|
getPathSeparator,
|
|
205
207
|
isAbsolutePath
|
|
206
|
-
} from "./chunk-
|
|
208
|
+
} from "./chunk-O3RCSKUH.js";
|
|
207
209
|
import {
|
|
208
210
|
createProviderManager,
|
|
209
211
|
detectModel,
|
|
210
212
|
getLlmStatus,
|
|
211
213
|
parseDefaultModelSelection
|
|
212
|
-
} from "./chunk-
|
|
214
|
+
} from "./chunk-5UQ4CKOA.js";
|
|
213
215
|
import {
|
|
214
216
|
buildOpenFoxMcpBootstrap
|
|
215
217
|
} from "./chunk-YNMP647F.js";
|
|
216
218
|
import {
|
|
217
219
|
VERSION
|
|
218
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-WY3PWHWY.js";
|
|
219
221
|
import {
|
|
220
222
|
deleteProject,
|
|
221
223
|
getProject,
|
|
@@ -235,12 +237,12 @@ import {
|
|
|
235
237
|
import {
|
|
236
238
|
SessionNotFoundError,
|
|
237
239
|
WorkspaceInUseError
|
|
238
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-J3NMNYGM.js";
|
|
239
241
|
import {
|
|
240
242
|
deleteSetting,
|
|
241
243
|
getSetting,
|
|
242
244
|
setSetting
|
|
243
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-CTWZPN7G.js";
|
|
244
246
|
import {
|
|
245
247
|
initDatabase
|
|
246
248
|
} from "./chunk-JU757HVI.js";
|
|
@@ -253,7 +255,7 @@ import {
|
|
|
253
255
|
} from "./chunk-K44MW7JJ.js";
|
|
254
256
|
import {
|
|
255
257
|
createServerMessage
|
|
256
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-HF3NDXB4.js";
|
|
257
259
|
import {
|
|
258
260
|
getGlobalConfigDir
|
|
259
261
|
} from "./chunk-CQGTEGKL.js";
|
|
@@ -3095,6 +3097,94 @@ var SessionManager = class {
|
|
|
3095
3097
|
this.emit({ type: "session_updated", session: this.requireSession(newSession.id) });
|
|
3096
3098
|
return this.requireSession(newSession.id);
|
|
3097
3099
|
}
|
|
3100
|
+
/**
|
|
3101
|
+
* Import a session from an export document into a target project.
|
|
3102
|
+
*
|
|
3103
|
+
* The cached layout (system prompt, tools, hash) is restored verbatim so the
|
|
3104
|
+
* provider-side prefix cache stays valid, and the event history is replayed
|
|
3105
|
+
* as-is. Drift between the original environment's cached layout and the
|
|
3106
|
+
* target environment (system prompt, tools) is announced via injected
|
|
3107
|
+
* <system-reminder> messages, followed by an import marker reminder.
|
|
3108
|
+
*
|
|
3109
|
+
* @param projectId - Target project (the session is created there)
|
|
3110
|
+
* @param rawPayload - Exported session document (validated)
|
|
3111
|
+
* @returns The imported session
|
|
3112
|
+
* @throws Error for invalid payloads or unknown project
|
|
3113
|
+
*/
|
|
3114
|
+
async importSession(projectId, rawPayload) {
|
|
3115
|
+
const { parseSessionExport, IMPORTED_SESSION_REMINDER, SESSION_EXPORT_VERSION } = await import("./export-import-3WMRLO4A.js");
|
|
3116
|
+
const { injectContextDriftReminders, getToolSetFingerprint } = await import("./dynamic-context-LKC6JYLQ.js");
|
|
3117
|
+
const { loadAllAgentsDefault: loadAllAgentsDefault2, resolveDefaultAgentId } = await import("./registry-BEIR7Y5G.js");
|
|
3118
|
+
const payload = parseSessionExport(rawPayload);
|
|
3119
|
+
if (payload.version !== SESSION_EXPORT_VERSION) {
|
|
3120
|
+
throw new Error(`Unsupported session export version: ${payload.version}`);
|
|
3121
|
+
}
|
|
3122
|
+
const project = getProject(projectId);
|
|
3123
|
+
if (!project) {
|
|
3124
|
+
throw new Error(`Project not found: ${projectId}`);
|
|
3125
|
+
}
|
|
3126
|
+
if (!payload.events.some((event) => event.type === "session.initialized")) {
|
|
3127
|
+
throw new Error("Invalid session export: missing session.initialized event");
|
|
3128
|
+
}
|
|
3129
|
+
const providers = this.providerManager.getProviders();
|
|
3130
|
+
const providerId = payload.session.providerId ?? null;
|
|
3131
|
+
const providerModel = payload.session.providerModel ?? null;
|
|
3132
|
+
let resolvedProviderId = null;
|
|
3133
|
+
let resolvedProviderModel = null;
|
|
3134
|
+
if (providerId && providers.some((p) => p.id === providerId)) {
|
|
3135
|
+
resolvedProviderId = providerId;
|
|
3136
|
+
resolvedProviderModel = providerModel;
|
|
3137
|
+
} else if (providerId && payload.source?.providerBackend && payload.source.providerUrl) {
|
|
3138
|
+
const normalizeUrl = (url) => url.replace(/\/+$/, "");
|
|
3139
|
+
const sourceBackend = payload.source.providerBackend;
|
|
3140
|
+
const sourceUrl = normalizeUrl(payload.source.providerUrl);
|
|
3141
|
+
const urlMatch = providers.find(
|
|
3142
|
+
(p) => p.backend === sourceBackend && p.url !== void 0 && normalizeUrl(p.url) === sourceUrl && providerModel !== null && p.models.some((m) => m.id === providerModel || m.apiModelId === providerModel)
|
|
3143
|
+
);
|
|
3144
|
+
if (urlMatch) {
|
|
3145
|
+
resolvedProviderId = urlMatch.id;
|
|
3146
|
+
resolvedProviderModel = providerModel;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
const session = createSession(
|
|
3150
|
+
projectId,
|
|
3151
|
+
project.workdir,
|
|
3152
|
+
payload.session.title,
|
|
3153
|
+
resolvedProviderId,
|
|
3154
|
+
resolvedProviderModel
|
|
3155
|
+
);
|
|
3156
|
+
const eventStore = getEventStore();
|
|
3157
|
+
eventStore.importEvents(session.id, payload.events);
|
|
3158
|
+
const agents = await loadAllAgentsDefault2(project.workdir);
|
|
3159
|
+
const restoredMode = getSessionState(session.id)?.mode ?? session.mode;
|
|
3160
|
+
if (!agents.some((agent) => agent.metadata.id === restoredMode)) {
|
|
3161
|
+
this.setMode(session.id, resolveDefaultAgentId(projectId));
|
|
3162
|
+
}
|
|
3163
|
+
if (payload.cachedLayout) {
|
|
3164
|
+
updateSessionCachedPrompt(
|
|
3165
|
+
session.id,
|
|
3166
|
+
payload.cachedLayout.systemPrompt,
|
|
3167
|
+
payload.cachedLayout.tools,
|
|
3168
|
+
payload.cachedLayout.hash,
|
|
3169
|
+
payload.cachedLayout.promptHash
|
|
3170
|
+
);
|
|
3171
|
+
this.setAnnouncedPromptHash(session.id, payload.cachedLayout.promptHash ?? payload.cachedLayout.hash);
|
|
3172
|
+
this.setAnnouncedToolFingerprint(session.id, getToolSetFingerprint(payload.cachedLayout.tools));
|
|
3173
|
+
this.markWarmedUp(session.id);
|
|
3174
|
+
}
|
|
3175
|
+
await injectContextDriftReminders(this, session.id);
|
|
3176
|
+
emitUserMessage(session.id, IMPORTED_SESSION_REMINDER, {
|
|
3177
|
+
isSystemGenerated: true,
|
|
3178
|
+
messageKind: "auto-prompt",
|
|
3179
|
+
metadata: { type: "session-import", name: "Session Imported", color: "#6b7280", kind: "reminder" }
|
|
3180
|
+
});
|
|
3181
|
+
const state = getSessionState(session.id);
|
|
3182
|
+
if (state) {
|
|
3183
|
+
setSessionMessageCount(session.id, state.messages.length);
|
|
3184
|
+
}
|
|
3185
|
+
this.emit({ type: "session_created", session: this.requireSession(session.id) });
|
|
3186
|
+
return this.requireSession(session.id);
|
|
3187
|
+
}
|
|
3098
3188
|
/**
|
|
3099
3189
|
* Get a session by ID. Returns null if not found.
|
|
3100
3190
|
* Session state is derived from EventStore.
|
|
@@ -3990,13 +4080,33 @@ var SessionManager = class {
|
|
|
3990
4080
|
}
|
|
3991
4081
|
} catch (innerErr) {
|
|
3992
4082
|
throw new Error(
|
|
3993
|
-
|
|
4083
|
+
serverT(
|
|
4084
|
+
{
|
|
4085
|
+
en: 'Failed to create branch "{{branch}}" in workspace "{{workspace}}": {{reason}}',
|
|
4086
|
+
fr: "\xC9chec de cr\xE9ation de la branche \xAB {{branch}} \xBB dans le workspace \xAB {{workspace}} \xBB : {{reason}}"
|
|
4087
|
+
},
|
|
4088
|
+
{
|
|
4089
|
+
branch,
|
|
4090
|
+
workspace: workspaceName,
|
|
4091
|
+
reason: innerErr instanceof Error ? innerErr.message : String(innerErr)
|
|
4092
|
+
}
|
|
4093
|
+
)
|
|
3994
4094
|
);
|
|
3995
4095
|
}
|
|
3996
4096
|
});
|
|
3997
4097
|
} catch (err) {
|
|
3998
4098
|
throw new Error(
|
|
3999
|
-
|
|
4099
|
+
serverT(
|
|
4100
|
+
{
|
|
4101
|
+
en: 'Failed to apply branch "{{branch}}" to workspace "{{workspace}}": {{reason}}',
|
|
4102
|
+
fr: "\xC9chec d\u2019application de la branche \xAB {{branch}} \xBB au workspace \xAB {{workspace}} \xBB : {{reason}}"
|
|
4103
|
+
},
|
|
4104
|
+
{
|
|
4105
|
+
branch,
|
|
4106
|
+
workspace: workspaceName,
|
|
4107
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
4108
|
+
}
|
|
4109
|
+
)
|
|
4000
4110
|
);
|
|
4001
4111
|
}
|
|
4002
4112
|
}
|
|
@@ -4375,8 +4485,16 @@ async function loadItemsForScope(config3, configDir, projectDir, scope) {
|
|
|
4375
4485
|
var ID_REGEX = /^[a-z0-9-]+$/;
|
|
4376
4486
|
function validateNameIdPrompt(body) {
|
|
4377
4487
|
const meta = body["metadata"];
|
|
4378
|
-
if (!meta?.["name"] || !body["prompt"])
|
|
4379
|
-
|
|
4488
|
+
if (!meta?.["name"] || !body["prompt"])
|
|
4489
|
+
return serverT({
|
|
4490
|
+
en: "Missing required fields: metadata.name, prompt",
|
|
4491
|
+
fr: "Champs requis manquants : metadata.name, prompt"
|
|
4492
|
+
});
|
|
4493
|
+
if (meta["id"] && !ID_REGEX.test(String(meta["id"])))
|
|
4494
|
+
return serverT({
|
|
4495
|
+
en: "ID must be lowercase alphanumeric with hyphens only",
|
|
4496
|
+
fr: "L\u2019ID doit \xEAtre en minuscules alphanum\xE9riques, avec des tirets uniquement"
|
|
4497
|
+
});
|
|
4380
4498
|
return null;
|
|
4381
4499
|
}
|
|
4382
4500
|
function getProjectItemPath(projectDir, dirName, id, ext) {
|
|
@@ -4416,7 +4534,7 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4416
4534
|
const allDefaults = await config3.loadDefaults();
|
|
4417
4535
|
const item = allDefaults.find((d) => d.metadata.id === id);
|
|
4418
4536
|
if (!item) {
|
|
4419
|
-
return res.status(404).json({ error: "Default not found" });
|
|
4537
|
+
return res.status(404).json({ error: serverT({ en: "Default not found", fr: "\xC9l\xE9ment par d\xE9faut introuvable" }) });
|
|
4420
4538
|
}
|
|
4421
4539
|
res.json(item);
|
|
4422
4540
|
});
|
|
@@ -4432,7 +4550,7 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4432
4550
|
const items = await loadItemsForScope(config3, configDir, effectiveProjectDir, scope);
|
|
4433
4551
|
const item = config3.findById(id, items);
|
|
4434
4552
|
if (!item) {
|
|
4435
|
-
return res.status(404).json({ error: "Not found" });
|
|
4553
|
+
return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4436
4554
|
}
|
|
4437
4555
|
res.json(item);
|
|
4438
4556
|
});
|
|
@@ -4441,17 +4559,19 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4441
4559
|
const meta = body["metadata"];
|
|
4442
4560
|
const customError = config3.validateCreate?.(body);
|
|
4443
4561
|
if (!meta?.["id"] || customError) {
|
|
4444
|
-
return res.status(400).json({ error: customError ?? "Missing required fields" });
|
|
4562
|
+
return res.status(400).json({ error: customError ?? serverT({ en: "Missing required fields", fr: "Champs requis manquants" }) });
|
|
4445
4563
|
}
|
|
4446
4564
|
const id = String(meta["id"]);
|
|
4447
4565
|
const destination = body["destination"] ?? "user";
|
|
4448
4566
|
const effectiveProjectDir = resolveProjectDir(req, projectDir);
|
|
4449
4567
|
if (destination === "project" && !effectiveProjectDir) {
|
|
4450
|
-
return res.status(400).json({ error: "No project directory configured" });
|
|
4568
|
+
return res.status(400).json({ error: serverT({ en: "No project directory configured", fr: "Aucun r\xE9pertoire de projet configur\xE9" }) });
|
|
4451
4569
|
}
|
|
4452
4570
|
const exists = await config3.exists(configDir, id, effectiveProjectDir);
|
|
4453
4571
|
if (exists) {
|
|
4454
|
-
return res.status(409).json({
|
|
4572
|
+
return res.status(409).json({
|
|
4573
|
+
error: serverT({ en: "An item with this ID already exists", fr: "Un \xE9l\xE9ment avec cet ID existe d\xE9j\xE0" })
|
|
4574
|
+
});
|
|
4455
4575
|
}
|
|
4456
4576
|
if (destination === "project") {
|
|
4457
4577
|
await config3.saveToProject(effectiveProjectDir, body);
|
|
@@ -4466,7 +4586,7 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4466
4586
|
const items = await config3.loadAll(configDir, effectiveProjectDir);
|
|
4467
4587
|
const existing = config3.findById(id, items);
|
|
4468
4588
|
if (!existing) {
|
|
4469
|
-
return res.status(404).json({ error: "Not found" });
|
|
4589
|
+
return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4470
4590
|
}
|
|
4471
4591
|
const body = req.body;
|
|
4472
4592
|
const meta = body["metadata"];
|
|
@@ -4492,7 +4612,7 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4492
4612
|
const result = target === "project" ? await config3.deleteProject(effectiveProjectDir, id) : await config3.delete(configDir, id);
|
|
4493
4613
|
if (!result.success) {
|
|
4494
4614
|
return res.status(target === "project" ? 500 : 403).json({
|
|
4495
|
-
error: target === "project" ? "Failed to delete project item" : result.reason ?? "Cannot delete this item"
|
|
4615
|
+
error: target === "project" ? serverT({ en: "Failed to delete project item", fr: "\xC9chec de suppression de l\u2019\xE9l\xE9ment de projet" }) : result.reason ?? serverT({ en: "Cannot delete this item", fr: "Impossible de supprimer cet \xE9l\xE9ment" })
|
|
4496
4616
|
});
|
|
4497
4617
|
}
|
|
4498
4618
|
res.json({ success: true });
|
|
@@ -4503,7 +4623,7 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4503
4623
|
const items = await config3.loadAll(configDir, effectiveProjectDir);
|
|
4504
4624
|
const source = config3.findById(id, items);
|
|
4505
4625
|
if (!source) {
|
|
4506
|
-
return res.status(404).json({ error: "Not found" });
|
|
4626
|
+
return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4507
4627
|
}
|
|
4508
4628
|
const newId = `${id}-copy-${Date.now()}`;
|
|
4509
4629
|
const duplicated = {
|
|
@@ -4512,7 +4632,10 @@ function createCrudRoutes(config3, configDir, projectDir) {
|
|
|
4512
4632
|
};
|
|
4513
4633
|
const destination = req.body.destination ?? "user";
|
|
4514
4634
|
if (destination === "project") {
|
|
4515
|
-
if (!effectiveProjectDir)
|
|
4635
|
+
if (!effectiveProjectDir)
|
|
4636
|
+
return res.status(400).json({
|
|
4637
|
+
error: serverT({ en: "No project directory configured", fr: "Aucun r\xE9pertoire de projet configur\xE9" })
|
|
4638
|
+
});
|
|
4516
4639
|
await config3.saveToProject(effectiveProjectDir, duplicated);
|
|
4517
4640
|
} else {
|
|
4518
4641
|
await config3.save(configDir, duplicated);
|
|
@@ -4625,13 +4748,16 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
4625
4748
|
const router = Router2();
|
|
4626
4749
|
router.put("/library", async (req, res) => {
|
|
4627
4750
|
const path = req.body.path;
|
|
4628
|
-
if (typeof path !== "string" || !path.trim())
|
|
4751
|
+
if (typeof path !== "string" || !path.trim())
|
|
4752
|
+
return res.status(400).json({ error: serverT({ en: "path is required", fr: "path est requis" }) });
|
|
4629
4753
|
try {
|
|
4630
4754
|
const selected = await resolveLibrary(path);
|
|
4631
4755
|
setSetting(SKILL_DIRECTORIES_SETTING, JSON.stringify([path]));
|
|
4632
4756
|
res.json(selected);
|
|
4633
4757
|
} catch (error) {
|
|
4634
|
-
res.status(400).json({
|
|
4758
|
+
res.status(400).json({
|
|
4759
|
+
error: error instanceof Error ? error.message : serverT({ en: "Cannot use directory", fr: "Impossible d\u2019utiliser ce r\xE9pertoire" })
|
|
4760
|
+
});
|
|
4635
4761
|
}
|
|
4636
4762
|
});
|
|
4637
4763
|
router.delete("/library", (_req, res) => {
|
|
@@ -4649,10 +4775,16 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
4649
4775
|
const paths = JSON.parse(String(req.body["paths"] ?? "[]"));
|
|
4650
4776
|
const files = req.files;
|
|
4651
4777
|
if (!Array.isArray(paths) || paths.length !== files.length || paths.some((path) => typeof path !== "string")) {
|
|
4652
|
-
return res.status(400).json({
|
|
4778
|
+
return res.status(400).json({
|
|
4779
|
+
error: serverT({
|
|
4780
|
+
en: "File path manifest does not match upload",
|
|
4781
|
+
fr: "Le manifeste des chemins de fichiers ne correspond pas \xE0 l\u2019envoi"
|
|
4782
|
+
})
|
|
4783
|
+
});
|
|
4653
4784
|
}
|
|
4654
4785
|
const totalBytes = files.reduce((total, file) => total + file.size, 0);
|
|
4655
|
-
if (totalBytes > 50 * 1024 * 1024)
|
|
4786
|
+
if (totalBytes > 50 * 1024 * 1024)
|
|
4787
|
+
return res.status(413).json({ error: serverT({ en: "Package exceeds 50 MiB", fr: "Le paquet d\xE9passe 50 Mio" }) });
|
|
4656
4788
|
const installed = await installSkillPackage(
|
|
4657
4789
|
library.resolvedPath,
|
|
4658
4790
|
packageName,
|
|
@@ -4661,29 +4793,35 @@ function createSkillRoutes(configDir, projectDir) {
|
|
|
4661
4793
|
res.status(201).json(installed);
|
|
4662
4794
|
} catch (error) {
|
|
4663
4795
|
const status = error instanceof SkillInstallError ? error.status : 400;
|
|
4664
|
-
res.status(status).json({
|
|
4796
|
+
res.status(status).json({
|
|
4797
|
+
error: error instanceof Error ? error.message : serverT({ en: "Install failed", fr: "\xC9chec de l\u2019installation" })
|
|
4798
|
+
});
|
|
4665
4799
|
}
|
|
4666
4800
|
});
|
|
4667
4801
|
});
|
|
4668
4802
|
router.post("/:id/toggle", async (req, res) => {
|
|
4669
4803
|
const existing = await findSkillByIdForRequest(req, configDir, projectDir);
|
|
4670
|
-
if (!existing) return res.status(404).json({ error: "Not found" });
|
|
4804
|
+
if (!existing) return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4671
4805
|
const enabled = !isSkillEnabled(existing.metadata.id);
|
|
4672
4806
|
setSkillEnabled(existing.metadata.id, enabled);
|
|
4673
4807
|
res.json({ enabled });
|
|
4674
4808
|
});
|
|
4675
4809
|
router.put("/:id", async (req, res) => {
|
|
4676
4810
|
const existing = await findSkillByIdForRequest(req, configDir, projectDir);
|
|
4677
|
-
if (!existing) return res.status(404).json({ error: "Not found" });
|
|
4811
|
+
if (!existing) return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4678
4812
|
const updated = await updateOwnedSkill(existing, req.body);
|
|
4679
|
-
if (!updated)
|
|
4813
|
+
if (!updated)
|
|
4814
|
+
return res.status(403).json({ error: serverT({ en: "This skill is read-only", fr: "Cette comp\xE9tence est en lecture seule" }) });
|
|
4680
4815
|
res.json(updated);
|
|
4681
4816
|
});
|
|
4682
4817
|
router.delete("/:id", async (req, res) => {
|
|
4683
4818
|
const existing = await findSkillByIdForRequest(req, configDir, projectDir);
|
|
4684
|
-
if (!existing) return res.status(404).json({ error: "Not found" });
|
|
4819
|
+
if (!existing) return res.status(404).json({ error: serverT({ en: "Not found", fr: "Introuvable" }) });
|
|
4685
4820
|
const result = await deleteOwnedSkill(existing);
|
|
4686
|
-
if (!result.success)
|
|
4821
|
+
if (!result.success)
|
|
4822
|
+
return res.status(403).json({
|
|
4823
|
+
error: result.reason ?? serverT({ en: "Cannot delete this skill", fr: "Impossible de supprimer cette comp\xE9tence" })
|
|
4824
|
+
});
|
|
4687
4825
|
res.json({ success: true });
|
|
4688
4826
|
});
|
|
4689
4827
|
router.use(createCrudRoutes(createConfig(configDir, projectDir), configDir, projectDir));
|
|
@@ -4767,7 +4905,12 @@ var config2 = {
|
|
|
4767
4905
|
const { id } = req.params;
|
|
4768
4906
|
const { providerId, model, reasoningEffort } = req.body;
|
|
4769
4907
|
if (reasoningEffort !== void 0 && !isReasoningEffortValue(reasoningEffort)) {
|
|
4770
|
-
return res.status(400).json({
|
|
4908
|
+
return res.status(400).json({
|
|
4909
|
+
error: serverT(
|
|
4910
|
+
{ en: "Unsupported reasoningEffort: {{value}}", fr: "reasoningEffort non pris en charge : {{value}}" },
|
|
4911
|
+
{ value: String(reasoningEffort) }
|
|
4912
|
+
)
|
|
4913
|
+
});
|
|
4771
4914
|
}
|
|
4772
4915
|
if (providerId && model) {
|
|
4773
4916
|
setAgentModelOverride(id, {
|
|
@@ -5595,7 +5738,7 @@ function createDevServerRoutes() {
|
|
|
5595
5738
|
const router = Router5();
|
|
5596
5739
|
router.get("/", async (req, res) => {
|
|
5597
5740
|
const workdir = req.query["workdir"];
|
|
5598
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5741
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5599
5742
|
const status = devServerManager.getStatus(workdir);
|
|
5600
5743
|
if (!status.config) {
|
|
5601
5744
|
const config3 = await devServerManager.loadConfig(workdir);
|
|
@@ -5609,37 +5752,41 @@ function createDevServerRoutes() {
|
|
|
5609
5752
|
});
|
|
5610
5753
|
router.post("/start", async (req, res) => {
|
|
5611
5754
|
const workdir = req.query["workdir"];
|
|
5612
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5755
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5613
5756
|
try {
|
|
5614
5757
|
const status = await devServerManager.start(workdir);
|
|
5615
5758
|
res.json(status);
|
|
5616
5759
|
} catch (err) {
|
|
5617
|
-
res.status(500).json({
|
|
5760
|
+
res.status(500).json({
|
|
5761
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to start", fr: "\xC9chec du d\xE9marrage" })
|
|
5762
|
+
});
|
|
5618
5763
|
}
|
|
5619
5764
|
});
|
|
5620
5765
|
router.post("/stop", async (req, res) => {
|
|
5621
5766
|
const workdir = req.query["workdir"];
|
|
5622
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5767
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5623
5768
|
try {
|
|
5624
5769
|
const status = await devServerManager.stop(workdir);
|
|
5625
5770
|
res.json(status);
|
|
5626
5771
|
} catch (err) {
|
|
5627
|
-
res.status(500).json({ error: err instanceof Error ? err.message : "Failed to stop" });
|
|
5772
|
+
res.status(500).json({ error: err instanceof Error ? err.message : serverT({ en: "Failed to stop", fr: "\xC9chec de l\u2019arr\xEAt" }) });
|
|
5628
5773
|
}
|
|
5629
5774
|
});
|
|
5630
5775
|
router.post("/restart", async (req, res) => {
|
|
5631
5776
|
const workdir = req.query["workdir"];
|
|
5632
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5777
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5633
5778
|
try {
|
|
5634
5779
|
const status = await devServerManager.restart(workdir);
|
|
5635
5780
|
res.json(status);
|
|
5636
5781
|
} catch (err) {
|
|
5637
|
-
res.status(500).json({
|
|
5782
|
+
res.status(500).json({
|
|
5783
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to restart", fr: "\xC9chec du red\xE9marrage" })
|
|
5784
|
+
});
|
|
5638
5785
|
}
|
|
5639
5786
|
});
|
|
5640
5787
|
router.get("/logs", (req, res) => {
|
|
5641
5788
|
const workdir = req.query["workdir"];
|
|
5642
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5789
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5643
5790
|
const offset = Math.max(0, parseInt(req.query["offset"]) || 0);
|
|
5644
5791
|
const limit = Math.max(1, parseInt(req.query["limit"]) || Infinity);
|
|
5645
5792
|
const result = devServerManager.getLogsSlice(workdir, offset, limit);
|
|
@@ -5647,43 +5794,51 @@ function createDevServerRoutes() {
|
|
|
5647
5794
|
});
|
|
5648
5795
|
router.post("/clear-logs", (req, res) => {
|
|
5649
5796
|
const workdir = req.query["workdir"];
|
|
5650
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5797
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5651
5798
|
try {
|
|
5652
5799
|
devServerManager.clearLogs(workdir);
|
|
5653
5800
|
res.json({ ok: true });
|
|
5654
5801
|
} catch (err) {
|
|
5655
|
-
res.status(500).json({
|
|
5802
|
+
res.status(500).json({
|
|
5803
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to clear logs", fr: "\xC9chec de l\u2019effacement des journaux" })
|
|
5804
|
+
});
|
|
5656
5805
|
}
|
|
5657
5806
|
});
|
|
5658
5807
|
router.post("/insert-marker", (req, res) => {
|
|
5659
5808
|
const workdir = req.query["workdir"];
|
|
5660
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5809
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5661
5810
|
try {
|
|
5662
5811
|
devServerManager.insertMarker(workdir);
|
|
5663
5812
|
res.json({ ok: true });
|
|
5664
5813
|
} catch (err) {
|
|
5665
|
-
res.status(500).json({
|
|
5814
|
+
res.status(500).json({
|
|
5815
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to insert marker", fr: "\xC9chec de l\u2019insertion du marqueur" })
|
|
5816
|
+
});
|
|
5666
5817
|
}
|
|
5667
5818
|
});
|
|
5668
5819
|
router.get("/config", async (req, res) => {
|
|
5669
5820
|
const workdir = req.query["workdir"];
|
|
5670
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5821
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5671
5822
|
const config3 = await devServerManager.loadConfig(workdir);
|
|
5672
5823
|
res.json({ config: config3 });
|
|
5673
5824
|
});
|
|
5674
5825
|
router.post("/config", async (req, res) => {
|
|
5675
5826
|
const workdir = req.query["workdir"];
|
|
5676
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5827
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5677
5828
|
const { command, url, hotReload, disableInspect } = req.body;
|
|
5678
5829
|
if (!command || !url) {
|
|
5679
|
-
return res.status(400).json({
|
|
5830
|
+
return res.status(400).json({
|
|
5831
|
+
error: serverT({ en: "command and url are required", fr: "command et url sont requis" })
|
|
5832
|
+
});
|
|
5680
5833
|
}
|
|
5681
5834
|
try {
|
|
5682
5835
|
const config3 = { command, url, hotReload: hotReload ?? false, disableInspect: disableInspect ?? false };
|
|
5683
5836
|
await devServerManager.saveConfig(workdir, config3);
|
|
5684
5837
|
res.json({ config: config3 });
|
|
5685
5838
|
} catch (err) {
|
|
5686
|
-
res.status(500).json({
|
|
5839
|
+
res.status(500).json({
|
|
5840
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to save config", fr: "\xC9chec de l\u2019enregistrement de la configuration" })
|
|
5841
|
+
});
|
|
5687
5842
|
}
|
|
5688
5843
|
});
|
|
5689
5844
|
return router;
|
|
@@ -5762,7 +5917,37 @@ async function checkDirExists(path) {
|
|
|
5762
5917
|
}
|
|
5763
5918
|
async function validatePathWritable(path) {
|
|
5764
5919
|
if (await isWritable(path)) return null;
|
|
5765
|
-
return
|
|
5920
|
+
return serverT({
|
|
5921
|
+
en: "Workspace root directory exists but is not writable",
|
|
5922
|
+
fr: "Le r\xE9pertoire racine du workspace existe mais n\u2019est pas accessible en \xE9criture"
|
|
5923
|
+
});
|
|
5924
|
+
}
|
|
5925
|
+
function rootDirBlockError(blockReason, displayPath, suggestion) {
|
|
5926
|
+
if (blockReason === "exact") {
|
|
5927
|
+
return suggestion ? serverT(
|
|
5928
|
+
{
|
|
5929
|
+
en: 'Cannot use "{{path}}" directly as workspace root. Use a subdirectory like "{{suggestion}}" instead.',
|
|
5930
|
+
fr: "Impossible d\u2019utiliser \xAB {{path}} \xBB directement comme racine du workspace. Utilisez plut\xF4t un sous-r\xE9pertoire comme \xAB {{suggestion}} \xBB."
|
|
5931
|
+
},
|
|
5932
|
+
{ path: displayPath, suggestion }
|
|
5933
|
+
) : serverT(
|
|
5934
|
+
{
|
|
5935
|
+
en: 'Cannot use "{{path}}" directly as workspace root. Use a subdirectory instead.',
|
|
5936
|
+
fr: "Impossible d\u2019utiliser \xAB {{path}} \xBB directement comme racine du workspace. Utilisez un sous-r\xE9pertoire \xE0 la place."
|
|
5937
|
+
},
|
|
5938
|
+
{ path: displayPath }
|
|
5939
|
+
);
|
|
5940
|
+
}
|
|
5941
|
+
if (blockReason === "virtual_fs") {
|
|
5942
|
+
return serverT(
|
|
5943
|
+
{
|
|
5944
|
+
en: 'Cannot use paths under "{{path}}" for workspaces.',
|
|
5945
|
+
fr: "Impossible d\u2019utiliser des chemins sous \xAB {{path}} \xBB pour les workspaces."
|
|
5946
|
+
},
|
|
5947
|
+
{ path: displayPath }
|
|
5948
|
+
);
|
|
5949
|
+
}
|
|
5950
|
+
return null;
|
|
5766
5951
|
}
|
|
5767
5952
|
async function findOrphanedWorkspaces(dir) {
|
|
5768
5953
|
const results = [];
|
|
@@ -5790,7 +5975,7 @@ function createWorkspaceConfigRoutes(sessionManager) {
|
|
|
5790
5975
|
const router = Router6();
|
|
5791
5976
|
router.get("/config", async (req, res) => {
|
|
5792
5977
|
const workdir = req.query["workdir"];
|
|
5793
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5978
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5794
5979
|
const config3 = await loadWorkspaceConfig(workdir);
|
|
5795
5980
|
const project = getProjectByWorkdir(workdir);
|
|
5796
5981
|
const rootDir = project?.workspaceRootDir ?? void 0;
|
|
@@ -5800,16 +5985,28 @@ function createWorkspaceConfigRoutes(sessionManager) {
|
|
|
5800
5985
|
});
|
|
5801
5986
|
router.post("/config", async (req, res) => {
|
|
5802
5987
|
const workdir = req.query["workdir"];
|
|
5803
|
-
if (!workdir) return res.status(400).json({ error: "workdir required" });
|
|
5988
|
+
if (!workdir) return res.status(400).json({ error: serverT({ en: "workdir required", fr: "workdir requis" }) });
|
|
5804
5989
|
const { setup, rootDir, mcpOverrides } = req.body;
|
|
5805
5990
|
if (!Array.isArray(setup) && typeof rootDir !== "string" && mcpOverrides === void 0) {
|
|
5806
|
-
return res.status(400).json({
|
|
5991
|
+
return res.status(400).json({
|
|
5992
|
+
error: serverT({
|
|
5993
|
+
en: "At least one of setup, rootDir, or mcpOverrides must be provided",
|
|
5994
|
+
fr: "Au moins un de setup, rootDir ou mcpOverrides doit \xEAtre fourni"
|
|
5995
|
+
})
|
|
5996
|
+
});
|
|
5807
5997
|
}
|
|
5808
5998
|
if (setup !== void 0 && !Array.isArray(setup)) {
|
|
5809
|
-
return res.status(400).json({
|
|
5999
|
+
return res.status(400).json({
|
|
6000
|
+
error: serverT({ en: "setup must be an array of strings", fr: "setup doit \xEAtre un tableau de cha\xEEnes" })
|
|
6001
|
+
});
|
|
5810
6002
|
}
|
|
5811
6003
|
if (mcpOverrides !== void 0 && (typeof mcpOverrides !== "object" || mcpOverrides === null || Array.isArray(mcpOverrides))) {
|
|
5812
|
-
return res.status(400).json({
|
|
6004
|
+
return res.status(400).json({
|
|
6005
|
+
error: serverT({
|
|
6006
|
+
en: "mcpOverrides must be an object mapping server names to overrides",
|
|
6007
|
+
fr: "mcpOverrides doit \xEAtre un objet associant les noms de serveurs \xE0 des surcharges"
|
|
6008
|
+
})
|
|
6009
|
+
});
|
|
5813
6010
|
}
|
|
5814
6011
|
const existing = await loadWorkspaceConfig(workdir);
|
|
5815
6012
|
const config3 = { ...existing };
|
|
@@ -5823,12 +6020,8 @@ function createWorkspaceConfigRoutes(sessionManager) {
|
|
|
5823
6020
|
const resolvedPath = resolveRootDir(trimmed, workdir);
|
|
5824
6021
|
const displayPath = formatRootDir(resolvedPath);
|
|
5825
6022
|
const blockReason = getRootDirBlockReason(resolvedPath);
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
}
|
|
5829
|
-
if (blockReason === "virtual_fs") {
|
|
5830
|
-
return res.status(400).json({ error: `Cannot use paths under "${displayPath}" for workspaces.` });
|
|
5831
|
-
}
|
|
6023
|
+
const blockError = rootDirBlockError(blockReason, displayPath);
|
|
6024
|
+
if (blockError) return res.status(400).json({ error: blockError });
|
|
5832
6025
|
const dirExists = await checkDirExists(resolvedPath);
|
|
5833
6026
|
if (dirExists) {
|
|
5834
6027
|
const writableErr = await validatePathWritable(resolvedPath);
|
|
@@ -5865,29 +6058,25 @@ function createWorkspaceConfigRoutes(sessionManager) {
|
|
|
5865
6058
|
}
|
|
5866
6059
|
res.json({ config: { ...config3, rootDir: savedRootDir ?? void 0 } });
|
|
5867
6060
|
} catch (err) {
|
|
5868
|
-
res.status(500).json({
|
|
6061
|
+
res.status(500).json({
|
|
6062
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to save config", fr: "\xC9chec de l\u2019enregistrement de la configuration" })
|
|
6063
|
+
});
|
|
5869
6064
|
}
|
|
5870
6065
|
});
|
|
5871
6066
|
router.post("/config/validate", async (req, res) => {
|
|
5872
6067
|
const { rootDir, workdir, projectName, createIfMissing } = req.body;
|
|
5873
6068
|
if (!rootDir || typeof rootDir !== "string") {
|
|
5874
|
-
return res.status(400).json({ error: "rootDir is required" });
|
|
6069
|
+
return res.status(400).json({ error: serverT({ en: "rootDir is required", fr: "rootDir est requis" }) });
|
|
5875
6070
|
}
|
|
5876
6071
|
if (!workdir || typeof workdir !== "string") {
|
|
5877
|
-
return res.status(400).json({ error: "workdir is required" });
|
|
6072
|
+
return res.status(400).json({ error: serverT({ en: "workdir is required", fr: "workdir est requis" }) });
|
|
5878
6073
|
}
|
|
5879
6074
|
const resolvedPath = resolveRootDir(rootDir, workdir);
|
|
5880
6075
|
const displayPath = formatRootDir(resolvedPath);
|
|
5881
6076
|
const blockReason = getRootDirBlockReason(resolvedPath);
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
error: suggestion ? `Cannot use "${displayPath}" directly as workspace root. Use a subdirectory like "${suggestion}" instead.` : `Cannot use "${displayPath}" directly as workspace root. Use a subdirectory instead.`
|
|
5886
|
-
});
|
|
5887
|
-
}
|
|
5888
|
-
if (blockReason === "virtual_fs") {
|
|
5889
|
-
return res.status(400).json({ error: `Cannot use paths under "${displayPath}" for workspaces.` });
|
|
5890
|
-
}
|
|
6077
|
+
const suggestion = typeof projectName === "string" ? suggestRootDirChild(resolvedPath, projectName) : void 0;
|
|
6078
|
+
const blockError = rootDirBlockError(blockReason, displayPath, suggestion);
|
|
6079
|
+
if (blockError) return res.status(400).json({ error: blockError });
|
|
5891
6080
|
let dirExists = await checkDirExists(resolvedPath);
|
|
5892
6081
|
if (dirExists) {
|
|
5893
6082
|
const writableErr = await validatePathWritable(resolvedPath);
|
|
@@ -5946,7 +6135,7 @@ function createTerminalRoutes() {
|
|
|
5946
6135
|
if (success) {
|
|
5947
6136
|
res.status(204).send();
|
|
5948
6137
|
} else {
|
|
5949
|
-
res.status(404).json({ error: "Terminal not found" });
|
|
6138
|
+
res.status(404).json({ error: serverT({ en: "Terminal not found", fr: "Terminal introuvable" }) });
|
|
5950
6139
|
}
|
|
5951
6140
|
});
|
|
5952
6141
|
router.get("/:id", (req, res) => {
|
|
@@ -5955,7 +6144,7 @@ function createTerminalRoutes() {
|
|
|
5955
6144
|
if (session) {
|
|
5956
6145
|
res.json({ id: session.id, workdir: session.workdir });
|
|
5957
6146
|
} else {
|
|
5958
|
-
res.status(404).json({ error: "Terminal not found" });
|
|
6147
|
+
res.status(404).json({ error: serverT({ en: "Terminal not found", fr: "Terminal introuvable" }) });
|
|
5959
6148
|
}
|
|
5960
6149
|
});
|
|
5961
6150
|
return router;
|
|
@@ -5989,7 +6178,7 @@ function createDirectoryRoutes() {
|
|
|
5989
6178
|
});
|
|
5990
6179
|
} catch {
|
|
5991
6180
|
res.status(400).json({
|
|
5992
|
-
error: "Cannot read directory",
|
|
6181
|
+
error: serverT({ en: "Cannot read directory", fr: "Impossible de lire le r\xE9pertoire" }),
|
|
5993
6182
|
current: DEFAULT_BASE_PATH,
|
|
5994
6183
|
parent: null,
|
|
5995
6184
|
directories: [],
|
|
@@ -6022,7 +6211,7 @@ function createFileSearchRoutes() {
|
|
|
6022
6211
|
const results = await searchFiles(query, workdir);
|
|
6023
6212
|
res.json(results);
|
|
6024
6213
|
} catch {
|
|
6025
|
-
res.status(500).json({ error: "File search failed" });
|
|
6214
|
+
res.status(500).json({ error: serverT({ en: "File search failed", fr: "\xC9chec de la recherche de fichiers" }) });
|
|
6026
6215
|
}
|
|
6027
6216
|
});
|
|
6028
6217
|
return router;
|
|
@@ -6127,6 +6316,11 @@ async function checkAuth(req, opts) {
|
|
|
6127
6316
|
}
|
|
6128
6317
|
return true;
|
|
6129
6318
|
}
|
|
6319
|
+
async function requireAuth(req, res, opts) {
|
|
6320
|
+
if (await checkAuth(req, opts)) return true;
|
|
6321
|
+
res.status(401).json({ error: serverT({ en: "Unauthorized", fr: "Non autoris\xE9" }) });
|
|
6322
|
+
return false;
|
|
6323
|
+
}
|
|
6130
6324
|
function isDevMode() {
|
|
6131
6325
|
return process.env["NODE_ENV"] === "development";
|
|
6132
6326
|
}
|
|
@@ -6252,12 +6446,9 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
6252
6446
|
}
|
|
6253
6447
|
});
|
|
6254
6448
|
router.post("/", async (req, res) => {
|
|
6255
|
-
if (!await
|
|
6256
|
-
res.status(401).json({ error: "Unauthorized" });
|
|
6257
|
-
return;
|
|
6258
|
-
}
|
|
6449
|
+
if (!await requireAuth(req, res, options)) return;
|
|
6259
6450
|
if (updateInProgress) {
|
|
6260
|
-
res.status(409).json({ error: "Update already in progress" });
|
|
6451
|
+
res.status(409).json({ error: serverT({ en: "Update already in progress", fr: "Une mise \xE0 jour est d\xE9j\xE0 en cours" }) });
|
|
6261
6452
|
return;
|
|
6262
6453
|
}
|
|
6263
6454
|
updateInProgress = true;
|
|
@@ -6289,20 +6480,19 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
6289
6480
|
const version = versionMatch?.[1] ?? VERSION;
|
|
6290
6481
|
res.json({ success: true, version, isService });
|
|
6291
6482
|
} else {
|
|
6292
|
-
const error = exitCode === null ? "Update timed out" : stderr || stdout || "Update failed";
|
|
6483
|
+
const error = exitCode === null ? serverT({ en: "Update timed out", fr: "Mise \xE0 jour expir\xE9e" }) : stderr || stdout || serverT({ en: "Update failed", fr: "\xC9chec de la mise \xE0 jour" });
|
|
6293
6484
|
res.json({ success: false, error, isService });
|
|
6294
6485
|
}
|
|
6295
6486
|
} catch (err) {
|
|
6296
|
-
res.status(500).json({
|
|
6487
|
+
res.status(500).json({
|
|
6488
|
+
error: err instanceof Error ? err.message : serverT({ en: "Update failed to start", fr: "\xC9chec du d\xE9marrage de la mise \xE0 jour" })
|
|
6489
|
+
});
|
|
6297
6490
|
} finally {
|
|
6298
6491
|
updateInProgress = false;
|
|
6299
6492
|
}
|
|
6300
6493
|
});
|
|
6301
6494
|
router.post("/restart", async (req, res) => {
|
|
6302
|
-
if (!await
|
|
6303
|
-
res.status(401).json({ error: "Unauthorized" });
|
|
6304
|
-
return;
|
|
6305
|
-
}
|
|
6495
|
+
if (!await requireAuth(req, res, options)) return;
|
|
6306
6496
|
try {
|
|
6307
6497
|
const child = spawn2("openfox service restart", {
|
|
6308
6498
|
detached: true,
|
|
@@ -6313,7 +6503,9 @@ function createAutoUpdateRoutes(options = {}) {
|
|
|
6313
6503
|
child.unref();
|
|
6314
6504
|
res.json({ success: true });
|
|
6315
6505
|
} catch (err) {
|
|
6316
|
-
res.status(500).json({
|
|
6506
|
+
res.status(500).json({
|
|
6507
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to trigger restart", fr: "\xC9chec du d\xE9clenchement du red\xE9marrage" })
|
|
6508
|
+
});
|
|
6317
6509
|
}
|
|
6318
6510
|
});
|
|
6319
6511
|
return router;
|
|
@@ -6326,13 +6518,19 @@ function createProviderAuthRoutes(config3, providerManager, registry) {
|
|
|
6326
6518
|
function resolveAuthContext(providerId, res) {
|
|
6327
6519
|
const provider = providerManager.getProviders().find((item) => item.id === providerId);
|
|
6328
6520
|
if (!provider) {
|
|
6329
|
-
res.status(404).json({ error: "Provider not found" });
|
|
6521
|
+
res.status(404).json({ error: serverT({ en: "Provider not found", fr: "Fournisseur introuvable" }) });
|
|
6330
6522
|
return void 0;
|
|
6331
6523
|
}
|
|
6332
6524
|
return { provider, adapter: registry.getAuth(provider.authAdapter) };
|
|
6333
6525
|
}
|
|
6334
6526
|
function missingAuthPlugin(provider) {
|
|
6335
|
-
return
|
|
6527
|
+
return serverT(
|
|
6528
|
+
{
|
|
6529
|
+
en: "Missing provider auth plugin: {{adapter}}",
|
|
6530
|
+
fr: "Plugin d\u2019authentification du fournisseur manquant : {{adapter}}"
|
|
6531
|
+
},
|
|
6532
|
+
{ adapter: provider.authAdapter ?? "unknown" }
|
|
6533
|
+
);
|
|
6336
6534
|
}
|
|
6337
6535
|
router.post("/:providerId/login", async (req, res) => {
|
|
6338
6536
|
const context = resolveAuthContext(req.params.providerId, res);
|
|
@@ -6356,7 +6554,12 @@ function createProviderAuthRoutes(config3, providerManager, registry) {
|
|
|
6356
6554
|
});
|
|
6357
6555
|
res.json(challenge);
|
|
6358
6556
|
} catch (error) {
|
|
6359
|
-
res.status(502).json({
|
|
6557
|
+
res.status(502).json({
|
|
6558
|
+
error: error instanceof Error ? error.message : serverT({
|
|
6559
|
+
en: "Unable to start provider login",
|
|
6560
|
+
fr: "Impossible de d\xE9marrer la connexion au fournisseur"
|
|
6561
|
+
})
|
|
6562
|
+
});
|
|
6360
6563
|
}
|
|
6361
6564
|
});
|
|
6362
6565
|
router.get("/:providerId/status", async (req, res) => {
|
|
@@ -6593,15 +6796,15 @@ function createPluginRoutes(options) {
|
|
|
6593
6796
|
router.post("/install", async (req, res) => {
|
|
6594
6797
|
const { githubUrl } = req.body;
|
|
6595
6798
|
if (!githubUrl || typeof githubUrl !== "string") {
|
|
6596
|
-
return res.status(400).json({ error: "githubUrl is required" });
|
|
6799
|
+
return res.status(400).json({ error: serverT({ en: "githubUrl is required", fr: "githubUrl est requis" }) });
|
|
6597
6800
|
}
|
|
6598
6801
|
const parsed = githubUrl.match(/github\.com\/([^/]+)\/([^/]+?)(?:\/|$)/);
|
|
6599
6802
|
if (!parsed) {
|
|
6600
|
-
return res.status(400).json({ error: "Invalid GitHub URL" });
|
|
6803
|
+
return res.status(400).json({ error: serverT({ en: "Invalid GitHub URL", fr: "URL GitHub invalide" }) });
|
|
6601
6804
|
}
|
|
6602
6805
|
const repoName = parsed[2].replace(/\.git$/, "");
|
|
6603
6806
|
if (!/^[a-zA-Z0-9_-]+$/.test(repoName)) {
|
|
6604
|
-
return res.status(400).json({ error: "Invalid repository name" });
|
|
6807
|
+
return res.status(400).json({ error: serverT({ en: "Invalid repository name", fr: "Nom de d\xE9p\xF4t invalide" }) });
|
|
6605
6808
|
}
|
|
6606
6809
|
const pluginsDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins");
|
|
6607
6810
|
const targetDir = join8(pluginsDir, repoName);
|
|
@@ -6609,7 +6812,12 @@ function createPluginRoutes(options) {
|
|
|
6609
6812
|
try {
|
|
6610
6813
|
await execFileP("mkdir", ["-p", pluginsDir], { timeout: 5e3 });
|
|
6611
6814
|
} catch {
|
|
6612
|
-
return res.status(500).json({
|
|
6815
|
+
return res.status(500).json({
|
|
6816
|
+
error: serverT({
|
|
6817
|
+
en: "Failed to create plugins directory",
|
|
6818
|
+
fr: "\xC9chec de la cr\xE9ation du r\xE9pertoire des plugins"
|
|
6819
|
+
})
|
|
6820
|
+
});
|
|
6613
6821
|
}
|
|
6614
6822
|
let gitOk = false;
|
|
6615
6823
|
try {
|
|
@@ -6618,7 +6826,12 @@ function createPluginRoutes(options) {
|
|
|
6618
6826
|
} catch {
|
|
6619
6827
|
}
|
|
6620
6828
|
if (!gitOk) {
|
|
6621
|
-
return res.status(500).json({
|
|
6829
|
+
return res.status(500).json({
|
|
6830
|
+
error: serverT({
|
|
6831
|
+
en: "git is not installed or not found in PATH",
|
|
6832
|
+
fr: "git n\u2019est pas install\xE9 ou introuvable dans le PATH"
|
|
6833
|
+
})
|
|
6834
|
+
});
|
|
6622
6835
|
}
|
|
6623
6836
|
try {
|
|
6624
6837
|
const cloneUrl = githubUrl.replace(/\/$/, "") + ".git";
|
|
@@ -6631,7 +6844,10 @@ function createPluginRoutes(options) {
|
|
|
6631
6844
|
await execFileP("npm", ["install", "--no-audit", "--no-fund"], { cwd: targetDir, timeout: 12e4 });
|
|
6632
6845
|
await execFileP("npm", ["run", "build"], { cwd: targetDir, timeout: 12e4 });
|
|
6633
6846
|
} catch (err) {
|
|
6634
|
-
loadError =
|
|
6847
|
+
loadError = serverT({
|
|
6848
|
+
en: "Failed to install/build plugin dependencies",
|
|
6849
|
+
fr: "\xC9chec de l\u2019installation/du build des d\xE9pendances du plugin"
|
|
6850
|
+
});
|
|
6635
6851
|
logger2.error("Plugin build failed", { repoName, error: String(err) });
|
|
6636
6852
|
}
|
|
6637
6853
|
if (!loadError) {
|
|
@@ -6640,13 +6856,25 @@ function createPluginRoutes(options) {
|
|
|
6640
6856
|
const pluginEntry = manifest.openfox?.plugin;
|
|
6641
6857
|
const apiVersion = manifest.openfox?.apiVersion;
|
|
6642
6858
|
if (!pluginEntry || !manifest.name) {
|
|
6643
|
-
loadError =
|
|
6859
|
+
loadError = serverT({
|
|
6860
|
+
en: "Plugin package.json is missing openfox.plugin or name field",
|
|
6861
|
+
fr: "Le package.json du plugin ne contient pas le champ openfox.plugin ou name"
|
|
6862
|
+
});
|
|
6644
6863
|
} else if (apiVersion !== 1) {
|
|
6645
|
-
loadError =
|
|
6864
|
+
loadError = serverT(
|
|
6865
|
+
{
|
|
6866
|
+
en: "Unsupported plugin API version: {{version}}",
|
|
6867
|
+
fr: "Version d\u2019API de plugin non prise en charge : {{version}}"
|
|
6868
|
+
},
|
|
6869
|
+
{ version: String(apiVersion) }
|
|
6870
|
+
);
|
|
6646
6871
|
} else {
|
|
6647
6872
|
const mod = await import(pathToFileURL2(join8(targetDir, pluginEntry)).href);
|
|
6648
6873
|
if (typeof mod.register !== "function") {
|
|
6649
|
-
loadError =
|
|
6874
|
+
loadError = serverT({
|
|
6875
|
+
en: "Plugin does not export register(registry)",
|
|
6876
|
+
fr: "Le plugin n\u2019exporte pas register(registry)"
|
|
6877
|
+
});
|
|
6650
6878
|
} else {
|
|
6651
6879
|
const diagnostic = {
|
|
6652
6880
|
packageName: manifest.name,
|
|
@@ -6680,14 +6908,14 @@ function createPluginRoutes(options) {
|
|
|
6680
6908
|
}
|
|
6681
6909
|
}
|
|
6682
6910
|
} catch (err) {
|
|
6683
|
-
loadError = err instanceof Error ? err.message : "Failed to load plugin";
|
|
6911
|
+
loadError = err instanceof Error ? err.message : serverT({ en: "Failed to load plugin", fr: "\xC9chec du chargement du plugin" });
|
|
6684
6912
|
logger2.error("Plugin runtime load failed", { repoName, error: loadError });
|
|
6685
6913
|
}
|
|
6686
6914
|
}
|
|
6687
6915
|
res.json({ success: true, loaded, loadError, path: targetDir });
|
|
6688
6916
|
} catch (err) {
|
|
6689
6917
|
await rm2(tmpDir, { recursive: true, force: true });
|
|
6690
|
-
const msg = err instanceof Error ? err.message : "Clone failed";
|
|
6918
|
+
const msg = err instanceof Error ? err.message : serverT({ en: "Clone failed", fr: "\xC9chec du clonage" });
|
|
6691
6919
|
logger2.error("Plugin install failed", { githubUrl, error: msg });
|
|
6692
6920
|
res.status(500).json({ error: msg });
|
|
6693
6921
|
}
|
|
@@ -6719,14 +6947,15 @@ function createPluginRoutes(options) {
|
|
|
6719
6947
|
});
|
|
6720
6948
|
router.get("/:name/open-folder", async (req, res) => {
|
|
6721
6949
|
const name = req.params.name;
|
|
6722
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(name))
|
|
6950
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(name))
|
|
6951
|
+
return res.status(400).json({ error: serverT({ en: "Invalid plugin name", fr: "Nom de plugin invalide" }) });
|
|
6723
6952
|
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
6724
6953
|
await openFolderRoute(targetDir, res);
|
|
6725
6954
|
});
|
|
6726
6955
|
router.delete("/:name", async (req, res) => {
|
|
6727
6956
|
const name = req.params.name;
|
|
6728
6957
|
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
6729
|
-
return res.status(400).json({ error: "Invalid plugin name" });
|
|
6958
|
+
return res.status(400).json({ error: serverT({ en: "Invalid plugin name", fr: "Nom de plugin invalide" }) });
|
|
6730
6959
|
}
|
|
6731
6960
|
const targetDir = join8(getGlobalConfigDir(config3.mode ?? "production"), "plugins", name);
|
|
6732
6961
|
try {
|
|
@@ -6736,7 +6965,9 @@ function createPluginRoutes(options) {
|
|
|
6736
6965
|
}
|
|
6737
6966
|
res.json({ success: true });
|
|
6738
6967
|
} catch (err) {
|
|
6739
|
-
res.status(500).json({
|
|
6968
|
+
res.status(500).json({
|
|
6969
|
+
error: err instanceof Error ? err.message : serverT({ en: "Failed to remove plugin", fr: "\xC9chec de la suppression du plugin" })
|
|
6970
|
+
});
|
|
6740
6971
|
}
|
|
6741
6972
|
});
|
|
6742
6973
|
return router;
|
|
@@ -6749,11 +6980,16 @@ function registerSessionFavoriteRoute(router, sessionManager) {
|
|
|
6749
6980
|
const id = req.params["id"];
|
|
6750
6981
|
const { isFavorite } = req.body;
|
|
6751
6982
|
if (typeof isFavorite !== "boolean") {
|
|
6752
|
-
return res.status(400).json({
|
|
6983
|
+
return res.status(400).json({
|
|
6984
|
+
error: serverT({
|
|
6985
|
+
en: "isFavorite is required and must be a boolean",
|
|
6986
|
+
fr: "isFavorite est requis et doit \xEAtre un bool\xE9en"
|
|
6987
|
+
})
|
|
6988
|
+
});
|
|
6753
6989
|
}
|
|
6754
6990
|
const session = sessionManager.getSession(id);
|
|
6755
6991
|
if (!session) {
|
|
6756
|
-
return res.status(404).json({ error: "Session not found" });
|
|
6992
|
+
return res.status(404).json({ error: serverT({ en: "Session not found", fr: "Session introuvable" }) });
|
|
6757
6993
|
}
|
|
6758
6994
|
toggleFavorite(id, isFavorite);
|
|
6759
6995
|
res.json({ success: true });
|
|
@@ -6810,7 +7046,7 @@ function detectWsl() {
|
|
|
6810
7046
|
// src/server/index.ts
|
|
6811
7047
|
var __dirname3 = dirname7(fileURLToPath6(import.meta.url));
|
|
6812
7048
|
async function announceContextDrift(sessionManager, sessionIds) {
|
|
6813
|
-
const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-
|
|
7049
|
+
const { injectContextDriftRemindersForSessions } = await import("./dynamic-context-LKC6JYLQ.js");
|
|
6814
7050
|
await injectContextDriftRemindersForSessions(sessionManager, sessionIds);
|
|
6815
7051
|
}
|
|
6816
7052
|
async function createServerHandle(config3) {
|
|
@@ -6917,7 +7153,7 @@ async function createServerHandle(config3) {
|
|
|
6917
7153
|
toolRegistry = createToolRegistry();
|
|
6918
7154
|
logger.info("MCP tools registered", { count: mcpTools.length });
|
|
6919
7155
|
}
|
|
6920
|
-
const { signalMcpReady } = await import("./server-
|
|
7156
|
+
const { signalMcpReady } = await import("./server-ZHEB7XS2.js");
|
|
6921
7157
|
signalMcpReady();
|
|
6922
7158
|
});
|
|
6923
7159
|
const app = express();
|
|
@@ -7028,9 +7264,9 @@ async function createServerHandle(config3) {
|
|
|
7028
7264
|
if (!name || !workdir) {
|
|
7029
7265
|
return res.status(400).json({ error: "name and workdir are required" });
|
|
7030
7266
|
}
|
|
7031
|
-
const {
|
|
7267
|
+
const { createProjectDirectory } = await import("./project-creator-T3A4H3YV.js");
|
|
7032
7268
|
try {
|
|
7033
|
-
const project = await
|
|
7269
|
+
const project = await createProjectDirectory(name, workdir);
|
|
7034
7270
|
res.status(201).json({ project });
|
|
7035
7271
|
} catch (err) {
|
|
7036
7272
|
const eaccError = err;
|
|
@@ -7132,9 +7368,9 @@ async function createServerHandle(config3) {
|
|
|
7132
7368
|
const sessionFavoriteRouter = express.Router();
|
|
7133
7369
|
registerSessionFavoriteRoute(sessionFavoriteRouter, sessionManager);
|
|
7134
7370
|
app.use("/api", sessionFavoriteRouter);
|
|
7135
|
-
const { createTasksService } = await import("./service-
|
|
7136
|
-
const { registerTaskRoutes } = await import("./tasks-
|
|
7137
|
-
const { setTasksService } = await import("./tools-
|
|
7371
|
+
const { createTasksService } = await import("./service-XIUNS5XV.js");
|
|
7372
|
+
const { registerTaskRoutes } = await import("./tasks-3JJWJJ3X.js");
|
|
7373
|
+
const { setTasksService } = await import("./tools-E63MOJBO.js");
|
|
7138
7374
|
const tasksService = createTasksService({
|
|
7139
7375
|
sessionManager,
|
|
7140
7376
|
config: config3,
|
|
@@ -7166,7 +7402,7 @@ async function createServerHandle(config3) {
|
|
|
7166
7402
|
}
|
|
7167
7403
|
try {
|
|
7168
7404
|
await checkoutBranch(project.workdir, branch);
|
|
7169
|
-
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-
|
|
7405
|
+
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
|
|
7170
7406
|
const allSessions = sessionManager.listSessions();
|
|
7171
7407
|
for (const s of allSessions) {
|
|
7172
7408
|
if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
|
|
@@ -7202,7 +7438,7 @@ async function createServerHandle(config3) {
|
|
|
7202
7438
|
);
|
|
7203
7439
|
}
|
|
7204
7440
|
await createBranch(project.workdir, name, sb);
|
|
7205
|
-
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-
|
|
7441
|
+
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
|
|
7206
7442
|
const allSessions = sessionManager.listSessions();
|
|
7207
7443
|
for (const s of allSessions) {
|
|
7208
7444
|
if (sessionManager.getEffectiveWorkdir(s.id) === project.workdir) {
|
|
@@ -7234,7 +7470,7 @@ async function createServerHandle(config3) {
|
|
|
7234
7470
|
if (!branch || typeof branch !== "string") return res.status(400).json({ error: "branch is required" });
|
|
7235
7471
|
const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
|
|
7236
7472
|
const { checkoutBranch, validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
|
|
7237
|
-
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-
|
|
7473
|
+
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
|
|
7238
7474
|
try {
|
|
7239
7475
|
await validateRef2(effectiveWorkdir, branch);
|
|
7240
7476
|
await checkoutBranch(effectiveWorkdir, branch);
|
|
@@ -7277,7 +7513,7 @@ All file and git operations should use this branch.
|
|
|
7277
7513
|
if (!name || typeof name !== "string") return res.status(400).json({ error: "name is required" });
|
|
7278
7514
|
const effectiveWorkdir = sessionManager.getEffectiveWorkdir(req.params.id);
|
|
7279
7515
|
const { validateRef: validateRef2 } = await import("./workspace-LM646OHC.js");
|
|
7280
|
-
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-
|
|
7516
|
+
const { updateSessionBranch: updateSessionBranch2 } = await import("./sessions-AOK3AGHY.js");
|
|
7281
7517
|
try {
|
|
7282
7518
|
await validateRef2(effectiveWorkdir, name);
|
|
7283
7519
|
if (sourceBranch) {
|
|
@@ -7332,8 +7568,8 @@ All file and git operations should use this branch.
|
|
|
7332
7568
|
res.json({ workspaces: workspacesList });
|
|
7333
7569
|
});
|
|
7334
7570
|
app.get("/api/sessions", async (req, res) => {
|
|
7335
|
-
const { getRecentUserPromptsForSession } = await import("./events-
|
|
7336
|
-
const { getPendingConfirmationsBySession: getPendingConfirmationsBySession2 } = await import("./path-security-
|
|
7571
|
+
const { getRecentUserPromptsForSession } = await import("./events-335XAKFK.js");
|
|
7572
|
+
const { getPendingConfirmationsBySession: getPendingConfirmationsBySession2 } = await import("./path-security-4LROI7F4.js");
|
|
7337
7573
|
const projectId = req.query["projectId"];
|
|
7338
7574
|
const rawLimit = req.query["limit"];
|
|
7339
7575
|
const offset = parseInt(req.query["offset"]) || 0;
|
|
@@ -7369,6 +7605,31 @@ All file and git operations should use this branch.
|
|
|
7369
7605
|
app.get("/api/sessions/home", (_req, res) => {
|
|
7370
7606
|
res.json({ sessions: sessionManager.listHomeSessions() });
|
|
7371
7607
|
});
|
|
7608
|
+
function buildSessionCreatedMessage(session) {
|
|
7609
|
+
return {
|
|
7610
|
+
type: "session.created",
|
|
7611
|
+
sessionId: session.id,
|
|
7612
|
+
payload: {
|
|
7613
|
+
session: {
|
|
7614
|
+
id: session.id,
|
|
7615
|
+
projectId: session.projectId,
|
|
7616
|
+
title: session.metadata.title,
|
|
7617
|
+
workdir: session.workdir,
|
|
7618
|
+
workspace: session.workspace,
|
|
7619
|
+
mode: session.mode,
|
|
7620
|
+
phase: session.phase,
|
|
7621
|
+
isRunning: session.isRunning,
|
|
7622
|
+
providerId: session.providerId,
|
|
7623
|
+
providerModel: session.providerModel,
|
|
7624
|
+
createdAt: session.createdAt,
|
|
7625
|
+
updatedAt: session.updatedAt,
|
|
7626
|
+
criteriaCount: session.criteria.length,
|
|
7627
|
+
criteriaCompleted: session.criteria.filter((c) => c.status.type === "passed").length,
|
|
7628
|
+
messageCount: session.messageCount ?? session.messages.length
|
|
7629
|
+
}
|
|
7630
|
+
}
|
|
7631
|
+
};
|
|
7632
|
+
}
|
|
7372
7633
|
app.post("/api/sessions", async (req, res) => {
|
|
7373
7634
|
const { projectId, title } = req.body;
|
|
7374
7635
|
if (!projectId) {
|
|
@@ -7388,34 +7649,12 @@ All file and git operations should use this branch.
|
|
|
7388
7649
|
disabledServers = mcpManager.getAllServers().filter((s) => s.config.disabled).map((s) => s.name);
|
|
7389
7650
|
}
|
|
7390
7651
|
if (disabledServers.length > 0) {
|
|
7391
|
-
const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-
|
|
7652
|
+
const { setSessionDisabledServers: setSessionDisabledServers2 } = await import("./session-overrides-LYW5PJ3R.js");
|
|
7392
7653
|
setSessionDisabledServers2(session.id, disabledServers);
|
|
7393
7654
|
}
|
|
7394
7655
|
} catch {
|
|
7395
7656
|
}
|
|
7396
|
-
wssExports.broadcastForProject(projectId, session.id,
|
|
7397
|
-
type: "session.created",
|
|
7398
|
-
sessionId: session.id,
|
|
7399
|
-
payload: {
|
|
7400
|
-
session: {
|
|
7401
|
-
id: session.id,
|
|
7402
|
-
projectId: session.projectId,
|
|
7403
|
-
title: session.metadata.title,
|
|
7404
|
-
workdir: session.workdir,
|
|
7405
|
-
workspace: session.workspace,
|
|
7406
|
-
mode: session.mode,
|
|
7407
|
-
phase: session.phase,
|
|
7408
|
-
isRunning: session.isRunning,
|
|
7409
|
-
providerId: session.providerId,
|
|
7410
|
-
providerModel: session.providerModel,
|
|
7411
|
-
createdAt: session.createdAt,
|
|
7412
|
-
updatedAt: session.updatedAt,
|
|
7413
|
-
criteriaCount: session.criteria.length,
|
|
7414
|
-
criteriaCompleted: session.criteria.filter((c) => c.status.type === "passed").length,
|
|
7415
|
-
messageCount: session.messageCount ?? session.messages.length
|
|
7416
|
-
}
|
|
7417
|
-
}
|
|
7418
|
-
});
|
|
7657
|
+
wssExports.broadcastForProject(projectId, session.id, buildSessionCreatedMessage(session));
|
|
7419
7658
|
res.status(201).json({ session: toClientSession(session) });
|
|
7420
7659
|
});
|
|
7421
7660
|
app.post("/api/sessions/:id/switch-workspace", async (req, res) => {
|
|
@@ -7461,10 +7700,10 @@ All file and git operations should use this branch.
|
|
|
7461
7700
|
}
|
|
7462
7701
|
});
|
|
7463
7702
|
app.get("/api/sessions/:id", async (req, res) => {
|
|
7464
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-
|
|
7465
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-
|
|
7466
|
-
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-
|
|
7467
|
-
const { getMaxVisibleItems } = await import("./settings-
|
|
7703
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-335XAKFK.js");
|
|
7704
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
|
|
7705
|
+
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
|
|
7706
|
+
const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
|
|
7468
7707
|
const session = sessionManager.getSession(req.params.id);
|
|
7469
7708
|
if (!session) {
|
|
7470
7709
|
return res.status(404).json({ error: "Session not found" });
|
|
@@ -7492,9 +7731,9 @@ All file and git operations should use this branch.
|
|
|
7492
7731
|
});
|
|
7493
7732
|
app.get("/api/sessions/:id/status", async (req, res) => {
|
|
7494
7733
|
const { projectSessionStatus: projectSessionStatus2 } = await import("./session-status-UFO5IFI7.js");
|
|
7495
|
-
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-
|
|
7496
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-
|
|
7497
|
-
const { foldPendingConfirmations } = await import("./folding-
|
|
7734
|
+
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
|
|
7735
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEventsWithSnapshot2 } = await import("./events-335XAKFK.js");
|
|
7736
|
+
const { foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
|
|
7498
7737
|
const sessionId = req.params["id"];
|
|
7499
7738
|
if (!sessionId) {
|
|
7500
7739
|
return res.status(400).json({ error: "Session id is required" });
|
|
@@ -7524,8 +7763,8 @@ All file and git operations should use this branch.
|
|
|
7524
7763
|
if (!session) {
|
|
7525
7764
|
return res.status(404).json({ error: "Session not found" });
|
|
7526
7765
|
}
|
|
7527
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
7528
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
7766
|
+
const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
|
|
7767
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
|
|
7529
7768
|
sessionManager.clearMessageQueue(sessionId);
|
|
7530
7769
|
stopSessionExecution(sessionId, sessionManager);
|
|
7531
7770
|
abortSession(sessionId);
|
|
@@ -7554,9 +7793,9 @@ All file and git operations should use this branch.
|
|
|
7554
7793
|
res.json({ success: true });
|
|
7555
7794
|
});
|
|
7556
7795
|
app.post("/api/sessions/:id/provider", async (req, res) => {
|
|
7557
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-
|
|
7558
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
7559
|
-
const { getMaxVisibleItems } = await import("./settings-
|
|
7796
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
|
|
7797
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
|
|
7798
|
+
const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
|
|
7560
7799
|
const sessionId = req.params.id;
|
|
7561
7800
|
const session = sessionManager.getSession(sessionId);
|
|
7562
7801
|
if (!session) {
|
|
@@ -7584,9 +7823,9 @@ All file and git operations should use this branch.
|
|
|
7584
7823
|
res.json({ session: toClientSession(updatedSession), messages, hiddenCount, contextState });
|
|
7585
7824
|
});
|
|
7586
7825
|
app.delete("/api/sessions/:id/provider", async (req, res) => {
|
|
7587
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-
|
|
7588
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
7589
|
-
const { getMaxVisibleItems } = await import("./settings-
|
|
7826
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
|
|
7827
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
|
|
7828
|
+
const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
|
|
7590
7829
|
const sessionId = req.params.id;
|
|
7591
7830
|
const session = sessionManager.getSession(sessionId);
|
|
7592
7831
|
if (!session) {
|
|
@@ -7716,9 +7955,9 @@ All file and git operations should use this branch.
|
|
|
7716
7955
|
res.json({ success: true });
|
|
7717
7956
|
});
|
|
7718
7957
|
app.put("/api/sessions/:id/mode", async (req, res) => {
|
|
7719
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-
|
|
7720
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
7721
|
-
const { getMaxVisibleItems } = await import("./settings-
|
|
7958
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEv } = await import("./events-335XAKFK.js");
|
|
7959
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
|
|
7960
|
+
const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
|
|
7722
7961
|
const sessionId = req.params.id;
|
|
7723
7962
|
const session = sessionManager.getSession(sessionId);
|
|
7724
7963
|
if (!session) {
|
|
@@ -7778,7 +8017,7 @@ All file and git operations should use this branch.
|
|
|
7778
8017
|
setSessionDisabledServers(sessionId, disabledServers);
|
|
7779
8018
|
const messages = session.messages ?? [];
|
|
7780
8019
|
if (messages.length === 0) {
|
|
7781
|
-
const { applyDynamicContext } = await import("./dynamic-context-
|
|
8020
|
+
const { applyDynamicContext } = await import("./dynamic-context-LKC6JYLQ.js");
|
|
7782
8021
|
const modelName = session.providerModel ?? providerManager.getCurrentModel();
|
|
7783
8022
|
await applyDynamicContext(sessionManager, sessionId, modelName);
|
|
7784
8023
|
} else {
|
|
@@ -7812,7 +8051,7 @@ All file and git operations should use this branch.
|
|
|
7812
8051
|
if (alwaysAllow !== void 0 && typeof alwaysAllow !== "boolean") {
|
|
7813
8052
|
return res.status(400).json({ error: "alwaysAllow must be a boolean if provided" });
|
|
7814
8053
|
}
|
|
7815
|
-
const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-
|
|
8054
|
+
const { providePathConfirmation: providePathConfirmation2, getConfirmationSessionId } = await import("./tools-E63MOJBO.js");
|
|
7816
8055
|
const pendingSessionId = getConfirmationSessionId(callId);
|
|
7817
8056
|
if (!pendingSessionId) {
|
|
7818
8057
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
@@ -7824,11 +8063,11 @@ All file and git operations should use this branch.
|
|
|
7824
8063
|
if (!result.found) {
|
|
7825
8064
|
return res.status(404).json({ error: "No pending path confirmation with that ID" });
|
|
7826
8065
|
}
|
|
7827
|
-
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-
|
|
7828
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-
|
|
7829
|
-
const { createSessionStateMessage } = await import("./protocol-
|
|
7830
|
-
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-
|
|
7831
|
-
const { getMaxVisibleItems } = await import("./settings-
|
|
8066
|
+
const { getEventStore: getEventStore2, combineEventsWithSnapshot: combineEvents } = await import("./events-335XAKFK.js");
|
|
8067
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2, foldPendingConfirmations } = await import("./folding-H7JTX6KI.js");
|
|
8068
|
+
const { createSessionStateMessage } = await import("./protocol-XO4ZROAU.js");
|
|
8069
|
+
const { getPendingQuestionsForSession: getPendingQuestionsForSession2 } = await import("./tools-E63MOJBO.js");
|
|
8070
|
+
const { getMaxVisibleItems } = await import("./settings-ZJPM6PQV.js");
|
|
7832
8071
|
const eventStore = getEventStore2();
|
|
7833
8072
|
const { snapshot, events: eventsSinceSnapshot } = eventStore.getEventsSinceSnapshot(sessionId);
|
|
7834
8073
|
const events = combineEvents(sessionId, snapshot, eventsSinceSnapshot);
|
|
@@ -7865,7 +8104,7 @@ All file and git operations should use this branch.
|
|
|
7865
8104
|
if (!skip && typeof answer !== "string") {
|
|
7866
8105
|
return res.status(400).json({ error: "answer is required when not skipping" });
|
|
7867
8106
|
}
|
|
7868
|
-
const { provideAnswer: provideAnswer2 } = await import("./tools-
|
|
8107
|
+
const { provideAnswer: provideAnswer2 } = await import("./tools-E63MOJBO.js");
|
|
7869
8108
|
const found = provideAnswer2(callId, answer ?? "", skip ?? false);
|
|
7870
8109
|
if (!found) {
|
|
7871
8110
|
return res.status(404).json({ error: "No pending question with that ID" });
|
|
@@ -7898,7 +8137,7 @@ All file and git operations should use this branch.
|
|
|
7898
8137
|
if (!session) {
|
|
7899
8138
|
return res.status(404).json({ error: "Session not found" });
|
|
7900
8139
|
}
|
|
7901
|
-
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-
|
|
8140
|
+
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
|
|
7902
8141
|
if (getSetting2(SETTINGS_KEYS.CACHE_WARMING) !== "true") {
|
|
7903
8142
|
return res.json({ success: false, reason: "disabled" });
|
|
7904
8143
|
}
|
|
@@ -7931,7 +8170,7 @@ All file and git operations should use this branch.
|
|
|
7931
8170
|
backend: activeProvider?.backend ?? llmClient.getBackend(),
|
|
7932
8171
|
model: llmClient.getModel()
|
|
7933
8172
|
};
|
|
7934
|
-
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-
|
|
8173
|
+
const { runAgentTurn, TurnMetrics } = await import("./orchestrator-JGJWTRO5.js");
|
|
7935
8174
|
runAgentTurn(
|
|
7936
8175
|
{
|
|
7937
8176
|
sessionManager,
|
|
@@ -7969,15 +8208,15 @@ All file and git operations should use this branch.
|
|
|
7969
8208
|
if (!session) {
|
|
7970
8209
|
return res.status(404).json({ error: "Session not found" });
|
|
7971
8210
|
}
|
|
7972
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
7973
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
8211
|
+
const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
|
|
8212
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
|
|
7974
8213
|
const queuedMessages = sessionManager.getQueueState(sessionId);
|
|
7975
8214
|
sessionManager.clearMessageQueue(sessionId);
|
|
7976
8215
|
stopSessionExecution(sessionId, sessionManager);
|
|
7977
8216
|
abortSession(sessionId);
|
|
7978
8217
|
cancelQuestionsForSession(sessionId, "Session stopped by user");
|
|
7979
8218
|
cancelPathConfirmationsForSession(sessionId, "Session stopped by user");
|
|
7980
|
-
const eventStore = (await import("./events-
|
|
8219
|
+
const eventStore = (await import("./events-335XAKFK.js")).getEventStore();
|
|
7981
8220
|
eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
|
|
7982
8221
|
res.json({ success: true, queuedMessages });
|
|
7983
8222
|
});
|
|
@@ -7991,7 +8230,7 @@ All file and git operations should use this branch.
|
|
|
7991
8230
|
if (typeof messageIndex !== "number" || messageIndex < 0) {
|
|
7992
8231
|
return res.status(400).json({ error: "messageIndex must be a non-negative number" });
|
|
7993
8232
|
}
|
|
7994
|
-
const { truncateSessionMessages } = await import("./events-
|
|
8233
|
+
const { truncateSessionMessages } = await import("./events-335XAKFK.js");
|
|
7995
8234
|
truncateSessionMessages(sessionId, messageIndex);
|
|
7996
8235
|
res.json({ success: true });
|
|
7997
8236
|
});
|
|
@@ -8011,8 +8250,8 @@ All file and git operations should use this branch.
|
|
|
8011
8250
|
if (attachments !== void 0 && !Array.isArray(attachments)) {
|
|
8012
8251
|
return res.status(400).json({ error: "attachments must be an array if provided" });
|
|
8013
8252
|
}
|
|
8014
|
-
const { getEventStore: getEventStore2 } = await import("./events-
|
|
8015
|
-
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-
|
|
8253
|
+
const { getEventStore: getEventStore2 } = await import("./events-335XAKFK.js");
|
|
8254
|
+
const { buildMessagesFromStoredEvents: buildMessagesFromStoredEvents2 } = await import("./folding-H7JTX6KI.js");
|
|
8016
8255
|
const eventStore = getEventStore2();
|
|
8017
8256
|
const events = eventStore.getEvents(sessionId);
|
|
8018
8257
|
const { messages } = buildMessagesFromStoredEvents2(events);
|
|
@@ -8024,7 +8263,7 @@ All file and git operations should use this branch.
|
|
|
8024
8263
|
if (msg.role !== "user" || msg.isSystemGenerated) {
|
|
8025
8264
|
return res.status(400).json({ error: "Can only replay user messages" });
|
|
8026
8265
|
}
|
|
8027
|
-
const { truncateSessionMessages } = await import("./events-
|
|
8266
|
+
const { truncateSessionMessages } = await import("./events-335XAKFK.js");
|
|
8028
8267
|
truncateSessionMessages(sessionId, msgIndex - 1);
|
|
8029
8268
|
sessionManager.queueMessage(
|
|
8030
8269
|
sessionId,
|
|
@@ -8059,6 +8298,43 @@ All file and git operations should use this branch.
|
|
|
8059
8298
|
return res.status(500).json({ error: message });
|
|
8060
8299
|
}
|
|
8061
8300
|
});
|
|
8301
|
+
app.get("/api/sessions/:id/export", async (req, res) => {
|
|
8302
|
+
const sessionId = req.params.id;
|
|
8303
|
+
const session = sessionManager.getSession(sessionId);
|
|
8304
|
+
if (!session) {
|
|
8305
|
+
return res.status(404).json({ error: "Session not found" });
|
|
8306
|
+
}
|
|
8307
|
+
try {
|
|
8308
|
+
const { buildSessionExport } = await import("./export-import-3WMRLO4A.js");
|
|
8309
|
+
const payload = buildSessionExport(sessionManager, sessionId);
|
|
8310
|
+
const filename = `${(payload.session.title ?? "session").replace(/[^a-zA-Z0-9-_]/g, "_")}.openfox-session.json`;
|
|
8311
|
+
res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
|
|
8312
|
+
return res.json(payload);
|
|
8313
|
+
} catch (err) {
|
|
8314
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8315
|
+
return res.status(500).json({ error: message });
|
|
8316
|
+
}
|
|
8317
|
+
});
|
|
8318
|
+
app.post("/api/sessions/import", async (req, res) => {
|
|
8319
|
+
const { projectId, payload } = req.body;
|
|
8320
|
+
if (typeof projectId !== "string" || !projectId) {
|
|
8321
|
+
return res.status(400).json({ error: "projectId is required" });
|
|
8322
|
+
}
|
|
8323
|
+
if (payload === void 0 || payload === null) {
|
|
8324
|
+
return res.status(400).json({ error: "payload is required" });
|
|
8325
|
+
}
|
|
8326
|
+
try {
|
|
8327
|
+
const newSession = await sessionManager.importSession(projectId, payload);
|
|
8328
|
+
wssExports.broadcastForProject(projectId, newSession.id, buildSessionCreatedMessage(newSession));
|
|
8329
|
+
return res.status(201).json({ session: toClientSession(newSession) });
|
|
8330
|
+
} catch (err) {
|
|
8331
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8332
|
+
if (message.includes("Project not found")) {
|
|
8333
|
+
return res.status(404).json({ error: message });
|
|
8334
|
+
}
|
|
8335
|
+
return res.status(400).json({ error: message });
|
|
8336
|
+
}
|
|
8337
|
+
});
|
|
8062
8338
|
app.post("/api/sessions/:id/chat", async (req, res) => {
|
|
8063
8339
|
const sessionId = req.params.id;
|
|
8064
8340
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -8086,7 +8362,7 @@ All file and git operations should use this branch.
|
|
|
8086
8362
|
res.json({ accepted: true });
|
|
8087
8363
|
});
|
|
8088
8364
|
app.get("/api/settings", async (req, res) => {
|
|
8089
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
8365
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
|
|
8090
8366
|
const keysParam = req.query["keys"];
|
|
8091
8367
|
if (!keysParam) {
|
|
8092
8368
|
return res.status(400).json({ error: "keys query parameter is required" });
|
|
@@ -8099,19 +8375,19 @@ All file and git operations should use this branch.
|
|
|
8099
8375
|
res.json(result);
|
|
8100
8376
|
});
|
|
8101
8377
|
app.get("/api/settings/:key", async (req, res) => {
|
|
8102
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
8378
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
|
|
8103
8379
|
const key = req.params.key;
|
|
8104
8380
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
8105
8381
|
res.json({ key, value });
|
|
8106
8382
|
});
|
|
8107
8383
|
app.get("/api/settings/:key", async (req, res) => {
|
|
8108
|
-
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-
|
|
8384
|
+
const { getSetting: getSetting2, SETTINGS_DEFAULTS } = await import("./settings-ZJPM6PQV.js");
|
|
8109
8385
|
const key = req.params.key;
|
|
8110
8386
|
const value = getSetting2(key) ?? SETTINGS_DEFAULTS[key] ?? null;
|
|
8111
8387
|
res.json({ key, value });
|
|
8112
8388
|
});
|
|
8113
8389
|
app.put("/api/settings/:key", async (req, res) => {
|
|
8114
|
-
const { setSetting: setSetting2 } = await import("./settings-
|
|
8390
|
+
const { setSetting: setSetting2 } = await import("./settings-ZJPM6PQV.js");
|
|
8115
8391
|
const key = req.params.key;
|
|
8116
8392
|
const { value } = req.body;
|
|
8117
8393
|
if (value === void 0) {
|
|
@@ -8138,7 +8414,7 @@ All file and git operations should use this branch.
|
|
|
8138
8414
|
}
|
|
8139
8415
|
});
|
|
8140
8416
|
app.get("/api/tools/shells", async (_req, res) => {
|
|
8141
|
-
const { listAvailableShells } = await import("./platform-
|
|
8417
|
+
const { listAvailableShells } = await import("./platform-XPMZKAUB.js");
|
|
8142
8418
|
res.json({ shells: listAvailableShells() });
|
|
8143
8419
|
});
|
|
8144
8420
|
app.get("/api/config", async (_req, res) => {
|
|
@@ -8175,7 +8451,8 @@ All file and git operations should use this branch.
|
|
|
8175
8451
|
activeProviderId: providerManager.getActiveProviderId(),
|
|
8176
8452
|
defaultModelSelection: config3.defaultModelSelection,
|
|
8177
8453
|
visionFallback,
|
|
8178
|
-
platform: platformInfo
|
|
8454
|
+
platform: platformInfo,
|
|
8455
|
+
locale: (await import("./settings-ZJPM6PQV.js")).getSetting("display.locale") ?? "automatic"
|
|
8179
8456
|
});
|
|
8180
8457
|
});
|
|
8181
8458
|
app.post("/api/model/refresh", async (_req, res) => {
|
|
@@ -8231,7 +8508,7 @@ All file and git operations should use this branch.
|
|
|
8231
8508
|
}));
|
|
8232
8509
|
}
|
|
8233
8510
|
app.post("/api/proxy/test", async (_req, res) => {
|
|
8234
|
-
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-
|
|
8511
|
+
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
|
|
8235
8512
|
const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
|
|
8236
8513
|
if (!proxyUrl) {
|
|
8237
8514
|
return res.status(400).json({ success: false, error: "No proxy URL configured" });
|
|
@@ -8323,7 +8600,7 @@ All file and git operations should use this branch.
|
|
|
8323
8600
|
}
|
|
8324
8601
|
});
|
|
8325
8602
|
app.post("/api/proxy/test", async (_req, res) => {
|
|
8326
|
-
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-
|
|
8603
|
+
const { getSetting: getSetting2, SETTINGS_KEYS } = await import("./settings-ZJPM6PQV.js");
|
|
8327
8604
|
const proxyUrl = getSetting2(SETTINGS_KEYS.PROXY_URL);
|
|
8328
8605
|
if (!proxyUrl) {
|
|
8329
8606
|
return res.status(400).json({ success: false, error: "No proxy URL configured" });
|
|
@@ -8350,7 +8627,7 @@ All file and git operations should use this branch.
|
|
|
8350
8627
|
const backend = req.query["backend"];
|
|
8351
8628
|
if (!url) return res.status(400).json({ error: "url is required" });
|
|
8352
8629
|
try {
|
|
8353
|
-
const { fetchModelsWithContext } = await import("./provider-manager-
|
|
8630
|
+
const { fetchModelsWithContext } = await import("./provider-manager-2KKZ37XJ.js");
|
|
8354
8631
|
const { getModelProfile: getModelProfile2 } = await import("./profiles-EBCVFYG7.js");
|
|
8355
8632
|
const { getCatalogEntry } = await import("./model-catalog-2PCKTYGW.js");
|
|
8356
8633
|
const models = await fetchModelsWithContext(
|
|
@@ -8425,7 +8702,7 @@ All file and git operations should use this branch.
|
|
|
8425
8702
|
const { getModelProfile: getModelProfile2 } = await import("./profiles-EBCVFYG7.js");
|
|
8426
8703
|
const { getBackendCapabilities } = await import("./backend-NDBY3DAQ.js");
|
|
8427
8704
|
const { buildNonStreamingCreateParams } = await import("./client-pure-FLKP6PTI.js");
|
|
8428
|
-
const { OpenAIHttpClient } = await import("./http-client-
|
|
8705
|
+
const { OpenAIHttpClient } = await import("./http-client-A445WYZU.js");
|
|
8429
8706
|
const { ensureVersionPrefix } = await import("./url-utils-C5BM7NF7.js");
|
|
8430
8707
|
const profile = getModelProfile2(model);
|
|
8431
8708
|
const capabilities = getBackendCapabilities(backend || "unknown");
|
|
@@ -8842,7 +9119,7 @@ All file and git operations should use this branch.
|
|
|
8842
9119
|
});
|
|
8843
9120
|
async function rebuildMcpTools() {
|
|
8844
9121
|
const { createMcpTools: createMcpTools2 } = await import("./tool-adapter-FJAFLDZA.js");
|
|
8845
|
-
const { setMcpTools: setMcpTools2 } = await import("./tools-
|
|
9122
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-E63MOJBO.js");
|
|
8846
9123
|
const mcpTools = createMcpTools2(mcpManager);
|
|
8847
9124
|
setMcpTools2(mcpTools);
|
|
8848
9125
|
toolRegistry = createToolRegistry();
|
|
@@ -9272,13 +9549,13 @@ All file and git operations should use this branch.
|
|
|
9272
9549
|
})
|
|
9273
9550
|
);
|
|
9274
9551
|
app.get("/api/sessions/:id/background-processes", async (req, res) => {
|
|
9275
|
-
const { getSessionProcesses } = await import("./manager-
|
|
9552
|
+
const { getSessionProcesses } = await import("./manager-ZACEUL5P.js");
|
|
9276
9553
|
const sessionId = req.params.id;
|
|
9277
9554
|
const processes = getSessionProcesses(sessionId);
|
|
9278
9555
|
res.json({ processes });
|
|
9279
9556
|
});
|
|
9280
9557
|
app.post("/api/sessions/:id/background-process/:processId/stop", async (req, res) => {
|
|
9281
|
-
const { stopProcess } = await import("./manager-
|
|
9558
|
+
const { stopProcess } = await import("./manager-ZACEUL5P.js");
|
|
9282
9559
|
const sessionId = req.params.id;
|
|
9283
9560
|
const processId = req.params.processId;
|
|
9284
9561
|
const session = sessionManager.getSession(sessionId);
|
|
@@ -9418,7 +9695,7 @@ All file and git operations should use this branch.
|
|
|
9418
9695
|
);
|
|
9419
9696
|
const wss = wssExports.wss;
|
|
9420
9697
|
deferTasksBroadcast = (projectId, payload) => wssExports.broadcastForProject(projectId, "", { type: "tasks.update", payload });
|
|
9421
|
-
const { launchWorkflowRun, abortRunnerRun } = await import("./launch-
|
|
9698
|
+
const { launchWorkflowRun, abortRunnerRun } = await import("./launch-GJ7EHQRI.js");
|
|
9422
9699
|
deferTasksLaunchWorkflow = (sessionId, launch) => {
|
|
9423
9700
|
const effective = sessionManager.resolveEffectiveProviderModel(sessionId);
|
|
9424
9701
|
let llmClient = getLLMClient();
|
|
@@ -9463,7 +9740,7 @@ All file and git operations should use this branch.
|
|
|
9463
9740
|
const state = sessionManager.getContextState(sessionId);
|
|
9464
9741
|
wssExports.broadcastForSession(sessionId, createContextStateMessage(state));
|
|
9465
9742
|
});
|
|
9466
|
-
const { QueueProcessor } = await import("./processor-
|
|
9743
|
+
const { QueueProcessor } = await import("./processor-MSQP63ML.js");
|
|
9467
9744
|
const queueProcessor = new QueueProcessor({
|
|
9468
9745
|
sessionManager,
|
|
9469
9746
|
providerManager,
|
|
@@ -9488,8 +9765,8 @@ All file and git operations should use this branch.
|
|
|
9488
9765
|
sessionManager,
|
|
9489
9766
|
listProjects: () => listProjects(),
|
|
9490
9767
|
createProject: async (name, workdir) => {
|
|
9491
|
-
const {
|
|
9492
|
-
return
|
|
9768
|
+
const { createProjectDirectory } = await import("./project-creator-T3A4H3YV.js");
|
|
9769
|
+
return createProjectDirectory(name, workdir);
|
|
9493
9770
|
},
|
|
9494
9771
|
deleteProject: (projectId) => {
|
|
9495
9772
|
const project = getProject(projectId);
|
|
@@ -9505,8 +9782,8 @@ All file and git operations should use this branch.
|
|
|
9505
9782
|
launchWorkflow: (sessionId, launch) => deferTasksLaunchWorkflow(sessionId, launch),
|
|
9506
9783
|
stopSession: (sessionId) => {
|
|
9507
9784
|
void (async () => {
|
|
9508
|
-
const { stopSessionExecution } = await import("./chat-handler-
|
|
9509
|
-
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-
|
|
9785
|
+
const { stopSessionExecution } = await import("./chat-handler-WGDFMOOD.js");
|
|
9786
|
+
const { cancelQuestionsForSession, cancelPathConfirmationsForSession } = await import("./tools-E63MOJBO.js");
|
|
9510
9787
|
sessionManager.clearMessageQueue(sessionId);
|
|
9511
9788
|
stopSessionExecution(sessionId, sessionManager);
|
|
9512
9789
|
abortSession(sessionId);
|
|
@@ -9627,4 +9904,4 @@ export {
|
|
|
9627
9904
|
createServerHandle,
|
|
9628
9905
|
createServer
|
|
9629
9906
|
};
|
|
9630
|
-
//# sourceMappingURL=chunk-
|
|
9907
|
+
//# sourceMappingURL=chunk-BIZFY3QP.js.map
|