jinzd-ai-cli 0.4.191 → 0.4.194
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-4XSN4VF7.js → batch-XGARS57W.js} +2 -2
- package/dist/{chunk-JTLPYPT3.js → chunk-2BLBXGOE.js} +3 -929
- package/dist/{chunk-HSQAKOYX.js → chunk-3KCEPI4E.js} +1 -1
- package/dist/{chunk-TRV47UK4.js → chunk-5IVUINDO.js} +1 -1
- package/dist/{chunk-IMSENBJ6.js → chunk-6VMXFFO3.js} +2 -2
- package/dist/{chunk-Y3PNCW7A.js → chunk-CKBBAXCA.js} +1 -1
- package/dist/{chunk-6Z42O3DN.js → chunk-LTBUGDLE.js} +1 -1
- package/dist/{chunk-ASVBZIUE.js → chunk-ZEHHAE3B.js} +1 -1
- package/dist/{chunk-RQ7JVLFM.js → chunk-ZJX6ZU5D.js} +43 -55
- package/dist/chunk-ZRG2FPC6.js +1066 -0
- package/dist/{chunk-XDH5EFWC.js → chunk-ZVMXIRBH.js} +1 -1
- package/dist/{ci-USJCTRP7.js → ci-4TYLP7HF.js} +4 -4
- package/dist/{constants-3T5G34S5.js → constants-CDVYNTU7.js} +1 -1
- package/dist/{doctor-cli-3QE7FZKB.js → doctor-cli-Q3QFVEWQ.js} +6 -6
- package/dist/electron-server.js +159 -69
- package/dist/{hub-LABDYMAE.js → hub-UORFAHQ3.js} +1 -1
- package/dist/index.js +78 -47
- package/dist/{run-tests-X2MCBIKN.js → run-tests-A2I3WZ2H.js} +2 -2
- package/dist/{run-tests-H3VCHOJB.js → run-tests-RFK53W3D.js} +1 -1
- package/dist/{server-TJDKEECG.js → server-6NLQUZKD.js} +63 -27
- package/dist/{server-FE7XTYVC.js → server-RULXWZD4.js} +5 -5
- package/dist/{task-orchestrator-VFCQGTYA.js → task-orchestrator-GJBPVYFW.js} +37 -65
- package/dist/{usage-FYKIOPJI.js → usage-7DVISDK2.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-HIU2SH4V.js +0 -64
|
@@ -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-2BLBXGOE.js";
|
|
10
|
+
import "./chunk-ZRG2FPC6.js";
|
|
11
11
|
import {
|
|
12
12
|
ConfigManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZVMXIRBH.js";
|
|
14
14
|
import "./chunk-TZQHYZKT.js";
|
|
15
15
|
import {
|
|
16
16
|
VERSION
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZEHHAE3B.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-5IVUINDO.js";
|
|
6
6
|
import {
|
|
7
7
|
ProviderRegistry
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2BLBXGOE.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-CKBBAXCA.js";
|
|
15
|
+
import "./chunk-ZRG2FPC6.js";
|
|
16
16
|
import {
|
|
17
17
|
ConfigManager
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZVMXIRBH.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-ZEHHAE3B.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-LTBUGDLE.js";
|
|
40
40
|
import {
|
|
41
41
|
hasSemanticIndex,
|
|
42
42
|
semanticSearch
|
|
@@ -1965,13 +1965,32 @@ 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
|
+
}
|
|
1968
1974
|
function teeFileStats(content) {
|
|
1969
1975
|
return { lines: content.split("\n").length, bytes: Buffer.byteLength(content, "utf-8") };
|
|
1970
1976
|
}
|
|
1971
|
-
function evaluateTeeContent(rawContent, saveToFile) {
|
|
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
|
+
};
|
|
1972
1991
|
const metaMatch = detectMetaNarration(rawContent);
|
|
1973
1992
|
if (metaMatch) {
|
|
1974
|
-
return {
|
|
1993
|
+
return fallback(metaMatch) ?? {
|
|
1975
1994
|
kind: "reject",
|
|
1976
1995
|
reason: "meta-narration",
|
|
1977
1996
|
matched: metaMatch,
|
|
@@ -1992,7 +2011,7 @@ This fresh stream has NO tools. Produce ONLY the document body: start with a mar
|
|
|
1992
2011
|
summary: `File saved (with cleanup): ${saveToFile} (${lines2} lines, ${bytes2} bytes; pseudo-tool-call markup matching ${pseudoMatch} was stripped before save)`
|
|
1993
2012
|
};
|
|
1994
2013
|
}
|
|
1995
|
-
return {
|
|
2014
|
+
return fallback(pseudoMatch) ?? {
|
|
1996
2015
|
kind: "reject",
|
|
1997
2016
|
reason: "pseudo-tool-call",
|
|
1998
2017
|
matched: pseudoMatch,
|
|
@@ -2008,6 +2027,12 @@ This fresh stream has NO tools \u2014 output is captured verbatim. STOP emitting
|
|
|
2008
2027
|
summary: `File saved: ${saveToFile} (${lines} lines, ${bytes} bytes)`
|
|
2009
2028
|
};
|
|
2010
2029
|
}
|
|
2030
|
+
function buildDeferredSaveInstruction(saveToFile) {
|
|
2031
|
+
return `[save_last_response \u65E0\u6CD5\u81EA\u52A8\u751F\u6210\u6587\u6863]
|
|
2032
|
+
content-only \u6D41\u4EA7\u51FA\u7684\u662F\u5DE5\u5177\u8C03\u7528\u6807\u8BB0 / \u5185\u5FC3\u72EC\u767D\u800C\u975E\u6587\u6863\u6B63\u6587\uFF0C${saveToFile} \u672A\u4FDD\u5B58\u3002
|
|
2033
|
+
|
|
2034
|
+
\u4E0D\u8981\u518D\u8C03\u7528 save_last_response\u3002\u8BF7\u76F4\u63A5\u7528**\u666E\u901A\u6587\u672C\u56DE\u590D**\u628A\u5B8C\u6574\u6587\u6863\u5199\u51FA\u6765\uFF1A\u7EAF markdown\uFF0C\u7B2C\u4E00\u4E2A\u5B57\u7B26\u5C31\u662F\u9876\u7EA7\u6807\u9898\uFF08\u5982 "# \u5BA1\u8BA1\u62A5\u544A"\uFF09\uFF0C\u4E0D\u8981\u4EFB\u4F55\u5DE5\u5177\u8C03\u7528\u3001\u4E0D\u8981\u524D\u8A00\u94FA\u57AB\u3002\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u628A\u4F60\u8FD9\u6761\u56DE\u590D\u4FDD\u5B58\u5230 ${saveToFile}\u3002`;
|
|
2035
|
+
}
|
|
2011
2036
|
function teeStreamErrorSummary(saveToFile, errMsg) {
|
|
2012
2037
|
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).`;
|
|
2013
2038
|
}
|
|
@@ -2460,6 +2485,52 @@ function summarizeRecentTools(history, interval) {
|
|
|
2460
2485
|
}
|
|
2461
2486
|
return [...counts.entries()].sort((a, b) => b[1] - a[1]).map(([name, count]) => count > 1 ? `${name}\xD7${count}` : name).join(", ");
|
|
2462
2487
|
}
|
|
2488
|
+
async function runLeanAgentLoop(opts) {
|
|
2489
|
+
const extraMessages = [];
|
|
2490
|
+
const usage = { inputTokens: 0, outputTokens: 0 };
|
|
2491
|
+
let content = "";
|
|
2492
|
+
let roundsUsed = 0;
|
|
2493
|
+
let toolCallCount = 0;
|
|
2494
|
+
try {
|
|
2495
|
+
for (let round = 0; round < opts.maxRounds; round++) {
|
|
2496
|
+
roundsUsed = round + 1;
|
|
2497
|
+
opts.onRoundStart?.(round, opts.maxRounds);
|
|
2498
|
+
const result = await opts.provider.chatWithTools(
|
|
2499
|
+
{
|
|
2500
|
+
messages: opts.messages,
|
|
2501
|
+
model: opts.model,
|
|
2502
|
+
systemPrompt: opts.systemPromptForRound(round, opts.maxRounds - round),
|
|
2503
|
+
stream: false,
|
|
2504
|
+
temperature: opts.chatParams?.temperature,
|
|
2505
|
+
maxTokens: opts.chatParams?.maxTokens,
|
|
2506
|
+
timeout: opts.chatParams?.timeout,
|
|
2507
|
+
thinking: opts.chatParams?.thinking,
|
|
2508
|
+
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
2509
|
+
},
|
|
2510
|
+
opts.toolDefsForRound(round)
|
|
2511
|
+
);
|
|
2512
|
+
if (result.usage) {
|
|
2513
|
+
usage.inputTokens += result.usage.inputTokens;
|
|
2514
|
+
usage.outputTokens += result.usage.outputTokens;
|
|
2515
|
+
}
|
|
2516
|
+
if ("content" in result) {
|
|
2517
|
+
content = result.content;
|
|
2518
|
+
break;
|
|
2519
|
+
}
|
|
2520
|
+
toolCallCount += result.toolCalls.length;
|
|
2521
|
+
const toolResults = await opts.executeTools(result.toolCalls);
|
|
2522
|
+
const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
|
|
2523
|
+
extraMessages.push(
|
|
2524
|
+
...opts.provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent)
|
|
2525
|
+
);
|
|
2526
|
+
}
|
|
2527
|
+
if (!content) content = opts.onRoundsExhausted(toolCallCount);
|
|
2528
|
+
} catch (err) {
|
|
2529
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2530
|
+
content = opts.onError(errMsg);
|
|
2531
|
+
}
|
|
2532
|
+
return { content, usage, roundsUsed, toolCallCount };
|
|
2533
|
+
}
|
|
2463
2534
|
|
|
2464
2535
|
// src/providers/openai-compatible.ts
|
|
2465
2536
|
function toUsage(u) {
|
|
@@ -8375,9 +8446,19 @@ ${preamble}`;
|
|
|
8375
8446
|
}
|
|
8376
8447
|
|
|
8377
8448
|
// src/tools/builtin/save-last-response.ts
|
|
8378
|
-
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
8449
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3, rmdirSync as rmdirSync2 } from "fs";
|
|
8379
8450
|
import { dirname as dirname4 } from "path";
|
|
8380
8451
|
var lastResponseStore = { content: "" };
|
|
8452
|
+
function cleanupRejectedTeeFile(filePath) {
|
|
8453
|
+
try {
|
|
8454
|
+
unlinkSync3(filePath);
|
|
8455
|
+
} catch {
|
|
8456
|
+
}
|
|
8457
|
+
try {
|
|
8458
|
+
rmdirSync2(dirname4(filePath));
|
|
8459
|
+
} catch {
|
|
8460
|
+
}
|
|
8461
|
+
}
|
|
8381
8462
|
var saveLastResponseTool = {
|
|
8382
8463
|
definition: {
|
|
8383
8464
|
name: "save_last_response",
|
|
@@ -8919,61 +9000,37 @@ async function runSubAgent(task, maxRounds, agentIndex, ctx) {
|
|
|
8919
9000
|
];
|
|
8920
9001
|
const subSystemPrompt = buildSubAgentSystemPrompt(task, ctx.systemPrompt);
|
|
8921
9002
|
const toolDefs = subRegistry.getDefinitions();
|
|
8922
|
-
const extraMessages = [];
|
|
8923
|
-
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
8924
|
-
let finalContent = "";
|
|
8925
9003
|
printSubAgentHeader(task, maxRounds, agentIndex);
|
|
8926
|
-
|
|
8927
|
-
|
|
9004
|
+
const loop = await runLeanAgentLoop({
|
|
9005
|
+
provider: ctx.provider,
|
|
9006
|
+
messages: subMessages,
|
|
9007
|
+
model: ctx.model,
|
|
9008
|
+
maxRounds,
|
|
9009
|
+
chatParams: {
|
|
9010
|
+
temperature: ctx.modelParams.temperature,
|
|
9011
|
+
maxTokens: ctx.modelParams.maxTokens,
|
|
9012
|
+
timeout: ctx.modelParams.timeout,
|
|
9013
|
+
thinking: ctx.modelParams.thinking
|
|
9014
|
+
},
|
|
9015
|
+
executeTools: (calls) => subExecutor.executeAll(calls),
|
|
9016
|
+
systemPromptForRound: () => subSystemPrompt,
|
|
9017
|
+
toolDefsForRound: () => toolDefs,
|
|
9018
|
+
onRoundStart: (round) => {
|
|
8928
9019
|
subExecutor.setRoundInfo(round + 1, maxRounds);
|
|
8929
|
-
const result = await ctx.provider.chatWithTools(
|
|
8930
|
-
{
|
|
8931
|
-
messages: subMessages,
|
|
8932
|
-
model: ctx.model,
|
|
8933
|
-
systemPrompt: subSystemPrompt,
|
|
8934
|
-
stream: false,
|
|
8935
|
-
temperature: ctx.modelParams.temperature,
|
|
8936
|
-
maxTokens: ctx.modelParams.maxTokens,
|
|
8937
|
-
timeout: ctx.modelParams.timeout,
|
|
8938
|
-
thinking: ctx.modelParams.thinking,
|
|
8939
|
-
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
8940
|
-
},
|
|
8941
|
-
toolDefs
|
|
8942
|
-
);
|
|
8943
|
-
if (result.usage) {
|
|
8944
|
-
totalUsage.inputTokens += result.usage.inputTokens;
|
|
8945
|
-
totalUsage.outputTokens += result.usage.outputTokens;
|
|
8946
|
-
}
|
|
8947
|
-
if ("content" in result) {
|
|
8948
|
-
finalContent = result.content;
|
|
8949
|
-
break;
|
|
8950
|
-
}
|
|
8951
9020
|
if (ctx.configManager) {
|
|
8952
9021
|
googleSearchContext.configManager = ctx.configManager;
|
|
8953
9022
|
}
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
toolResults,
|
|
8959
|
-
reasoningContent
|
|
8960
|
-
);
|
|
8961
|
-
extraMessages.push(...newMsgs);
|
|
8962
|
-
}
|
|
8963
|
-
if (!finalContent) {
|
|
8964
|
-
finalContent = `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`;
|
|
8965
|
-
}
|
|
8966
|
-
} catch (err) {
|
|
8967
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
8968
|
-
finalContent = `(Sub-agent error: ${errMsg})`;
|
|
8969
|
-
process.stderr.write(
|
|
8970
|
-
`
|
|
9023
|
+
},
|
|
9024
|
+
onRoundsExhausted: () => `(Sub-agent reached maximum rounds (${maxRounds}) without producing a final response)`,
|
|
9025
|
+
onError: (errMsg) => {
|
|
9026
|
+
process.stderr.write(`
|
|
8971
9027
|
[spawn_agent] Error in sub-agent loop: ${errMsg}
|
|
8972
|
-
`
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
9028
|
+
`);
|
|
9029
|
+
return `(Sub-agent error: ${errMsg})`;
|
|
9030
|
+
}
|
|
9031
|
+
});
|
|
9032
|
+
printSubAgentFooter(loop.usage, agentIndex);
|
|
9033
|
+
return { content: loop.content, usage: loop.usage };
|
|
8977
9034
|
}
|
|
8978
9035
|
var spawnAgentTool = {
|
|
8979
9036
|
definition: {
|
|
@@ -11220,7 +11277,7 @@ import { existsSync as existsSync19, readFileSync as readFileSync13 } from "fs";
|
|
|
11220
11277
|
import { join as join12 } from "path";
|
|
11221
11278
|
|
|
11222
11279
|
// src/repl/dev-state.ts
|
|
11223
|
-
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync6, unlinkSync as
|
|
11280
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, mkdirSync as mkdirSync9 } from "fs";
|
|
11224
11281
|
import { join as join11 } from "path";
|
|
11225
11282
|
import { homedir as homedir6 } from "os";
|
|
11226
11283
|
function getDevStatePath() {
|
|
@@ -11494,7 +11551,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
|
|
|
11494
11551
|
}
|
|
11495
11552
|
|
|
11496
11553
|
// src/web/session-handler.ts
|
|
11497
|
-
import { existsSync as existsSync21, readFileSync as readFileSync14, appendFileSync as appendFileSync3, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10, readdirSync as readdirSync9, statSync as statSync8, createWriteStream
|
|
11554
|
+
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";
|
|
11498
11555
|
import { join as join15, resolve as resolve5, dirname as dirname5 } from "path";
|
|
11499
11556
|
import { execSync as execSync3 } from "child_process";
|
|
11500
11557
|
|
|
@@ -12202,6 +12259,20 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
|
|
|
12202
12259
|
}
|
|
12203
12260
|
|
|
12204
12261
|
// src/web/session-handler.ts
|
|
12262
|
+
function lastAssistantText(messages) {
|
|
12263
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
12264
|
+
const m = messages[i];
|
|
12265
|
+
if (!m || m.role !== "assistant") continue;
|
|
12266
|
+
const c = m.content;
|
|
12267
|
+
if (typeof c === "string") return c;
|
|
12268
|
+
if (Array.isArray(c)) {
|
|
12269
|
+
const text = c.filter((p) => p && p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
|
|
12270
|
+
if (text) return text;
|
|
12271
|
+
}
|
|
12272
|
+
return void 0;
|
|
12273
|
+
}
|
|
12274
|
+
return void 0;
|
|
12275
|
+
}
|
|
12205
12276
|
var SessionHandler = class _SessionHandler {
|
|
12206
12277
|
ws;
|
|
12207
12278
|
config;
|
|
@@ -12695,6 +12766,7 @@ ${mcpBudgetNote}` : "");
|
|
|
12695
12766
|
const supportsStreamingTools = typeof provider.chatWithToolsStream === "function";
|
|
12696
12767
|
const ac = new AbortController();
|
|
12697
12768
|
this.abortController = ac;
|
|
12769
|
+
let pendingTeeSave = null;
|
|
12698
12770
|
try {
|
|
12699
12771
|
const loopResult = await runAgentLoop({
|
|
12700
12772
|
maxToolRounds,
|
|
@@ -12838,6 +12910,18 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
|
|
|
12838
12910
|
},
|
|
12839
12911
|
onFinalContent: (content, { reasoningContent }) => {
|
|
12840
12912
|
this.send({ type: "response_done", content, usage });
|
|
12913
|
+
if (pendingTeeSave && isCleanDocumentBody(content)) {
|
|
12914
|
+
try {
|
|
12915
|
+
mkdirSync10(dirname5(pendingTeeSave), { recursive: true });
|
|
12916
|
+
writeFileSync7(pendingTeeSave, content, "utf-8");
|
|
12917
|
+
undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
|
|
12918
|
+
const lines = content.split("\n").length;
|
|
12919
|
+
this.send({ type: "info", message: `\u2705 Saved (from reply): ${pendingTeeSave} (${lines} lines, ${content.length} chars)` });
|
|
12920
|
+
} catch (saveErr) {
|
|
12921
|
+
this.send({ type: "info", message: `\u2717 Could not save to ${pendingTeeSave}: ${saveErr.message ?? saveErr}` });
|
|
12922
|
+
}
|
|
12923
|
+
pendingTeeSave = null;
|
|
12924
|
+
}
|
|
12841
12925
|
session.addMessage({
|
|
12842
12926
|
role: "assistant",
|
|
12843
12927
|
content,
|
|
@@ -12895,6 +12979,15 @@ ${summaryContent}`,
|
|
|
12895
12979
|
// 与 REPL 不同:Web 端 tee 成功后继续 agentic 循环(返回 'continue'),
|
|
12896
12980
|
// 让模型基于工具结果给出最终文本。
|
|
12897
12981
|
runSaveLastResponseTee: async ({ toolCalls, call, saveToFile, extraMessages, reasoningContent }) => {
|
|
12982
|
+
if (pendingTeeSave === saveToFile) {
|
|
12983
|
+
const results = toolCalls.map((tc) => ({
|
|
12984
|
+
callId: tc.id,
|
|
12985
|
+
content: tc.id === call.id ? buildDeferredSaveInstruction(saveToFile) : "[skipped: write the document as plain text, not via tools]",
|
|
12986
|
+
isError: tc.id === call.id
|
|
12987
|
+
}));
|
|
12988
|
+
extraMessages.push(...provider.buildToolResultMessages(toolCalls, results, reasoningContent));
|
|
12989
|
+
return "continue";
|
|
12990
|
+
}
|
|
12898
12991
|
const teeResult = await this.runSaveLastResponseTee(
|
|
12899
12992
|
provider,
|
|
12900
12993
|
call,
|
|
@@ -12907,6 +13000,7 @@ ${summaryContent}`,
|
|
|
12907
13000
|
ac,
|
|
12908
13001
|
usage
|
|
12909
13002
|
);
|
|
13003
|
+
if (teeResult.deferred) pendingTeeSave = saveToFile;
|
|
12910
13004
|
const teeToolResults = toolCalls.map((tc) => {
|
|
12911
13005
|
if (tc.id === call.id) {
|
|
12912
13006
|
return {
|
|
@@ -12963,6 +13057,7 @@ ${summaryContent}`,
|
|
|
12963
13057
|
* 场景极少。
|
|
12964
13058
|
*/
|
|
12965
13059
|
async runSaveLastResponseTee(provider, call, saveToFile, apiMessages, extraMessages, systemPrompt, systemPromptVolatile, modelParams, ac, roundUsage) {
|
|
13060
|
+
let deferred = false;
|
|
12966
13061
|
this.send({
|
|
12967
13062
|
type: "tool_call_start",
|
|
12968
13063
|
callId: call.id,
|
|
@@ -13011,17 +13106,15 @@ ${summaryContent}`,
|
|
|
13011
13106
|
await new Promise((resolve7, reject) => {
|
|
13012
13107
|
fileStream.end((err) => err ? reject(err) : resolve7());
|
|
13013
13108
|
});
|
|
13014
|
-
const verdict = evaluateTeeContent(fullContent, saveToFile);
|
|
13109
|
+
const verdict = evaluateTeeContent(fullContent, saveToFile, lastAssistantText(apiMessages));
|
|
13015
13110
|
if (verdict.kind === "reject") {
|
|
13016
|
-
|
|
13017
|
-
unlinkSync4(saveToFile);
|
|
13018
|
-
} catch {
|
|
13019
|
-
}
|
|
13111
|
+
cleanupRejectedTeeFile(saveToFile);
|
|
13020
13112
|
isError = true;
|
|
13021
|
-
|
|
13113
|
+
deferred = true;
|
|
13114
|
+
summary = buildDeferredSaveInstruction(saveToFile);
|
|
13022
13115
|
fullContent = "";
|
|
13023
13116
|
} else {
|
|
13024
|
-
if (verdict.kind === "salvaged") {
|
|
13117
|
+
if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
|
|
13025
13118
|
writeFileSync7(saveToFile, verdict.content, "utf-8");
|
|
13026
13119
|
fullContent = verdict.content;
|
|
13027
13120
|
}
|
|
@@ -13041,10 +13134,7 @@ ${summaryContent}`,
|
|
|
13041
13134
|
} catch {
|
|
13042
13135
|
}
|
|
13043
13136
|
}
|
|
13044
|
-
|
|
13045
|
-
unlinkSync4(saveToFile);
|
|
13046
|
-
} catch {
|
|
13047
|
-
}
|
|
13137
|
+
cleanupRejectedTeeFile(saveToFile);
|
|
13048
13138
|
isError = true;
|
|
13049
13139
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13050
13140
|
summary = teeStreamErrorSummary(saveToFile, msg);
|
|
@@ -13056,7 +13146,7 @@ ${summaryContent}`,
|
|
|
13056
13146
|
content: summary,
|
|
13057
13147
|
isError
|
|
13058
13148
|
});
|
|
13059
|
-
return { content: fullContent, summary, isError };
|
|
13149
|
+
return { content: fullContent, summary, isError, deferred };
|
|
13060
13150
|
}
|
|
13061
13151
|
/**
|
|
13062
13152
|
* Consume streaming tool call events and forward to client.
|
|
@@ -14090,7 +14180,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
14090
14180
|
case "test": {
|
|
14091
14181
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
14092
14182
|
try {
|
|
14093
|
-
const { executeTests } = await import("./run-tests-
|
|
14183
|
+
const { executeTests } = await import("./run-tests-RFK53W3D.js");
|
|
14094
14184
|
const argStr = args.join(" ").trim();
|
|
14095
14185
|
let testArgs = {};
|
|
14096
14186
|
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-GJBPVYFW.js");
|
|
158
158
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
159
159
|
let interrupted = false;
|
|
160
160
|
const onSigint = () => {
|