@co0ontty/wand 0.2.1 → 0.3.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 +25 -5
- package/dist/acp-protocol.d.ts +67 -0
- package/dist/acp-protocol.js +291 -0
- package/dist/claude-pty-bridge.d.ts +139 -0
- package/dist/claude-pty-bridge.js +649 -0
- package/dist/claude-stream-adapter.d.ts +35 -0
- package/dist/claude-stream-adapter.js +153 -0
- package/dist/claude-structured-runner.d.ts +27 -0
- package/dist/claude-structured-runner.js +106 -0
- package/dist/config.js +2 -2
- package/dist/message-parser.js +12 -66
- package/dist/message-queue.d.ts +57 -0
- package/dist/message-queue.js +127 -0
- package/dist/process-manager.d.ts +32 -25
- package/dist/process-manager.js +503 -780
- package/dist/server.js +366 -51
- package/dist/session-lifecycle.d.ts +81 -0
- package/dist/session-lifecycle.js +176 -0
- package/dist/storage.js +12 -1
- package/dist/types.d.ts +105 -5
- package/dist/web-ui/content/scripts.js +2307 -658
- package/dist/web-ui/content/styles.css +5284 -2771
- package/dist/web-ui/index.js +8 -5
- package/dist/web-ui/scripts.js +8 -1
- package/package.json +2 -9
- package/dist/web-ui/utils.d.ts +0 -4
- package/dist/web-ui/utils.js +0 -12
- package/dist/web-ui.d.ts +0 -1
- package/dist/web-ui.js +0 -2
package/README.md
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
# wand
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
通过浏览器访问本地终端,支持 Claude 等命令行工具。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 功能
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Web 终端 / Chat 模式双视图
|
|
8
|
+
- 会话持久化与恢复
|
|
9
|
+
- Claude Code 集成
|
|
10
|
+
- 文件浏览器
|
|
11
|
+
- HTTPS 安全连接
|
|
12
|
+
|
|
13
|
+
## 快速开始
|
|
8
14
|
|
|
9
15
|
```bash
|
|
10
|
-
npm install -g @co0ontty/wand
|
|
16
|
+
npm install -g @co0ontty/wand
|
|
17
|
+
wand init
|
|
18
|
+
wand web
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
配置文件:`~/.wand/config.json`
|
|
22
|
+
|
|
23
|
+
## 开发
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
npm run build
|
|
28
|
+
npm run dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## License
|
|
32
|
+
|
|
33
|
+
MIT
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACP (Agent Communication Protocol) implementation
|
|
3
|
+
* Inspired by Happy's unified agent communication format
|
|
4
|
+
*/
|
|
5
|
+
import type { ACPMessage, ACPTextMessage, ACPReasoningMessage, ACPToolCallMessage, ACPToolResultMessage, ACPFileEditMessage, ACPTerminalOutputMessage, ACPPermissionRequestMessage, ACPSessionStartMessage, ACPSessionEndMessage, ACPErrorMessage, ConversationTurn } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create a text message
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTextMessage(sessionId: string, role: "user" | "assistant" | "system", content: string): ACPTextMessage;
|
|
10
|
+
/**
|
|
11
|
+
* Create a reasoning message
|
|
12
|
+
*/
|
|
13
|
+
export declare function createReasoningMessage(sessionId: string, content: string, isStreaming?: boolean): ACPReasoningMessage;
|
|
14
|
+
/**
|
|
15
|
+
* Create a tool call message
|
|
16
|
+
*/
|
|
17
|
+
export declare function createToolCallMessage(sessionId: string, toolCallId: string, name: string, input: Record<string, unknown>, description?: string): ACPToolCallMessage;
|
|
18
|
+
/**
|
|
19
|
+
* Create a tool result message
|
|
20
|
+
*/
|
|
21
|
+
export declare function createToolResultMessage(sessionId: string, toolCallId: string, output: string | Array<{
|
|
22
|
+
type: string;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}>, isError?: boolean): ACPToolResultMessage;
|
|
25
|
+
/**
|
|
26
|
+
* Create a file edit message
|
|
27
|
+
*/
|
|
28
|
+
export declare function createFileEditMessage(sessionId: string, filePath: string, description: string, options?: {
|
|
29
|
+
oldContent?: string;
|
|
30
|
+
newContent?: string;
|
|
31
|
+
diff?: string;
|
|
32
|
+
}): ACPFileEditMessage;
|
|
33
|
+
/**
|
|
34
|
+
* Create a terminal output message
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTerminalOutputMessage(sessionId: string, data: string, toolCallId?: string): ACPTerminalOutputMessage;
|
|
37
|
+
/**
|
|
38
|
+
* Create a permission request message
|
|
39
|
+
*/
|
|
40
|
+
export declare function createPermissionRequestMessage(sessionId: string, permissionId: string, toolName: string, description: string): ACPPermissionRequestMessage;
|
|
41
|
+
/**
|
|
42
|
+
* Create a session start message
|
|
43
|
+
*/
|
|
44
|
+
export declare function createSessionStartMessage(sessionId: string, workingDirectory: string, agent?: string): ACPSessionStartMessage;
|
|
45
|
+
/**
|
|
46
|
+
* Create a session end message
|
|
47
|
+
*/
|
|
48
|
+
export declare function createSessionEndMessage(sessionId: string, exitCode: number | null): ACPSessionEndMessage;
|
|
49
|
+
/**
|
|
50
|
+
* Create an error message
|
|
51
|
+
*/
|
|
52
|
+
export declare function createErrorMessage(sessionId: string, error: string, details?: string): ACPErrorMessage;
|
|
53
|
+
/**
|
|
54
|
+
* Convert ConversationTurn to ACP messages
|
|
55
|
+
*/
|
|
56
|
+
export declare function conversationTurnToACP(sessionId: string, turn: ConversationTurn): ACPMessage[];
|
|
57
|
+
/**
|
|
58
|
+
* Convert ACP messages to ConversationTurn
|
|
59
|
+
*/
|
|
60
|
+
export declare function acpToConversationTurns(messages: ACPMessage[]): ConversationTurn[];
|
|
61
|
+
/**
|
|
62
|
+
* Parse Claude stream-json event to ACP message
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseClaudeStreamEvent(sessionId: string, event: {
|
|
65
|
+
type?: string;
|
|
66
|
+
[key: string]: unknown;
|
|
67
|
+
}): ACPMessage | null;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACP (Agent Communication Protocol) implementation
|
|
3
|
+
* Inspired by Happy's unified agent communication format
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a unique message ID
|
|
7
|
+
*/
|
|
8
|
+
function generateId() {
|
|
9
|
+
return `acp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create a text message
|
|
13
|
+
*/
|
|
14
|
+
export function createTextMessage(sessionId, role, content) {
|
|
15
|
+
return {
|
|
16
|
+
id: generateId(),
|
|
17
|
+
type: "message",
|
|
18
|
+
timestamp: Date.now(),
|
|
19
|
+
sessionId,
|
|
20
|
+
role,
|
|
21
|
+
content,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a reasoning message
|
|
26
|
+
*/
|
|
27
|
+
export function createReasoningMessage(sessionId, content, isStreaming = false) {
|
|
28
|
+
return {
|
|
29
|
+
id: generateId(),
|
|
30
|
+
type: "reasoning",
|
|
31
|
+
timestamp: Date.now(),
|
|
32
|
+
sessionId,
|
|
33
|
+
content,
|
|
34
|
+
isStreaming,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create a tool call message
|
|
39
|
+
*/
|
|
40
|
+
export function createToolCallMessage(sessionId, toolCallId, name, input, description) {
|
|
41
|
+
return {
|
|
42
|
+
id: generateId(),
|
|
43
|
+
type: "tool-call",
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
sessionId,
|
|
46
|
+
toolCallId,
|
|
47
|
+
name,
|
|
48
|
+
input,
|
|
49
|
+
description,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a tool result message
|
|
54
|
+
*/
|
|
55
|
+
export function createToolResultMessage(sessionId, toolCallId, output, isError = false) {
|
|
56
|
+
return {
|
|
57
|
+
id: generateId(),
|
|
58
|
+
type: "tool-result",
|
|
59
|
+
timestamp: Date.now(),
|
|
60
|
+
sessionId,
|
|
61
|
+
toolCallId,
|
|
62
|
+
output,
|
|
63
|
+
isError,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create a file edit message
|
|
68
|
+
*/
|
|
69
|
+
export function createFileEditMessage(sessionId, filePath, description, options = {}) {
|
|
70
|
+
return {
|
|
71
|
+
id: generateId(),
|
|
72
|
+
type: "file-edit",
|
|
73
|
+
timestamp: Date.now(),
|
|
74
|
+
sessionId,
|
|
75
|
+
filePath,
|
|
76
|
+
description,
|
|
77
|
+
...options,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a terminal output message
|
|
82
|
+
*/
|
|
83
|
+
export function createTerminalOutputMessage(sessionId, data, toolCallId) {
|
|
84
|
+
return {
|
|
85
|
+
id: generateId(),
|
|
86
|
+
type: "terminal-output",
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
sessionId,
|
|
89
|
+
data,
|
|
90
|
+
toolCallId,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Create a permission request message
|
|
95
|
+
*/
|
|
96
|
+
export function createPermissionRequestMessage(sessionId, permissionId, toolName, description) {
|
|
97
|
+
return {
|
|
98
|
+
id: generateId(),
|
|
99
|
+
type: "permission-request",
|
|
100
|
+
timestamp: Date.now(),
|
|
101
|
+
sessionId,
|
|
102
|
+
permissionId,
|
|
103
|
+
toolName,
|
|
104
|
+
description,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Create a session start message
|
|
109
|
+
*/
|
|
110
|
+
export function createSessionStartMessage(sessionId, workingDirectory, agent) {
|
|
111
|
+
return {
|
|
112
|
+
id: generateId(),
|
|
113
|
+
type: "session-start",
|
|
114
|
+
timestamp: Date.now(),
|
|
115
|
+
sessionId,
|
|
116
|
+
workingDirectory,
|
|
117
|
+
agent,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create a session end message
|
|
122
|
+
*/
|
|
123
|
+
export function createSessionEndMessage(sessionId, exitCode) {
|
|
124
|
+
return {
|
|
125
|
+
id: generateId(),
|
|
126
|
+
type: "session-end",
|
|
127
|
+
timestamp: Date.now(),
|
|
128
|
+
sessionId,
|
|
129
|
+
exitCode,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Create an error message
|
|
134
|
+
*/
|
|
135
|
+
export function createErrorMessage(sessionId, error, details) {
|
|
136
|
+
return {
|
|
137
|
+
id: generateId(),
|
|
138
|
+
type: "error",
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
sessionId,
|
|
141
|
+
error,
|
|
142
|
+
details,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Convert ConversationTurn to ACP messages
|
|
147
|
+
*/
|
|
148
|
+
export function conversationTurnToACP(sessionId, turn) {
|
|
149
|
+
const messages = [];
|
|
150
|
+
for (const block of turn.content) {
|
|
151
|
+
switch (block.type) {
|
|
152
|
+
case "text":
|
|
153
|
+
messages.push(createTextMessage(sessionId, turn.role, block.text));
|
|
154
|
+
break;
|
|
155
|
+
case "thinking":
|
|
156
|
+
messages.push(createReasoningMessage(sessionId, block.thinking));
|
|
157
|
+
break;
|
|
158
|
+
case "tool_use":
|
|
159
|
+
messages.push(createToolCallMessage(sessionId, block.id, block.name, block.input, block.description));
|
|
160
|
+
break;
|
|
161
|
+
case "tool_result":
|
|
162
|
+
messages.push(createToolResultMessage(sessionId, block.tool_use_id, block.content, block.is_error ?? false));
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return messages;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Convert ACP messages to ConversationTurn
|
|
170
|
+
*/
|
|
171
|
+
export function acpToConversationTurns(messages) {
|
|
172
|
+
const turns = [];
|
|
173
|
+
let currentTurn = null;
|
|
174
|
+
for (const msg of messages) {
|
|
175
|
+
switch (msg.type) {
|
|
176
|
+
case "message":
|
|
177
|
+
if (msg.role === "user") {
|
|
178
|
+
// Start a new user turn
|
|
179
|
+
if (currentTurn) {
|
|
180
|
+
turns.push(currentTurn);
|
|
181
|
+
}
|
|
182
|
+
currentTurn = {
|
|
183
|
+
role: "user",
|
|
184
|
+
content: [{ type: "text", text: msg.content }],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
else if (msg.role === "assistant") {
|
|
188
|
+
if (currentTurn?.role === "assistant") {
|
|
189
|
+
// Add to existing assistant turn
|
|
190
|
+
currentTurn.content.push({ type: "text", text: msg.content });
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Start new assistant turn
|
|
194
|
+
if (currentTurn) {
|
|
195
|
+
turns.push(currentTurn);
|
|
196
|
+
}
|
|
197
|
+
currentTurn = {
|
|
198
|
+
role: "assistant",
|
|
199
|
+
content: [{ type: "text", text: msg.content }],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case "reasoning":
|
|
205
|
+
if (currentTurn?.role === "assistant") {
|
|
206
|
+
currentTurn.content.push({ type: "thinking", thinking: msg.content });
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
case "tool-call":
|
|
210
|
+
if (currentTurn?.role === "assistant") {
|
|
211
|
+
currentTurn.content.push({
|
|
212
|
+
type: "tool_use",
|
|
213
|
+
id: msg.toolCallId,
|
|
214
|
+
name: msg.name,
|
|
215
|
+
input: msg.input,
|
|
216
|
+
description: msg.description,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
case "tool-result":
|
|
221
|
+
if (currentTurn?.role === "assistant") {
|
|
222
|
+
currentTurn.content.push({
|
|
223
|
+
type: "tool_result",
|
|
224
|
+
tool_use_id: msg.toolCallId,
|
|
225
|
+
content: msg.output,
|
|
226
|
+
is_error: msg.isError,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (currentTurn) {
|
|
233
|
+
turns.push(currentTurn);
|
|
234
|
+
}
|
|
235
|
+
return turns;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Parse Claude stream-json event to ACP message
|
|
239
|
+
*/
|
|
240
|
+
export function parseClaudeStreamEvent(sessionId, event) {
|
|
241
|
+
switch (event.type) {
|
|
242
|
+
case "content_block_start": {
|
|
243
|
+
const block = event.content_block;
|
|
244
|
+
if (!block)
|
|
245
|
+
return null;
|
|
246
|
+
if (block.type === "text") {
|
|
247
|
+
return createTextMessage(sessionId, "assistant", "");
|
|
248
|
+
}
|
|
249
|
+
if (block.type === "thinking") {
|
|
250
|
+
return createReasoningMessage(sessionId, "", true);
|
|
251
|
+
}
|
|
252
|
+
if (block.type === "tool_use") {
|
|
253
|
+
return createToolCallMessage(sessionId, block.id ?? "", block.name ?? "", block.input ?? {});
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
case "content_block_delta": {
|
|
258
|
+
const delta = event.delta;
|
|
259
|
+
if (!delta)
|
|
260
|
+
return null;
|
|
261
|
+
if (delta.type === "text_delta" && delta.text) {
|
|
262
|
+
return createTextMessage(sessionId, "assistant", delta.text);
|
|
263
|
+
}
|
|
264
|
+
if (delta.type === "thinking_delta" && delta.thinking) {
|
|
265
|
+
return createReasoningMessage(sessionId, delta.thinking, true);
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
case "content_block_stop": {
|
|
270
|
+
// Block completed - could emit a completion event
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
case "message_start": {
|
|
274
|
+
const message = event.message;
|
|
275
|
+
if (message?.role === "assistant") {
|
|
276
|
+
return createTextMessage(sessionId, "assistant", "");
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
case "message_stop": {
|
|
281
|
+
// Message completed
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
case "error": {
|
|
285
|
+
const error = event.error;
|
|
286
|
+
return createErrorMessage(sessionId, error?.message ?? "Unknown error");
|
|
287
|
+
}
|
|
288
|
+
default:
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudePtyBridge - PTY output parsing and event bridge
|
|
3
|
+
*
|
|
4
|
+
* Transforms raw PTY output into structured events for WebSocket broadcast.
|
|
5
|
+
* Maintains two parallel output streams:
|
|
6
|
+
* 1. Raw output for terminal view (passthrough)
|
|
7
|
+
* 2. Structured messages for chat view (parsed)
|
|
8
|
+
*/
|
|
9
|
+
import { EventEmitter } from "node:events";
|
|
10
|
+
import type { ApprovalPolicy, ConversationTurn, EscalationScope, TaskData } from "./types.js";
|
|
11
|
+
interface PermissionState {
|
|
12
|
+
/** Rolling window for prompt detection */
|
|
13
|
+
window: string;
|
|
14
|
+
/** Currently blocked */
|
|
15
|
+
isBlocked: boolean;
|
|
16
|
+
/** Last detected prompt text */
|
|
17
|
+
lastPrompt: string | null;
|
|
18
|
+
/** Last detected scope */
|
|
19
|
+
lastScope: EscalationScope | null;
|
|
20
|
+
/** Last detected target */
|
|
21
|
+
lastTarget: string | null;
|
|
22
|
+
/** Timestamp of last auto-confirm to prevent rapid repeats */
|
|
23
|
+
lastAutoConfirmAt: number;
|
|
24
|
+
}
|
|
25
|
+
/** Permission resolution result */
|
|
26
|
+
export type PermissionResolution = "approve_once" | "approve_turn" | "deny";
|
|
27
|
+
export interface ClaudePtyBridgeOptions {
|
|
28
|
+
sessionId: string;
|
|
29
|
+
/** Initial messages from storage (for restart recovery) */
|
|
30
|
+
initialMessages?: ConversationTurn[];
|
|
31
|
+
/** Initial raw output from storage */
|
|
32
|
+
initialOutput?: string;
|
|
33
|
+
/** Whether this is a Claude CLI command (enables permission detection) */
|
|
34
|
+
isClaudeCommand?: boolean;
|
|
35
|
+
/** Whether to auto-approve permission prompts */
|
|
36
|
+
autoApprove?: boolean;
|
|
37
|
+
/** Approval policy for permission handling */
|
|
38
|
+
approvalPolicy?: ApprovalPolicy;
|
|
39
|
+
/** PTY write function for sending approval input */
|
|
40
|
+
ptyWrite?: (input: string) => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* ClaudePtyBridge transforms raw PTY output into structured events.
|
|
44
|
+
*
|
|
45
|
+
* Events emitted:
|
|
46
|
+
* - "output.raw" - Raw PTY output for terminal view
|
|
47
|
+
* - "output.chat" - Structured chat content update
|
|
48
|
+
* - "chat.turn" - Conversation turn completed
|
|
49
|
+
* - "permission.prompt" - Permission request detected
|
|
50
|
+
* - "permission.resolved" - Permission resolved
|
|
51
|
+
* - "session.id" - Claude session ID captured
|
|
52
|
+
* - "task" - Task info update
|
|
53
|
+
* - "ended" - Session ended
|
|
54
|
+
*/
|
|
55
|
+
export declare class ClaudePtyBridge extends EventEmitter {
|
|
56
|
+
readonly sessionId: string;
|
|
57
|
+
private rawOutput;
|
|
58
|
+
private messages;
|
|
59
|
+
private chatState;
|
|
60
|
+
private permissionState;
|
|
61
|
+
private sessionIdWindow;
|
|
62
|
+
private claudeSessionId;
|
|
63
|
+
private currentTask;
|
|
64
|
+
private taskDebounceTimer;
|
|
65
|
+
private lastEmittedTask;
|
|
66
|
+
private isClaudeCommand;
|
|
67
|
+
private autoApprove;
|
|
68
|
+
private approvalPolicy;
|
|
69
|
+
private ptyWrite;
|
|
70
|
+
/** Set to true once onExit() has been called; guards against post-exit method calls */
|
|
71
|
+
private _exited;
|
|
72
|
+
private rememberedScopes;
|
|
73
|
+
private rememberedTargets;
|
|
74
|
+
constructor(options: ClaudePtyBridgeOptions);
|
|
75
|
+
/**
|
|
76
|
+
* Process a raw PTY chunk.
|
|
77
|
+
* Emits events via EventEmitter.
|
|
78
|
+
*/
|
|
79
|
+
processChunk(chunk: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Called when user sends input.
|
|
82
|
+
* Starts tracking a new assistant response.
|
|
83
|
+
*/
|
|
84
|
+
onUserInput(input: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Called when PTY process exits.
|
|
87
|
+
* Finalizes any pending response.
|
|
88
|
+
*/
|
|
89
|
+
onExit(exitCode: number | null): void;
|
|
90
|
+
getMessages(): ConversationTurn[];
|
|
91
|
+
getRawOutput(): string;
|
|
92
|
+
getClaudeSessionId(): string | null;
|
|
93
|
+
isPermissionBlocked(): boolean;
|
|
94
|
+
getPermissionState(): PermissionState;
|
|
95
|
+
getCurrentTask(): TaskData | null;
|
|
96
|
+
/**
|
|
97
|
+
* Set the PTY write function for sending approval input.
|
|
98
|
+
*/
|
|
99
|
+
setPtyWrite(fn: (input: string) => void): void;
|
|
100
|
+
/**
|
|
101
|
+
* Resolve the current permission prompt.
|
|
102
|
+
* @param resolution - How to resolve the permission
|
|
103
|
+
*/
|
|
104
|
+
resolvePermission(resolution: PermissionResolution): void;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a permission scope/target should be auto-approved based on remembered decisions.
|
|
107
|
+
*/
|
|
108
|
+
shouldAutoApprove(scope: EscalationScope, target?: string): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Clear remembered permissions (call at the start of a new turn).
|
|
111
|
+
*/
|
|
112
|
+
clearRememberedPermissions(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Clear permission blocked state (called when permission is resolved externally).
|
|
115
|
+
*/
|
|
116
|
+
clearPermissionBlocked(): void;
|
|
117
|
+
private emitEvent;
|
|
118
|
+
private isRealChatInput;
|
|
119
|
+
private captureSessionId;
|
|
120
|
+
private detectPermission;
|
|
121
|
+
private isPermissionPromptDetected;
|
|
122
|
+
private extractPromptText;
|
|
123
|
+
private extractPermissionTarget;
|
|
124
|
+
private inferScope;
|
|
125
|
+
private parseChatResponse;
|
|
126
|
+
private detectCompletion;
|
|
127
|
+
private updateAssistantContent;
|
|
128
|
+
private finalizeResponse;
|
|
129
|
+
private stripAnsi;
|
|
130
|
+
/**
|
|
131
|
+
* Find the end index of the echoed user input in the PTY buffer.
|
|
132
|
+
* The echo may contain ANSI codes between characters.
|
|
133
|
+
* Returns the index after the last character of the echo.
|
|
134
|
+
*/
|
|
135
|
+
private findEchoEndIndex;
|
|
136
|
+
private isStatusLine;
|
|
137
|
+
private cleanForChat;
|
|
138
|
+
}
|
|
139
|
+
export {};
|