deepseeker-code 1.0.53 → 1.0.54
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/cli.mjs
CHANGED
|
@@ -102,7 +102,7 @@ var init_strings = __esm({
|
|
|
102
102
|
"\u89E3\u91CA runAgent \u7684\u4E3B\u5FAA\u73AF\u903B\u8F91"
|
|
103
103
|
],
|
|
104
104
|
placeholder: "\u53D1\u9001\u6D88\u606F\uFF08Shift+Enter \u6362\u884C\uFF0CEnter \u53D1\u9001\uFF09\u2026",
|
|
105
|
-
|
|
105
|
+
thinkVerbs: ["\u601D\u8003\u4E2D", "\u6784\u601D\u4E2D", "\u63A8\u6572\u4E2D", "\u659F\u914C\u4E2D", "\u915D\u917F\u4E2D", "\u7F16\u7EC7\u4E2D", "\u63D0\u70BC\u4E2D", "\u7075\u611F\u6D8C\u73B0\u4E2D"],
|
|
106
106
|
round: (n) => `\u7B2C ${n} \u8F6E`,
|
|
107
107
|
thinkingStreaming: "\u273B \u6DF1\u5EA6\u601D\u8003\u4E2D\u2026",
|
|
108
108
|
thinkingCollapsed: (lines) => `\u273B \u601D\u8003\u8FC7\u7A0B\uFF08${lines} \u884C\uFF09\xB7 Ctrl+T \u5C55\u5F00`,
|
|
@@ -229,6 +229,7 @@ DeepSeeker-Code \u5C06\u5728\u6B64\u76EE\u5F55\u8BFB\u53D6\u3001\u7F16\u8F91\u54
|
|
|
229
229
|
"/plan \u2014 \u5207\u6362\u8BA1\u5212\u6A21\u5F0F\uFF08\u53EA\u8BFB\u8C03\u7814 \u2192 \u65B9\u6848\u5BA1\u6279 \u2192 \u5B9E\u73B0\uFF09",
|
|
230
230
|
`/model <\u6A21\u578Bid> \u2014 \u5207\u6362\u6A21\u578B\uFF08\u76F4\u8F93\uFF0C\u5F53\u524D ${model}\uFF09`,
|
|
231
231
|
"/switch \u2014 \u5F39\u51FA\u5019\u9009\u6A21\u578B\u9009\u62E9\u5668",
|
|
232
|
+
"/archive \u2014 \u67E5\u770B\u6700\u8FD1\u4E00\u6B21\u538B\u7F29\u7684\u5F52\u6863\u6458\u8981",
|
|
232
233
|
`/thinking [off|high|max] \u2014 \u5207\u6362\u601D\u8003\u7B49\u7EA7\uFF08\u5F53\u524D ${thinking}\uFF09`,
|
|
233
234
|
`/lang [zh|en] \u2014 \u5207\u6362\u754C\u9762\u8BED\u8A00\uFF08\u5F53\u524D ${locale2}\uFF09`,
|
|
234
235
|
"/sessions \u2014 \u9009\u62E9\u5E76\u8F7D\u5165\u5386\u53F2\u4F1A\u8BDD\uFF08\u7EED\u63A5\u5BF9\u8BDD\uFF09",
|
|
@@ -255,7 +256,7 @@ DeepSeeker-Code \u5C06\u5728\u6B64\u76EE\u5F55\u8BFB\u53D6\u3001\u7F16\u8F91\u54
|
|
|
255
256
|
"Explain runAgent's main loop"
|
|
256
257
|
],
|
|
257
258
|
placeholder: "Send a message (Shift+Enter newline, Enter to send)\u2026",
|
|
258
|
-
|
|
259
|
+
thinkVerbs: ["Thinking", "Ideating", "Pondering", "Brewing", "Forging", "Weaving", "Distilling", "Synthesizing"],
|
|
259
260
|
round: (n) => `Round ${n}`,
|
|
260
261
|
thinkingStreaming: "\u273B Thinking\u2026",
|
|
261
262
|
thinkingCollapsed: (lines) => `\u273B Thoughts (${lines} lines) \xB7 Ctrl+T expand`,
|
|
@@ -382,6 +383,7 @@ DeepSeeker-Code will read, edit, and execute files here.`,
|
|
|
382
383
|
"/plan \u2014 Toggle plan mode (read-only research \u2192 review \u2192 implement)",
|
|
383
384
|
`/model <model-id> \u2014 Switch model (direct input; current ${model})`,
|
|
384
385
|
"/switch \u2014 Open the model picker",
|
|
386
|
+
"/archive \u2014 Show the latest compaction summary",
|
|
385
387
|
`/thinking [off|high|max] \u2014 Switch thinking level (current ${thinking})`,
|
|
386
388
|
`/lang [zh|en] \u2014 Switch interface language (current ${locale2})`,
|
|
387
389
|
"/sessions \u2014 Pick a past session to resume",
|
|
@@ -1289,6 +1291,14 @@ var init_replay = __esm({
|
|
|
1289
1291
|
const f = fault;
|
|
1290
1292
|
const n = Math.min(f.afterChars ?? 0, (turn.content ?? "").length);
|
|
1291
1293
|
if (n > 0) yield { kind: "text", text: (turn.content ?? "").slice(0, n) };
|
|
1294
|
+
if (f.withToolCalls) {
|
|
1295
|
+
const fts = turn.toolCalls ?? [];
|
|
1296
|
+
for (let i = 0; i < fts.length; i++) {
|
|
1297
|
+
const tc = fts[i];
|
|
1298
|
+
yield { kind: "tool_call_delta", index: i, id: tc.id ?? `call_replay_${turnIndex}_${i}`, type: "function", nameDelta: tc.name };
|
|
1299
|
+
yield { kind: "tool_call_delta", index: i, argumentsDelta: JSON.stringify(tc.args ?? {}) };
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1292
1302
|
throw makeFaultError(f);
|
|
1293
1303
|
}
|
|
1294
1304
|
if (turn.reasoning) yield { kind: "reasoning", text: turn.reasoning };
|
|
@@ -1800,7 +1810,7 @@ var init_store = __esm({
|
|
|
1800
1810
|
|
|
1801
1811
|
// ../core/src/session/transcript.ts
|
|
1802
1812
|
import fs6 from "fs/promises";
|
|
1803
|
-
var isEventLine, readTranscriptLines, appendSizeCache, appendLineWithRetry, appendMessage, appendEvent;
|
|
1813
|
+
var isEventLine, readTranscriptLines, appendSizeCache, appendLineWithRetry, appendMessage, appendMessages, appendEvent;
|
|
1804
1814
|
var init_transcript = __esm({
|
|
1805
1815
|
"../core/src/session/transcript.ts"() {
|
|
1806
1816
|
"use strict";
|
|
@@ -1830,7 +1840,7 @@ var init_transcript = __esm({
|
|
|
1830
1840
|
}
|
|
1831
1841
|
};
|
|
1832
1842
|
appendSizeCache = /* @__PURE__ */ new Map();
|
|
1833
|
-
appendLineWithRetry = async (p, payload) => {
|
|
1843
|
+
appendLineWithRetry = async (p, payload, handle) => {
|
|
1834
1844
|
const MAX_ATTEMPTS = 3;
|
|
1835
1845
|
const payloadBytes = Buffer.byteLength(payload, "utf-8");
|
|
1836
1846
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
@@ -1843,7 +1853,8 @@ var init_transcript = __esm({
|
|
|
1843
1853
|
}
|
|
1844
1854
|
}
|
|
1845
1855
|
try {
|
|
1846
|
-
await
|
|
1856
|
+
if (handle) await handle.appendFile(payload, "utf-8");
|
|
1857
|
+
else await fs6.appendFile(p, payload, "utf-8");
|
|
1847
1858
|
appendSizeCache.set(p, beforeSize + payloadBytes);
|
|
1848
1859
|
return;
|
|
1849
1860
|
} catch (e) {
|
|
@@ -1873,6 +1884,35 @@ var init_transcript = __esm({
|
|
|
1873
1884
|
console.warn(`\u26A0\uFE0F \u6D88\u606F\u843D\u76D8\u5931\u8D25\uFF08\u5DF2\u91CD\u8BD5 3 \u6B21\uFF0C\u5185\u5B58\u4E0E\u78C1\u76D8\u8F6C\u5F55\u53EF\u80FD\u4E0D\u4E00\u81F4\uFF09:`, e);
|
|
1874
1885
|
}
|
|
1875
1886
|
};
|
|
1887
|
+
appendMessages = async (sessionId, entries) => {
|
|
1888
|
+
if (entries.length === 0) return;
|
|
1889
|
+
if (entries.length === 1) return appendMessage(entries[0]);
|
|
1890
|
+
try {
|
|
1891
|
+
await ensureSessionsDir(sessionId);
|
|
1892
|
+
const p = getTranscriptPath(sessionId);
|
|
1893
|
+
const payloads = entries.map((entry) => {
|
|
1894
|
+
const { sessionId: _sid, ...rest } = entry;
|
|
1895
|
+
return JSON.stringify({ id: createUUID(), ts: (/* @__PURE__ */ new Date()).toISOString(), ...rest }) + "\n";
|
|
1896
|
+
});
|
|
1897
|
+
const FFFD = String.fromCharCode(65533);
|
|
1898
|
+
const fffdTotal = payloads.reduce((n, pl) => n + (pl.split(FFFD).length - 1), 0);
|
|
1899
|
+
if (fffdTotal > 0) console.warn(`[transcript] \u6279\u91CF\u6D88\u606F\u542B ${fffdTotal} \u4E2A\u4E71\u7801\u5B57\u7B26\uFF08U+FFFD\uFF09\uFF0C\u5DF2\u539F\u6837\u5199\u5165\u5386\u53F2\u3002\u6765\u6E90\u53EF\u80FD\u662F GBK \u5B50\u8FDB\u7A0B\u8F93\u51FA\u6216\u4E71\u7801\u7C98\u8D34\u3002`);
|
|
1900
|
+
let handle = null;
|
|
1901
|
+
let i = 0;
|
|
1902
|
+
try {
|
|
1903
|
+
handle = await fs6.open(p, "a");
|
|
1904
|
+
for (; i < payloads.length; i++) await appendLineWithRetry(p, payloads[i], handle);
|
|
1905
|
+
} catch (e) {
|
|
1906
|
+
console.warn(`[transcript] \u6279\u91CF\u843D\u76D8\u7B2C ${i + 1}/${payloads.length} \u6761\u5931\u8D25\uFF0C\u8BE5\u6761\u8D77\u56DE\u843D\u9010\u6761\u65E7\u8DEF\u5F84:`, e instanceof Error ? e.message : e);
|
|
1907
|
+
for (; i < entries.length; i++) await appendMessage(entries[i]);
|
|
1908
|
+
} finally {
|
|
1909
|
+
if (handle) await handle.close().catch(() => {
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
} catch (e) {
|
|
1913
|
+
console.warn(`\u6279\u91CF\u6D88\u606F\u843D\u76D8\u5931\u8D25\uFF08\u5185\u5B58\u4E0E\u78C1\u76D8\u8F6C\u5F55\u53EF\u80FD\u4E0D\u4E00\u81F4\uFF09:`, e);
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1876
1916
|
appendEvent = async (sessionId, ev) => {
|
|
1877
1917
|
if (!appConfig.transcriptEvents) return;
|
|
1878
1918
|
try {
|
|
@@ -2629,8 +2669,16 @@ ${lines}
|
|
|
2629
2669
|
if (batch.length > 0) batches.push(batch);
|
|
2630
2670
|
return batches;
|
|
2631
2671
|
};
|
|
2632
|
-
compactBatches = async (batches, signal) => {
|
|
2633
|
-
|
|
2672
|
+
compactBatches = async (batches, signal, onUIEvent) => {
|
|
2673
|
+
if (onUIEvent && batches.length > 0) onUIEvent({ type: "compact.progress", done: 0, total: batches.length });
|
|
2674
|
+
let done = 0;
|
|
2675
|
+
const lines = await Promise.all(batches.map(
|
|
2676
|
+
(b, i) => compactBatch(b, signal, i === batches.length - 1).then((line) => {
|
|
2677
|
+
done++;
|
|
2678
|
+
onUIEvent?.({ type: "compact.progress", done, total: batches.length });
|
|
2679
|
+
return line;
|
|
2680
|
+
})
|
|
2681
|
+
));
|
|
2634
2682
|
return lines.join("\n");
|
|
2635
2683
|
};
|
|
2636
2684
|
ensureSummarySlot = (messageArr) => {
|
|
@@ -2679,6 +2727,7 @@ ${lines}
|
|
|
2679
2727
|
const summaryMsg = event.messageArr[1];
|
|
2680
2728
|
let keep = event.keepRecentUnits;
|
|
2681
2729
|
let lastSize = estReal(event.messageArr);
|
|
2730
|
+
const preCompactSize = Math.round(lastSize);
|
|
2682
2731
|
const startTime = performance.now();
|
|
2683
2732
|
let round = 0;
|
|
2684
2733
|
while (lastSize > event.modelWindow * effectiveRatio) {
|
|
@@ -2692,7 +2741,7 @@ ${lines}
|
|
|
2692
2741
|
if (toCompact.length > 0) {
|
|
2693
2742
|
summaryMsg.content = mergeSummarySlot(summaryMsg?.content || "", "", extractArchiveEntities(toCompact));
|
|
2694
2743
|
const batches = splitIntoBatches(toCompact);
|
|
2695
|
-
summaryMsg.content = batches.length === 1 ? await synthesizeSlotNarrativeFromBatch(summaryMsg.content, batches[0], event.signal) : await synthesizeSlotNarrative(summaryMsg.content, await compactBatches(batches, event.signal), event.signal);
|
|
2744
|
+
summaryMsg.content = batches.length === 1 ? await synthesizeSlotNarrativeFromBatch(summaryMsg.content, batches[0], event.signal) : await synthesizeSlotNarrative(summaryMsg.content, await compactBatches(batches, event.signal, event.depth === 0 ? event.onUIEvent : void 0), event.signal);
|
|
2696
2745
|
if (estimateTokens([summaryMsg]) > SUMMARY_SELF_COMPACT_THRESHOLD) {
|
|
2697
2746
|
summaryMsg.content = await compactSlotNarrative(summaryMsg.content, event.modelWindow, event.signal);
|
|
2698
2747
|
}
|
|
@@ -2775,6 +2824,25 @@ ${lines}
|
|
|
2775
2824
|
}
|
|
2776
2825
|
await dispatch("PostCompact", { sessionId: event.sessionId, depth: event.depth, tokensBefore: Math.round(lastSize), tokensAfter: Math.round(estReal(event.messageArr)) }).catch(() => {
|
|
2777
2826
|
});
|
|
2827
|
+
if (event.onUIEvent && event.depth === 0) {
|
|
2828
|
+
const afterSize = Math.round(estReal(event.messageArr));
|
|
2829
|
+
if (preCompactSize - afterSize > 0) {
|
|
2830
|
+
let summary;
|
|
2831
|
+
try {
|
|
2832
|
+
const slotRaw = event.messageArr[1]?.content;
|
|
2833
|
+
summary = parseSummarySlot(typeof slotRaw === "string" ? slotRaw : "").notes.slice(0, 6e3) || void 0;
|
|
2834
|
+
} catch {
|
|
2835
|
+
}
|
|
2836
|
+
event.onUIEvent({
|
|
2837
|
+
type: "compact.done",
|
|
2838
|
+
tokensBefore: preCompactSize,
|
|
2839
|
+
tokensAfter: afterSize,
|
|
2840
|
+
durationMs: Math.round(performance.now() - startTime),
|
|
2841
|
+
trigger: "auto",
|
|
2842
|
+
summary
|
|
2843
|
+
});
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2778
2846
|
const hardLimitRatio = Math.min(event.compactRatio + 0.13, 0.95);
|
|
2779
2847
|
const finalTokens = estReal(event.messageArr);
|
|
2780
2848
|
if (finalTokens > event.modelWindow * hardLimitRatio) {
|
|
@@ -3270,6 +3338,48 @@ var init_guard = __esm({
|
|
|
3270
3338
|
}
|
|
3271
3339
|
});
|
|
3272
3340
|
|
|
3341
|
+
// ../core/src/agent/inbox.ts
|
|
3342
|
+
var INBOX_MAX_ITEMS, sessionInboxes, pushSessionInbox, claimSessionInbox, flushLeftoverToTranscript;
|
|
3343
|
+
var init_inbox = __esm({
|
|
3344
|
+
"../core/src/agent/inbox.ts"() {
|
|
3345
|
+
"use strict";
|
|
3346
|
+
init_transcript();
|
|
3347
|
+
init_config();
|
|
3348
|
+
INBOX_MAX_ITEMS = 50;
|
|
3349
|
+
sessionInboxes = /* @__PURE__ */ new Map();
|
|
3350
|
+
pushSessionInbox = (sessionId, content) => {
|
|
3351
|
+
if (!appConfig.inboxSteering) return false;
|
|
3352
|
+
const text = (content ?? "").trim();
|
|
3353
|
+
if (!text) return false;
|
|
3354
|
+
const q = sessionInboxes.get(sessionId) ?? [];
|
|
3355
|
+
if (q.length >= INBOX_MAX_ITEMS) {
|
|
3356
|
+
console.warn(`[inbox] \u4F1A\u8BDD ${sessionId} \u961F\u5217\u5DF2\u6EE1\uFF08${INBOX_MAX_ITEMS}\uFF09\uFF0C\u4E22\u5F03\u65B0\u8F93\u5165`);
|
|
3357
|
+
return false;
|
|
3358
|
+
}
|
|
3359
|
+
q.push(text);
|
|
3360
|
+
sessionInboxes.set(sessionId, q);
|
|
3361
|
+
return true;
|
|
3362
|
+
};
|
|
3363
|
+
claimSessionInbox = (sessionId) => {
|
|
3364
|
+
if (!appConfig.inboxSteering) return [];
|
|
3365
|
+
const q = sessionInboxes.get(sessionId);
|
|
3366
|
+
if (!q || q.length === 0) return [];
|
|
3367
|
+
sessionInboxes.delete(sessionId);
|
|
3368
|
+
return q;
|
|
3369
|
+
};
|
|
3370
|
+
flushLeftoverToTranscript = async (sessionId) => {
|
|
3371
|
+
const texts = claimSessionInbox(sessionId);
|
|
3372
|
+
for (const t of texts) {
|
|
3373
|
+
await appendMessage({ sessionId, role: "user", content: t });
|
|
3374
|
+
}
|
|
3375
|
+
if (texts.length > 0) {
|
|
3376
|
+
console.warn(`[inbox] \u4F1A\u8BDD ${sessionId} \u7ED3\u675F\u65F6 ${texts.length} \u6761\u8865\u5145\u8F93\u5165\u672A\u8BA4\u9886\uFF0C\u5DF2\u5199\u5165 transcript\uFF08\u4E0B\u8F6E\u81EA\u52A8\u5E26\u5165\uFF09`);
|
|
3377
|
+
}
|
|
3378
|
+
return texts.length;
|
|
3379
|
+
};
|
|
3380
|
+
}
|
|
3381
|
+
});
|
|
3382
|
+
|
|
3273
3383
|
// ../core/src/tool/registry/background.ts
|
|
3274
3384
|
import { spawn as spawn2, execFileSync } from "child_process";
|
|
3275
3385
|
import fsSync2 from "fs";
|
|
@@ -3314,13 +3424,14 @@ async function killBackgroundTasksUnder(dirPath) {
|
|
|
3314
3424
|
}
|
|
3315
3425
|
return killed;
|
|
3316
3426
|
}
|
|
3317
|
-
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, createBgTask, attachTaskLifecycle, adoptRunningProcess, backgroundTools, killAllBackgroundTasks;
|
|
3427
|
+
var _winShellCache, resolveWinShell, MAX_BUFFER_CHARS, registry, createBgTask, attachTaskLifecycle, makeTaskExitNotifier, adoptRunningProcess, backgroundTools, killAllBackgroundTasks;
|
|
3318
3428
|
var init_background = __esm({
|
|
3319
3429
|
"../core/src/tool/registry/background.ts"() {
|
|
3320
3430
|
"use strict";
|
|
3321
3431
|
init_type();
|
|
3322
3432
|
init_guard();
|
|
3323
3433
|
init_common();
|
|
3434
|
+
init_inbox();
|
|
3324
3435
|
resolveWinShell = () => {
|
|
3325
3436
|
if (process.platform !== "win32") return null;
|
|
3326
3437
|
if (_winShellCache !== void 0) return _winShellCache;
|
|
@@ -3377,6 +3488,17 @@ var init_background = __esm({
|
|
|
3377
3488
|
if (finished) return;
|
|
3378
3489
|
finished = true;
|
|
3379
3490
|
apply();
|
|
3491
|
+
try {
|
|
3492
|
+
opts.onExit?.({
|
|
3493
|
+
taskId: task.taskId,
|
|
3494
|
+
command: task.command,
|
|
3495
|
+
sessionId: task.sessionId,
|
|
3496
|
+
status: task.status === "killed" ? "killed" : "exited",
|
|
3497
|
+
exitCode: task.exitCode,
|
|
3498
|
+
ok: task.status === "exited" && task.exitCode === 0
|
|
3499
|
+
});
|
|
3500
|
+
} catch {
|
|
3501
|
+
}
|
|
3380
3502
|
setTimeout(() => registry.delete(task.taskId), 6e4);
|
|
3381
3503
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
3382
3504
|
try {
|
|
@@ -3428,6 +3550,20 @@ var init_background = __esm({
|
|
|
3428
3550
|
});
|
|
3429
3551
|
});
|
|
3430
3552
|
};
|
|
3553
|
+
makeTaskExitNotifier = (ctx) => (info) => {
|
|
3554
|
+
const brief = info.command.length > 80 ? `${info.command.slice(0, 80)}\u2026` : info.command;
|
|
3555
|
+
try {
|
|
3556
|
+
ctx?.onUIEvent?.({ type: "task.exit", taskId: info.taskId, command: brief, status: info.status, exitCode: info.exitCode, ok: info.ok });
|
|
3557
|
+
} catch {
|
|
3558
|
+
}
|
|
3559
|
+
if (!info.ok && info.status === "exited" && info.sessionId) {
|
|
3560
|
+
try {
|
|
3561
|
+
pushSessionInbox(info.sessionId, `\u26A0\uFE0F \u540E\u53F0\u4EFB\u52A1\u5931\u8D25\uFF08exit=${info.exitCode ?? "\u672A\u77E5"}\uFF09\uFF1A${brief}
|
|
3562
|
+
\uFF08\u540E\u53F0\u547D\u4EE4\u975E\u96F6\u9000\u51FA\u3002\u8BF7\u7528 get_background_output(task_id="${info.taskId}") \u67E5\u770B\u65E5\u5FD7\uFF0C\u5E76\u51B3\u5B9A\u662F\u5426\u4FEE\u590D\u91CD\u8DD1\u3002\uFF09`);
|
|
3563
|
+
} catch {
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
};
|
|
3431
3567
|
adoptRunningProcess = (proc, meta, seedOutput, codec) => {
|
|
3432
3568
|
const task = createBgTask(proc, meta.command, meta.cwd, meta.sessionId);
|
|
3433
3569
|
if (seedOutput) appendOutput(task, seedOutput);
|
|
@@ -3450,7 +3586,7 @@ var init_background = __esm({
|
|
|
3450
3586
|
const onData = (d) => appendOutput(task, codec.decode(d));
|
|
3451
3587
|
proc.stdout?.on("data", onData);
|
|
3452
3588
|
proc.stderr?.on("data", onData);
|
|
3453
|
-
void attachTaskLifecycle(task, proc, { signal: meta.signal, codec });
|
|
3589
|
+
void attachTaskLifecycle(task, proc, { signal: meta.signal, codec, onExit: meta.onExit });
|
|
3454
3590
|
return task.taskId;
|
|
3455
3591
|
};
|
|
3456
3592
|
backgroundTools = [
|
|
@@ -3528,7 +3664,7 @@ var init_background = __esm({
|
|
|
3528
3664
|
task_id: ${taskId}
|
|
3529
3665
|
\u547D\u4EE4: ${args.command}
|
|
3530
3666
|
\u7528 get_background_output(task_id="${taskId}") \u67E5\u65E5\u5FD7\uFF0Cstop_background_task(task_id="${taskId}") \u7EC8\u6B62\u3002`;
|
|
3531
|
-
await attachTaskLifecycle(task, proc, { signal: ctx?.abortSignal, codec });
|
|
3667
|
+
await attachTaskLifecycle(task, proc, { signal: ctx?.abortSignal, codec, onExit: makeTaskExitNotifier(ctx) });
|
|
3532
3668
|
}
|
|
3533
3669
|
}
|
|
3534
3670
|
},
|
|
@@ -4601,48 +4737,6 @@ var init_httpExecutor = __esm({
|
|
|
4601
4737
|
}
|
|
4602
4738
|
});
|
|
4603
4739
|
|
|
4604
|
-
// ../core/src/agent/inbox.ts
|
|
4605
|
-
var INBOX_MAX_ITEMS, sessionInboxes, pushSessionInbox, claimSessionInbox, flushLeftoverToTranscript;
|
|
4606
|
-
var init_inbox = __esm({
|
|
4607
|
-
"../core/src/agent/inbox.ts"() {
|
|
4608
|
-
"use strict";
|
|
4609
|
-
init_transcript();
|
|
4610
|
-
init_config();
|
|
4611
|
-
INBOX_MAX_ITEMS = 50;
|
|
4612
|
-
sessionInboxes = /* @__PURE__ */ new Map();
|
|
4613
|
-
pushSessionInbox = (sessionId, content) => {
|
|
4614
|
-
if (!appConfig.inboxSteering) return false;
|
|
4615
|
-
const text = (content ?? "").trim();
|
|
4616
|
-
if (!text) return false;
|
|
4617
|
-
const q = sessionInboxes.get(sessionId) ?? [];
|
|
4618
|
-
if (q.length >= INBOX_MAX_ITEMS) {
|
|
4619
|
-
console.warn(`[inbox] \u4F1A\u8BDD ${sessionId} \u961F\u5217\u5DF2\u6EE1\uFF08${INBOX_MAX_ITEMS}\uFF09\uFF0C\u4E22\u5F03\u65B0\u8F93\u5165`);
|
|
4620
|
-
return false;
|
|
4621
|
-
}
|
|
4622
|
-
q.push(text);
|
|
4623
|
-
sessionInboxes.set(sessionId, q);
|
|
4624
|
-
return true;
|
|
4625
|
-
};
|
|
4626
|
-
claimSessionInbox = (sessionId) => {
|
|
4627
|
-
if (!appConfig.inboxSteering) return [];
|
|
4628
|
-
const q = sessionInboxes.get(sessionId);
|
|
4629
|
-
if (!q || q.length === 0) return [];
|
|
4630
|
-
sessionInboxes.delete(sessionId);
|
|
4631
|
-
return q;
|
|
4632
|
-
};
|
|
4633
|
-
flushLeftoverToTranscript = async (sessionId) => {
|
|
4634
|
-
const texts = claimSessionInbox(sessionId);
|
|
4635
|
-
for (const t of texts) {
|
|
4636
|
-
await appendMessage({ sessionId, role: "user", content: t });
|
|
4637
|
-
}
|
|
4638
|
-
if (texts.length > 0) {
|
|
4639
|
-
console.warn(`[inbox] \u4F1A\u8BDD ${sessionId} \u7ED3\u675F\u65F6 ${texts.length} \u6761\u8865\u5145\u8F93\u5165\u672A\u8BA4\u9886\uFF0C\u5DF2\u5199\u5165 transcript\uFF08\u4E0B\u8F6E\u81EA\u52A8\u5E26\u5165\uFF09`);
|
|
4640
|
-
}
|
|
4641
|
-
return texts.length;
|
|
4642
|
-
};
|
|
4643
|
-
}
|
|
4644
|
-
});
|
|
4645
|
-
|
|
4646
4740
|
// ../core/src/agent/repeatBreaker.ts
|
|
4647
4741
|
var createRepeatBreaker;
|
|
4648
4742
|
var init_repeatBreaker = __esm({
|
|
@@ -5123,7 +5217,9 @@ var init_systemInjections = __esm({
|
|
|
5123
5217
|
events,
|
|
5124
5218
|
onUIEvent: options.onUIEvent,
|
|
5125
5219
|
requestApproval: options.requestApproval,
|
|
5126
|
-
requestQuestion: options.requestQuestion
|
|
5220
|
+
requestQuestion: options.requestQuestion,
|
|
5221
|
+
ideAction: options.ideAction
|
|
5222
|
+
// ★ ide_* 三工具 validateEnvironment 据此判定自隐藏(CLI/HTTP 宿主无钩子 → 不暴露)
|
|
5127
5223
|
};
|
|
5128
5224
|
const rawTools = await filterByEnvironment(rawToolsPreEnv, validationCtx);
|
|
5129
5225
|
const cleanedEntries = rawTools.map((t) => cleanToolSchema(t));
|
|
@@ -6130,7 +6226,7 @@ var init_fs = __esm({
|
|
|
6130
6226
|
// ★ 内容级脱敏(defense-in-depth):黑名单外的代码文件也可能内联硬编码密钥,
|
|
6131
6227
|
// 在 verifyResult 之后、回灌云端模型之前由 runAgent 调用,仅影响"发给模型的视图"。
|
|
6132
6228
|
privacyMaskingRules: maskSecretsInContent,
|
|
6133
|
-
async execute(args) {
|
|
6229
|
+
async execute(args, toolCtx) {
|
|
6134
6230
|
try {
|
|
6135
6231
|
const absPath = resolveReadablePath(args.path);
|
|
6136
6232
|
const lowerExt = absPath.toLowerCase();
|
|
@@ -6164,7 +6260,22 @@ var init_fs = __esm({
|
|
|
6164
6260
|
if (requestedLines.length === 0) {
|
|
6165
6261
|
return `[File: ${args.path}] \u8BF7\u6C42\u7684\u884C\u533A\u95F4 ${start}-${end} \u65E0\u5185\u5BB9\uFF08\u6587\u4EF6\u603B\u884C\u6570\u7EA6 ${currentLineNum}\uFF09\u3002`;
|
|
6166
6262
|
}
|
|
6167
|
-
|
|
6263
|
+
let readStamp = "";
|
|
6264
|
+
if (toolCtx?.readTracker) {
|
|
6265
|
+
try {
|
|
6266
|
+
const st = await fs13.stat(absPath);
|
|
6267
|
+
const prev = toolCtx.readTracker.get(absPath);
|
|
6268
|
+
const count = (prev?.count ?? 0) + 1;
|
|
6269
|
+
const changed = prev !== void 0 && prev.mtimeMs !== st.mtimeMs;
|
|
6270
|
+
toolCtx.readTracker.set(absPath, { mtimeMs: st.mtimeMs, count });
|
|
6271
|
+
if (count > 1) {
|
|
6272
|
+
readStamp = `[\u7B2C ${count} \u6B21\u8BFB\u53D6\uFF08\u672C run\uFF09\xB7 \u5185\u5BB9\u81EA\u4E0A\u6B21\u8BFB\u53D6${changed ? "\u5DF2\u53D8\u66F4" : "\u672A\u53D8\u66F4"}]
|
|
6273
|
+
`;
|
|
6274
|
+
}
|
|
6275
|
+
} catch {
|
|
6276
|
+
}
|
|
6277
|
+
}
|
|
6278
|
+
return `${readStamp}[File: ${args.path} | Lines ${start}-${realEnd}]
|
|
6168
6279
|
${formattedCode}${hasMore ? `
|
|
6169
6280
|
|
|
6170
6281
|
[... \u540E\u9762\u8FD8\u6709\u4EE3\u7801\u5DF2\u88AB\u9690\u85CF\uFF0C\u4F60\u53EF\u4EE5\u8C03\u6574 start_line \u7EE7\u7EED\u5206\u7247\u8BFB\u53D6\u3002]` : ""}`;
|
|
@@ -7051,7 +7162,7 @@ ${tail}`,
|
|
|
7051
7162
|
if (degraded) {
|
|
7052
7163
|
const taskId = adoptRunningProcess(
|
|
7053
7164
|
proc,
|
|
7054
|
-
{ command: args.command, cwd, sessionId: ctx?.sessionId, signal: ctx?.abortSignal },
|
|
7165
|
+
{ command: args.command, cwd, sessionId: ctx?.sessionId, signal: ctx?.abortSignal, onExit: makeTaskExitNotifier(ctx) },
|
|
7055
7166
|
fullOutput + queue.join(""),
|
|
7056
7167
|
codec
|
|
7057
7168
|
);
|
|
@@ -7980,7 +8091,7 @@ ${body}${truncNote}`;
|
|
|
7980
8091
|
});
|
|
7981
8092
|
|
|
7982
8093
|
// ../core/src/tool/registry/http.ts
|
|
7983
|
-
var HTTP_TIMEOUT_MS, DEFAULT_MAX_CHARS2, USER_AGENT2, ALLOWED_METHODS, httpTools;
|
|
8094
|
+
var HTTP_TIMEOUT_MS, DEFAULT_MAX_CHARS2, USER_AGENT2, ALLOWED_METHODS, READY_PROBE_TIMEOUT_MS, READY_POLL_INTERVAL_MS, READY_DEFAULT_TIMEOUT_S, READY_MAX_TIMEOUT_S, READY_CLUE_CHARS, isLoopbackHost, httpTools;
|
|
7984
8095
|
var init_http = __esm({
|
|
7985
8096
|
"../core/src/tool/registry/http.ts"() {
|
|
7986
8097
|
"use strict";
|
|
@@ -7990,6 +8101,15 @@ var init_http = __esm({
|
|
|
7990
8101
|
DEFAULT_MAX_CHARS2 = 16e3;
|
|
7991
8102
|
USER_AGENT2 = "DeepSeeker-Code-Agent/1.0 (+http_request tool)";
|
|
7992
8103
|
ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
8104
|
+
READY_PROBE_TIMEOUT_MS = 3e3;
|
|
8105
|
+
READY_POLL_INTERVAL_MS = 1e3;
|
|
8106
|
+
READY_DEFAULT_TIMEOUT_S = 60;
|
|
8107
|
+
READY_MAX_TIMEOUT_S = 180;
|
|
8108
|
+
READY_CLUE_CHARS = 200;
|
|
8109
|
+
isLoopbackHost = (host) => {
|
|
8110
|
+
const h = host.toLowerCase().replace(/^\[|\]$/g, "");
|
|
8111
|
+
return h === "localhost" || h.endsWith(".localhost") || h === "::1" || h === "::" || h === "0.0.0.0" || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
|
|
8112
|
+
};
|
|
7993
8113
|
httpTools = [
|
|
7994
8114
|
{
|
|
7995
8115
|
type: "function",
|
|
@@ -8086,6 +8206,85 @@ var init_http = __esm({
|
|
|
8086
8206
|
}
|
|
8087
8207
|
}
|
|
8088
8208
|
}
|
|
8209
|
+
},
|
|
8210
|
+
{
|
|
8211
|
+
type: "function",
|
|
8212
|
+
function: {
|
|
8213
|
+
name: "wait_http_ready",
|
|
8214
|
+
description: [
|
|
8215
|
+
"\u963B\u585E\u7B49\u5F85\u672C\u5730\u670D\u52A1\u5C31\u7EEA\uFF1A1s \u95F4\u9694\u8F6E\u8BE2 URL \u76F4\u5230\u670D\u52A1\u54CD\u5E94\uFF08run-stack \u7F16\u6392\u7528\u2014\u2014\u300C\u8D77\u6CA1\u8D77\u6765\u300D\u4ECE\u731C\u65E5\u5FD7\u53D8\u786E\u5B9A\u6027\u5224\u5B9A\uFF09\u3002",
|
|
8216
|
+
"\u4EC5\u9650 loopback \u5730\u5740\uFF08localhost/127.x/[::1]\uFF09\uFF0C\u5176\u4ED6\u5730\u5740\u76F4\u63A5\u62D2\u7EDD\u2014\u2014\u5916\u90E8 URL \u8BF7\u7528 http_request\uFF08\u8D70\u5BA1\u6279\uFF09\u3002",
|
|
8217
|
+
"expect_status \u7F3A\u7701=\u6536\u5230\u4EFB\u610F HTTP \u54CD\u5E94\u5373\u7B97\u5C31\u7EEA\uFF08\u7AEF\u53E3\u5DF2\u670D\u52A1\uFF0C404/503 \u4E5F\u7B97\uFF1B\u72B6\u6001\u7801\u4F1A\u56DE\u6267\uFF09\uFF1B\u6307\u5B9A\u4E86\u5219\u7CBE\u786E\u5339\u914D\u8BE5\u72B6\u6001\u7801\u624D\u901A\u8FC7\u3002",
|
|
8218
|
+
"\u8D85\u65F6\u65F6\u56DE\u6267\u5E26\u6700\u540E\u4E00\u6B21\u72B6\u6001\u7801\u4E0E body \u6458\u8981\uFF0C\u53EF\u5F53\u6392\u969C\u7EBF\u7D22\u3002\u2605 SAFE \u514D\u5BA1\u3001\u53EF\u957F\u963B\u585E\uFF0C\u66FF\u4EE3\u9010\u6B21 http_request \u63A2\u6D4B\u3002"
|
|
8219
|
+
].join(" "),
|
|
8220
|
+
parameters: {
|
|
8221
|
+
type: "object",
|
|
8222
|
+
properties: {
|
|
8223
|
+
url: { type: "string", description: "\u7B49\u5F85\u7684\u672C\u5730 URL\uFF08\u5982 http://localhost:5173 \u6216\u5065\u5EB7\u7AEF\u70B9 http://localhost:8080/actuator/health\uFF09" },
|
|
8224
|
+
expect_status: { type: "number", description: "\u8981\u6C42\u7684 HTTP \u72B6\u6001\u7801\uFF08\u53EF\u9009\uFF0C\u7F3A\u7701\u4EFB\u610F\u54CD\u5E94\u5373\u5C31\u7EEA\uFF09" },
|
|
8225
|
+
timeout_seconds: { type: "number", description: `\u6700\u957F\u7B49\u5F85\u79D2\u6570\uFF08\u9ED8\u8BA4 ${READY_DEFAULT_TIMEOUT_S}\uFF0C\u4E0A\u9650 ${READY_MAX_TIMEOUT_S}\uFF09` }
|
|
8226
|
+
},
|
|
8227
|
+
required: ["url"]
|
|
8228
|
+
},
|
|
8229
|
+
safetyLevel: "safe" /* SAFE */,
|
|
8230
|
+
// loopback-only 硬闸(见文件头安全红线)+ GET 语义探测,免审
|
|
8231
|
+
isSync: true,
|
|
8232
|
+
maxOutputCharacters: 2e3,
|
|
8233
|
+
async execute(args, ctx) {
|
|
8234
|
+
let parsed;
|
|
8235
|
+
try {
|
|
8236
|
+
parsed = new URL(String(args?.url ?? ""));
|
|
8237
|
+
} catch {
|
|
8238
|
+
return toolFailure(`[wait_http_ready] URL \u4E0D\u5408\u6CD5\uFF1A${args?.url}`);
|
|
8239
|
+
}
|
|
8240
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
8241
|
+
return toolFailure(`[wait_http_ready] \u4EC5\u5141\u8BB8 http/https\uFF0C\u62D2\u7EDD ${parsed.protocol}`);
|
|
8242
|
+
}
|
|
8243
|
+
if (!isLoopbackHost(parsed.hostname)) {
|
|
8244
|
+
return toolFailure(`[wait_http_ready] \u4EC5\u652F\u6301\u672C\u5730\u5730\u5740\uFF08localhost/127.x/[::1]\uFF09\uFF0C\u62D2\u7EDD ${parsed.hostname}\u3002\u5916\u90E8 URL \u8BF7\u7528 http_request\uFF08DANGER \u5BA1\u6279\uFF09\u53D1\u8D77\u3002`, "permission");
|
|
8245
|
+
}
|
|
8246
|
+
const timeoutS = Math.min(Math.max(args?.timeout_seconds && args.timeout_seconds > 0 ? args.timeout_seconds : READY_DEFAULT_TIMEOUT_S, 1), READY_MAX_TIMEOUT_S);
|
|
8247
|
+
const startedAt = Date.now();
|
|
8248
|
+
const deadline = startedAt + timeoutS * 1e3;
|
|
8249
|
+
const elapsedS = () => Math.round((Date.now() - startedAt) / 1e3);
|
|
8250
|
+
let lastLine = "\u5C1A\u672A\u53D1\u8D77\u63A2\u6D4B";
|
|
8251
|
+
let lastClue = "";
|
|
8252
|
+
let attempts = 0;
|
|
8253
|
+
let nextProgressAt = startedAt + 5e3;
|
|
8254
|
+
while (Date.now() < deadline) {
|
|
8255
|
+
if (ctx?.abortSignal?.aborted) return `\u23F9\uFE0F [wait_http_ready \u5DF2\u4E2D\u6B62]\uFF1A\u7528\u6237\u4E2D\u65AD\uFF08\u5DF2\u7B49\u5F85 ${elapsedS()}s\uFF09`;
|
|
8256
|
+
attempts++;
|
|
8257
|
+
let status = null;
|
|
8258
|
+
try {
|
|
8259
|
+
const res = await safeFetchFollow(
|
|
8260
|
+
parsed.href,
|
|
8261
|
+
{ "User-Agent": USER_AGENT2, "Accept": "*/*" },
|
|
8262
|
+
[AbortSignal.timeout(READY_PROBE_TIMEOUT_MS)],
|
|
8263
|
+
true,
|
|
8264
|
+
{ method: "GET" }
|
|
8265
|
+
);
|
|
8266
|
+
status = res.status;
|
|
8267
|
+
if (args?.expect_status === void 0 || status === args.expect_status) {
|
|
8268
|
+
return `\u2705 \u670D\u52A1\u5C31\u7EEA ${parsed.href}\uFF08HTTP ${status}${res.statusText ? " " + res.statusText : ""}\uFF0C\u7B2C ${attempts} \u6B21\u63A2\u6D4B\uFF0C\u8017\u65F6 ${elapsedS()}s\uFF09`;
|
|
8269
|
+
}
|
|
8270
|
+
lastLine = `HTTP ${status} ${res.statusText}\uFF08\u671F\u671B ${args.expect_status}\uFF0C\u7EE7\u7EED\u7B49\uFF09`;
|
|
8271
|
+
try {
|
|
8272
|
+
lastClue = (await readBodyCapped(res, READY_CLUE_CHARS * 4)).text.slice(0, READY_CLUE_CHARS);
|
|
8273
|
+
} catch {
|
|
8274
|
+
}
|
|
8275
|
+
} catch (e) {
|
|
8276
|
+
lastLine = e?.name === "TimeoutError" ? "\u63A2\u6D4B\u8D85\u65F6\uFF08\u670D\u52A1\u672A\u54CD\u5E94\uFF09" : `\u8FDE\u63A5\u5931\u8D25\uFF1A${e?.message ?? e}`;
|
|
8277
|
+
}
|
|
8278
|
+
if (ctx?.emitProgress && Date.now() >= nextProgressAt) {
|
|
8279
|
+
ctx.emitProgress(`\u4ECD\u5728\u7B49\u5F85 ${parsed.href}\uFF08\u5269\u4F59 ${Math.max(Math.ceil((deadline - Date.now()) / 1e3), 0)}s\uFF09\uFF1A${lastLine}`);
|
|
8280
|
+
nextProgressAt = Date.now() + 5e3;
|
|
8281
|
+
}
|
|
8282
|
+
await new Promise((r) => setTimeout(r, READY_POLL_INTERVAL_MS));
|
|
8283
|
+
}
|
|
8284
|
+
return toolFailure(`[wait_http_ready \u8D85\u65F6]\uFF1A${timeoutS}s \u5185\u672A\u5C31\u7EEA\uFF08\u5171 ${attempts} \u6B21\u63A2\u6D4B\uFF09\u3002\u6700\u540E\u72B6\u6001\uFF1A${lastLine}${lastClue ? `
|
|
8285
|
+
\u54CD\u5E94 body \u6458\u8981\uFF1A${lastClue}` : ""}`);
|
|
8286
|
+
}
|
|
8287
|
+
}
|
|
8089
8288
|
}
|
|
8090
8289
|
];
|
|
8091
8290
|
}
|
|
@@ -9349,6 +9548,7 @@ var init_ask = __esm({
|
|
|
9349
9548
|
description: [
|
|
9350
9549
|
"\u5411\u7528\u6237\u63D0\u51FA\u591A\u9009\u95EE\u9898\u5E76\u7B49\u5F85\u4F5C\u7B54\uFF1A\u6280\u672F\u65B9\u6848\u4E8C\u9009\u4E00\u3001\u8DEF\u5F84\u53D6\u820D\u3001\u8303\u56F4\u786E\u8BA4\u7B49\u9700\u7528\u6237\u62CD\u677F\u7684\u51B3\u7B56\u6216\u6B67\u4E49\u6F84\u6E05\u2014\u2014\u52FF\u7528\u4E8E\u80FD\u4ECE\u4EE3\u7801/\u4E0A\u4E0B\u6587\u81EA\u884C\u786E\u5B9A\u7684\u95EE\u9898\u3002",
|
|
9351
9550
|
"2-4 \u4E2A\u9009\u9879\uFF08label + \u53EF\u9009 description\uFF09\uFF1BmultiSelect=true \u591A\u9009\uFF08\u9ED8\u8BA4\u5355\u9009\uFF09\u3002\u7528\u6237\u53D6\u6D88\u8FD4\u56DE\u7A7A\u9009\u62E9\uFF08\u6539\u7528\u9ED8\u8BA4\u6216\u91CD\u65B0\u63D0\u95EE\uFF09\u3002",
|
|
9551
|
+
"\u5BBF\u4E3B\u6A21\u6001\u6052\u6709\u300COther\u300D\u81EA\u7531\u8F93\u5165\u6863\uFF1A\u9700\u8981\u7528\u6237\u63D0\u4F9B\u9009\u9879\u4E4B\u5916\u7684\u8D44\u6599\uFF08token\u3001\u8DEF\u5F84\u3001\u94FE\u63A5\u7B49\uFF09\u65F6\uFF0C\u628A\u5B83\u8BBE\u8BA1\u6210\u4E00\u4E2A\u9009\u9879\u5373\u53EF\uFF0C\u7528\u6237\u4F1A\u7ECF Other \u7C98\u8D34\u6587\u672C\u56DE\u4F20\uFF08\u7ED3\u679C\u542B\u300C\u8865\u5145\u8F93\u5165\u300D\u5B57\u6837\uFF09\u3002",
|
|
9352
9552
|
"\u4EC5\u4EA4\u4E92\u5F0F\u73AF\u5883\u53EF\u7528\uFF1B\u7ED3\u679C\u63D0\u793A\u300C\u4E0D\u652F\u6301\u300D\u65F6\u6539\u7528\u7EAF\u6587\u672C\u63D0\u95EE\u3002"
|
|
9353
9553
|
].join("\n"),
|
|
9354
9554
|
parameters: {
|
|
@@ -9395,8 +9595,15 @@ var init_ask = __esm({
|
|
|
9395
9595
|
return toolFailure(`[\u63D0\u95EE\u5F02\u5E38]\uFF1A${e?.message ?? e}\u3002\u8BF7\u6539\u7528\u7EAF\u6587\u672C\u5411\u7528\u6237\u63D0\u95EE\u3002`);
|
|
9396
9596
|
}
|
|
9397
9597
|
if (!answer.selected || answer.selected.length === 0) {
|
|
9598
|
+
const free2 = (answer.freeText ?? "").trim();
|
|
9599
|
+
if (free2) return `\u7528\u6237\u7ECF\u300COther\u300D\u8865\u5145\u8F93\u5165\uFF1A\u300C${free2}\u300D`;
|
|
9398
9600
|
return "\uFF08\u7528\u6237\u53D6\u6D88\u4E86\u672C\u6B21\u63D0\u95EE\uFF0C\u672A\u4F5C\u9009\u62E9\u3002\u53EF\u6309\u9ED8\u8BA4\u7EE7\u7EED\uFF0C\u6216\u91CD\u65B0\u7EC4\u7EC7\u95EE\u9898\u518D\u6B21\u8BE2\u95EE\u3002\uFF09";
|
|
9399
9601
|
}
|
|
9602
|
+
const free = (answer.freeText ?? "").trim();
|
|
9603
|
+
if (free) {
|
|
9604
|
+
const selPart = answer.selected.map((s) => `\u300C${s}\u300D`).join("\u3001");
|
|
9605
|
+
return `\u7528\u6237\u9009\u62E9\u4E86 ${selPart}\uFF0C\u5E76\u7ECF\u300COther\u300D\u8865\u5145\u8F93\u5165\uFF1A\u300C${free}\u300D`;
|
|
9606
|
+
}
|
|
9400
9607
|
return args?.multiSelect ? `\u7528\u6237\u9009\u62E9\u4E86 ${answer.selected.length} \u9879\uFF1A${answer.selected.map((s) => `\u300C${s}\u300D`).join("\u3001")}` : `\u7528\u6237\u9009\u62E9\uFF1A\u300C${answer.selected[0]}\u300D`;
|
|
9401
9608
|
}
|
|
9402
9609
|
}
|
|
@@ -10440,6 +10647,123 @@ var init_document = __esm({
|
|
|
10440
10647
|
}
|
|
10441
10648
|
});
|
|
10442
10649
|
|
|
10650
|
+
// ../core/src/tool/registry/ide.ts
|
|
10651
|
+
var requireIdeHost, IDE_UNAVAILABLE, formatDiagnostics, ideResultToText, ideTools;
|
|
10652
|
+
var init_ide = __esm({
|
|
10653
|
+
"../core/src/tool/registry/ide.ts"() {
|
|
10654
|
+
"use strict";
|
|
10655
|
+
init_type();
|
|
10656
|
+
requireIdeHost = (ctx) => !!ctx?.ideAction;
|
|
10657
|
+
IDE_UNAVAILABLE = toolFailure(
|
|
10658
|
+
"[IDE \u6865\u4E0D\u53EF\u7528]\uFF1A\u5F53\u524D\u5BBF\u4E3B\u672A\u63A5\u5165 IDE\u3002\u8BCA\u65AD\u8BF7\u6539\u7528 run_command \u8DD1\u5BF9\u5E94\u5DE5\u5177\u94FE\uFF08tsc/vue-tsc/mvn compile \u7B49\uFF09\uFF1B\u6253\u5F00\u6587\u4EF6\u8BF7\u5728\u56DE\u590D\u4E2D\u76F4\u63A5\u7ED9\u51FA \u6587\u4EF6\u8DEF\u5F84:\u884C\u53F7\u3002\u672C\u5DE5\u5177\u4EC5\u5728 VSCode \u5BBF\u4E3B\u53EF\u7528\u3002",
|
|
10659
|
+
"permission"
|
|
10660
|
+
);
|
|
10661
|
+
formatDiagnostics = (items, truncated) => {
|
|
10662
|
+
const count = (s) => items.filter((i) => i.severity === s).length;
|
|
10663
|
+
const sources = [...new Set(items.map((i) => i.source).filter(Boolean))].join("/");
|
|
10664
|
+
const head = `[IDE \u8BCA\u65AD] error\xD7${count("error")} warning\xD7${count("warning")} info\xD7${count("info")}${sources ? `\uFF08\u6765\u6E90: ${sources}\uFF09` : ""}${truncated ? `\uFF1B\u53E6\u6709 ${truncated} \u6761\u672A\u663E\u793A` : ""}`;
|
|
10665
|
+
const body = items.map((i) => `${i.file}:${i.line}:${i.column} ${i.severity}${i.code != null && i.code !== "" ? " " + i.code : ""} ${i.message}${i.source ? ` (${i.source})` : ""}`).join("\n");
|
|
10666
|
+
const hint = items.length === 0 ? "\n\uFF08\u8BCA\u65AD\u4E3A\u7A7A\uFF1A\u82E5\u76EE\u6807\u6587\u4EF6\u53EF\u80FD\u672A\u5728 IDE \u4E2D\u52A0\u8F7D\uFF0C\u5148 ide_open_file \u6253\u5F00\u518D\u53D6\u4E00\u6B21\uFF09" : "\n\u4FEE\u590D\u540E\u53EF\u518D\u6B21\u8C03\u7528\u786E\u8BA4\u6E05\u96F6\u3002.vue \u7B49\u8BCA\u65AD\u6765\u81EA IDE \u8BED\u8A00\u670D\u52A1\u5668\uFF08\u5982 Volar\uFF09\uFF0C\u4E0E run_command \u8DD1 vue-tsc \u7684\u53E3\u5F84\u4E00\u81F4\u3002";
|
|
10667
|
+
return `${head}
|
|
10668
|
+
${body}${hint}`;
|
|
10669
|
+
};
|
|
10670
|
+
ideResultToText = (r) => {
|
|
10671
|
+
if (!r.ok) return toolFailure(`[IDE \u52A8\u4F5C\u5931\u8D25]\uFF1A${r.message}`);
|
|
10672
|
+
if (r.action === "diagnostics") return formatDiagnostics(r.items, r.truncated);
|
|
10673
|
+
return `\u2705 ${r.message}`;
|
|
10674
|
+
};
|
|
10675
|
+
ideTools = [
|
|
10676
|
+
{
|
|
10677
|
+
type: "function",
|
|
10678
|
+
function: {
|
|
10679
|
+
name: "ide_open_file",
|
|
10680
|
+
planAllowed: true,
|
|
10681
|
+
validateEnvironment: requireIdeHost,
|
|
10682
|
+
description: "\u5728\u7528\u6237\u7684 IDE \u7F16\u8F91\u5668\u91CC\u6253\u5F00\u6587\u4EF6\u5E76\u8DF3\u8F6C\u5230\u6307\u5B9A\u884C/\u5217\uFF08\u5982\u6539\u5B8C\u4EE3\u7801\u540E\u8BA9\u7528\u6237\u76F4\u63A5\u770B\u5230\u4FEE\u6539\u5904\uFF09\u3002\u4EC5 VSCode \u5BBF\u4E3B\u53EF\u7528\uFF1B\u5176\u4ED6\u73AF\u5883\u672C\u5DE5\u5177\u4E0D\u4F1A\u51FA\u73B0\uFF0C\u51FA\u73B0\u5373\u4EE3\u8868\u53EF\u7528\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u4E0E\u5176\u5B83\u53EA\u8BFB\u5DE5\u5177\u5728\u540C\u4E00\u6761\u6D88\u606F\u91CC\u5E76\u884C\u8C03\u7528\u3002",
|
|
10683
|
+
parameters: {
|
|
10684
|
+
type: "object",
|
|
10685
|
+
properties: {
|
|
10686
|
+
path: { type: "string", description: "\u76EE\u6807\u6587\u4EF6\u8DEF\u5F84\uFF08\u76F8\u5BF9\u5DE5\u4F5C\u533A\u6839\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF09" },
|
|
10687
|
+
line: { type: "number", description: "\u8DF3\u8F6C\u884C\u53F7\uFF081-based\uFF0C\u53EF\u9009\uFF09" },
|
|
10688
|
+
column: { type: "number", description: "\u8DF3\u8F6C\u5217\u53F7\uFF081-based\uFF0C\u53EF\u9009\uFF0C\u7F3A\u7701\u884C\u9996\uFF09" }
|
|
10689
|
+
},
|
|
10690
|
+
required: ["path"]
|
|
10691
|
+
},
|
|
10692
|
+
safetyLevel: "safe" /* SAFE */,
|
|
10693
|
+
isSync: true,
|
|
10694
|
+
async execute(args, ctx) {
|
|
10695
|
+
const p = (args?.path ?? "").trim();
|
|
10696
|
+
if (!p) return toolFailure("[\u6253\u5F00\u5931\u8D25]\uFF1Apath \u4E0D\u80FD\u4E3A\u7A7A\u3002", "syntax");
|
|
10697
|
+
if (!ctx?.ideAction) return IDE_UNAVAILABLE;
|
|
10698
|
+
try {
|
|
10699
|
+
const r = await ctx.ideAction({ action: "open", path: p, line: args?.line, column: args?.column });
|
|
10700
|
+
return ideResultToText(r);
|
|
10701
|
+
} catch (e) {
|
|
10702
|
+
return toolFailure(`[IDE \u5F02\u5E38]\uFF1A${e?.message ?? e}`);
|
|
10703
|
+
}
|
|
10704
|
+
}
|
|
10705
|
+
}
|
|
10706
|
+
},
|
|
10707
|
+
{
|
|
10708
|
+
type: "function",
|
|
10709
|
+
function: {
|
|
10710
|
+
name: "ide_diagnostics",
|
|
10711
|
+
planAllowed: true,
|
|
10712
|
+
validateEnvironment: requireIdeHost,
|
|
10713
|
+
maxOutputCharacters: 8e3,
|
|
10714
|
+
description: "\u8BFB\u53D6 IDE \u5F53\u524D\u771F\u5B9E\u8BCA\u65AD\uFF08\u9519\u8BEF\u6CE2\u6D6A\u7EBF\uFF09\uFF0C\u652F\u6301\u6240\u6709\u5DF2\u88C5\u8BED\u8A00\u670D\u52A1\u5668\u7684\u8BED\u8A00\u2014\u2014\u542B .vue\uFF08Volar\uFF09/Java \u7B49\uFF1Bget_diagnostics \u53EA\u8986\u76D6 TS/JS\uFF0C\u4E24\u8005\u4E92\u8865\u3002path \u7F3A\u7701=\u6574\u4E2A\u5DE5\u4F5C\u533A\uFF08\u6309 error \u4F18\u5148\u6392\u5E8F\uFF09\uFF1Bseverity \u7F3A\u7701 error\u3002\u2605 \u4FEE\u590D .vue \u62A5\u9519\u3001\u9A8C\u8BC1\u6539\u52A8\u540E IDE \u662F\u5426\u8FD8\u4EAE\u7EA2\uFF0C\u7528\u5B83\uFF1B\u6587\u4EF6\u53EF\u80FD\u672A\u52A0\u8F7D\u65F6\u5148 ide_open_file \u6253\u5F00\u518D\u53D6\u3002\u2605 \u53EA\u8BFB\u5B89\u5168\uFF0C\u53EF\u5E76\u884C\u8C03\u7528\u3002",
|
|
10715
|
+
parameters: {
|
|
10716
|
+
type: "object",
|
|
10717
|
+
properties: {
|
|
10718
|
+
path: { type: "string", description: "\u76EE\u6807\u6587\u4EF6\u8DEF\u5F84\uFF08\u53EF\u9009\uFF0C\u7F3A\u7701=\u5168\u5DE5\u4F5C\u533A\u8BCA\u65AD\uFF09" },
|
|
10719
|
+
severity: { type: "string", enum: ["error", "warning", "all"], description: "\u6700\u4F4E\u4E25\u91CD\u5EA6\uFF08\u7F3A\u7701 error\uFF1B\u6392\u67E5\u8B66\u544A\u65F6\u7528 warning/all\uFF09" }
|
|
10720
|
+
},
|
|
10721
|
+
required: []
|
|
10722
|
+
},
|
|
10723
|
+
safetyLevel: "safe" /* SAFE */,
|
|
10724
|
+
isSync: true,
|
|
10725
|
+
async execute(args, ctx) {
|
|
10726
|
+
if (!ctx?.ideAction) return IDE_UNAVAILABLE;
|
|
10727
|
+
try {
|
|
10728
|
+
const r = await ctx.ideAction({ action: "diagnostics", path: args?.path?.trim() || void 0, severity: args?.severity });
|
|
10729
|
+
return ideResultToText(r);
|
|
10730
|
+
} catch (e) {
|
|
10731
|
+
return toolFailure(`[IDE \u5F02\u5E38]\uFF1A${e?.message ?? e}`);
|
|
10732
|
+
}
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
},
|
|
10736
|
+
{
|
|
10737
|
+
type: "function",
|
|
10738
|
+
function: {
|
|
10739
|
+
name: "ide_run_task",
|
|
10740
|
+
validateEnvironment: requireIdeHost,
|
|
10741
|
+
description: "\u89E6\u53D1 VSCode \u4EFB\u52A1\uFF08.vscode/tasks.json \u91CC\u5B9A\u4E49\u7684 build/test/watch \u7B49\uFF09\uFF0C\u5728 IDE \u7EC8\u7AEF\u9762\u677F\u542F\u52A8\u3002\u2605 \u89E6\u53D1\u5373\u8FD4\u56DE\u3001\u4E0D\u7B49\u5F85\u5B8C\u6210\uFF08watch \u7C7B\u4EFB\u52A1\u6C38\u4E0D\u7ED3\u675F\uFF09\uFF1B\u8981\u770B\u7A0B\u5E8F\u5316\u8F93\u51FA\u8BF7\u6539\u7528 run_command\u3002name \u7F3A\u7701=\u53EA\u5217\u51FA\u53EF\u7528\u4EFB\u52A1\u540D\u4E0D\u6267\u884C\uFF08SAFE \u63A2\u6D4B\uFF09\u3002\u4EC5 VSCode \u5BBF\u4E3B\u53EF\u7528\u3002",
|
|
10742
|
+
parameters: {
|
|
10743
|
+
type: "object",
|
|
10744
|
+
properties: {
|
|
10745
|
+
name: { type: "string", description: "\u4EFB\u52A1\u540D\uFF08\u7F3A\u7701\u5219\u4EC5\u5217\u51FA\u53EF\u7528\u4EFB\u52A1\uFF09" }
|
|
10746
|
+
},
|
|
10747
|
+
required: []
|
|
10748
|
+
},
|
|
10749
|
+
safetyLevel: "danger" /* DANGER */,
|
|
10750
|
+
isSync: true,
|
|
10751
|
+
requireApproval: (args) => args?.name ? `\u5728 IDE \u4E2D\u89E6\u53D1\u4EFB\u52A1\u300C${args.name}\u300D\uFF1F\u4EFB\u52A1\u5C06\u5728 VSCode \u7EC8\u7AEF\u9762\u677F\u6267\u884C\u3002` : "\u8BFB\u53D6 IDE \u53EF\u7528\u4EFB\u52A1\u5217\u8868\uFF1F",
|
|
10752
|
+
async execute(args, ctx) {
|
|
10753
|
+
if (!ctx?.ideAction) return IDE_UNAVAILABLE;
|
|
10754
|
+
try {
|
|
10755
|
+
const r = await ctx.ideAction({ action: "task", name: args?.name?.trim() || void 0 });
|
|
10756
|
+
return ideResultToText(r);
|
|
10757
|
+
} catch (e) {
|
|
10758
|
+
return toolFailure(`[IDE \u5F02\u5E38]\uFF1A${e?.message ?? e}`);
|
|
10759
|
+
}
|
|
10760
|
+
}
|
|
10761
|
+
}
|
|
10762
|
+
}
|
|
10763
|
+
];
|
|
10764
|
+
}
|
|
10765
|
+
});
|
|
10766
|
+
|
|
10443
10767
|
// ../core/src/tool/index.ts
|
|
10444
10768
|
var tool_exports = {};
|
|
10445
10769
|
__export(tool_exports, {
|
|
@@ -10475,6 +10799,7 @@ var init_tool = __esm({
|
|
|
10475
10799
|
init_recall();
|
|
10476
10800
|
init_spreadsheet();
|
|
10477
10801
|
init_document();
|
|
10802
|
+
init_ide();
|
|
10478
10803
|
init_type();
|
|
10479
10804
|
agentTools = [];
|
|
10480
10805
|
agentSubTools = createAgentTools(() => agentTools);
|
|
@@ -10500,8 +10825,9 @@ var init_tool = __esm({
|
|
|
10500
10825
|
...memoryTools,
|
|
10501
10826
|
...recallTools,
|
|
10502
10827
|
...spreadsheetTools,
|
|
10503
|
-
...documentTools
|
|
10504
|
-
|
|
10828
|
+
...documentTools,
|
|
10829
|
+
...ideTools
|
|
10830
|
+
// IDE 桥(ide_open_file / ide_diagnostics / ide_run_task;仅 VSCode 宿主注入钩子,否则 validateEnvironment 自隐藏)
|
|
10505
10831
|
);
|
|
10506
10832
|
}
|
|
10507
10833
|
});
|
|
@@ -10801,7 +11127,7 @@ var init_autoPermission = __esm({
|
|
|
10801
11127
|
|
|
10802
11128
|
// ../core/src/agent/toolExecution.ts
|
|
10803
11129
|
import path34 from "path";
|
|
10804
|
-
var applyPrivacyMasking, processToolCall;
|
|
11130
|
+
var applyPrivacyMasking, scaleTruncBudget, processToolCall;
|
|
10805
11131
|
var init_toolExecution = __esm({
|
|
10806
11132
|
"../core/src/agent/toolExecution.ts"() {
|
|
10807
11133
|
"use strict";
|
|
@@ -10833,6 +11159,14 @@ var init_toolExecution = __esm({
|
|
|
10833
11159
|
return output;
|
|
10834
11160
|
}
|
|
10835
11161
|
};
|
|
11162
|
+
scaleTruncBudget = (base, fill) => {
|
|
11163
|
+
if (!Number.isFinite(base) || base <= 0) return base;
|
|
11164
|
+
if (fill === void 0 || !Number.isFinite(fill) || fill <= 0.5) return base;
|
|
11165
|
+
const floor = Math.min(base, 2e3);
|
|
11166
|
+
if (fill > 0.85) return Math.max(floor, Math.floor(base * 0.35));
|
|
11167
|
+
const factor = 1 - (fill - 0.5) / 0.35 * 0.6;
|
|
11168
|
+
return Math.max(floor, Math.floor(base * factor));
|
|
11169
|
+
};
|
|
10836
11170
|
processToolCall = async (toolCall, ctx) => {
|
|
10837
11171
|
const {
|
|
10838
11172
|
sessionId,
|
|
@@ -10848,10 +11182,12 @@ var init_toolExecution = __esm({
|
|
|
10848
11182
|
onUIEvent,
|
|
10849
11183
|
requestApproval: hostRequestApproval,
|
|
10850
11184
|
requestQuestion: hostRequestQuestion,
|
|
11185
|
+
ideAction,
|
|
10851
11186
|
keepRecentUnits,
|
|
10852
11187
|
compactRatio,
|
|
10853
11188
|
modelWindow,
|
|
10854
|
-
parentSystemPrompt
|
|
11189
|
+
parentSystemPrompt,
|
|
11190
|
+
readTracker
|
|
10855
11191
|
} = ctx;
|
|
10856
11192
|
let calledName = "";
|
|
10857
11193
|
let calledArgs = {};
|
|
@@ -10889,7 +11225,7 @@ var init_toolExecution = __esm({
|
|
|
10889
11225
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: note } });
|
|
10890
11226
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel: note, resultForUser: note, ok: false };
|
|
10891
11227
|
}
|
|
10892
|
-
const toolCtx = { sessionId, cwd: getActiveWorkspaceRoot(), abortSignal: signal, depth, keepRecentUnits, compactRatio, modelWindow, parentSystemPrompt, events, onUIEvent, requestApproval: hostRequestApproval, requestQuestion: hostRequestQuestion, emitProgress: (m) => onUIEvent?.({ type: "tool.progress", toolsId: toolCall.id, toolName: calledName, message: m }), permissionMode };
|
|
11228
|
+
const toolCtx = { sessionId, cwd: getActiveWorkspaceRoot(), abortSignal: signal, depth, keepRecentUnits, compactRatio, modelWindow, parentSystemPrompt, events, onUIEvent, requestApproval: hostRequestApproval, requestQuestion: hostRequestQuestion, ideAction, emitProgress: (m) => onUIEvent?.({ type: "tool.progress", toolsId: toolCall.id, toolName: calledName, message: m }), permissionMode, readTracker };
|
|
10893
11229
|
let result = "";
|
|
10894
11230
|
let resultStatus = "success";
|
|
10895
11231
|
let errorCategory;
|
|
@@ -11082,9 +11418,10 @@ ${result}`;
|
|
|
11082
11418
|
events({ sessionId, eventType: "tool.validation.failed", metadata: { depth, decisionSource: llmDecisionSource, durationMs: performance.now() - startTime, round, tools_id: toolCall.id, toolName: calledName, toolSource: "builtin", ok: false, attempt: round }, payload: { output: result } });
|
|
11083
11419
|
}
|
|
11084
11420
|
result = applyPrivacyMasking(matchedTool?.function?.privacyMaskingRules, calledArgs, result);
|
|
11085
|
-
const
|
|
11421
|
+
const fill = ctx.contextTokensEst !== void 0 && modelWindow > 0 ? ctx.contextTokensEst / modelWindow : void 0;
|
|
11422
|
+
const truncBudget = scaleTruncBudget(matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS, fill);
|
|
11086
11423
|
const sidecarNote = result.length > truncBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), result) : void 0;
|
|
11087
|
-
result = truncateToolResult(result,
|
|
11424
|
+
result = truncateToolResult(result, truncBudget, sidecarNote);
|
|
11088
11425
|
const ok = resultStatus === "success";
|
|
11089
11426
|
let resultForModel = result;
|
|
11090
11427
|
let resultForUser = result;
|
|
@@ -11098,9 +11435,9 @@ ${result}`;
|
|
|
11098
11435
|
}
|
|
11099
11436
|
if (postHookOverride !== void 0) {
|
|
11100
11437
|
console.log(`\u270F\uFE0F [Post-hook] [${calledName}] \u6A21\u578B\u89C6\u56FE\u7ED3\u679C\u5DF2\u88AB hook \u6539\u5199`);
|
|
11101
|
-
const overrideBudget = matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS;
|
|
11438
|
+
const overrideBudget = scaleTruncBudget(matchedTool?.function?.maxOutputCharacters ?? appConfig.MAX_TOOL_RESULT_CHARS, fill);
|
|
11102
11439
|
const overrideNote = postHookOverride.length > overrideBudget ? await writeSidecarArchive(sessionId, String(toolCall.id), postHookOverride) : void 0;
|
|
11103
|
-
resultForModel = truncateToolResult(postHookOverride,
|
|
11440
|
+
resultForModel = truncateToolResult(postHookOverride, overrideBudget, overrideNote);
|
|
11104
11441
|
}
|
|
11105
11442
|
return { toolCallId: toolCall.id, calledName, calledArgs, resultForModel, resultForUser, ok, imageAttachments };
|
|
11106
11443
|
};
|
|
@@ -11108,7 +11445,7 @@ ${result}`;
|
|
|
11108
11445
|
});
|
|
11109
11446
|
|
|
11110
11447
|
// ../core/src/agent/toolScheduling.ts
|
|
11111
|
-
var scheduleToolCalls;
|
|
11448
|
+
var dedupeSameRoundCalls, scheduleToolCalls;
|
|
11112
11449
|
var init_toolScheduling = __esm({
|
|
11113
11450
|
"../core/src/agent/toolScheduling.ts"() {
|
|
11114
11451
|
"use strict";
|
|
@@ -11118,6 +11455,22 @@ var init_toolScheduling = __esm({
|
|
|
11118
11455
|
init_config();
|
|
11119
11456
|
init_tool();
|
|
11120
11457
|
init_permissions();
|
|
11458
|
+
dedupeSameRoundCalls = (tcs) => {
|
|
11459
|
+
const batch = [];
|
|
11460
|
+
const plan = [];
|
|
11461
|
+
const firstBySig = /* @__PURE__ */ new Map();
|
|
11462
|
+
for (const tc of tcs) {
|
|
11463
|
+
const sig = `${tc?.function?.name ?? ""}::${tc?.function?.arguments ?? ""}`;
|
|
11464
|
+
const first = firstBySig.get(sig);
|
|
11465
|
+
if (first) plan.push({ tc, dupOf: first });
|
|
11466
|
+
else {
|
|
11467
|
+
firstBySig.set(sig, tc);
|
|
11468
|
+
batch.push(tc);
|
|
11469
|
+
plan.push({ tc });
|
|
11470
|
+
}
|
|
11471
|
+
}
|
|
11472
|
+
return { batch, plan };
|
|
11473
|
+
};
|
|
11121
11474
|
scheduleToolCalls = async function* (assistantMessage, message, ctx) {
|
|
11122
11475
|
const { sessionId, signal, rawTools } = ctx;
|
|
11123
11476
|
let abortedDuringTools = false;
|
|
@@ -11172,26 +11525,43 @@ var init_toolScheduling = __esm({
|
|
|
11172
11525
|
const tc = tcs[idx];
|
|
11173
11526
|
const { name: pname, args: pargs, parseFailed: pparseFailed } = parseTc(tc);
|
|
11174
11527
|
if (canParallelize(pname, pargs, pparseFailed)) {
|
|
11175
|
-
const
|
|
11528
|
+
const seg = [];
|
|
11176
11529
|
while (idx < tcs.length) {
|
|
11177
11530
|
const btc = tcs[idx];
|
|
11178
11531
|
const bp = parseTc(btc);
|
|
11179
11532
|
if (!canParallelize(bp.name, bp.args, bp.parseFailed)) break;
|
|
11180
|
-
|
|
11533
|
+
seg.push(btc);
|
|
11181
11534
|
idx++;
|
|
11182
11535
|
}
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11536
|
+
const { batch, plan } = dedupeSameRoundCalls(seg);
|
|
11537
|
+
for (const p of plan) {
|
|
11538
|
+
const bp = parseTc(p.tc);
|
|
11539
|
+
yield { type: "tool.start", toolCallId: p.tc.id, toolName: bp.name, args: bp.args };
|
|
11186
11540
|
}
|
|
11187
11541
|
const outcomes = await Promise.all(batch.map((btc) => processToolCall(btc, ctx)));
|
|
11188
|
-
|
|
11542
|
+
const outcomeByTc = /* @__PURE__ */ new Map();
|
|
11543
|
+
batch.forEach((btc, i) => outcomeByTc.set(btc, outcomes[i]));
|
|
11544
|
+
const batchEntries = [];
|
|
11545
|
+
const dupSeq = /* @__PURE__ */ new Map();
|
|
11546
|
+
for (const p of plan) {
|
|
11547
|
+
let oc;
|
|
11548
|
+
if (p.dupOf) {
|
|
11549
|
+
const firstOc = outcomeByTc.get(p.dupOf);
|
|
11550
|
+
const n = (dupSeq.get(p.dupOf) ?? 1) + 1;
|
|
11551
|
+
dupSeq.set(p.dupOf, n);
|
|
11552
|
+
const note = `(\u540C\u8F6E\u91CD\u590D\u8C03\u7528 #${n}\uFF0C\u5DF2\u590D\u7528 #1 \u7684\u7ED3\u679C)
|
|
11553
|
+
`;
|
|
11554
|
+
oc = { ...firstOc, toolCallId: p.tc.id, resultForModel: note + firstOc.resultForModel, resultForUser: note + firstOc.resultForUser, imageAttachments: void 0 };
|
|
11555
|
+
} else {
|
|
11556
|
+
oc = outcomeByTc.get(p.tc);
|
|
11557
|
+
}
|
|
11189
11558
|
yield { type: "tool.end", toolCallId: oc.toolCallId, toolName: oc.calledName, result: oc.resultForUser, ok: oc.ok };
|
|
11190
11559
|
message.push({ role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
11191
|
-
|
|
11560
|
+
batchEntries.push({ sessionId, role: "tool", tool_call_id: oc.toolCallId, content: oc.resultForModel });
|
|
11192
11561
|
if (oc.imageAttachments?.length) pendingImages.push(...oc.imageAttachments);
|
|
11193
11562
|
if (oc.aborted) abortedDuringTools = true;
|
|
11194
11563
|
}
|
|
11564
|
+
await appendMessages(sessionId, batchEntries);
|
|
11195
11565
|
} else {
|
|
11196
11566
|
yield { type: "tool.start", toolCallId: tc.id, toolName: pname, args: pargs };
|
|
11197
11567
|
const oc = await processToolCall(tc, ctx);
|
|
@@ -11368,9 +11738,10 @@ var init_streamInference = __esm({
|
|
|
11368
11738
|
}
|
|
11369
11739
|
);
|
|
11370
11740
|
const noOutputYet = !contentBuf && !reasoningBuf && toolCallsBuf.size === 0;
|
|
11371
|
-
if (isIdleTimeout &&
|
|
11741
|
+
if (isIdleTimeout && streamAttempt < MAX_STREAM_RETRIES) {
|
|
11372
11742
|
if (!noOutputYet) yield { type: "text.reset" };
|
|
11373
|
-
|
|
11743
|
+
const stallShape = noOutputYet ? "\uFF0C\u5C1A\u65E0\u8F93\u51FA" : hasCompleteToolCall ? "\uFF0C\u5DF2\u6709\u5B8C\u6574 tool_call\uFF08\u6D41\u5C3E\u90E8 stall\uFF09" : "\uFF0Ctool_call \u672A\u6D41\u5B8C";
|
|
11744
|
+
console.warn(`\u26A0\uFE0F \u6D41\u5F0F stall\uFF08idle \u8D85\u65F6${stallShape}\uFF09\uFF0C\u7B2C ${streamAttempt + 1}/${MAX_STREAM_RETRIES} \u6B21\u91CD\u8BD5...`);
|
|
11374
11745
|
contentBuf = "";
|
|
11375
11746
|
reasoningBuf = "";
|
|
11376
11747
|
toolCallsBuf.clear();
|
|
@@ -11416,7 +11787,8 @@ var init_streamInference = __esm({
|
|
|
11416
11787
|
events,
|
|
11417
11788
|
depth,
|
|
11418
11789
|
signal,
|
|
11419
|
-
toolsTokens
|
|
11790
|
+
toolsTokens,
|
|
11791
|
+
onUIEvent: ctx.onUIEvent
|
|
11420
11792
|
});
|
|
11421
11793
|
inferenceMessages = withNudgeTail(message, nudgeMsg);
|
|
11422
11794
|
compactedThisRound = true;
|
|
@@ -11498,7 +11870,7 @@ var init_streamInference = __esm({
|
|
|
11498
11870
|
});
|
|
11499
11871
|
|
|
11500
11872
|
// ../core/src/agent/agentNudges.ts
|
|
11501
|
-
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, TODO_INCOMPLETE_FENCE, TODO_INCOMPLETE_MAX, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, TODO_INCOMPLETE_TEXT, createNudgeScheduler;
|
|
11873
|
+
var NUDGE_EVERY, NUDGE_FENCE, PHANTOM_FENCE, PHANTOM_RETRY_MAX, EARLY_FINAL_FENCE, EARLY_FINAL_TURN_THRESHOLD, EARLY_FINAL_MAX, TOOL_DIGEST_FENCE, TOOL_DIGEST_MAX, TOOL_DIGEST_WINDOW, TOOL_DIGEST_TEXT_MAX_LEN, PLAN_FIRST_FENCE, REPEAT_FENCE, READ_REPEAT_THRESHOLD, GREP_REPEAT_THRESHOLD, REPEAT_NUDGE_MAX, TODO_INCOMPLETE_FENCE, TODO_INCOMPLETE_MAX, PHANTOM_TEXT, EARLY_FINAL_TEXT, TOOL_DIGEST_TEXT, usageNoteText, NUDGE_TEXT, COMPLEX_VERBS, COMPLEX_OBJECTS, COMPLEX_MARKERS, QUERY_LEAD, looksComplex, PLAN_FIRST_TEXT, looksComplete, parseToolCall, normPath, normQuery, REPEAT_READ_TEXT, REPEAT_GREP_TEXT, TODO_INCOMPLETE_TEXT, createNudgeScheduler;
|
|
11502
11874
|
var init_agentNudges = __esm({
|
|
11503
11875
|
"../core/src/agent/agentNudges.ts"() {
|
|
11504
11876
|
"use strict";
|
|
@@ -11523,7 +11895,11 @@ var init_agentNudges = __esm({
|
|
|
11523
11895
|
PHANTOM_TEXT = "\u4F60\u7684\u4E0A\u4E00\u6761\u56DE\u590D\u6CA1\u6709\u4EFB\u4F55\u5185\u5BB9\u3001\u4E5F\u6CA1\u6709\u8C03\u7528\u4EFB\u4F55\u5DE5\u5177\uFF0C\u4F46\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\u3002\u8BF7\u7EE7\u7EED\u63A8\u8FDB\uFF08\u8C03\u7528\u5DE5\u5177\u6216\u7ED9\u51FA\u5B9E\u8D28\u56DE\u7B54\uFF09\uFF1B\u82E5\u786E\u5B9E\u53D7\u963B\u3001\u9700\u8981\u7528\u6237\u51B3\u7B56\uFF0C\u7528 ask_question \u8BF4\u660E\u5177\u4F53\u963B\u585E\u70B9\u3002\u4E0D\u8981\u8FD4\u56DE\u7A7A\u56DE\u590D\u3002";
|
|
11524
11896
|
EARLY_FINAL_TEXT = (round) => `\u4F60\u4EC5 ${round} \u8F6E\u5C31\u51C6\u5907\u6536\u5C3E\uFF0C\u4E14\u56DE\u7B54\u4E2D\u6CA1\u6709\u660E\u786E\u7684\u5B8C\u6210\u58F0\u660E\u3002\u8BF7\u81EA\u68C0\uFF1A\u82E5\u7528\u6237\u8F93\u5165\u672C\u5C31\u65E0\u9700\u5DE5\u5177\uFF08\u5BD2\u6684/\u95F2\u804A/\u7EAF\u95EE\u7B54\uFF09\u3001\u6216\u4F60\u5728\u7B49\u7528\u6237\u6F84\u6E05\u51B3\u7B56\uFF0C\u76F4\u63A5\u6B63\u5E38\u56DE\u5E94\u5373\u53EF\uFF0C\u5FFD\u7565\u672C\u81EA\u68C0\u3001\u4E0D\u8981\u8F93\u51FA\u4EFB\u4F55\u81EA\u68C0\u8BF4\u660E\uFF1B\u82E5\u786E\u6709\u4EFB\u52A1\u672A\u843D\u5730\uFF08\u6240\u9700\u4FE1\u606F\u672A\u83B7\u53D6\u9F50 / \u8BE5\u6539\u7684\u6587\u4EF6\u672A\u6539\u5B8C / \u672A\u9A8C\u8BC1\uFF09\uFF0C\u7ACB\u5373\u7EE7\u7EED\u8C03\u7528\u5DE5\u5177\u63A8\u8FDB\uFF0C\u4E0D\u8981\u8349\u7387\u603B\u7ED3\u6536\u5C3E\uFF1B\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002`;
|
|
11525
11897
|
TOOL_DIGEST_TEXT = "\u4F60\u521A\u6267\u884C\u5B8C\u5DE5\u5177\u62FF\u5230\u7ED3\u679C\uFF0C\u5374\u672A\u57FA\u4E8E\u8BE5\u7ED3\u679C\u7ED9\u51FA\u5B9E\u8D28\u56DE\u5E94\u5C31\u51C6\u5907\u6536\u5C3E\u3002\u8BF7\u7ED3\u5408\u5DE5\u5177\u8FD4\u56DE\u7ED3\u679C\u7EE7\u7EED\u63A8\u8FDB\uFF1B\u82E5\u7ED3\u679C\u8868\u660E\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\uFF08\u5982\u4ECD\u5728\u7F16\u8BD1/\u8FD0\u884C\u3001\u9700\u7EE7\u7EED\u8F6E\u8BE2\uFF09\uFF0C\u7ACB\u5373\u91C7\u53D6\u4E0B\u4E00\u6B65\u884C\u52A8\uFF0C\u4E0D\u8981\u7A7A\u624B\u6536\u5C3E\u3002\u82E5\u786E\u5DF2\u5168\u90E8\u5B8C\u6210\uFF0C\u8BF7\u660E\u786E\u56DE\u590D\u300C\u5DF2\u5B8C\u6210\u300D\u5E76\u7B80\u8FF0\u6210\u679C\u3002";
|
|
11526
|
-
|
|
11898
|
+
usageNoteText = (usage) => {
|
|
11899
|
+
const pct = usage.windowTokens > 0 ? Math.min(100, Math.max(0, Math.round(usage.usedTokens / usage.windowTokens * 100))) : 0;
|
|
11900
|
+
return `\u5F53\u524D\u4E0A\u4E0B\u6587\u5DF2\u7528\u7EA6 ${pct}%\uFF08\u4F30\u7B97 \u2248${usage.usedTokens}/${usage.windowTokens} token\uFF09\u3002\u82E5\u5360\u6BD4\u5DF2\u9AD8\uFF08>70%\uFF09\uFF1A\u4F18\u5148\u6536\u655B\u6536\u5C3E\u3001\u51CF\u5C0F\u5355\u6B21\u8BFB\u53D6\u91CF\uFF08search_grep \u5B9A\u4F4D\u540E\u5C40\u90E8\u8BFB\u53D6\uFF09\uFF0C\u907F\u514D\u89E6\u53D1\u5F3A\u5236\u538B\u7F29\u3002`;
|
|
11901
|
+
};
|
|
11902
|
+
NUDGE_TEXT = (round, usage) => `\u4F60\u5DF2\u6267\u884C\u7EA6 ${round} \u8F6E\u5DE5\u5177\u8C03\u7528\u3002\u8BF7\u81EA\u8BC4\uFF1A\u82E5\u4EFB\u52A1\u5DF2\u53EF\u5B8C\u6210\uFF0C\u7ACB\u5373\u7ED9\u51FA\u6700\u7EC8\u7B54\u6848\u3001\u4E0D\u518D\u8C03\u7528\u5DE5\u5177\uFF1B\u82E5\u786E\u9700\u66F4\u591A\u6B65\u9AA4\uFF0C\u7EE7\u7EED\uFF0C\u4F46\u786E\u4FDD\u6BCF\u6B65\u90FD\u5728\u5B9E\u8D28\u63A8\u8FDB\u4EFB\u52A1\u3001\u4E0D\u91CD\u590D\u68C0\u7D22\u3002${usage ? usageNoteText(usage) : ""}`;
|
|
11527
11903
|
COMPLEX_VERBS = /实现|新增|添加|重构|改造|迁移|重写|拆分|升级|开发|编写|构建|集成|支持|完善|implement|refactor|migrate|rewrite|rebuild|restructure|split|upgrade|integrate|develop/i;
|
|
11528
11904
|
COMPLEX_OBJECTS = /功能|模块|系统|架构|流程|机制|组件|服务|页面|接口|能力|特性|面板|feature|module|system|architecture|pipeline|component|service|page|api\b|interface|panel|workflow|endpoint/i;
|
|
11529
11905
|
COMPLEX_MARKERS = /多个文件|多文件|整体|全套|端到端|从零|重新设计|一整套|跨[^,。\s]{1,6}|multiple files|multi-file|end-to-end|from scratch|across\s+\S+/i;
|
|
@@ -11610,11 +11986,13 @@ ${PLAN_FIRST_TEXT}` };
|
|
|
11610
11986
|
if (repeatRetrievalPending) {
|
|
11611
11987
|
const m = repeatRetrievalPending;
|
|
11612
11988
|
repeatRetrievalPending = null;
|
|
11613
|
-
|
|
11989
|
+
const usage = opts.getContextUsage?.() ?? null;
|
|
11990
|
+
return usage ? { ...m, content: `${m.content}${usageNoteText(usage)}` } : m;
|
|
11614
11991
|
}
|
|
11615
11992
|
if (round > 1 && round % NUDGE_EVERY === 1) {
|
|
11993
|
+
const usage = opts.getContextUsage?.() ?? null;
|
|
11616
11994
|
return { role: "system", content: `${NUDGE_FENCE}
|
|
11617
|
-
${NUDGE_TEXT(round)}` };
|
|
11995
|
+
${NUDGE_TEXT(round, usage)}` };
|
|
11618
11996
|
}
|
|
11619
11997
|
return null;
|
|
11620
11998
|
},
|
|
@@ -11839,7 +12217,13 @@ async function* runAgent(message, options) {
|
|
|
11839
12217
|
const m = message.find((x) => x?.role === "user");
|
|
11840
12218
|
return msgText(m?.content);
|
|
11841
12219
|
})();
|
|
11842
|
-
const nudges = createNudgeScheduler({
|
|
12220
|
+
const nudges = createNudgeScheduler({
|
|
12221
|
+
firstPrompt,
|
|
12222
|
+
planMode: !!options.planMode,
|
|
12223
|
+
noEarlyFinal: !!options.noEarlyFinal,
|
|
12224
|
+
getContextUsage: () => ({ usedTokens: Math.round(estimateTokens(message) * calibRatio + toolsTokens), windowTokens: modelWindow })
|
|
12225
|
+
});
|
|
12226
|
+
const readTracker = /* @__PURE__ */ new Map();
|
|
11843
12227
|
const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
|
|
11844
12228
|
const llmDecisionSource = depth > 0 ? "llm_spawn_agent" : "llm";
|
|
11845
12229
|
const startTime = performance.now();
|
|
@@ -11910,7 +12294,8 @@ async function* runAgent(message, options) {
|
|
|
11910
12294
|
correctionRatio: calibRatio,
|
|
11911
12295
|
lastRealPromptTokens,
|
|
11912
12296
|
lastCachedTokens,
|
|
11913
|
-
toolsTokens
|
|
12297
|
+
toolsTokens,
|
|
12298
|
+
onUIEvent: options.onUIEvent
|
|
11914
12299
|
}
|
|
11915
12300
|
);
|
|
11916
12301
|
} catch (e) {
|
|
@@ -11943,7 +12328,8 @@ async function* runAgent(message, options) {
|
|
|
11943
12328
|
keepRecentUnits,
|
|
11944
12329
|
compactRatio,
|
|
11945
12330
|
modelWindow,
|
|
11946
|
-
toolsTokens
|
|
12331
|
+
toolsTokens,
|
|
12332
|
+
onUIEvent: options.onUIEvent
|
|
11947
12333
|
});
|
|
11948
12334
|
if (infResult.kind === "aborted") {
|
|
11949
12335
|
yield { type: "final", text: infResult.partialText || lastContent || "\uFF08\u5DF2\u4E2D\u6B62\uFF09" };
|
|
@@ -11989,8 +12375,8 @@ async function* runAgent(message, options) {
|
|
|
11989
12375
|
for (const tc of assistantMessage.tool_calls) {
|
|
11990
12376
|
const ph = "\uFF08\u91CD\u590D\u8C03\u7528\u7194\u65AD\uFF0C\u672A\u6267\u884C\uFF09";
|
|
11991
12377
|
message.push({ role: "tool", tool_call_id: tc.id, content: ph });
|
|
11992
|
-
await appendMessage({ sessionId, role: "tool", tool_call_id: tc.id, content: ph });
|
|
11993
12378
|
}
|
|
12379
|
+
await appendMessages(sessionId, assistantMessage.tool_calls.map((tc) => ({ sessionId, role: "tool", tool_call_id: tc.id, content: "\uFF08\u91CD\u590D\u8C03\u7528\u7194\u65AD\uFF0C\u672A\u6267\u884C\uFF09" })));
|
|
11994
12380
|
yield { type: "final", text: repeatVerdict.text };
|
|
11995
12381
|
return;
|
|
11996
12382
|
}
|
|
@@ -12010,10 +12396,17 @@ async function* runAgent(message, options) {
|
|
|
12010
12396
|
onUIEvent: options.onUIEvent,
|
|
12011
12397
|
requestApproval: options.requestApproval,
|
|
12012
12398
|
requestQuestion: options.requestQuestion,
|
|
12399
|
+
ideAction: options.ideAction,
|
|
12013
12400
|
keepRecentUnits,
|
|
12014
12401
|
compactRatio,
|
|
12015
12402
|
modelWindow,
|
|
12016
|
-
parentSystemPrompt
|
|
12403
|
+
parentSystemPrompt,
|
|
12404
|
+
// ★ P2-1:本时刻上下文用量估算(此时已含本轮 assistant,常数近似足够,不逐工具更新)——
|
|
12405
|
+
// processToolCall 据此收缩截断预算:最坏组合「上下文已 75% 满时跑大输出命令 → 16K 字符
|
|
12406
|
+
// 进上下文 → 下一轮立刻压缩」被釜底抽薪;口径与 ensureFitsWindow/nudge 闭包同公式。
|
|
12407
|
+
contextTokensEst: Math.round(estimateTokens(message) * calibRatio + toolsTokens),
|
|
12408
|
+
readTracker
|
|
12409
|
+
// ★ P3-8:run 级读取追踪(同一引用透传,跨轮累计)
|
|
12017
12410
|
};
|
|
12018
12411
|
const scheduleResult = yield* scheduleToolCalls(assistantMessage, message, toolCallCtx);
|
|
12019
12412
|
if (scheduleResult.kind === "aborted") {
|
|
@@ -12153,7 +12546,7 @@ var init_lineage = __esm({
|
|
|
12153
12546
|
});
|
|
12154
12547
|
|
|
12155
12548
|
// ../core/src/agent/subagent.ts
|
|
12156
|
-
var SUBAGENT_DENYLIST, activeSubagents, failText, RESUME_NOTE, runSubagent;
|
|
12549
|
+
var SUBAGENT_DENYLIST, activeSubagents, failText, RESUME_NOTE, createProgressThrottler, runSubagent;
|
|
12157
12550
|
var init_subagent = __esm({
|
|
12158
12551
|
"../core/src/agent/subagent.ts"() {
|
|
12159
12552
|
"use strict";
|
|
@@ -12174,6 +12567,24 @@ var init_subagent = __esm({
|
|
|
12174
12567
|
`\u4F60\u6B64\u524D\u7684\u5DE5\u4F5C\u5386\u53F2\u5DF2\u5B8C\u6574\u6062\u590D\u5230\u672C\u6B21\u4E0A\u4E0B\u6587\uFF08\u78C1\u76D8\u6700\u65B0\u72B6\u6001\uFF0C\u53EF\u80FD\u6BD4\u4F60\u4E0A\u6B21\u8BB0\u5FC6\u66F4\u65B0\uFF09\u3002`,
|
|
12175
12568
|
`\u8BF7\u5148\u5BF9\u7167\u5386\u53F2\u7B80\u8981\u56DE\u987E\u5DF2\u5B8C\u6210 / \u672A\u5B8C\u6210\u90E8\u5206\uFF0C\u518D\u7EE7\u7EED\u6267\u884C\u65B0\u4EFB\u52A1\uFF1B\u6700\u7EC8\u6C47\u62A5\u4E5F\u8BF7\u5148\u6982\u8FF0\u6B64\u524D\u8FDB\u5C55\u3002`
|
|
12176
12569
|
].join("\n");
|
|
12570
|
+
createProgressThrottler = (onEmit, throttleMs = 1e3, now = Date.now) => {
|
|
12571
|
+
let acc = "";
|
|
12572
|
+
let lastAt = 0;
|
|
12573
|
+
return {
|
|
12574
|
+
push(delta) {
|
|
12575
|
+
acc += delta ?? "";
|
|
12576
|
+
const t = now();
|
|
12577
|
+
if (t - lastAt < throttleMs) return;
|
|
12578
|
+
lastAt = t;
|
|
12579
|
+
const lines = acc.split("\n");
|
|
12580
|
+
const complete = lines.slice(0, -1).filter((l) => l.trim().length > 0);
|
|
12581
|
+
let last = complete[complete.length - 1] ?? "";
|
|
12582
|
+
if (!last) return;
|
|
12583
|
+
if (last.length > 120) last = last.slice(0, 119) + "\u2026";
|
|
12584
|
+
onEmit(last);
|
|
12585
|
+
}
|
|
12586
|
+
};
|
|
12587
|
+
};
|
|
12177
12588
|
runSubagent = async (spec, ctx, getGlobalTools) => {
|
|
12178
12589
|
const { task, name, role, resumeSessionId } = spec;
|
|
12179
12590
|
const resuming = typeof resumeSessionId === "string" && resumeSessionId.length > 0;
|
|
@@ -12255,6 +12666,7 @@ var init_subagent = __esm({
|
|
|
12255
12666
|
const toolSchemas = manifest && manifest.tools.length > 0 ? allTools.filter((t) => manifest.tools.includes(t.function.name) || wantsMcp && (t.function.name === "mcp_call" || t.function.name === "mcp_list_tools")) : allTools.filter((t) => !SUBAGENT_DENYLIST.has(t.function.name));
|
|
12256
12667
|
console.log(`${resuming ? "\u{1F501} \u7EED\u8DD1" : "\u{1F423} \u6D3E\u751F"}\u5B50 Agent [\u6DF1\u5EA6: ${ctx.depth + 1}/${MAX_AGENT_DEPTH}][${subSessionId}]${manifest ? ` \u58F0\u660E\u5F0F=${manifest.name}` : ""} \u4EFB\u52A1: "${task.slice(0, 50)}..."`);
|
|
12257
12668
|
activeSubagents.add(subSessionId);
|
|
12669
|
+
ctx.onUIEvent?.({ type: "subagent.count", running: activeSubagents.size, phase: "start", name: manifest?.name, depth: ctx.depth + 1 });
|
|
12258
12670
|
try {
|
|
12259
12671
|
const subMessages = await buildContextMessages(subSessionId, { role: "user", content: task }, subSystem, manifest?.model);
|
|
12260
12672
|
await appendMessage({ sessionId: subSessionId, role: "user", content: task });
|
|
@@ -12276,6 +12688,8 @@ var init_subagent = __esm({
|
|
|
12276
12688
|
// ★ 必须透传:否则子 agent 调用需审批工具时前端收不到弹窗,waitForUserApproval 永久挂起(死锁)
|
|
12277
12689
|
requestApproval: ctx.requestApproval,
|
|
12278
12690
|
// ★ 同步透传宿主审批钩子,子 agent 高危工具仍走同一审批通道
|
|
12691
|
+
ideAction: ctx.ideAction,
|
|
12692
|
+
// ★ IDE 桥透传:ide_diagnostics 等 SAFE 只读动作子 agent 也可用(缺省 undefined → 工具自隐藏)
|
|
12279
12693
|
permissionMode: ctx.permissionMode,
|
|
12280
12694
|
// ★ P1-6 透传:子 agent 工作区文件编辑也走 auto 分类器
|
|
12281
12695
|
noEarlyFinal: true,
|
|
@@ -12286,6 +12700,7 @@ var init_subagent = __esm({
|
|
|
12286
12700
|
const startCtx = { sessionId: subSessionId, parentSessionId: ctx.sessionId, task, depth: ctx.depth + 1, name: manifest?.name, cwd: ctx.cwd };
|
|
12287
12701
|
await dispatch("SubagentStart", startCtx);
|
|
12288
12702
|
let result;
|
|
12703
|
+
const progress = createProgressThrottler((line) => ctx.onUIEvent?.({ type: "subagent.progress", text: line }));
|
|
12289
12704
|
try {
|
|
12290
12705
|
for await (const e of runAgent(subMessages, subOptions)) {
|
|
12291
12706
|
if (ctx.abortSignal?.aborted) {
|
|
@@ -12295,6 +12710,8 @@ var init_subagent = __esm({
|
|
|
12295
12710
|
if (e.type === "final") {
|
|
12296
12711
|
subResult = e.text;
|
|
12297
12712
|
hasFinalResult = true;
|
|
12713
|
+
} else if (e.type === "text.delta") {
|
|
12714
|
+
progress.push(e.text ?? "");
|
|
12298
12715
|
}
|
|
12299
12716
|
}
|
|
12300
12717
|
if (result === void 0) {
|
|
@@ -12306,6 +12723,10 @@ var init_subagent = __esm({
|
|
|
12306
12723
|
} catch (streamError) {
|
|
12307
12724
|
result = { ok: false, output: failText(`[\u5B50Agent\u5D29\u6E83]\uFF1A\u5B50 Agent \u5728\u8FED\u4EE3\u63A8\u7406\u4E3B\u5FAA\u73AF\u65F6\u906D\u9047\u5E95\u5C42\u5F02\u5E38: ${streamError.message}`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
12308
12725
|
} finally {
|
|
12726
|
+
try {
|
|
12727
|
+
ctx.onUIEvent?.({ type: "subagent.progress", text: "", done: true });
|
|
12728
|
+
} catch {
|
|
12729
|
+
}
|
|
12309
12730
|
if (result) {
|
|
12310
12731
|
await dispatch("SubagentStop", { ...startCtx, ok: result.ok, output: result.output.slice(0, 2e3) }).catch((e) => console.warn(`\u26A0\uFE0F SubagentStop hook \u5F02\u5E38\uFF08\u5DF2\u5FFD\u7565\uFF09: ${e?.message ?? e}`));
|
|
12311
12732
|
}
|
|
@@ -12315,6 +12736,7 @@ var init_subagent = __esm({
|
|
|
12315
12736
|
return { ok: false, output: failText(`[\u6D3E\u751F\u6267\u884C\u5931\u8D25]: ${error.message}`), sessionId: subSessionId, manifestName: manifest?.name };
|
|
12316
12737
|
} finally {
|
|
12317
12738
|
activeSubagents.delete(subSessionId);
|
|
12739
|
+
ctx.onUIEvent?.({ type: "subagent.count", running: activeSubagents.size, phase: "stop", name: manifest?.name, depth: ctx.depth + 1 });
|
|
12318
12740
|
}
|
|
12319
12741
|
};
|
|
12320
12742
|
}
|
|
@@ -13618,7 +14040,7 @@ var init_systemPrompt = __esm({
|
|
|
13618
14040
|
|
|
13619
14041
|
\u3010\u64CD\u4F5C\u786E\u8BA4\u7EA6\u5B9A\u3011
|
|
13620
14042
|
- \u9047\u5230\u4F1A\u6539\u53D8\u72B6\u6001\u6216\u5177\u98CE\u9669\u7684\u5DE5\u5177\uFF08\u5199\u6587\u4EF6\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u79FB\u52A8\u3001\u6267\u884C\u547D\u4EE4\u3001\u5BF9\u5916\u7F51\u7EDC\u8BF7\u6C42\u7B49\uFF09\uFF0C\u76F4\u63A5\u8C03\u7528\u8BE5\u5DE5\u5177\u5373\u53EF\uFF0C\u4E0D\u8981\u5148\u7528\u81EA\u7136\u8BED\u8A00\u5F81\u6C42\u786E\u8BA4\uFF08\u5982"\u6211\u53EF\u4EE5\u6267\u884C\u5417\uFF1F""\u662F\u5426\u7EE7\u7EED\uFF1F"\uFF09\u3002\u8FD9\u7C7B\u5DE5\u5177\u7531\u7CFB\u7EDF\u7EDF\u4E00\u62E6\u622A\u5E76\u5F39\u51FA\u5BA1\u6279\u754C\u9762\uFF0C\u7528\u6237\u4F1A\u4E00\u952E\u540C\u610F\u6216\u62D2\u7EDD\u2014\u2014\u4F60\u65E0\u9700\u4EE3\u66FF\u7CFB\u7EDF\u53D1\u95EE\uFF0C\u66F4\u4E0D\u8981\u505C\u4E0B\u7B49\u7528\u6237\u6253\u5B57\u786E\u8BA4\u3002
|
|
13621
|
-
- \u4EC5\u5F53\u5B58\u5728\u591A\u79CD\u660E\u663E\u4E0D\u540C\u7684\u5B9E\u73B0\u65B9\u6848\u3001\u9700\u8981\u7528\u6237\u5728\u65B9\u5411\u4E0A\u62CD\u677F\u65F6\uFF0C\u8C03\u7528 ask_question \u5DE5\u5177\u63D0\u51FA 2-4 \u4E2A\u7ED3\u6784\u5316\u9009\u9879\u8BA9\u7528\u6237\u9009\u62E9\uFF08\u7EC8\u7AEF\u4F1A\u5F39\u51FA\u591A\u9009\u6846\uFF0C\u6BD4\u7EAF\u6587\u5B57\u66F4\u6E05\u6670\u9AD8\u6548\uFF0C\u7528\u6237\u9009\u62E9\u4F1A\u81EA\u52A8\u56DE\u4F20\u7ED9\u4F60\uFF09\uFF1B\u5BF9"\u67D0\u4E2A\u5177\u4F53\u64CD\u4F5C\u662F\u5426\u6267\u884C"\u4E00\u5F8B\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u8D70\u5BA1\u6279\uFF0C\u4E0D\u8981\u7528 ask_question \u53BB\u95EE\u80FD\u5426\u6267\u884C\u67D0\u4E2A\u64CD\u4F5C\u3002
|
|
14043
|
+
- \u4EC5\u5F53\u5B58\u5728\u591A\u79CD\u660E\u663E\u4E0D\u540C\u7684\u5B9E\u73B0\u65B9\u6848\u3001\u9700\u8981\u7528\u6237\u5728\u65B9\u5411\u4E0A\u62CD\u677F\u65F6\uFF0C\u8C03\u7528 ask_question \u5DE5\u5177\u63D0\u51FA 2-4 \u4E2A\u7ED3\u6784\u5316\u9009\u9879\u8BA9\u7528\u6237\u9009\u62E9\uFF08\u7EC8\u7AEF\u4F1A\u5F39\u51FA\u591A\u9009\u6846\uFF0C\u6BD4\u7EAF\u6587\u5B57\u66F4\u6E05\u6670\u9AD8\u6548\uFF0C\u7528\u6237\u9009\u62E9\u4F1A\u81EA\u52A8\u56DE\u4F20\u7ED9\u4F60\uFF1B\u63D0\u95EE\u6846\u6052\u6709\u300COther\u300D\u81EA\u7531\u8F93\u5165\u6863\uFF0C\u9700\u8981\u7528\u6237\u63D0\u4F9B\u9009\u9879\u4E4B\u5916\u7684\u8D44\u6599\u2014\u2014\u5982\u767B\u5F55 token\u3001\u6587\u4EF6\u8DEF\u5F84\u2014\u2014\u4E5F\u7528 ask_question \u63D0\u51FA\uFF0C\u7528\u6237\u4F1A\u7ECF Other \u7C98\u8D34\u539F\u6587\u56DE\u4F20\uFF09\uFF1B\u5BF9"\u67D0\u4E2A\u5177\u4F53\u64CD\u4F5C\u662F\u5426\u6267\u884C"\u4E00\u5F8B\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u8D70\u5BA1\u6279\uFF0C\u4E0D\u8981\u7528 ask_question \u53BB\u95EE\u80FD\u5426\u6267\u884C\u67D0\u4E2A\u64CD\u4F5C\u3002
|
|
13622
14044
|
|
|
13623
14045
|
\u3010\u8BA1\u5212\u6A21\u5F0F\u3011
|
|
13624
14046
|
${PLAN_MODE_AUTO_ENTER_HINT}
|
|
@@ -13759,6 +14181,7 @@ ${envLines.join("\n")}`;
|
|
|
13759
14181
|
onUIEvent,
|
|
13760
14182
|
requestApproval: requestApproval2,
|
|
13761
14183
|
requestQuestion: opts?.requestQuestion,
|
|
14184
|
+
ideAction: opts?.ideAction,
|
|
13762
14185
|
// ★ CLI 宿主注入项:计划模式两阶段 / 模型覆盖 / 思考等级。serve 不传 → 均为 undefined,行为不变。
|
|
13763
14186
|
planMode: opts?.planMode,
|
|
13764
14187
|
permissionMode: opts?.permissionMode,
|
|
@@ -14211,6 +14634,7 @@ var init_useChatState = __esm({
|
|
|
14211
14634
|
const [rows, setRows] = useState([]);
|
|
14212
14635
|
const [busy, setBusy] = useState(false);
|
|
14213
14636
|
const [aborting, setAborting] = useState(false);
|
|
14637
|
+
const [runningAgents, setRunningAgents] = useState(0);
|
|
14214
14638
|
const [showThinkingText, setShowThinkingText] = useState(false);
|
|
14215
14639
|
const [pendingApproval, setPendingApproval] = useState(null);
|
|
14216
14640
|
const [pendingQuestion, setPendingQuestion] = useState(null);
|
|
@@ -14239,6 +14663,21 @@ var init_useChatState = __esm({
|
|
|
14239
14663
|
const thinkingLevelRef = useRef(
|
|
14240
14664
|
!MODEL_THINKING_ENABLED ? "off" : MODEL_REASONING_EFFORT === "max" ? "max" : "high"
|
|
14241
14665
|
);
|
|
14666
|
+
const archivedSummaryRef = useRef("");
|
|
14667
|
+
const compactProgressIdRef = useRef(null);
|
|
14668
|
+
const dropCompactProgressRow = useCallback(() => {
|
|
14669
|
+
const pid = compactProgressIdRef.current;
|
|
14670
|
+
if (pid == null) return;
|
|
14671
|
+
compactProgressIdRef.current = null;
|
|
14672
|
+
setRows((prev) => prev.filter((r) => r.id !== pid));
|
|
14673
|
+
}, []);
|
|
14674
|
+
const subagentProgressIdRef = useRef(null);
|
|
14675
|
+
const dropSubagentProgressRow = useCallback(() => {
|
|
14676
|
+
const pid = subagentProgressIdRef.current;
|
|
14677
|
+
if (pid == null) return;
|
|
14678
|
+
subagentProgressIdRef.current = null;
|
|
14679
|
+
setRows((prev) => prev.filter((r) => r.id !== pid));
|
|
14680
|
+
}, []);
|
|
14242
14681
|
const outputStyleRef = useRef(void 0);
|
|
14243
14682
|
const lastUsageRef = useRef(null);
|
|
14244
14683
|
useEffect(() => {
|
|
@@ -14374,6 +14813,69 @@ var init_useChatState = __esm({
|
|
|
14374
14813
|
}
|
|
14375
14814
|
break;
|
|
14376
14815
|
}
|
|
14816
|
+
case "compact.progress": {
|
|
14817
|
+
flush();
|
|
14818
|
+
const done = obj.done ?? 0;
|
|
14819
|
+
const total = obj.total ?? 0;
|
|
14820
|
+
if (compactProgressIdRef.current == null) {
|
|
14821
|
+
const id = newRowId();
|
|
14822
|
+
compactProgressIdRef.current = id;
|
|
14823
|
+
setRows((prev) => [...prev, { id, kind: "compact-progress", done, total }]);
|
|
14824
|
+
} else {
|
|
14825
|
+
const pid = compactProgressIdRef.current;
|
|
14826
|
+
setRows((prev) => prev.map((r) => r.id === pid && r.kind === "compact-progress" ? { ...r, done, total } : r));
|
|
14827
|
+
}
|
|
14828
|
+
break;
|
|
14829
|
+
}
|
|
14830
|
+
case "compact.done": {
|
|
14831
|
+
flush();
|
|
14832
|
+
dropCompactProgressRow();
|
|
14833
|
+
archivedSummaryRef.current = obj.summary || "";
|
|
14834
|
+
setRows((prev) => [...prev, {
|
|
14835
|
+
id: newRowId(),
|
|
14836
|
+
kind: "compact",
|
|
14837
|
+
tokensBefore: obj.tokensBefore ?? 0,
|
|
14838
|
+
tokensAfter: obj.tokensAfter ?? 0,
|
|
14839
|
+
trigger: obj.trigger ?? "auto",
|
|
14840
|
+
hasSummary: !!obj.summary
|
|
14841
|
+
}]);
|
|
14842
|
+
break;
|
|
14843
|
+
}
|
|
14844
|
+
case "task.exit": {
|
|
14845
|
+
flush();
|
|
14846
|
+
const cmd = obj.command ?? "";
|
|
14847
|
+
const id = newRowId();
|
|
14848
|
+
if (obj.ok) {
|
|
14849
|
+
setRows((prev) => [...prev, { id, kind: "meta", text: `\u{1F4E7} \u540E\u53F0\u4EFB\u52A1\u5B8C\u6210\uFF08exit=0\uFF09\uFF1A${cmd}` }]);
|
|
14850
|
+
} else if (obj.status === "killed") {
|
|
14851
|
+
setRows((prev) => [...prev, { id, kind: "meta", text: `\u23F9 \u540E\u53F0\u4EFB\u52A1\u5DF2\u505C\u6B62\uFF1A${cmd}` }]);
|
|
14852
|
+
} else {
|
|
14853
|
+
setRows((prev) => [...prev, { id, kind: "system", text: `\u26A0\uFE0F \u540E\u53F0\u4EFB\u52A1\u5931\u8D25\uFF08exit=${obj.exitCode ?? "?"}\uFF09\uFF1A${cmd}` }]);
|
|
14854
|
+
}
|
|
14855
|
+
break;
|
|
14856
|
+
}
|
|
14857
|
+
case "subagent.count": {
|
|
14858
|
+
setRunningAgents(Math.max(0, obj.running ?? 0));
|
|
14859
|
+
break;
|
|
14860
|
+
}
|
|
14861
|
+
case "subagent.progress": {
|
|
14862
|
+
flush();
|
|
14863
|
+
if (obj.done) {
|
|
14864
|
+
dropSubagentProgressRow();
|
|
14865
|
+
break;
|
|
14866
|
+
}
|
|
14867
|
+
const ptext = String(obj.text ?? "").slice(0, 160);
|
|
14868
|
+
if (!ptext) break;
|
|
14869
|
+
if (subagentProgressIdRef.current == null) {
|
|
14870
|
+
const id = newRowId();
|
|
14871
|
+
subagentProgressIdRef.current = id;
|
|
14872
|
+
setRows((prev) => [...prev, { id, kind: "subagent-progress", text: ptext }]);
|
|
14873
|
+
} else {
|
|
14874
|
+
const pid = subagentProgressIdRef.current;
|
|
14875
|
+
setRows((prev) => prev.map((r) => r.id === pid && r.kind === "subagent-progress" ? { ...r, text: ptext } : r));
|
|
14876
|
+
}
|
|
14877
|
+
break;
|
|
14878
|
+
}
|
|
14377
14879
|
case "round.start": {
|
|
14378
14880
|
closeStreaming();
|
|
14379
14881
|
break;
|
|
@@ -14393,6 +14895,9 @@ var init_useChatState = __esm({
|
|
|
14393
14895
|
}
|
|
14394
14896
|
case "final": {
|
|
14395
14897
|
closeStreaming();
|
|
14898
|
+
dropCompactProgressRow();
|
|
14899
|
+
dropSubagentProgressRow();
|
|
14900
|
+
setRunningAgents(0);
|
|
14396
14901
|
const ft = obj.text ?? "";
|
|
14397
14902
|
if (ft) {
|
|
14398
14903
|
const id = newRowId();
|
|
@@ -14402,6 +14907,9 @@ var init_useChatState = __esm({
|
|
|
14402
14907
|
}
|
|
14403
14908
|
case "error": {
|
|
14404
14909
|
closeStreaming();
|
|
14910
|
+
dropCompactProgressRow();
|
|
14911
|
+
dropSubagentProgressRow();
|
|
14912
|
+
setRunningAgents(0);
|
|
14405
14913
|
const id = newRowId();
|
|
14406
14914
|
setRows((prev) => [...prev, { id, kind: "system", text: `\u274C ${obj.message ?? "\u672A\u77E5\u9519\u8BEF"}` }]);
|
|
14407
14915
|
break;
|
|
@@ -14630,6 +15138,7 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
14630
15138
|
const clearRows = useCallback(() => {
|
|
14631
15139
|
flush();
|
|
14632
15140
|
setRows([]);
|
|
15141
|
+
setRunningAgents(0);
|
|
14633
15142
|
toolRowByCallId.current.clear();
|
|
14634
15143
|
}, [flush]);
|
|
14635
15144
|
const loadSession = useCallback(async (id) => {
|
|
@@ -14728,11 +15237,13 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
14728
15237
|
outputStyleRef.current = name;
|
|
14729
15238
|
}, []);
|
|
14730
15239
|
const getOutputStyle2 = useCallback(() => outputStyleRef.current, []);
|
|
15240
|
+
const getArchivedSummary = useCallback(() => archivedSummaryRef.current, []);
|
|
14731
15241
|
return {
|
|
14732
15242
|
// 状态
|
|
14733
15243
|
rows,
|
|
14734
15244
|
busy,
|
|
14735
15245
|
aborting,
|
|
15246
|
+
runningAgents,
|
|
14736
15247
|
showThinkingText,
|
|
14737
15248
|
pendingApproval,
|
|
14738
15249
|
pendingQuestion,
|
|
@@ -14765,6 +15276,7 @@ ${r.output.trim() || "(\u65E0\u8F93\u51FA)"}`);
|
|
|
14765
15276
|
getThinkingLevel,
|
|
14766
15277
|
setOutputStyle,
|
|
14767
15278
|
getOutputStyle: getOutputStyle2,
|
|
15279
|
+
getArchivedSummary,
|
|
14768
15280
|
openSessionPicker,
|
|
14769
15281
|
resolveSession,
|
|
14770
15282
|
loadSession,
|
|
@@ -15003,6 +15515,33 @@ var init_MessageBlock = __esm({
|
|
|
15003
15515
|
row.text
|
|
15004
15516
|
] }) });
|
|
15005
15517
|
}
|
|
15518
|
+
if (row.kind === "compact") {
|
|
15519
|
+
const freed = Math.max(0, (row.tokensBefore || 0) - (row.tokensAfter || 0));
|
|
15520
|
+
const freedText = freed >= 1e3 ? `${Math.round(freed / 1e3)}k` : String(freed);
|
|
15521
|
+
return /* @__PURE__ */ jsx3(Box, { marginTop: 0.25, marginBottom: 0.25, children: /* @__PURE__ */ jsxs(Text3, { italic: true, color: THEME.grayDim, children: [
|
|
15522
|
+
"\u5DF2\u538B\u7F29\u4E0A\u4E0B\u6587 \xB7 ",
|
|
15523
|
+
row.trigger === "manual" ? "\u624B\u52A8" : "\u81EA\u52A8",
|
|
15524
|
+
" \xB7 \u91CA\u653E ",
|
|
15525
|
+
freedText,
|
|
15526
|
+
" tokens \xB7 \u4E0B\u6761\u6D88\u606F\u5C06\u91CD\u5EFA\u7F13\u5B58",
|
|
15527
|
+
row.hasSummary ? "\uFF08/archive \u770B\u6458\u8981\uFF09" : ""
|
|
15528
|
+
] }) });
|
|
15529
|
+
}
|
|
15530
|
+
if (row.kind === "compact-progress") {
|
|
15531
|
+
return /* @__PURE__ */ jsx3(Box, { marginTop: 0.25, marginBottom: 0.25, children: /* @__PURE__ */ jsxs(Text3, { italic: true, color: THEME.grayDim, children: [
|
|
15532
|
+
"\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587 ",
|
|
15533
|
+
row.done,
|
|
15534
|
+
"/",
|
|
15535
|
+
row.total,
|
|
15536
|
+
" \u6279\u2026\uFF08\u8F85\u52A9\u6A21\u578B\u6458\u8981\u4E2D\uFF0C\u8BF7\u7A0D\u5019\uFF09"
|
|
15537
|
+
] }) });
|
|
15538
|
+
}
|
|
15539
|
+
if (row.kind === "subagent-progress") {
|
|
15540
|
+
return /* @__PURE__ */ jsx3(Box, { marginTop: 0.25, marginBottom: 0.25, children: /* @__PURE__ */ jsxs(Text3, { italic: true, color: THEME.grayDim, children: [
|
|
15541
|
+
"\u21B3 \u5B50agent ",
|
|
15542
|
+
row.text
|
|
15543
|
+
] }) });
|
|
15544
|
+
}
|
|
15006
15545
|
if (row.kind === "info") {
|
|
15007
15546
|
const lines = wrapText(row.text, Math.max(8, wrapW));
|
|
15008
15547
|
return /* @__PURE__ */ jsx3(Box, { flexDirection: "column", marginTop: 0.5, marginBottom: 0.5, children: lines.map((line, j) => /* @__PURE__ */ jsxs(Text3, { color: THEME.coralMuted, children: [
|
|
@@ -15413,79 +15952,9 @@ var init_ApprovalModal = __esm({
|
|
|
15413
15952
|
}
|
|
15414
15953
|
});
|
|
15415
15954
|
|
|
15416
|
-
// src/components/QuestionModal.tsx
|
|
15417
|
-
import { Box as Box6, Text as Text8 } from "ink";
|
|
15418
|
-
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
15419
|
-
var QuestionModal;
|
|
15420
|
-
var init_QuestionModal = __esm({
|
|
15421
|
-
"src/components/QuestionModal.tsx"() {
|
|
15422
|
-
"use strict";
|
|
15423
|
-
init_theme();
|
|
15424
|
-
init_util();
|
|
15425
|
-
QuestionModal = ({ question, options, multiSelect, cursor, checked, wrapW }) => {
|
|
15426
|
-
const contentW = Math.max(16, wrapW);
|
|
15427
|
-
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: THEME.coralBright, paddingX: 1, paddingY: 1, marginTop: 1, children: [
|
|
15428
|
-
/* @__PURE__ */ jsxs6(Text8, { color: THEME.coralBright, bold: true, children: [
|
|
15429
|
-
"\u2753 ",
|
|
15430
|
-
multiSelect ? "\u591A\u9009\u63D0\u95EE" : "\u63D0\u95EE"
|
|
15431
|
-
] }),
|
|
15432
|
-
/* @__PURE__ */ jsx8(Box6, { flexDirection: "column", marginTop: 0.5, marginBottom: 0.5, children: wrapText(question || "(\u65E0\u95EE\u9898)", contentW).map((line, j) => /* @__PURE__ */ jsx8(Text8, { color: THEME.white, children: line }, j)) }),
|
|
15433
|
-
options.map((opt, i) => {
|
|
15434
|
-
const active = i === cursor;
|
|
15435
|
-
const isChecked = checked.has(i);
|
|
15436
|
-
const marker2 = multiSelect ? isChecked ? "[x] " : "[ ] " : "";
|
|
15437
|
-
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
15438
|
-
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", children: [
|
|
15439
|
-
/* @__PURE__ */ jsx8(Text8, { color: active ? THEME.coralBright : void 0, bold: true, children: active ? "\u203A " : " " }),
|
|
15440
|
-
/* @__PURE__ */ jsxs6(Text8, { color: active ? THEME.white : THEME.gray, bold: active, children: [
|
|
15441
|
-
marker2,
|
|
15442
|
-
opt.label
|
|
15443
|
-
] })
|
|
15444
|
-
] }),
|
|
15445
|
-
opt.description ? /* @__PURE__ */ jsxs6(Text8, { color: THEME.grayDim, children: [
|
|
15446
|
-
" ",
|
|
15447
|
-
wrapText(opt.description, contentW - 4).map((l) => l).join(" ")
|
|
15448
|
-
] }) : null
|
|
15449
|
-
] }, i);
|
|
15450
|
-
}),
|
|
15451
|
-
/* @__PURE__ */ jsx8(Text8, { color: THEME.grayDim, children: multiSelect ? "\u2191\u2193 \u79FB\u52A8 \xB7 Space \u52FE\u9009 \xB7 Enter \u63D0\u4EA4 \xB7 Esc \u53D6\u6D88" : "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" })
|
|
15452
|
-
] });
|
|
15453
|
-
};
|
|
15454
|
-
}
|
|
15455
|
-
});
|
|
15456
|
-
|
|
15457
|
-
// src/components/PlanModal.tsx
|
|
15458
|
-
import { Box as Box7, Text as Text9 } from "ink";
|
|
15459
|
-
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
15460
|
-
var OPTIONS2, PlanModal;
|
|
15461
|
-
var init_PlanModal = __esm({
|
|
15462
|
-
"src/components/PlanModal.tsx"() {
|
|
15463
|
-
"use strict";
|
|
15464
|
-
init_theme();
|
|
15465
|
-
init_strings();
|
|
15466
|
-
OPTIONS2 = [
|
|
15467
|
-
{ label: S.planAcceptAuto, color: THEME.ok },
|
|
15468
|
-
{ label: S.planAcceptManual, color: THEME.warn },
|
|
15469
|
-
{ label: S.planEdit, color: THEME.blue },
|
|
15470
|
-
{ label: S.planReject, color: THEME.danger }
|
|
15471
|
-
];
|
|
15472
|
-
PlanModal = ({ selectedIndex }) => /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: THEME.blue, paddingX: 1, paddingY: 1, marginTop: 1, children: [
|
|
15473
|
-
/* @__PURE__ */ jsx9(Text9, { color: THEME.blue, bold: true, children: S.planTitle }),
|
|
15474
|
-
/* @__PURE__ */ jsx9(Text9, { color: THEME.grayDim, children: S.planPrompt }),
|
|
15475
|
-
OPTIONS2.map((opt, i) => {
|
|
15476
|
-
const active = i === selectedIndex;
|
|
15477
|
-
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
|
|
15478
|
-
/* @__PURE__ */ jsx9(Text9, { color: active ? THEME.coralBright : void 0, bold: true, children: active ? "\u203A " : " " }),
|
|
15479
|
-
/* @__PURE__ */ jsx9(Text9, { color: active ? THEME.white : opt.color, bold: active, children: opt.label })
|
|
15480
|
-
] }, opt.label);
|
|
15481
|
-
})
|
|
15482
|
-
] });
|
|
15483
|
-
}
|
|
15484
|
-
});
|
|
15485
|
-
|
|
15486
15955
|
// src/components/MultilineInput.tsx
|
|
15487
|
-
import { Box as
|
|
15488
|
-
import { jsx as
|
|
15956
|
+
import { Box as Box6, Text as Text8, useInput } from "ink";
|
|
15957
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
15489
15958
|
var lineColOf, offsetOf, MultilineInput;
|
|
15490
15959
|
var init_MultilineInput = __esm({
|
|
15491
15960
|
"src/components/MultilineInput.tsx"() {
|
|
@@ -15546,30 +16015,112 @@ var init_MultilineInput = __esm({
|
|
|
15546
16015
|
const [curLine, curCol] = lineColOf(value, cursor);
|
|
15547
16016
|
const lines = value.length ? value.split("\n") : [""];
|
|
15548
16017
|
const renderLine = (line, i, isActive) => {
|
|
15549
|
-
if (!isActive) return /* @__PURE__ */
|
|
16018
|
+
if (!isActive) return /* @__PURE__ */ jsx8(Text8, { color: THEME.white, children: line || " " }, i);
|
|
15550
16019
|
const before = line.slice(0, curCol);
|
|
15551
16020
|
const at = curCol < line.length ? line[curCol] : "";
|
|
15552
16021
|
const after = curCol < line.length ? line.slice(curCol + 1) : "";
|
|
15553
|
-
return /* @__PURE__ */
|
|
15554
|
-
/* @__PURE__ */
|
|
15555
|
-
at ? /* @__PURE__ */
|
|
15556
|
-
/* @__PURE__ */
|
|
16022
|
+
return /* @__PURE__ */ jsxs6(Text8, { children: [
|
|
16023
|
+
/* @__PURE__ */ jsx8(Text8, { color: THEME.white, children: before }),
|
|
16024
|
+
at ? /* @__PURE__ */ jsx8(Text8, { inverse: true, color: THEME.white, children: at }) : /* @__PURE__ */ jsx8(Text8, { color: THEME.coralBright, children: "\u2588" }),
|
|
16025
|
+
/* @__PURE__ */ jsx8(Text8, { color: THEME.white, children: after })
|
|
15557
16026
|
] }, i);
|
|
15558
16027
|
};
|
|
15559
|
-
return /* @__PURE__ */
|
|
15560
|
-
/* @__PURE__ */
|
|
15561
|
-
/* @__PURE__ */
|
|
15562
|
-
/* @__PURE__ */
|
|
15563
|
-
/* @__PURE__ */
|
|
16028
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", flexShrink: 0, children: [
|
|
16029
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: THEME.coralBright, children: "> " }),
|
|
16030
|
+
/* @__PURE__ */ jsx8(Box6, { flexGrow: 1, minWidth: 0, children: value === "" && placeholder ? /* @__PURE__ */ jsxs6(Text8, { children: [
|
|
16031
|
+
/* @__PURE__ */ jsx8(Text8, { color: THEME.coralBright, children: "\u2588" }),
|
|
16032
|
+
/* @__PURE__ */ jsxs6(Text8, { color: THEME.grayDim, children: [
|
|
15564
16033
|
" ",
|
|
15565
16034
|
placeholder
|
|
15566
16035
|
] })
|
|
15567
|
-
] }) : /* @__PURE__ */
|
|
16036
|
+
] }) : /* @__PURE__ */ jsx8(Box6, { flexDirection: "column", children: lines.map((line, i) => renderLine(line, i, i === curLine)) }) })
|
|
15568
16037
|
] });
|
|
15569
16038
|
};
|
|
15570
16039
|
}
|
|
15571
16040
|
});
|
|
15572
16041
|
|
|
16042
|
+
// src/components/QuestionModal.tsx
|
|
16043
|
+
import { Box as Box7, Text as Text9 } from "ink";
|
|
16044
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
16045
|
+
var QuestionModal;
|
|
16046
|
+
var init_QuestionModal = __esm({
|
|
16047
|
+
"src/components/QuestionModal.tsx"() {
|
|
16048
|
+
"use strict";
|
|
16049
|
+
init_theme();
|
|
16050
|
+
init_util();
|
|
16051
|
+
init_MultilineInput();
|
|
16052
|
+
QuestionModal = ({ question, options, multiSelect, cursor, checked, wrapW, editing, draft, draftCursor, onDraftChange, onDraftSubmit }) => {
|
|
16053
|
+
const contentW = Math.max(16, wrapW);
|
|
16054
|
+
const onOther = cursor === options.length && !editing;
|
|
16055
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: THEME.coralBright, paddingX: 1, paddingY: 1, marginTop: 1, children: [
|
|
16056
|
+
/* @__PURE__ */ jsxs7(Text9, { color: THEME.coralBright, bold: true, children: [
|
|
16057
|
+
"\u2753 ",
|
|
16058
|
+
multiSelect ? "\u591A\u9009\u63D0\u95EE" : "\u63D0\u95EE"
|
|
16059
|
+
] }),
|
|
16060
|
+
/* @__PURE__ */ jsx9(Box7, { flexDirection: "column", marginTop: 0.5, marginBottom: 0.5, children: wrapText(question || "(\u65E0\u95EE\u9898)", contentW).map((line, j) => /* @__PURE__ */ jsx9(Text9, { color: THEME.white, children: line }, j)) }),
|
|
16061
|
+
options.map((opt, i) => {
|
|
16062
|
+
const active = i === cursor;
|
|
16063
|
+
const isChecked = checked.has(i);
|
|
16064
|
+
const marker2 = multiSelect ? isChecked ? "[x] " : "[ ] " : "";
|
|
16065
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
16066
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
|
|
16067
|
+
/* @__PURE__ */ jsx9(Text9, { color: active ? THEME.coralBright : void 0, bold: true, children: active ? "\u203A " : " " }),
|
|
16068
|
+
/* @__PURE__ */ jsxs7(Text9, { color: active ? THEME.white : THEME.gray, bold: active, children: [
|
|
16069
|
+
marker2,
|
|
16070
|
+
opt.label
|
|
16071
|
+
] })
|
|
16072
|
+
] }),
|
|
16073
|
+
opt.description ? /* @__PURE__ */ jsxs7(Text9, { color: THEME.grayDim, children: [
|
|
16074
|
+
" ",
|
|
16075
|
+
wrapText(opt.description, contentW - 4).map((l) => l).join(" ")
|
|
16076
|
+
] }) : null
|
|
16077
|
+
] }, i);
|
|
16078
|
+
}),
|
|
16079
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 0.5, children: [
|
|
16080
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", children: [
|
|
16081
|
+
/* @__PURE__ */ jsx9(Text9, { color: onOther ? THEME.coralBright : void 0, bold: true, children: onOther ? "\u203A " : " " }),
|
|
16082
|
+
/* @__PURE__ */ jsxs7(Text9, { color: editing || onOther ? THEME.white : THEME.gray, bold: onOther, children: [
|
|
16083
|
+
"\u270E Other",
|
|
16084
|
+
editing ? "\uFF08\u8F93\u5165\u540E Enter \u63D0\u4EA4\uFF09" : " \u2014 \u81EA\u7531\u8F93\u5165"
|
|
16085
|
+
] })
|
|
16086
|
+
] }),
|
|
16087
|
+
editing ? /* @__PURE__ */ jsx9(Box7, { flexDirection: "row", marginLeft: 2, marginTop: 0.5, children: /* @__PURE__ */ jsx9(MultilineInput, { value: draft, cursor: draftCursor, onChange: onDraftChange, onSubmit: onDraftSubmit, active: true, placeholder: "\u7C98\u8D34 token / \u8DEF\u5F84\u7B49\uFF0CEnter \u63D0\u4EA4" }) }) : null
|
|
16088
|
+
] }),
|
|
16089
|
+
/* @__PURE__ */ jsx9(Text9, { color: THEME.grayDim, children: editing ? "Enter \u63D0\u4EA4 \xB7 Esc \u8FD4\u56DE\u9009\u9879" : multiSelect ? "\u2191\u2193 \u79FB\u52A8 \xB7 Space \u52FE\u9009 \xB7 Enter \u63D0\u4EA4 \xB7 Esc \u53D6\u6D88" : "\u2191\u2193 \u9009\u62E9 \xB7 Enter \u786E\u8BA4 \xB7 Esc \u53D6\u6D88" })
|
|
16090
|
+
] });
|
|
16091
|
+
};
|
|
16092
|
+
}
|
|
16093
|
+
});
|
|
16094
|
+
|
|
16095
|
+
// src/components/PlanModal.tsx
|
|
16096
|
+
import { Box as Box8, Text as Text10 } from "ink";
|
|
16097
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
16098
|
+
var OPTIONS2, PlanModal;
|
|
16099
|
+
var init_PlanModal = __esm({
|
|
16100
|
+
"src/components/PlanModal.tsx"() {
|
|
16101
|
+
"use strict";
|
|
16102
|
+
init_theme();
|
|
16103
|
+
init_strings();
|
|
16104
|
+
OPTIONS2 = [
|
|
16105
|
+
{ label: S.planAcceptAuto, color: THEME.ok },
|
|
16106
|
+
{ label: S.planAcceptManual, color: THEME.warn },
|
|
16107
|
+
{ label: S.planEdit, color: THEME.blue },
|
|
16108
|
+
{ label: S.planReject, color: THEME.danger }
|
|
16109
|
+
];
|
|
16110
|
+
PlanModal = ({ selectedIndex }) => /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: THEME.blue, paddingX: 1, paddingY: 1, marginTop: 1, children: [
|
|
16111
|
+
/* @__PURE__ */ jsx10(Text10, { color: THEME.blue, bold: true, children: S.planTitle }),
|
|
16112
|
+
/* @__PURE__ */ jsx10(Text10, { color: THEME.grayDim, children: S.planPrompt }),
|
|
16113
|
+
OPTIONS2.map((opt, i) => {
|
|
16114
|
+
const active = i === selectedIndex;
|
|
16115
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "row", children: [
|
|
16116
|
+
/* @__PURE__ */ jsx10(Text10, { color: active ? THEME.coralBright : void 0, bold: true, children: active ? "\u203A " : " " }),
|
|
16117
|
+
/* @__PURE__ */ jsx10(Text10, { color: active ? THEME.white : opt.color, bold: active, children: opt.label })
|
|
16118
|
+
] }, opt.label);
|
|
16119
|
+
})
|
|
16120
|
+
] });
|
|
16121
|
+
}
|
|
16122
|
+
});
|
|
16123
|
+
|
|
15573
16124
|
// src/components/PlanEditor.tsx
|
|
15574
16125
|
import { Box as Box9, Text as Text11 } from "ink";
|
|
15575
16126
|
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -16047,7 +16598,7 @@ var init_App = __esm({
|
|
|
16047
16598
|
}
|
|
16048
16599
|
return /* @__PURE__ */ jsx18(MessageBlock, { row, wrapW, streamTail });
|
|
16049
16600
|
};
|
|
16050
|
-
isDynamicRow = (r) => r.kind === "assistant" && !!r.streaming || r.kind === "thinking" && !!r.streaming || r.kind === "tool" && r.status === "running" || r.kind === "todos" && !!r.active;
|
|
16601
|
+
isDynamicRow = (r) => r.kind === "assistant" && !!r.streaming || r.kind === "thinking" && !!r.streaming || r.kind === "tool" && r.status === "running" || r.kind === "todos" && !!r.active || r.kind === "compact-progress" || r.kind === "subagent-progress";
|
|
16051
16602
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
16052
16603
|
App = ({ resumeSessionId, initialPlanMode, initialAutoMode, initialIncludeProject, engineReady }) => {
|
|
16053
16604
|
const state = useChatState(resumeSessionId, initialPlanMode, initialAutoMode);
|
|
@@ -16076,8 +16627,13 @@ var init_App = __esm({
|
|
|
16076
16627
|
const [planCursor, setPlanCursor] = useState4(0);
|
|
16077
16628
|
const [qCursor, setQCursor] = useState4(0);
|
|
16078
16629
|
const [qChecked, setQChecked] = useState4(/* @__PURE__ */ new Set());
|
|
16630
|
+
const [qEditing, setQEditing] = useState4(false);
|
|
16631
|
+
const [qDraft, setQDraft] = useState4("");
|
|
16632
|
+
const [qDraftCursor, setQDraftCursor] = useState4(0);
|
|
16079
16633
|
const qCursorRef = useRef2(0);
|
|
16080
16634
|
const qCheckedRef = useRef2(/* @__PURE__ */ new Set());
|
|
16635
|
+
const qEditingRef = useRef2(false);
|
|
16636
|
+
const qDraftRef = useRef2("");
|
|
16081
16637
|
const inputRef = useRef2(input);
|
|
16082
16638
|
const selectIdxRef = useRef2(selectIdx);
|
|
16083
16639
|
const busyRef = useRef2(state.busy);
|
|
@@ -16090,6 +16646,8 @@ var init_App = __esm({
|
|
|
16090
16646
|
planDraftRef.current = planDraft;
|
|
16091
16647
|
qCursorRef.current = qCursor;
|
|
16092
16648
|
qCheckedRef.current = qChecked;
|
|
16649
|
+
qEditingRef.current = qEditing;
|
|
16650
|
+
qDraftRef.current = qDraft;
|
|
16093
16651
|
const statusLineCfgRef = useRef2(null);
|
|
16094
16652
|
const statusLineRunRef = useRef2(false);
|
|
16095
16653
|
const [statusLineText, setStatusLineText] = useState4("");
|
|
@@ -16231,6 +16789,9 @@ var init_App = __esm({
|
|
|
16231
16789
|
useEffect4(() => {
|
|
16232
16790
|
setQCursor(0);
|
|
16233
16791
|
setQChecked(/* @__PURE__ */ new Set());
|
|
16792
|
+
setQEditing(false);
|
|
16793
|
+
setQDraft("");
|
|
16794
|
+
setQDraftCursor(0);
|
|
16234
16795
|
}, [state.pendingQuestion]);
|
|
16235
16796
|
useEffect4(() => {
|
|
16236
16797
|
if (state.pendingModel) {
|
|
@@ -16307,6 +16868,12 @@ ${list}
|
|
|
16307
16868
|
case "/debug":
|
|
16308
16869
|
state.pushInfo(inspectDebug(state.sessionIdRef.current ?? ""));
|
|
16309
16870
|
return true;
|
|
16871
|
+
case "/archive": {
|
|
16872
|
+
const s = state.getArchivedSummary();
|
|
16873
|
+
state.pushInfo(s ? `\u{1F4DC} \u6700\u8FD1\u4E00\u6B21\u538B\u7F29\u7684\u5F52\u6863\u6458\u8981\uFF1A
|
|
16874
|
+
${s}` : "\u672C\u4F1A\u8BDD\u542F\u52A8\u4EE5\u6765\u5C1A\u672A\u53D1\u751F\u8FC7\u538B\u7F29\uFF08\u6458\u8981\u4EC5\u4FDD\u7559\u8FD0\u884C\u65F6\u6700\u8FD1\u4E00\u6B21\uFF09\u3002");
|
|
16875
|
+
return true;
|
|
16876
|
+
}
|
|
16310
16877
|
case "/plan": {
|
|
16311
16878
|
const on = !state.getPlanMode();
|
|
16312
16879
|
state.setPlanMode(on);
|
|
@@ -16448,6 +17015,13 @@ ${listText}`);
|
|
|
16448
17015
|
}
|
|
16449
17016
|
state.resolvePlan({ action: "accept", plan: planDraftRef.current });
|
|
16450
17017
|
};
|
|
17018
|
+
const confirmQuestionDraft = () => {
|
|
17019
|
+
const q = state.pendingQuestion?.req;
|
|
17020
|
+
const text = qDraftRef.current.trim();
|
|
17021
|
+
if (!q || !text) return;
|
|
17022
|
+
const sel = q.multiSelect ? [...qCheckedRef.current].sort((a, b) => a - b).map((i) => q.options[i]?.label).filter(Boolean) : [];
|
|
17023
|
+
state.resolveQuestion({ selected: sel, freeText: text });
|
|
17024
|
+
};
|
|
16451
17025
|
useInput2((ch, key) => {
|
|
16452
17026
|
if (key.ctrl && ch === "c") {
|
|
16453
17027
|
exit();
|
|
@@ -16463,18 +17037,34 @@ ${listText}`);
|
|
|
16463
17037
|
}
|
|
16464
17038
|
if (state.pendingQuestion) {
|
|
16465
17039
|
const q = state.pendingQuestion.req;
|
|
16466
|
-
const n = q.options.length;
|
|
17040
|
+
const n = q.options.length + 1;
|
|
16467
17041
|
const multi = !!q.multiSelect;
|
|
17042
|
+
if (qEditingRef.current) {
|
|
17043
|
+
if (key.escape || key.ctrl && ch === "g") {
|
|
17044
|
+
setQEditing(false);
|
|
17045
|
+
setQDraft("");
|
|
17046
|
+
setQDraftCursor(0);
|
|
17047
|
+
}
|
|
17048
|
+
return;
|
|
17049
|
+
}
|
|
16468
17050
|
if (key.upArrow) setQCursor((i) => (i - 1 + n) % n);
|
|
16469
17051
|
else if (key.downArrow) setQCursor((i) => (i + 1) % n);
|
|
16470
17052
|
else if (multi && ch === " ") {
|
|
16471
|
-
|
|
17053
|
+
if (qCursorRef.current >= q.options.length) {
|
|
17054
|
+
setQDraft("");
|
|
17055
|
+
setQDraftCursor(0);
|
|
17056
|
+
setQEditing(true);
|
|
17057
|
+
} else setQChecked((prev) => {
|
|
16472
17058
|
const nx = new Set(prev);
|
|
16473
17059
|
nx.has(qCursorRef.current) ? nx.delete(qCursorRef.current) : nx.add(qCursorRef.current);
|
|
16474
17060
|
return nx;
|
|
16475
17061
|
});
|
|
16476
17062
|
} else if (key.return) {
|
|
16477
|
-
if (
|
|
17063
|
+
if (qCursorRef.current >= q.options.length) {
|
|
17064
|
+
setQDraft("");
|
|
17065
|
+
setQDraftCursor(0);
|
|
17066
|
+
setQEditing(true);
|
|
17067
|
+
} else if (multi) {
|
|
16478
17068
|
const sel = qCheckedRef.current.size > 0 ? [...qCheckedRef.current].sort((a, b) => a - b).map((i) => q.options[i]?.label).filter(Boolean) : [q.options[qCursorRef.current]?.label].filter(Boolean);
|
|
16479
17069
|
state.resolveQuestion({ selected: sel });
|
|
16480
17070
|
} else {
|
|
@@ -16577,7 +17167,15 @@ ${listText}`);
|
|
|
16577
17167
|
/* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", width: cols, children: [
|
|
16578
17168
|
menuActive ? null : /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", paddingX: 1, children: [
|
|
16579
17169
|
dynamicRows.map((row) => /* @__PURE__ */ jsx18(RowView, { row, wrapW, streamTail, showThinking: state.showThinkingText }, row.id)),
|
|
16580
|
-
state.busy ? /* @__PURE__ */ jsx18(Box16, { marginTop: 0.5, children: /* @__PURE__ */
|
|
17170
|
+
state.busy ? /* @__PURE__ */ jsx18(Box16, { marginTop: 0.5, children: /* @__PURE__ */ jsxs16(Text18, { color: THEME.coralBright, children: [
|
|
17171
|
+
`${SPINNER_FRAMES[busyClock.frame]} ${S.thinkVerbs[Math.floor(busyClock.sec / 3) % S.thinkVerbs.length]}\u2026 (${busyClock.sec}s \xB7 ${S.escInterrupt})`,
|
|
17172
|
+
state.runningAgents > 0 ? /* @__PURE__ */ jsxs16(Text18, { color: "green", children: [
|
|
17173
|
+
" \xB7 \u25CF ",
|
|
17174
|
+
state.runningAgents,
|
|
17175
|
+
" agent",
|
|
17176
|
+
state.runningAgents > 1 ? "s" : ""
|
|
17177
|
+
] }) : null
|
|
17178
|
+
] }) }) : null
|
|
16581
17179
|
] }),
|
|
16582
17180
|
/* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", paddingX: 1, flexShrink: 0, children: [
|
|
16583
17181
|
state.pendingApproval ? /* @__PURE__ */ jsx18(ApprovalModal, { toolName: state.pendingApproval.toolName, detail: state.pendingApproval.detail, selectedIndex: selectIdx, wrapW }) : null,
|
|
@@ -16589,7 +17187,15 @@ ${listText}`);
|
|
|
16589
17187
|
multiSelect: !!state.pendingQuestion.req.multiSelect,
|
|
16590
17188
|
cursor: qCursor,
|
|
16591
17189
|
checked: qChecked,
|
|
16592
|
-
wrapW
|
|
17190
|
+
wrapW,
|
|
17191
|
+
editing: qEditing,
|
|
17192
|
+
draft: qDraft,
|
|
17193
|
+
draftCursor: qDraftCursor,
|
|
17194
|
+
onDraftChange: (v, c) => {
|
|
17195
|
+
setQDraft(v);
|
|
17196
|
+
setQDraftCursor(c);
|
|
17197
|
+
},
|
|
17198
|
+
onDraftSubmit: confirmQuestionDraft
|
|
16593
17199
|
}
|
|
16594
17200
|
) : null,
|
|
16595
17201
|
state.pendingPlan ? planEditing ? /* @__PURE__ */ jsx18(
|