nolo-cli 0.37.0-alpha.3 → 0.38.0-alpha.1
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/{agentEmailCommands-C6G4F4JL.js → agentEmailCommands-NGL5B3UC.js} +2 -2
- package/{agentMachineCommands-JGA4C6ZZ.js → agentMachineCommands-AXOO4OKN.js} +1 -1
- package/{agentRecordCommands-ZHH7KRWS.js → agentRecordCommands-GJHH5GYI.js} +2 -2
- package/{agentRunCommand-5LLSNUAJ.js → agentRunCommand-4MEMHFT5.js} +2 -2
- package/{chunk-PEEWLG6V.js → chunk-45NBTCS2.js} +7 -3
- package/{chunk-55U32YAP.js → chunk-GEGSCLZZ.js} +1 -1
- package/{chunk-5OXHHCUI.js → chunk-LZZQTQPY.js} +1 -1
- package/{chunk-QKCJPJNO.js → chunk-TH7ZZKPJ.js} +21 -4
- package/index.js +15 -15
- package/{machineCommands-FSLAJSUC.js → machineCommands-NAFWPMLI.js} +2 -2
- package/{machineWsRunDispatch-PHYQYE4Q.js → machineWsRunDispatch-EWA7J37I.js} +2 -2
- package/package.json +1 -1
- package/{readlineWorkspace-WOKEACUU.js → readlineWorkspace-BCQVDX4V.js} +415 -322
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
} from "./chunk-W445DPVT.js";
|
|
5
5
|
import {
|
|
6
6
|
runAgentCreateCommand
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LZZQTQPY.js";
|
|
8
8
|
import {
|
|
9
9
|
positionalArgs,
|
|
10
10
|
readFlagValue
|
|
11
11
|
} from "./chunk-4AWH4LQA.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-TH7ZZKPJ.js";
|
|
13
13
|
import "./chunk-IZNJDUJ4.js";
|
|
14
14
|
import "./chunk-6XG52ZQ6.js";
|
|
15
15
|
import {
|
|
@@ -84,7 +84,7 @@ async function defaultExecuteCli(provider, prompt, options) {
|
|
|
84
84
|
return executeCli(provider, prompt, options);
|
|
85
85
|
}
|
|
86
86
|
async function forwardConnectorRunMessage(machine, message, pushMessage, executeCli, env, fetchImpl) {
|
|
87
|
-
const { handleConnectorRunMessage } = await import("./machineWsRunDispatch-
|
|
87
|
+
const { handleConnectorRunMessage } = await import("./machineWsRunDispatch-EWA7J37I.js");
|
|
88
88
|
return handleConnectorRunMessage(message, pushMessage, executeCli, env, fetchImpl);
|
|
89
89
|
}
|
|
90
90
|
async function detectLaunchableMachineInfo() {
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
runAgentCreateCommand,
|
|
3
3
|
runAgentReadCommand,
|
|
4
4
|
runAgentUpdateCommand
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-LZZQTQPY.js";
|
|
6
|
+
import "./chunk-TH7ZZKPJ.js";
|
|
7
7
|
import "./chunk-IZNJDUJ4.js";
|
|
8
8
|
import "./chunk-6XG52ZQ6.js";
|
|
9
9
|
import "./chunk-UNHKVD2N.js";
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
prependSubjectDialogMarker,
|
|
6
6
|
resolveWorkflowReference,
|
|
7
7
|
runAgentRunCommand
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-45NBTCS2.js";
|
|
9
9
|
import "./chunk-IMHO5LC6.js";
|
|
10
10
|
import {
|
|
11
11
|
parseAgentRunArgs
|
|
12
12
|
} from "./chunk-4AWH4LQA.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-TH7ZZKPJ.js";
|
|
14
14
|
import "./chunk-IZNJDUJ4.js";
|
|
15
15
|
import "./chunk-6XG52ZQ6.js";
|
|
16
16
|
import "./chunk-UNHKVD2N.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
parseAgentRunEvent,
|
|
21
21
|
t,
|
|
22
22
|
toolLabel
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-TH7ZZKPJ.js";
|
|
24
24
|
import {
|
|
25
25
|
getReadableCliDb
|
|
26
26
|
} from "./chunk-UNHKVD2N.js";
|
|
@@ -5589,8 +5589,12 @@ function describeLocalRunFailure(message, rawError) {
|
|
|
5589
5589
|
busyDetail = rawError.detail.trim();
|
|
5590
5590
|
}
|
|
5591
5591
|
if (/PLATFORM_LLM_BUSY|服务器紧张/.test(message)) {
|
|
5592
|
-
const
|
|
5593
|
-
|
|
5592
|
+
const stripDebugNoise = (s) => s.replace(/\s*raw=".*"/g, "").replace(/\s*raw=\S+/g, "").replace(/\s*headers=\[[^\]]*\]/g, "").replace(/\s*headers=\S+/g, "").trim();
|
|
5593
|
+
const shown = stripDebugNoise(
|
|
5594
|
+
message.replace(/\s*\(PLATFORM_LLM_BUSY\)\s*$/, "")
|
|
5595
|
+
);
|
|
5596
|
+
const cleanedBusyDetail = busyDetail ? stripDebugNoise(busyDetail) : void 0;
|
|
5597
|
+
return `${RUN_UNAVAILABLE_PREFIX} \u670D\u52A1\u5668\u7D27\u5F20${shown !== "\u670D\u52A1\u5668\u7D27\u5F20" ? ` (${shown})` : ""} (PLATFORM_LLM_BUSY)${cleanedBusyDetail ? `: ${cleanedBusyDetail}` : ""}. ${NO_FALLBACK} \u5E73\u53F0\u6A21\u578B\u4E0A\u6E38\u7E41\u5FD9\uFF0C\u7A0D\u540E\u91CD\u8BD5\u6216\u6362\u4E2A\u6A21\u578B\u3002Retry shortly, ${SERVER_FALLBACK_HINT}
|
|
5594
5598
|
`;
|
|
5595
5599
|
}
|
|
5596
5600
|
if (/UPSTREAM_402|Insufficient Balance|余额不足|insufficient\s+balance/i.test(
|
|
@@ -9372,7 +9372,7 @@ async function shouldRetryPlatformProxyResponse(response) {
|
|
|
9372
9372
|
if (response.status !== 503) return false;
|
|
9373
9373
|
try {
|
|
9374
9374
|
const body = await response.clone().json();
|
|
9375
|
-
return body?.reason === "core_draining";
|
|
9375
|
+
return body?.reason === "core_draining" || body?.retryable === true;
|
|
9376
9376
|
} catch {
|
|
9377
9377
|
return false;
|
|
9378
9378
|
}
|
|
@@ -9552,9 +9552,17 @@ import { fileURLToPath } from "node:url";
|
|
|
9552
9552
|
var PROVIDER_STREAM_RETRY_MAX_ATTEMPTS = 2;
|
|
9553
9553
|
var STREAM_RETRY_MARKER = "\n\n[nolo] \u4E0A\u6E38\u6D41\u4E2D\u65AD\uFF0C\u81EA\u52A8\u91CD\u8BD5\uFF08\u4EE5\u4E0B\u4E3A\u8BE5\u8F6E\u91CD\u65B0\u751F\u6210\u7684\u5185\u5BB9\uFF09\n\n";
|
|
9554
9554
|
var UPSTREAM_STREAM_INTERRUPTED_RE = /UPSTREAM_STREAM_INTERRUPTED/i;
|
|
9555
|
+
var BUSY_STREAM_ERROR_RE = /PLATFORM_LLM_BUSY|服务器紧张/i;
|
|
9556
|
+
var BUSY_STREAM_RETRY_DELAY_MS = 1200;
|
|
9557
|
+
function isBusyProviderStreamError(error) {
|
|
9558
|
+
return BUSY_STREAM_ERROR_RE.test(toErrorMessage(error));
|
|
9559
|
+
}
|
|
9560
|
+
async function defaultSleep3(ms) {
|
|
9561
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
9562
|
+
}
|
|
9555
9563
|
function isRetryableProviderStreamError(error) {
|
|
9556
9564
|
const message = toErrorMessage(error);
|
|
9557
|
-
return UPSTREAM_STREAM_INTERRUPTED_RE.test(message) || isTransientFetchError(message);
|
|
9565
|
+
return UPSTREAM_STREAM_INTERRUPTED_RE.test(message) || BUSY_STREAM_ERROR_RE.test(message) || isTransientFetchError(message);
|
|
9558
9566
|
}
|
|
9559
9567
|
function withProviderStreamRetry(provider, deps) {
|
|
9560
9568
|
return {
|
|
@@ -9583,11 +9591,17 @@ function withProviderStreamRetry(provider, deps) {
|
|
|
9583
9591
|
if (options?.signal?.aborted) throw error;
|
|
9584
9592
|
if (attempt >= PROVIDER_STREAM_RETRY_MAX_ATTEMPTS) throw error;
|
|
9585
9593
|
if (!isRetryableProviderStreamError(error)) throw error;
|
|
9594
|
+
if (deps.retryOnly && !deps.retryOnly(error)) throw error;
|
|
9586
9595
|
if (sawToolEvent) throw error;
|
|
9587
9596
|
if (streamedChars > 0 && options?.onTextDelta) {
|
|
9588
9597
|
options.onTextDelta(STREAM_RETRY_MARKER);
|
|
9589
9598
|
}
|
|
9590
|
-
|
|
9599
|
+
if (isBusyProviderStreamError(error)) {
|
|
9600
|
+
deps.activityReporter?.("\u670D\u52A1\u5668\u7D27\u5F20 \xB7 \u7A0D\u5019\u81EA\u52A8\u91CD\u8BD5");
|
|
9601
|
+
await (deps.sleep ?? defaultSleep3)(BUSY_STREAM_RETRY_DELAY_MS);
|
|
9602
|
+
} else {
|
|
9603
|
+
deps.activityReporter?.("\u4E0A\u6E38\u6D41\u4E2D\u65AD \xB7 \u81EA\u52A8\u91CD\u8BD5");
|
|
9604
|
+
}
|
|
9591
9605
|
}
|
|
9592
9606
|
}
|
|
9593
9607
|
}
|
|
@@ -12246,7 +12260,10 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
12246
12260
|
const provider = await adapterBase.resolveProviderBase(
|
|
12247
12261
|
agentConfig
|
|
12248
12262
|
);
|
|
12249
|
-
return shouldUsePlatformChatProvider(deps.env, agentConfig) ?
|
|
12263
|
+
return shouldUsePlatformChatProvider(deps.env, agentConfig) ? withProviderStreamRetry(provider, {
|
|
12264
|
+
...deps,
|
|
12265
|
+
retryOnly: isBusyProviderStreamError
|
|
12266
|
+
}) : withProviderStreamRetry(provider, deps);
|
|
12250
12267
|
}
|
|
12251
12268
|
};
|
|
12252
12269
|
}
|
package/index.js
CHANGED
|
@@ -127,7 +127,7 @@ function createDaemonShortcutCommand(path, description, command2) {
|
|
|
127
127
|
// packages/cli/agentInternalCommandEntries.ts
|
|
128
128
|
function getAgentInternalCommandEntries() {
|
|
129
129
|
const createAgentRunCommand = (path, description) => createContextCommand(path, description, async (args2, ctx) => {
|
|
130
|
-
const { runAgentRunCommand } = await import("./agentRunCommand-
|
|
130
|
+
const { runAgentRunCommand } = await import("./agentRunCommand-4MEMHFT5.js");
|
|
131
131
|
return runAgentRunCommand(args2, {
|
|
132
132
|
env: ctx.env,
|
|
133
133
|
scriptDir: ctx.scriptDir,
|
|
@@ -143,7 +143,7 @@ function getAgentInternalCommandEntries() {
|
|
|
143
143
|
return runAgentListCommand(args2, deps);
|
|
144
144
|
}),
|
|
145
145
|
createEnvCommand(["agent", "create"], "Create a new agent", async (args2, deps) => {
|
|
146
|
-
const { runAgentCreateCommand } = await import("./agentRecordCommands-
|
|
146
|
+
const { runAgentCreateCommand } = await import("./agentRecordCommands-GJHH5GYI.js");
|
|
147
147
|
return runAgentCreateCommand(args2, deps);
|
|
148
148
|
}),
|
|
149
149
|
createEnvCommand(["agent", "models"], "List models available on an OpenAI-compatible provider", async (args2, deps) => {
|
|
@@ -155,7 +155,7 @@ function getAgentInternalCommandEntries() {
|
|
|
155
155
|
return runAgentPullCommand(args2, deps);
|
|
156
156
|
}),
|
|
157
157
|
createEnvCommand(["agent", "read"], "Read a single agent", async (args2, deps) => {
|
|
158
|
-
const { runAgentReadCommand } = await import("./agentRecordCommands-
|
|
158
|
+
const { runAgentReadCommand } = await import("./agentRecordCommands-GJHH5GYI.js");
|
|
159
159
|
return runAgentReadCommand(args2, deps);
|
|
160
160
|
}),
|
|
161
161
|
createAgentRunCommand(["agent", "run"], "Run an agent"),
|
|
@@ -193,26 +193,26 @@ function getAgentInternalCommandEntries() {
|
|
|
193
193
|
return runSetupOfflineMarxistsAgentCommand(args2, deps);
|
|
194
194
|
}),
|
|
195
195
|
createEnvCommand(["agent", "update"], "Update agent fields", async (args2, deps) => {
|
|
196
|
-
const { runAgentUpdateCommand } = await import("./agentRecordCommands-
|
|
196
|
+
const { runAgentUpdateCommand } = await import("./agentRecordCommands-GJHH5GYI.js");
|
|
197
197
|
return runAgentUpdateCommand(args2, deps);
|
|
198
198
|
}),
|
|
199
199
|
createEnvCommand(["agent", "email", "provision"], "Provision a controlled inbox for an agent", async (args2, deps) => {
|
|
200
|
-
const { runAgentEmailProvisionCommand } = await import("./agentEmailCommands-
|
|
200
|
+
const { runAgentEmailProvisionCommand } = await import("./agentEmailCommands-NGL5B3UC.js");
|
|
201
201
|
return runAgentEmailProvisionCommand(args2, deps);
|
|
202
202
|
}),
|
|
203
203
|
createEnvCommand(["agent", "email", "bind"], "Bind an existing email address to an agent", async (args2, deps) => {
|
|
204
|
-
const { runAgentEmailBindCommand } = await import("./agentEmailCommands-
|
|
204
|
+
const { runAgentEmailBindCommand } = await import("./agentEmailCommands-NGL5B3UC.js");
|
|
205
205
|
return runAgentEmailBindCommand(args2, deps);
|
|
206
206
|
}),
|
|
207
207
|
createEnvCommand(["agent", "email", "transfer"], "Transfer an email identity from one agent to another (cross-account)", async (args2, deps) => {
|
|
208
|
-
const { runAgentEmailTransferCommand } = await import("./agentEmailCommands-
|
|
208
|
+
const { runAgentEmailTransferCommand } = await import("./agentEmailCommands-NGL5B3UC.js");
|
|
209
209
|
return runAgentEmailTransferCommand(args2, deps);
|
|
210
210
|
}),
|
|
211
211
|
createEnvCommand(
|
|
212
212
|
["agent", "email", "create-and-provision"],
|
|
213
213
|
"Create an agent and provision its controlled inbox",
|
|
214
214
|
async (args2, deps) => {
|
|
215
|
-
const { runAgentEmailCreateAndProvisionCommand } = await import("./agentEmailCommands-
|
|
215
|
+
const { runAgentEmailCreateAndProvisionCommand } = await import("./agentEmailCommands-NGL5B3UC.js");
|
|
216
216
|
return runAgentEmailCreateAndProvisionCommand(args2, deps);
|
|
217
217
|
}
|
|
218
218
|
),
|
|
@@ -233,15 +233,15 @@ function getAgentInternalCommandEntries() {
|
|
|
233
233
|
return runAgentRevokeGrantCommand(args2, deps);
|
|
234
234
|
}),
|
|
235
235
|
createEnvCommand(["agent", "bind-current"], "Bind an agent to this machine", async (args2, deps) => {
|
|
236
|
-
const { runAgentBindCurrentCommand } = await import("./agentMachineCommands-
|
|
236
|
+
const { runAgentBindCurrentCommand } = await import("./agentMachineCommands-AXOO4OKN.js");
|
|
237
237
|
return runAgentBindCurrentCommand(args2, deps);
|
|
238
238
|
}),
|
|
239
239
|
createEnvCommand(["agent", "smoke-current"], "Smoke test a bound agent through this machine", async (args2, deps) => {
|
|
240
|
-
const { runAgentSmokeCurrentCommand } = await import("./agentMachineCommands-
|
|
240
|
+
const { runAgentSmokeCurrentCommand } = await import("./agentMachineCommands-AXOO4OKN.js");
|
|
241
241
|
return runAgentSmokeCurrentCommand(args2, deps);
|
|
242
242
|
}),
|
|
243
243
|
createEnvCommand(["agent", "runtime-doctor"], "Diagnose current machine runtime compatibility", async (args2, deps) => {
|
|
244
|
-
const { runAgentRuntimeDoctorCommand } = await import("./agentMachineCommands-
|
|
244
|
+
const { runAgentRuntimeDoctorCommand } = await import("./agentMachineCommands-AXOO4OKN.js");
|
|
245
245
|
return runAgentRuntimeDoctorCommand(args2, deps);
|
|
246
246
|
}),
|
|
247
247
|
createAgentRunCommand(["agent", "chat"], "Chat with an agent")
|
|
@@ -426,15 +426,15 @@ function getSystemInternalCommandEntries(renderHelpText2) {
|
|
|
426
426
|
return runWhoamiCommand({ args: args2, env: ctx.env });
|
|
427
427
|
}),
|
|
428
428
|
createEntrypointEnvCommand(["connect"], "Send machine heartbeats or hold a connector websocket", async (args2, deps) => {
|
|
429
|
-
const { runMachineConnectCommand } = await import("./machineCommands-
|
|
429
|
+
const { runMachineConnectCommand } = await import("./machineCommands-NAFWPMLI.js");
|
|
430
430
|
return runMachineConnectCommand(args2, deps);
|
|
431
431
|
}),
|
|
432
432
|
createDaemonShortcutCommand(["daemon"], "Run the connector daemon shortcut", async (args2, deps) => {
|
|
433
|
-
const { runMachineConnectCommand } = await import("./machineCommands-
|
|
433
|
+
const { runMachineConnectCommand } = await import("./machineCommands-NAFWPMLI.js");
|
|
434
434
|
return runMachineConnectCommand(args2, deps);
|
|
435
435
|
}),
|
|
436
436
|
createEnvCommand(["machine", "status"], "List machines registered to the current profile", async (args2, deps) => {
|
|
437
|
-
const { runMachineStatusCommand } = await import("./machineCommands-
|
|
437
|
+
const { runMachineStatusCommand } = await import("./machineCommands-NAFWPMLI.js");
|
|
438
438
|
return runMachineStatusCommand(args2, deps);
|
|
439
439
|
}),
|
|
440
440
|
createEnvCommand(["doctor", "runtime"], "Diagnose local-first agent runtime selection", async (args2, deps) => {
|
|
@@ -824,7 +824,7 @@ async function runScript(script, forwardedArgs, env) {
|
|
|
824
824
|
return proc.exited;
|
|
825
825
|
}
|
|
826
826
|
async function launchTuiWorkspace(args2) {
|
|
827
|
-
const { startTuiWorkspace } = await import("./readlineWorkspace-
|
|
827
|
+
const { startTuiWorkspace } = await import("./readlineWorkspace-BCQVDX4V.js");
|
|
828
828
|
const { createTuiSummaryLlmCaller } = await import("./tuiSummaryLlmCaller-SHRB4RWM.js");
|
|
829
829
|
return startTuiWorkspace({
|
|
830
830
|
...args2,
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
buildMachinePermissionPromptBlock,
|
|
3
3
|
handleConnectorRunMessage,
|
|
4
4
|
resolveMachineRunPermissionPolicy
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GEGSCLZZ.js";
|
|
6
6
|
import {
|
|
7
7
|
isConnectorWebSocketAuthError,
|
|
8
8
|
isConnectorWebSocketRetryableError,
|
|
9
9
|
resolveConnectorWebSocketTarget
|
|
10
10
|
} from "./chunk-MQRZ5QUH.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-TH7ZZKPJ.js";
|
|
12
12
|
import "./chunk-IZNJDUJ4.js";
|
|
13
13
|
import "./chunk-6XG52ZQ6.js";
|
|
14
14
|
import "./chunk-J5NMOM35.js";
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
runtimeWorkspacePermissionPolicy,
|
|
12
12
|
scopePermissionPolicyToRuntimeWorkspace,
|
|
13
13
|
summarizeAgentConfigForLogs
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-GEGSCLZZ.js";
|
|
15
|
+
import "./chunk-TH7ZZKPJ.js";
|
|
16
16
|
import "./chunk-IZNJDUJ4.js";
|
|
17
17
|
import "./chunk-6XG52ZQ6.js";
|
|
18
18
|
import "./chunk-J5NMOM35.js";
|
package/package.json
CHANGED
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
wrapTextToLines,
|
|
77
77
|
wrapTranscriptLine,
|
|
78
78
|
wrapTranscriptLineWithLayout
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-45NBTCS2.js";
|
|
80
80
|
import "./chunk-IMHO5LC6.js";
|
|
81
81
|
import "./chunk-4AWH4LQA.js";
|
|
82
82
|
import {
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
readTimestamp,
|
|
87
87
|
setCliLocale,
|
|
88
88
|
t
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-TH7ZZKPJ.js";
|
|
90
90
|
import "./chunk-IZNJDUJ4.js";
|
|
91
91
|
import "./chunk-6XG52ZQ6.js";
|
|
92
92
|
import {
|
|
@@ -7094,6 +7094,219 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
|
|
|
7094
7094
|
}
|
|
7095
7095
|
});
|
|
7096
7096
|
}
|
|
7097
|
+
async function runOneAgentTurn(ctx, inputMsg, imageUrls, actionGateHandler, confirmDestructiveAction) {
|
|
7098
|
+
const scheduleTitlePatchSync = (runResult) => {
|
|
7099
|
+
if (!runResult.titlePatchPromise || !runResult.dialogId) return;
|
|
7100
|
+
const patchDialogId = runResult.dialogId;
|
|
7101
|
+
runResult.titlePatchPromise.then((patchedTitle) => {
|
|
7102
|
+
if (!patchedTitle || ctx.sessionEnded) return;
|
|
7103
|
+
if (ctx.state.dialogId !== patchDialogId) return;
|
|
7104
|
+
if (ctx.state.dialogLabel === patchedTitle) return;
|
|
7105
|
+
ctx.state = {
|
|
7106
|
+
...ctx.state,
|
|
7107
|
+
dialogLabel: patchedTitle,
|
|
7108
|
+
dialogTitle: patchedTitle
|
|
7109
|
+
};
|
|
7110
|
+
ctx.syncWindowTitle();
|
|
7111
|
+
}).catch(() => {
|
|
7112
|
+
});
|
|
7113
|
+
};
|
|
7114
|
+
let req = createTurnRequest(inputMsg);
|
|
7115
|
+
if (req.event.kind === "child-run-completed") {
|
|
7116
|
+
const nowMs = Date.now();
|
|
7117
|
+
const { remainingRuns, claimedRunIds } = filterUnclaimedChildRuns(
|
|
7118
|
+
req.event.runs,
|
|
7119
|
+
{ env: ctx.effectiveEnv, now: () => nowMs }
|
|
7120
|
+
);
|
|
7121
|
+
for (const runId of claimedRunIds) {
|
|
7122
|
+
ctx.runCompletionWatcher.markAcknowledged(runId);
|
|
7123
|
+
}
|
|
7124
|
+
if (remainingRuns.length === 0) {
|
|
7125
|
+
for (const r of req.event.runs) {
|
|
7126
|
+
ctx.runCompletionWatcher.markAcknowledged(r.runId);
|
|
7127
|
+
}
|
|
7128
|
+
return { ok: true, aborted: false };
|
|
7129
|
+
}
|
|
7130
|
+
for (const r of remainingRuns) {
|
|
7131
|
+
ctx.runCompletionWatcher.markAcknowledged(r.runId);
|
|
7132
|
+
}
|
|
7133
|
+
if (remainingRuns.length !== req.event.runs.length) {
|
|
7134
|
+
const text = buildWakeMessage(remainingRuns, nowMs);
|
|
7135
|
+
const displayText = buildWakeDisplayText(remainingRuns, nowMs);
|
|
7136
|
+
const updatedEvent = {
|
|
7137
|
+
kind: "child-run-completed",
|
|
7138
|
+
runs: remainingRuns,
|
|
7139
|
+
text,
|
|
7140
|
+
displayText
|
|
7141
|
+
};
|
|
7142
|
+
req = {
|
|
7143
|
+
text,
|
|
7144
|
+
event: updatedEvent
|
|
7145
|
+
};
|
|
7146
|
+
}
|
|
7147
|
+
}
|
|
7148
|
+
const message = req.text;
|
|
7149
|
+
ctx.forcedStop = false;
|
|
7150
|
+
ctx.turnEpoch += 1;
|
|
7151
|
+
const myEpoch = ctx.turnEpoch;
|
|
7152
|
+
ctx.history.followBottom = true;
|
|
7153
|
+
const isInternalEvent = req.event.kind !== "user";
|
|
7154
|
+
const transcriptText = req.event.kind === "child-run-completed" ? req.event.displayText ?? req.event.text : message;
|
|
7155
|
+
startTurn(ctx.history, isInternalEvent ? "assistant" : "user");
|
|
7156
|
+
appendToCurrentTurn(
|
|
7157
|
+
ctx.history,
|
|
7158
|
+
isInternalEvent ? dimCliText(transcriptText, resolveCliColorEnabled()) : transcriptText
|
|
7159
|
+
);
|
|
7160
|
+
finalizeCurrentTurn(ctx.history);
|
|
7161
|
+
ctx.renderHistoryToOutput();
|
|
7162
|
+
if (ctx.fixedInput.active) ctx.fixedInput.repaint(ctx.buffer, ctx.cursorPos);
|
|
7163
|
+
startTurn(ctx.history, "assistant");
|
|
7164
|
+
const agentOutput = isInteractiveInput(ctx.input) ? createHistoryOutputStream(ctx.history, () => {
|
|
7165
|
+
ctx.scheduleRender();
|
|
7166
|
+
}) : ctx.output;
|
|
7167
|
+
const requestUserChoice = isInteractiveInput(ctx.input) && ctx.dialogHost ? async (choiceReq) => {
|
|
7168
|
+
ctx.modalOwnsKeyboard = true;
|
|
7169
|
+
try {
|
|
7170
|
+
return await ctx.dialogHost.run(
|
|
7171
|
+
(anchor) => runAskChoiceDialog({
|
|
7172
|
+
request: choiceReq,
|
|
7173
|
+
input: ctx.input,
|
|
7174
|
+
output: ctx.output,
|
|
7175
|
+
...anchor
|
|
7176
|
+
})
|
|
7177
|
+
);
|
|
7178
|
+
} catch {
|
|
7179
|
+
return { kind: "cancelled" };
|
|
7180
|
+
} finally {
|
|
7181
|
+
ctx.composerDecoderDrain?.();
|
|
7182
|
+
ctx.modalOwnsKeyboard = false;
|
|
7183
|
+
}
|
|
7184
|
+
} : void 0;
|
|
7185
|
+
try {
|
|
7186
|
+
ctx.activeTurnAbort = new AbortController();
|
|
7187
|
+
ctx.activeTurnEpoch = myEpoch;
|
|
7188
|
+
const runResult = await runAgentChat(
|
|
7189
|
+
ctx.options.scriptDir,
|
|
7190
|
+
ctx.state,
|
|
7191
|
+
message,
|
|
7192
|
+
ctx.options.env ?? process.env,
|
|
7193
|
+
agentOutput,
|
|
7194
|
+
ctx.options.agentRunner,
|
|
7195
|
+
{
|
|
7196
|
+
...imageUrls.length > 0 ? { imageUrls } : {},
|
|
7197
|
+
actionGateHandler,
|
|
7198
|
+
...confirmDestructiveAction ? { confirmDestructiveAction } : {},
|
|
7199
|
+
...requestUserChoice ? { requestUserChoice } : {},
|
|
7200
|
+
abortSignal: ctx.activeTurnAbort.signal,
|
|
7201
|
+
pastedTextStore: ctx.pasteStore,
|
|
7202
|
+
activityReporter: ctx.activityReporter,
|
|
7203
|
+
onAgentRunStatus: (snapshot) => {
|
|
7204
|
+
if (snapshot) {
|
|
7205
|
+
ctx.activityIndicator.updateAgentRun(snapshot);
|
|
7206
|
+
ctx.runRegistryPoller.ensureRunning();
|
|
7207
|
+
} else {
|
|
7208
|
+
ctx.activityIndicator.clearAgentRun();
|
|
7209
|
+
}
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
);
|
|
7213
|
+
const wasForceStopped = ctx.forcedStopEpoch === myEpoch;
|
|
7214
|
+
if (wasForceStopped) {
|
|
7215
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
7216
|
+
const nextDialogKey = runResult.dialogId ? runResult.dialogId === ctx.state.dialogId && ctx.state.dialogKey ? ctx.state.dialogKey : ctx.state.dialogOwnerId ? `dialog-${ctx.state.dialogOwnerId}-${runResult.dialogId}` : void 0 : ctx.state.dialogKey;
|
|
7217
|
+
ctx.state = {
|
|
7218
|
+
...ctx.state,
|
|
7219
|
+
...runResult.dialogId ? {
|
|
7220
|
+
dialogId: runResult.dialogId,
|
|
7221
|
+
dialogKey: nextDialogKey,
|
|
7222
|
+
dialogLabel: runResult.title || runResult.dialogId,
|
|
7223
|
+
...runResult.title ? { dialogTitle: runResult.title } : {}
|
|
7224
|
+
} : {},
|
|
7225
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
7226
|
+
...runResult.cachedMemoryOverlay !== void 0 ? { cachedMemoryOverlay: runResult.cachedMemoryOverlay } : {}
|
|
7227
|
+
};
|
|
7228
|
+
if (runResult.dialogId && nextDialogKey) {
|
|
7229
|
+
ctx.refreshDialogTotalCredits(runResult.dialogId, nextDialogKey);
|
|
7230
|
+
}
|
|
7231
|
+
}
|
|
7232
|
+
scheduleTitlePatchSync(runResult);
|
|
7233
|
+
return { ok: false, aborted: true };
|
|
7234
|
+
}
|
|
7235
|
+
const wasAborted = ctx.activeTurnAbort.signal.aborted;
|
|
7236
|
+
ctx.activeTurnAbort = null;
|
|
7237
|
+
if (shouldEmitTerminalBell({
|
|
7238
|
+
wasAborted,
|
|
7239
|
+
streamInterrupted: runResult.streamInterrupted,
|
|
7240
|
+
exitCode: runResult.exitCode,
|
|
7241
|
+
interactive: isInteractiveInput(ctx.input)
|
|
7242
|
+
})) {
|
|
7243
|
+
emitTerminalBell(ctx.output);
|
|
7244
|
+
}
|
|
7245
|
+
if (isInteractiveInput(ctx.input)) {
|
|
7246
|
+
finalizeCurrentTurn(ctx.history);
|
|
7247
|
+
ctx.flushPendingRender();
|
|
7248
|
+
ctx.renderHistoryToOutput();
|
|
7249
|
+
if (ctx.fixedInput.active) ctx.fixedInput.repaint(ctx.buffer, ctx.cursorPos);
|
|
7250
|
+
}
|
|
7251
|
+
if (wasAborted) {
|
|
7252
|
+
if (runResult.pendingToolName) {
|
|
7253
|
+
ctx.emitCommandOutput(t("turnStoppedToolPending", runResult.pendingToolName));
|
|
7254
|
+
} else {
|
|
7255
|
+
ctx.emitCommandOutput(t("turnStopped"));
|
|
7256
|
+
}
|
|
7257
|
+
}
|
|
7258
|
+
if (runResult.dialogId || runResult.turnTokens || runResult.contextWindow) {
|
|
7259
|
+
const nextDialogKey = runResult.dialogId ? runResult.dialogId === ctx.state.dialogId && ctx.state.dialogKey ? ctx.state.dialogKey : ctx.state.dialogOwnerId ? `dialog-${ctx.state.dialogOwnerId}-${runResult.dialogId}` : void 0 : ctx.state.dialogKey;
|
|
7260
|
+
ctx.state = {
|
|
7261
|
+
...ctx.state,
|
|
7262
|
+
...runResult.dialogId ? {
|
|
7263
|
+
dialogId: runResult.dialogId,
|
|
7264
|
+
dialogKey: nextDialogKey,
|
|
7265
|
+
dialogLabel: runResult.title || runResult.dialogId,
|
|
7266
|
+
...runResult.title ? { dialogTitle: runResult.title } : {}
|
|
7267
|
+
} : {},
|
|
7268
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
7269
|
+
...runResult.contextWindow ? { contextWindow: runResult.contextWindow } : {},
|
|
7270
|
+
// input_tokens 是累计上下文输入(含历史消息),把它持久化到
|
|
7271
|
+
// estimatedContextTokens:下一轮若 provider 不返回 usage,context
|
|
7272
|
+
// chip 仍显示真实累计占用而不是回退到启动时的静态估算。
|
|
7273
|
+
...runResult.turnTokens && runResult.turnTokens.input > 0 ? { estimatedContextTokens: runResult.turnTokens.input } : {},
|
|
7274
|
+
...runResult.cachedMemoryOverlay !== void 0 ? { cachedMemoryOverlay: runResult.cachedMemoryOverlay } : {}
|
|
7275
|
+
};
|
|
7276
|
+
if (runResult.dialogId && nextDialogKey) {
|
|
7277
|
+
ctx.refreshDialogTotalCredits(runResult.dialogId, nextDialogKey);
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
scheduleTitlePatchSync(runResult);
|
|
7281
|
+
if (!wasAborted && runResult.exitCode !== 0) {
|
|
7282
|
+
if (isBalanceExhaustedError(runResult.localError) && runResult.dialogId) {
|
|
7283
|
+
ctx.emitCommandOutput(t("balanceExhaustedHint"));
|
|
7284
|
+
} else if (isQuotaExhaustedError(runResult.localError)) {
|
|
7285
|
+
ctx.emitCommandOutput(t("quotaExhaustedHint"));
|
|
7286
|
+
} else if (runResult.dialogId) {
|
|
7287
|
+
ctx.emitCommandOutput(t("dialogPreservedHint"));
|
|
7288
|
+
} else {
|
|
7289
|
+
ctx.emitCommandOutput(t("dialogNotSavedHint"));
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
return { ok: !wasAborted, aborted: wasAborted };
|
|
7293
|
+
} finally {
|
|
7294
|
+
ctx.activityIndicator.stop();
|
|
7295
|
+
ctx.activeTurnAbort = null;
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
function ensureChatQueueBinding(ctx, actionGateHandler, confirmDestructiveAction) {
|
|
7299
|
+
if (ctx.chatQueueBinding) return ctx.chatQueueBinding;
|
|
7300
|
+
ctx.chatQueueBinding = createChatQueueTuiBinding(async (text) => {
|
|
7301
|
+
return runOneAgentTurn(ctx, text, [], actionGateHandler, confirmDestructiveAction);
|
|
7302
|
+
});
|
|
7303
|
+
return ctx.chatQueueBinding;
|
|
7304
|
+
}
|
|
7305
|
+
function preemptAndAbortForDrain(binding, activeTurnAbort) {
|
|
7306
|
+
if (binding.preemptForDrain() && activeTurnAbort) {
|
|
7307
|
+
activeTurnAbort.abort();
|
|
7308
|
+
}
|
|
7309
|
+
}
|
|
7097
7310
|
var latestWorkspaceThemeOwner = 0;
|
|
7098
7311
|
async function runTuiWorkspace(options) {
|
|
7099
7312
|
initCliLocale(options.env ?? process.env);
|
|
@@ -7373,220 +7586,6 @@ ${content}`);
|
|
|
7373
7586
|
});
|
|
7374
7587
|
};
|
|
7375
7588
|
let composerDecoderDrain = null;
|
|
7376
|
-
const runOneAgentTurn = async (inputMsg, imageUrls, actionGateHandler, confirmDestructiveAction) => {
|
|
7377
|
-
const scheduleTitlePatchSync = (runResult) => {
|
|
7378
|
-
if (!runResult.titlePatchPromise || !runResult.dialogId) return;
|
|
7379
|
-
const patchDialogId = runResult.dialogId;
|
|
7380
|
-
runResult.titlePatchPromise.then((patchedTitle) => {
|
|
7381
|
-
if (!patchedTitle || sessionEnded) return;
|
|
7382
|
-
if (state.dialogId !== patchDialogId) return;
|
|
7383
|
-
if (state.dialogLabel === patchedTitle) return;
|
|
7384
|
-
state = {
|
|
7385
|
-
...state,
|
|
7386
|
-
dialogLabel: patchedTitle,
|
|
7387
|
-
dialogTitle: patchedTitle
|
|
7388
|
-
};
|
|
7389
|
-
syncWindowTitle();
|
|
7390
|
-
}).catch(() => {
|
|
7391
|
-
});
|
|
7392
|
-
};
|
|
7393
|
-
let req = createTurnRequest(inputMsg);
|
|
7394
|
-
if (req.event.kind === "child-run-completed") {
|
|
7395
|
-
const nowMs = Date.now();
|
|
7396
|
-
const { remainingRuns, claimedRunIds } = filterUnclaimedChildRuns(
|
|
7397
|
-
req.event.runs,
|
|
7398
|
-
{ env: effectiveEnv, now: () => nowMs }
|
|
7399
|
-
);
|
|
7400
|
-
for (const runId of claimedRunIds) {
|
|
7401
|
-
runCompletionWatcher.markAcknowledged(runId);
|
|
7402
|
-
}
|
|
7403
|
-
if (remainingRuns.length === 0) {
|
|
7404
|
-
for (const r of req.event.runs) {
|
|
7405
|
-
runCompletionWatcher.markAcknowledged(r.runId);
|
|
7406
|
-
}
|
|
7407
|
-
return { ok: true, aborted: false };
|
|
7408
|
-
}
|
|
7409
|
-
for (const r of remainingRuns) {
|
|
7410
|
-
runCompletionWatcher.markAcknowledged(r.runId);
|
|
7411
|
-
}
|
|
7412
|
-
if (remainingRuns.length !== req.event.runs.length) {
|
|
7413
|
-
const text = buildWakeMessage(remainingRuns, nowMs);
|
|
7414
|
-
const displayText = buildWakeDisplayText(remainingRuns, nowMs);
|
|
7415
|
-
const updatedEvent = {
|
|
7416
|
-
kind: "child-run-completed",
|
|
7417
|
-
runs: remainingRuns,
|
|
7418
|
-
text,
|
|
7419
|
-
displayText
|
|
7420
|
-
};
|
|
7421
|
-
req = {
|
|
7422
|
-
text,
|
|
7423
|
-
event: updatedEvent
|
|
7424
|
-
};
|
|
7425
|
-
}
|
|
7426
|
-
}
|
|
7427
|
-
const message = req.text;
|
|
7428
|
-
forcedStop = false;
|
|
7429
|
-
turnEpoch += 1;
|
|
7430
|
-
const myEpoch = turnEpoch;
|
|
7431
|
-
history.followBottom = true;
|
|
7432
|
-
const isInternalEvent = req.event.kind !== "user";
|
|
7433
|
-
const transcriptText = req.event.kind === "child-run-completed" ? req.event.displayText ?? req.event.text : message;
|
|
7434
|
-
startTurn(history, isInternalEvent ? "assistant" : "user");
|
|
7435
|
-
appendToCurrentTurn(
|
|
7436
|
-
history,
|
|
7437
|
-
isInternalEvent ? dimCliText(transcriptText, resolveCliColorEnabled()) : transcriptText
|
|
7438
|
-
);
|
|
7439
|
-
finalizeCurrentTurn(history);
|
|
7440
|
-
renderHistoryToOutput();
|
|
7441
|
-
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
7442
|
-
startTurn(history, "assistant");
|
|
7443
|
-
const agentOutput = isInteractiveInput(input) ? createHistoryOutputStream(history, () => {
|
|
7444
|
-
scheduleRender();
|
|
7445
|
-
}) : output;
|
|
7446
|
-
const requestUserChoice = isInteractiveInput(input) && dialogHost ? async (req2) => {
|
|
7447
|
-
modalOwnsKeyboard = true;
|
|
7448
|
-
try {
|
|
7449
|
-
return await dialogHost.run(
|
|
7450
|
-
(anchor) => runAskChoiceDialog({
|
|
7451
|
-
request: req2,
|
|
7452
|
-
input,
|
|
7453
|
-
output,
|
|
7454
|
-
...anchor
|
|
7455
|
-
})
|
|
7456
|
-
);
|
|
7457
|
-
} catch {
|
|
7458
|
-
return { kind: "cancelled" };
|
|
7459
|
-
} finally {
|
|
7460
|
-
composerDecoderDrain?.();
|
|
7461
|
-
modalOwnsKeyboard = false;
|
|
7462
|
-
}
|
|
7463
|
-
} : void 0;
|
|
7464
|
-
try {
|
|
7465
|
-
activeTurnAbort = new AbortController();
|
|
7466
|
-
activeTurnEpoch = myEpoch;
|
|
7467
|
-
const runResult = await runAgentChat(
|
|
7468
|
-
options.scriptDir,
|
|
7469
|
-
state,
|
|
7470
|
-
message,
|
|
7471
|
-
options.env ?? process.env,
|
|
7472
|
-
agentOutput,
|
|
7473
|
-
options.agentRunner,
|
|
7474
|
-
{
|
|
7475
|
-
...imageUrls.length > 0 ? { imageUrls } : {},
|
|
7476
|
-
actionGateHandler,
|
|
7477
|
-
...confirmDestructiveAction ? { confirmDestructiveAction } : {},
|
|
7478
|
-
...requestUserChoice ? { requestUserChoice } : {},
|
|
7479
|
-
abortSignal: activeTurnAbort.signal,
|
|
7480
|
-
pastedTextStore: pasteStore,
|
|
7481
|
-
activityReporter,
|
|
7482
|
-
onAgentRunStatus: (snapshot) => {
|
|
7483
|
-
if (snapshot) {
|
|
7484
|
-
activityIndicator.updateAgentRun(snapshot);
|
|
7485
|
-
runRegistryPoller.ensureRunning();
|
|
7486
|
-
} else {
|
|
7487
|
-
activityIndicator.clearAgentRun();
|
|
7488
|
-
}
|
|
7489
|
-
}
|
|
7490
|
-
}
|
|
7491
|
-
);
|
|
7492
|
-
const wasForceStopped = forcedStopEpoch === myEpoch;
|
|
7493
|
-
if (wasForceStopped) {
|
|
7494
|
-
if (runResult.dialogId || runResult.turnTokens) {
|
|
7495
|
-
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
7496
|
-
state = {
|
|
7497
|
-
...state,
|
|
7498
|
-
...runResult.dialogId ? {
|
|
7499
|
-
dialogId: runResult.dialogId,
|
|
7500
|
-
dialogKey: nextDialogKey,
|
|
7501
|
-
dialogLabel: runResult.title || runResult.dialogId,
|
|
7502
|
-
...runResult.title ? { dialogTitle: runResult.title } : {}
|
|
7503
|
-
} : {},
|
|
7504
|
-
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
7505
|
-
...runResult.cachedMemoryOverlay !== void 0 ? { cachedMemoryOverlay: runResult.cachedMemoryOverlay } : {}
|
|
7506
|
-
};
|
|
7507
|
-
if (runResult.dialogId && nextDialogKey) {
|
|
7508
|
-
refreshDialogTotalCredits(runResult.dialogId, nextDialogKey);
|
|
7509
|
-
}
|
|
7510
|
-
}
|
|
7511
|
-
scheduleTitlePatchSync(runResult);
|
|
7512
|
-
return { ok: false, aborted: true };
|
|
7513
|
-
}
|
|
7514
|
-
const wasAborted = activeTurnAbort.signal.aborted;
|
|
7515
|
-
activeTurnAbort = null;
|
|
7516
|
-
if (shouldEmitTerminalBell({
|
|
7517
|
-
wasAborted,
|
|
7518
|
-
streamInterrupted: runResult.streamInterrupted,
|
|
7519
|
-
exitCode: runResult.exitCode,
|
|
7520
|
-
interactive: isInteractiveInput(input)
|
|
7521
|
-
})) {
|
|
7522
|
-
emitTerminalBell(output);
|
|
7523
|
-
}
|
|
7524
|
-
if (isInteractiveInput(input)) {
|
|
7525
|
-
finalizeCurrentTurn(history);
|
|
7526
|
-
flushPendingRender();
|
|
7527
|
-
renderHistoryToOutput();
|
|
7528
|
-
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
7529
|
-
}
|
|
7530
|
-
if (wasAborted) {
|
|
7531
|
-
if (runResult.pendingToolName) {
|
|
7532
|
-
emitCommandOutput(t("turnStoppedToolPending", runResult.pendingToolName));
|
|
7533
|
-
} else {
|
|
7534
|
-
emitCommandOutput(t("turnStopped"));
|
|
7535
|
-
}
|
|
7536
|
-
}
|
|
7537
|
-
if (runResult.dialogId || runResult.turnTokens || runResult.contextWindow) {
|
|
7538
|
-
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
7539
|
-
state = {
|
|
7540
|
-
...state,
|
|
7541
|
-
...runResult.dialogId ? {
|
|
7542
|
-
dialogId: runResult.dialogId,
|
|
7543
|
-
dialogKey: nextDialogKey,
|
|
7544
|
-
dialogLabel: runResult.title || runResult.dialogId,
|
|
7545
|
-
...runResult.title ? { dialogTitle: runResult.title } : {}
|
|
7546
|
-
} : {},
|
|
7547
|
-
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
7548
|
-
...runResult.contextWindow ? { contextWindow: runResult.contextWindow } : {},
|
|
7549
|
-
// input_tokens 是累计上下文输入(含历史消息),把它持久化到
|
|
7550
|
-
// estimatedContextTokens:下一轮若 provider 不返回 usage,context
|
|
7551
|
-
// chip 仍显示真实累计占用而不是回退到启动时的静态估算。
|
|
7552
|
-
...runResult.turnTokens && runResult.turnTokens.input > 0 ? { estimatedContextTokens: runResult.turnTokens.input } : {},
|
|
7553
|
-
...runResult.cachedMemoryOverlay !== void 0 ? { cachedMemoryOverlay: runResult.cachedMemoryOverlay } : {}
|
|
7554
|
-
};
|
|
7555
|
-
if (runResult.dialogId && nextDialogKey) {
|
|
7556
|
-
refreshDialogTotalCredits(runResult.dialogId, nextDialogKey);
|
|
7557
|
-
}
|
|
7558
|
-
}
|
|
7559
|
-
scheduleTitlePatchSync(runResult);
|
|
7560
|
-
if (!wasAborted && runResult.exitCode !== 0) {
|
|
7561
|
-
if (isBalanceExhaustedError(runResult.localError) && runResult.dialogId) {
|
|
7562
|
-
emitCommandOutput(t("balanceExhaustedHint"));
|
|
7563
|
-
} else if (isQuotaExhaustedError(runResult.localError)) {
|
|
7564
|
-
emitCommandOutput(t("quotaExhaustedHint"));
|
|
7565
|
-
} else if (runResult.dialogId) {
|
|
7566
|
-
emitCommandOutput(t("dialogPreservedHint"));
|
|
7567
|
-
} else {
|
|
7568
|
-
emitCommandOutput(t("dialogNotSavedHint"));
|
|
7569
|
-
}
|
|
7570
|
-
}
|
|
7571
|
-
return { ok: !wasAborted, aborted: wasAborted };
|
|
7572
|
-
} finally {
|
|
7573
|
-
activityIndicator.stop();
|
|
7574
|
-
activeTurnAbort = null;
|
|
7575
|
-
}
|
|
7576
|
-
};
|
|
7577
|
-
let chatQueueBinding = null;
|
|
7578
|
-
const ensureChatQueueBinding = (actionGateHandler, confirmDestructiveAction) => {
|
|
7579
|
-
if (chatQueueBinding) return chatQueueBinding;
|
|
7580
|
-
chatQueueBinding = createChatQueueTuiBinding(async (text) => {
|
|
7581
|
-
return runOneAgentTurn(text, [], actionGateHandler, confirmDestructiveAction);
|
|
7582
|
-
});
|
|
7583
|
-
return chatQueueBinding;
|
|
7584
|
-
};
|
|
7585
|
-
const preemptAndAbortForDrain = (binding) => {
|
|
7586
|
-
if (binding.preemptForDrain() && activeTurnAbort) {
|
|
7587
|
-
activeTurnAbort.abort();
|
|
7588
|
-
}
|
|
7589
|
-
};
|
|
7590
7589
|
const emitCommandOutput = (text, command = "") => {
|
|
7591
7590
|
if (!text) return;
|
|
7592
7591
|
if (!isInteractiveInput(input)) {
|
|
@@ -7599,6 +7598,92 @@ ${content}`);
|
|
|
7599
7598
|
renderHistoryToOutput();
|
|
7600
7599
|
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
7601
7600
|
};
|
|
7601
|
+
let chatQueueBinding = null;
|
|
7602
|
+
const turnCtx = {
|
|
7603
|
+
get state() {
|
|
7604
|
+
return state;
|
|
7605
|
+
},
|
|
7606
|
+
set state(v) {
|
|
7607
|
+
state = v;
|
|
7608
|
+
},
|
|
7609
|
+
get forcedStop() {
|
|
7610
|
+
return forcedStop;
|
|
7611
|
+
},
|
|
7612
|
+
set forcedStop(v) {
|
|
7613
|
+
forcedStop = v;
|
|
7614
|
+
},
|
|
7615
|
+
get forcedStopEpoch() {
|
|
7616
|
+
return forcedStopEpoch;
|
|
7617
|
+
},
|
|
7618
|
+
set forcedStopEpoch(v) {
|
|
7619
|
+
forcedStopEpoch = v;
|
|
7620
|
+
},
|
|
7621
|
+
get turnEpoch() {
|
|
7622
|
+
return turnEpoch;
|
|
7623
|
+
},
|
|
7624
|
+
set turnEpoch(v) {
|
|
7625
|
+
turnEpoch = v;
|
|
7626
|
+
},
|
|
7627
|
+
get activeTurnAbort() {
|
|
7628
|
+
return activeTurnAbort;
|
|
7629
|
+
},
|
|
7630
|
+
set activeTurnAbort(v) {
|
|
7631
|
+
activeTurnAbort = v;
|
|
7632
|
+
},
|
|
7633
|
+
get activeTurnEpoch() {
|
|
7634
|
+
return activeTurnEpoch;
|
|
7635
|
+
},
|
|
7636
|
+
set activeTurnEpoch(v) {
|
|
7637
|
+
activeTurnEpoch = v;
|
|
7638
|
+
},
|
|
7639
|
+
get modalOwnsKeyboard() {
|
|
7640
|
+
return modalOwnsKeyboard;
|
|
7641
|
+
},
|
|
7642
|
+
set modalOwnsKeyboard(v) {
|
|
7643
|
+
modalOwnsKeyboard = v;
|
|
7644
|
+
},
|
|
7645
|
+
get composerDecoderDrain() {
|
|
7646
|
+
return composerDecoderDrain;
|
|
7647
|
+
},
|
|
7648
|
+
set composerDecoderDrain(v) {
|
|
7649
|
+
composerDecoderDrain = v;
|
|
7650
|
+
},
|
|
7651
|
+
get chatQueueBinding() {
|
|
7652
|
+
return chatQueueBinding;
|
|
7653
|
+
},
|
|
7654
|
+
set chatQueueBinding(v) {
|
|
7655
|
+
chatQueueBinding = v;
|
|
7656
|
+
},
|
|
7657
|
+
get sessionEnded() {
|
|
7658
|
+
return sessionEnded;
|
|
7659
|
+
},
|
|
7660
|
+
get buffer() {
|
|
7661
|
+
return buffer;
|
|
7662
|
+
},
|
|
7663
|
+
get cursorPos() {
|
|
7664
|
+
return cursorPos;
|
|
7665
|
+
},
|
|
7666
|
+
get fixedInput() {
|
|
7667
|
+
return fixedInput;
|
|
7668
|
+
},
|
|
7669
|
+
options,
|
|
7670
|
+
effectiveEnv,
|
|
7671
|
+
history,
|
|
7672
|
+
activityIndicator,
|
|
7673
|
+
activityReporter,
|
|
7674
|
+
runRegistryPoller,
|
|
7675
|
+
runCompletionWatcher,
|
|
7676
|
+
pasteStore,
|
|
7677
|
+
dialogHost,
|
|
7678
|
+
input,
|
|
7679
|
+
output,
|
|
7680
|
+
syncWindowTitle,
|
|
7681
|
+
renderHistoryToOutput,
|
|
7682
|
+
scheduleRender,
|
|
7683
|
+
flushPendingRender,
|
|
7684
|
+
refreshDialogTotalCredits,
|
|
7685
|
+
emitCommandOutput
|
|
7686
|
+
};
|
|
7602
7687
|
const persistExplicitAgentSwitch = (previousAgentKey) => {
|
|
7603
7688
|
if (state.agentKey === previousAgentKey) return false;
|
|
7604
7689
|
persistAgentSelection(
|
|
@@ -8020,10 +8105,11 @@ ${stderrText.trim()}
|
|
|
8020
8105
|
attachedImages: []
|
|
8021
8106
|
};
|
|
8022
8107
|
history.followBottom = true;
|
|
8023
|
-
const binding = ensureChatQueueBinding(actionGateHandler, confirmDestructiveAction);
|
|
8108
|
+
const binding = ensureChatQueueBinding(turnCtx, actionGateHandler, confirmDestructiveAction);
|
|
8024
8109
|
binding.notifyTurnStart();
|
|
8025
8110
|
try {
|
|
8026
8111
|
const outcome = await runOneAgentTurn(
|
|
8112
|
+
turnCtx,
|
|
8027
8113
|
result.action.message,
|
|
8028
8114
|
imageUrls,
|
|
8029
8115
|
actionGateHandler,
|
|
@@ -8182,12 +8268,13 @@ ${err.message}` : ""}`
|
|
|
8182
8268
|
const runIdleTextTurn = async (inputMsg) => {
|
|
8183
8269
|
const req = createTurnRequest(inputMsg);
|
|
8184
8270
|
const { actionGateHandler, confirmDestructiveAction } = buildInteractiveTurnHandlers();
|
|
8185
|
-
const binding = ensureChatQueueBinding(actionGateHandler, confirmDestructiveAction);
|
|
8271
|
+
const binding = ensureChatQueueBinding(turnCtx, actionGateHandler, confirmDestructiveAction);
|
|
8186
8272
|
binding.notifyTurnStart();
|
|
8187
8273
|
busy = true;
|
|
8188
8274
|
fixedInput.enterOutputMode(req.text);
|
|
8189
8275
|
try {
|
|
8190
8276
|
const outcome = await runOneAgentTurn(
|
|
8277
|
+
turnCtx,
|
|
8191
8278
|
req,
|
|
8192
8279
|
[],
|
|
8193
8280
|
actionGateHandler,
|
|
@@ -8211,7 +8298,7 @@ ${err.message}` : ""}`
|
|
|
8211
8298
|
if (done) return;
|
|
8212
8299
|
if (busy || fixedInput.isPaused()) {
|
|
8213
8300
|
const { actionGateHandler, confirmDestructiveAction } = buildInteractiveTurnHandlers();
|
|
8214
|
-
ensureChatQueueBinding(actionGateHandler, confirmDestructiveAction).enqueue(event);
|
|
8301
|
+
ensureChatQueueBinding(turnCtx, actionGateHandler, confirmDestructiveAction).enqueue(event);
|
|
8215
8302
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
8216
8303
|
fixedInput.repaint(buffer, cursorPos);
|
|
8217
8304
|
}
|
|
@@ -8271,6 +8358,109 @@ ${err.message}` : ""}`
|
|
|
8271
8358
|
paintFrame(buffer);
|
|
8272
8359
|
}, 60);
|
|
8273
8360
|
};
|
|
8361
|
+
const handleCtrlCKey = async (busyLock) => {
|
|
8362
|
+
if (busyLock && activeTurnAbort) {
|
|
8363
|
+
const stopBinding = chatQueueBinding;
|
|
8364
|
+
if (stopBinding && stopBinding.queueLength() > 0) {
|
|
8365
|
+
stopBinding.preemptForStop();
|
|
8366
|
+
}
|
|
8367
|
+
activityIndicator.markStopping();
|
|
8368
|
+
activeTurnAbort.abort();
|
|
8369
|
+
return;
|
|
8370
|
+
}
|
|
8371
|
+
const now = Date.now();
|
|
8372
|
+
const hasSelection = selectionState.anchor !== null && selectionState.head !== null && !areSelectionPointsEqual(selectionState.anchor, selectionState.head);
|
|
8373
|
+
if (hasSelection) {
|
|
8374
|
+
const tty = output;
|
|
8375
|
+
const columns = tty.columns ?? 80;
|
|
8376
|
+
const contentWidth = Math.max(1, columns - 1);
|
|
8377
|
+
const textToCopy = extractSelectedText(
|
|
8378
|
+
history,
|
|
8379
|
+
selectionState.anchor,
|
|
8380
|
+
selectionState.head,
|
|
8381
|
+
contentWidth
|
|
8382
|
+
);
|
|
8383
|
+
clearSelection();
|
|
8384
|
+
if (textToCopy.length > 0) {
|
|
8385
|
+
try {
|
|
8386
|
+
await writeClipboard2(textToCopy);
|
|
8387
|
+
emitCommandOutput(t("copiedSelection"));
|
|
8388
|
+
} catch (error) {
|
|
8389
|
+
emitCommandOutput(
|
|
8390
|
+
`[nolo] ${t("copyFailed")}: ${toErrorMessage(error)}`
|
|
8391
|
+
);
|
|
8392
|
+
}
|
|
8393
|
+
}
|
|
8394
|
+
paintFrame(buffer);
|
|
8395
|
+
return;
|
|
8396
|
+
}
|
|
8397
|
+
if (selectionState.anchor) {
|
|
8398
|
+
clearSelection();
|
|
8399
|
+
}
|
|
8400
|
+
if (buffer.length > 0) {
|
|
8401
|
+
buffer = "";
|
|
8402
|
+
cursorPos = 0;
|
|
8403
|
+
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8404
|
+
emitCommandOutput(t("ctrlCClearedDraft"));
|
|
8405
|
+
return;
|
|
8406
|
+
}
|
|
8407
|
+
if (lastCtrlCDoublePress !== null && now - lastCtrlCDoublePress <= 1e3) {
|
|
8408
|
+
lastCtrlCDoublePress = null;
|
|
8409
|
+
fixedInput.disable();
|
|
8410
|
+
finish();
|
|
8411
|
+
return;
|
|
8412
|
+
}
|
|
8413
|
+
lastCtrlCDoublePress = now;
|
|
8414
|
+
emitCommandOutput(t("ctrlCExitHint"));
|
|
8415
|
+
};
|
|
8416
|
+
const handleBusyLocalSlash = async (submittedText, busySlashCommand) => {
|
|
8417
|
+
releaseCollapsedPasteReferences(submittedText, pasteStore);
|
|
8418
|
+
buffer = "";
|
|
8419
|
+
cursorPos = 0;
|
|
8420
|
+
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8421
|
+
const beforeAgentKey = state.agentKey;
|
|
8422
|
+
const res = handleTuiInput(submittedText, state);
|
|
8423
|
+
if (res.action?.type === "theme-refresh") {
|
|
8424
|
+
state = res.nextState;
|
|
8425
|
+
const detected = await detectTerminalBackground({
|
|
8426
|
+
stdin: input,
|
|
8427
|
+
stdout: output,
|
|
8428
|
+
allowSystemFallback: true
|
|
8429
|
+
});
|
|
8430
|
+
let refreshMsg = "";
|
|
8431
|
+
if (detected && applyDetectedBackground(detected)) {
|
|
8432
|
+
refreshMsg = t("themeRefreshed", detected.brightness);
|
|
8433
|
+
} else if (detected) {
|
|
8434
|
+
refreshMsg = t("themeRefreshed", detected.brightness);
|
|
8435
|
+
} else {
|
|
8436
|
+
refreshMsg = t("themeRefreshFailed");
|
|
8437
|
+
}
|
|
8438
|
+
if (refreshMsg) {
|
|
8439
|
+
output.write(`${refreshMsg}
|
|
8440
|
+
`);
|
|
8441
|
+
}
|
|
8442
|
+
} else if (res.action) {
|
|
8443
|
+
output.write(
|
|
8444
|
+
"Model picker isn't available while a reply is running. Use `/switch <name>` to switch now (takes effect on the next turn), or wait for the reply to finish.\n"
|
|
8445
|
+
);
|
|
8446
|
+
} else {
|
|
8447
|
+
state = res.nextState;
|
|
8448
|
+
let msg = res.output;
|
|
8449
|
+
if (busySlashCommand === "/switch" && persistExplicitAgentSwitch(beforeAgentKey)) {
|
|
8450
|
+
const hint = "Note: the new model takes effect on the next turn. Switching models may consume more tokens because the conversation context is re-sent to the new model.";
|
|
8451
|
+
msg = msg ? `${msg}
|
|
8452
|
+
${hint}` : hint;
|
|
8453
|
+
}
|
|
8454
|
+
if (msg) {
|
|
8455
|
+
output.write(`${msg}
|
|
8456
|
+
`);
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
if (busySlashCommand === "/theme") {
|
|
8460
|
+
renderHistoryToOutput();
|
|
8461
|
+
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8462
|
+
}
|
|
8463
|
+
};
|
|
8274
8464
|
const handleInputToken = async (sequence) => {
|
|
8275
8465
|
if (done) return;
|
|
8276
8466
|
if (modalOwnsKeyboard) {
|
|
@@ -8293,7 +8483,7 @@ ${merged}` : merged;
|
|
|
8293
8483
|
t(busy ? "flushQueuedBusyHint" : "flushQueuedIdleHint", String(totalCount))
|
|
8294
8484
|
);
|
|
8295
8485
|
if (busy) {
|
|
8296
|
-
preemptAndAbortForDrain(chatQueueBinding);
|
|
8486
|
+
preemptAndAbortForDrain(chatQueueBinding, activeTurnAbort);
|
|
8297
8487
|
return;
|
|
8298
8488
|
}
|
|
8299
8489
|
buffer = "";
|
|
@@ -8400,59 +8590,7 @@ ${merged}` : merged;
|
|
|
8400
8590
|
return;
|
|
8401
8591
|
}
|
|
8402
8592
|
if (sequence === "") {
|
|
8403
|
-
|
|
8404
|
-
const stopBinding = chatQueueBinding;
|
|
8405
|
-
if (stopBinding && stopBinding.queueLength() > 0) {
|
|
8406
|
-
stopBinding.preemptForStop();
|
|
8407
|
-
}
|
|
8408
|
-
activityIndicator.markStopping();
|
|
8409
|
-
activeTurnAbort.abort();
|
|
8410
|
-
return;
|
|
8411
|
-
}
|
|
8412
|
-
const now = Date.now();
|
|
8413
|
-
const hasSelection = selectionState.anchor !== null && selectionState.head !== null && !areSelectionPointsEqual(selectionState.anchor, selectionState.head);
|
|
8414
|
-
if (hasSelection) {
|
|
8415
|
-
const tty = output;
|
|
8416
|
-
const columns = tty.columns ?? 80;
|
|
8417
|
-
const contentWidth = Math.max(1, columns - 1);
|
|
8418
|
-
const textToCopy = extractSelectedText(
|
|
8419
|
-
history,
|
|
8420
|
-
selectionState.anchor,
|
|
8421
|
-
selectionState.head,
|
|
8422
|
-
contentWidth
|
|
8423
|
-
);
|
|
8424
|
-
clearSelection();
|
|
8425
|
-
if (textToCopy.length > 0) {
|
|
8426
|
-
try {
|
|
8427
|
-
await writeClipboard2(textToCopy);
|
|
8428
|
-
emitCommandOutput(t("copiedSelection"));
|
|
8429
|
-
} catch (error) {
|
|
8430
|
-
emitCommandOutput(
|
|
8431
|
-
`[nolo] ${t("copyFailed")}: ${toErrorMessage(error)}`
|
|
8432
|
-
);
|
|
8433
|
-
}
|
|
8434
|
-
}
|
|
8435
|
-
paintFrame(buffer);
|
|
8436
|
-
return;
|
|
8437
|
-
}
|
|
8438
|
-
if (selectionState.anchor) {
|
|
8439
|
-
clearSelection();
|
|
8440
|
-
}
|
|
8441
|
-
if (buffer.length > 0) {
|
|
8442
|
-
buffer = "";
|
|
8443
|
-
cursorPos = 0;
|
|
8444
|
-
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8445
|
-
emitCommandOutput(t("ctrlCClearedDraft"));
|
|
8446
|
-
return;
|
|
8447
|
-
}
|
|
8448
|
-
if (lastCtrlCDoublePress !== null && now - lastCtrlCDoublePress <= 1e3) {
|
|
8449
|
-
lastCtrlCDoublePress = null;
|
|
8450
|
-
fixedInput.disable();
|
|
8451
|
-
finish();
|
|
8452
|
-
return;
|
|
8453
|
-
}
|
|
8454
|
-
lastCtrlCDoublePress = now;
|
|
8455
|
-
emitCommandOutput(t("ctrlCExitHint"));
|
|
8593
|
+
await handleCtrlCKey(busyLock);
|
|
8456
8594
|
return;
|
|
8457
8595
|
}
|
|
8458
8596
|
if (selectionState.anchor) {
|
|
@@ -8535,56 +8673,11 @@ ${merged}` : merged;
|
|
|
8535
8673
|
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
8536
8674
|
const isBusyLocalSlash = busySlashCommand === "/context" || busySlashCommand === "/ctx" || busySlashCommand === "/switch" || busySlashCommand === "/theme" || busySlashCommand === "/density" || busySlashCommand === "/runtime" || busySlashCommand === "/tools" || busySlashCommand === "/thinking" || busySlashCommand === "/auto" || busySlashCommand === "/tasks" || busySlashCommand === "/jobs" || busySlashCommand === "/procs" || busySlashCommand === "/agents" || busySlashCommand === "/doc" || busySlashCommand === "/skill" || busySlashCommand === "/customize" || busySlashCommand === "/login" || busySlashCommand === "/profile" || busySlashCommand === "/version";
|
|
8537
8675
|
if (isBusyLocalSlash) {
|
|
8538
|
-
|
|
8539
|
-
buffer = "";
|
|
8540
|
-
cursorPos = 0;
|
|
8541
|
-
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8542
|
-
const beforeAgentKey = state.agentKey;
|
|
8543
|
-
const res = handleTuiInput(submittedText, state);
|
|
8544
|
-
if (res.action?.type === "theme-refresh") {
|
|
8545
|
-
state = res.nextState;
|
|
8546
|
-
const detected = await detectTerminalBackground({
|
|
8547
|
-
stdin: input,
|
|
8548
|
-
stdout: output,
|
|
8549
|
-
allowSystemFallback: true
|
|
8550
|
-
});
|
|
8551
|
-
let refreshMsg = "";
|
|
8552
|
-
if (detected && applyDetectedBackground(detected)) {
|
|
8553
|
-
refreshMsg = t("themeRefreshed", detected.brightness);
|
|
8554
|
-
} else if (detected) {
|
|
8555
|
-
refreshMsg = t("themeRefreshed", detected.brightness);
|
|
8556
|
-
} else {
|
|
8557
|
-
refreshMsg = t("themeRefreshFailed");
|
|
8558
|
-
}
|
|
8559
|
-
if (refreshMsg) {
|
|
8560
|
-
output.write(`${refreshMsg}
|
|
8561
|
-
`);
|
|
8562
|
-
}
|
|
8563
|
-
} else if (res.action) {
|
|
8564
|
-
output.write(
|
|
8565
|
-
"Model picker isn't available while a reply is running. Use `/switch <name>` to switch now (takes effect on the next turn), or wait for the reply to finish.\n"
|
|
8566
|
-
);
|
|
8567
|
-
} else {
|
|
8568
|
-
state = res.nextState;
|
|
8569
|
-
let msg = res.output;
|
|
8570
|
-
if (busySlashCommand === "/switch" && persistExplicitAgentSwitch(beforeAgentKey)) {
|
|
8571
|
-
const hint = "Note: the new model takes effect on the next turn. Switching models may consume more tokens because the conversation context is re-sent to the new model.";
|
|
8572
|
-
msg = msg ? `${msg}
|
|
8573
|
-
${hint}` : hint;
|
|
8574
|
-
}
|
|
8575
|
-
if (msg) {
|
|
8576
|
-
output.write(`${msg}
|
|
8577
|
-
`);
|
|
8578
|
-
}
|
|
8579
|
-
}
|
|
8580
|
-
if (busySlashCommand === "/theme") {
|
|
8581
|
-
renderHistoryToOutput();
|
|
8582
|
-
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos);
|
|
8583
|
-
}
|
|
8676
|
+
await handleBusyLocalSlash(submittedText, busySlashCommand);
|
|
8584
8677
|
return;
|
|
8585
8678
|
}
|
|
8586
8679
|
const { actionGateHandler, confirmDestructiveAction } = buildInteractiveTurnHandlers();
|
|
8587
|
-
const binding = ensureChatQueueBinding(actionGateHandler, confirmDestructiveAction);
|
|
8680
|
+
const binding = ensureChatQueueBinding(turnCtx, actionGateHandler, confirmDestructiveAction);
|
|
8588
8681
|
const decision = binding.resolveSubmit({
|
|
8589
8682
|
text: submittedText,
|
|
8590
8683
|
isRunning: true
|
|
@@ -8596,13 +8689,13 @@ ${hint}` : hint;
|
|
|
8596
8689
|
fixedInput.repaint(buffer, cursorPos);
|
|
8597
8690
|
} else if (decision.kind === "queue-blocked") {
|
|
8598
8691
|
} else if (decision.kind === "noop" && !submittedText.trim() && binding.queueLength() > 0) {
|
|
8599
|
-
preemptAndAbortForDrain(binding);
|
|
8692
|
+
preemptAndAbortForDrain(binding, activeTurnAbort);
|
|
8600
8693
|
}
|
|
8601
8694
|
return;
|
|
8602
8695
|
}
|
|
8603
8696
|
if (!submittedText.trim() && chatQueueBinding && chatQueueBinding.queueLength() > 0) {
|
|
8604
8697
|
const { actionGateHandler, confirmDestructiveAction } = buildInteractiveTurnHandlers();
|
|
8605
|
-
const manualBinding = ensureChatQueueBinding(actionGateHandler, confirmDestructiveAction);
|
|
8698
|
+
const manualBinding = ensureChatQueueBinding(turnCtx, actionGateHandler, confirmDestructiveAction);
|
|
8606
8699
|
const drainedText = manualBinding.drainHeadForManualTurn();
|
|
8607
8700
|
if (drainedText !== null) {
|
|
8608
8701
|
buffer = "";
|