@co0ontty/wand 1.6.1 → 1.7.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/dist/config.js +23 -0
- package/dist/git-worktree.d.ts +12 -0
- package/dist/git-worktree.js +43 -0
- package/dist/message-parser.d.ts +1 -1
- package/dist/message-parser.js +275 -1
- package/dist/process-manager.d.ts +6 -3
- package/dist/process-manager.js +135 -81
- package/dist/pty-text-utils.js +79 -29
- package/dist/server-session-routes.js +39 -7
- package/dist/server.js +141 -15
- package/dist/session-logger.d.ts +2 -0
- package/dist/session-logger.js +23 -0
- package/dist/storage.js +80 -18
- package/dist/structured-session-manager.d.ts +5 -0
- package/dist/structured-session-manager.js +115 -49
- package/dist/types.d.ts +23 -0
- package/dist/web-ui/content/scripts.js +1511 -306
- package/dist/web-ui/content/styles.css +142 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
+
import { prepareSessionWorktree } from "./git-worktree.js";
|
|
3
4
|
const STREAM_EMIT_DEBOUNCE_MS = 16;
|
|
4
5
|
function isRunningAsRoot() {
|
|
5
6
|
return process.getuid?.() === 0 || process.geteuid?.() === 0;
|
|
@@ -25,6 +26,15 @@ function withSummary(snapshot) {
|
|
|
25
26
|
function shouldAutoApproveForMode(mode) {
|
|
26
27
|
return mode === "full-access" || mode === "managed" || mode === "auto-edit";
|
|
27
28
|
}
|
|
29
|
+
function buildStructuredOutputPayload(snapshot) {
|
|
30
|
+
return {
|
|
31
|
+
output: snapshot.output,
|
|
32
|
+
messages: snapshot.messages,
|
|
33
|
+
queuedMessages: snapshot.queuedMessages,
|
|
34
|
+
sessionKind: "structured",
|
|
35
|
+
structuredState: snapshot.structuredState,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
28
38
|
export class StructuredSessionManager {
|
|
29
39
|
storage;
|
|
30
40
|
config;
|
|
@@ -41,13 +51,16 @@ export class StructuredSessionManager {
|
|
|
41
51
|
const restored = {
|
|
42
52
|
...snapshot,
|
|
43
53
|
sessionKind: "structured",
|
|
54
|
+
provider: snapshot.provider ?? "claude",
|
|
44
55
|
runner: snapshot.runner ?? "claude-cli-print",
|
|
45
56
|
status: restoredStatus,
|
|
46
57
|
autoApprovePermissions: snapshot.autoApprovePermissions ?? shouldAutoApproveForMode(snapshot.mode),
|
|
47
58
|
approvalStats: snapshot.approvalStats ?? { tool: 0, command: 0, file: 0, total: 0 },
|
|
59
|
+
queuedMessages: snapshot.queuedMessages ?? [],
|
|
48
60
|
pendingEscalation: null,
|
|
49
61
|
permissionBlocked: false,
|
|
50
62
|
structuredState: {
|
|
63
|
+
provider: snapshot.structuredState?.provider ?? snapshot.provider ?? "claude",
|
|
51
64
|
runner: snapshot.runner ?? "claude-cli-print",
|
|
52
65
|
model: snapshot.structuredState?.model,
|
|
53
66
|
lastError: snapshot.structuredState?.lastError ?? null,
|
|
@@ -75,23 +88,31 @@ export class StructuredSessionManager {
|
|
|
75
88
|
const id = randomUUID();
|
|
76
89
|
const startedAt = new Date().toISOString();
|
|
77
90
|
const prompt = options.prompt?.trim();
|
|
91
|
+
const worktreeSetup = options.worktreeEnabled
|
|
92
|
+
? prepareSessionWorktree({ cwd: options.cwd, sessionId: id })
|
|
93
|
+
: null;
|
|
78
94
|
const snapshot = {
|
|
79
95
|
id,
|
|
80
96
|
sessionKind: "structured",
|
|
97
|
+
provider: "claude",
|
|
81
98
|
runner: options.runner ?? "claude-cli-print",
|
|
82
99
|
command: "claude -p --output-format stream-json",
|
|
83
|
-
cwd: options.cwd,
|
|
100
|
+
cwd: worktreeSetup?.cwd ?? options.cwd,
|
|
84
101
|
mode: options.mode,
|
|
85
|
-
|
|
102
|
+
worktreeEnabled: Boolean(worktreeSetup),
|
|
103
|
+
worktree: worktreeSetup?.worktree ?? null,
|
|
104
|
+
status: "running",
|
|
86
105
|
exitCode: null,
|
|
87
106
|
startedAt,
|
|
88
|
-
endedAt:
|
|
107
|
+
endedAt: null,
|
|
89
108
|
output: "",
|
|
90
109
|
archived: false,
|
|
91
110
|
archivedAt: null,
|
|
92
111
|
claudeSessionId: null,
|
|
93
112
|
messages: [],
|
|
113
|
+
queuedMessages: [],
|
|
94
114
|
structuredState: {
|
|
115
|
+
provider: "claude",
|
|
95
116
|
runner: options.runner ?? "claude-cli-print",
|
|
96
117
|
inFlight: false,
|
|
97
118
|
activeRequestId: null,
|
|
@@ -119,7 +140,6 @@ export class StructuredSessionManager {
|
|
|
119
140
|
const child = this.pendingChildren.get(id);
|
|
120
141
|
const childAlive = child && !child.killed && child.exitCode === null;
|
|
121
142
|
if (!childAlive) {
|
|
122
|
-
// Auto-recover: inFlight is stuck but child process is gone or dead
|
|
123
143
|
if (child)
|
|
124
144
|
this.pendingChildren.delete(id);
|
|
125
145
|
const recovered = {
|
|
@@ -137,7 +157,18 @@ export class StructuredSessionManager {
|
|
|
137
157
|
session = recovered;
|
|
138
158
|
}
|
|
139
159
|
else {
|
|
140
|
-
|
|
160
|
+
const queue = [...(session.queuedMessages ?? [])];
|
|
161
|
+
if (queue.length >= 10) {
|
|
162
|
+
throw new Error("排队消息已满(最多 10 条),请等待当前消息处理完成。");
|
|
163
|
+
}
|
|
164
|
+
const queued = {
|
|
165
|
+
...session,
|
|
166
|
+
queuedMessages: [...queue, prompt],
|
|
167
|
+
};
|
|
168
|
+
this.sessions.set(id, queued);
|
|
169
|
+
this.storage.saveSession(queued);
|
|
170
|
+
this.emitStructuredSnapshot(queued);
|
|
171
|
+
return queued;
|
|
141
172
|
}
|
|
142
173
|
}
|
|
143
174
|
const userTurn = {
|
|
@@ -152,7 +183,7 @@ export class StructuredSessionManager {
|
|
|
152
183
|
endedAt: null,
|
|
153
184
|
messages: [...(session.messages ?? []), userTurn],
|
|
154
185
|
structuredState: {
|
|
155
|
-
...(session.structuredState ?? { runner: "claude-cli-print", lastError: null, inFlight: false, activeRequestId: null }),
|
|
186
|
+
...(session.structuredState ?? { provider: "claude", runner: "claude-cli-print", lastError: null, inFlight: false, activeRequestId: null }),
|
|
156
187
|
inFlight: true,
|
|
157
188
|
activeRequestId: requestId,
|
|
158
189
|
lastError: null,
|
|
@@ -160,15 +191,11 @@ export class StructuredSessionManager {
|
|
|
160
191
|
};
|
|
161
192
|
this.sessions.set(id, updated);
|
|
162
193
|
this.storage.saveSession(updated);
|
|
163
|
-
this.
|
|
164
|
-
type: "output",
|
|
165
|
-
sessionId: id,
|
|
166
|
-
data: { output: updated.output, messages: updated.messages, sessionKind: "structured" },
|
|
167
|
-
});
|
|
194
|
+
this.emitStructuredSnapshot(updated);
|
|
168
195
|
this.emit({
|
|
169
196
|
type: "status",
|
|
170
197
|
sessionId: id,
|
|
171
|
-
data: { status: "running", sessionKind: "structured" },
|
|
198
|
+
data: { status: "running", sessionKind: "structured", queuedMessages: updated.queuedMessages, structuredState: updated.structuredState },
|
|
172
199
|
});
|
|
173
200
|
try {
|
|
174
201
|
await this.runClaudeStreaming(id, updated, prompt);
|
|
@@ -197,13 +224,9 @@ export class StructuredSessionManager {
|
|
|
197
224
|
this.emit({
|
|
198
225
|
type: "status",
|
|
199
226
|
sessionId: id,
|
|
200
|
-
data: { status: failed.status, error: message, sessionKind: "structured" },
|
|
201
|
-
});
|
|
202
|
-
this.emit({
|
|
203
|
-
type: "ended",
|
|
204
|
-
sessionId: id,
|
|
205
|
-
data: { status: failed.status, exitCode: 1, messages: failed.messages, sessionKind: "structured", structuredState: failed.structuredState },
|
|
227
|
+
data: { status: failed.status, error: message, sessionKind: "structured", queuedMessages: failed.queuedMessages, structuredState: failed.structuredState },
|
|
206
228
|
});
|
|
229
|
+
this.emitStructuredSnapshot(failed, "ended");
|
|
207
230
|
throw error;
|
|
208
231
|
}
|
|
209
232
|
}
|
|
@@ -268,14 +291,14 @@ export class StructuredSessionManager {
|
|
|
268
291
|
pendingEscalation: null,
|
|
269
292
|
permissionBlocked: false,
|
|
270
293
|
structuredState: {
|
|
271
|
-
...(session.structuredState ?? { runner: "claude-cli-print", lastError: null, inFlight: false, activeRequestId: null }),
|
|
294
|
+
...(session.structuredState ?? { provider: "claude", runner: "claude-cli-print", lastError: null, inFlight: false, activeRequestId: null }),
|
|
272
295
|
inFlight: false,
|
|
273
296
|
activeRequestId: null,
|
|
274
297
|
},
|
|
275
298
|
};
|
|
276
299
|
this.sessions.set(id, stopped);
|
|
277
300
|
this.storage.saveSession(stopped);
|
|
278
|
-
this.
|
|
301
|
+
this.emitStructuredSnapshot(stopped, "ended");
|
|
279
302
|
return stopped;
|
|
280
303
|
}
|
|
281
304
|
delete(id) {
|
|
@@ -297,6 +320,58 @@ export class StructuredSessionManager {
|
|
|
297
320
|
}
|
|
298
321
|
return session;
|
|
299
322
|
}
|
|
323
|
+
buildQueuedPlaceholderTurns(session) {
|
|
324
|
+
return (session.queuedMessages ?? []).map((text) => ({
|
|
325
|
+
role: "user",
|
|
326
|
+
content: [{ type: "text", text, __queued: true }],
|
|
327
|
+
}));
|
|
328
|
+
}
|
|
329
|
+
buildRenderableMessages(session) {
|
|
330
|
+
return [
|
|
331
|
+
...(session.messages ?? []),
|
|
332
|
+
...this.buildQueuedPlaceholderTurns(session),
|
|
333
|
+
];
|
|
334
|
+
}
|
|
335
|
+
emitStructuredSnapshot(session, eventType = "output") {
|
|
336
|
+
const payload = buildStructuredOutputPayload(session);
|
|
337
|
+
const data = {
|
|
338
|
+
...payload,
|
|
339
|
+
messages: this.buildRenderableMessages(session),
|
|
340
|
+
status: session.status,
|
|
341
|
+
exitCode: session.exitCode,
|
|
342
|
+
};
|
|
343
|
+
this.emit({
|
|
344
|
+
type: eventType,
|
|
345
|
+
sessionId: session.id,
|
|
346
|
+
data,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
async flushNextQueuedMessage(sessionId) {
|
|
350
|
+
const current = this.sessions.get(sessionId);
|
|
351
|
+
if (!current || (current.queuedMessages?.length ?? 0) === 0) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (current.structuredState?.inFlight) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const [nextInput, ...restQueue] = current.queuedMessages ?? [];
|
|
358
|
+
if (!nextInput) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
const nextSession = {
|
|
362
|
+
...current,
|
|
363
|
+
queuedMessages: restQueue,
|
|
364
|
+
};
|
|
365
|
+
this.sessions.set(sessionId, nextSession);
|
|
366
|
+
this.storage.saveSession(nextSession);
|
|
367
|
+
this.emitStructuredSnapshot(nextSession);
|
|
368
|
+
try {
|
|
369
|
+
await this.sendMessage(sessionId, nextInput);
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
console.error("[WAND] flushNextQueuedMessage failed:", error);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
300
375
|
emit(event) {
|
|
301
376
|
if (this.emitEvent) {
|
|
302
377
|
this.emitEvent(event);
|
|
@@ -345,19 +420,21 @@ export class StructuredSessionManager {
|
|
|
345
420
|
// ---------------------------------------------------------------------------
|
|
346
421
|
// CLI argument construction
|
|
347
422
|
// ---------------------------------------------------------------------------
|
|
348
|
-
buildPermissionArgs(mode) {
|
|
423
|
+
buildPermissionArgs(mode, autoApprove) {
|
|
424
|
+
const shouldBypass = autoApprove || mode === "full-access" || mode === "managed";
|
|
425
|
+
const shouldAcceptEdits = mode === "auto-edit";
|
|
349
426
|
if (!isRunningAsRoot()) {
|
|
350
|
-
if (
|
|
427
|
+
if (shouldBypass) {
|
|
351
428
|
return ["--permission-mode", "bypassPermissions"];
|
|
352
429
|
}
|
|
353
|
-
if (
|
|
430
|
+
if (shouldAcceptEdits) {
|
|
354
431
|
return ["--permission-mode", "acceptEdits"];
|
|
355
432
|
}
|
|
356
433
|
return [];
|
|
357
434
|
}
|
|
358
435
|
// Root: Claude CLI refuses bypassPermissions.
|
|
359
436
|
// acceptEdits auto-approves within CWD; --allowedTools extends to all paths.
|
|
360
|
-
if (
|
|
437
|
+
if (shouldBypass || shouldAcceptEdits) {
|
|
361
438
|
return [
|
|
362
439
|
"--permission-mode", "acceptEdits",
|
|
363
440
|
"--allowedTools", "Bash", "Edit", "Write", "Read", "Glob", "Grep",
|
|
@@ -384,8 +461,8 @@ export class StructuredSessionManager {
|
|
|
384
461
|
return new Promise((resolve, reject) => {
|
|
385
462
|
const args = ["-p", "--verbose", "--output-format", "stream-json"];
|
|
386
463
|
console.log("[WAND] runClaudeStreaming sessionId:", sessionId, "mode:", session.mode, "claudeSessionId:", session.claudeSessionId);
|
|
387
|
-
// Add permission args based on mode
|
|
388
|
-
const permArgs = this.buildPermissionArgs(session.mode);
|
|
464
|
+
// Add permission args based on mode + autoApprovePermissions toggle
|
|
465
|
+
const permArgs = this.buildPermissionArgs(session.mode, session.autoApprovePermissions ?? false);
|
|
389
466
|
args.push(...permArgs);
|
|
390
467
|
// In managed mode, append autonomous system prompt
|
|
391
468
|
if (session.mode === "managed") {
|
|
@@ -429,7 +506,7 @@ export class StructuredSessionManager {
|
|
|
429
506
|
this.emit({
|
|
430
507
|
type: "output",
|
|
431
508
|
sessionId,
|
|
432
|
-
data:
|
|
509
|
+
data: buildStructuredOutputPayload(current),
|
|
433
510
|
});
|
|
434
511
|
};
|
|
435
512
|
const scheduleEmit = () => {
|
|
@@ -460,12 +537,16 @@ export class StructuredSessionManager {
|
|
|
460
537
|
...current,
|
|
461
538
|
claudeSessionId: turnState.sessionId ?? current.claudeSessionId,
|
|
462
539
|
messages: msgs,
|
|
540
|
+
output: turnState.result || current.output,
|
|
463
541
|
structuredState: {
|
|
464
542
|
...current.structuredState,
|
|
465
543
|
model: turnState.model ?? current.structuredState?.model,
|
|
466
544
|
},
|
|
467
545
|
};
|
|
468
546
|
this.sessions.set(sessionId, patched);
|
|
547
|
+
// Persist streaming progress so a server restart does not roll back the
|
|
548
|
+
// latest assistant turn to the pre-stream snapshot.
|
|
549
|
+
this.storage.saveSession(patched);
|
|
469
550
|
};
|
|
470
551
|
const processLine = (line) => {
|
|
471
552
|
const trimmed = line.trim();
|
|
@@ -588,16 +669,8 @@ export class StructuredSessionManager {
|
|
|
588
669
|
};
|
|
589
670
|
this.sessions.set(sessionId, failed);
|
|
590
671
|
this.storage.saveSession(failed);
|
|
591
|
-
this.
|
|
592
|
-
|
|
593
|
-
sessionId,
|
|
594
|
-
data: { output: failed.output, messages: failed.messages, sessionKind: "structured" },
|
|
595
|
-
});
|
|
596
|
-
this.emit({
|
|
597
|
-
type: "ended",
|
|
598
|
-
sessionId,
|
|
599
|
-
data: { status: failed.status, exitCode: failed.exitCode, messages: failed.messages, sessionKind: "structured", structuredState: failed.structuredState },
|
|
600
|
-
});
|
|
672
|
+
this.emitStructuredSnapshot(failed);
|
|
673
|
+
this.emitStructuredSnapshot(failed, "ended");
|
|
601
674
|
reject(new Error(errorText));
|
|
602
675
|
return;
|
|
603
676
|
}
|
|
@@ -637,16 +710,8 @@ export class StructuredSessionManager {
|
|
|
637
710
|
};
|
|
638
711
|
this.sessions.set(sessionId, finished);
|
|
639
712
|
this.storage.saveSession(finished);
|
|
640
|
-
this.
|
|
641
|
-
|
|
642
|
-
sessionId,
|
|
643
|
-
data: { output: finished.output, messages: finished.messages, sessionKind: "structured" },
|
|
644
|
-
});
|
|
645
|
-
this.emit({
|
|
646
|
-
type: "ended",
|
|
647
|
-
sessionId,
|
|
648
|
-
data: { status: finished.status, exitCode: 0, messages: finished.messages, sessionKind: "structured", structuredState: finished.structuredState },
|
|
649
|
-
});
|
|
713
|
+
this.emitStructuredSnapshot(finished);
|
|
714
|
+
this.emitStructuredSnapshot(finished, "ended");
|
|
650
715
|
// Auto-continue after plan mode exit: when Claude calls ExitPlanMode,
|
|
651
716
|
// the `-p` process exits because stdin is "ignore" and it cannot get
|
|
652
717
|
// user confirmation. Detect this and automatically resume execution
|
|
@@ -655,8 +720,6 @@ export class StructuredSessionManager {
|
|
|
655
720
|
if (lastToolUse && lastToolUse.name === "ExitPlanMode" && turnState.sessionId) {
|
|
656
721
|
console.log("[WAND] ExitPlanMode detected – auto-continuing plan execution for session:", sessionId);
|
|
657
722
|
resolve();
|
|
658
|
-
// Schedule the continuation outside the current promise chain so it
|
|
659
|
-
// does not block the close handler.
|
|
660
723
|
setImmediate(() => {
|
|
661
724
|
this.sendMessage(sessionId, "Plan approved. Proceed with the implementation.").catch((err) => {
|
|
662
725
|
console.error("[WAND] Auto-continue after ExitPlanMode failed:", err);
|
|
@@ -665,6 +728,9 @@ export class StructuredSessionManager {
|
|
|
665
728
|
return;
|
|
666
729
|
}
|
|
667
730
|
resolve();
|
|
731
|
+
setImmediate(() => {
|
|
732
|
+
void this.flushNextQueuedMessage(sessionId);
|
|
733
|
+
});
|
|
668
734
|
});
|
|
669
735
|
});
|
|
670
736
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type SessionKind = "pty" | "structured";
|
|
2
2
|
export type SessionCreateKind = "pty" | "structured";
|
|
3
|
+
export type SessionProvider = "claude" | "codex";
|
|
3
4
|
export type SessionRunner = "claude-cli" | "claude-cli-print" | "pty";
|
|
4
5
|
export type ExecutionMode = "assist" | "agent" | "agent-max" | "default" | "auto-edit" | "full-access" | "native" | "managed";
|
|
5
6
|
export type AutonomyPolicy = "assist" | "agent" | "agent-max";
|
|
@@ -38,6 +39,14 @@ export interface CommandPreset {
|
|
|
38
39
|
command: string;
|
|
39
40
|
mode?: ExecutionMode;
|
|
40
41
|
}
|
|
42
|
+
export interface StructuredChatPersonaRoleConfig {
|
|
43
|
+
name?: string;
|
|
44
|
+
avatar?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface StructuredChatPersonaConfig {
|
|
47
|
+
user?: StructuredChatPersonaRoleConfig;
|
|
48
|
+
assistant?: StructuredChatPersonaRoleConfig;
|
|
49
|
+
}
|
|
41
50
|
export interface WandConfig {
|
|
42
51
|
host: string;
|
|
43
52
|
port: number;
|
|
@@ -50,16 +59,23 @@ export interface WandConfig {
|
|
|
50
59
|
startupCommands: string[];
|
|
51
60
|
allowedCommandPrefixes: string[];
|
|
52
61
|
commandPresets: CommandPreset[];
|
|
62
|
+
structuredChatPersona?: StructuredChatPersonaConfig;
|
|
53
63
|
/** Max total size (bytes) for shortcut interaction logs per session (default: 10 MB). Set 0 to disable logging. */
|
|
54
64
|
shortcutLogMaxBytes?: number;
|
|
55
65
|
/** Preferred response language for Claude (e.g. "中文", "English"). Empty string means no override. */
|
|
56
66
|
language?: string;
|
|
57
67
|
}
|
|
68
|
+
interface WorktreeInfo {
|
|
69
|
+
branch: string;
|
|
70
|
+
path: string;
|
|
71
|
+
}
|
|
58
72
|
export interface CommandRequest {
|
|
59
73
|
command: string;
|
|
74
|
+
provider?: SessionProvider;
|
|
60
75
|
cwd?: string;
|
|
61
76
|
mode?: ExecutionMode;
|
|
62
77
|
initialInput?: string;
|
|
78
|
+
worktreeEnabled?: boolean;
|
|
63
79
|
}
|
|
64
80
|
export interface InputRequest {
|
|
65
81
|
input?: string;
|
|
@@ -134,6 +150,7 @@ export interface ConversationTurn {
|
|
|
134
150
|
};
|
|
135
151
|
}
|
|
136
152
|
export interface StructuredSessionState {
|
|
153
|
+
provider?: SessionProvider;
|
|
137
154
|
runner: SessionRunner;
|
|
138
155
|
model?: string;
|
|
139
156
|
lastError: string | null;
|
|
@@ -143,10 +160,13 @@ export interface StructuredSessionState {
|
|
|
143
160
|
export interface SessionSnapshot {
|
|
144
161
|
id: string;
|
|
145
162
|
sessionKind?: SessionKind;
|
|
163
|
+
provider?: SessionProvider;
|
|
146
164
|
runner?: SessionRunner;
|
|
147
165
|
command: string;
|
|
148
166
|
cwd: string;
|
|
149
167
|
mode: ExecutionMode;
|
|
168
|
+
worktreeEnabled?: boolean;
|
|
169
|
+
worktree?: WorktreeInfo | null;
|
|
150
170
|
autonomyPolicy?: AutonomyPolicy;
|
|
151
171
|
approvalPolicy?: ApprovalPolicy;
|
|
152
172
|
allowedScopes?: EscalationScope[];
|
|
@@ -169,6 +189,8 @@ export interface SessionSnapshot {
|
|
|
169
189
|
claudeSessionId: string | null;
|
|
170
190
|
/** Structured conversation messages derived from PTY output. */
|
|
171
191
|
messages?: ConversationTurn[];
|
|
192
|
+
/** Pending structured user inputs queued while an assistant response is in flight. */
|
|
193
|
+
queuedMessages?: string[];
|
|
172
194
|
structuredState?: StructuredSessionState;
|
|
173
195
|
/** Session lifecycle state */
|
|
174
196
|
lifecycleState?: "running" | "idle" | "archived";
|
|
@@ -246,3 +268,4 @@ export interface TaskData {
|
|
|
246
268
|
export interface SessionEndData {
|
|
247
269
|
exitCode: number | null;
|
|
248
270
|
}
|
|
271
|
+
export {};
|