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
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
getGateConfig,
|
|
8
8
|
isTaskConflictError,
|
|
9
|
-
isTaskGateError
|
|
10
|
-
|
|
9
|
+
isTaskGateError,
|
|
10
|
+
serverT
|
|
11
|
+
} from "./chunk-OZWHRBDY.js";
|
|
11
12
|
import {
|
|
12
13
|
getSessionDisabledServers
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-S67WIWUG.js";
|
|
14
15
|
import {
|
|
15
16
|
TurnMetrics,
|
|
16
17
|
clearLLMFailure,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
spawnShellProcess,
|
|
42
43
|
startProcessCommand,
|
|
43
44
|
stopProcess
|
|
44
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-5UMXFLET.js";
|
|
45
46
|
import {
|
|
46
47
|
getMaxPerSession,
|
|
47
48
|
getSessionProcessCount,
|
|
@@ -59,12 +60,12 @@ import {
|
|
|
59
60
|
getEnabledSkillMetadata,
|
|
60
61
|
isSkillEnabled,
|
|
61
62
|
loadAllSkills
|
|
62
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-DWA4IE65.js";
|
|
63
64
|
import {
|
|
64
65
|
COMPACTION_PROMPT,
|
|
65
66
|
buildBasePrompt,
|
|
66
67
|
computeEffectiveTools
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-7QMWYNVF.js";
|
|
68
69
|
import {
|
|
69
70
|
AskUserInterrupt,
|
|
70
71
|
askUserTool
|
|
@@ -76,12 +77,12 @@ import {
|
|
|
76
77
|
registerPathConfirmation,
|
|
77
78
|
requestPathAccess,
|
|
78
79
|
resolveRelativeTraversals
|
|
79
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-I5ODJKYM.js";
|
|
80
81
|
import {
|
|
81
82
|
getCurrentContextWindowId,
|
|
82
83
|
getCurrentWindowMessageOptions,
|
|
83
84
|
getEventStore
|
|
84
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-QZOV4OVN.js";
|
|
85
86
|
import {
|
|
86
87
|
buildContextMessagesFromEventHistory,
|
|
87
88
|
foldContextState,
|
|
@@ -91,13 +92,13 @@ import {
|
|
|
91
92
|
handleToolResult,
|
|
92
93
|
reorderToolMessages,
|
|
93
94
|
stripOrphanedToolCalls
|
|
94
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-MEEUXRFL.js";
|
|
95
96
|
import {
|
|
96
97
|
findAgentById,
|
|
97
98
|
getRuntimeConfig,
|
|
98
99
|
getSubAgents,
|
|
99
100
|
loadAllAgentsDefault
|
|
100
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-ORCQ3EXQ.js";
|
|
101
102
|
import {
|
|
102
103
|
createChatDoneMessage,
|
|
103
104
|
createChatLLMRetryFailedMessage,
|
|
@@ -107,7 +108,7 @@ import {
|
|
|
107
108
|
createChatPathConfirmationMessage,
|
|
108
109
|
createChatStatsMessage,
|
|
109
110
|
createQueueStateMessage
|
|
110
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-AATMPL7S.js";
|
|
111
112
|
import {
|
|
112
113
|
getModelProfile,
|
|
113
114
|
modelSupportsVision
|
|
@@ -127,7 +128,7 @@ import {
|
|
|
127
128
|
SETTINGS_KEYS,
|
|
128
129
|
getSetting,
|
|
129
130
|
setSetting
|
|
130
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-CTWZPN7G.js";
|
|
131
132
|
import {
|
|
132
133
|
logger
|
|
133
134
|
} from "./chunk-K44MW7JJ.js";
|
|
@@ -151,7 +152,7 @@ async function requestUserConfirmation(context, toolLabel, desc) {
|
|
|
151
152
|
if (context.dangerLevel === "dangerous") return Promise.resolve(true);
|
|
152
153
|
if (toolLabel === "workspace" || toolLabel === "command") {
|
|
153
154
|
try {
|
|
154
|
-
const { getSetting: getSetting2, SETTINGS_KEYS: SETTINGS_KEYS2 } = await import("./settings-
|
|
155
|
+
const { getSetting: getSetting2, SETTINGS_KEYS: SETTINGS_KEYS2 } = await import("./settings-ZJPM6PQV.js");
|
|
155
156
|
if (getSetting2(SETTINGS_KEYS2.CONFIRM_ON_WORKSPACE_ACTIONS) !== "true") {
|
|
156
157
|
return Promise.resolve(true);
|
|
157
158
|
}
|
|
@@ -194,7 +195,13 @@ function validateAction(action, allowed, startTime) {
|
|
|
194
195
|
if (!action || !allowed.includes(action)) {
|
|
195
196
|
return {
|
|
196
197
|
success: false,
|
|
197
|
-
error:
|
|
198
|
+
error: serverT(
|
|
199
|
+
{
|
|
200
|
+
en: "Invalid action: {{action}}. Must be one of: {{allowed}}",
|
|
201
|
+
fr: "Action invalide : {{action}}. Doit \xEAtre l\u2019une des actions suivantes : {{allowed}}"
|
|
202
|
+
},
|
|
203
|
+
{ action: action ?? "", allowed: allowed.join(", ") }
|
|
204
|
+
),
|
|
198
205
|
durationMs: Date.now() - startTime,
|
|
199
206
|
truncated: false
|
|
200
207
|
};
|
|
@@ -205,7 +212,13 @@ function checkActionPermission(action, permittedActions, startTime) {
|
|
|
205
212
|
if (action && permittedActions && permittedActions.length > 0 && !permittedActions.includes(action)) {
|
|
206
213
|
return {
|
|
207
214
|
success: false,
|
|
208
|
-
error:
|
|
215
|
+
error: serverT(
|
|
216
|
+
{
|
|
217
|
+
en: "Action '{{action}}' not allowed. Available: {{available}}",
|
|
218
|
+
fr: "Action \xAB {{action}} \xBB non autoris\xE9e. Disponibles : {{available}}"
|
|
219
|
+
},
|
|
220
|
+
{ action: action ?? "", available: permittedActions.join(", ") }
|
|
221
|
+
),
|
|
209
222
|
durationMs: Date.now() - startTime,
|
|
210
223
|
truncated: false
|
|
211
224
|
};
|
|
@@ -268,7 +281,10 @@ function createTool(name, definition, handler2) {
|
|
|
268
281
|
}
|
|
269
282
|
return {
|
|
270
283
|
success: false,
|
|
271
|
-
error: error instanceof Error ? error.message :
|
|
284
|
+
error: error instanceof Error ? error.message : serverT({
|
|
285
|
+
en: "Unknown error in tool execution",
|
|
286
|
+
fr: "Erreur inconnue lors de l\u2019ex\xE9cution de l\u2019outil"
|
|
287
|
+
}),
|
|
272
288
|
durationMs: Date.now() - startTime,
|
|
273
289
|
truncated: false
|
|
274
290
|
};
|
|
@@ -607,16 +623,30 @@ var readFileTool = createTool(
|
|
|
607
623
|
}
|
|
608
624
|
if (stats.size > OUTPUT_LIMITS.read_file.maxFileBytes) {
|
|
609
625
|
return helpers.error(
|
|
610
|
-
|
|
626
|
+
serverT(
|
|
627
|
+
{
|
|
628
|
+
en: "File size ({{size}} bytes) exceeds maximum file size (20MB). Use shell command to process large files.",
|
|
629
|
+
fr: "La taille du fichier ({{size}} octets) d\xE9passe la taille maximale (20 Mo). Utilisez une commande shell pour traiter les fichiers volumineux."
|
|
630
|
+
},
|
|
631
|
+
{ size: stats.size }
|
|
632
|
+
)
|
|
611
633
|
);
|
|
612
634
|
}
|
|
613
635
|
if (stats.size > OUTPUT_LIMITS.read_file.maxImageBytes) {
|
|
614
636
|
return helpers.error(
|
|
615
|
-
|
|
637
|
+
serverT(
|
|
638
|
+
{
|
|
639
|
+
en: "File size ({{size}} bytes) exceeds image size limit (2MB). Use shell command to process large files.",
|
|
640
|
+
fr: "La taille du fichier ({{size}} octets) d\xE9passe la limite pour les images (2 Mo). Utilisez une commande shell pour traiter les fichiers volumineux."
|
|
641
|
+
},
|
|
642
|
+
{ size: stats.size }
|
|
643
|
+
)
|
|
616
644
|
);
|
|
617
645
|
}
|
|
618
646
|
} catch {
|
|
619
|
-
return helpers.error(
|
|
647
|
+
return helpers.error(
|
|
648
|
+
serverT({ en: "File not found: {{path}}", fr: "Fichier introuvable : {{path}}" }, { path: args.path })
|
|
649
|
+
);
|
|
620
650
|
}
|
|
621
651
|
const rawBuffer = await readFile2(fullPath);
|
|
622
652
|
const mimeType = await detectImageType(rawBuffer, args.path);
|
|
@@ -632,15 +662,22 @@ var readFileTool = createTool(
|
|
|
632
662
|
relative2(context.workdir, fullPath)
|
|
633
663
|
);
|
|
634
664
|
}
|
|
635
|
-
return helpers.success(
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
size: rawBuffer.length
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
665
|
+
return helpers.success(
|
|
666
|
+
serverT(
|
|
667
|
+
{ en: "[Image: {{path}} ({{mime}}, {{size}} bytes)]", fr: "[Image : {{path}} ({{mime}}, {{size}} octets)]" },
|
|
668
|
+
{ path: args.path, mime: mimeType, size: rawBuffer.length }
|
|
669
|
+
),
|
|
670
|
+
false,
|
|
671
|
+
{
|
|
672
|
+
metadata: {
|
|
673
|
+
mimeType,
|
|
674
|
+
size: rawBuffer.length,
|
|
675
|
+
base64Data,
|
|
676
|
+
dataUrl,
|
|
677
|
+
path: fullPath
|
|
678
|
+
}
|
|
642
679
|
}
|
|
643
|
-
|
|
680
|
+
);
|
|
644
681
|
}
|
|
645
682
|
if (isPdfBuffer(rawBuffer)) {
|
|
646
683
|
try {
|
|
@@ -795,7 +832,9 @@ var writeFileTool = createTool(
|
|
|
795
832
|
const readFiles = context.sessionManager.getReadFiles(context.sessionId);
|
|
796
833
|
const validation = await validateFileForWrite(fullPath, readFiles, context.workdir);
|
|
797
834
|
if (!validation.valid) {
|
|
798
|
-
return helpers.error(
|
|
835
|
+
return helpers.error(
|
|
836
|
+
validation.error?.message ?? serverT({ en: "File validation failed", fr: "\xC9chec de la validation du fichier" })
|
|
837
|
+
);
|
|
799
838
|
}
|
|
800
839
|
const dir = dirname(fullPath);
|
|
801
840
|
await mkdir(dir, { recursive: true });
|
|
@@ -804,7 +843,13 @@ var writeFileTool = createTool(
|
|
|
804
843
|
await writeFile(fullPath, encoded);
|
|
805
844
|
const lineCount = args.content.split("\n").length;
|
|
806
845
|
const byteCount = encoded.length;
|
|
807
|
-
let output =
|
|
846
|
+
let output = serverT(
|
|
847
|
+
{
|
|
848
|
+
en: "Successfully wrote {{lines}} lines ({{bytes}} bytes) to {{path}}",
|
|
849
|
+
fr: "{{lines}} lignes ({{bytes}} octets) \xE9crites avec succ\xE8s dans {{path}}"
|
|
850
|
+
},
|
|
851
|
+
{ lines: lineCount, bytes: byteCount, path: args.path }
|
|
852
|
+
);
|
|
808
853
|
let diagnostics = [];
|
|
809
854
|
if (context.lspManager) {
|
|
810
855
|
diagnostics = await context.lspManager.notifyFileChange(fullPath, args.content);
|
|
@@ -992,13 +1037,17 @@ var editFileTool = createTool(
|
|
|
992
1037
|
const readFiles = context.sessionManager.getReadFiles(context.sessionId);
|
|
993
1038
|
const validation = await validateFileForWrite(fullPath, readFiles, context.workdir);
|
|
994
1039
|
if (!validation.valid) {
|
|
995
|
-
return helpers.error(
|
|
1040
|
+
return helpers.error(
|
|
1041
|
+
validation.error?.message ?? serverT({ en: "File validation failed", fr: "\xC9chec de la validation du fichier" })
|
|
1042
|
+
);
|
|
996
1043
|
}
|
|
997
1044
|
let rawBuffer;
|
|
998
1045
|
try {
|
|
999
1046
|
rawBuffer = await readFile3(fullPath);
|
|
1000
1047
|
} catch {
|
|
1001
|
-
return helpers.error(
|
|
1048
|
+
return helpers.error(
|
|
1049
|
+
serverT({ en: "File not found: {{path}}", fr: "Fichier introuvable : {{path}}" }, { path: args.path })
|
|
1050
|
+
);
|
|
1002
1051
|
}
|
|
1003
1052
|
const { encoding, bomSize } = detectEncoding(rawBuffer);
|
|
1004
1053
|
const content = decodeContent(rawBuffer, encoding);
|
|
@@ -1009,17 +1058,24 @@ var editFileTool = createTool(
|
|
|
1009
1058
|
if (occurrences === 0) {
|
|
1010
1059
|
const preview = args.old_string.length > 100 ? args.old_string.slice(0, 100) + "..." : args.old_string;
|
|
1011
1060
|
return helpers.error(
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1061
|
+
serverT(
|
|
1062
|
+
{
|
|
1063
|
+
en: "old_string not found in file.\n\nSearched for:\n{{preview}}\n\nMake sure whitespace and indentation match exactly.",
|
|
1064
|
+
fr: "old_string introuvable dans le fichier.\n\nRecherch\xE9 :\n{{preview}}\n\nV\xE9rifiez que les espaces et l\u2019indentation correspondent exactement."
|
|
1065
|
+
},
|
|
1066
|
+
{ preview }
|
|
1067
|
+
)
|
|
1018
1068
|
);
|
|
1019
1069
|
}
|
|
1020
1070
|
if (occurrences > 1 && !replaceAll) {
|
|
1021
1071
|
return helpers.error(
|
|
1022
|
-
|
|
1072
|
+
serverT(
|
|
1073
|
+
{
|
|
1074
|
+
en: "Found {{count}} matches for old_string. Use replace_all: true to replace all, or provide more context to make the match unique.",
|
|
1075
|
+
fr: "{{count}} correspondances trouv\xE9es pour old_string. Utilisez replace_all : true pour tout remplacer, ou fournissez plus de contexte pour rendre la correspondance unique."
|
|
1076
|
+
},
|
|
1077
|
+
{ count: occurrences }
|
|
1078
|
+
)
|
|
1023
1079
|
);
|
|
1024
1080
|
}
|
|
1025
1081
|
const contextResult = extractEditContext(
|
|
@@ -1055,7 +1111,12 @@ Make sure whitespace and indentation match exactly.`
|
|
|
1055
1111
|
} else {
|
|
1056
1112
|
const index = normalizedContent.indexOf(normalizedOldString);
|
|
1057
1113
|
if (index === -1) {
|
|
1058
|
-
return helpers.error(
|
|
1114
|
+
return helpers.error(
|
|
1115
|
+
serverT({
|
|
1116
|
+
en: "old_string not found in file (unexpected)",
|
|
1117
|
+
fr: "old_string introuvable dans le fichier (inattendu)"
|
|
1118
|
+
})
|
|
1119
|
+
);
|
|
1059
1120
|
}
|
|
1060
1121
|
replacedContent = normalizedContent.slice(0, index) + normalizedNewString + normalizedContent.slice(index + normalizedOldString.length);
|
|
1061
1122
|
}
|
|
@@ -1065,7 +1126,13 @@ Make sure whitespace and indentation match exactly.`
|
|
|
1065
1126
|
);
|
|
1066
1127
|
const encoded = encodeContent(restoredContent, encoding, bomSize > 0);
|
|
1067
1128
|
await writeFile2(fullPath, encoded);
|
|
1068
|
-
let output =
|
|
1129
|
+
let output = serverT(
|
|
1130
|
+
{
|
|
1131
|
+
en: "Successfully replaced {{count}} occurrence(s) in {{path}}",
|
|
1132
|
+
fr: "{{count}} occurrence(s) remplac\xE9e(s) avec succ\xE8s dans {{path}}"
|
|
1133
|
+
},
|
|
1134
|
+
{ count: replaceAll ? occurrences : 1, path: args.path }
|
|
1135
|
+
);
|
|
1069
1136
|
let diagnostics = [];
|
|
1070
1137
|
if (context.lspManager) {
|
|
1071
1138
|
diagnostics = await context.lspManager.notifyFileChange(fullPath, restoredContent);
|
|
@@ -1204,16 +1271,31 @@ var runCommandTool = createTool(
|
|
|
1204
1271
|
const timeout = args.timeout ?? 12e4;
|
|
1205
1272
|
if (hasBackgroundAmpersand(args.command)) {
|
|
1206
1273
|
return helpers.error(
|
|
1207
|
-
|
|
1274
|
+
serverT({
|
|
1275
|
+
en: `Use background_process tool (action: "start") for background/long-running commands instead of '&'. See the tool description for details.`,
|
|
1276
|
+
fr: "Utilisez l\u2019outil background_process (action : \xAB start \xBB) pour les commandes d\u2019arri\xE8re-plan ou de longue dur\xE9e au lieu de \xAB & \xBB. Consultez la description de l\u2019outil pour plus de d\xE9tails."
|
|
1277
|
+
})
|
|
1208
1278
|
);
|
|
1209
1279
|
}
|
|
1210
1280
|
const mutationMatch = detectGitMutation(args.command);
|
|
1211
1281
|
if (mutationMatch) {
|
|
1212
|
-
const desc =
|
|
1282
|
+
const desc = serverT(
|
|
1283
|
+
{
|
|
1284
|
+
en: 'Command "{{cmd}}" modifies Git state ({{mutation}}). Allow this Git operation?',
|
|
1285
|
+
fr: "La commande \xAB {{cmd}} \xBB modifie l\u2019\xE9tat Git ({{mutation}}). Autoriser cette op\xE9ration Git ?"
|
|
1286
|
+
},
|
|
1287
|
+
{ cmd: args.command, mutation: mutationMatch }
|
|
1288
|
+
);
|
|
1213
1289
|
const approved = await requestUserConfirmation(context, "command", desc);
|
|
1214
1290
|
if (!approved) {
|
|
1215
1291
|
return helpers.error(
|
|
1216
|
-
|
|
1292
|
+
serverT(
|
|
1293
|
+
{
|
|
1294
|
+
en: 'User denied: "{{mutation}}" modifies Git state. Use the workspace tool to switch workspaces or branches.',
|
|
1295
|
+
fr: "Refus\xE9 par l\u2019utilisateur : \xAB {{mutation}} \xBB modifie l\u2019\xE9tat Git. Utilisez l\u2019outil workspace pour changer de workspace ou de branche."
|
|
1296
|
+
},
|
|
1297
|
+
{ mutation: mutationMatch }
|
|
1298
|
+
)
|
|
1217
1299
|
);
|
|
1218
1300
|
}
|
|
1219
1301
|
}
|
|
@@ -1271,7 +1353,12 @@ ${result.stderr}`;
|
|
|
1271
1353
|
const wasInterrupted = output.includes("[interrupted by user]");
|
|
1272
1354
|
return helpers.success(output, truncated, {
|
|
1273
1355
|
success: result.exitCode === 0,
|
|
1274
|
-
...result.exitCode !== 0 && !wasInterrupted ? {
|
|
1356
|
+
...result.exitCode !== 0 && !wasInterrupted ? {
|
|
1357
|
+
error: serverT(
|
|
1358
|
+
{ en: "Command exited with code {{code}}", fr: "La commande s\u2019est termin\xE9e avec le code {{code}}" },
|
|
1359
|
+
{ code: result.exitCode }
|
|
1360
|
+
)
|
|
1361
|
+
} : {}
|
|
1275
1362
|
});
|
|
1276
1363
|
}
|
|
1277
1364
|
);
|
|
@@ -1412,10 +1499,14 @@ function normalizeId(id) {
|
|
|
1412
1499
|
return String(id);
|
|
1413
1500
|
}
|
|
1414
1501
|
function requireKeyAndId(args, helpers, entries) {
|
|
1415
|
-
if (!args.key) return helpers.error("Missing required field: key");
|
|
1416
|
-
if (normalizeId(args.id) === void 0)
|
|
1502
|
+
if (!args.key) return helpers.error(serverT({ en: "Missing required field: key", fr: "Champ requis manquant : key" }));
|
|
1503
|
+
if (normalizeId(args.id) === void 0)
|
|
1504
|
+
return helpers.error(serverT({ en: "Missing required field: id", fr: "Champ requis manquant : id" }));
|
|
1417
1505
|
const current = entries[args.key];
|
|
1418
|
-
if (!current)
|
|
1506
|
+
if (!current)
|
|
1507
|
+
return helpers.error(
|
|
1508
|
+
serverT({ en: 'Key "{{key}}" not found.', fr: "Cl\xE9 \xAB {{key}} \xBB introuvable." }, { key: args.key ?? "" })
|
|
1509
|
+
);
|
|
1419
1510
|
return current;
|
|
1420
1511
|
}
|
|
1421
1512
|
var sessionMetadataTool = createTool(
|
|
@@ -1466,18 +1557,26 @@ var sessionMetadataTool = createTool(
|
|
|
1466
1557
|
const entries = session.metadataEntries ?? {};
|
|
1467
1558
|
if (args.action === "list") {
|
|
1468
1559
|
const keys = Object.keys(entries);
|
|
1469
|
-
if (keys.length === 0)
|
|
1560
|
+
if (keys.length === 0)
|
|
1561
|
+
return helpers.success(serverT({ en: "No metadata keys defined.", fr: "Aucune cl\xE9 de m\xE9tadonn\xE9es d\xE9finie." }));
|
|
1470
1562
|
return helpers.success(
|
|
1471
1563
|
`Metadata keys:
|
|
1472
1564
|
${keys.map((k) => `- ${k} (${entries[k]?.length ?? 0} items)`).join("\n")}`
|
|
1473
1565
|
);
|
|
1474
1566
|
}
|
|
1475
1567
|
if (args.action === "schema") {
|
|
1476
|
-
if (!args.key)
|
|
1568
|
+
if (!args.key)
|
|
1569
|
+
return helpers.error(serverT({ en: "Missing required field: key", fr: "Champ requis manquant : key" }));
|
|
1477
1570
|
const schema = SCHEMAS[args.key];
|
|
1478
1571
|
if (!schema)
|
|
1479
1572
|
return helpers.success(
|
|
1480
|
-
|
|
1573
|
+
serverT(
|
|
1574
|
+
{
|
|
1575
|
+
en: 'No schema defined for key "{{key}}". Items have id, description, and status fields.',
|
|
1576
|
+
fr: "Aucun sch\xE9ma d\xE9fini pour la cl\xE9 \xAB {{key}} \xBB. Les \xE9l\xE9ments ont des champs id, description et status."
|
|
1577
|
+
},
|
|
1578
|
+
{ key: args.key ?? "" }
|
|
1579
|
+
)
|
|
1481
1580
|
);
|
|
1482
1581
|
return helpers.success(
|
|
1483
1582
|
`Key: ${args.key}
|
|
@@ -1487,14 +1586,25 @@ ${Object.entries(schema.fields).map(([f, t]) => ` ${f}: ${t}`).join("\n")}`
|
|
|
1487
1586
|
);
|
|
1488
1587
|
}
|
|
1489
1588
|
if (args.action === "get") {
|
|
1490
|
-
if (!args.key)
|
|
1589
|
+
if (!args.key)
|
|
1590
|
+
return helpers.error(serverT({ en: "Missing required field: key", fr: "Champ requis manquant : key" }));
|
|
1491
1591
|
const keyEntries = entries[args.key];
|
|
1492
|
-
if (!keyEntries || keyEntries.length === 0)
|
|
1592
|
+
if (!keyEntries || keyEntries.length === 0)
|
|
1593
|
+
return helpers.success(
|
|
1594
|
+
serverT(
|
|
1595
|
+
{ en: 'No entries for key "{{key}}".', fr: "Aucune entr\xE9e pour la cl\xE9 \xAB {{key}} \xBB." },
|
|
1596
|
+
{ key: args.key ?? "" }
|
|
1597
|
+
)
|
|
1598
|
+
);
|
|
1493
1599
|
return helpers.success(JSON.stringify(keyEntries, null, 2));
|
|
1494
1600
|
}
|
|
1495
1601
|
if (args.action === "add") {
|
|
1496
|
-
if (!args.key)
|
|
1497
|
-
|
|
1602
|
+
if (!args.key)
|
|
1603
|
+
return helpers.error(serverT({ en: "Missing required field: key", fr: "Champ requis manquant : key" }));
|
|
1604
|
+
if (!args.description)
|
|
1605
|
+
return helpers.error(
|
|
1606
|
+
serverT({ en: "Missing required field: description", fr: "Champ requis manquant : description" })
|
|
1607
|
+
);
|
|
1498
1608
|
const current = entries[args.key] ?? [];
|
|
1499
1609
|
const newEntry = {
|
|
1500
1610
|
id: normalizeId(args.id) ?? (current.length + 1).toString(),
|
|
@@ -1503,14 +1613,28 @@ ${Object.entries(schema.fields).map(([f, t]) => ` ${f}: ${t}`).join("\n")}`
|
|
|
1503
1613
|
};
|
|
1504
1614
|
const updated = [...current, newEntry];
|
|
1505
1615
|
context.sessionManager.setMetadataEntries(context.sessionId, args.key, updated);
|
|
1506
|
-
return helpers.success(
|
|
1616
|
+
return helpers.success(
|
|
1617
|
+
serverT(
|
|
1618
|
+
{
|
|
1619
|
+
en: 'Added item "{{id}}" to "{{key}}". Total: {{count}} items.',
|
|
1620
|
+
fr: "\xC9l\xE9ment \xAB {{id}} \xBB ajout\xE9 \xE0 \xAB {{key}} \xBB. Total : {{count}} \xE9l\xE9ments."
|
|
1621
|
+
},
|
|
1622
|
+
{ id: newEntry.id, key: args.key ?? "", count: updated.length }
|
|
1623
|
+
)
|
|
1624
|
+
);
|
|
1507
1625
|
}
|
|
1508
1626
|
if (args.action === "update") {
|
|
1509
1627
|
const current = requireKeyAndId(args, helpers, entries);
|
|
1510
1628
|
if (!Array.isArray(current)) return current;
|
|
1511
1629
|
const id = normalizeId(args.id);
|
|
1512
1630
|
const idx = current.findIndex((e) => e.id === id);
|
|
1513
|
-
if (idx === -1)
|
|
1631
|
+
if (idx === -1)
|
|
1632
|
+
return helpers.error(
|
|
1633
|
+
serverT(
|
|
1634
|
+
{ en: 'Item "{{id}}" not found in "{{key}}".', fr: "\xC9l\xE9ment \xAB {{id}} \xBB introuvable dans \xAB {{key}} \xBB." },
|
|
1635
|
+
{ id, key: args.key ?? "" }
|
|
1636
|
+
)
|
|
1637
|
+
);
|
|
1514
1638
|
const updated = current.map(
|
|
1515
1639
|
(e, i) => i === idx ? {
|
|
1516
1640
|
...e,
|
|
@@ -1519,18 +1643,37 @@ ${Object.entries(schema.fields).map(([f, t]) => ` ${f}: ${t}`).join("\n")}`
|
|
|
1519
1643
|
} : e
|
|
1520
1644
|
);
|
|
1521
1645
|
context.sessionManager.setMetadataEntries(context.sessionId, args.key, updated);
|
|
1522
|
-
return helpers.success(
|
|
1646
|
+
return helpers.success(
|
|
1647
|
+
serverT(
|
|
1648
|
+
{ en: 'Updated item "{{id}}" in "{{key}}".', fr: "\xC9l\xE9ment \xAB {{id}} \xBB mis \xE0 jour dans \xAB {{key}} \xBB." },
|
|
1649
|
+
{ id, key: args.key ?? "" }
|
|
1650
|
+
)
|
|
1651
|
+
);
|
|
1523
1652
|
}
|
|
1524
1653
|
if (args.action === "remove") {
|
|
1525
1654
|
const current = requireKeyAndId(args, helpers, entries);
|
|
1526
1655
|
if (!Array.isArray(current)) return current;
|
|
1527
1656
|
const id = normalizeId(args.id);
|
|
1528
1657
|
const updated = current.filter((e) => e.id !== id);
|
|
1529
|
-
if (updated.length === current.length)
|
|
1658
|
+
if (updated.length === current.length)
|
|
1659
|
+
return helpers.error(
|
|
1660
|
+
serverT(
|
|
1661
|
+
{ en: 'Item "{{id}}" not found in "{{key}}".', fr: "\xC9l\xE9ment \xAB {{id}} \xBB introuvable dans \xAB {{key}} \xBB." },
|
|
1662
|
+
{ id, key: args.key ?? "" }
|
|
1663
|
+
)
|
|
1664
|
+
);
|
|
1530
1665
|
context.sessionManager.setMetadataEntries(context.sessionId, args.key, updated);
|
|
1531
|
-
return helpers.success(
|
|
1666
|
+
return helpers.success(
|
|
1667
|
+
serverT(
|
|
1668
|
+
{
|
|
1669
|
+
en: 'Removed item "{{id}}" from "{{key}}". {{count}} items remaining.',
|
|
1670
|
+
fr: "\xC9l\xE9ment \xAB {{id}} \xBB supprim\xE9 de \xAB {{key}} \xBB. {{count}} \xE9l\xE9ments restants."
|
|
1671
|
+
},
|
|
1672
|
+
{ id, key: args.key ?? "", count: updated.length }
|
|
1673
|
+
)
|
|
1674
|
+
);
|
|
1532
1675
|
}
|
|
1533
|
-
return helpers.error("Unexpected error");
|
|
1676
|
+
return helpers.error(serverT({ en: "Unexpected error", fr: "Erreur inattendue" }));
|
|
1534
1677
|
}
|
|
1535
1678
|
);
|
|
1536
1679
|
|
|
@@ -1623,7 +1766,12 @@ function createToolProgressHandler(append, messageId, callId, _sessionId) {
|
|
|
1623
1766
|
|
|
1624
1767
|
// src/server/chat/execute-tools.ts
|
|
1625
1768
|
import stripAnsi2 from "strip-ansi";
|
|
1626
|
-
|
|
1769
|
+
function interruptedError() {
|
|
1770
|
+
return serverT({
|
|
1771
|
+
en: "Tool execution was interrupted by user",
|
|
1772
|
+
fr: "L\u2019ex\xE9cution de l\u2019outil a \xE9t\xE9 interrompue par l\u2019utilisateur"
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1627
1775
|
function extractSubAgentPrompt(args) {
|
|
1628
1776
|
return args["prompt"] || args["query"] || args["task"] || "";
|
|
1629
1777
|
}
|
|
@@ -1642,7 +1790,7 @@ async function transformSubAgentAliases(toolCalls, toolRegistry, projectDir) {
|
|
|
1642
1790
|
function createInterruptedResult(startTime) {
|
|
1643
1791
|
return {
|
|
1644
1792
|
success: false,
|
|
1645
|
-
error:
|
|
1793
|
+
error: interruptedError(),
|
|
1646
1794
|
durationMs: startTime ? Date.now() - startTime : 0,
|
|
1647
1795
|
truncated: false
|
|
1648
1796
|
};
|
|
@@ -1663,7 +1811,13 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1663
1811
|
if (error instanceof PathAccessDeniedError) {
|
|
1664
1812
|
return {
|
|
1665
1813
|
success: false,
|
|
1666
|
-
error:
|
|
1814
|
+
error: serverT(
|
|
1815
|
+
{
|
|
1816
|
+
en: "User denied access to {{paths}}. If you need this file, explain why and ask for permission.",
|
|
1817
|
+
fr: "Acc\xE8s refus\xE9 par l\u2019utilisateur : {{paths}}. Si vous avez besoin de ce fichier, expliquez pourquoi et demandez l\u2019autorisation."
|
|
1818
|
+
},
|
|
1819
|
+
{ paths: error.paths.join(", ") }
|
|
1820
|
+
),
|
|
1667
1821
|
durationMs: Date.now() - startTime,
|
|
1668
1822
|
truncated: false
|
|
1669
1823
|
};
|
|
@@ -1676,7 +1830,15 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1676
1830
|
const { awaitAnswer } = await import("./ask-UBIRH3SO.js");
|
|
1677
1831
|
const answerPromise = awaitAnswer(error.callId);
|
|
1678
1832
|
if (!answerPromise) {
|
|
1679
|
-
throw new Error(
|
|
1833
|
+
throw new Error(
|
|
1834
|
+
serverT(
|
|
1835
|
+
{
|
|
1836
|
+
en: "No pending question found for callId: {{id}}",
|
|
1837
|
+
fr: "Aucune question en attente trouv\xE9e pour callId : {{id}}"
|
|
1838
|
+
},
|
|
1839
|
+
{ id: error.callId }
|
|
1840
|
+
)
|
|
1841
|
+
);
|
|
1680
1842
|
}
|
|
1681
1843
|
const answer = await answerPromise;
|
|
1682
1844
|
return {
|
|
@@ -1698,7 +1860,7 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1698
1860
|
return {
|
|
1699
1861
|
toolCall,
|
|
1700
1862
|
toolResult: toolResult2,
|
|
1701
|
-
content:
|
|
1863
|
+
content: serverT({ en: "Error: {{message}}", fr: "Erreur : {{message}}" }, { message: interruptedError() }),
|
|
1702
1864
|
index
|
|
1703
1865
|
};
|
|
1704
1866
|
}
|
|
@@ -1709,7 +1871,13 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1709
1871
|
} else {
|
|
1710
1872
|
const toolResult2 = {
|
|
1711
1873
|
success: false,
|
|
1712
|
-
error:
|
|
1874
|
+
error: serverT(
|
|
1875
|
+
{
|
|
1876
|
+
en: "Failed to parse tool call arguments: {{error}}. Please ensure your JSON function call arguments are valid.",
|
|
1877
|
+
fr: "\xC9chec de l\u2019analyse des arguments de l\u2019appel d\u2019outil : {{error}}. Assurez-vous que vos arguments JSON d\u2019appel de fonction sont valides."
|
|
1878
|
+
},
|
|
1879
|
+
{ error: toolCall.parseError ?? "" }
|
|
1880
|
+
),
|
|
1713
1881
|
durationMs: 0,
|
|
1714
1882
|
truncated: false
|
|
1715
1883
|
};
|
|
@@ -1717,7 +1885,10 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1717
1885
|
return {
|
|
1718
1886
|
toolCall,
|
|
1719
1887
|
toolResult: toolResult2,
|
|
1720
|
-
content:
|
|
1888
|
+
content: serverT(
|
|
1889
|
+
{ en: "Error: {{message}}", fr: "Erreur : {{message}}" },
|
|
1890
|
+
{ message: toolResult2.error ?? "" }
|
|
1891
|
+
),
|
|
1721
1892
|
index
|
|
1722
1893
|
};
|
|
1723
1894
|
}
|
|
@@ -1760,9 +1931,10 @@ async function executeTools(assistantMsgId, toolCalls, ctx, append) {
|
|
|
1760
1931
|
stepDoneCalled = true;
|
|
1761
1932
|
}
|
|
1762
1933
|
const rawContent = stripAnsi2(
|
|
1763
|
-
toolResult.success ? toolResult.output ?? "Success" : toolResult.output ?
|
|
1764
|
-
|
|
1765
|
-
|
|
1934
|
+
toolResult.success ? toolResult.output ?? serverT({ en: "Success", fr: "Succ\xE8s" }) : toolResult.output ? serverT(
|
|
1935
|
+
{ en: "{{output}}\n\nError: {{error}}", fr: "{{output}}\n\nErreur : {{error}}" },
|
|
1936
|
+
{ output: toolResult.output, error: toolResult.error ?? "" }
|
|
1937
|
+
) : serverT({ en: "Error: {{error}}", fr: "Erreur : {{error}}" }, { error: toolResult.error ?? "" })
|
|
1766
1938
|
);
|
|
1767
1939
|
const { clean: content, corrupted } = sanitizeUtf8(rawContent);
|
|
1768
1940
|
if (corrupted) {
|
|
@@ -2082,7 +2254,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
|
|
|
2082
2254
|
return { failed: { error: attemptResult.error } };
|
|
2083
2255
|
}
|
|
2084
2256
|
if (!config.subAgentMetadata) {
|
|
2085
|
-
config.onMessage?.(createChatLLMRetryMessage(decision.attempt, decision.delayMs));
|
|
2257
|
+
config.onMessage?.(createChatLLMRetryMessage(decision.attempt, decision.delayMs, attemptResult.error));
|
|
2086
2258
|
}
|
|
2087
2259
|
const waitResult = await sleepThroughRetryBackoff(decision.delayMs, sessionId, signal);
|
|
2088
2260
|
if (waitResult === "aborted") throw new Error("Aborted");
|
|
@@ -2094,7 +2266,16 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
|
|
|
2094
2266
|
if (!retryLimiter.canRetry()) {
|
|
2095
2267
|
append({
|
|
2096
2268
|
type: "chat.error",
|
|
2097
|
-
data: {
|
|
2269
|
+
data: {
|
|
2270
|
+
error: serverT(
|
|
2271
|
+
{
|
|
2272
|
+
en: "Auto-retry limit exceeded after {{count}} retries",
|
|
2273
|
+
fr: "Limite de relance automatique d\xE9pass\xE9e apr\xE8s {{count}} tentatives"
|
|
2274
|
+
},
|
|
2275
|
+
{ count: retryLimiter.maxRetries() }
|
|
2276
|
+
),
|
|
2277
|
+
recoverable: false
|
|
2278
|
+
}
|
|
2098
2279
|
});
|
|
2099
2280
|
append(createChatDoneEvent(assistantMsgId, "error", void 0, agentType));
|
|
2100
2281
|
throw new Error("Auto-retry limit exceeded");
|
|
@@ -2154,7 +2335,7 @@ ${CONTINUE_PROMPT}` : CONTINUE_PROMPT;
|
|
|
2154
2335
|
currentMaxTokensOverride = void 0;
|
|
2155
2336
|
if (!compacting) {
|
|
2156
2337
|
const contextState = sessionManager.getContextState(sessionId);
|
|
2157
|
-
const { shouldCompact, appendCompactionPrompt } = await import("./compactor-
|
|
2338
|
+
const { shouldCompact, appendCompactionPrompt } = await import("./compactor-454UEIEX.js");
|
|
2158
2339
|
if (shouldCompact(
|
|
2159
2340
|
contextState.currentTokens,
|
|
2160
2341
|
contextState.maxTokens,
|
|
@@ -2319,7 +2500,13 @@ ${COMPACTION_PROMPT}`,
|
|
|
2319
2500
|
if (!summary) {
|
|
2320
2501
|
append({
|
|
2321
2502
|
type: "chat.error",
|
|
2322
|
-
data: {
|
|
2503
|
+
data: {
|
|
2504
|
+
error: serverT({
|
|
2505
|
+
en: "Compaction produced empty summary, continuing with full context",
|
|
2506
|
+
fr: "La compaction a produit un r\xE9sum\xE9 vide, poursuite avec le contexte complet"
|
|
2507
|
+
}),
|
|
2508
|
+
recoverable: true
|
|
2509
|
+
}
|
|
2323
2510
|
});
|
|
2324
2511
|
logger.warn("Compaction produced empty summary, continuing", { sessionId });
|
|
2325
2512
|
compacting = false;
|
|
@@ -3187,7 +3374,7 @@ var callSubAgentTool = {
|
|
|
3187
3374
|
};
|
|
3188
3375
|
}
|
|
3189
3376
|
try {
|
|
3190
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
3377
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-E63MOJBO.js");
|
|
3191
3378
|
const toolRegistry = getToolRegistryForAgent2(agentDef);
|
|
3192
3379
|
const turnMetrics = new TurnMetrics();
|
|
3193
3380
|
const result = await executeSubAgent({
|
|
@@ -3236,10 +3423,17 @@ ${skill.prompt}`;
|
|
|
3236
3423
|
var handler = async (args, context, helpers) => {
|
|
3237
3424
|
const { skillId } = args;
|
|
3238
3425
|
if (!skillId) {
|
|
3239
|
-
return helpers.error(
|
|
3426
|
+
return helpers.error(
|
|
3427
|
+
serverT({ en: "Missing required parameter: skillId", fr: "Param\xE8tre requis manquant : skillId" })
|
|
3428
|
+
);
|
|
3240
3429
|
}
|
|
3241
3430
|
if (!isSkillEnabled(skillId)) {
|
|
3242
|
-
return helpers.error(
|
|
3431
|
+
return helpers.error(
|
|
3432
|
+
serverT(
|
|
3433
|
+
{ en: 'Skill "{{id}}" is not enabled.', fr: "La comp\xE9tence \xAB {{id}} \xBB n\u2019est pas activ\xE9e." },
|
|
3434
|
+
{ id: skillId }
|
|
3435
|
+
)
|
|
3436
|
+
);
|
|
3243
3437
|
}
|
|
3244
3438
|
const config = getRuntimeConfig();
|
|
3245
3439
|
const configDir = getGlobalConfigDir(config.mode ?? "production");
|
|
@@ -3247,7 +3441,15 @@ var handler = async (args, context, helpers) => {
|
|
|
3247
3441
|
const skill = findSkillById(skillId, allSkills);
|
|
3248
3442
|
if (!skill) {
|
|
3249
3443
|
const available = allSkills.map((s) => s.metadata.id).join(", ");
|
|
3250
|
-
return helpers.error(
|
|
3444
|
+
return helpers.error(
|
|
3445
|
+
serverT(
|
|
3446
|
+
{
|
|
3447
|
+
en: 'Skill "{{id}}" not found. Available skills: {{available}}',
|
|
3448
|
+
fr: "Comp\xE9tence \xAB {{id}} \xBB introuvable. Comp\xE9tences disponibles : {{available}}"
|
|
3449
|
+
},
|
|
3450
|
+
{ id: skillId, available }
|
|
3451
|
+
)
|
|
3452
|
+
);
|
|
3251
3453
|
}
|
|
3252
3454
|
return helpers.success(formatSkillPrompt(skill));
|
|
3253
3455
|
};
|
|
@@ -3374,7 +3576,9 @@ var webFetchTool = createTool(
|
|
|
3374
3576
|
const url = args.url;
|
|
3375
3577
|
const format = args.format ?? "markdown";
|
|
3376
3578
|
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
3377
|
-
return helpers.error(
|
|
3579
|
+
return helpers.error(
|
|
3580
|
+
serverT({ en: "URL must start with http:// or https://", fr: "L\u2019URL doit commencer par http:// ou https://" })
|
|
3581
|
+
);
|
|
3378
3582
|
}
|
|
3379
3583
|
const timeoutMs = (args.timeout ?? DEFAULT_TIMEOUT_MS / 1e3) * 1e3;
|
|
3380
3584
|
const signal = buildSignal(timeoutMs, context.signal);
|
|
@@ -3386,22 +3590,40 @@ var webFetchTool = createTool(
|
|
|
3386
3590
|
const initial = await fetch(url, { signal, headers });
|
|
3387
3591
|
const response = initial.status === 403 && initial.headers.get("cf-mitigated") === "challenge" ? await fetch(url, { signal, headers: { ...headers, "User-Agent": "openfox" } }) : initial;
|
|
3388
3592
|
if (!response.ok) {
|
|
3389
|
-
return helpers.error(
|
|
3593
|
+
return helpers.error(
|
|
3594
|
+
serverT(
|
|
3595
|
+
{
|
|
3596
|
+
en: "Request failed with status code: {{status}}",
|
|
3597
|
+
fr: "\xC9chec de la requ\xEAte avec le code de statut : {{status}}"
|
|
3598
|
+
},
|
|
3599
|
+
{ status: response.status }
|
|
3600
|
+
)
|
|
3601
|
+
);
|
|
3390
3602
|
}
|
|
3391
3603
|
const contentLength = response.headers.get("content-length");
|
|
3392
3604
|
if (contentLength && parseInt(contentLength) > MAX_RESPONSE_SIZE) {
|
|
3393
|
-
return helpers.error(
|
|
3605
|
+
return helpers.error(
|
|
3606
|
+
serverT({
|
|
3607
|
+
en: "Response too large (exceeds 5MB limit)",
|
|
3608
|
+
fr: "R\xE9ponse trop volumineuse (d\xE9passe la limite de 5 Mo)"
|
|
3609
|
+
})
|
|
3610
|
+
);
|
|
3394
3611
|
}
|
|
3395
3612
|
const arrayBuffer = await response.arrayBuffer();
|
|
3396
3613
|
if (arrayBuffer.byteLength > MAX_RESPONSE_SIZE) {
|
|
3397
|
-
return helpers.error(
|
|
3614
|
+
return helpers.error(
|
|
3615
|
+
serverT({
|
|
3616
|
+
en: "Response too large (exceeds 5MB limit)",
|
|
3617
|
+
fr: "R\xE9ponse trop volumineuse (d\xE9passe la limite de 5 Mo)"
|
|
3618
|
+
})
|
|
3619
|
+
);
|
|
3398
3620
|
}
|
|
3399
3621
|
const contentType = response.headers.get("content-type") || "";
|
|
3400
3622
|
const mime = contentType.split(";")[0]?.trim().toLowerCase() || "";
|
|
3401
3623
|
const isImage = mime.startsWith("image/") && mime !== "image/svg+xml" && mime !== "image/vnd.fastbidsheet";
|
|
3402
3624
|
if (isImage) {
|
|
3403
3625
|
const base64Data = Buffer.from(arrayBuffer).toString("base64");
|
|
3404
|
-
return helpers.success("Image fetched successfully", false, {
|
|
3626
|
+
return helpers.success(serverT({ en: "Image fetched successfully", fr: "Image r\xE9cup\xE9r\xE9e avec succ\xE8s" }), false, {
|
|
3405
3627
|
metadata: {
|
|
3406
3628
|
mimeType: mime,
|
|
3407
3629
|
base64Data,
|
|
@@ -3882,7 +4104,19 @@ var devServerTool = createTool(
|
|
|
3882
4104
|
}
|
|
3883
4105
|
if (!status.config) {
|
|
3884
4106
|
return helpers.error(
|
|
3885
|
-
|
|
4107
|
+
serverT(
|
|
4108
|
+
{
|
|
4109
|
+
en: "No .openfox/dev.json config found. Create one in the project root:\n\n{{config}}\n\n(Worktrees inherit the project root config automatically.)",
|
|
4110
|
+
fr: "Aucun fichier .openfox/dev.json trouv\xE9. Cr\xE9ez-en un \xE0 la racine du projet :\n\n{{config}}\n\n(Les worktrees h\xE9ritent automatiquement de la configuration du projet.)"
|
|
4111
|
+
},
|
|
4112
|
+
{
|
|
4113
|
+
config: JSON.stringify(
|
|
4114
|
+
{ command: "npm run dev", url: "http://localhost:3000", hotReload: true, disableInspect: false },
|
|
4115
|
+
null,
|
|
4116
|
+
2
|
|
4117
|
+
)
|
|
4118
|
+
}
|
|
4119
|
+
)
|
|
3886
4120
|
);
|
|
3887
4121
|
}
|
|
3888
4122
|
return helpers.success(
|
|
@@ -3918,7 +4152,7 @@ var stepDoneTool = {
|
|
|
3918
4152
|
async execute(_args, _context) {
|
|
3919
4153
|
return {
|
|
3920
4154
|
success: true,
|
|
3921
|
-
output: "Step completion signal recorded.",
|
|
4155
|
+
output: serverT({ en: "Step completion signal recorded.", fr: "Signal de fin d\u2019\xE9tape enregistr\xE9." }),
|
|
3922
4156
|
durationMs: 0,
|
|
3923
4157
|
truncated: false
|
|
3924
4158
|
};
|
|
@@ -3926,6 +4160,9 @@ var stepDoneTool = {
|
|
|
3926
4160
|
};
|
|
3927
4161
|
|
|
3928
4162
|
// src/server/tools/background-process/index.ts
|
|
4163
|
+
function processNotFoundError(id) {
|
|
4164
|
+
return serverT({ en: "Process not found: {{id}}", fr: "Processus introuvable : {{id}}" }, { id: id ?? "" });
|
|
4165
|
+
}
|
|
3929
4166
|
var backgroundProcessTool = createTool(
|
|
3930
4167
|
"background_process",
|
|
3931
4168
|
{
|
|
@@ -3998,17 +4235,28 @@ These processes run independently of agent turns and persist across session comp
|
|
|
3998
4235
|
const maxPerSession = getMaxPerSession();
|
|
3999
4236
|
if (count >= maxPerSession) {
|
|
4000
4237
|
return helpers.error(
|
|
4001
|
-
|
|
4238
|
+
serverT(
|
|
4239
|
+
{
|
|
4240
|
+
en: "Maximum number of background processes ({{count}}) reached. Stop existing processes before starting new ones.",
|
|
4241
|
+
fr: "Nombre maximal de processus en arri\xE8re-plan ({{count}}) atteint. Arr\xEAtez des processus existants avant d\u2019en d\xE9marrer de nouveaux."
|
|
4242
|
+
},
|
|
4243
|
+
{ count: maxPerSession }
|
|
4244
|
+
)
|
|
4002
4245
|
);
|
|
4003
4246
|
}
|
|
4004
4247
|
const name = args.name ?? args.command?.split(" ")[0] ?? "process";
|
|
4005
4248
|
const process2 = createProcess(sessionId, name, args.command, cwd, args.timeout);
|
|
4006
4249
|
if (!process2) {
|
|
4007
|
-
return helpers.error(
|
|
4250
|
+
return helpers.error(
|
|
4251
|
+
serverT({
|
|
4252
|
+
en: "Failed to create process. Maximum limit may have been reached.",
|
|
4253
|
+
fr: "\xC9chec de la cr\xE9ation du processus. La limite maximale a peut-\xEAtre \xE9t\xE9 atteinte."
|
|
4254
|
+
})
|
|
4255
|
+
);
|
|
4008
4256
|
}
|
|
4009
4257
|
const pid = startProcessCommand(process2.id, sessionId, args.command, cwd);
|
|
4010
4258
|
if (!pid) {
|
|
4011
|
-
return helpers.error(
|
|
4259
|
+
return helpers.error(serverT({ en: "Failed to start process.", fr: "\xC9chec du d\xE9marrage du processus." }));
|
|
4012
4260
|
}
|
|
4013
4261
|
return helpers.success(
|
|
4014
4262
|
JSON.stringify(
|
|
@@ -4026,11 +4274,17 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4026
4274
|
}
|
|
4027
4275
|
case "stop": {
|
|
4028
4276
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
4029
|
-
if (!proc)
|
|
4030
|
-
return helpers.error(`Process not found: ${args.processId}`);
|
|
4031
|
-
}
|
|
4277
|
+
if (!proc) return helpers.error(processNotFoundError(args.processId));
|
|
4032
4278
|
if (proc.status !== "running") {
|
|
4033
|
-
return helpers.error(
|
|
4279
|
+
return helpers.error(
|
|
4280
|
+
serverT(
|
|
4281
|
+
{
|
|
4282
|
+
en: "Process is not running (status: {{status}}). Cannot stop.",
|
|
4283
|
+
fr: "Le processus n\u2019est pas en cours d\u2019ex\xE9cution (statut : {{status}}). Impossible de l\u2019arr\xEAter."
|
|
4284
|
+
},
|
|
4285
|
+
{ status: proc.status }
|
|
4286
|
+
)
|
|
4287
|
+
);
|
|
4034
4288
|
}
|
|
4035
4289
|
await stopProcess(args.processId, sessionId);
|
|
4036
4290
|
return helpers.success(
|
|
@@ -4061,9 +4315,7 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4061
4315
|
}
|
|
4062
4316
|
case "status": {
|
|
4063
4317
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
4064
|
-
if (!proc)
|
|
4065
|
-
return helpers.error(`Process not found: ${args.processId}`);
|
|
4066
|
-
}
|
|
4318
|
+
if (!proc) return helpers.error(processNotFoundError(args.processId));
|
|
4067
4319
|
const uptime = proc.startedAt ? Date.now() - proc.startedAt : null;
|
|
4068
4320
|
return helpers.success(
|
|
4069
4321
|
JSON.stringify(
|
|
@@ -4078,9 +4330,7 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4078
4330
|
}
|
|
4079
4331
|
case "logs": {
|
|
4080
4332
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
4081
|
-
if (!proc)
|
|
4082
|
-
return helpers.error(`Process not found: ${args.processId}`);
|
|
4083
|
-
}
|
|
4333
|
+
if (!proc) return helpers.error(processNotFoundError(args.processId));
|
|
4084
4334
|
const since = args.since ?? 0;
|
|
4085
4335
|
const maxLines = Math.min(args.maxLines ?? 500, 2e3);
|
|
4086
4336
|
const { lines, totalLines, nextOffset, hasMore } = getProcessLogs(args.processId, since, maxLines);
|
|
@@ -4100,7 +4350,9 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4100
4350
|
);
|
|
4101
4351
|
}
|
|
4102
4352
|
default:
|
|
4103
|
-
return helpers.error(
|
|
4353
|
+
return helpers.error(
|
|
4354
|
+
serverT({ en: "Unknown action: {{action}}", fr: "Action inconnue : {{action}}" }, { action: args.action })
|
|
4355
|
+
);
|
|
4104
4356
|
}
|
|
4105
4357
|
}
|
|
4106
4358
|
);
|
|
@@ -4200,13 +4452,18 @@ var mcpConfigTool = createTool(
|
|
|
4200
4452
|
if (actionError) return actionError;
|
|
4201
4453
|
if (args.action === "bootstrap") {
|
|
4202
4454
|
if (!mcpBootstrapForTools) {
|
|
4203
|
-
return helpers.error(
|
|
4455
|
+
return helpers.error(
|
|
4456
|
+
serverT({
|
|
4457
|
+
en: "MCP bootstrap is not available for this server",
|
|
4458
|
+
fr: "Le bootstrap MCP n\u2019est pas disponible pour ce serveur"
|
|
4459
|
+
})
|
|
4460
|
+
);
|
|
4204
4461
|
}
|
|
4205
4462
|
const config = await mcpBootstrapForTools();
|
|
4206
4463
|
return helpers.success(JSON.stringify(config, null, 2));
|
|
4207
4464
|
}
|
|
4208
4465
|
if (!mcpManagerForTools) {
|
|
4209
|
-
return helpers.error("MCP manager not available");
|
|
4466
|
+
return helpers.error(serverT({ en: "MCP manager not available", fr: "Gestionnaire MCP indisponible" }));
|
|
4210
4467
|
}
|
|
4211
4468
|
async function persistAndRebuild(updater) {
|
|
4212
4469
|
const globalConfig = await loadGlobalConfig(mcpConfigMode, mcpConfigPath);
|
|
@@ -4214,59 +4471,85 @@ var mcpConfigTool = createTool(
|
|
|
4214
4471
|
const updated = updater(mcpServers);
|
|
4215
4472
|
await saveGlobalConfig(mcpConfigMode, { ...globalConfig, mcpServers: updated }, mcpConfigPath);
|
|
4216
4473
|
}
|
|
4217
|
-
const APPLY_PROMPT_MESSAGE =
|
|
4474
|
+
const APPLY_PROMPT_MESSAGE = serverT({
|
|
4475
|
+
en: "Tool changes are announced automatically.",
|
|
4476
|
+
fr: "Les modifications d\u2019outils sont annonc\xE9es automatiquement."
|
|
4477
|
+
});
|
|
4218
4478
|
async function notifyContextChanged(sessionId) {
|
|
4219
4479
|
context.sessionManager.setDynamicContextChanged(sessionId, true);
|
|
4220
4480
|
mcpNotifyChanged?.(sessionId);
|
|
4221
|
-
const { injectContextDriftReminders } = await import("./dynamic-context-
|
|
4481
|
+
const { injectContextDriftReminders } = await import("./dynamic-context-LKC6JYLQ.js");
|
|
4222
4482
|
await injectContextDriftReminders(context.sessionManager, sessionId);
|
|
4223
4483
|
}
|
|
4224
4484
|
async function rebuildTools() {
|
|
4225
|
-
const { setMcpTools: setMcpTools2 } = await import("./tools-
|
|
4485
|
+
const { setMcpTools: setMcpTools2 } = await import("./tools-E63MOJBO.js");
|
|
4226
4486
|
const mcpTools = createMcpTools(mcpManagerForTools);
|
|
4227
4487
|
setMcpTools2(mcpTools);
|
|
4228
4488
|
}
|
|
4229
4489
|
if (args.action === "list") {
|
|
4230
4490
|
const servers = mcpManagerForTools.getAllServers();
|
|
4231
4491
|
if (servers.length === 0) {
|
|
4232
|
-
return helpers.success("No MCP servers configured.");
|
|
4492
|
+
return helpers.success(serverT({ en: "No MCP servers configured.", fr: "Aucun serveur MCP configur\xE9." }));
|
|
4233
4493
|
}
|
|
4234
|
-
const { getSessionDisabledServers: getSessionDisabledServers2 } = await import("./session-overrides-
|
|
4494
|
+
const { getSessionDisabledServers: getSessionDisabledServers2 } = await import("./session-overrides-LYW5PJ3R.js");
|
|
4235
4495
|
const disabledForSession = new Set(context.sessionId ? getSessionDisabledServers2(context.sessionId) : []);
|
|
4236
4496
|
const visibleServers = servers.filter((server) => !disabledForSession.has(server.name));
|
|
4237
4497
|
if (visibleServers.length === 0) {
|
|
4238
|
-
return helpers.success("No MCP servers configured.");
|
|
4498
|
+
return helpers.success(serverT({ en: "No MCP servers configured.", fr: "Aucun serveur MCP configur\xE9." }));
|
|
4239
4499
|
}
|
|
4240
4500
|
const lines = [];
|
|
4241
4501
|
for (const server of visibleServers) {
|
|
4242
4502
|
const connStr = server.status === "connected" ? "\u25CF" : server.status === "error" ? "\u2717" : "\u25CB";
|
|
4243
4503
|
const cmdStr = server.config.command ? `${server.config.command} ${(server.config.args ?? []).join(" ")}` : server.config.url ?? "";
|
|
4244
4504
|
const hasCachedTools = server.tools.length > 0;
|
|
4245
|
-
const sourceLabel = server.status === "connected" ? " (live)" : hasCachedTools ? " (from cache)" : "";
|
|
4505
|
+
const sourceLabel = server.status === "connected" ? serverT({ en: " (live)", fr: " (en direct)" }) : hasCachedTools ? serverT({ en: " (from cache)", fr: " (depuis le cache)" }) : "";
|
|
4246
4506
|
const statusLine = server.error ? `${server.status}${sourceLabel}: ${server.error}` : `${server.status}${sourceLabel}`;
|
|
4247
4507
|
lines.push(`${connStr} ${server.name} (${server.config.transport}) \u2014 ${statusLine}`);
|
|
4248
4508
|
lines.push(` ${cmdStr}`);
|
|
4249
|
-
lines.push(
|
|
4509
|
+
lines.push(
|
|
4510
|
+
serverT(
|
|
4511
|
+
{ en: " {{count}} tools, ~{{tokens}} tokens", fr: " {{count}} outils, ~{{tokens}} tokens" },
|
|
4512
|
+
{ count: server.tools.length, tokens: server.estimatedTokens }
|
|
4513
|
+
)
|
|
4514
|
+
);
|
|
4250
4515
|
const enabledTools = server.tools.filter((t) => t.enabled);
|
|
4251
4516
|
const disabledTools = server.tools.filter((t) => !t.enabled);
|
|
4252
4517
|
if (enabledTools.length > 0) {
|
|
4253
|
-
lines.push(
|
|
4518
|
+
lines.push(
|
|
4519
|
+
serverT(
|
|
4520
|
+
{ en: " Enabled: {{list}}", fr: " Activ\xE9s : {{list}}" },
|
|
4521
|
+
{ list: enabledTools.map((t) => t.name).join(", ") }
|
|
4522
|
+
)
|
|
4523
|
+
);
|
|
4254
4524
|
}
|
|
4255
4525
|
if (disabledTools.length > 0) {
|
|
4256
|
-
lines.push(
|
|
4526
|
+
lines.push(
|
|
4527
|
+
serverT(
|
|
4528
|
+
{ en: " Disabled: {{list}}", fr: " D\xE9sactiv\xE9s : {{list}}" },
|
|
4529
|
+
{ list: disabledTools.map((t) => t.name).join(", ") }
|
|
4530
|
+
)
|
|
4531
|
+
);
|
|
4257
4532
|
}
|
|
4258
4533
|
}
|
|
4259
4534
|
return helpers.success(lines.join("\n"));
|
|
4260
4535
|
}
|
|
4261
4536
|
if (args.action === "add") {
|
|
4262
|
-
if (!args.name)
|
|
4537
|
+
if (!args.name)
|
|
4538
|
+
return helpers.error(serverT({ en: "Missing required field: name", fr: "Champ requis manquant : name" }));
|
|
4263
4539
|
if (args.transport === "http") {
|
|
4264
|
-
if (!args.url)
|
|
4540
|
+
if (!args.url)
|
|
4541
|
+
return helpers.error(
|
|
4542
|
+
serverT({ en: "url is required for http transport", fr: "url est requis pour le transport http" })
|
|
4543
|
+
);
|
|
4265
4544
|
} else if (!args.command) {
|
|
4266
|
-
return helpers.error(
|
|
4545
|
+
return helpers.error(
|
|
4546
|
+
serverT({ en: "command is required for stdio transport", fr: "command est requis pour le transport stdio" })
|
|
4547
|
+
);
|
|
4267
4548
|
}
|
|
4268
4549
|
if (args.timeout !== void 0 && (typeof args.timeout !== "number" || args.timeout <= 0)) {
|
|
4269
|
-
return helpers.error(
|
|
4550
|
+
return helpers.error(
|
|
4551
|
+
serverT({ en: "timeout must be a positive number", fr: "timeout doit \xEAtre un nombre positif" })
|
|
4552
|
+
);
|
|
4270
4553
|
}
|
|
4271
4554
|
const serverCfg = {
|
|
4272
4555
|
transport: args.transport ?? "stdio",
|
|
@@ -4286,12 +4569,27 @@ var mcpConfigTool = createTool(
|
|
|
4286
4569
|
await notifyContextChanged(context.sessionId);
|
|
4287
4570
|
const server = mcpManagerForTools.getServer(args.name);
|
|
4288
4571
|
const toolCount = server?.tools.length ?? 0;
|
|
4289
|
-
return helpers.success(
|
|
4572
|
+
return helpers.success(
|
|
4573
|
+
serverT(
|
|
4574
|
+
{
|
|
4575
|
+
en: 'Added MCP server "{{name}}" ({{count}} tools discovered). {{prompt}}',
|
|
4576
|
+
fr: "Serveur MCP \xAB {{name}} \xBB ajout\xE9 ({{count}} outils d\xE9couverts). {{prompt}}"
|
|
4577
|
+
},
|
|
4578
|
+
{ name: args.name ?? "", count: toolCount, prompt: APPLY_PROMPT_MESSAGE }
|
|
4579
|
+
)
|
|
4580
|
+
);
|
|
4290
4581
|
}
|
|
4291
4582
|
if (args.action === "update") {
|
|
4292
|
-
if (!args.name)
|
|
4583
|
+
if (!args.name)
|
|
4584
|
+
return helpers.error(serverT({ en: "Missing required field: name", fr: "Champ requis manquant : name" }));
|
|
4293
4585
|
const existing = mcpManagerForTools.getServer(args.name);
|
|
4294
|
-
if (!existing)
|
|
4586
|
+
if (!existing)
|
|
4587
|
+
return helpers.error(
|
|
4588
|
+
serverT(
|
|
4589
|
+
{ en: 'MCP server "{{name}}" not found', fr: "Serveur MCP \xAB {{name}} \xBB introuvable" },
|
|
4590
|
+
{ name: args.name ?? "" }
|
|
4591
|
+
)
|
|
4592
|
+
);
|
|
4295
4593
|
const globalConfig = await loadGlobalConfig(mcpConfigMode, mcpConfigPath);
|
|
4296
4594
|
const mcpServers = { ...globalConfig.mcpServers ?? {} };
|
|
4297
4595
|
const patch = {
|
|
@@ -4320,11 +4618,18 @@ var mcpConfigTool = createTool(
|
|
|
4320
4618
|
const server = mcpManagerForTools.getServer(args.name);
|
|
4321
4619
|
const toolCount = server?.tools.length ?? 0;
|
|
4322
4620
|
return helpers.success(
|
|
4323
|
-
|
|
4621
|
+
serverT(
|
|
4622
|
+
{
|
|
4623
|
+
en: 'Updated MCP server "{{name}}" ({{count}} tools discovered). {{prompt}}',
|
|
4624
|
+
fr: "Serveur MCP \xAB {{name}} \xBB mis \xE0 jour ({{count}} outils d\xE9couverts). {{prompt}}"
|
|
4625
|
+
},
|
|
4626
|
+
{ name: args.name ?? "", count: toolCount, prompt: APPLY_PROMPT_MESSAGE }
|
|
4627
|
+
)
|
|
4324
4628
|
);
|
|
4325
4629
|
}
|
|
4326
4630
|
if (args.action === "remove") {
|
|
4327
|
-
if (!args.name)
|
|
4631
|
+
if (!args.name)
|
|
4632
|
+
return helpers.error(serverT({ en: "Missing required field: name", fr: "Champ requis manquant : name" }));
|
|
4328
4633
|
await persistAndRebuild((mcpServers) => {
|
|
4329
4634
|
delete mcpServers[args.name];
|
|
4330
4635
|
return mcpServers;
|
|
@@ -4332,12 +4637,22 @@ var mcpConfigTool = createTool(
|
|
|
4332
4637
|
mcpManagerForTools.removeServer(args.name);
|
|
4333
4638
|
await rebuildTools();
|
|
4334
4639
|
await notifyContextChanged(context.sessionId);
|
|
4335
|
-
return helpers.success(
|
|
4640
|
+
return helpers.success(
|
|
4641
|
+
serverT(
|
|
4642
|
+
{ en: 'Removed MCP server "{{name}}". {{prompt}}', fr: "Serveur MCP \xAB {{name}} \xBB supprim\xE9. {{prompt}}" },
|
|
4643
|
+
{ name: args.name ?? "", prompt: APPLY_PROMPT_MESSAGE }
|
|
4644
|
+
)
|
|
4645
|
+
);
|
|
4336
4646
|
}
|
|
4337
4647
|
if (args.action === "toggle-tool") {
|
|
4338
|
-
if (!args.name)
|
|
4339
|
-
|
|
4340
|
-
if (args.
|
|
4648
|
+
if (!args.name)
|
|
4649
|
+
return helpers.error(serverT({ en: "Missing required field: name", fr: "Champ requis manquant : name" }));
|
|
4650
|
+
if (!args.toolName)
|
|
4651
|
+
return helpers.error(
|
|
4652
|
+
serverT({ en: "Missing required field: toolName", fr: "Champ requis manquant : toolName" })
|
|
4653
|
+
);
|
|
4654
|
+
if (args.enabled === void 0)
|
|
4655
|
+
return helpers.error(serverT({ en: "Missing required field: enabled", fr: "Champ requis manquant : enabled" }));
|
|
4341
4656
|
const server = mcpManagerForTools.getServer(args.name);
|
|
4342
4657
|
const currentDisabled = (server?.tools ?? []).filter((t) => !t.enabled).map((t) => t.name);
|
|
4343
4658
|
const afterDisabled = args.enabled ? currentDisabled.filter((n) => n !== args.toolName) : [...currentDisabled, args.toolName];
|
|
@@ -4358,10 +4673,21 @@ var mcpConfigTool = createTool(
|
|
|
4358
4673
|
await rebuildTools();
|
|
4359
4674
|
await notifyContextChanged(context.sessionId);
|
|
4360
4675
|
return helpers.success(
|
|
4361
|
-
|
|
4676
|
+
serverT(
|
|
4677
|
+
{
|
|
4678
|
+
en: 'Tool "{{tool}}" {{state}} on server "{{name}}". {{prompt}}',
|
|
4679
|
+
fr: "Outil \xAB {{tool}} \xBB {{state}} sur le serveur \xAB {{name}} \xBB. {{prompt}}"
|
|
4680
|
+
},
|
|
4681
|
+
{
|
|
4682
|
+
tool: args.toolName ?? "",
|
|
4683
|
+
state: args.enabled ? serverT({ en: "enabled", fr: "activ\xE9" }) : serverT({ en: "disabled", fr: "d\xE9sactiv\xE9" }),
|
|
4684
|
+
name: args.name ?? "",
|
|
4685
|
+
prompt: APPLY_PROMPT_MESSAGE
|
|
4686
|
+
}
|
|
4687
|
+
)
|
|
4362
4688
|
);
|
|
4363
4689
|
}
|
|
4364
|
-
return helpers.error("Unexpected error");
|
|
4690
|
+
return helpers.error(serverT({ en: "Unexpected error", fr: "Erreur inattendue" }));
|
|
4365
4691
|
}
|
|
4366
4692
|
);
|
|
4367
4693
|
|
|
@@ -4474,7 +4800,10 @@ var webSearchTool = createTool(
|
|
|
4474
4800
|
const active = getActiveEngine();
|
|
4475
4801
|
if (!active) {
|
|
4476
4802
|
return helpers.error(
|
|
4477
|
-
|
|
4803
|
+
serverT({
|
|
4804
|
+
en: "web_search requires at least one search engine configured. Set the TAVILY_API_KEY environment variable, or configure SearXNG via SEARXNG_URL (and optionally SEARXNG_API_KEY). You can also configure these in Settings > Advanced > Search Engine.",
|
|
4805
|
+
fr: "web_search n\xE9cessite au moins un moteur de recherche configur\xE9. D\xE9finissez la variable d\u2019environnement TAVILY_API_KEY, ou configurez SearXNG via SEARXNG_URL (et \xE9ventuellement SEARXNG_API_KEY). Vous pouvez aussi les configurer dans Param\xE8tres > Avanc\xE9 > Moteur de recherche."
|
|
4806
|
+
})
|
|
4478
4807
|
);
|
|
4479
4808
|
}
|
|
4480
4809
|
const signal = buildSignal(DEFAULT_TIMEOUT_MS2, context.signal);
|
|
@@ -4488,14 +4817,24 @@ var webSearchTool = createTool(
|
|
|
4488
4817
|
results = await searchSearxng(query, maxResults, searxngConfig, signal);
|
|
4489
4818
|
}
|
|
4490
4819
|
if (results.length === 0) {
|
|
4491
|
-
return helpers.success(
|
|
4820
|
+
return helpers.success(
|
|
4821
|
+
serverT({ en: "No search results found.", fr: "Aucun r\xE9sultat de recherche trouv\xE9." }),
|
|
4822
|
+
false
|
|
4823
|
+
);
|
|
4492
4824
|
}
|
|
4493
4825
|
return helpers.success(formatResults(results), false);
|
|
4494
4826
|
} catch (error) {
|
|
4495
4827
|
if (error instanceof DOMException && error.name === "AbortError") {
|
|
4496
|
-
return helpers.error(
|
|
4828
|
+
return helpers.error(
|
|
4829
|
+
serverT({
|
|
4830
|
+
en: "Search request timed out (15s). Try a more specific query.",
|
|
4831
|
+
fr: "La recherche a expir\xE9 (15 s). Essayez une requ\xEAte plus pr\xE9cise."
|
|
4832
|
+
})
|
|
4833
|
+
);
|
|
4497
4834
|
}
|
|
4498
|
-
return helpers.error(
|
|
4835
|
+
return helpers.error(
|
|
4836
|
+
error instanceof Error ? error.message : serverT({ en: "Search request failed", fr: "\xC9chec de la requ\xEAte de recherche" })
|
|
4837
|
+
);
|
|
4499
4838
|
}
|
|
4500
4839
|
}
|
|
4501
4840
|
);
|
|
@@ -4559,22 +4898,43 @@ Actions:
|
|
|
4559
4898
|
const { sessionId, sessionManager } = context;
|
|
4560
4899
|
const validActions = ["switch", "list", "delete"];
|
|
4561
4900
|
if (!validActions.includes(args.action)) {
|
|
4562
|
-
return helpers.error(
|
|
4901
|
+
return helpers.error(
|
|
4902
|
+
serverT(
|
|
4903
|
+
{
|
|
4904
|
+
en: "Invalid action: {{action}}. Must be one of: {{allowed}}",
|
|
4905
|
+
fr: "Action invalide : {{action}}. Doit \xEAtre l\u2019une des actions suivantes : {{allowed}}"
|
|
4906
|
+
},
|
|
4907
|
+
{ action: args.action, allowed: validActions.join(", ") }
|
|
4908
|
+
)
|
|
4909
|
+
);
|
|
4563
4910
|
}
|
|
4564
4911
|
switch (args.action) {
|
|
4565
4912
|
case "switch": {
|
|
4566
4913
|
if (!args.target || typeof args.target !== "string") {
|
|
4567
|
-
return helpers.error(
|
|
4914
|
+
return helpers.error(
|
|
4915
|
+
serverT({
|
|
4916
|
+
en: 'Parameter "target" is required for action=switch ("original" or a workspace name)',
|
|
4917
|
+
fr: "Le param\xE8tre \xAB target \xBB est requis pour action=switch (\xAB original \xBB ou un nom de workspace)"
|
|
4918
|
+
})
|
|
4919
|
+
);
|
|
4568
4920
|
}
|
|
4569
4921
|
if (await isGitRepository(context.workdir) === false) {
|
|
4570
|
-
return helpers.error(
|
|
4922
|
+
return helpers.error(
|
|
4923
|
+
serverT({ en: "Project is not a git repository", fr: "Le projet n\u2019est pas un d\xE9p\xF4t git" })
|
|
4924
|
+
);
|
|
4571
4925
|
}
|
|
4572
4926
|
const currentSession = sessionManager.getSession(sessionId);
|
|
4573
4927
|
const isBranchChange = args.branch !== void 0 && currentSession != null && args.target !== "original" && currentSession.workspace?.split("/").pop() === args.target;
|
|
4574
4928
|
const label = args.target === "original" ? "original project" : `workspace "${args.target}"`;
|
|
4575
4929
|
const desc = isBranchChange ? `Change branch to "${args.branch}" on ${label}` : `Switch to ${label}${args.branch ? ` on branch "${args.branch}"` : ""}`;
|
|
4576
4930
|
const approved = await requestUserConfirmation(context, "workspace", desc);
|
|
4577
|
-
if (!approved)
|
|
4931
|
+
if (!approved)
|
|
4932
|
+
return helpers.error(
|
|
4933
|
+
serverT(
|
|
4934
|
+
{ en: "User denied: {{what}}", fr: "Refus\xE9 par l\u2019utilisateur : {{what}}" },
|
|
4935
|
+
{ what: isBranchChange ? "branch change" : `switch to ${label}` }
|
|
4936
|
+
)
|
|
4937
|
+
);
|
|
4578
4938
|
const updated = await sessionManager.switchWorkspace(sessionId, args.target, args.branch, args.sourceBranch);
|
|
4579
4939
|
const wsName = args.target === "original" ? "original" : updated.workspace?.split("/").pop() ?? args.target;
|
|
4580
4940
|
const branch = await getGitBranch(updated.workspace ?? updated.workdir);
|
|
@@ -4584,7 +4944,13 @@ Actions:
|
|
|
4584
4944
|
workspace: wsName,
|
|
4585
4945
|
path: updated.workspace ?? updated.workdir,
|
|
4586
4946
|
branch,
|
|
4587
|
-
message: args.target === "original" ? "Switched to original project" :
|
|
4947
|
+
message: args.target === "original" ? serverT({ en: "Switched to original project", fr: "Basculement vers le projet d\u2019origine" }) : serverT(
|
|
4948
|
+
{
|
|
4949
|
+
en: 'Switched to workspace "{{name}}" on branch "{{branch}}"',
|
|
4950
|
+
fr: "Basculement vers le workspace \xAB {{name}} \xBB sur la branche \xAB {{branch}} \xBB"
|
|
4951
|
+
},
|
|
4952
|
+
{ name: wsName, branch: branch ?? "unknown" }
|
|
4953
|
+
)
|
|
4588
4954
|
},
|
|
4589
4955
|
null,
|
|
4590
4956
|
2
|
|
@@ -4593,9 +4959,9 @@ Actions:
|
|
|
4593
4959
|
}
|
|
4594
4960
|
case "list": {
|
|
4595
4961
|
const session = sessionManager.getSession(sessionId);
|
|
4596
|
-
if (!session) return helpers.error("Session not found");
|
|
4962
|
+
if (!session) return helpers.error(serverT({ en: "Session not found", fr: "Session introuvable" }));
|
|
4597
4963
|
const project = sessionManager.getProject(session.projectId);
|
|
4598
|
-
if (!project) return helpers.error("Project not found");
|
|
4964
|
+
if (!project) return helpers.error(serverT({ en: "Project not found", fr: "Projet introuvable" }));
|
|
4599
4965
|
const currentBranch = await getGitBranch(sessionManager.getEffectiveWorkdir(session.id));
|
|
4600
4966
|
const named = await listWorkspaces(project.name, project.workdir);
|
|
4601
4967
|
const activeWsName = session.workspace?.split("/").pop() ?? null;
|
|
@@ -4611,11 +4977,24 @@ Actions:
|
|
|
4611
4977
|
}
|
|
4612
4978
|
case "delete": {
|
|
4613
4979
|
if (!args.target || typeof args.target !== "string") {
|
|
4614
|
-
return helpers.error(
|
|
4980
|
+
return helpers.error(
|
|
4981
|
+
serverT({
|
|
4982
|
+
en: 'Parameter "target" is required for action=delete (the workspace name)',
|
|
4983
|
+
fr: "Le param\xE8tre \xAB target \xBB est requis pour action=delete (le nom du workspace)"
|
|
4984
|
+
})
|
|
4985
|
+
);
|
|
4615
4986
|
}
|
|
4616
|
-
if (args.target === "original")
|
|
4987
|
+
if (args.target === "original")
|
|
4988
|
+
return helpers.error(
|
|
4989
|
+
serverT({
|
|
4990
|
+
en: "Cannot delete the original workspace",
|
|
4991
|
+
fr: "Impossible de supprimer le workspace d\u2019origine"
|
|
4992
|
+
})
|
|
4993
|
+
);
|
|
4617
4994
|
if (await isGitRepository(context.workdir) === false) {
|
|
4618
|
-
return helpers.error(
|
|
4995
|
+
return helpers.error(
|
|
4996
|
+
serverT({ en: "Project is not a git repository", fr: "Le projet n\u2019est pas un d\xE9p\xF4t git" })
|
|
4997
|
+
);
|
|
4619
4998
|
}
|
|
4620
4999
|
const forceDesc = args.force ? " (will auto-switch other sessions to original)" : "";
|
|
4621
5000
|
const approved = await requestUserConfirmation(
|
|
@@ -4623,13 +5002,25 @@ Actions:
|
|
|
4623
5002
|
"workspace",
|
|
4624
5003
|
`Delete workspace "${args.target}"${forceDesc}`
|
|
4625
5004
|
);
|
|
4626
|
-
if (!approved)
|
|
5005
|
+
if (!approved)
|
|
5006
|
+
return helpers.error(
|
|
5007
|
+
serverT(
|
|
5008
|
+
{
|
|
5009
|
+
en: 'User denied: delete workspace "{{name}}"',
|
|
5010
|
+
fr: "Refus\xE9 par l\u2019utilisateur : supprimer le workspace \xAB {{name}} \xBB"
|
|
5011
|
+
},
|
|
5012
|
+
{ name: args.target }
|
|
5013
|
+
)
|
|
5014
|
+
);
|
|
4627
5015
|
await sessionManager.deleteWorkspace(sessionId, args.target, args.force === true);
|
|
4628
5016
|
return helpers.success(
|
|
4629
5017
|
JSON.stringify(
|
|
4630
5018
|
{
|
|
4631
5019
|
workspace: args.target,
|
|
4632
|
-
message:
|
|
5020
|
+
message: serverT(
|
|
5021
|
+
{ en: 'Workspace "{{name}}" has been deleted', fr: "Le workspace \xAB {{name}} \xBB a \xE9t\xE9 supprim\xE9" },
|
|
5022
|
+
{ name: args.target }
|
|
5023
|
+
)
|
|
4633
5024
|
},
|
|
4634
5025
|
null,
|
|
4635
5026
|
2
|
|
@@ -4637,7 +5028,9 @@ Actions:
|
|
|
4637
5028
|
);
|
|
4638
5029
|
}
|
|
4639
5030
|
default:
|
|
4640
|
-
return helpers.error(
|
|
5031
|
+
return helpers.error(
|
|
5032
|
+
serverT({ en: "Unknown action: {{action}}", fr: "Action inconnue : {{action}}" }, { action: args.action })
|
|
5033
|
+
);
|
|
4641
5034
|
}
|
|
4642
5035
|
}
|
|
4643
5036
|
);
|
|
@@ -4709,7 +5102,7 @@ var projectTasksTool = createTool(
|
|
|
4709
5102
|
const permError = validateActionWithPermission(action, VALID_ACTIONS, "project_tasks", context.permittedActions);
|
|
4710
5103
|
if (permError) return permError;
|
|
4711
5104
|
const session = context.sessionManager.getSession(context.sessionId);
|
|
4712
|
-
if (!session) return helpers.error("Session not found");
|
|
5105
|
+
if (!session) return helpers.error(serverT({ en: "Session not found", fr: "Session introuvable" }));
|
|
4713
5106
|
const projectId = session.projectId;
|
|
4714
5107
|
const svc = getTasksService();
|
|
4715
5108
|
const actor = { actor: "agent", actorName: "agent" };
|
|
@@ -4719,7 +5112,13 @@ var projectTasksTool = createTool(
|
|
|
4719
5112
|
const status = args.status;
|
|
4720
5113
|
if (status !== void 0 && !LIST_STATUSES.includes(status)) {
|
|
4721
5114
|
return helpers.error(
|
|
4722
|
-
|
|
5115
|
+
serverT(
|
|
5116
|
+
{
|
|
5117
|
+
en: 'Invalid "status" filter for action=list: "{{status}}". Expected one of: todo, in_progress, done, all.',
|
|
5118
|
+
fr: "Filtre \xAB status \xBB invalide pour action=list : \xAB {{status}} \xBB. Valeurs attendues : todo, in_progress, done, all."
|
|
5119
|
+
},
|
|
5120
|
+
{ status: String(status) }
|
|
5121
|
+
)
|
|
4723
5122
|
);
|
|
4724
5123
|
}
|
|
4725
5124
|
const page = parseListPage(args.limit, args.offset);
|
|
@@ -4758,7 +5157,13 @@ var projectTasksTool = createTool(
|
|
|
4758
5157
|
return helpers.success(JSON.stringify(taskForAgent(task), null, 2));
|
|
4759
5158
|
}
|
|
4760
5159
|
case "edit": {
|
|
4761
|
-
if (!args.taskId)
|
|
5160
|
+
if (!args.taskId)
|
|
5161
|
+
return helpers.error(
|
|
5162
|
+
serverT({
|
|
5163
|
+
en: 'Parameter "taskId" is required for action=edit',
|
|
5164
|
+
fr: "Le param\xE8tre \xAB taskId \xBB est requis pour action=edit"
|
|
5165
|
+
})
|
|
5166
|
+
);
|
|
4762
5167
|
const result = await svc.update(
|
|
4763
5168
|
projectId,
|
|
4764
5169
|
args.taskId,
|
|
@@ -4775,9 +5180,20 @@ var projectTasksTool = createTool(
|
|
|
4775
5180
|
return helpers.success(JSON.stringify(taskForAgent(result.task), null, 2));
|
|
4776
5181
|
}
|
|
4777
5182
|
case "move": {
|
|
4778
|
-
if (!args.taskId)
|
|
5183
|
+
if (!args.taskId)
|
|
5184
|
+
return helpers.error(
|
|
5185
|
+
serverT({
|
|
5186
|
+
en: 'Parameter "taskId" is required for action=move',
|
|
5187
|
+
fr: "Le param\xE8tre \xAB taskId \xBB est requis pour action=move"
|
|
5188
|
+
})
|
|
5189
|
+
);
|
|
4779
5190
|
if (!args.to)
|
|
4780
|
-
return helpers.error(
|
|
5191
|
+
return helpers.error(
|
|
5192
|
+
serverT({
|
|
5193
|
+
en: 'Parameter "to" is required for action=move ("todo" | "in_progress" | "done")',
|
|
5194
|
+
fr: "Le param\xE8tre \xAB to \xBB est requis pour action=move (\xAB todo \xBB | \xAB in_progress \xBB | \xAB done \xBB)"
|
|
5195
|
+
})
|
|
5196
|
+
);
|
|
4781
5197
|
const result = await svc.move(projectId, args.taskId, args.to, {
|
|
4782
5198
|
actor: "agent",
|
|
4783
5199
|
actorName: "agent",
|
|
@@ -4788,9 +5204,27 @@ var projectTasksTool = createTool(
|
|
|
4788
5204
|
return helpers.success(JSON.stringify(taskForAgent(result.task), null, 2));
|
|
4789
5205
|
}
|
|
4790
5206
|
case "set_gate_value": {
|
|
4791
|
-
if (!args.taskId)
|
|
4792
|
-
|
|
4793
|
-
|
|
5207
|
+
if (!args.taskId)
|
|
5208
|
+
return helpers.error(
|
|
5209
|
+
serverT({
|
|
5210
|
+
en: 'Parameter "taskId" is required for action=set_gate_value',
|
|
5211
|
+
fr: "Le param\xE8tre \xAB taskId \xBB est requis pour action=set_gate_value"
|
|
5212
|
+
})
|
|
5213
|
+
);
|
|
5214
|
+
if (!args.gateId)
|
|
5215
|
+
return helpers.error(
|
|
5216
|
+
serverT({
|
|
5217
|
+
en: 'Parameter "gateId" is required for action=set_gate_value',
|
|
5218
|
+
fr: "Le param\xE8tre \xAB gateId \xBB est requis pour action=set_gate_value"
|
|
5219
|
+
})
|
|
5220
|
+
);
|
|
5221
|
+
if (args.value === void 0)
|
|
5222
|
+
return helpers.error(
|
|
5223
|
+
serverT({
|
|
5224
|
+
en: 'Parameter "value" is required for action=set_gate_value',
|
|
5225
|
+
fr: "Le param\xE8tre \xAB value \xBB est requis pour action=set_gate_value"
|
|
5226
|
+
})
|
|
5227
|
+
);
|
|
4794
5228
|
const result = await svc.setGateValue(
|
|
4795
5229
|
projectId,
|
|
4796
5230
|
args.taskId,
|
|
@@ -4803,9 +5237,18 @@ var projectTasksTool = createTool(
|
|
|
4803
5237
|
return helpers.success(JSON.stringify(taskForAgent(result.task), null, 2));
|
|
4804
5238
|
}
|
|
4805
5239
|
case "delete": {
|
|
4806
|
-
if (!args.taskId)
|
|
5240
|
+
if (!args.taskId)
|
|
5241
|
+
return helpers.error(
|
|
5242
|
+
serverT({
|
|
5243
|
+
en: 'Parameter "taskId" is required for action=delete',
|
|
5244
|
+
fr: "Le param\xE8tre \xAB taskId \xBB est requis pour action=delete"
|
|
5245
|
+
})
|
|
5246
|
+
);
|
|
4807
5247
|
const task = svc.get(projectId, args.taskId);
|
|
4808
|
-
if (!task)
|
|
5248
|
+
if (!task)
|
|
5249
|
+
return helpers.error(
|
|
5250
|
+
serverT({ en: "Task not found: {{id}}", fr: "T\xE2che introuvable : {{id}}" }, { id: args.taskId ?? "" })
|
|
5251
|
+
);
|
|
4809
5252
|
await svc.remove(projectId, args.taskId, actor);
|
|
4810
5253
|
return helpers.success(
|
|
4811
5254
|
JSON.stringify(
|
|
@@ -4816,18 +5259,32 @@ var projectTasksTool = createTool(
|
|
|
4816
5259
|
);
|
|
4817
5260
|
}
|
|
4818
5261
|
default:
|
|
4819
|
-
return helpers.error(
|
|
5262
|
+
return helpers.error(
|
|
5263
|
+
serverT(
|
|
5264
|
+
{ en: "Unknown action: {{action}}", fr: "Action inconnue : {{action}}" },
|
|
5265
|
+
{ action: String(action) }
|
|
5266
|
+
)
|
|
5267
|
+
);
|
|
4820
5268
|
}
|
|
4821
5269
|
} catch (error) {
|
|
4822
5270
|
if (isTaskGateError(error)) {
|
|
4823
5271
|
const missing = error.missing.map((m) => `'${m.name}' (${m.gateId}): ${m.description}`).join("; ");
|
|
4824
5272
|
return helpers.error(
|
|
4825
|
-
|
|
5273
|
+
serverT(
|
|
5274
|
+
{
|
|
5275
|
+
en: "Move blocked by column gates. Missing required gate fields: {{missing}}. Fill them with action=set_gate_value (taskId, gateId, value=<acceptable proof>) and then call move again. You set these values as part of your work \u2014 this is the intended loop, not a dead end.",
|
|
5276
|
+
fr: "D\xE9placement bloqu\xE9 par les portes de colonne. Champs de porte requis manquants : {{missing}}. Renseignez-les avec action=set_gate_value (taskId, gateId, value=<preuve acceptable>) puis appelez \xE0 nouveau move. Vous d\xE9finissez ces valeurs dans le cadre de votre travail \u2014 c\u2019est la boucle pr\xE9vue, pas une impasse."
|
|
5277
|
+
},
|
|
5278
|
+
{ missing }
|
|
5279
|
+
)
|
|
4826
5280
|
);
|
|
4827
5281
|
}
|
|
4828
5282
|
if (isTaskConflictError(error)) {
|
|
4829
5283
|
return helpers.error(
|
|
4830
|
-
|
|
5284
|
+
serverT({
|
|
5285
|
+
en: "Task changed, refresh and retry. Another actor modified this task since your last read. Re-list and retry with the latest updatedAt.",
|
|
5286
|
+
fr: "T\xE2che modifi\xE9e, actualisez et r\xE9essayez. Un autre acteur a modifi\xE9 cette t\xE2che depuis votre derni\xE8re lecture. Re-listez et r\xE9essayez avec le updatedAt le plus r\xE9cent."
|
|
5287
|
+
})
|
|
4831
5288
|
);
|
|
4832
5289
|
}
|
|
4833
5290
|
throw error;
|
|
@@ -5158,4 +5615,4 @@ export {
|
|
|
5158
5615
|
getToolRegistryForAgent,
|
|
5159
5616
|
createToolRegistry
|
|
5160
5617
|
};
|
|
5161
|
-
//# sourceMappingURL=chunk-
|
|
5618
|
+
//# sourceMappingURL=chunk-ESZQTFQP.js.map
|