jinzd-ai-cli 0.4.54 → 0.4.56
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/{chunk-6FYFVPVE.js → chunk-2DC5ABAM.js} +220 -67
- package/dist/{chunk-NP5KZVP6.js → chunk-7FOGK5TM.js} +1 -1
- package/dist/{chunk-TAR67QTH.js → chunk-FJSEFQ54.js} +1 -1
- package/dist/{chunk-FOFQAEU6.js → chunk-REWBXK2G.js} +1 -1
- package/dist/{hub-6V54V4O3.js → hub-HQ5QX7CV.js} +1 -1
- package/dist/index.js +112 -42
- package/dist/{run-tests-6G65OGSL.js → run-tests-FRHDE3VB.js} +1 -1
- package/dist/{run-tests-P53FNUJY.js → run-tests-GISOOQZC.js} +1 -1
- package/dist/{server-BQHIMEBH.js → server-MOTFJN6L.js} +128 -29
- package/dist/{task-orchestrator-TSY7CJE6.js → task-orchestrator-6RGRKSTU.js} +2 -2
- package/dist/web/client/app.js +63 -1
- package/package.json +1 -1
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
SessionManager,
|
|
8
8
|
SkillManager,
|
|
9
9
|
TOOL_CALL_REMINDER,
|
|
10
|
+
computeCost,
|
|
10
11
|
detectsHallucinatedFileOp,
|
|
12
|
+
formatCost,
|
|
11
13
|
formatGitContextForPrompt,
|
|
12
14
|
getContentText,
|
|
13
15
|
getGitContext,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
hadPreviousWriteToolCalls,
|
|
16
18
|
loadDevState,
|
|
17
19
|
setupProxy
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-2DC5ABAM.js";
|
|
19
21
|
import {
|
|
20
22
|
AuthManager
|
|
21
23
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -34,7 +36,7 @@ import {
|
|
|
34
36
|
spawnAgentContext,
|
|
35
37
|
truncateOutput,
|
|
36
38
|
undoStack
|
|
37
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-FJSEFQ54.js";
|
|
38
40
|
import "./chunk-4BKXL7SM.js";
|
|
39
41
|
import {
|
|
40
42
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -54,7 +56,7 @@ import {
|
|
|
54
56
|
SKILLS_DIR_NAME,
|
|
55
57
|
VERSION,
|
|
56
58
|
buildUserIdentityPrompt
|
|
57
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-7FOGK5TM.js";
|
|
58
60
|
|
|
59
61
|
// src/web/server.ts
|
|
60
62
|
import express from "express";
|
|
@@ -483,12 +485,24 @@ var SessionHandler = class _SessionHandler {
|
|
|
483
485
|
currentModel;
|
|
484
486
|
planMode = false;
|
|
485
487
|
runtimeThinking = null;
|
|
486
|
-
sessionTokenUsage = { inputTokens: 0, outputTokens: 0 };
|
|
488
|
+
sessionTokenUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
489
|
+
/** Accumulate a TokenUsage (with optional cache fields) into sessionTokenUsage. */
|
|
490
|
+
addWebSessionUsage(u) {
|
|
491
|
+
this.sessionTokenUsage.inputTokens += u.inputTokens;
|
|
492
|
+
this.sessionTokenUsage.outputTokens += u.outputTokens;
|
|
493
|
+
this.sessionTokenUsage.cacheCreationTokens += u.cacheCreationTokens ?? 0;
|
|
494
|
+
this.sessionTokenUsage.cacheReadTokens += u.cacheReadTokens ?? 0;
|
|
495
|
+
}
|
|
496
|
+
resetWebSessionUsage() {
|
|
497
|
+
this.sessionTokenUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
498
|
+
}
|
|
487
499
|
abortController = null;
|
|
488
500
|
userInterjection = null;
|
|
489
501
|
processing = false;
|
|
490
502
|
/** Pending ask_user promises */
|
|
491
503
|
pendingAskUser = /* @__PURE__ */ new Map();
|
|
504
|
+
/** Pending auto-pause promises */
|
|
505
|
+
pendingAutoPause = /* @__PURE__ */ new Map();
|
|
492
506
|
/** Active system prompt from context files */
|
|
493
507
|
activeSystemPrompt;
|
|
494
508
|
/** Directories added via /add-dir */
|
|
@@ -547,6 +561,7 @@ var SessionHandler = class _SessionHandler {
|
|
|
547
561
|
displayName: p.info.displayName,
|
|
548
562
|
models: p.info.models.map((m) => ({ id: m.id, name: m.displayName ?? m.id }))
|
|
549
563
|
}));
|
|
564
|
+
const costUsd = computeCost(this.currentProvider, this.currentModel, this.sessionTokenUsage);
|
|
550
565
|
this.send({
|
|
551
566
|
type: "status",
|
|
552
567
|
provider: this.currentProvider,
|
|
@@ -557,6 +572,7 @@ var SessionHandler = class _SessionHandler {
|
|
|
557
572
|
planMode: this.planMode,
|
|
558
573
|
thinkingMode: this.runtimeThinking ?? false,
|
|
559
574
|
tokenUsage: { ...this.sessionTokenUsage },
|
|
575
|
+
costUsd,
|
|
560
576
|
providers: providerList
|
|
561
577
|
});
|
|
562
578
|
}
|
|
@@ -588,6 +604,14 @@ var SessionHandler = class _SessionHandler {
|
|
|
588
604
|
}
|
|
589
605
|
return;
|
|
590
606
|
}
|
|
607
|
+
case "auto_pause_response": {
|
|
608
|
+
const resolve3 = this.pendingAutoPause.get(msg.requestId);
|
|
609
|
+
if (resolve3) {
|
|
610
|
+
this.pendingAutoPause.delete(msg.requestId);
|
|
611
|
+
resolve3({ action: msg.action, message: msg.message });
|
|
612
|
+
}
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
591
615
|
case "abort":
|
|
592
616
|
if (this.abortController) {
|
|
593
617
|
this.abortController.abort();
|
|
@@ -603,6 +627,8 @@ var SessionHandler = class _SessionHandler {
|
|
|
603
627
|
if (this.abortController) this.abortController.abort();
|
|
604
628
|
for (const resolve3 of this.pendingAskUser.values()) resolve3(null);
|
|
605
629
|
this.pendingAskUser.clear();
|
|
630
|
+
for (const resolve3 of this.pendingAutoPause.values()) resolve3({ action: "stop" });
|
|
631
|
+
this.pendingAutoPause.clear();
|
|
606
632
|
this.saveIfNeeded();
|
|
607
633
|
}
|
|
608
634
|
/** 根据当前模型 context window 更新工具输出截断上限 */
|
|
@@ -724,8 +750,7 @@ var SessionHandler = class _SessionHandler {
|
|
|
724
750
|
if (chunk.done) {
|
|
725
751
|
this.send({ type: "response_done", content: fullContent, usage: chunk.usage });
|
|
726
752
|
if (chunk.usage) {
|
|
727
|
-
this.
|
|
728
|
-
this.sessionTokenUsage.outputTokens += chunk.usage.outputTokens;
|
|
753
|
+
this.addWebSessionUsage(chunk.usage);
|
|
729
754
|
session.addTokenUsage(chunk.usage);
|
|
730
755
|
}
|
|
731
756
|
break;
|
|
@@ -749,19 +774,24 @@ var SessionHandler = class _SessionHandler {
|
|
|
749
774
|
const apiMessages = [...messages];
|
|
750
775
|
const extraMessages = [];
|
|
751
776
|
const maxToolRounds = this.config.get("maxToolRounds") ?? DEFAULT_MAX_TOOL_ROUNDS;
|
|
777
|
+
const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
|
|
778
|
+
const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : 50;
|
|
752
779
|
const baseSystemPrompt = (this.buildSystemPrompt() ?? "") + TOOL_CALL_REMINDER;
|
|
780
|
+
const pauseHint = autoPauseInterval > 0 ? `
|
|
781
|
+
- Every ${autoPauseInterval} rounds the user will be asked whether to continue \u2014 use this as a natural checkpoint to report progress.` : "";
|
|
753
782
|
const roundBudgetHint = `
|
|
754
783
|
|
|
755
784
|
[Tool Round Budget]
|
|
756
785
|
You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan efficiently:
|
|
757
786
|
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
758
787
|
- Prioritize the most critical tasks first in case rounds run out.
|
|
759
|
-
- When remaining rounds are low, focus on completing the current task and summarizing
|
|
788
|
+
- When remaining rounds are low, focus on completing the current task and summarizing.${pauseHint}`;
|
|
760
789
|
const systemPrompt = baseSystemPrompt + roundBudgetHint;
|
|
761
790
|
const modelParams = this.getModelParams();
|
|
762
|
-
const roundUsage = { inputTokens: 0, outputTokens: 0 };
|
|
791
|
+
const roundUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
763
792
|
const supportsStreamingTools = typeof provider.chatWithToolsStream === "function";
|
|
764
793
|
let consecutiveFreeRounds = 0;
|
|
794
|
+
const roundToolHistory = [];
|
|
765
795
|
const warnNoteAt = Math.max(10, Math.floor(maxToolRounds * 0.2));
|
|
766
796
|
const warnLowAt = Math.max(5, Math.floor(maxToolRounds * 0.1));
|
|
767
797
|
const warnCriticalAt = Math.max(3, Math.floor(maxToolRounds * 0.05));
|
|
@@ -829,6 +859,8 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
829
859
|
if (result.usage) {
|
|
830
860
|
roundUsage.inputTokens += result.usage.inputTokens;
|
|
831
861
|
roundUsage.outputTokens += result.usage.outputTokens;
|
|
862
|
+
roundUsage.cacheCreationTokens += result.usage.cacheCreationTokens ?? 0;
|
|
863
|
+
roundUsage.cacheReadTokens += result.usage.cacheReadTokens ?? 0;
|
|
832
864
|
}
|
|
833
865
|
if (result.content && !result.toolCalls) {
|
|
834
866
|
const hasWriteTools = toolDefs.some((t) => t.name === "write_file" || t.name === "edit_file");
|
|
@@ -843,12 +875,15 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
843
875
|
}
|
|
844
876
|
this.send({ type: "response_done", content: result.content, usage: roundUsage });
|
|
845
877
|
session.addMessage({ role: "assistant", content: result.content, timestamp: /* @__PURE__ */ new Date() });
|
|
846
|
-
this.
|
|
847
|
-
this.sessionTokenUsage.outputTokens += roundUsage.outputTokens;
|
|
878
|
+
this.addWebSessionUsage(roundUsage);
|
|
848
879
|
session.addTokenUsage(roundUsage);
|
|
849
880
|
return;
|
|
850
881
|
}
|
|
851
882
|
if (result.toolCalls && result.toolCalls.length > 0) {
|
|
883
|
+
roundToolHistory.push({
|
|
884
|
+
round: round + 1,
|
|
885
|
+
tools: result.toolCalls.map((tc) => tc.name)
|
|
886
|
+
});
|
|
852
887
|
googleSearchContext.configManager = this.config;
|
|
853
888
|
spawnAgentContext.provider = provider;
|
|
854
889
|
spawnAgentContext.model = this.currentModel;
|
|
@@ -876,6 +911,39 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
876
911
|
extraMessages.push({ role: "user", content: msg });
|
|
877
912
|
}
|
|
878
913
|
}
|
|
914
|
+
const effectiveRound = round + 1;
|
|
915
|
+
const remaining = maxToolRounds - effectiveRound;
|
|
916
|
+
if (autoPauseInterval > 0 && effectiveRound > 0 && effectiveRound % autoPauseInterval === 0 && remaining > 0 && !ac.signal.aborted) {
|
|
917
|
+
const recentHistory = roundToolHistory.slice(-autoPauseInterval);
|
|
918
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
919
|
+
for (const rh of recentHistory) {
|
|
920
|
+
for (const t of rh.tools) toolCounts.set(t, (toolCounts.get(t) || 0) + 1);
|
|
921
|
+
}
|
|
922
|
+
const toolSummary = [...toolCounts.entries()].sort((a, b) => b[1] - a[1]).map(([name, count]) => count > 1 ? `${name}\xD7${count}` : name).join(", ");
|
|
923
|
+
const requestId = `pause_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
924
|
+
const pauseResp = await new Promise((resolve3) => {
|
|
925
|
+
this.pendingAutoPause.set(requestId, resolve3);
|
|
926
|
+
this.send({
|
|
927
|
+
type: "auto_pause_request",
|
|
928
|
+
requestId,
|
|
929
|
+
currentRound: effectiveRound,
|
|
930
|
+
totalRounds: maxToolRounds,
|
|
931
|
+
toolSummary
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
if (ac.signal.aborted) break;
|
|
935
|
+
if (pauseResp.action === "stop") {
|
|
936
|
+
this.send({ type: "info", message: `\u23F8 Stopped by user at ${effectiveRound}/${maxToolRounds}` });
|
|
937
|
+
extraMessages.push({
|
|
938
|
+
role: "user",
|
|
939
|
+
content: `The user has stopped the task at round ${effectiveRound}/${maxToolRounds}. Do not call any more tools. Summarize what has been completed and what remains.`
|
|
940
|
+
});
|
|
941
|
+
break;
|
|
942
|
+
} else if (pauseResp.action === "redirect" && pauseResp.message) {
|
|
943
|
+
this.send({ type: "info", message: `\u26A1 Redirect: "${pauseResp.message}"` });
|
|
944
|
+
extraMessages.push({ role: "user", content: pauseResp.message });
|
|
945
|
+
}
|
|
946
|
+
}
|
|
879
947
|
}
|
|
880
948
|
try {
|
|
881
949
|
const summaryExtra = [
|
|
@@ -917,8 +985,7 @@ ${summaryResult.content}`,
|
|
|
917
985
|
message: `Reached maximum tool call rounds (${maxToolRounds}). You can continue by asking the AI to proceed.`
|
|
918
986
|
});
|
|
919
987
|
}
|
|
920
|
-
this.
|
|
921
|
-
this.sessionTokenUsage.outputTokens += roundUsage.outputTokens;
|
|
988
|
+
this.addWebSessionUsage(roundUsage);
|
|
922
989
|
session.addTokenUsage(roundUsage);
|
|
923
990
|
} catch (err) {
|
|
924
991
|
if (err.name === "AbortError") {
|
|
@@ -1034,7 +1101,7 @@ ${summaryResult.content}`,
|
|
|
1034
1101
|
case "clear":
|
|
1035
1102
|
this.saveIfNeeded();
|
|
1036
1103
|
this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
1037
|
-
this.
|
|
1104
|
+
this.resetWebSessionUsage();
|
|
1038
1105
|
this.send({ type: "info", message: "Conversation cleared." });
|
|
1039
1106
|
this.sendStatus();
|
|
1040
1107
|
this.sendSessionList();
|
|
@@ -1068,12 +1135,19 @@ ${summaryResult.content}`,
|
|
|
1068
1135
|
}
|
|
1069
1136
|
case "status": {
|
|
1070
1137
|
const session = this.sessions.current;
|
|
1138
|
+
const cacheRead = this.sessionTokenUsage.cacheReadTokens;
|
|
1139
|
+
const cacheCreate = this.sessionTokenUsage.cacheCreationTokens;
|
|
1140
|
+
const cost = computeCost(this.currentProvider, this.currentModel, this.sessionTokenUsage);
|
|
1141
|
+
const cacheLine = cacheRead > 0 || cacheCreate > 0 ? `
|
|
1142
|
+
Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
1143
|
+
const costLine = cost != null ? `
|
|
1144
|
+
Cost: ${formatCost(cost)}` : "";
|
|
1071
1145
|
this.send({
|
|
1072
1146
|
type: "info",
|
|
1073
1147
|
message: `Provider: ${this.currentProvider}
|
|
1074
1148
|
Model: ${this.currentModel}
|
|
1075
1149
|
Session: ${session?.id ?? "none"} (${session?.messages.length ?? 0} messages)
|
|
1076
|
-
Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.outputTokens}`
|
|
1150
|
+
Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.outputTokens}${cacheLine}${costLine}`
|
|
1077
1151
|
});
|
|
1078
1152
|
break;
|
|
1079
1153
|
}
|
|
@@ -1083,7 +1157,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1083
1157
|
this.saveIfNeeded();
|
|
1084
1158
|
const created = this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
1085
1159
|
this.unsavedSessions.set(created.id, created);
|
|
1086
|
-
this.
|
|
1160
|
+
this.resetWebSessionUsage();
|
|
1087
1161
|
this.send({ type: "info", message: "New session created." });
|
|
1088
1162
|
this.sendStatus();
|
|
1089
1163
|
this.sendSessionList();
|
|
@@ -1094,7 +1168,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1094
1168
|
const cached = cachedExact ?? [...this.unsavedSessions.values()].find((s) => s.id.startsWith(targetId));
|
|
1095
1169
|
if (cached) {
|
|
1096
1170
|
this.sessions.setCurrent(cached);
|
|
1097
|
-
this.
|
|
1171
|
+
this.resetWebSessionUsage();
|
|
1098
1172
|
this.send({
|
|
1099
1173
|
type: "info",
|
|
1100
1174
|
message: `Loaded session: ${cached.id.slice(0, 8)} "${cached.title ?? ""}" (${cached.messages.length} messages)`
|
|
@@ -1108,7 +1182,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1108
1182
|
const found = list.find((s) => s.id.startsWith(targetId));
|
|
1109
1183
|
if (found) {
|
|
1110
1184
|
this.sessions.loadSession(found.id);
|
|
1111
|
-
this.
|
|
1185
|
+
this.resetWebSessionUsage();
|
|
1112
1186
|
this.send({ type: "info", message: `Loaded session: ${found.id.slice(0, 8)} "${found.title ?? ""}" (${found.messageCount} messages)` });
|
|
1113
1187
|
this.sendSessionMessages();
|
|
1114
1188
|
this.sendStatus();
|
|
@@ -1116,7 +1190,7 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1116
1190
|
} else {
|
|
1117
1191
|
const recreated = this.sessions.createSession(this.currentProvider, this.currentModel);
|
|
1118
1192
|
this.unsavedSessions.set(recreated.id, recreated);
|
|
1119
|
-
this.
|
|
1193
|
+
this.resetWebSessionUsage();
|
|
1120
1194
|
this.send({
|
|
1121
1195
|
type: "info",
|
|
1122
1196
|
message: `Previous session (${targetId.slice(0, 8)}) is no longer available \u2014 started a new one.`
|
|
@@ -1256,16 +1330,41 @@ Tokens: in=${this.sessionTokenUsage.inputTokens} out=${this.sessionTokenUsage.ou
|
|
|
1256
1330
|
});
|
|
1257
1331
|
break;
|
|
1258
1332
|
case "cost": {
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1333
|
+
const u = this.sessionTokenUsage;
|
|
1334
|
+
const total = u.inputTokens + u.outputTokens + u.cacheCreationTokens + u.cacheReadTokens;
|
|
1335
|
+
const cost = computeCost(this.currentProvider, this.currentModel, u);
|
|
1336
|
+
let savings = null;
|
|
1337
|
+
if (cost != null && u.cacheReadTokens > 0) {
|
|
1338
|
+
const withoutCache = computeCost(this.currentProvider, this.currentModel, {
|
|
1339
|
+
inputTokens: u.inputTokens + u.cacheReadTokens,
|
|
1340
|
+
outputTokens: u.outputTokens,
|
|
1341
|
+
cacheCreationTokens: u.cacheCreationTokens,
|
|
1342
|
+
cacheReadTokens: 0
|
|
1343
|
+
});
|
|
1344
|
+
if (withoutCache != null) savings = withoutCache - cost;
|
|
1345
|
+
}
|
|
1346
|
+
const lines = [
|
|
1347
|
+
"\u{1F4B0} Session Cost & Token Usage",
|
|
1348
|
+
` Provider : ${this.currentProvider}`,
|
|
1349
|
+
` Model : ${this.currentModel}`,
|
|
1350
|
+
` Input (uncached): ${u.inputTokens.toLocaleString()}`,
|
|
1351
|
+
` Output : ${u.outputTokens.toLocaleString()}`
|
|
1352
|
+
];
|
|
1353
|
+
if (u.cacheCreationTokens > 0) lines.push(` Cache write : ${u.cacheCreationTokens.toLocaleString()}`);
|
|
1354
|
+
if (u.cacheReadTokens > 0) {
|
|
1355
|
+
const pct = Math.round(u.cacheReadTokens / (u.cacheReadTokens + u.inputTokens) * 100);
|
|
1356
|
+
lines.push(` Cache read : ${u.cacheReadTokens.toLocaleString()} (${pct}% hit rate)`);
|
|
1357
|
+
}
|
|
1358
|
+
lines.push(` Total tokens : ${total.toLocaleString()}`);
|
|
1359
|
+
if (cost != null) {
|
|
1360
|
+
lines.push(` Cost : ${formatCost(cost)}`);
|
|
1361
|
+
if (savings != null && savings > 0) {
|
|
1362
|
+
lines.push(` Cache savings : -${formatCost(savings)} (vs no cache)`);
|
|
1363
|
+
}
|
|
1364
|
+
} else {
|
|
1365
|
+
lines.push(` Cost : \u2014 (pricing unknown for this model)`);
|
|
1366
|
+
}
|
|
1367
|
+
this.send({ type: "info", message: lines.join("\n") });
|
|
1269
1368
|
break;
|
|
1270
1369
|
}
|
|
1271
1370
|
case "tools":
|
|
@@ -1691,7 +1790,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1691
1790
|
case "test": {
|
|
1692
1791
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1693
1792
|
try {
|
|
1694
|
-
const { executeTests } = await import("./run-tests-
|
|
1793
|
+
const { executeTests } = await import("./run-tests-GISOOQZC.js");
|
|
1695
1794
|
const argStr = args.join(" ").trim();
|
|
1696
1795
|
let testArgs = {};
|
|
1697
1796
|
if (argStr) {
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
getDangerLevel,
|
|
5
5
|
googleSearchContext,
|
|
6
6
|
truncateOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FJSEFQ54.js";
|
|
8
8
|
import "./chunk-4BKXL7SM.js";
|
|
9
9
|
import {
|
|
10
10
|
SUBAGENT_ALLOWED_TOOLS
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7FOGK5TM.js";
|
|
12
12
|
|
|
13
13
|
// src/hub/task-orchestrator.ts
|
|
14
14
|
import { createInterface } from "readline";
|
package/dist/web/client/app.js
CHANGED
|
@@ -176,6 +176,7 @@ function handleServerMessage(msg) {
|
|
|
176
176
|
case 'confirm_request': handleConfirmRequest(msg); break;
|
|
177
177
|
case 'batch_confirm_request': handleBatchConfirmRequest(msg); break;
|
|
178
178
|
case 'ask_user_request':handleAskUserRequest(msg); break;
|
|
179
|
+
case 'auto_pause_request': handleAutoPauseRequest(msg); break;
|
|
179
180
|
case 'thinking_start': handleThinkingStart(); break;
|
|
180
181
|
case 'thinking_delta': handleThinkingDelta(msg.delta); break;
|
|
181
182
|
case 'thinking_end': handleThinkingEnd(); break;
|
|
@@ -377,6 +378,34 @@ function handleAskUserRequest(msg) {
|
|
|
377
378
|
setTimeout(() => document.getElementById(`ask-input-${msg.requestId}`)?.focus(), 100);
|
|
378
379
|
}
|
|
379
380
|
|
|
381
|
+
function handleAutoPauseRequest(msg) {
|
|
382
|
+
const el = document.createElement('div');
|
|
383
|
+
el.className = 'confirm-card tool-border-write my-1';
|
|
384
|
+
el.id = `pause-card-${msg.requestId}`;
|
|
385
|
+
const summary = msg.toolSummary ? escapeHtml(msg.toolSummary) : '(none)';
|
|
386
|
+
el.innerHTML = `
|
|
387
|
+
<div class="flex items-center gap-2 mb-2">
|
|
388
|
+
<span class="badge badge-warning badge-sm">⏸ Auto-pause</span>
|
|
389
|
+
<span class="text-xs opacity-70">Round ${msg.currentRound}/${msg.totalRounds} · ${msg.totalRounds - msg.currentRound} remaining</span>
|
|
390
|
+
</div>
|
|
391
|
+
<div class="text-xs opacity-70 mb-2">Recent tools: ${summary}</div>
|
|
392
|
+
<div class="flex gap-2 w-full mb-2">
|
|
393
|
+
<input type="text" id="pause-input-${msg.requestId}"
|
|
394
|
+
class="input input-sm input-bordered flex-1"
|
|
395
|
+
placeholder="Optional: redirect AI with a new instruction..."
|
|
396
|
+
onkeydown="if(event.key==='Enter')respondAutoPause('${msg.requestId}','redirect')">
|
|
397
|
+
</div>
|
|
398
|
+
<div class="flex gap-2">
|
|
399
|
+
<button class="btn btn-success btn-sm flex-1" onclick="respondAutoPause('${msg.requestId}','continue')">▶ Continue</button>
|
|
400
|
+
<button class="btn btn-primary btn-sm flex-1" onclick="respondAutoPause('${msg.requestId}','redirect')">↪ Redirect</button>
|
|
401
|
+
<button class="btn btn-error btn-sm flex-1" onclick="respondAutoPause('${msg.requestId}','stop')">⏹ Stop</button>
|
|
402
|
+
</div>
|
|
403
|
+
`;
|
|
404
|
+
messagesEl.appendChild(el);
|
|
405
|
+
scrollToBottom();
|
|
406
|
+
setTimeout(() => document.getElementById(`pause-input-${msg.requestId}`)?.focus(), 100);
|
|
407
|
+
}
|
|
408
|
+
|
|
380
409
|
function handleRoundProgress(msg) {
|
|
381
410
|
const progressBar = document.getElementById('round-progress');
|
|
382
411
|
const progressBarEl = document.getElementById('round-progress-bar');
|
|
@@ -496,7 +525,16 @@ function handleStatus(msg) {
|
|
|
496
525
|
btnPlan.classList.toggle('btn-active-toggle', msg.planMode);
|
|
497
526
|
statusSession.textContent = `📋 ${msg.sessionId?.slice(0, 8) || '—'} (${msg.messageCount} msgs)`;
|
|
498
527
|
if (msg.tokenUsage) {
|
|
499
|
-
|
|
528
|
+
const u = msg.tokenUsage;
|
|
529
|
+
const cacheRead = u.cacheReadTokens || 0;
|
|
530
|
+
let line = `📊 in: ${u.inputTokens.toLocaleString()} out: ${u.outputTokens.toLocaleString()}`;
|
|
531
|
+
if (cacheRead > 0) line += ` cache: ${cacheRead.toLocaleString()}`;
|
|
532
|
+
if (msg.costUsd != null) {
|
|
533
|
+
const cost = msg.costUsd;
|
|
534
|
+
const costStr = cost === 0 ? '$0' : cost < 0.01 ? `$${cost.toFixed(4)}` : cost < 1 ? `$${cost.toFixed(3)}` : `$${cost.toFixed(2)}`;
|
|
535
|
+
line += ` 💰 ${costStr}`;
|
|
536
|
+
}
|
|
537
|
+
statusTokens.textContent = line;
|
|
500
538
|
}
|
|
501
539
|
sessionListEl.querySelectorAll('.session-item').forEach(el => {
|
|
502
540
|
el.classList.toggle('active', el.dataset.sessionId === msg.sessionId);
|
|
@@ -559,6 +597,30 @@ window.respondAskUser = function(requestId) {
|
|
|
559
597
|
}
|
|
560
598
|
};
|
|
561
599
|
|
|
600
|
+
window.respondAutoPause = function(requestId, action) {
|
|
601
|
+
const card = document.getElementById(`pause-card-${requestId}`);
|
|
602
|
+
const input = document.getElementById(`pause-input-${requestId}`);
|
|
603
|
+
const typed = input ? input.value.trim() : '';
|
|
604
|
+
|
|
605
|
+
// 若用户在输入框敲回车,action 是 'redirect';若内容为空则视作 continue
|
|
606
|
+
let effective = action;
|
|
607
|
+
let message;
|
|
608
|
+
if (action === 'redirect') {
|
|
609
|
+
if (!typed) { effective = 'continue'; }
|
|
610
|
+
else { message = typed; }
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
send({ type: 'auto_pause_response', requestId, action: effective, message });
|
|
614
|
+
|
|
615
|
+
if (card) {
|
|
616
|
+
card.className = 'confirm-card tool-border-safe my-1 opacity-60';
|
|
617
|
+
const label = effective === 'continue' ? '▶ Continued'
|
|
618
|
+
: effective === 'stop' ? '⏹ Stopped'
|
|
619
|
+
: `↪ Redirected: ${escapeHtml(message || '')}`;
|
|
620
|
+
card.innerHTML = `<span class="text-sm">${label}</span>`;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
|
|
562
624
|
// DaisyUI light themes → highlight.js light stylesheet; others → dark
|
|
563
625
|
const LIGHT_DAISYUI_THEMES = new Set(['light', 'cupcake', 'bumblebee', 'emerald', 'corporate', 'garden', 'lofi', 'pastel', 'fantasy', 'wireframe', 'cmyk', 'autumn', 'acid', 'lemonade', 'winter', 'nord']);
|
|
564
626
|
const HLJS_CDN = 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles';
|