@co0ontty/wand 4.89.5 → 4.90.0
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/README.md +5 -3
- package/dist/agent-dispatch.js +4 -9
- package/dist/ai-team-employee-binding.js +10 -9
- package/dist/ai-team-runner.d.ts +2 -1
- package/dist/ai-team-runner.js +38 -2
- package/dist/ai-team-types.js +3 -2
- package/dist/ai-text-runner.d.ts +61 -0
- package/dist/ai-text-runner.js +653 -0
- package/dist/avatar-input.d.ts +2 -0
- package/dist/avatar-input.js +19 -0
- package/dist/bounded-process-output.d.ts +5 -0
- package/dist/bounded-process-output.js +9 -0
- package/dist/build-info.json +3 -3
- package/dist/command-error.d.ts +6 -0
- package/dist/command-error.js +8 -0
- package/dist/config.js +11 -42
- package/dist/conversation-service.d.ts +12 -2
- package/dist/conversation-service.js +104 -25
- package/dist/conversation-session-preview.d.ts +2 -0
- package/dist/conversation-session-preview.js +4 -0
- package/dist/decision-client.js +22 -6
- package/dist/decision-expert-employee.js +2 -2
- package/dist/decision-expert-identity.d.ts +1 -1
- package/dist/decision-expert-identity.js +1 -1
- package/dist/decision-expert-service.d.ts +1 -0
- package/dist/decision-expert-service.js +82 -76
- package/dist/decision-hardware.js +4 -3
- package/dist/decision-types.d.ts +4 -0
- package/dist/decision-types.js +4 -0
- package/dist/deployment-lock.d.ts +13 -0
- package/dist/deployment-lock.js +189 -0
- package/dist/employee-text.js +1 -1
- package/dist/fixed-employee-avatar.d.ts +7 -0
- package/dist/fixed-employee-avatar.js +13 -0
- package/dist/git-quick-commit.d.ts +5 -40
- package/dist/git-quick-commit.js +8 -636
- package/dist/hr-employee-identity.d.ts +5 -0
- package/dist/hr-employee-identity.js +5 -0
- package/dist/hr-employee.d.ts +5 -0
- package/dist/hr-employee.js +21 -0
- package/dist/middleware/path-safety.js +1 -1
- package/dist/milestone-scope.js +1 -1
- package/dist/model-auto-assign.d.ts +1 -1
- package/dist/model-auto-assign.js +1 -1
- package/dist/models.d.ts +4 -0
- package/dist/models.js +21 -1
- package/dist/npm-update-utils.js +5 -44
- package/dist/pi-auto-resources.js +6 -3
- package/dist/plush-avatar.d.ts +10 -1
- package/dist/plush-avatar.js +13 -1
- package/dist/plush-cat-appearance.d.ts +97 -0
- package/dist/plush-cat-appearance.js +118 -0
- package/dist/plush-cat-whiskers.d.ts +6 -0
- package/dist/plush-cat-whiskers.js +42 -0
- package/dist/process-manager.d.ts +22 -21
- package/dist/process-manager.js +49 -83
- package/dist/prompt-optimizer.d.ts +1 -1
- package/dist/prompt-optimizer.js +1 -1
- package/dist/render-host.js +1 -19
- package/dist/scheduled-task-service.d.ts +41 -0
- package/dist/scheduled-task-service.js +294 -0
- package/dist/scheduled-task-state.d.ts +11 -0
- package/dist/scheduled-task-state.js +65 -0
- package/dist/scheduled-task-time.d.ts +4 -0
- package/dist/scheduled-task-time.js +82 -0
- package/dist/scheduled-task-types.d.ts +71 -0
- package/dist/scheduled-task-types.js +1 -0
- package/dist/server-ai-team-routes.js +3 -17
- package/dist/server-employee-routes.d.ts +3 -0
- package/dist/server-employee-routes.js +20 -38
- package/dist/server-file-routes.js +44 -1
- package/dist/server-pi-recommendation-routes.js +13 -4
- package/dist/server-request.d.ts +2 -0
- package/dist/server-request.js +9 -0
- package/dist/server-resume-routes.js +1 -1
- package/dist/server-scheduled-task-routes.d.ts +4 -0
- package/dist/server-scheduled-task-routes.js +34 -0
- package/dist/server-session-routes.d.ts +5 -13
- package/dist/server-session-routes.js +35 -70
- package/dist/server-task-routes.d.ts +6 -21
- package/dist/server-task-routes.js +25 -120
- package/dist/server-team-dispatch-routes.js +12 -2
- package/dist/server-workspace-routes.d.ts +1 -1
- package/dist/server-workspace-routes.js +33 -78
- package/dist/server.js +55 -20
- package/dist/session-model.d.ts +15 -0
- package/dist/session-model.js +23 -0
- package/dist/session-registry.d.ts +5 -1
- package/dist/session-registry.js +20 -11
- package/dist/session-request.d.ts +9 -0
- package/dist/session-request.js +27 -0
- package/dist/session-topic.d.ts +1 -1
- package/dist/session-topic.js +1 -1
- package/dist/session-transport.d.ts +3 -1
- package/dist/session-transport.js +11 -5
- package/dist/silicon-employee-draft.d.ts +2 -2
- package/dist/silicon-employee-draft.js +3 -3
- package/dist/socket-probe.d.ts +2 -0
- package/dist/socket-probe.js +20 -0
- package/dist/storage-schedules.d.ts +20 -0
- package/dist/storage-schedules.js +78 -0
- package/dist/storage-schema.d.ts +3 -0
- package/dist/storage-schema.js +702 -0
- package/dist/storage.d.ts +42 -8
- package/dist/storage.js +182 -715
- package/dist/structured-claude-adapter.js +12 -0
- package/dist/structured-claude-protocol.d.ts +4 -0
- package/dist/structured-claude-protocol.js +18 -4
- package/dist/structured-codex-adapter.js +11 -0
- package/dist/structured-exec-pump.js +79 -38
- package/dist/structured-failure.d.ts +21 -0
- package/dist/structured-failure.js +14 -0
- package/dist/structured-gemini-adapter.js +12 -2
- package/dist/structured-grok-adapter.js +12 -2
- package/dist/structured-opencode-adapter.js +8 -1
- package/dist/structured-qoder-adapter.js +14 -0
- package/dist/structured-session-manager.d.ts +13 -18
- package/dist/structured-session-manager.js +147 -517
- package/dist/system-employee.d.ts +1 -1
- package/dist/system-employee.js +1 -1
- package/dist/task-archive-policy.js +1 -1
- package/dist/task-read-model.d.ts +27 -0
- package/dist/task-read-model.js +47 -0
- package/dist/task-retention.d.ts +1 -1
- package/dist/task-retention.js +1 -1
- package/dist/task-title-service.d.ts +30 -0
- package/dist/task-title-service.js +122 -0
- package/dist/task-title.d.ts +1 -1
- package/dist/task-title.js +1 -1
- package/dist/terminal-daemon-client.js +1 -18
- package/dist/user-memory.js +1 -1
- package/dist/web-ui/asset-runtime.d.ts +12 -0
- package/dist/web-ui/asset-runtime.js +6 -0
- package/dist/web-ui/composer-avatar-activity.d.ts +6 -0
- package/dist/web-ui/composer-avatar-activity.js +29 -0
- package/dist/web-ui/content/ai-teams.js +13 -13
- package/dist/web-ui/content/module-manifest.json +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chat-render-PY6DIXNZ.js +24 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-2YZLCGYN.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-6CFHW3FA.js +111 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-6XQEBIEX.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-DDSO7OX7.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-G3CXNMA2.js +20 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-LGVAPHRS.js +36 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-NURCNMRU.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-PCMFGZKX.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-QRNA4D7E.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-TMRPHNJO.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-WC7RK7LP.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-YOXXNXOX.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-YX475LXO.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/employee-card-MDWKU4V3.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-56WPSON2.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-5QOHKHNC.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-AWIJ5L2K.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-BOZLGIT5.js +69 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-EZV22Q7Y.js +4 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-IW43Z5ZF.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-JT7NIUQL.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-JWEIDB55.js +3 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-OU5TRYH6.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-PRSTCPVE.js +5 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-TWPJI3HE.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-WZGJSNML.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-X6KQVFD6.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-YKCQFMQR.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-bridge-2LZX6UUZ.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/library-bridge-MQFJGTGY.js +4 -0
- package/dist/web-ui/content/modules/5478be410b112154/page-T3VUCU2W.js +3 -0
- package/dist/web-ui/content/modules/5478be410b112154/panel-HJBGBBPY.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/runtime.js +920 -0
- package/dist/web-ui/content/modules/5478be410b112154/sha256-ANXV72UC.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/task-board-host-AVMDIHIV.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/workspace-agent-picker-KI7QVSK3.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/workspace-window-L542FGP2.js +1 -0
- package/dist/web-ui/content/plush-avatar.js +177 -177
- package/dist/web-ui/content/scripts.js +1 -994
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/content/tailwind.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +32 -0
- package/dist/web-ui/embedded-assets.js +10 -8
- package/dist/web-ui/markdown.d.ts +3 -2
- package/dist/web-ui/markdown.js +61 -48
- package/dist/web-ui/message-file-target.d.ts +13 -0
- package/dist/web-ui/message-file-target.js +85 -0
- package/dist/web-ui/provider-identity.d.ts +1 -1
- package/dist/web-ui/provider-identity.js +3 -4
- package/dist/web-ui/react/local-preview/controller.d.ts +2 -0
- package/dist/web-ui/react/local-preview/controller.js +12 -0
- package/dist/web-ui/scripts.d.ts +10 -0
- package/dist/web-ui/scripts.js +42 -5
- package/package.json +6 -3
- package/browser-extension/icons/wand-128.png +0 -0
- package/browser-extension/icons/wand-16.png +0 -0
- package/browser-extension/icons/wand-32.png +0 -0
- package/browser-extension/icons/wand-48.png +0 -0
- package/dist/web-ui/content/licenses/codex-LICENSE.txt +0 -21
|
@@ -6,6 +6,7 @@ import { startStructuredCli } from "./structured-exec-pump.js";
|
|
|
6
6
|
import { buildLanguageDirective, buildManagedAutonomyDirective } from "./language-prompt.js";
|
|
7
7
|
import { thinkingEffortToClaudeCliEffort } from "./structured-provider-common.js";
|
|
8
8
|
import { ClaudeCliProtocolReducer } from "./structured-claude-protocol.js";
|
|
9
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
9
10
|
const ROOT_FALLBACK_ALLOWED_TOOLS = [
|
|
10
11
|
"Bash", "Edit", "Write", "Read", "Glob", "Grep", "NotebookEdit", "WebFetch", "WebSearch",
|
|
11
12
|
];
|
|
@@ -143,6 +144,7 @@ export class ClaudeCliRunner {
|
|
|
143
144
|
const reducer = new ClaudeCliProtocolReducer(context.session);
|
|
144
145
|
let killedForQuestion = false;
|
|
145
146
|
let stdoutTail = "";
|
|
147
|
+
let unparsedStdout = false;
|
|
146
148
|
return startStructuredCli({
|
|
147
149
|
sessionId: context.session.id,
|
|
148
150
|
file: "claude",
|
|
@@ -164,6 +166,7 @@ export class ClaudeCliRunner {
|
|
|
164
166
|
event = JSON.parse(trimmed);
|
|
165
167
|
}
|
|
166
168
|
catch {
|
|
169
|
+
unparsedStdout = true;
|
|
167
170
|
return;
|
|
168
171
|
}
|
|
169
172
|
if (event && typeof event === "object" && !Array.isArray(event)) {
|
|
@@ -191,6 +194,15 @@ export class ClaudeCliRunner {
|
|
|
191
194
|
primaryError: reducer.errorText,
|
|
192
195
|
stopReason: killedForQuestion ? "ask-user-question" : undefined,
|
|
193
196
|
spawnError,
|
|
197
|
+
...cliUnacceptedFacts({
|
|
198
|
+
state: reducer.state,
|
|
199
|
+
primaryError: reducer.errorText,
|
|
200
|
+
protocolError: reducer.errorResultObserved,
|
|
201
|
+
unparsedStdout,
|
|
202
|
+
signal,
|
|
203
|
+
progressed: reducer.assistantWorkObserved,
|
|
204
|
+
...(spawnError ? { spawnError } : {}),
|
|
205
|
+
}),
|
|
194
206
|
}),
|
|
195
207
|
});
|
|
196
208
|
}
|
|
@@ -22,6 +22,10 @@ export declare class ClaudeCliProtocolReducer {
|
|
|
22
22
|
askUserQuestionDetected: boolean;
|
|
23
23
|
/** result 事件带 is_error 时的说明(如「API Error: 503 …」),作为这一轮的主错误。 */
|
|
24
24
|
errorText: string | null;
|
|
25
|
+
/** 协议里出现过带 is_error 的 result 事件;没有本轮助手内容时才是可降级的执行前拒绝。 */
|
|
26
|
+
errorResultObserved: boolean;
|
|
27
|
+
/** 本轮真正跑出来的助手/工具内容,错误回显不算。 */
|
|
28
|
+
assistantWorkObserved: boolean;
|
|
25
29
|
private readonly blocksByKey;
|
|
26
30
|
private readonly keyOrder;
|
|
27
31
|
private readonly taskMetaRegistry;
|
|
@@ -123,6 +123,10 @@ export class ClaudeCliProtocolReducer {
|
|
|
123
123
|
askUserQuestionDetected = false;
|
|
124
124
|
/** result 事件带 is_error 时的说明(如「API Error: 503 …」),作为这一轮的主错误。 */
|
|
125
125
|
errorText = null;
|
|
126
|
+
/** 协议里出现过带 is_error 的 result 事件;没有本轮助手内容时才是可降级的执行前拒绝。 */
|
|
127
|
+
errorResultObserved = false;
|
|
128
|
+
/** 本轮真正跑出来的助手/工具内容,错误回显不算。 */
|
|
129
|
+
assistantWorkObserved = false;
|
|
126
130
|
blocksByKey = new Map();
|
|
127
131
|
keyOrder = [];
|
|
128
132
|
taskMetaRegistry = new Map();
|
|
@@ -150,8 +154,10 @@ export class ClaudeCliProtocolReducer {
|
|
|
150
154
|
const stamped = parentId === null
|
|
151
155
|
? stampSelfTask(extracted.content, this.taskMetaRegistry)
|
|
152
156
|
: tagSubagentBlocks(extracted.content, parentId, this.taskMetaRegistry);
|
|
153
|
-
if (stamped.length > 0)
|
|
157
|
+
if (stamped.length > 0) {
|
|
158
|
+
this.assistantWorkObserved = true;
|
|
154
159
|
this.upsertBlocks(key, stamped);
|
|
160
|
+
}
|
|
155
161
|
if (!managed && extracted.content.some((block) => block.type === "tool_use" && block.name === "AskUserQuestion")) {
|
|
156
162
|
this.askUserQuestionDetected = true;
|
|
157
163
|
}
|
|
@@ -181,15 +187,23 @@ export class ClaudeCliProtocolReducer {
|
|
|
181
187
|
const stamped = parentId === null
|
|
182
188
|
? stampParentTaskResults(collected, this.taskMetaRegistry)
|
|
183
189
|
: tagSubagentBlocks(collected, parentId, this.taskMetaRegistry);
|
|
184
|
-
if (stamped.length > 0)
|
|
190
|
+
if (stamped.length > 0) {
|
|
191
|
+
this.assistantWorkObserved = true;
|
|
185
192
|
this.upsertBlocks(`tool_result:${this.toolResultSequence++}`, stamped);
|
|
193
|
+
}
|
|
186
194
|
return true;
|
|
187
195
|
}
|
|
188
196
|
if (event.type === "result") {
|
|
189
197
|
if (typeof event.result === "string")
|
|
190
198
|
this.state.result = event.result.trim();
|
|
191
|
-
if (event.is_error === true
|
|
192
|
-
this.
|
|
199
|
+
if (event.is_error === true) {
|
|
200
|
+
this.errorResultObserved = true;
|
|
201
|
+
const detail = this.state.result
|
|
202
|
+
|| (typeof event.subtype === "string" && event.subtype && event.subtype !== "success"
|
|
203
|
+
? `Claude 以 ${event.subtype} 结束,未产生任何输出。` : "");
|
|
204
|
+
if (detail)
|
|
205
|
+
this.errorText = detail;
|
|
206
|
+
}
|
|
193
207
|
this.state.model = extractClaudeModelName(event.modelUsage && typeof event.modelUsage === "object"
|
|
194
208
|
? event.modelUsage
|
|
195
209
|
: undefined) ?? this.state.model;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { startStructuredCli } from "./structured-exec-pump.js";
|
|
3
3
|
import { CodexProtocolReducer } from "./structured-codex-protocol.js";
|
|
4
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
4
5
|
import { whichSync } from "./path-repair.js";
|
|
5
6
|
import { thinkingEffortToCodexReasoningEffort, promptWithSystemFallback } from "./structured-provider-common.js";
|
|
6
7
|
/** Build the stable CLI contract for a structured Codex turn. */
|
|
@@ -43,6 +44,7 @@ export class CodexRunner {
|
|
|
43
44
|
const args = buildCodexArgs(context.session);
|
|
44
45
|
const file = whichSync("codex", { env: context.env }) ?? "codex";
|
|
45
46
|
const reducer = new CodexProtocolReducer(context.session);
|
|
47
|
+
let unparsedStdout = false;
|
|
46
48
|
return startStructuredCli({
|
|
47
49
|
sessionId: context.session.id,
|
|
48
50
|
file,
|
|
@@ -65,6 +67,7 @@ export class CodexRunner {
|
|
|
65
67
|
event = JSON.parse(trimmed);
|
|
66
68
|
}
|
|
67
69
|
catch {
|
|
70
|
+
unparsedStdout = true;
|
|
68
71
|
return;
|
|
69
72
|
}
|
|
70
73
|
if (event && typeof event === "object" && !Array.isArray(event)) {
|
|
@@ -81,6 +84,14 @@ export class CodexRunner {
|
|
|
81
84
|
primaryError: reducer.primaryError,
|
|
82
85
|
errors: reducer.errors,
|
|
83
86
|
spawnError,
|
|
87
|
+
...cliUnacceptedFacts({
|
|
88
|
+
state: reducer.state,
|
|
89
|
+
primaryError: reducer.primaryError,
|
|
90
|
+
protocolError: !!reducer.primaryError,
|
|
91
|
+
unparsedStdout,
|
|
92
|
+
signal,
|
|
93
|
+
...(spawnError ? { spawnError } : {}),
|
|
94
|
+
}),
|
|
84
95
|
}),
|
|
85
96
|
});
|
|
86
97
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { appendDiagnosticTail, MAX_PROTOCOL_LINE_BYTES } from "./bounded-process-output.js";
|
|
2
3
|
import { createUtf8TextDecoder, } from "./structured-exec-host.js";
|
|
3
4
|
import { signalNameFromNumber } from "./signal-utils.js";
|
|
4
5
|
export function startStructuredCli(options) {
|
|
@@ -8,41 +9,87 @@ export function startStructuredCli(options) {
|
|
|
8
9
|
state: options.createState(),
|
|
9
10
|
stderr: "",
|
|
10
11
|
observer,
|
|
11
|
-
requestStop: () =>
|
|
12
|
+
requestStop: () => requestStop(),
|
|
12
13
|
};
|
|
13
14
|
let source = null;
|
|
14
|
-
let sourceReady;
|
|
15
15
|
let lineBuffer = "";
|
|
16
|
+
let lineBytes = 0;
|
|
16
17
|
let settled = false;
|
|
18
|
+
let stopRequested = false;
|
|
19
|
+
let stopDelivered = false;
|
|
20
|
+
// A pending spawn has no cancellable handle yet. Remember one request and
|
|
21
|
+
// deliver it once when ready; never install a self-referential placeholder.
|
|
22
|
+
function interruptSource() {
|
|
23
|
+
if (!source || stopDelivered)
|
|
24
|
+
return;
|
|
25
|
+
stopDelivered = true;
|
|
26
|
+
try {
|
|
27
|
+
source.interrupt();
|
|
28
|
+
}
|
|
29
|
+
catch { /* best-effort interruption */ }
|
|
30
|
+
}
|
|
31
|
+
function requestStop() {
|
|
32
|
+
if (settled || stopRequested)
|
|
33
|
+
return;
|
|
34
|
+
stopRequested = true;
|
|
35
|
+
interruptSource();
|
|
36
|
+
}
|
|
17
37
|
let resolveCompletion;
|
|
18
|
-
|
|
38
|
+
let rejectCompletion;
|
|
39
|
+
const completion = new Promise((resolve, reject) => {
|
|
19
40
|
resolveCompletion = resolve;
|
|
41
|
+
rejectCompletion = reject;
|
|
20
42
|
});
|
|
21
|
-
const finish = (exitCode, signal, spawnError) => {
|
|
43
|
+
const finish = (exitCode, signal, spawnError, protocolError) => {
|
|
22
44
|
if (settled)
|
|
23
45
|
return;
|
|
24
46
|
settled = true;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
try {
|
|
48
|
+
if (!protocolError && lineBuffer.trim())
|
|
49
|
+
options.processLine(lineBuffer, ctx);
|
|
50
|
+
const result = options.finalize(ctx, exitCode, signal, spawnError);
|
|
51
|
+
resolveCompletion(protocolError ? { ...result, exitCode: 1, primaryError: protocolError.message,
|
|
52
|
+
retryForbidden: true, failure: { kind: "runtime", delivery: "unknown", retryable: false } } : result);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
rejectCompletion(error);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
lineBuffer = "";
|
|
59
|
+
lineBytes = 0;
|
|
60
|
+
}
|
|
29
61
|
};
|
|
30
62
|
const handleStdoutText = (text) => {
|
|
31
|
-
if (!text || !observer.isActive())
|
|
63
|
+
if (settled || !text || !observer.isActive())
|
|
32
64
|
return;
|
|
33
65
|
observer.onStdout?.(text);
|
|
34
66
|
options.onStdoutText?.(text);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
try {
|
|
68
|
+
const parts = text.split("\n");
|
|
69
|
+
for (let index = 0; index < parts.length; index++) {
|
|
70
|
+
const part = parts[index];
|
|
71
|
+
lineBytes += Buffer.byteLength(part, "utf8");
|
|
72
|
+
if (lineBytes > MAX_PROTOCOL_LINE_BYTES)
|
|
73
|
+
throw new Error("CLI 协议单行超过 8 MiB 上限;本轮已停止,送达结果不能据此推定为未接受。");
|
|
74
|
+
lineBuffer += part;
|
|
75
|
+
if (index < parts.length - 1) {
|
|
76
|
+
options.processLine(lineBuffer, ctx);
|
|
77
|
+
lineBuffer = "";
|
|
78
|
+
lineBytes = 0;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// Settle the failure before kill can synchronously deliver a close event.
|
|
84
|
+
finish(1, null, undefined, error instanceof Error ? error : new Error(String(error)));
|
|
85
|
+
interruptSource();
|
|
86
|
+
}
|
|
40
87
|
};
|
|
41
88
|
const handleStderrText = (text) => {
|
|
42
|
-
if (!text || !observer.isActive())
|
|
89
|
+
if (settled || !text || !observer.isActive())
|
|
43
90
|
return;
|
|
44
91
|
observer.onStderr?.(text);
|
|
45
|
-
ctx.stderr
|
|
92
|
+
ctx.stderr = appendDiagnosticTail(ctx.stderr, text);
|
|
46
93
|
};
|
|
47
94
|
const host = options.execHost;
|
|
48
95
|
if (host?.persistent) {
|
|
@@ -54,23 +101,23 @@ export function startStructuredCli(options) {
|
|
|
54
101
|
env: options.env,
|
|
55
102
|
...(options.stdinData !== undefined ? { stdinData: options.stdinData } : {}),
|
|
56
103
|
};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
source = { pid: handle.pid, interrupt: () => handle.interrupt() };
|
|
60
|
-
if (pendingInterrupt !== null)
|
|
61
|
-
handle.interrupt(pendingInterrupt);
|
|
62
|
-
wireRemoteHandle(handle, handleStdoutText, handleStderrText, finish);
|
|
63
|
-
}, () => {
|
|
104
|
+
const unavailable = () => {
|
|
105
|
+
source = null;
|
|
64
106
|
// Daemon vanished between health check and spawn; surface as spawn error.
|
|
65
107
|
finish(null, null, Object.assign(new Error(`terminal daemon unavailable for ${options.file}`), { code: "EDAEMON" }));
|
|
66
|
-
});
|
|
67
|
-
source = {
|
|
68
|
-
pid: null,
|
|
69
|
-
interrupt: (signal) => {
|
|
70
|
-
pendingInterrupt = signal ?? "SIGTERM";
|
|
71
|
-
void sourceReady.then(() => source?.interrupt());
|
|
72
|
-
},
|
|
73
108
|
};
|
|
109
|
+
try {
|
|
110
|
+
void host.spawnStructured(request).then((handle) => {
|
|
111
|
+
source = { pid: handle.pid, interrupt: () => handle.interrupt() };
|
|
112
|
+
// Replay and subscribe before applying a pending external cancellation.
|
|
113
|
+
wireRemoteHandle(handle, handleStdoutText, handleStderrText, finish);
|
|
114
|
+
if (stopRequested && !settled)
|
|
115
|
+
interruptSource();
|
|
116
|
+
}, unavailable);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
unavailable();
|
|
120
|
+
}
|
|
74
121
|
}
|
|
75
122
|
else {
|
|
76
123
|
const spawnProcess = options.spawnProcess ?? spawn;
|
|
@@ -87,8 +134,8 @@ export function startStructuredCli(options) {
|
|
|
87
134
|
child.stderr?.on("data", (chunk) => handleStderrText(stderrDecoder.write(chunk)));
|
|
88
135
|
child.on("error", (error) => finish(null, null, error));
|
|
89
136
|
child.stdin?.on("error", (error) => {
|
|
137
|
+
requestStop();
|
|
90
138
|
finish(null, null, error);
|
|
91
|
-
child.kill("SIGTERM");
|
|
92
139
|
});
|
|
93
140
|
child.on("close", (exitCode, signalName) => {
|
|
94
141
|
handleStdoutText(stdoutDecoder.end());
|
|
@@ -97,7 +144,6 @@ export function startStructuredCli(options) {
|
|
|
97
144
|
});
|
|
98
145
|
if (wantsStdin)
|
|
99
146
|
child.stdin?.end(options.stdinData);
|
|
100
|
-
sourceReady = Promise.resolve();
|
|
101
147
|
}
|
|
102
148
|
return {
|
|
103
149
|
args: options.args,
|
|
@@ -106,12 +152,7 @@ export function startStructuredCli(options) {
|
|
|
106
152
|
return source?.pid ?? null;
|
|
107
153
|
},
|
|
108
154
|
completion,
|
|
109
|
-
interrupt:
|
|
110
|
-
try {
|
|
111
|
-
source?.interrupt();
|
|
112
|
-
}
|
|
113
|
-
catch { /* best-effort external interruption */ }
|
|
114
|
-
},
|
|
155
|
+
interrupt: requestStop,
|
|
115
156
|
};
|
|
116
157
|
}
|
|
117
158
|
function wireRemoteHandle(handle, onStdout, onStderr, finish) {
|
|
@@ -5,6 +5,27 @@ export interface StructuredFailure {
|
|
|
5
5
|
delivery: "rejected" | "accepted" | "unknown";
|
|
6
6
|
retryable: boolean;
|
|
7
7
|
}
|
|
8
|
+
/** Extra facts a CLI-backed adapter adds to its finalize() result. */
|
|
9
|
+
export type StructuredCliUnacceptedFacts = Pick<StructuredRunnerResult, "inputAccepted" | "rejection">;
|
|
10
|
+
/**
|
|
11
|
+
* An in-band provider protocol error is the only evidence that lets a CLI adapter claim the input
|
|
12
|
+
* was never taken: the reply arrived from the provider itself, this turn produced no block, usage
|
|
13
|
+
* or cost, and stdout held nothing we could not account for as protocol traffic. Anything else —
|
|
14
|
+
* unparsed stdout, a signal, a spawn failure or work already done — stays unknown/accepted so no
|
|
15
|
+
* executed turn can be replayed on another candidate.
|
|
16
|
+
*/
|
|
17
|
+
export declare function cliUnacceptedFacts(input: {
|
|
18
|
+
state: StructuredRunnerTurnState;
|
|
19
|
+
primaryError: string | null;
|
|
20
|
+
/** The provider reported this error inside its own protocol stream. */
|
|
21
|
+
protocolError: boolean;
|
|
22
|
+
/** Stdout carried bytes the adapter could not parse as protocol events. */
|
|
23
|
+
unparsedStdout: boolean;
|
|
24
|
+
signal: NodeJS.Signals | null;
|
|
25
|
+
spawnError?: NodeJS.ErrnoException;
|
|
26
|
+
/** Adapters whose protocol echoes the failure text into `result` state what really ran. */
|
|
27
|
+
progressed?: boolean;
|
|
28
|
+
}): StructuredCliUnacceptedFacts;
|
|
8
29
|
/** Only call for a provider protocol error, never assistant text, stderr or a caught transport error. */
|
|
9
30
|
export declare function classifyProviderRejection(message: string | null | undefined): ProviderRejectionKind | null;
|
|
10
31
|
/** Monotonic observations matter: a final error can replace earlier usage or content. */
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An in-band provider protocol error is the only evidence that lets a CLI adapter claim the input
|
|
3
|
+
* was never taken: the reply arrived from the provider itself, this turn produced no block, usage
|
|
4
|
+
* or cost, and stdout held nothing we could not account for as protocol traffic. Anything else —
|
|
5
|
+
* unparsed stdout, a signal, a spawn failure or work already done — stays unknown/accepted so no
|
|
6
|
+
* executed turn can be replayed on another candidate.
|
|
7
|
+
*/
|
|
8
|
+
export function cliUnacceptedFacts(input) {
|
|
9
|
+
if (!input.protocolError || input.unparsedStdout || input.signal || input.spawnError || !input.primaryError?.trim())
|
|
10
|
+
return {};
|
|
11
|
+
if (input.progressed ?? hasStructuredExecutionProgress(input.state))
|
|
12
|
+
return {};
|
|
13
|
+
return { inputAccepted: false, rejection: classifyProviderRejection(input.primaryError) ?? "model-unavailable" };
|
|
14
|
+
}
|
|
1
15
|
/** Only call for a provider protocol error, never assistant text, stderr or a caught transport error. */
|
|
2
16
|
export function classifyProviderRejection(message) {
|
|
3
17
|
const text = message?.trim() ?? "";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { startStructuredCli } from "./structured-exec-pump.js";
|
|
3
3
|
import { asRecord } from "./structured-content.js";
|
|
4
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
4
5
|
import { promptWithSystemFallback } from "./structured-provider-common.js";
|
|
5
6
|
/**
|
|
6
7
|
* Gemini CLI 的会话写在 `~/.gemini/tmp/<project_hash>/chats/`。ID 找不回来时 headless
|
|
@@ -163,6 +164,8 @@ export class GeminiRunner {
|
|
|
163
164
|
phase: "responding",
|
|
164
165
|
};
|
|
165
166
|
let primaryError = null;
|
|
167
|
+
let protocolError = false;
|
|
168
|
+
let unparsedStdout = false;
|
|
166
169
|
return startStructuredCli({
|
|
167
170
|
sessionId: context.session.id,
|
|
168
171
|
file: "gemini",
|
|
@@ -180,10 +183,16 @@ export class GeminiRunner {
|
|
|
180
183
|
try {
|
|
181
184
|
const event = JSON.parse(line);
|
|
182
185
|
observer.onEvent?.(event);
|
|
183
|
-
|
|
186
|
+
const error = applyGeminiEvent(state, event);
|
|
187
|
+
if (error) {
|
|
188
|
+
primaryError = primaryError ?? error;
|
|
189
|
+
protocolError = true;
|
|
190
|
+
}
|
|
184
191
|
observer.onUpdate(state);
|
|
185
192
|
}
|
|
186
|
-
catch {
|
|
193
|
+
catch {
|
|
194
|
+
unparsedStdout = true; /* Non-protocol stdout is not evidence of a safe refusal. */
|
|
195
|
+
}
|
|
187
196
|
},
|
|
188
197
|
finalize: (ctx, exitCode, signal, spawnError) => ({
|
|
189
198
|
state,
|
|
@@ -192,6 +201,7 @@ export class GeminiRunner {
|
|
|
192
201
|
stderr: ctx.stderr,
|
|
193
202
|
primaryError,
|
|
194
203
|
...(spawnError ? { spawnError } : {}),
|
|
204
|
+
...cliUnacceptedFacts({ state, primaryError, protocolError, unparsedStdout, signal, ...(spawnError ? { spawnError } : {}) }),
|
|
195
205
|
}),
|
|
196
206
|
});
|
|
197
207
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { startStructuredCli } from "./structured-exec-pump.js";
|
|
3
3
|
import { asRecord } from "./structured-content.js";
|
|
4
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
4
5
|
import { systemPromptArgs, thinkingEffortToGrokEffort } from "./structured-provider-common.js";
|
|
5
6
|
function grokText(value) {
|
|
6
7
|
if (typeof value === "string")
|
|
@@ -220,6 +221,8 @@ export class GrokRunner {
|
|
|
220
221
|
model: context.session.selectedModel ?? context.session.structuredState?.model,
|
|
221
222
|
};
|
|
222
223
|
let primaryError = null;
|
|
224
|
+
let protocolError = false;
|
|
225
|
+
let unparsedStdout = false;
|
|
223
226
|
return startStructuredCli({
|
|
224
227
|
sessionId: context.session.id,
|
|
225
228
|
file: "grok",
|
|
@@ -239,13 +242,20 @@ export class GrokRunner {
|
|
|
239
242
|
try {
|
|
240
243
|
const event = JSON.parse(trimmed);
|
|
241
244
|
observer.onEvent?.(event);
|
|
242
|
-
|
|
245
|
+
const error = applyGrokEvent(state, event);
|
|
246
|
+
if (error) {
|
|
247
|
+
primaryError = primaryError ?? error;
|
|
248
|
+
protocolError = true;
|
|
249
|
+
}
|
|
243
250
|
observer.onUpdate(state);
|
|
244
251
|
}
|
|
245
|
-
catch {
|
|
252
|
+
catch {
|
|
253
|
+
unparsedStdout = true; /* Non-protocol stdout is not evidence of a safe refusal. */
|
|
254
|
+
}
|
|
246
255
|
},
|
|
247
256
|
finalize: (ctx, exitCode, signal, spawnError) => ({
|
|
248
257
|
state, exitCode, signal, stderr: ctx.stderr, primaryError, ...(spawnError ? { spawnError } : {}),
|
|
258
|
+
...cliUnacceptedFacts({ state, primaryError, protocolError, unparsedStdout, signal, ...(spawnError ? { spawnError } : {}) }),
|
|
249
259
|
}),
|
|
250
260
|
});
|
|
251
261
|
}
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { startStructuredCli } from "./structured-exec-pump.js";
|
|
4
4
|
import { asRecord } from "./structured-content.js";
|
|
5
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
5
6
|
import { thinkingEffortToOpenCodeVariant, promptWithSystemFallback } from "./structured-provider-common.js";
|
|
6
7
|
function extractStructuredText(value) {
|
|
7
8
|
if (typeof value === "string")
|
|
@@ -129,6 +130,8 @@ export class OpenCodeRunner {
|
|
|
129
130
|
usage: undefined,
|
|
130
131
|
};
|
|
131
132
|
let primaryError = null;
|
|
133
|
+
let protocolError = false;
|
|
134
|
+
let unparsedStdout = false;
|
|
132
135
|
return startStructuredCli({
|
|
133
136
|
sessionId: context.session.id,
|
|
134
137
|
file: "opencode",
|
|
@@ -151,12 +154,15 @@ export class OpenCodeRunner {
|
|
|
151
154
|
event = JSON.parse(trimmed);
|
|
152
155
|
}
|
|
153
156
|
catch {
|
|
157
|
+
unparsedStdout = true;
|
|
154
158
|
return;
|
|
155
159
|
}
|
|
156
160
|
observer.onEvent?.(event);
|
|
157
161
|
const error = applyOpenCodeEvent(state, event);
|
|
158
|
-
if (error)
|
|
162
|
+
if (error) {
|
|
159
163
|
primaryError = error;
|
|
164
|
+
protocolError = true;
|
|
165
|
+
}
|
|
160
166
|
observer.onUpdate(state);
|
|
161
167
|
},
|
|
162
168
|
finalize: (ctx, exitCode, signal, spawnError) => ({
|
|
@@ -166,6 +172,7 @@ export class OpenCodeRunner {
|
|
|
166
172
|
stderr: ctx.stderr,
|
|
167
173
|
primaryError,
|
|
168
174
|
...(spawnError ? { spawnError } : {}),
|
|
175
|
+
...cliUnacceptedFacts({ state, primaryError, protocolError, unparsedStdout, signal, ...(spawnError ? { spawnError } : {}) }),
|
|
169
176
|
}),
|
|
170
177
|
});
|
|
171
178
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { ClaudeCliProtocolReducer } from "./structured-claude-protocol.js";
|
|
3
|
+
import { cliUnacceptedFacts } from "./structured-failure.js";
|
|
3
4
|
import { startStructuredCli } from "./structured-exec-pump.js";
|
|
4
5
|
import { systemPromptArgs, thinkingEffortToQoderEffort } from "./structured-provider-common.js";
|
|
5
6
|
export function buildQoderArgs(session, prompt) {
|
|
@@ -31,6 +32,8 @@ export class QoderRunner {
|
|
|
31
32
|
const reducer = new ClaudeCliProtocolReducer(context.session);
|
|
32
33
|
let stdoutTail = "";
|
|
33
34
|
let primaryError = null;
|
|
35
|
+
let protocolError = false;
|
|
36
|
+
let unparsedStdout = false;
|
|
34
37
|
return startStructuredCli({
|
|
35
38
|
sessionId: context.session.id,
|
|
36
39
|
file: "qodercli",
|
|
@@ -52,6 +55,7 @@ export class QoderRunner {
|
|
|
52
55
|
event = JSON.parse(trimmed);
|
|
53
56
|
}
|
|
54
57
|
catch {
|
|
58
|
+
unparsedStdout = true;
|
|
55
59
|
return;
|
|
56
60
|
}
|
|
57
61
|
if (event && typeof event === "object" && !Array.isArray(event)) {
|
|
@@ -62,6 +66,7 @@ export class QoderRunner {
|
|
|
62
66
|
? record.errors.filter((item) => typeof item === "string")
|
|
63
67
|
: [];
|
|
64
68
|
primaryError = errors.join("\n") || "Qoder CLI execution failed";
|
|
69
|
+
protocolError = true;
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
if (reducer.apply(event, context.session.mode === "managed"))
|
|
@@ -80,6 +85,15 @@ export class QoderRunner {
|
|
|
80
85
|
stdoutTail,
|
|
81
86
|
primaryError,
|
|
82
87
|
...(spawnError ? { spawnError } : {}),
|
|
88
|
+
...cliUnacceptedFacts({
|
|
89
|
+
state: reducer.state,
|
|
90
|
+
primaryError,
|
|
91
|
+
protocolError: protocolError || reducer.errorResultObserved,
|
|
92
|
+
unparsedStdout,
|
|
93
|
+
signal,
|
|
94
|
+
progressed: reducer.assistantWorkObserved,
|
|
95
|
+
...(spawnError ? { spawnError } : {}),
|
|
96
|
+
}),
|
|
83
97
|
}),
|
|
84
98
|
});
|
|
85
99
|
}
|
|
@@ -70,6 +70,8 @@ interface CreateStructuredSessionOptions {
|
|
|
70
70
|
* 按 automationId 前缀识别,重启后照样生效。
|
|
71
71
|
*/
|
|
72
72
|
export type StructuredRelayHandler = (sessionId: string, text: string) => void | Promise<void>;
|
|
73
|
+
/** Quiet heartbeat is a status ping, not another copy of the transcript or uploaded avatar. */
|
|
74
|
+
export declare function structuredQuietStatusData(session: SessionSnapshot): Record<string, unknown>;
|
|
73
75
|
/**
|
|
74
76
|
* 返回最近一次真正提交给结构化会话的用户输入。
|
|
75
77
|
*
|
|
@@ -113,7 +115,6 @@ export declare class StructuredSessionManager {
|
|
|
113
115
|
private readonly seenIdempotencyKeys;
|
|
114
116
|
private readonly relayHandlers;
|
|
115
117
|
private emitEvent;
|
|
116
|
-
private archiveTimer;
|
|
117
118
|
/**
|
|
118
119
|
* 静默期心跳:回合在飞且连续 TURN_QUIET_HEARTBEAT_MS 没有任何事件时,用现有的
|
|
119
120
|
* status 事件重发一次权威快照(含最新 turn 锚点)。timer 只在 inFlight 期间存在。
|
|
@@ -122,6 +123,8 @@ export declare class StructuredSessionManager {
|
|
|
122
123
|
private readonly topicCoordinator;
|
|
123
124
|
private readonly nativeTitles;
|
|
124
125
|
private readonly streamEmitTimers;
|
|
126
|
+
/** 员工候选链的「本轮还没开始执行」看门狗,按会话一个;首个协议事件或回合收敛即撤销。 */
|
|
127
|
+
private readonly candidateStartupWatchdogs;
|
|
125
128
|
private readonly claudeCliRunner;
|
|
126
129
|
private readonly codexRunner;
|
|
127
130
|
private readonly openCodeRunner;
|
|
@@ -144,7 +147,6 @@ export declare class StructuredSessionManager {
|
|
|
144
147
|
constructor(storage: WandStorage, config: WandConfig, logger?: SessionLogger | null, runners?: StructuredSessionManagerRunners, execHost?: StructuredExecHost | undefined, decisionRuntime?: () => DecisionRuntimeAccess | null, openRouter?: OpenRouterFreeModelsService | undefined,
|
|
145
148
|
/** 「智能分配」专用的本地决策入口:只有真正能跑时才注入,没注入则用系统员工回退。 */
|
|
146
149
|
autoAssignEvaluate?: () => DecisionRuntimeAccess["evaluate"]);
|
|
147
|
-
private archiveExpiredSessions;
|
|
148
150
|
setEventEmitter(emitEvent: (event: ProcessEvent) => void): void;
|
|
149
151
|
getCoreTurnStatus(): CoreStatus;
|
|
150
152
|
/** Keep current turns running; new Pi inputs stay in the durable input queue. */
|
|
@@ -172,6 +174,7 @@ export declare class StructuredSessionManager {
|
|
|
172
174
|
/** Return lightweight snapshots for the session list (no output/messages). */
|
|
173
175
|
listSlim(): SessionSnapshot[];
|
|
174
176
|
get(id: string): SessionSnapshot | null;
|
|
177
|
+
getSlim(id: string): SessionSnapshot | null;
|
|
175
178
|
setSessionWorkspace(id: string, membership: Pick<SessionSnapshot, "workspaceId" | "workspaceTaskId">): void;
|
|
176
179
|
setSessionTopic(id: string, title: string, description: string): SessionSnapshot;
|
|
177
180
|
/** 归档只写标记,正在执行的回合和历史继续保留。 */
|
|
@@ -199,7 +202,12 @@ export declare class StructuredSessionManager {
|
|
|
199
202
|
/** Consume only the exact failed request observed by dispatch, once, before a newer request can replace it. */
|
|
200
203
|
consumeUnacceptedTeamFailure(id: string, requestId: string): StructuredFailure | null;
|
|
201
204
|
private employeeCandidateModel;
|
|
202
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* A turn the provider rejected before it accepted any input may replay on the next candidate.
|
|
207
|
+
* Same-tool switches carry the conversation as it stood before this turn — history plus the native
|
|
208
|
+
* session it already had — so they also cover an already-started chat. A cross-tool switch cannot
|
|
209
|
+
* hand that context over, so it stays limited to conversations that have not produced a turn yet.
|
|
210
|
+
*/
|
|
203
211
|
private retryEmployeeCandidate;
|
|
204
212
|
private throwUnacceptedInput;
|
|
205
213
|
/** 往转发会话里追加别的参与者的发言。 */
|
|
@@ -315,21 +323,8 @@ export declare class StructuredSessionManager {
|
|
|
315
323
|
private flushNextQueuedMessage;
|
|
316
324
|
private emit;
|
|
317
325
|
private incrementApprovalStats;
|
|
318
|
-
|
|
319
|
-
private
|
|
320
|
-
private runOpenCodeStreaming;
|
|
321
|
-
/**
|
|
322
|
-
* Spawn `claude -p --output-format stream-json` and parse NDJSON lines as
|
|
323
|
-
* they arrive, emitting incremental WebSocket events so the UI can render
|
|
324
|
-
* text / thinking / tool_use blocks in real-time.
|
|
325
|
-
*
|
|
326
|
-
* Permission handling:
|
|
327
|
-
* - Non-root + full-access/managed: --permission-mode bypassPermissions
|
|
328
|
-
* - Non-root + auto-edit: --permission-mode acceptEdits
|
|
329
|
-
* - Root: --permission-mode acceptEdits + --allowedTools (extends approval
|
|
330
|
-
* outside CWD). stdin is always "ignore" — no ACP bidirectional control.
|
|
331
|
-
*/
|
|
332
|
-
private runClaudeStreaming;
|
|
326
|
+
/** One turn lifecycle for every structured adapter; provider protocol reducers stay separate. */
|
|
327
|
+
private runStructuredStreaming;
|
|
333
328
|
private compactContentBlocks;
|
|
334
329
|
private buildCompletedAssistantMessages;
|
|
335
330
|
/**
|