openfox 1.6.75 → 1.6.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -18
- package/dist/agent-defaults/code-reviewer.agent.md +1 -0
- package/dist/agent-defaults/explorer.agent.md +2 -1
- package/dist/agent-defaults/verifier.agent.md +4 -0
- package/dist/{ask-3RK5YJZE.js → ask-5SSOA6SZ.js} +2 -2
- package/dist/{auth-LZZX63KI.js → auth-56SIRACI.js} +3 -6
- package/dist/auto-compaction-GOHNI2R2.js +27 -0
- package/dist/{branch.api-XADFZZAA.js → branch.api-PWFW26KC.js} +2 -2
- package/dist/{chat-handler-KYMMXPP6.js → chat-handler-K2RDXBO6.js} +31 -29
- package/dist/{chunk-IA4O65CR.js → chunk-6SYNGMU4.js} +100 -68
- package/dist/{chunk-AFATQ5LJ.js → chunk-B5AP3RSV.js} +1 -1
- package/dist/{chunk-PFRQO5Z3.js → chunk-BBC46FN4.js} +61 -28
- package/dist/{chunk-22CTURMH.js → chunk-BJYPTN5S.js} +1 -1
- package/dist/{chunk-DLINTLB7.js → chunk-BSTVRSV6.js} +7 -5
- package/dist/{chunk-7JPKRM6M.js → chunk-CMQCO27Y.js} +22 -12
- package/dist/{chunk-R4HADRYO.js → chunk-CQGTEGKL.js} +1 -1
- package/dist/{chunk-J5DV33SS.js → chunk-CUDAT6SS.js} +46 -18
- package/dist/{chunk-ETIXH35K.js → chunk-EBQYRNNU.js} +535 -291
- package/dist/{chunk-4CQ7CUQ6.js → chunk-I7JVS7V5.js} +5 -5
- package/dist/{chunk-PNBH3RAX.js → chunk-K44MW7JJ.js} +1 -1
- package/dist/{chunk-BLNFJ22S.js → chunk-KIOUKC3Z.js} +6 -4
- package/dist/{chunk-CTAIXOZJ.js → chunk-NDJ6FKSP.js} +1 -1
- package/dist/{chunk-VIGOXEZG.js → chunk-OJBFC6ER.js} +15 -16
- package/dist/{chunk-GQZGIMJO.js → chunk-OXI26S7U.js} +12 -7
- package/dist/{chunk-NBU6KIOD.js → chunk-PBGOZMVY.js} +4 -4
- package/dist/{chunk-B7E3BICY.js → chunk-RGRBWDZP.js} +2 -4
- package/dist/{chunk-KFBIHS3S.js → chunk-STYHKCG7.js} +20 -14
- package/dist/{chunk-55Z3DJ7G.js → chunk-TGWEH2BC.js} +10 -11
- package/dist/{chunk-TYUNDOX2.js → chunk-UKMRZDWM.js} +90 -41
- package/dist/{chunk-5UTTLO4D.js → chunk-UVN6AKIO.js} +89 -49
- package/dist/{chunk-574HZVLE.js → chunk-VRGRAQDG.js} +2 -2
- package/dist/{chunk-JQBTYHUR.js → chunk-WR6QCJJO.js} +53 -15
- package/dist/{chunk-RBPOAAIZ.js → chunk-XKIEDGQF.js} +22 -18
- package/dist/{chunk-XIZ6B6IS.js → chunk-XSUQDB6R.js} +541 -299
- package/dist/cli/dev.js +2 -2
- package/dist/cli/index.js +2 -2
- package/dist/{config-6T4EHAP2.js → config-5CONAOL7.js} +7 -7
- package/dist/{events-LKEZ3YCW.js → events-5RIXWI5Y.js} +6 -6
- package/dist/{folding-JN2WT44N.js → folding-JNOUTI5Z.js} +2 -2
- package/dist/{inspect-proxy-Y4MRAVB7.js → inspect-proxy-Y75AXMRX.js} +3 -3
- package/dist/{manager-HM2J5VMW.js → manager-W7N3XQ4Q.js} +3 -3
- package/dist/orchestrator-TW5II347.js +43 -0
- package/dist/package.json +19 -3
- package/dist/{paths-ZRI56O63.js → paths-X46PPOI2.js} +2 -2
- package/dist/{processor-23O4HPSS.js → processor-MZ3QIUED.js} +15 -11
- package/dist/{project-creator-LASKNQPA.js → project-creator-VD7MLOWE.js} +8 -5
- package/dist/{projects-HEUOWNSR.js → projects-XLMSDFTQ.js} +4 -4
- package/dist/{protocol-5AWNGFLH.js → protocol-4CTV7OZC.js} +3 -3
- package/dist/{protocol-DRBnujwe.d.ts → protocol-4xbfAlGO.d.ts} +3 -0
- package/dist/{provider-AKN355YH.js → provider-ESEBV3LL.js} +15 -11
- package/dist/{pwa-GHQCMCIU.js → pwa-76XP2DY2.js} +2 -2
- package/dist/{runtime-config-ZCK74XKM.js → runtime-config-CBJJJGBD.js} +2 -2
- package/dist/{serve-TW63YCNQ.js → serve-FTTLGRAO.js} +29 -27
- package/dist/server/index.d.ts +6 -1
- package/dist/server/index.js +22 -22
- package/dist/server/public/__inspect__.js +163 -143
- package/dist/{service-74Z7JK2J.js → service-D6LC3CAM.js} +3 -2
- package/dist/{settings-NI4ITGV6.js → settings-TQNQB56H.js} +4 -4
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +2 -2
- package/dist/{store-2IF3ZSLD.js → store-OQ45KONN.js} +2 -2
- package/dist/{tools-RUAY6EVI.js → tools-QJ5K5IJP.js} +18 -18
- package/dist/{vision-fallback-AXH3BGJC.js → vision-fallback-ED27LH6C.js} +3 -3
- package/dist/web/__inspect__.js +178 -155
- package/dist/web/assets/{index-CWdKiSP8.js → index-FjLp1t6r.js} +62 -62
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +19 -3
- package/dist/auto-compaction-OW4P2QWQ.js +0 -27
- package/dist/orchestrator-QP4O7MUM.js +0 -43
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
deleteSetting,
|
|
4
4
|
getSetting,
|
|
5
5
|
setSetting
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OXI26S7U.js";
|
|
7
7
|
import {
|
|
8
8
|
getProject
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CMQCO27Y.js";
|
|
10
10
|
import {
|
|
11
11
|
startInspectProxy
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XKIEDGQF.js";
|
|
13
13
|
import {
|
|
14
14
|
createProcess,
|
|
15
15
|
getPlatformShell,
|
|
@@ -18,22 +18,22 @@ import {
|
|
|
18
18
|
getSessionProcesses,
|
|
19
19
|
startProcessCommand,
|
|
20
20
|
stopProcess
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PBGOZMVY.js";
|
|
22
22
|
import {
|
|
23
23
|
getMaxPerSession,
|
|
24
24
|
getSessionProcessCount
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-VRGRAQDG.js";
|
|
26
26
|
import {
|
|
27
27
|
buildModelParams,
|
|
28
28
|
getBackendCapabilities,
|
|
29
29
|
getModelProfile,
|
|
30
30
|
streamWithSegments
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-CUDAT6SS.js";
|
|
32
32
|
import {
|
|
33
33
|
getContextMessages,
|
|
34
34
|
getCurrentContextWindowId,
|
|
35
35
|
getEventStore
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-UVN6AKIO.js";
|
|
37
37
|
import {
|
|
38
38
|
createChatDoneMessage,
|
|
39
39
|
createChatMessageMessage,
|
|
@@ -42,20 +42,20 @@ import {
|
|
|
42
42
|
createChatToolOutputMessage,
|
|
43
43
|
createChatVisionFallbackMessage,
|
|
44
44
|
createQueueStateMessage
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-STYHKCG7.js";
|
|
46
46
|
import {
|
|
47
47
|
AskUserInterrupt,
|
|
48
48
|
askUserTool
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-BJYPTN5S.js";
|
|
50
50
|
import {
|
|
51
51
|
getGlobalConfigDir
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-CQGTEGKL.js";
|
|
53
53
|
import {
|
|
54
54
|
getRuntimeConfig
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-B5AP3RSV.js";
|
|
56
56
|
import {
|
|
57
57
|
logger
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-K44MW7JJ.js";
|
|
59
59
|
|
|
60
60
|
// src/server/context/instructions.ts
|
|
61
61
|
import { readFile, access } from "fs/promises";
|
|
@@ -147,6 +147,13 @@ async function fileExists(path) {
|
|
|
147
147
|
return false;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
function toInjectedFiles(files) {
|
|
151
|
+
return files.map((file) => ({
|
|
152
|
+
path: file.path,
|
|
153
|
+
content: file.content ?? "",
|
|
154
|
+
source: file.source
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
150
157
|
|
|
151
158
|
// src/server/context/compactor.ts
|
|
152
159
|
function shouldCompact(currentTokens, maxTokens, threshold) {
|
|
@@ -403,6 +410,7 @@ function minimalMessageToRequestContextMessage(message, source = "history") {
|
|
|
403
410
|
role: message.role,
|
|
404
411
|
content: message.content,
|
|
405
412
|
source,
|
|
413
|
+
...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
|
|
406
414
|
...spreadMessageProps(message)
|
|
407
415
|
};
|
|
408
416
|
}
|
|
@@ -410,6 +418,7 @@ function messageToMinimal(message) {
|
|
|
410
418
|
return {
|
|
411
419
|
role: message.role,
|
|
412
420
|
content: message.content,
|
|
421
|
+
...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
|
|
413
422
|
...spreadMessageProps(message)
|
|
414
423
|
};
|
|
415
424
|
}
|
|
@@ -475,12 +484,7 @@ function buildAssemblyInput(systemPrompt, baseInput) {
|
|
|
475
484
|
function assembleAgentRequest(input) {
|
|
476
485
|
const { agentDef, subAgentDefs, ...baseInput } = input;
|
|
477
486
|
if (agentDef.metadata.subagent) {
|
|
478
|
-
const systemPrompt2 = buildSubAgentSystemPrompt(
|
|
479
|
-
baseInput.workdir,
|
|
480
|
-
agentDef,
|
|
481
|
-
baseInput.skills,
|
|
482
|
-
baseInput.modelName
|
|
483
|
-
);
|
|
487
|
+
const systemPrompt2 = buildSubAgentSystemPrompt(baseInput.workdir, agentDef, baseInput.skills, baseInput.modelName);
|
|
484
488
|
return buildAssemblyInput(systemPrompt2, baseInput);
|
|
485
489
|
}
|
|
486
490
|
const systemPrompt = buildTopLevelSystemPrompt(
|
|
@@ -495,7 +499,16 @@ function assembleAgentRequest(input) {
|
|
|
495
499
|
|
|
496
500
|
// src/server/chat/stream-utils.ts
|
|
497
501
|
function buildStreamRequestObject(params) {
|
|
498
|
-
const {
|
|
502
|
+
const {
|
|
503
|
+
messages,
|
|
504
|
+
tools,
|
|
505
|
+
toolChoice,
|
|
506
|
+
disableThinking,
|
|
507
|
+
signal,
|
|
508
|
+
modelSettings,
|
|
509
|
+
onVisionFallbackStart,
|
|
510
|
+
onVisionFallbackDone
|
|
511
|
+
} = params;
|
|
499
512
|
const streamRequest = {
|
|
500
513
|
messages,
|
|
501
514
|
...tools && { tools },
|
|
@@ -515,7 +528,17 @@ function buildStreamRequest(client, options) {
|
|
|
515
528
|
// src/server/chat/stats.ts
|
|
516
529
|
var roundTo1 = (n) => Math.round(n * 10) / 10;
|
|
517
530
|
function computeAggregatedStats(input) {
|
|
518
|
-
const {
|
|
531
|
+
const {
|
|
532
|
+
identity,
|
|
533
|
+
mode,
|
|
534
|
+
totalPrefillTokens,
|
|
535
|
+
totalGenTokens,
|
|
536
|
+
totalPrefillTime,
|
|
537
|
+
totalGenTime,
|
|
538
|
+
totalToolTime,
|
|
539
|
+
totalTime,
|
|
540
|
+
llmCalls
|
|
541
|
+
} = input;
|
|
519
542
|
return {
|
|
520
543
|
...identity,
|
|
521
544
|
mode,
|
|
@@ -530,6 +553,25 @@ function computeAggregatedStats(input) {
|
|
|
530
553
|
}
|
|
531
554
|
|
|
532
555
|
// src/server/chat/stream-pure.ts
|
|
556
|
+
function toStreamMessages(messages) {
|
|
557
|
+
return messages.map((m) => ({
|
|
558
|
+
role: m.role,
|
|
559
|
+
content: m.content,
|
|
560
|
+
...m.thinkingContent ? { thinkingContent: m.thinkingContent } : {},
|
|
561
|
+
...m.toolCalls?.length ? { toolCalls: m.toolCalls.map((tc) => ({ id: tc.id, name: tc.name, arguments: tc.arguments })) } : {},
|
|
562
|
+
...m.toolCallId ? { toolCallId: m.toolCallId } : {},
|
|
563
|
+
...m.attachments?.length ? { attachments: m.attachments } : {}
|
|
564
|
+
}));
|
|
565
|
+
}
|
|
566
|
+
function createAssistantMessage(content, thinkingContent, toolCalls) {
|
|
567
|
+
return {
|
|
568
|
+
role: "assistant",
|
|
569
|
+
content,
|
|
570
|
+
source: "history",
|
|
571
|
+
...thinkingContent ? { thinkingContent } : {},
|
|
572
|
+
...toolCalls.length > 0 ? { toolCalls } : {}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
533
575
|
function createEmptyStreamResult(aborted, xmlFormatError, modelParams) {
|
|
534
576
|
return {
|
|
535
577
|
content: "",
|
|
@@ -543,7 +585,18 @@ function createEmptyStreamResult(aborted, xmlFormatError, modelParams) {
|
|
|
543
585
|
};
|
|
544
586
|
}
|
|
545
587
|
async function* streamLLMPure(options) {
|
|
546
|
-
const {
|
|
588
|
+
const {
|
|
589
|
+
messageId,
|
|
590
|
+
systemPrompt,
|
|
591
|
+
llmClient,
|
|
592
|
+
messages,
|
|
593
|
+
tools,
|
|
594
|
+
toolChoice,
|
|
595
|
+
signal,
|
|
596
|
+
disableThinking,
|
|
597
|
+
onVisionFallbackStart,
|
|
598
|
+
onVisionFallbackDone
|
|
599
|
+
} = options;
|
|
547
600
|
const llmMessages = [{ role: "system", content: systemPrompt }, ...messages];
|
|
548
601
|
const profile = getModelProfile(llmClient.getModel());
|
|
549
602
|
const backend = getBackendCapabilities(llmClient.getBackend());
|
|
@@ -584,6 +637,7 @@ async function* streamLLMPure(options) {
|
|
|
584
637
|
const toolNames = /* @__PURE__ */ new Map();
|
|
585
638
|
const toolIds = /* @__PURE__ */ new Map();
|
|
586
639
|
const returnValueArgs = /* @__PURE__ */ new Map();
|
|
640
|
+
const toolArgs = /* @__PURE__ */ new Map();
|
|
587
641
|
let result = null;
|
|
588
642
|
let aborted = false;
|
|
589
643
|
let xmlFormatError = false;
|
|
@@ -619,13 +673,34 @@ async function* streamLLMPure(options) {
|
|
|
619
673
|
if (value.id) {
|
|
620
674
|
toolIds.set(value.index, value.id);
|
|
621
675
|
}
|
|
676
|
+
if (value.arguments) {
|
|
677
|
+
const existingArgs = toolArgs.get(value.index) ?? "";
|
|
678
|
+
toolArgs.set(value.index, existingArgs + value.arguments);
|
|
679
|
+
}
|
|
622
680
|
const fullName = toolNames.get(value.index);
|
|
623
681
|
if (!seenToolIndices.has(value.index) && fullName) {
|
|
624
682
|
seenToolIndices.add(value.index);
|
|
683
|
+
const accumulatedArgs = toolArgs.get(value.index);
|
|
625
684
|
yield {
|
|
626
685
|
type: "tool.preparing",
|
|
627
|
-
data: {
|
|
686
|
+
data: {
|
|
687
|
+
messageId,
|
|
688
|
+
index: value.index,
|
|
689
|
+
name: fullName,
|
|
690
|
+
...accumulatedArgs ? { arguments: accumulatedArgs } : {}
|
|
691
|
+
}
|
|
628
692
|
};
|
|
693
|
+
} else if (seenToolIndices.has(value.index) && value.arguments) {
|
|
694
|
+
const name = toolNames.get(value.index);
|
|
695
|
+
if (name === "run_command" || name === "return_value") {
|
|
696
|
+
const accumulatedArgs = toolArgs.get(value.index);
|
|
697
|
+
if (accumulatedArgs) {
|
|
698
|
+
yield {
|
|
699
|
+
type: "tool.preparing",
|
|
700
|
+
data: { messageId, index: value.index, name, arguments: accumulatedArgs }
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
}
|
|
629
704
|
}
|
|
630
705
|
if (fullName === "return_value" && value.arguments) {
|
|
631
706
|
const toolCallId = toolIds.get(value.index);
|
|
@@ -884,10 +959,12 @@ async function consumeStreamWithToolLoop(options) {
|
|
|
884
959
|
turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens, result.modelParams);
|
|
885
960
|
if (result.toolCalls.length > 0) {
|
|
886
961
|
const stats = turnMetrics.buildStats(statsIdentity, "compaction");
|
|
887
|
-
onEvent(
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
962
|
+
onEvent(
|
|
963
|
+
createMessageDoneEvent(messageId, {
|
|
964
|
+
segments: result.segments,
|
|
965
|
+
stats
|
|
966
|
+
})
|
|
967
|
+
);
|
|
891
968
|
const toolContext = {
|
|
892
969
|
sessionId,
|
|
893
970
|
workdir,
|
|
@@ -910,6 +987,7 @@ async function consumeStreamWithToolLoop(options) {
|
|
|
910
987
|
currentMessages.push({
|
|
911
988
|
role: "assistant",
|
|
912
989
|
content: result.content,
|
|
990
|
+
...result.thinkingContent ? { thinkingContent: result.thinkingContent } : {},
|
|
913
991
|
toolCalls: result.toolCalls
|
|
914
992
|
});
|
|
915
993
|
continue;
|
|
@@ -1036,10 +1114,7 @@ async function loadUserAgents(configDir) {
|
|
|
1036
1114
|
return loadAgentsFromDir(getAgentsDir(configDir));
|
|
1037
1115
|
}
|
|
1038
1116
|
async function loadAllAgents(configDir) {
|
|
1039
|
-
const [defaultAgents, userAgents] = await Promise.all([
|
|
1040
|
-
loadDefaultAgents(),
|
|
1041
|
-
loadUserAgents(configDir)
|
|
1042
|
-
]);
|
|
1117
|
+
const [defaultAgents, userAgents] = await Promise.all([loadDefaultAgents(), loadUserAgents(configDir)]);
|
|
1043
1118
|
const agentMap = /* @__PURE__ */ new Map();
|
|
1044
1119
|
for (const agent of defaultAgents) {
|
|
1045
1120
|
agentMap.set(agent.metadata.id, agent);
|
|
@@ -1077,10 +1152,7 @@ async function isDefaultAgent(agentId) {
|
|
|
1077
1152
|
}
|
|
1078
1153
|
function getAgentFilePaths(agentsDir, agentId) {
|
|
1079
1154
|
const hyphenated = agentId.replace(/_/g, "-");
|
|
1080
|
-
return [
|
|
1081
|
-
join2(agentsDir, `${agentId}${AGENT_EXTENSION}`),
|
|
1082
|
-
join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)
|
|
1083
|
-
];
|
|
1155
|
+
return [join2(agentsDir, `${agentId}${AGENT_EXTENSION}`), join2(agentsDir, `${hyphenated}${AGENT_EXTENSION}`)];
|
|
1084
1156
|
}
|
|
1085
1157
|
function findAgentById(agentId, agents) {
|
|
1086
1158
|
return agents.find((a) => a.metadata.id === agentId);
|
|
@@ -1171,11 +1243,7 @@ var SAFE_PATHS = /* @__PURE__ */ new Set([
|
|
|
1171
1243
|
"/dev/fd/1",
|
|
1172
1244
|
"/dev/fd/2"
|
|
1173
1245
|
]);
|
|
1174
|
-
var ALLOWED_ROOTS = [
|
|
1175
|
-
"/tmp",
|
|
1176
|
-
"/var/tmp",
|
|
1177
|
-
tmpdir()
|
|
1178
|
-
];
|
|
1246
|
+
var ALLOWED_ROOTS = ["/tmp", "/var/tmp", tmpdir()];
|
|
1179
1247
|
var SENSITIVE_FILE_PATTERNS = [
|
|
1180
1248
|
// Dotenv files (but not .envrc, .env-example, .env.example)
|
|
1181
1249
|
/^\.env$/,
|
|
@@ -1261,7 +1329,7 @@ function extractAbsolutePathsFromCommand(command) {
|
|
|
1261
1329
|
const paths = [];
|
|
1262
1330
|
const home = homedir();
|
|
1263
1331
|
let sanitized = command.replace(/https?:\/\/[^\s'"]+/g, " __URL__ ").replace(/ftp:\/\/[^\s'"]+/g, " __URL__ ");
|
|
1264
|
-
sanitized = sanitized.replace(/s\/[
|
|
1332
|
+
sanitized = sanitized.replace(/s\/[^/]*\/[^/]*\/[gip]*/g, " __SED__ ");
|
|
1265
1333
|
sanitized = sanitized.replace(/s\|[^|]*\|[^|]*\|[gip]*/g, " __SED__ ");
|
|
1266
1334
|
sanitized = sanitized.replace(/s:[^:]*:[^:]*:[gip]*/g, " __SED__ ");
|
|
1267
1335
|
const fileUrlMatches = command.matchAll(/file:\/\/([^\s'"]+)/g);
|
|
@@ -1371,7 +1439,7 @@ async function checkPathsAccess(paths, workdir, sessionId) {
|
|
|
1371
1439
|
}
|
|
1372
1440
|
var DANGEROUS_PATTERNS = [
|
|
1373
1441
|
/sudo\s/,
|
|
1374
|
-
/rm\s+(-rf?|--recursive)\s+[
|
|
1442
|
+
/rm\s+(-rf?|--recursive)\s+[~]/,
|
|
1375
1443
|
/chmod\s+777/,
|
|
1376
1444
|
/>\s*\/dev\/sd/,
|
|
1377
1445
|
/mkfs\s/,
|
|
@@ -1387,9 +1455,20 @@ function extractDangerousPatterns(command) {
|
|
|
1387
1455
|
}
|
|
1388
1456
|
return dangerous;
|
|
1389
1457
|
}
|
|
1390
|
-
var GIT_NO_VERIFY_PATTERN = /\bgit\s+\w+\s+.*(?:--no-verify|-n)/;
|
|
1391
1458
|
function extractGitNoVerify(command) {
|
|
1392
|
-
|
|
1459
|
+
const parts = command.split(/\s+/);
|
|
1460
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1461
|
+
if (parts[i] === "git") {
|
|
1462
|
+
const sub = parts[i + 1];
|
|
1463
|
+
if (sub && !sub.startsWith("-")) {
|
|
1464
|
+
const args = parts.slice(i + 2);
|
|
1465
|
+
if (args.includes("--no-verify") || args.includes("-n")) {
|
|
1466
|
+
return true;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
return false;
|
|
1393
1472
|
}
|
|
1394
1473
|
async function requestPathAccess(paths, workdir, sessionId, callId, tool, onEvent, dangerLevel, command) {
|
|
1395
1474
|
const emitPendingEvent = (confirmationPaths, confirmationReason) => {
|
|
@@ -1421,7 +1500,9 @@ async function requestPathAccess(paths, workdir, sessionId, callId, tool, onEven
|
|
|
1421
1500
|
if (dangerousPatterns.length > 0) {
|
|
1422
1501
|
emitPendingEvent([workdir], "dangerous_command");
|
|
1423
1502
|
const confirmationPromise2 = registerPathConfirmation(callId, [workdir], sessionId);
|
|
1424
|
-
onEvent(
|
|
1503
|
+
onEvent(
|
|
1504
|
+
createChatPathConfirmationMessage(callId, tool, [dangerousPatterns.join(", ")], workdir, "dangerous_command")
|
|
1505
|
+
);
|
|
1425
1506
|
const approved2 = await confirmationPromise2;
|
|
1426
1507
|
if (!approved2) {
|
|
1427
1508
|
throw new PathAccessDeniedError(dangerousPatterns, tool, "dangerous_command");
|
|
@@ -1477,7 +1558,7 @@ function providePathConfirmation(callId, approved, alwaysAllow) {
|
|
|
1477
1558
|
type: "path.confirmation_responded",
|
|
1478
1559
|
data: { callId, approved, alwaysAllow: alwaysAllow ?? false }
|
|
1479
1560
|
});
|
|
1480
|
-
} catch
|
|
1561
|
+
} catch {
|
|
1481
1562
|
}
|
|
1482
1563
|
if (approved) {
|
|
1483
1564
|
if (alwaysAllow) {
|
|
@@ -1602,7 +1683,9 @@ var FileNotReadError = class extends Error {
|
|
|
1602
1683
|
};
|
|
1603
1684
|
var FileChangedExternallyError = class extends Error {
|
|
1604
1685
|
constructor(path) {
|
|
1605
|
-
super(
|
|
1686
|
+
super(
|
|
1687
|
+
`File "${path}" was modified externally and must be read before writing. Use read_file to see current contents.`
|
|
1688
|
+
);
|
|
1606
1689
|
this.name = "FileChangedExternallyError";
|
|
1607
1690
|
}
|
|
1608
1691
|
};
|
|
@@ -1655,7 +1738,11 @@ var IMAGE_MIME_TYPES = {
|
|
|
1655
1738
|
".svg": "image/svg+xml"
|
|
1656
1739
|
};
|
|
1657
1740
|
var IMAGE_SIGNATURES = [
|
|
1658
|
-
{
|
|
1741
|
+
{
|
|
1742
|
+
mimeType: "image/png",
|
|
1743
|
+
signature: Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
1744
|
+
extension: ".png"
|
|
1745
|
+
},
|
|
1659
1746
|
{ mimeType: "image/jpeg", signature: Buffer.from([255, 216, 255]), extension: ".jpg" },
|
|
1660
1747
|
{ mimeType: "image/gif", signature: Buffer.from([71, 73, 70, 56]), extension: ".gif" },
|
|
1661
1748
|
{ mimeType: "image/webp", signature: Buffer.from([]), extension: ".webp" },
|
|
@@ -1723,10 +1810,7 @@ var readFileTool = createTool(
|
|
|
1723
1810
|
},
|
|
1724
1811
|
async (args, context, helpers) => {
|
|
1725
1812
|
const offset = args.offset ?? 1;
|
|
1726
|
-
const limit = Math.min(
|
|
1727
|
-
args.limit ?? OUTPUT_LIMITS.read_file.maxLines,
|
|
1728
|
-
OUTPUT_LIMITS.read_file.maxLines
|
|
1729
|
-
);
|
|
1813
|
+
const limit = Math.min(args.limit ?? OUTPUT_LIMITS.read_file.maxLines, OUTPUT_LIMITS.read_file.maxLines);
|
|
1730
1814
|
const fullPath = helpers.resolvePath(args.path);
|
|
1731
1815
|
await helpers.checkPathAccess([fullPath]);
|
|
1732
1816
|
try {
|
|
@@ -1735,7 +1819,9 @@ var readFileTool = createTool(
|
|
|
1735
1819
|
return helpers.error(`Path is a directory, not a file: ${args.path}`);
|
|
1736
1820
|
}
|
|
1737
1821
|
if (stats.size > OUTPUT_LIMITS.read_file.maxImageBytes) {
|
|
1738
|
-
return helpers.error(
|
|
1822
|
+
return helpers.error(
|
|
1823
|
+
`File size (${stats.size} bytes) exceeds image size limit (2MB). Use shell command to process large files.`
|
|
1824
|
+
);
|
|
1739
1825
|
}
|
|
1740
1826
|
} catch {
|
|
1741
1827
|
return helpers.error(`File not found: ${args.path}`);
|
|
@@ -1749,19 +1835,15 @@ var readFileTool = createTool(
|
|
|
1749
1835
|
if (contentHash2) {
|
|
1750
1836
|
context.sessionManager.recordFileRead(context.sessionId, fullPath, contentHash2);
|
|
1751
1837
|
}
|
|
1752
|
-
return helpers.success(
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
base64Data,
|
|
1760
|
-
dataUrl,
|
|
1761
|
-
path: fullPath
|
|
1762
|
-
}
|
|
1838
|
+
return helpers.success(`[Image: ${args.path} (${mimeType}, ${rawBuffer.length} bytes)]`, false, {
|
|
1839
|
+
metadata: {
|
|
1840
|
+
mimeType,
|
|
1841
|
+
size: rawBuffer.length,
|
|
1842
|
+
base64Data,
|
|
1843
|
+
dataUrl,
|
|
1844
|
+
path: fullPath
|
|
1763
1845
|
}
|
|
1764
|
-
);
|
|
1846
|
+
});
|
|
1765
1847
|
}
|
|
1766
1848
|
const content = rawBuffer.toString("utf-8");
|
|
1767
1849
|
const lines = content.split("\n");
|
|
@@ -1865,11 +1947,7 @@ var writeFileTool = createTool(
|
|
|
1865
1947
|
if (newHash) {
|
|
1866
1948
|
context.sessionManager.updateFileHash(context.sessionId, fullPath, newHash);
|
|
1867
1949
|
}
|
|
1868
|
-
return helpers.success(
|
|
1869
|
-
output,
|
|
1870
|
-
false,
|
|
1871
|
-
diagnostics.length > 0 ? { diagnostics } : void 0
|
|
1872
|
-
);
|
|
1950
|
+
return helpers.success(output, false, diagnostics.length > 0 ? { diagnostics } : void 0);
|
|
1873
1951
|
}
|
|
1874
1952
|
);
|
|
1875
1953
|
|
|
@@ -2054,7 +2132,12 @@ Make sure whitespace and indentation match exactly.`
|
|
|
2054
2132
|
`Found ${occurrences} matches for old_string. Use replace_all: true to replace all, or provide more context to make the match unique.`
|
|
2055
2133
|
);
|
|
2056
2134
|
}
|
|
2057
|
-
const contextResult = extractEditContext(
|
|
2135
|
+
const contextResult = extractEditContext(
|
|
2136
|
+
normalizedContent,
|
|
2137
|
+
normalizedOldString,
|
|
2138
|
+
normalizeToLF(args.new_string),
|
|
2139
|
+
replaceAll
|
|
2140
|
+
);
|
|
2058
2141
|
const editContextRegions = contextResult.regions.map((region) => ({
|
|
2059
2142
|
beforeContext: region.beforeContext.map((line) => ({
|
|
2060
2143
|
lineNumber: line.lineNumber,
|
|
@@ -2086,7 +2169,10 @@ Make sure whitespace and indentation match exactly.`
|
|
|
2086
2169
|
}
|
|
2087
2170
|
replacedContent = normalizedContent.slice(0, index) + normalizedNewString + normalizedContent.slice(index + normalizedOldString.length);
|
|
2088
2171
|
}
|
|
2089
|
-
const newContent = replacedContent.replace(
|
|
2172
|
+
const newContent = replacedContent.replace(
|
|
2173
|
+
/\n/g,
|
|
2174
|
+
fileLineEnding === "crlf" ? "\r\n" : fileLineEnding === "cr" ? "\r" : "\n"
|
|
2175
|
+
);
|
|
2090
2176
|
await writeFile3(fullPath, newContent, "utf-8");
|
|
2091
2177
|
let output = `Successfully replaced ${replaceAll ? occurrences : 1} occurrence(s) in ${args.path}`;
|
|
2092
2178
|
let diagnostics = [];
|
|
@@ -2359,12 +2445,21 @@ var criterionTool = createTool(
|
|
|
2359
2445
|
}
|
|
2360
2446
|
},
|
|
2361
2447
|
async (args, context, helpers) => {
|
|
2362
|
-
const actionError = validateActionWithPermission(
|
|
2448
|
+
const actionError = validateActionWithPermission(
|
|
2449
|
+
args.action,
|
|
2450
|
+
["get", "add", "update", "remove", "complete", "pass", "fail"],
|
|
2451
|
+
"criterion",
|
|
2452
|
+
context.permittedActions
|
|
2453
|
+
);
|
|
2363
2454
|
if (actionError) return actionError;
|
|
2364
2455
|
const session = requireSession(context.sessionManager, context.sessionId);
|
|
2365
2456
|
if (args.action === "get") {
|
|
2366
2457
|
return helpers.success(
|
|
2367
|
-
session.criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(
|
|
2458
|
+
session.criteria.length === 0 ? "No criteria defined yet." : JSON.stringify(
|
|
2459
|
+
session.criteria.map((c) => ({ id: c.id, description: c.description })),
|
|
2460
|
+
null,
|
|
2461
|
+
2
|
|
2462
|
+
)
|
|
2368
2463
|
);
|
|
2369
2464
|
}
|
|
2370
2465
|
if (args.action === "add") {
|
|
@@ -2377,14 +2472,18 @@ var criterionTool = createTool(
|
|
|
2377
2472
|
};
|
|
2378
2473
|
const result = context.sessionManager.addCriterion(context.sessionId, criterion);
|
|
2379
2474
|
if ("error" in result) return helpers.error(result.error);
|
|
2380
|
-
return helpers.success(
|
|
2381
|
-
${
|
|
2475
|
+
return helpers.success(
|
|
2476
|
+
`Added criterion "${result.actualId}". Current criteria:
|
|
2477
|
+
${formatCriteriaList(result.criteria)}`
|
|
2478
|
+
);
|
|
2382
2479
|
}
|
|
2383
2480
|
if (args.action === "update") {
|
|
2384
2481
|
if (!args.id) return helpers.error("Missing required field: id");
|
|
2385
2482
|
if (!args.description) return helpers.error("Missing required field: description");
|
|
2386
2483
|
if (!session.criteria.find((c) => c.id === args.id)) return helpers.error(`Criterion "${args.id}" not found`);
|
|
2387
|
-
const criteria = context.sessionManager.updateCriterionFull(context.sessionId, args.id, {
|
|
2484
|
+
const criteria = context.sessionManager.updateCriterionFull(context.sessionId, args.id, {
|
|
2485
|
+
description: args.description
|
|
2486
|
+
});
|
|
2388
2487
|
return helpers.success(`Updated criterion "${args.id}". Current criteria:
|
|
2389
2488
|
${formatCriteriaList(criteria)}`);
|
|
2390
2489
|
}
|
|
@@ -2400,13 +2499,18 @@ ${formatCriteriaList(criteria)}`
|
|
|
2400
2499
|
if (args.action === "complete") {
|
|
2401
2500
|
if (!args.id) return helpers.error("Missing required field: id");
|
|
2402
2501
|
const criterion = session.criteria.find((c) => c.id === args.id);
|
|
2403
|
-
if (!criterion)
|
|
2502
|
+
if (!criterion)
|
|
2503
|
+
return helpers.error(
|
|
2504
|
+
`Criterion "${args.id}" not found. Available: ${session.criteria.map((c) => c.id).join(", ")}`
|
|
2505
|
+
);
|
|
2404
2506
|
context.sessionManager.updateCriterionStatus(context.sessionId, args.id, {
|
|
2405
2507
|
type: "completed",
|
|
2406
2508
|
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2407
2509
|
...args.reason ? { reason: args.reason } : {}
|
|
2408
2510
|
});
|
|
2409
|
-
return helpers.success(
|
|
2511
|
+
return helpers.success(
|
|
2512
|
+
`Criterion "${args.id}" marked as completed.${args.reason ? ` Reason: ${args.reason}` : ""}`
|
|
2513
|
+
);
|
|
2410
2514
|
}
|
|
2411
2515
|
if (args.action === "pass") {
|
|
2412
2516
|
if (!args.id) return helpers.error("Missing required field: id");
|
|
@@ -2485,13 +2589,16 @@ var todoTool = createTool(
|
|
|
2485
2589
|
}
|
|
2486
2590
|
},
|
|
2487
2591
|
async (args, context, helpers) => {
|
|
2488
|
-
const actionError = validateActionWithPermission(
|
|
2592
|
+
const actionError = validateActionWithPermission(
|
|
2593
|
+
args.action,
|
|
2594
|
+
["list", "write", "add", "update", "remove"],
|
|
2595
|
+
"todo",
|
|
2596
|
+
context.permittedActions
|
|
2597
|
+
);
|
|
2489
2598
|
if (actionError) return actionError;
|
|
2490
2599
|
if (args.action === "list") {
|
|
2491
2600
|
const todosList = sessionTodos.get(context.sessionId) ?? [];
|
|
2492
|
-
return helpers.success(
|
|
2493
|
-
todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2)
|
|
2494
|
-
);
|
|
2601
|
+
return helpers.success(todosList.length === 0 ? "No tasks defined yet." : JSON.stringify(todosList, null, 2));
|
|
2495
2602
|
}
|
|
2496
2603
|
if (args.action === "write") {
|
|
2497
2604
|
if (!args.todos) return helpers.error("Missing required field: todos");
|
|
@@ -2504,7 +2611,9 @@ var todoTool = createTool(
|
|
|
2504
2611
|
}
|
|
2505
2612
|
sessionTodos.set(context.sessionId, args.todos);
|
|
2506
2613
|
if (onTodoUpdate) onTodoUpdate(context.sessionId, args.todos);
|
|
2507
|
-
return helpers.success(
|
|
2614
|
+
return helpers.success(
|
|
2615
|
+
`${args.todos.filter((t) => t.status === "completed").length} completed, ${args.todos.filter((t) => t.status === "in_progress").length} in progress, ${args.todos.filter((t) => t.status === "pending").length} pending`
|
|
2616
|
+
);
|
|
2508
2617
|
}
|
|
2509
2618
|
if (args.action === "add") {
|
|
2510
2619
|
if (!args.content) return helpers.error("Missing required field: content");
|
|
@@ -2650,10 +2759,7 @@ async function loadUserSkills(configDir) {
|
|
|
2650
2759
|
});
|
|
2651
2760
|
}
|
|
2652
2761
|
async function loadAllSkills(configDir) {
|
|
2653
|
-
const [defaultSkills, userSkills] = await Promise.all([
|
|
2654
|
-
loadDefaultSkills(),
|
|
2655
|
-
loadUserSkills(configDir)
|
|
2656
|
-
]);
|
|
2762
|
+
const [defaultSkills, userSkills] = await Promise.all([loadDefaultSkills(), loadUserSkills(configDir)]);
|
|
2657
2763
|
const skillMap = /* @__PURE__ */ new Map();
|
|
2658
2764
|
for (const skill of defaultSkills) {
|
|
2659
2765
|
skillMap.set(skill.metadata.id, skill);
|
|
@@ -2726,11 +2832,14 @@ async function deleteSkill(configDir, skillId) {
|
|
|
2726
2832
|
import stripAnsi from "strip-ansi";
|
|
2727
2833
|
function emitPartialDoneEvents(sessionId, assistantMsgId, statsIdentity, mode, turnMetrics, promptContext, eventStore) {
|
|
2728
2834
|
const stats = turnMetrics.buildStats(statsIdentity, mode);
|
|
2729
|
-
eventStore.append(
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2835
|
+
eventStore.append(
|
|
2836
|
+
sessionId,
|
|
2837
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
2838
|
+
stats,
|
|
2839
|
+
partial: true,
|
|
2840
|
+
promptContext
|
|
2841
|
+
})
|
|
2842
|
+
);
|
|
2734
2843
|
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats));
|
|
2735
2844
|
}
|
|
2736
2845
|
function getCurrentWindowMessageOptions(sessionId) {
|
|
@@ -2798,7 +2907,7 @@ async function executeToolBatch(assistantMsgId, toolCalls, ctx) {
|
|
|
2798
2907
|
type: "chat.ask_user",
|
|
2799
2908
|
data: { callId: error.callId, question: error.question }
|
|
2800
2909
|
});
|
|
2801
|
-
const { awaitAnswer } = await import("./ask-
|
|
2910
|
+
const { awaitAnswer } = await import("./ask-5SSOA6SZ.js");
|
|
2802
2911
|
const answerPromise = awaitAnswer(error.callId);
|
|
2803
2912
|
if (!answerPromise) {
|
|
2804
2913
|
throw new Error(`No pending question found for callId: ${error.callId}`);
|
|
@@ -2823,9 +2932,11 @@ async function executeToolBatch(assistantMsgId, toolCalls, ctx) {
|
|
|
2823
2932
|
}
|
|
2824
2933
|
toolMessages.push({
|
|
2825
2934
|
role: "tool",
|
|
2826
|
-
content: stripAnsi(
|
|
2935
|
+
content: stripAnsi(
|
|
2936
|
+
toolResult.success ? toolResult.output ?? "Success" : toolResult.output ? `${toolResult.output}
|
|
2827
2937
|
|
|
2828
|
-
Error: ${toolResult.error}` : `Error: ${toolResult.error}`
|
|
2938
|
+
Error: ${toolResult.error}` : `Error: ${toolResult.error}`
|
|
2939
|
+
),
|
|
2829
2940
|
source: "history",
|
|
2830
2941
|
toolCallId: toolCall.id
|
|
2831
2942
|
});
|
|
@@ -2845,7 +2956,14 @@ function toRequestContextMessages(messages) {
|
|
|
2845
2956
|
role: message.role,
|
|
2846
2957
|
content: message.content,
|
|
2847
2958
|
source: "history",
|
|
2848
|
-
...message.
|
|
2959
|
+
...message.thinkingContent ? { thinkingContent: message.thinkingContent } : {},
|
|
2960
|
+
...message.toolCalls ? {
|
|
2961
|
+
toolCalls: message.toolCalls.map((toolCall) => ({
|
|
2962
|
+
id: toolCall.id,
|
|
2963
|
+
name: toolCall.name,
|
|
2964
|
+
arguments: toolCall.arguments
|
|
2965
|
+
}))
|
|
2966
|
+
} : {},
|
|
2849
2967
|
...message.toolCallId ? { toolCallId: message.toolCallId } : {},
|
|
2850
2968
|
...message.attachments ? { attachments: message.attachments } : {}
|
|
2851
2969
|
}));
|
|
@@ -2881,11 +2999,14 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
2881
2999
|
const requestMessages = toRequestContextMessages(getContextMessages(sessionId));
|
|
2882
3000
|
if (formatRetryCount > 0) {
|
|
2883
3001
|
const correctionMsgId = crypto.randomUUID();
|
|
2884
|
-
eventStore.append(
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
3002
|
+
eventStore.append(
|
|
3003
|
+
sessionId,
|
|
3004
|
+
createMessageStartEvent(correctionMsgId, "user", FORMAT_CORRECTION_PROMPT2, {
|
|
3005
|
+
...currentWindowMessageOptions ?? {},
|
|
3006
|
+
isSystemGenerated: true,
|
|
3007
|
+
messageKind: "correction"
|
|
3008
|
+
})
|
|
3009
|
+
);
|
|
2889
3010
|
eventStore.append(sessionId, createFormatRetryEvent(formatRetryCount, MAX_FORMAT_RETRIES));
|
|
2890
3011
|
requestMessages.push({ role: "user", content: FORMAT_CORRECTION_PROMPT2, source: "runtime" });
|
|
2891
3012
|
}
|
|
@@ -2902,7 +3023,10 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
2902
3023
|
...skills.length > 0 ? { skills } : {}
|
|
2903
3024
|
});
|
|
2904
3025
|
const assistantMsgId = crypto.randomUUID();
|
|
2905
|
-
eventStore.append(
|
|
3026
|
+
eventStore.append(
|
|
3027
|
+
sessionId,
|
|
3028
|
+
createMessageStartEvent(assistantMsgId, "assistant", void 0, currentWindowMessageOptions)
|
|
3029
|
+
);
|
|
2906
3030
|
const doOnMessage = (msg) => {
|
|
2907
3031
|
onMessage?.(msg);
|
|
2908
3032
|
};
|
|
@@ -2933,7 +3057,9 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
2933
3057
|
type: "vision_fallback.done",
|
|
2934
3058
|
data: { messageId: assistantMsgId, attachmentId, description }
|
|
2935
3059
|
});
|
|
2936
|
-
doOnMessage(
|
|
3060
|
+
doOnMessage(
|
|
3061
|
+
createChatVisionFallbackMessage({ type: "done", messageId: assistantMsgId, attachmentId, description })
|
|
3062
|
+
);
|
|
2937
3063
|
};
|
|
2938
3064
|
const modelSettings = sessionManager.getCurrentModelSettings();
|
|
2939
3065
|
const streamGen = streamLLMPure({
|
|
@@ -2965,16 +3091,27 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
2965
3091
|
}
|
|
2966
3092
|
}
|
|
2967
3093
|
if (result.aborted) {
|
|
2968
|
-
emitPartialDoneEvents(
|
|
3094
|
+
emitPartialDoneEvents(
|
|
3095
|
+
sessionId,
|
|
3096
|
+
assistantMsgId,
|
|
3097
|
+
statsIdentity,
|
|
3098
|
+
mode,
|
|
3099
|
+
turnMetrics,
|
|
3100
|
+
assembledRequest.promptContext,
|
|
3101
|
+
eventStore
|
|
3102
|
+
);
|
|
2969
3103
|
throw new Error("Aborted");
|
|
2970
3104
|
}
|
|
2971
3105
|
turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens, result.modelParams);
|
|
2972
3106
|
sessionManager.setCurrentContextSize(sessionId, result.usage.promptTokens);
|
|
2973
3107
|
if (result.toolCalls.length > 0) {
|
|
2974
|
-
eventStore.append(
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
3108
|
+
eventStore.append(
|
|
3109
|
+
sessionId,
|
|
3110
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3111
|
+
segments: result.segments,
|
|
3112
|
+
promptContext: assembledRequest.promptContext
|
|
3113
|
+
})
|
|
3114
|
+
);
|
|
2978
3115
|
try {
|
|
2979
3116
|
const batchContext = {
|
|
2980
3117
|
toolRegistry,
|
|
@@ -3000,22 +3137,41 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3000
3137
|
}
|
|
3001
3138
|
} catch (error) {
|
|
3002
3139
|
if (error instanceof Error && error.message === "Aborted") {
|
|
3003
|
-
emitPartialDoneEvents(
|
|
3140
|
+
emitPartialDoneEvents(
|
|
3141
|
+
sessionId,
|
|
3142
|
+
assistantMsgId,
|
|
3143
|
+
statsIdentity,
|
|
3144
|
+
mode,
|
|
3145
|
+
turnMetrics,
|
|
3146
|
+
assembledRequest.promptContext,
|
|
3147
|
+
eventStore
|
|
3148
|
+
);
|
|
3004
3149
|
throw error;
|
|
3005
3150
|
}
|
|
3006
3151
|
throw error;
|
|
3007
3152
|
}
|
|
3008
3153
|
if (signal?.aborted) {
|
|
3009
|
-
emitPartialDoneEvents(
|
|
3154
|
+
emitPartialDoneEvents(
|
|
3155
|
+
sessionId,
|
|
3156
|
+
assistantMsgId,
|
|
3157
|
+
statsIdentity,
|
|
3158
|
+
mode,
|
|
3159
|
+
turnMetrics,
|
|
3160
|
+
assembledRequest.promptContext,
|
|
3161
|
+
eventStore
|
|
3162
|
+
);
|
|
3010
3163
|
throw new Error("Aborted");
|
|
3011
3164
|
}
|
|
3012
3165
|
const asapMessages = sessionManager.drainAsapMessages(sessionId);
|
|
3013
3166
|
for (const asap of asapMessages) {
|
|
3014
3167
|
const asapMsgId = crypto.randomUUID();
|
|
3015
|
-
eventStore.append(
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3168
|
+
eventStore.append(
|
|
3169
|
+
sessionId,
|
|
3170
|
+
createMessageStartEvent(asapMsgId, "user", asap.content, {
|
|
3171
|
+
...getCurrentWindowMessageOptions(sessionId),
|
|
3172
|
+
...asap.attachments ? { attachments: asap.attachments } : {}
|
|
3173
|
+
})
|
|
3174
|
+
);
|
|
3019
3175
|
eventStore.append(sessionId, { type: "message.done", data: { messageId: asapMsgId } });
|
|
3020
3176
|
}
|
|
3021
3177
|
if (asapMessages.length > 0) {
|
|
@@ -3025,11 +3181,14 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3025
3181
|
continue;
|
|
3026
3182
|
}
|
|
3027
3183
|
const stats = turnMetrics.buildStats(statsIdentity, mode);
|
|
3028
|
-
eventStore.append(
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3184
|
+
eventStore.append(
|
|
3185
|
+
sessionId,
|
|
3186
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3187
|
+
segments: result.segments,
|
|
3188
|
+
stats,
|
|
3189
|
+
promptContext: assembledRequest.promptContext
|
|
3190
|
+
})
|
|
3191
|
+
);
|
|
3033
3192
|
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "complete", stats));
|
|
3034
3193
|
const currentWindowMessages = sessionManager.getCurrentWindowMessages(sessionId);
|
|
3035
3194
|
const lastUserMessage = [...currentWindowMessages].reverse().find((m) => m.role === "user");
|
|
@@ -3045,15 +3204,36 @@ async function runTopLevelAgentLoop(config, turnMetrics) {
|
|
|
3045
3204
|
}
|
|
3046
3205
|
|
|
3047
3206
|
// src/server/context/nudge-helpers.ts
|
|
3207
|
+
function buildPromptContextForNudge(systemPrompt, injectedFiles, userMessage, messages, tools) {
|
|
3208
|
+
return {
|
|
3209
|
+
systemPrompt,
|
|
3210
|
+
injectedFiles,
|
|
3211
|
+
userMessage,
|
|
3212
|
+
messages: messages.map((m) => ({
|
|
3213
|
+
role: m.role,
|
|
3214
|
+
content: m.content,
|
|
3215
|
+
source: m.source
|
|
3216
|
+
})),
|
|
3217
|
+
tools: tools.map((t) => ({
|
|
3218
|
+
name: t.function.name,
|
|
3219
|
+
description: t.function.description,
|
|
3220
|
+
parameters: t.function.parameters
|
|
3221
|
+
})),
|
|
3222
|
+
requestOptions: { toolChoice: "auto", disableThinking: true }
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3048
3225
|
function appendNudgeMessage(eventStore, sessionId, content, currentWindowMessageOptions, options) {
|
|
3049
3226
|
const msgId = crypto.randomUUID();
|
|
3050
|
-
eventStore.append(
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3227
|
+
eventStore.append(
|
|
3228
|
+
sessionId,
|
|
3229
|
+
createMessageStartEvent(msgId, "user", content, {
|
|
3230
|
+
...currentWindowMessageOptions ?? {},
|
|
3231
|
+
isSystemGenerated: true,
|
|
3232
|
+
messageKind: "correction",
|
|
3233
|
+
subAgentId: options.subAgentId,
|
|
3234
|
+
subAgentType: options.subAgentType
|
|
3235
|
+
})
|
|
3236
|
+
);
|
|
3057
3237
|
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
3058
3238
|
}
|
|
3059
3239
|
|
|
@@ -3104,40 +3284,26 @@ async function executeSubAgent(options) {
|
|
|
3104
3284
|
const subAgentId = crypto.randomUUID();
|
|
3105
3285
|
let session = sessionManager.requireSession(sessionId);
|
|
3106
3286
|
const currentWindowMessageOptions = getCurrentWindowMessageOptions2(sessionId);
|
|
3107
|
-
const contextMessages = [
|
|
3108
|
-
{ role: "user", content: prompt, source: "runtime" }
|
|
3109
|
-
];
|
|
3287
|
+
const contextMessages = [{ role: "user", content: prompt, source: "runtime" }];
|
|
3110
3288
|
logger.debug("Sub-agent starting", { subAgentType, subAgentId, sessionId });
|
|
3111
3289
|
const resetMsgId = crypto.randomUUID();
|
|
3112
|
-
eventStore.append(
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
messageKind: "context-reset",
|
|
3116
|
-
subAgentId,
|
|
3117
|
-
subAgentType
|
|
3118
|
-
}));
|
|
3119
|
-
eventStore.append(sessionId, { type: "message.done", data: { messageId: resetMsgId } });
|
|
3120
|
-
for (const msg of contextMessages) {
|
|
3121
|
-
const msgId = crypto.randomUUID();
|
|
3122
|
-
eventStore.append(sessionId, createMessageStartEvent(msgId, "user", msg.content, {
|
|
3290
|
+
eventStore.append(
|
|
3291
|
+
sessionId,
|
|
3292
|
+
createMessageStartEvent(resetMsgId, "user", `Fresh Context - ${agentDef.metadata.name} Sub-Agent`, {
|
|
3123
3293
|
...currentWindowMessageOptions ?? {},
|
|
3124
3294
|
isSystemGenerated: true,
|
|
3125
|
-
messageKind: "
|
|
3295
|
+
messageKind: "context-reset",
|
|
3126
3296
|
subAgentId,
|
|
3127
|
-
subAgentType
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
id: msgId,
|
|
3138
|
-
role: "user",
|
|
3139
|
-
content: msg.content,
|
|
3140
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3297
|
+
subAgentType
|
|
3298
|
+
})
|
|
3299
|
+
);
|
|
3300
|
+
eventStore.append(sessionId, { type: "message.done", data: { messageId: resetMsgId } });
|
|
3301
|
+
for (const msg of contextMessages) {
|
|
3302
|
+
const msgId = crypto.randomUUID();
|
|
3303
|
+
eventStore.append(
|
|
3304
|
+
sessionId,
|
|
3305
|
+
createMessageStartEvent(msgId, "user", msg.content, {
|
|
3306
|
+
...currentWindowMessageOptions ?? {},
|
|
3141
3307
|
isSystemGenerated: true,
|
|
3142
3308
|
messageKind: "auto-prompt",
|
|
3143
3309
|
subAgentId,
|
|
@@ -3147,15 +3313,31 @@ async function executeSubAgent(options) {
|
|
|
3147
3313
|
name: agentDef.metadata.name,
|
|
3148
3314
|
color: agentDef.metadata.color ?? "#6b7280"
|
|
3149
3315
|
}
|
|
3150
|
-
})
|
|
3316
|
+
})
|
|
3317
|
+
);
|
|
3318
|
+
eventStore.append(sessionId, { type: "message.done", data: { messageId: msgId } });
|
|
3319
|
+
if (onMessage) {
|
|
3320
|
+
onMessage(
|
|
3321
|
+
createChatMessageMessage({
|
|
3322
|
+
id: msgId,
|
|
3323
|
+
role: "user",
|
|
3324
|
+
content: msg.content,
|
|
3325
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3326
|
+
isSystemGenerated: true,
|
|
3327
|
+
messageKind: "auto-prompt",
|
|
3328
|
+
subAgentId,
|
|
3329
|
+
subAgentType,
|
|
3330
|
+
metadata: {
|
|
3331
|
+
type: "subagent",
|
|
3332
|
+
name: agentDef.metadata.name,
|
|
3333
|
+
color: agentDef.metadata.color ?? "#6b7280"
|
|
3334
|
+
}
|
|
3335
|
+
})
|
|
3336
|
+
);
|
|
3151
3337
|
}
|
|
3152
3338
|
}
|
|
3153
3339
|
const { files } = await getAllInstructions(session.workdir, session.projectId);
|
|
3154
|
-
const injectedFiles = files
|
|
3155
|
-
path: file.path,
|
|
3156
|
-
content: file.content ?? "",
|
|
3157
|
-
source: file.source
|
|
3158
|
-
}));
|
|
3340
|
+
const injectedFiles = toInjectedFiles(files);
|
|
3159
3341
|
const configDir = getGlobalConfigDir(getRuntimeConfig().mode ?? "production");
|
|
3160
3342
|
const skills = await getEnabledSkillMetadata(configDir);
|
|
3161
3343
|
const systemPrompt = buildSubAgentSystemPrompt(
|
|
@@ -3166,7 +3348,7 @@ async function executeSubAgent(options) {
|
|
|
3166
3348
|
);
|
|
3167
3349
|
let customMessages = [...contextMessages];
|
|
3168
3350
|
let consecutiveEmptyStops = 0;
|
|
3169
|
-
let finalContent
|
|
3351
|
+
let finalContent;
|
|
3170
3352
|
let returnValueContent = null;
|
|
3171
3353
|
let returnValueResult = void 0;
|
|
3172
3354
|
let returnValueNudged = false;
|
|
@@ -3182,29 +3364,26 @@ async function executeSubAgent(options) {
|
|
|
3182
3364
|
...signal ? { signal } : {}
|
|
3183
3365
|
});
|
|
3184
3366
|
const assistantMsgId = crypto.randomUUID();
|
|
3185
|
-
eventStore.append(
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3367
|
+
eventStore.append(
|
|
3368
|
+
sessionId,
|
|
3369
|
+
createMessageStartEvent(assistantMsgId, "assistant", void 0, {
|
|
3370
|
+
...currentWindowMessageOptions ?? {},
|
|
3371
|
+
subAgentId,
|
|
3372
|
+
subAgentType
|
|
3373
|
+
})
|
|
3374
|
+
);
|
|
3375
|
+
const promptContext = buildPromptContextForNudge(
|
|
3191
3376
|
systemPrompt,
|
|
3192
3377
|
injectedFiles,
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
};
|
|
3378
|
+
prompt,
|
|
3379
|
+
customMessages,
|
|
3380
|
+
toolRegistry.definitions
|
|
3381
|
+
);
|
|
3198
3382
|
const streamGen = streamLLMPure({
|
|
3199
3383
|
messageId: assistantMsgId,
|
|
3200
3384
|
systemPrompt: systemPrompt + RETURN_VALUE_INSTRUCTION,
|
|
3201
3385
|
llmClient,
|
|
3202
|
-
messages: customMessages
|
|
3203
|
-
role: m.role,
|
|
3204
|
-
content: m.content,
|
|
3205
|
-
...m.toolCalls ? { toolCalls: m.toolCalls.map((tc) => ({ id: tc.id, name: tc.name, arguments: tc.arguments })) } : {},
|
|
3206
|
-
...m.toolCallId ? { toolCallId: m.toolCallId } : {}
|
|
3207
|
-
})),
|
|
3386
|
+
messages: toStreamMessages(customMessages),
|
|
3208
3387
|
tools: toolRegistry.definitions,
|
|
3209
3388
|
toolChoice: "auto",
|
|
3210
3389
|
signal,
|
|
@@ -3215,23 +3394,21 @@ async function executeSubAgent(options) {
|
|
|
3215
3394
|
});
|
|
3216
3395
|
if (result.aborted) {
|
|
3217
3396
|
const stats = turnMetrics.buildStats(statsIdentity, "verifier");
|
|
3218
|
-
eventStore.append(
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3397
|
+
eventStore.append(
|
|
3398
|
+
sessionId,
|
|
3399
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3400
|
+
stats,
|
|
3401
|
+
partial: true,
|
|
3402
|
+
promptContext
|
|
3403
|
+
})
|
|
3404
|
+
);
|
|
3223
3405
|
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "stopped", stats));
|
|
3224
3406
|
throw new Error("Aborted");
|
|
3225
3407
|
}
|
|
3226
3408
|
turnMetrics.addLLMCall(result.timing, result.usage.promptTokens, result.usage.completionTokens, result.modelParams);
|
|
3227
3409
|
sessionManager.setCurrentContextSize(sessionId, result.usage.promptTokens, subAgentId);
|
|
3228
3410
|
finalContent = result.content;
|
|
3229
|
-
customMessages.push(
|
|
3230
|
-
role: "assistant",
|
|
3231
|
-
content: result.content,
|
|
3232
|
-
source: "history",
|
|
3233
|
-
...result.toolCalls.length > 0 && { toolCalls: result.toolCalls }
|
|
3234
|
-
});
|
|
3411
|
+
customMessages.push(createAssistantMessage(result.content, result.thinkingContent, result.toolCalls));
|
|
3235
3412
|
session = sessionManager.requireSession(sessionId);
|
|
3236
3413
|
if (result.toolCalls.length === 0) {
|
|
3237
3414
|
if (nudgeConfig) {
|
|
@@ -3240,48 +3417,69 @@ async function executeSubAgent(options) {
|
|
|
3240
3417
|
if (consecutiveEmptyStops < nudgeConfig.maxConsecutiveNudges) {
|
|
3241
3418
|
consecutiveEmptyStops += 1;
|
|
3242
3419
|
const nudgeContent = nudgeConfig.buildNudgeContent(criteriaAwaiting);
|
|
3243
|
-
eventStore.append(
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3420
|
+
eventStore.append(
|
|
3421
|
+
sessionId,
|
|
3422
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3423
|
+
segments: result.segments,
|
|
3424
|
+
promptContext
|
|
3425
|
+
})
|
|
3426
|
+
);
|
|
3427
|
+
appendNudgeMessage(eventStore, sessionId, nudgeContent, currentWindowMessageOptions, {
|
|
3428
|
+
subAgentId,
|
|
3429
|
+
subAgentType
|
|
3430
|
+
});
|
|
3248
3431
|
customMessages = [...customMessages, { role: "user", content: nudgeContent, source: "runtime" }];
|
|
3249
3432
|
continue;
|
|
3250
3433
|
}
|
|
3251
3434
|
const stalledMsgId = crypto.randomUUID();
|
|
3252
|
-
eventStore.append(
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3435
|
+
eventStore.append(
|
|
3436
|
+
sessionId,
|
|
3437
|
+
createMessageStartEvent(stalledMsgId, "user", nudgeConfig.buildRestartContent(criteriaAwaiting), {
|
|
3438
|
+
...currentWindowMessageOptions ?? {},
|
|
3439
|
+
isSystemGenerated: true,
|
|
3440
|
+
messageKind: "correction",
|
|
3441
|
+
subAgentId,
|
|
3442
|
+
subAgentType
|
|
3443
|
+
})
|
|
3444
|
+
);
|
|
3259
3445
|
eventStore.append(sessionId, { type: "message.done", data: { messageId: stalledMsgId } });
|
|
3260
3446
|
}
|
|
3261
3447
|
}
|
|
3262
3448
|
if (!returnValueContent && !returnValueNudged) {
|
|
3263
3449
|
returnValueNudged = true;
|
|
3264
|
-
eventStore.append(
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3450
|
+
eventStore.append(
|
|
3451
|
+
sessionId,
|
|
3452
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3453
|
+
segments: result.segments,
|
|
3454
|
+
promptContext
|
|
3455
|
+
})
|
|
3456
|
+
);
|
|
3457
|
+
appendNudgeMessage(eventStore, sessionId, RETURN_VALUE_NUDGE, currentWindowMessageOptions, {
|
|
3458
|
+
subAgentId,
|
|
3459
|
+
subAgentType
|
|
3460
|
+
});
|
|
3269
3461
|
customMessages = [...customMessages, { role: "user", content: RETURN_VALUE_NUDGE, source: "runtime" }];
|
|
3270
3462
|
continue;
|
|
3271
3463
|
}
|
|
3272
3464
|
const stats = turnMetrics.buildStats(statsIdentity, "verifier");
|
|
3273
|
-
eventStore.append(
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3465
|
+
eventStore.append(
|
|
3466
|
+
sessionId,
|
|
3467
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3468
|
+
segments: result.segments,
|
|
3469
|
+
stats,
|
|
3470
|
+
promptContext
|
|
3471
|
+
})
|
|
3472
|
+
);
|
|
3278
3473
|
eventStore.append(sessionId, createChatDoneEvent(assistantMsgId, "complete", stats));
|
|
3279
3474
|
break;
|
|
3280
3475
|
}
|
|
3281
|
-
eventStore.append(
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3476
|
+
eventStore.append(
|
|
3477
|
+
sessionId,
|
|
3478
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3479
|
+
segments: result.segments,
|
|
3480
|
+
promptContext
|
|
3481
|
+
})
|
|
3482
|
+
);
|
|
3285
3483
|
const batchResult = await executeToolBatch(assistantMsgId, result.toolCalls, {
|
|
3286
3484
|
toolRegistry,
|
|
3287
3485
|
sessionManager,
|
|
@@ -3294,13 +3492,15 @@ async function executeSubAgent(options) {
|
|
|
3294
3492
|
if (batchResult.returnValueContent) {
|
|
3295
3493
|
returnValueContent = batchResult.returnValueContent;
|
|
3296
3494
|
returnValueResult = batchResult.returnValueResult;
|
|
3297
|
-
customMessages = [...customMessages, ...batchResult.toolMessages];
|
|
3298
3495
|
const stats = turnMetrics.buildStats(statsIdentity, subAgentType);
|
|
3299
|
-
eventStore.append(
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3496
|
+
eventStore.append(
|
|
3497
|
+
sessionId,
|
|
3498
|
+
createMessageDoneEvent(assistantMsgId, {
|
|
3499
|
+
segments: result.segments,
|
|
3500
|
+
stats,
|
|
3501
|
+
promptContext
|
|
3502
|
+
})
|
|
3503
|
+
);
|
|
3304
3504
|
if (onMessage) {
|
|
3305
3505
|
onMessage(createChatMessageUpdatedMessage(assistantMsgId, { isStreaming: false, stats, promptContext }));
|
|
3306
3506
|
}
|
|
@@ -3323,7 +3523,13 @@ async function executeSubAgent(options) {
|
|
|
3323
3523
|
});
|
|
3324
3524
|
const failed = session.criteria.filter((c) => c.status.type === "failed").map((c) => ({ id: c.id, reason: c.status.reason ?? "unknown" }));
|
|
3325
3525
|
const remaining = nudgeConfig?.getCriteriaAwaiting(session.criteria) ?? [];
|
|
3326
|
-
return buildSubAgentResult(
|
|
3526
|
+
return buildSubAgentResult(
|
|
3527
|
+
returnValueContent ?? void 0,
|
|
3528
|
+
returnValueResult ?? (subAgentType !== "verifier" ? "success" : void 0),
|
|
3529
|
+
subAgentType,
|
|
3530
|
+
failed,
|
|
3531
|
+
remaining
|
|
3532
|
+
);
|
|
3327
3533
|
}
|
|
3328
3534
|
|
|
3329
3535
|
// src/server/tools/sub-agent.ts
|
|
@@ -3391,7 +3597,7 @@ var callSubAgentTool = {
|
|
|
3391
3597
|
};
|
|
3392
3598
|
}
|
|
3393
3599
|
try {
|
|
3394
|
-
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-
|
|
3600
|
+
const { getToolRegistryForAgent: getToolRegistryForAgent2 } = await import("./tools-QJ5K5IJP.js");
|
|
3395
3601
|
const toolRegistry = getToolRegistryForAgent2(agentDef);
|
|
3396
3602
|
const turnMetrics = new TurnMetrics();
|
|
3397
3603
|
const result = await executeSubAgent({
|
|
@@ -3580,14 +3786,11 @@ var webFetchTool = createTool(
|
|
|
3580
3786
|
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
3581
3787
|
return helpers.error("URL must start with http:// or https://");
|
|
3582
3788
|
}
|
|
3583
|
-
const timeoutMs = Math.min(
|
|
3584
|
-
(args.timeout ?? DEFAULT_TIMEOUT_MS / 1e3) * 1e3,
|
|
3585
|
-
MAX_TIMEOUT_MS
|
|
3586
|
-
);
|
|
3789
|
+
const timeoutMs = Math.min((args.timeout ?? DEFAULT_TIMEOUT_MS / 1e3) * 1e3, MAX_TIMEOUT_MS);
|
|
3587
3790
|
const signal = buildSignal(timeoutMs, context.signal);
|
|
3588
3791
|
const headers = {
|
|
3589
3792
|
"User-Agent": USER_AGENT,
|
|
3590
|
-
|
|
3793
|
+
Accept: buildAcceptHeader(format),
|
|
3591
3794
|
"Accept-Language": "en-US,en;q=0.9"
|
|
3592
3795
|
};
|
|
3593
3796
|
const initial = await fetch(url, { signal, headers });
|
|
@@ -3919,16 +4122,20 @@ var devServerTool = createTool(
|
|
|
3919
4122
|
const offset = args.offset ?? 0;
|
|
3920
4123
|
const limit = args.limit ?? 100;
|
|
3921
4124
|
const result = devServerManager.getLogsSlice(workdir, offset, limit);
|
|
3922
|
-
const formattedLogs = result.logs.map(
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
4125
|
+
const formattedLogs = result.logs.map((entry) => `${entry.stream === "stderr" ? "[stderr] " : ""}${entry.content}`).join("");
|
|
4126
|
+
return helpers.success(
|
|
4127
|
+
JSON.stringify(
|
|
4128
|
+
{
|
|
4129
|
+
logs: formattedLogs,
|
|
4130
|
+
total: result.total,
|
|
4131
|
+
offset,
|
|
4132
|
+
limit,
|
|
4133
|
+
hasMore: offset + limit < result.total
|
|
4134
|
+
},
|
|
4135
|
+
null,
|
|
4136
|
+
2
|
|
4137
|
+
)
|
|
4138
|
+
);
|
|
3932
4139
|
}
|
|
3933
4140
|
let status;
|
|
3934
4141
|
switch (args.action) {
|
|
@@ -3958,12 +4165,18 @@ var devServerTool = createTool(
|
|
|
3958
4165
|
'No .openfox/dev-dev.json (dev mode) or .openfox/dev.json (prod) config found. Create one with:\n\n{\n "command": "npm run dev",\n "url": "http://localhost:3000",\n "hotReload": true\n}'
|
|
3959
4166
|
);
|
|
3960
4167
|
}
|
|
3961
|
-
return helpers.success(
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
4168
|
+
return helpers.success(
|
|
4169
|
+
JSON.stringify(
|
|
4170
|
+
{
|
|
4171
|
+
state: status.state,
|
|
4172
|
+
url: status.url,
|
|
4173
|
+
hotReload: status.hotReload,
|
|
4174
|
+
...status.errorMessage ? { error: status.errorMessage } : {}
|
|
4175
|
+
},
|
|
4176
|
+
null,
|
|
4177
|
+
2
|
|
4178
|
+
)
|
|
4179
|
+
);
|
|
3967
4180
|
}
|
|
3968
4181
|
);
|
|
3969
4182
|
|
|
@@ -4064,7 +4277,9 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4064
4277
|
const count = getSessionProcessCount(sessionId);
|
|
4065
4278
|
const maxPerSession = getMaxPerSession();
|
|
4066
4279
|
if (count >= maxPerSession) {
|
|
4067
|
-
return helpers.error(
|
|
4280
|
+
return helpers.error(
|
|
4281
|
+
`Maximum number of background processes (${maxPerSession}) reached. Stop existing processes before starting new ones.`
|
|
4282
|
+
);
|
|
4068
4283
|
}
|
|
4069
4284
|
const name = args.name ?? args.command?.split(" ")[0] ?? "process";
|
|
4070
4285
|
const process2 = createProcess(sessionId, name, args.command, cwd, args.timeout);
|
|
@@ -4075,13 +4290,19 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4075
4290
|
if (!pid) {
|
|
4076
4291
|
return helpers.error(`Failed to start process.`);
|
|
4077
4292
|
}
|
|
4078
|
-
return helpers.success(
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4293
|
+
return helpers.success(
|
|
4294
|
+
JSON.stringify(
|
|
4295
|
+
{
|
|
4296
|
+
processId: process2.id,
|
|
4297
|
+
name: process2.name,
|
|
4298
|
+
pid,
|
|
4299
|
+
status: "running",
|
|
4300
|
+
maxReached: count + 1 >= maxPerSession
|
|
4301
|
+
},
|
|
4302
|
+
null,
|
|
4303
|
+
2
|
|
4304
|
+
)
|
|
4305
|
+
);
|
|
4085
4306
|
}
|
|
4086
4307
|
case "stop": {
|
|
4087
4308
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
@@ -4092,19 +4313,31 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4092
4313
|
return helpers.error(`Process is not running (status: ${proc.status}). Cannot stop.`);
|
|
4093
4314
|
}
|
|
4094
4315
|
await stopProcess(args.processId, sessionId);
|
|
4095
|
-
return helpers.success(
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4316
|
+
return helpers.success(
|
|
4317
|
+
JSON.stringify(
|
|
4318
|
+
{
|
|
4319
|
+
processId: args.processId,
|
|
4320
|
+
status: "removed"
|
|
4321
|
+
},
|
|
4322
|
+
null,
|
|
4323
|
+
2
|
|
4324
|
+
)
|
|
4325
|
+
);
|
|
4099
4326
|
}
|
|
4100
4327
|
case "list": {
|
|
4101
4328
|
const processes = getSessionProcesses(sessionId);
|
|
4102
4329
|
const maxPerSession = getMaxPerSession();
|
|
4103
|
-
return helpers.success(
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4330
|
+
return helpers.success(
|
|
4331
|
+
JSON.stringify(
|
|
4332
|
+
{
|
|
4333
|
+
processes,
|
|
4334
|
+
maxPerSession,
|
|
4335
|
+
currentCount: processes.filter((p) => p.status !== "exited").length
|
|
4336
|
+
},
|
|
4337
|
+
null,
|
|
4338
|
+
2
|
|
4339
|
+
)
|
|
4340
|
+
);
|
|
4108
4341
|
}
|
|
4109
4342
|
case "status": {
|
|
4110
4343
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
@@ -4112,10 +4345,16 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4112
4345
|
return helpers.error(`Process not found: ${args.processId}`);
|
|
4113
4346
|
}
|
|
4114
4347
|
const uptime = proc.startedAt ? Date.now() - proc.startedAt : null;
|
|
4115
|
-
return helpers.success(
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4348
|
+
return helpers.success(
|
|
4349
|
+
JSON.stringify(
|
|
4350
|
+
{
|
|
4351
|
+
process: proc,
|
|
4352
|
+
uptime
|
|
4353
|
+
},
|
|
4354
|
+
null,
|
|
4355
|
+
2
|
|
4356
|
+
)
|
|
4357
|
+
);
|
|
4119
4358
|
}
|
|
4120
4359
|
case "logs": {
|
|
4121
4360
|
const proc = getProcessStatus(args.processId, sessionId);
|
|
@@ -4125,14 +4364,20 @@ These processes run independently of agent turns and persist across session comp
|
|
|
4125
4364
|
const since = args.since ?? 0;
|
|
4126
4365
|
const maxLines = Math.min(args.maxLines ?? 500, 2e3);
|
|
4127
4366
|
const { lines, totalLines, nextOffset, hasMore } = getProcessLogs(args.processId, since, maxLines);
|
|
4128
|
-
return helpers.success(
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4367
|
+
return helpers.success(
|
|
4368
|
+
JSON.stringify(
|
|
4369
|
+
{
|
|
4370
|
+
processId: args.processId,
|
|
4371
|
+
lines,
|
|
4372
|
+
totalLines,
|
|
4373
|
+
nextOffset,
|
|
4374
|
+
hasMore,
|
|
4375
|
+
truncated: hasMore
|
|
4376
|
+
},
|
|
4377
|
+
null,
|
|
4378
|
+
2
|
|
4379
|
+
)
|
|
4380
|
+
);
|
|
4136
4381
|
}
|
|
4137
4382
|
default:
|
|
4138
4383
|
return helpers.error(`Unknown action: ${args.action}`);
|
|
@@ -4384,11 +4629,7 @@ async function performContextCompaction(options) {
|
|
|
4384
4629
|
const eventStore = getEventStore();
|
|
4385
4630
|
const session = sessionManager.requireSession(sessionId);
|
|
4386
4631
|
const { content: instructions, files } = await getAllInstructions(session.workdir, session.projectId);
|
|
4387
|
-
const injectedFiles = files
|
|
4388
|
-
path: file.path,
|
|
4389
|
-
content: file.content ?? "",
|
|
4390
|
-
source: file.source
|
|
4391
|
-
}));
|
|
4632
|
+
const injectedFiles = toInjectedFiles(files);
|
|
4392
4633
|
const requestMessages = toRequestContextMessages2(getContextMessages(sessionId));
|
|
4393
4634
|
const config = getRuntimeConfig();
|
|
4394
4635
|
const allAgents = await loadAllAgentsDefault();
|
|
@@ -4414,20 +4655,23 @@ async function performContextCompaction(options) {
|
|
|
4414
4655
|
const compactionReminder = `<system-reminder>
|
|
4415
4656
|
${COMPACTION_PROMPT}
|
|
4416
4657
|
</system-reminder>`;
|
|
4417
|
-
const llmMessages = [
|
|
4418
|
-
...assembledRequest.messages,
|
|
4419
|
-
{ role: "user", content: compactionReminder }
|
|
4420
|
-
];
|
|
4658
|
+
const llmMessages = [...assembledRequest.messages, { role: "user", content: compactionReminder }];
|
|
4421
4659
|
const compactPromptMsgId = crypto.randomUUID();
|
|
4422
|
-
eventStore.append(
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4660
|
+
eventStore.append(
|
|
4661
|
+
sessionId,
|
|
4662
|
+
createMessageStartEvent(compactPromptMsgId, "user", COMPACTION_PROMPT, {
|
|
4663
|
+
...getCurrentWindowMessageOptions3(sessionId) ?? {},
|
|
4664
|
+
isSystemGenerated: true,
|
|
4665
|
+
messageKind: "auto-prompt",
|
|
4666
|
+
metadata: { type: "compaction", name: "Compaction", color: "#64748b" }
|
|
4667
|
+
})
|
|
4668
|
+
);
|
|
4428
4669
|
eventStore.append(sessionId, { type: "message.done", data: { messageId: compactPromptMsgId } });
|
|
4429
4670
|
const assistantMsgId = crypto.randomUUID();
|
|
4430
|
-
eventStore.append(
|
|
4671
|
+
eventStore.append(
|
|
4672
|
+
sessionId,
|
|
4673
|
+
createMessageStartEvent(assistantMsgId, "assistant", void 0, getCurrentWindowMessageOptions3(sessionId))
|
|
4674
|
+
);
|
|
4431
4675
|
const turnMetrics = new TurnMetrics();
|
|
4432
4676
|
const compactionToolRegistry = {
|
|
4433
4677
|
execute: async (name, args, ctx) => {
|
|
@@ -4545,4 +4789,4 @@ export {
|
|
|
4545
4789
|
getToolRegistryForAgent,
|
|
4546
4790
|
createToolRegistry
|
|
4547
4791
|
};
|
|
4548
|
-
//# sourceMappingURL=chunk-
|
|
4792
|
+
//# sourceMappingURL=chunk-EBQYRNNU.js.map
|