jinzd-ai-cli 0.4.55 → 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-JL5NK6AR.js → chunk-2DC5ABAM.js} +6 -2
- package/dist/{chunk-W7QVBFIJ.js → chunk-7FOGK5TM.js} +1 -1
- package/dist/{chunk-YQEIQJ6K.js → chunk-FJSEFQ54.js} +1 -1
- package/dist/{chunk-DJ342VFS.js → chunk-REWBXK2G.js} +1 -1
- package/dist/{hub-AUWP4SWJ.js → hub-HQ5QX7CV.js} +1 -1
- package/dist/index.js +15 -13
- package/dist/{run-tests-I6UDHVIS.js → run-tests-FRHDE3VB.js} +1 -1
- package/dist/{run-tests-X4PCLXA2.js → run-tests-GISOOQZC.js} +1 -1
- package/dist/{server-YPAZWGUE.js → server-MOTFJN6L.js} +59 -5
- package/dist/{task-orchestrator-MWO6A4KQ.js → task-orchestrator-6RGRKSTU.js} +2 -2
- package/dist/web/client/app.js +53 -0
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
ProviderNotFoundError,
|
|
8
8
|
RateLimitError,
|
|
9
9
|
schemaToJsonSchema
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FJSEFQ54.js";
|
|
11
11
|
import {
|
|
12
12
|
APP_NAME,
|
|
13
13
|
CONFIG_DIR_NAME,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
MCP_TOOL_PREFIX,
|
|
21
21
|
PLUGINS_DIR_NAME,
|
|
22
22
|
VERSION
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-7FOGK5TM.js";
|
|
24
24
|
|
|
25
25
|
// src/config/config-manager.ts
|
|
26
26
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
@@ -172,6 +172,10 @@ var ConfigSchema = z.object({
|
|
|
172
172
|
// 建议范围:25(保守)~ 1000(宽松,接近 Claude Code)。
|
|
173
173
|
// CLI `--max-tool-rounds <n>` 可覆盖此值。
|
|
174
174
|
maxToolRounds: z.number().int().min(1).max(1e4).default(200),
|
|
175
|
+
// Auto-pause checkpoint:Agentic 循环每隔多少轮暂停一次,让用户确认方向或中途介入。
|
|
176
|
+
// 默认 50;设为 0 禁用(完全自动执行到完成或 maxToolRounds 用尽)。
|
|
177
|
+
// CLI 与 Web UI 行为一致:CLI 用 readline question 提示,Web UI 弹出对话框。
|
|
178
|
+
autoPauseInterval: z.number().int().min(0).max(1e4).default(50),
|
|
175
179
|
// 单次工具输出(如 read_file、bash、grep_files)返回给 AI 的最大字符数上限。
|
|
176
180
|
// 默认 500_000 (~500K chars ≈ 6000-8000 行代码)。
|
|
177
181
|
// 实际上限还会受模型 contextWindow 动态约束(取 contextWindow/4 作为下限)。
|
|
@@ -385,7 +385,7 @@ ${content}`);
|
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
388
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
388
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-6RGRKSTU.js");
|
|
389
389
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
390
390
|
let interrupted = false;
|
|
391
391
|
const onSigint = () => {
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
saveDevState,
|
|
28
28
|
sessionHasMeaningfulContent,
|
|
29
29
|
setupProxy
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2DC5ABAM.js";
|
|
31
31
|
import {
|
|
32
32
|
ToolExecutor,
|
|
33
33
|
ToolRegistry,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
spawnAgentContext,
|
|
42
42
|
theme,
|
|
43
43
|
undoStack
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-FJSEFQ54.js";
|
|
45
45
|
import {
|
|
46
46
|
fileCheckpoints
|
|
47
47
|
} from "./chunk-4BKXL7SM.js";
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
SKILLS_DIR_NAME,
|
|
67
67
|
VERSION,
|
|
68
68
|
buildUserIdentityPrompt
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-7FOGK5TM.js";
|
|
70
70
|
|
|
71
71
|
// src/index.ts
|
|
72
72
|
import { program } from "commander";
|
|
@@ -2161,7 +2161,7 @@ ${hint}` : "")
|
|
|
2161
2161
|
usage: "/test [command|filter]",
|
|
2162
2162
|
async execute(args, ctx) {
|
|
2163
2163
|
try {
|
|
2164
|
-
const { executeTests } = await import("./run-tests-
|
|
2164
|
+
const { executeTests } = await import("./run-tests-GISOOQZC.js");
|
|
2165
2165
|
const argStr = args.join(" ").trim();
|
|
2166
2166
|
let testArgs = {};
|
|
2167
2167
|
if (argStr) {
|
|
@@ -3337,7 +3337,7 @@ ${content}
|
|
|
3337
3337
|
var FREE_ROUND_TOOLS = /* @__PURE__ */ new Set(["write_todos"]);
|
|
3338
3338
|
var MAX_CONSECUTIVE_FREE_ROUNDS = 3;
|
|
3339
3339
|
var MAX_REPEATED_TOOL_CALLS = 2;
|
|
3340
|
-
var
|
|
3340
|
+
var DEFAULT_AUTO_PAUSE_INTERVAL = 50;
|
|
3341
3341
|
function fmtTokens(n) {
|
|
3342
3342
|
if (n >= 1e6) return `${Math.round(n / 1e5) / 10}M`;
|
|
3343
3343
|
if (n >= 1e3) return `${Math.round(n / 1024)}K`;
|
|
@@ -4833,7 +4833,11 @@ Session '${this.resumeSessionId}' not found.
|
|
|
4833
4833
|
const apiMessages = [...messages];
|
|
4834
4834
|
const extraMessages = [];
|
|
4835
4835
|
const maxToolRounds = this.maxToolRoundsOverride ?? this.config.get("maxToolRounds") ?? DEFAULT_MAX_TOOL_ROUNDS;
|
|
4836
|
+
const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
|
|
4837
|
+
const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : DEFAULT_AUTO_PAUSE_INTERVAL;
|
|
4836
4838
|
const baseSystemPrompt = (this.buildCurrentSystemPrompt() ?? "") + TOOL_CALL_REMINDER;
|
|
4839
|
+
const pauseHint = autoPauseInterval > 0 ? `
|
|
4840
|
+
- Every ${autoPauseInterval} rounds the user will be asked whether to continue \u2014 use this as a natural checkpoint to report progress.` : "";
|
|
4837
4841
|
const roundBudgetHint = this.planMode ? `
|
|
4838
4842
|
|
|
4839
4843
|
[Tool Round Budget \u2014 Plan Mode]
|
|
@@ -4843,16 +4847,14 @@ You have a maximum of ${maxToolRounds} tool call rounds. You are in READ-ONLY Pl
|
|
|
4843
4847
|
- Do NOT write shell commands or code blocks as a substitute for tool calls
|
|
4844
4848
|
- Do NOT read the same file more than once
|
|
4845
4849
|
- Call write_todos ONCE to present your plan, then give a text summary
|
|
4846
|
-
- If the user asks you to execute anything, respond: "Please type /plan execute to switch to execute mode."
|
|
4847
|
-
- Every ${AUTO_PAUSE_INTERVAL} rounds the user will be asked whether to continue.` : `
|
|
4850
|
+
- If the user asks you to execute anything, respond: "Please type /plan execute to switch to execute mode."${pauseHint}` : `
|
|
4848
4851
|
|
|
4849
4852
|
[Tool Round Budget]
|
|
4850
4853
|
You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan efficiently:
|
|
4851
4854
|
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
4852
4855
|
- Do NOT read the same file more than once \u2014 use the content from previous reads.
|
|
4853
4856
|
- Prioritize the most critical tasks first in case rounds run out.
|
|
4854
|
-
- When remaining rounds are low, focus on completing the current task and summarizing
|
|
4855
|
-
- Every ${AUTO_PAUSE_INTERVAL} rounds the user will be asked whether to continue \u2014 use this as a natural checkpoint to report progress.`;
|
|
4857
|
+
- When remaining rounds are low, focus on completing the current task and summarizing.${pauseHint}`;
|
|
4856
4858
|
const systemPrompt = baseSystemPrompt + roundBudgetHint;
|
|
4857
4859
|
const modelParams = this.getModelParams();
|
|
4858
4860
|
const useStreaming = this.config.get("ui").streaming;
|
|
@@ -5178,12 +5180,12 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
5178
5180
|
}
|
|
5179
5181
|
const effectiveRound = round + 1;
|
|
5180
5182
|
const remaining = maxToolRounds - effectiveRound;
|
|
5181
|
-
if (
|
|
5183
|
+
if (autoPauseInterval > 0 && effectiveRound > 0 && effectiveRound % autoPauseInterval === 0 && remaining > 0) {
|
|
5182
5184
|
spinner.stop();
|
|
5183
5185
|
process.stdout.write("\n");
|
|
5184
5186
|
process.stdout.write(theme.warning(`\u23F8 Auto-pause: ${effectiveRound}/${maxToolRounds} rounds used, ${remaining} remaining
|
|
5185
5187
|
`));
|
|
5186
|
-
const recentHistory = roundToolHistory.slice(-
|
|
5188
|
+
const recentHistory = roundToolHistory.slice(-autoPauseInterval);
|
|
5187
5189
|
if (recentHistory.length > 0) {
|
|
5188
5190
|
const toolCounts = /* @__PURE__ */ new Map();
|
|
5189
5191
|
for (const rh of recentHistory) {
|
|
@@ -5561,7 +5563,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
5561
5563
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
5562
5564
|
process.exit(1);
|
|
5563
5565
|
}
|
|
5564
|
-
const { startWebServer } = await import("./server-
|
|
5566
|
+
const { startWebServer } = await import("./server-MOTFJN6L.js");
|
|
5565
5567
|
await startWebServer({ port, host: options.host });
|
|
5566
5568
|
});
|
|
5567
5569
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -5794,7 +5796,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
5794
5796
|
}),
|
|
5795
5797
|
config.get("customProviders")
|
|
5796
5798
|
);
|
|
5797
|
-
const { startHub } = await import("./hub-
|
|
5799
|
+
const { startHub } = await import("./hub-HQ5QX7CV.js");
|
|
5798
5800
|
await startHub(
|
|
5799
5801
|
{
|
|
5800
5802
|
topic: topic ?? "",
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
hadPreviousWriteToolCalls,
|
|
18
18
|
loadDevState,
|
|
19
19
|
setupProxy
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-2DC5ABAM.js";
|
|
21
21
|
import {
|
|
22
22
|
AuthManager
|
|
23
23
|
} from "./chunk-BYNY5JPB.js";
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
spawnAgentContext,
|
|
37
37
|
truncateOutput,
|
|
38
38
|
undoStack
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-FJSEFQ54.js";
|
|
40
40
|
import "./chunk-4BKXL7SM.js";
|
|
41
41
|
import {
|
|
42
42
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
SKILLS_DIR_NAME,
|
|
57
57
|
VERSION,
|
|
58
58
|
buildUserIdentityPrompt
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-7FOGK5TM.js";
|
|
60
60
|
|
|
61
61
|
// src/web/server.ts
|
|
62
62
|
import express from "express";
|
|
@@ -501,6 +501,8 @@ var SessionHandler = class _SessionHandler {
|
|
|
501
501
|
processing = false;
|
|
502
502
|
/** Pending ask_user promises */
|
|
503
503
|
pendingAskUser = /* @__PURE__ */ new Map();
|
|
504
|
+
/** Pending auto-pause promises */
|
|
505
|
+
pendingAutoPause = /* @__PURE__ */ new Map();
|
|
504
506
|
/** Active system prompt from context files */
|
|
505
507
|
activeSystemPrompt;
|
|
506
508
|
/** Directories added via /add-dir */
|
|
@@ -602,6 +604,14 @@ var SessionHandler = class _SessionHandler {
|
|
|
602
604
|
}
|
|
603
605
|
return;
|
|
604
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
|
+
}
|
|
605
615
|
case "abort":
|
|
606
616
|
if (this.abortController) {
|
|
607
617
|
this.abortController.abort();
|
|
@@ -617,6 +627,8 @@ var SessionHandler = class _SessionHandler {
|
|
|
617
627
|
if (this.abortController) this.abortController.abort();
|
|
618
628
|
for (const resolve3 of this.pendingAskUser.values()) resolve3(null);
|
|
619
629
|
this.pendingAskUser.clear();
|
|
630
|
+
for (const resolve3 of this.pendingAutoPause.values()) resolve3({ action: "stop" });
|
|
631
|
+
this.pendingAutoPause.clear();
|
|
620
632
|
this.saveIfNeeded();
|
|
621
633
|
}
|
|
622
634
|
/** 根据当前模型 context window 更新工具输出截断上限 */
|
|
@@ -762,19 +774,24 @@ var SessionHandler = class _SessionHandler {
|
|
|
762
774
|
const apiMessages = [...messages];
|
|
763
775
|
const extraMessages = [];
|
|
764
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;
|
|
765
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.` : "";
|
|
766
782
|
const roundBudgetHint = `
|
|
767
783
|
|
|
768
784
|
[Tool Round Budget]
|
|
769
785
|
You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan efficiently:
|
|
770
786
|
- Prefer batch operations (e.g. global find-and-replace) over repetitive single edits.
|
|
771
787
|
- Prioritize the most critical tasks first in case rounds run out.
|
|
772
|
-
- 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}`;
|
|
773
789
|
const systemPrompt = baseSystemPrompt + roundBudgetHint;
|
|
774
790
|
const modelParams = this.getModelParams();
|
|
775
791
|
const roundUsage = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };
|
|
776
792
|
const supportsStreamingTools = typeof provider.chatWithToolsStream === "function";
|
|
777
793
|
let consecutiveFreeRounds = 0;
|
|
794
|
+
const roundToolHistory = [];
|
|
778
795
|
const warnNoteAt = Math.max(10, Math.floor(maxToolRounds * 0.2));
|
|
779
796
|
const warnLowAt = Math.max(5, Math.floor(maxToolRounds * 0.1));
|
|
780
797
|
const warnCriticalAt = Math.max(3, Math.floor(maxToolRounds * 0.05));
|
|
@@ -863,6 +880,10 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
863
880
|
return;
|
|
864
881
|
}
|
|
865
882
|
if (result.toolCalls && result.toolCalls.length > 0) {
|
|
883
|
+
roundToolHistory.push({
|
|
884
|
+
round: round + 1,
|
|
885
|
+
tools: result.toolCalls.map((tc) => tc.name)
|
|
886
|
+
});
|
|
866
887
|
googleSearchContext.configManager = this.config;
|
|
867
888
|
spawnAgentContext.provider = provider;
|
|
868
889
|
spawnAgentContext.model = this.currentModel;
|
|
@@ -890,6 +911,39 @@ You have a maximum of ${maxToolRounds} tool call rounds for this task. Plan effi
|
|
|
890
911
|
extraMessages.push({ role: "user", content: msg });
|
|
891
912
|
}
|
|
892
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
|
+
}
|
|
893
947
|
}
|
|
894
948
|
try {
|
|
895
949
|
const summaryExtra = [
|
|
@@ -1736,7 +1790,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
1736
1790
|
case "test": {
|
|
1737
1791
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
1738
1792
|
try {
|
|
1739
|
-
const { executeTests } = await import("./run-tests-
|
|
1793
|
+
const { executeTests } = await import("./run-tests-GISOOQZC.js");
|
|
1740
1794
|
const argStr = args.join(" ").trim();
|
|
1741
1795
|
let testArgs = {};
|
|
1742
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');
|
|
@@ -568,6 +597,30 @@ window.respondAskUser = function(requestId) {
|
|
|
568
597
|
}
|
|
569
598
|
};
|
|
570
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
|
+
|
|
571
624
|
// DaisyUI light themes → highlight.js light stylesheet; others → dark
|
|
572
625
|
const LIGHT_DAISYUI_THEMES = new Set(['light', 'cupcake', 'bumblebee', 'emerald', 'corporate', 'garden', 'lofi', 'pastel', 'fantasy', 'wireframe', 'cmyk', 'autumn', 'acid', 'lemonade', 'winter', 'nord']);
|
|
573
626
|
const HLJS_CDN = 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles';
|