jinzd-ai-cli 0.4.190 → 0.4.193
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{batch-HF5RWUBL.js → batch-M6367YB4.js} +2 -2
- package/dist/{chunk-NV6W7TZW.js → chunk-7PX3ZX4G.js} +1 -1
- package/dist/{chunk-IQ7JE43O.js → chunk-BGXQGCEO.js} +3 -885
- package/dist/{chunk-ZN5IEPSS.js → chunk-IFETB4PY.js} +1 -1
- package/dist/chunk-JOR572WG.js +1058 -0
- package/dist/{chunk-JATZIZJV.js → chunk-MI23I43Y.js} +2 -2
- package/dist/{chunk-4KMDKDAK.js → chunk-P3PTUSP4.js} +1 -1
- package/dist/{chunk-UVW3WLSV.js → chunk-PO3ZY3PN.js} +1 -1
- package/dist/{chunk-KHS7RSGR.js → chunk-SHI5UFUH.js} +1 -1
- package/dist/{chunk-5CLH6XAW.js → chunk-SI5EO3NJ.js} +43 -55
- package/dist/{chunk-X4J2DZB5.js → chunk-VQT27CZK.js} +1 -1
- package/dist/{ci-X24WFUDF.js → ci-4MJ4EGKQ.js} +4 -4
- package/dist/{constants-4QBBHLU4.js → constants-LEU54VQQ.js} +1 -1
- package/dist/{doctor-cli-EUOCY7VN.js → doctor-cli-4RKSIH7N.js} +6 -6
- package/dist/electron-server.js +177 -104
- package/dist/{hub-YW3KLBZM.js → hub-XMUI5HMK.js} +1 -1
- package/dist/index.js +71 -118
- package/dist/{run-tests-OTZE5CEN.js → run-tests-4QWMA4ZF.js} +1 -1
- package/dist/{run-tests-7ZUNEUEX.js → run-tests-IL4342SV.js} +2 -2
- package/dist/{server-WMLZOLD5.js → server-KE7X3BHW.js} +45 -70
- package/dist/{server-YMCGJOXV.js → server-Y7TCCIGA.js} +5 -5
- package/dist/{task-orchestrator-DEWKVJGQ.js → task-orchestrator-RI63ZZNN.js} +37 -65
- package/dist/{usage-5LMWDGZ4.js → usage-CG7PJ3AB.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-HIU2SH4V.js +0 -64
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
truncateForPersist
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SI5EO3NJ.js";
|
|
5
5
|
import {
|
|
6
6
|
APP_NAME,
|
|
7
7
|
CONFIG_DIR_NAME,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
MCP_PROTOCOL_VERSION,
|
|
12
12
|
MCP_TOOL_PREFIX,
|
|
13
13
|
VERSION
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-P3PTUSP4.js";
|
|
15
15
|
|
|
16
16
|
// src/mcp/client.ts
|
|
17
17
|
import { spawn } from "child_process";
|
|
@@ -5,14 +5,15 @@ import {
|
|
|
5
5
|
} from "./chunk-T2NL5ZIA.js";
|
|
6
6
|
import {
|
|
7
7
|
runTestsTool
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7PX3ZX4G.js";
|
|
9
9
|
import {
|
|
10
10
|
runTool
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SHI5UFUH.js";
|
|
12
12
|
import {
|
|
13
13
|
getDangerLevel,
|
|
14
|
-
isFileWriteTool
|
|
15
|
-
|
|
14
|
+
isFileWriteTool,
|
|
15
|
+
runLeanAgentLoop
|
|
16
|
+
} from "./chunk-JOR572WG.js";
|
|
16
17
|
import {
|
|
17
18
|
EnvLoader,
|
|
18
19
|
NetworkError,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
SUBAGENT_ALLOWED_TOOLS,
|
|
26
27
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
27
28
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
28
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-P3PTUSP4.js";
|
|
29
30
|
import {
|
|
30
31
|
fileCheckpoints
|
|
31
32
|
} from "./chunk-4BKXL7SM.js";
|
|
@@ -3801,9 +3802,19 @@ ${preamble}`;
|
|
|
3801
3802
|
}
|
|
3802
3803
|
|
|
3803
3804
|
// src/tools/builtin/save-last-response.ts
|
|
3804
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
3805
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, rmdirSync as rmdirSync2 } from "fs";
|
|
3805
3806
|
import { dirname as dirname3 } from "path";
|
|
3806
3807
|
var lastResponseStore = { content: "" };
|
|
3808
|
+
function cleanupRejectedTeeFile(filePath) {
|
|
3809
|
+
try {
|
|
3810
|
+
unlinkSync2(filePath);
|
|
3811
|
+
} catch {
|
|
3812
|
+
}
|
|
3813
|
+
try {
|
|
3814
|
+
rmdirSync2(dirname3(filePath));
|
|
3815
|
+
} catch {
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3807
3818
|
var saveLastResponseTool = {
|
|
3808
3819
|
definition: {
|
|
3809
3820
|
name: "save_last_response",
|
|
@@ -4345,61 +4356,37 @@ async function runSubAgent(task, maxRounds, agentIndex, ctx) {
|
|
|
4345
4356
|
];
|
|
4346
4357
|
const subSystemPrompt = buildSubAgentSystemPrompt(task, ctx.systemPrompt);
|
|
4347
4358
|
const toolDefs = subRegistry.getDefinitions();
|
|
4348
|
-
const extraMessages = [];
|
|
4349
|
-
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
4350
|
-
let finalContent = "";
|
|
4351
4359
|
printSubAgentHeader(task, maxRounds, agentIndex);
|
|
4352
|
-
|
|
4353
|
-
|
|
4360
|
+
const loop = await runLeanAgentLoop({
|
|
4361
|
+
provider: ctx.provider,
|
|
4362
|
+
messages: subMessages,
|
|
4363
|
+
model: ctx.model,
|
|
4364
|
+
maxRounds,
|
|
4365
|
+
chatParams: {
|
|
4366
|
+
temperature: ctx.modelParams.temperature,
|
|
4367
|
+
maxTokens: ctx.modelParams.maxTokens,
|
|
4368
|
+
timeout: ctx.modelParams.timeout,
|
|
4369
|
+
thinking: ctx.modelParams.thinking
|
|
4370
|
+
},
|
|
4371
|
+
executeTools: (calls) => subExecutor.executeAll(calls),
|
|
4372
|
+
systemPromptForRound: () => subSystemPrompt,
|
|
4373
|
+
toolDefsForRound: () => toolDefs,
|
|
4374
|
+
onRoundStart: (round) => {
|
|
4354
4375
|
subExecutor.setRoundInfo(round + 1, maxRounds);
|
|
4355
|
-
const result = await ctx.provider.chatWithTools(
|
|
4356
|
-
{
|
|
4357
|
-
messages: subMessages,
|
|
4358
|
-
model: ctx.model,
|
|
4359
|
-
systemPrompt: subSystemPrompt,
|
|
4360
|
-
stream: false,
|
|
4361
|
-
temperature: ctx.modelParams.temperature,
|
|
4362
|
-
maxTokens: ctx.modelParams.maxTokens,
|
|
4363
|
-
timeout: ctx.modelParams.timeout,
|
|
4364
|
-
thinking: ctx.modelParams.thinking,
|
|
4365
|
-
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
4366
|
-
},
|
|
4367
|
-
toolDefs
|
|
4368
|
-
);
|
|
4369
|
-
if (result.usage) {
|
|
4370
|
-
totalUsage.inputTokens += result.usage.inputTokens;
|
|
4371
|
-
totalUsage.outputTokens += result.usage.outputTokens;
|
|
4372
|
-
}
|
|
4373
|
-
if ("content" in result) {
|
|
4374
|
-
finalContent = result.content;
|
|
4375
|
-
break;
|
|
4376
|
-
}
|
|
4377
4376
|
if (ctx.configManager) {
|
|
4378
4377
|
googleSearchContext.configManager = ctx.configManager;
|
|
4379
4378
|
}
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
toolResults,
|
|
4385
|
-
reasoningContent
|
|
4386
|
-
);
|
|
4387
|
-
extraMessages.push(...newMsgs);
|
|
4388
|
-
}
|
|
4389
|
-
if (!finalContent) {
|
|
4390
|
-
finalContent = `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`;
|
|
4391
|
-
}
|
|
4392
|
-
} catch (err) {
|
|
4393
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
4394
|
-
finalContent = `(Sub-agent error: ${errMsg})`;
|
|
4395
|
-
process.stderr.write(
|
|
4396
|
-
`
|
|
4379
|
+
},
|
|
4380
|
+
onRoundsExhausted: () => `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`,
|
|
4381
|
+
onError: (errMsg) => {
|
|
4382
|
+
process.stderr.write(`
|
|
4397
4383
|
[spawn_agent] Error in sub-agent loop: ${errMsg}
|
|
4398
|
-
`
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4384
|
+
`);
|
|
4385
|
+
return `(Sub-agent error: ${errMsg})`;
|
|
4386
|
+
}
|
|
4387
|
+
});
|
|
4388
|
+
printSubAgentFooter(loop.usage, agentIndex);
|
|
4389
|
+
return { content: loop.content, usage: loop.usage };
|
|
4403
4390
|
}
|
|
4404
4391
|
var spawnAgentTool = {
|
|
4405
4392
|
definition: {
|
|
@@ -5660,6 +5647,7 @@ export {
|
|
|
5660
5647
|
truncateOutput,
|
|
5661
5648
|
ToolExecutor,
|
|
5662
5649
|
lastResponseStore,
|
|
5650
|
+
cleanupRejectedTeeFile,
|
|
5663
5651
|
askUserContext,
|
|
5664
5652
|
googleSearchContext,
|
|
5665
5653
|
spawnAgentContext,
|
|
@@ -6,15 +6,15 @@ import {
|
|
|
6
6
|
} from "./chunk-HLWUDRBO.js";
|
|
7
7
|
import {
|
|
8
8
|
ProviderRegistry
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-BGXQGCEO.js";
|
|
10
|
+
import "./chunk-JOR572WG.js";
|
|
11
11
|
import {
|
|
12
12
|
ConfigManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VQT27CZK.js";
|
|
14
14
|
import "./chunk-TZQHYZKT.js";
|
|
15
15
|
import {
|
|
16
16
|
VERSION
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-P3PTUSP4.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/ci.ts
|
|
20
20
|
import { execFileSync, execSync } from "child_process";
|
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getConfigDirUsage,
|
|
4
4
|
listRecentCrashes
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PO3ZY3PN.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderRegistry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BGXQGCEO.js";
|
|
9
9
|
import {
|
|
10
10
|
getStatsSnapshot,
|
|
11
11
|
getTopFailingTools,
|
|
12
12
|
getTopUsedTools,
|
|
13
13
|
resetStats
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-SHI5UFUH.js";
|
|
15
|
+
import "./chunk-JOR572WG.js";
|
|
16
16
|
import {
|
|
17
17
|
ConfigManager
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VQT27CZK.js";
|
|
19
19
|
import "./chunk-TZQHYZKT.js";
|
|
20
20
|
import {
|
|
21
21
|
DEV_STATE_FILE_NAME,
|
|
22
22
|
MEMORY_FILE_NAME,
|
|
23
23
|
VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-P3PTUSP4.js";
|
|
25
25
|
import "./chunk-IW3Q7AE5.js";
|
|
26
26
|
|
|
27
27
|
// src/diagnostics/doctor-cli.ts
|
package/dist/electron-server.js
CHANGED
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
VERSION,
|
|
37
37
|
buildUserIdentityPrompt,
|
|
38
38
|
runTestsTool
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-IFETB4PY.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -1965,6 +1965,71 @@ You are now in a CONTENT-ONLY streaming pass. The file at the configured path wi
|
|
|
1965
1965
|
- If you accidentally start a <tool_call>, STOP and produce the document body instead.
|
|
1966
1966
|
|
|
1967
1967
|
The file is closed and named when this stream ends. If your output contains pseudo-tool-call markup, the save will be REJECTED and you will be asked to retry.`;
|
|
1968
|
+
function isCleanDocumentBody(content) {
|
|
1969
|
+
if (!content) return false;
|
|
1970
|
+
if (detectMetaNarration(content)) return false;
|
|
1971
|
+
if (detectPseudoToolCalls(content)) return false;
|
|
1972
|
+
return looksLikeDocumentBody(content);
|
|
1973
|
+
}
|
|
1974
|
+
function teeFileStats(content) {
|
|
1975
|
+
return { lines: content.split("\n").length, bytes: Buffer.byteLength(content, "utf-8") };
|
|
1976
|
+
}
|
|
1977
|
+
function evaluateTeeContent(rawContent, saveToFile, priorContent) {
|
|
1978
|
+
const fallback = (matched) => {
|
|
1979
|
+
if (priorContent && priorContent !== rawContent && isCleanDocumentBody(priorContent)) {
|
|
1980
|
+
const body = priorContent.trim();
|
|
1981
|
+
const { lines: lines2, bytes: bytes2 } = teeFileStats(body);
|
|
1982
|
+
return {
|
|
1983
|
+
kind: "fallback",
|
|
1984
|
+
content: body,
|
|
1985
|
+
matched,
|
|
1986
|
+
summary: `File saved (fallback to last shown response): ${saveToFile} (${lines2} lines, ${bytes2} bytes). The fresh content-only stream produced no usable document body (matched: ${matched}); saved the response you previously displayed instead. Verify it is the intended document.`
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
return null;
|
|
1990
|
+
};
|
|
1991
|
+
const metaMatch = detectMetaNarration(rawContent);
|
|
1992
|
+
if (metaMatch) {
|
|
1993
|
+
return fallback(metaMatch) ?? {
|
|
1994
|
+
kind: "reject",
|
|
1995
|
+
reason: "meta-narration",
|
|
1996
|
+
matched: metaMatch,
|
|
1997
|
+
summary: `[save_last_response REJECTED] Your output was internal reasoning / meta-narration (e.g. "Let me re-read\u2026", "the user is asking me to\u2026") instead of the requested document body (matched: ${metaMatch}). ${saveToFile} was NOT saved.
|
|
1998
|
+
|
|
1999
|
+
This fresh stream has NO tools. Produce ONLY the document body: start with a markdown heading like "# \u5BA1\u8BA1\u62A5\u544A" / "# Audit Report" and write the full content. Do NOT narrate that you will produce the document \u2014 produce it.`
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
const pseudoMatch = detectPseudoToolCalls(rawContent);
|
|
2003
|
+
if (pseudoMatch) {
|
|
2004
|
+
const cleaned = stripPseudoToolCalls(rawContent);
|
|
2005
|
+
if (looksLikeDocumentBody(cleaned)) {
|
|
2006
|
+
const { lines: lines2, bytes: bytes2 } = teeFileStats(cleaned);
|
|
2007
|
+
return {
|
|
2008
|
+
kind: "salvaged",
|
|
2009
|
+
content: cleaned,
|
|
2010
|
+
matched: pseudoMatch,
|
|
2011
|
+
summary: `File saved (with cleanup): ${saveToFile} (${lines2} lines, ${bytes2} bytes; pseudo-tool-call markup matching ${pseudoMatch} was stripped before save)`
|
|
2012
|
+
};
|
|
2013
|
+
}
|
|
2014
|
+
return fallback(pseudoMatch) ?? {
|
|
2015
|
+
kind: "reject",
|
|
2016
|
+
reason: "pseudo-tool-call",
|
|
2017
|
+
matched: pseudoMatch,
|
|
2018
|
+
summary: `[save_last_response REJECTED] Your output was tool-call markup with no usable document body (matched: ${pseudoMatch}). ${saveToFile} was NOT saved.
|
|
2019
|
+
|
|
2020
|
+
This fresh stream has NO tools \u2014 output is captured verbatim. STOP emitting <tool_call>, <function_calls>, <invoke>, <think>, or JSON tool blocks. Produce the document body NOW: start with a markdown heading like "# \u5BA1\u8BA1\u62A5\u544A" and write the full report.`
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
const { lines, bytes } = teeFileStats(rawContent);
|
|
2024
|
+
return {
|
|
2025
|
+
kind: "ok",
|
|
2026
|
+
content: rawContent,
|
|
2027
|
+
summary: `File saved: ${saveToFile} (${lines} lines, ${bytes} bytes)`
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
function teeStreamErrorSummary(saveToFile, errMsg) {
|
|
2031
|
+
return `[save_last_response failed] streaming was interrupted: ${errMsg}. ${saveToFile} (partial) was deleted. Retry \u2014 and consider producing a more compact output (split very large reports across multiple save_last_response calls if the previous attempt timed out).`;
|
|
2032
|
+
}
|
|
1968
2033
|
|
|
1969
2034
|
// src/core/agent-loop.ts
|
|
1970
2035
|
function partialTagTail(s, tag) {
|
|
@@ -2414,6 +2479,52 @@ function summarizeRecentTools(history, interval) {
|
|
|
2414
2479
|
}
|
|
2415
2480
|
return [...counts.entries()].sort((a, b) => b[1] - a[1]).map(([name, count]) => count > 1 ? `${name}\xD7${count}` : name).join(", ");
|
|
2416
2481
|
}
|
|
2482
|
+
async function runLeanAgentLoop(opts) {
|
|
2483
|
+
const extraMessages = [];
|
|
2484
|
+
const usage = { inputTokens: 0, outputTokens: 0 };
|
|
2485
|
+
let content = "";
|
|
2486
|
+
let roundsUsed = 0;
|
|
2487
|
+
let toolCallCount = 0;
|
|
2488
|
+
try {
|
|
2489
|
+
for (let round = 0; round < opts.maxRounds; round++) {
|
|
2490
|
+
roundsUsed = round + 1;
|
|
2491
|
+
opts.onRoundStart?.(round, opts.maxRounds);
|
|
2492
|
+
const result = await opts.provider.chatWithTools(
|
|
2493
|
+
{
|
|
2494
|
+
messages: opts.messages,
|
|
2495
|
+
model: opts.model,
|
|
2496
|
+
systemPrompt: opts.systemPromptForRound(round, opts.maxRounds - round),
|
|
2497
|
+
stream: false,
|
|
2498
|
+
temperature: opts.chatParams?.temperature,
|
|
2499
|
+
maxTokens: opts.chatParams?.maxTokens,
|
|
2500
|
+
timeout: opts.chatParams?.timeout,
|
|
2501
|
+
thinking: opts.chatParams?.thinking,
|
|
2502
|
+
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
2503
|
+
},
|
|
2504
|
+
opts.toolDefsForRound(round)
|
|
2505
|
+
);
|
|
2506
|
+
if (result.usage) {
|
|
2507
|
+
usage.inputTokens += result.usage.inputTokens;
|
|
2508
|
+
usage.outputTokens += result.usage.outputTokens;
|
|
2509
|
+
}
|
|
2510
|
+
if ("content" in result) {
|
|
2511
|
+
content = result.content;
|
|
2512
|
+
break;
|
|
2513
|
+
}
|
|
2514
|
+
toolCallCount += result.toolCalls.length;
|
|
2515
|
+
const toolResults = await opts.executeTools(result.toolCalls);
|
|
2516
|
+
const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
|
|
2517
|
+
extraMessages.push(
|
|
2518
|
+
...opts.provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent)
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
if (!content) content = opts.onRoundsExhausted(toolCallCount);
|
|
2522
|
+
} catch (err) {
|
|
2523
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2524
|
+
content = opts.onError(errMsg);
|
|
2525
|
+
}
|
|
2526
|
+
return { content, usage, roundsUsed, toolCallCount };
|
|
2527
|
+
}
|
|
2417
2528
|
|
|
2418
2529
|
// src/providers/openai-compatible.ts
|
|
2419
2530
|
function toUsage(u) {
|
|
@@ -8329,9 +8440,19 @@ ${preamble}`;
|
|
|
8329
8440
|
}
|
|
8330
8441
|
|
|
8331
8442
|
// src/tools/builtin/save-last-response.ts
|
|
8332
|
-
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
8443
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3, rmdirSync as rmdirSync2 } from "fs";
|
|
8333
8444
|
import { dirname as dirname4 } from "path";
|
|
8334
8445
|
var lastResponseStore = { content: "" };
|
|
8446
|
+
function cleanupRejectedTeeFile(filePath) {
|
|
8447
|
+
try {
|
|
8448
|
+
unlinkSync3(filePath);
|
|
8449
|
+
} catch {
|
|
8450
|
+
}
|
|
8451
|
+
try {
|
|
8452
|
+
rmdirSync2(dirname4(filePath));
|
|
8453
|
+
} catch {
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8335
8456
|
var saveLastResponseTool = {
|
|
8336
8457
|
definition: {
|
|
8337
8458
|
name: "save_last_response",
|
|
@@ -8873,61 +8994,37 @@ async function runSubAgent(task, maxRounds, agentIndex, ctx) {
|
|
|
8873
8994
|
];
|
|
8874
8995
|
const subSystemPrompt = buildSubAgentSystemPrompt(task, ctx.systemPrompt);
|
|
8875
8996
|
const toolDefs = subRegistry.getDefinitions();
|
|
8876
|
-
const extraMessages = [];
|
|
8877
|
-
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
8878
|
-
let finalContent = "";
|
|
8879
8997
|
printSubAgentHeader(task, maxRounds, agentIndex);
|
|
8880
|
-
|
|
8881
|
-
|
|
8998
|
+
const loop = await runLeanAgentLoop({
|
|
8999
|
+
provider: ctx.provider,
|
|
9000
|
+
messages: subMessages,
|
|
9001
|
+
model: ctx.model,
|
|
9002
|
+
maxRounds,
|
|
9003
|
+
chatParams: {
|
|
9004
|
+
temperature: ctx.modelParams.temperature,
|
|
9005
|
+
maxTokens: ctx.modelParams.maxTokens,
|
|
9006
|
+
timeout: ctx.modelParams.timeout,
|
|
9007
|
+
thinking: ctx.modelParams.thinking
|
|
9008
|
+
},
|
|
9009
|
+
executeTools: (calls) => subExecutor.executeAll(calls),
|
|
9010
|
+
systemPromptForRound: () => subSystemPrompt,
|
|
9011
|
+
toolDefsForRound: () => toolDefs,
|
|
9012
|
+
onRoundStart: (round) => {
|
|
8882
9013
|
subExecutor.setRoundInfo(round + 1, maxRounds);
|
|
8883
|
-
const result = await ctx.provider.chatWithTools(
|
|
8884
|
-
{
|
|
8885
|
-
messages: subMessages,
|
|
8886
|
-
model: ctx.model,
|
|
8887
|
-
systemPrompt: subSystemPrompt,
|
|
8888
|
-
stream: false,
|
|
8889
|
-
temperature: ctx.modelParams.temperature,
|
|
8890
|
-
maxTokens: ctx.modelParams.maxTokens,
|
|
8891
|
-
timeout: ctx.modelParams.timeout,
|
|
8892
|
-
thinking: ctx.modelParams.thinking,
|
|
8893
|
-
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
8894
|
-
},
|
|
8895
|
-
toolDefs
|
|
8896
|
-
);
|
|
8897
|
-
if (result.usage) {
|
|
8898
|
-
totalUsage.inputTokens += result.usage.inputTokens;
|
|
8899
|
-
totalUsage.outputTokens += result.usage.outputTokens;
|
|
8900
|
-
}
|
|
8901
|
-
if ("content" in result) {
|
|
8902
|
-
finalContent = result.content;
|
|
8903
|
-
break;
|
|
8904
|
-
}
|
|
8905
9014
|
if (ctx.configManager) {
|
|
8906
9015
|
googleSearchContext.configManager = ctx.configManager;
|
|
8907
9016
|
}
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
toolResults,
|
|
8913
|
-
reasoningContent
|
|
8914
|
-
);
|
|
8915
|
-
extraMessages.push(...newMsgs);
|
|
8916
|
-
}
|
|
8917
|
-
if (!finalContent) {
|
|
8918
|
-
finalContent = `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`;
|
|
8919
|
-
}
|
|
8920
|
-
} catch (err) {
|
|
8921
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
8922
|
-
finalContent = `(Sub-agent error: ${errMsg})`;
|
|
8923
|
-
process.stderr.write(
|
|
8924
|
-
`
|
|
9017
|
+
},
|
|
9018
|
+
onRoundsExhausted: () => `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`,
|
|
9019
|
+
onError: (errMsg) => {
|
|
9020
|
+
process.stderr.write(`
|
|
8925
9021
|
[spawn_agent] Error in sub-agent loop: ${errMsg}
|
|
8926
|
-
`
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
9022
|
+
`);
|
|
9023
|
+
return `(Sub-agent error: ${errMsg})`;
|
|
9024
|
+
}
|
|
9025
|
+
});
|
|
9026
|
+
printSubAgentFooter(loop.usage, agentIndex);
|
|
9027
|
+
return { content: loop.content, usage: loop.usage };
|
|
8931
9028
|
}
|
|
8932
9029
|
var spawnAgentTool = {
|
|
8933
9030
|
definition: {
|
|
@@ -11174,7 +11271,7 @@ import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
|
11174
11271
|
import { join as join12 } from "path";
|
|
11175
11272
|
|
|
11176
11273
|
// src/repl/dev-state.ts
|
|
11177
|
-
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync6, unlinkSync as
|
|
11274
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, mkdirSync as mkdirSync9 } from "fs";
|
|
11178
11275
|
import { join as join11 } from "path";
|
|
11179
11276
|
import { homedir as homedir6 } from "os";
|
|
11180
11277
|
function getDevStatePath() {
|
|
@@ -11448,7 +11545,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
11448
11545
|
}
|
|
11449
11546
|
|
|
11450
11547
|
// src/web/session-handler.ts
|
|
11451
|
-
import { existsSync as existsSync21, readFileSync as readFileSync14, appendFileSync as appendFileSync3, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10, readdirSync as readdirSync9, statSync as statSync8, createWriteStream
|
|
11548
|
+
import { existsSync as existsSync21, readFileSync as readFileSync14, appendFileSync as appendFileSync3, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10, readdirSync as readdirSync9, statSync as statSync8, createWriteStream } from "fs";
|
|
11452
11549
|
import { join as join15, resolve as resolve5, dirname as dirname5 } from "path";
|
|
11453
11550
|
import { execSync as execSync3 } from "child_process";
|
|
11454
11551
|
|
|
@@ -12156,6 +12253,20 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
|
|
|
12156
12253
|
}
|
|
12157
12254
|
|
|
12158
12255
|
// src/web/session-handler.ts
|
|
12256
|
+
function lastAssistantText(messages) {
|
|
12257
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
12258
|
+
const m = messages[i];
|
|
12259
|
+
if (!m || m.role !== "assistant") continue;
|
|
12260
|
+
const c = m.content;
|
|
12261
|
+
if (typeof c === "string") return c;
|
|
12262
|
+
if (Array.isArray(c)) {
|
|
12263
|
+
const text = c.filter((p) => p && p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
|
|
12264
|
+
if (text) return text;
|
|
12265
|
+
}
|
|
12266
|
+
return void 0;
|
|
12267
|
+
}
|
|
12268
|
+
return void 0;
|
|
12269
|
+
}
|
|
12159
12270
|
var SessionHandler = class _SessionHandler {
|
|
12160
12271
|
ws;
|
|
12161
12272
|
config;
|
|
@@ -12965,53 +13076,18 @@ ${summaryContent}`,
|
|
|
12965
13076
|
await new Promise((resolve7, reject) => {
|
|
12966
13077
|
fileStream.end((err) => err ? reject(err) : resolve7());
|
|
12967
13078
|
});
|
|
12968
|
-
const
|
|
12969
|
-
if (
|
|
12970
|
-
|
|
12971
|
-
unlinkSync4(saveToFile);
|
|
12972
|
-
} catch {
|
|
12973
|
-
}
|
|
13079
|
+
const verdict = evaluateTeeContent(fullContent, saveToFile, lastAssistantText(apiMessages));
|
|
13080
|
+
if (verdict.kind === "reject") {
|
|
13081
|
+
cleanupRejectedTeeFile(saveToFile);
|
|
12974
13082
|
isError = true;
|
|
12975
|
-
summary =
|
|
12976
|
-
|
|
12977
|
-
This fresh stream has NO tools. Produce ONLY the document body: start with a markdown heading and write the full content. Do NOT narrate that you will produce the document \u2014 produce it.`;
|
|
12978
|
-
if (teeUsage) {
|
|
12979
|
-
roundUsage.inputTokens += teeUsage.inputTokens;
|
|
12980
|
-
roundUsage.outputTokens += teeUsage.outputTokens;
|
|
12981
|
-
roundUsage.cacheCreationTokens += teeUsage.cacheCreationTokens ?? 0;
|
|
12982
|
-
roundUsage.cacheReadTokens += teeUsage.cacheReadTokens ?? 0;
|
|
12983
|
-
}
|
|
12984
|
-
this.send({
|
|
12985
|
-
type: "tool_call_result",
|
|
12986
|
-
callId: call.id,
|
|
12987
|
-
toolName: call.name,
|
|
12988
|
-
content: summary,
|
|
12989
|
-
isError: true
|
|
12990
|
-
});
|
|
12991
|
-
return { content: "", summary, isError: true };
|
|
12992
|
-
}
|
|
12993
|
-
const pseudoMatch = detectPseudoToolCalls(fullContent);
|
|
12994
|
-
if (pseudoMatch) {
|
|
12995
|
-
const cleaned = stripPseudoToolCalls(fullContent);
|
|
12996
|
-
if (looksLikeDocumentBody(cleaned)) {
|
|
12997
|
-
writeFileSync7(saveToFile, cleaned, "utf-8");
|
|
12998
|
-
fullContent = cleaned;
|
|
12999
|
-
const lines = cleaned.split("\n").length;
|
|
13000
|
-
const bytes = Buffer.byteLength(cleaned, "utf-8");
|
|
13001
|
-
summary = `File saved (with cleanup): ${saveToFile} (${lines} lines, ${bytes} bytes; pseudo-tool-call markup matching ${pseudoMatch} was stripped before save)`;
|
|
13002
|
-
undoStack.push(saveToFile, `save_last_response: ${saveToFile}`);
|
|
13003
|
-
} else {
|
|
13004
|
-
try {
|
|
13005
|
-
unlinkSync4(saveToFile);
|
|
13006
|
-
} catch {
|
|
13007
|
-
}
|
|
13008
|
-
isError = true;
|
|
13009
|
-
summary = `[save_last_response REJECTED] Your output was tool-call markup with no usable document body (matched: ${pseudoMatch}). ${saveToFile} was NOT saved. This fresh stream has NO tools \u2014 output is captured verbatim. STOP emitting <tool_call>, <function_calls>, <invoke>, <think>, or JSON tool blocks. Produce the document body NOW: start with a markdown heading and write the full content.`;
|
|
13010
|
-
}
|
|
13083
|
+
summary = verdict.summary;
|
|
13084
|
+
fullContent = "";
|
|
13011
13085
|
} else {
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13086
|
+
if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
|
|
13087
|
+
writeFileSync7(saveToFile, verdict.content, "utf-8");
|
|
13088
|
+
fullContent = verdict.content;
|
|
13089
|
+
}
|
|
13090
|
+
summary = verdict.summary;
|
|
13015
13091
|
undoStack.push(saveToFile, `save_last_response: ${saveToFile}`);
|
|
13016
13092
|
}
|
|
13017
13093
|
if (teeUsage) {
|
|
@@ -13027,13 +13103,10 @@ This fresh stream has NO tools. Produce ONLY the document body: start with a mar
|
|
|
13027
13103
|
} catch {
|
|
13028
13104
|
}
|
|
13029
13105
|
}
|
|
13030
|
-
|
|
13031
|
-
unlinkSync4(saveToFile);
|
|
13032
|
-
} catch {
|
|
13033
|
-
}
|
|
13106
|
+
cleanupRejectedTeeFile(saveToFile);
|
|
13034
13107
|
isError = true;
|
|
13035
13108
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13036
|
-
summary =
|
|
13109
|
+
summary = teeStreamErrorSummary(saveToFile, msg);
|
|
13037
13110
|
}
|
|
13038
13111
|
this.send({
|
|
13039
13112
|
type: "tool_call_result",
|
|
@@ -14076,7 +14149,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
14076
14149
|
case "test": {
|
|
14077
14150
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
14078
14151
|
try {
|
|
14079
|
-
const { executeTests } = await import("./run-tests-
|
|
14152
|
+
const { executeTests } = await import("./run-tests-4QWMA4ZF.js");
|
|
14080
14153
|
const argStr = args.join(" ").trim();
|
|
14081
14154
|
let testArgs = {};
|
|
14082
14155
|
if (argStr) {
|
|
@@ -154,7 +154,7 @@ ${content}`);
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
157
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
157
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-RI63ZZNN.js");
|
|
158
158
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
159
159
|
let interrupted = false;
|
|
160
160
|
const onSigint = () => {
|