@xagent-ai/cli 1.3.0 → 1.3.2
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/.github/release.yml +76 -0
- package/.github/workflows/ci.yml +3 -0
- package/.github/workflows/release.yml +11 -17
- package/README.md +2 -2
- package/README_CN.md +2 -2
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +7 -3
- package/dist/agents.js.map +1 -1
- package/dist/ai-client/factory.d.ts +0 -12
- package/dist/ai-client/factory.d.ts.map +1 -1
- package/dist/ai-client/factory.js +0 -32
- package/dist/ai-client/factory.js.map +1 -1
- package/dist/ai-client/index.js +1 -1
- package/dist/ai-client/index.js.map +1 -1
- package/dist/ai-client/providers/anthropic.d.ts.map +1 -1
- package/dist/ai-client/providers/anthropic.js +10 -4
- package/dist/ai-client/providers/anthropic.js.map +1 -1
- package/dist/ai-client/providers/openai.d.ts.map +1 -1
- package/dist/ai-client/providers/openai.js +8 -4
- package/dist/ai-client/providers/openai.js.map +1 -1
- package/dist/ai-client/providers/remote.d.ts +0 -1
- package/dist/ai-client/providers/remote.d.ts.map +1 -1
- package/dist/ai-client/providers/remote.js +11 -10
- package/dist/ai-client/providers/remote.js.map +1 -1
- package/dist/ai-client/types.d.ts +14 -0
- package/dist/ai-client/types.d.ts.map +1 -1
- package/dist/ai-client/types.js +17 -0
- package/dist/ai-client/types.js.map +1 -1
- package/dist/ai-client-factory.d.ts.map +1 -1
- package/dist/ai-client-factory.js +4 -4
- package/dist/ai-client-factory.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +10 -12
- package/dist/auth.js.map +1 -1
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +3 -5
- package/dist/cancellation.js.map +1 -1
- package/dist/checkpoint.d.ts +1 -0
- package/dist/checkpoint.d.ts.map +1 -1
- package/dist/checkpoint.js +38 -4
- package/dist/checkpoint.js.map +1 -1
- package/dist/cli.js +132 -32
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/context-compressor.d.ts +1 -2
- package/dist/context-compressor.d.ts.map +1 -1
- package/dist/context-compressor.js +22 -17
- package/dist/context-compressor.js.map +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +8 -7
- package/dist/conversation.js.map +1 -1
- package/dist/gui-subagent/action-parser/actionParser.js +2 -2
- package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.d.ts +10 -0
- package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.js +105 -32
- package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
- package/dist/gui-subagent/index.d.ts +7 -0
- package/dist/gui-subagent/index.d.ts.map +1 -1
- package/dist/gui-subagent/index.js +2 -0
- package/dist/gui-subagent/index.js.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.js +2 -0
- package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
- package/dist/input-processor.js +2 -2
- package/dist/input-processor.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +84 -21
- package/dist/mcp.js.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +3 -3
- package/dist/memory.js.map +1 -1
- package/dist/output-util.d.ts +27 -0
- package/dist/output-util.d.ts.map +1 -0
- package/dist/output-util.js +74 -0
- package/dist/output-util.js.map +1 -0
- package/dist/retry.js +1 -1
- package/dist/retry.js.map +1 -1
- package/dist/ripgrep.d.ts.map +1 -1
- package/dist/ripgrep.js +5 -3
- package/dist/ripgrep.js.map +1 -1
- package/dist/sdk-output-adapter.d.ts +265 -0
- package/dist/sdk-output-adapter.d.ts.map +1 -0
- package/dist/sdk-output-adapter.js +701 -0
- package/dist/sdk-output-adapter.js.map +1 -0
- package/dist/sdk-session.d.ts +13 -0
- package/dist/sdk-session.d.ts.map +1 -0
- package/dist/sdk-session.js +50 -0
- package/dist/sdk-session.js.map +1 -0
- package/dist/session-manager.js +3 -3
- package/dist/session-manager.js.map +1 -1
- package/dist/session.d.ts +96 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +849 -262
- package/dist/session.js.map +1 -1
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +5 -4
- package/dist/shell.js.map +1 -1
- package/dist/skill-installer.js +3 -3
- package/dist/skill-installer.js.map +1 -1
- package/dist/skill-invoker.d.ts +1 -1
- package/dist/skill-invoker.d.ts.map +1 -1
- package/dist/skill-invoker.js +2 -2
- package/dist/skill-invoker.js.map +1 -1
- package/dist/skill-loader.js +6 -5
- package/dist/skill-loader.js.map +1 -1
- package/dist/skill-manager.d.ts.map +1 -1
- package/dist/skill-manager.js +3 -2
- package/dist/skill-manager.js.map +1 -1
- package/dist/slash-commands.d.ts +1 -1
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +24 -11
- package/dist/slash-commands.js.map +1 -1
- package/dist/smart-approval.d.ts +20 -1
- package/dist/smart-approval.d.ts.map +1 -1
- package/dist/smart-approval.js +58 -1
- package/dist/smart-approval.js.map +1 -1
- package/dist/system-prompt-generator.js +3 -3
- package/dist/system-prompt-generator.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +9 -8
- package/dist/theme.js.map +1 -1
- package/dist/tools.d.ts +15 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +487 -215
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +49 -0
- package/dist/types.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +12 -9
- package/dist/update.js.map +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +1 -2
- package/dist/workflow.js.map +1 -1
- package/docs/third-party-models.md +16 -15
- package/package.json +3 -1
- package/src/agents.ts +7 -3
- package/src/ai-client/factory.ts +1 -36
- package/src/ai-client/index.ts +1 -1
- package/src/ai-client/providers/anthropic.ts +12 -3
- package/src/ai-client/providers/openai.ts +10 -4
- package/src/ai-client/providers/remote.ts +13 -10
- package/src/ai-client/types.ts +19 -0
- package/src/ai-client-factory.ts +5 -5
- package/src/auth.ts +11 -13
- package/src/cancellation.ts +3 -6
- package/src/checkpoint.ts +41 -4
- package/src/cli.ts +154 -37
- package/src/config.ts +1 -1
- package/src/context-compressor.ts +27 -22
- package/src/conversation.ts +9 -7
- package/src/gui-subagent/action-parser/actionParser.ts +2 -2
- package/src/gui-subagent/agent/gui-agent.ts +117 -34
- package/src/gui-subagent/index.ts +8 -0
- package/src/gui-subagent/operator/computer-operator.ts +2 -1
- package/src/input-processor.ts +2 -2
- package/src/logger.ts +2 -4
- package/src/mcp.ts +87 -23
- package/src/memory.ts +3 -4
- package/src/output-util.ts +80 -0
- package/src/retry.ts +1 -1
- package/src/ripgrep.ts +5 -3
- package/src/sdk-output-adapter.ts +842 -0
- package/src/sdk-session.ts +62 -0
- package/src/session-manager.ts +3 -3
- package/src/session.ts +942 -302
- package/src/shell.ts +6 -5
- package/src/skill-installer.ts +3 -3
- package/src/skill-invoker.ts +3 -4
- package/src/skill-loader.ts +7 -7
- package/src/skill-manager.ts +4 -3
- package/src/slash-commands.ts +24 -16
- package/src/smart-approval.ts +76 -1
- package/src/system-prompt-generator.ts +3 -3
- package/src/theme.ts +10 -9
- package/src/tools.ts +563 -267
- package/src/types.ts +118 -0
- package/src/update.ts +12 -9
- package/src/workflow.ts +2 -4
- package/test/cli-launch.test.ts +279 -0
- package/vitest.config.ts +2 -0
- /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SDK Output Adapter
|
|
5
|
+
*
|
|
6
|
+
* This module provides output formatting for SDK mode.
|
|
7
|
+
* It converts CLI-style output into JSON format for programmatic consumption.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SessionInput, SessionOutput } from './types.js';
|
|
11
|
+
|
|
12
|
+
// GUI Agent types (re-exported for SDK usage)
|
|
13
|
+
export type GUIAgentStatus = 'init' | 'running' | 'paused' | 'end' | 'error' | 'user_stopped' | 'call_llm';
|
|
14
|
+
|
|
15
|
+
export interface GUIAgentOutput {
|
|
16
|
+
type: 'status' | 'conversation' | 'action' | 'screenshot' | 'error' | 'complete';
|
|
17
|
+
timestamp: number;
|
|
18
|
+
data: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface GUIAgentConversation {
|
|
22
|
+
from: 'human' | 'assistant';
|
|
23
|
+
value: string;
|
|
24
|
+
screenshotBase64?: string;
|
|
25
|
+
screenshotContext?: {
|
|
26
|
+
size: { width: number; height: number };
|
|
27
|
+
mime?: string;
|
|
28
|
+
scaleFactor: number;
|
|
29
|
+
};
|
|
30
|
+
actionType?: string;
|
|
31
|
+
actionInputs?: Record<string, unknown>;
|
|
32
|
+
timing?: {
|
|
33
|
+
start: number;
|
|
34
|
+
end: number;
|
|
35
|
+
cost: number;
|
|
36
|
+
};
|
|
37
|
+
predictionParsed?: Array<{
|
|
38
|
+
action_type: string;
|
|
39
|
+
[key: string]: unknown;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface GUIAgentHandler {
|
|
44
|
+
(output: GUIAgentOutput): void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SdkOutputMessage {
|
|
48
|
+
type: 'output' | 'input' | 'system' | 'tool' | 'error' | 'thinking' | 'result';
|
|
49
|
+
subtype?: string;
|
|
50
|
+
timestamp: number;
|
|
51
|
+
data: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface SdkStreamEvent {
|
|
55
|
+
event_type: string;
|
|
56
|
+
timestamp: number;
|
|
57
|
+
data: Record<string, unknown>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type OutputHandler = (message: SdkOutputMessage) => void;
|
|
61
|
+
|
|
62
|
+
export class SdkOutputAdapter {
|
|
63
|
+
private outputHandler: OutputHandler;
|
|
64
|
+
private indentLevel: number;
|
|
65
|
+
|
|
66
|
+
constructor(outputHandler?: OutputHandler) {
|
|
67
|
+
this.outputHandler = outputHandler || ((msg) => {
|
|
68
|
+
process.stdout.write(JSON.stringify(msg) + '\n');
|
|
69
|
+
});
|
|
70
|
+
this.indentLevel = 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Set indent level for output formatting.
|
|
75
|
+
*/
|
|
76
|
+
setIndentLevel(level: number): void {
|
|
77
|
+
this.indentLevel = level;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get current indent string.
|
|
82
|
+
*/
|
|
83
|
+
getIndent(): string {
|
|
84
|
+
return ' '.repeat(this.indentLevel);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Format and output a welcome message.
|
|
89
|
+
*/
|
|
90
|
+
outputWelcome(language: 'zh' | 'en', executionMode: string): void {
|
|
91
|
+
const messages = {
|
|
92
|
+
zh: {
|
|
93
|
+
title: '🤖 XAGENT CLI',
|
|
94
|
+
version: 'v1.0.0',
|
|
95
|
+
subtitle: 'AI-powered command-line assistant',
|
|
96
|
+
modeLabel: '当前模式',
|
|
97
|
+
modeDescription: '智能审批与安全检查',
|
|
98
|
+
help: '输入 /help 查看可用命令'
|
|
99
|
+
},
|
|
100
|
+
en: {
|
|
101
|
+
title: '🤖 XAGENT CLI',
|
|
102
|
+
version: 'v1.0.0',
|
|
103
|
+
subtitle: 'AI-powered command-line assistant',
|
|
104
|
+
modeLabel: 'Current Mode',
|
|
105
|
+
modeDescription: 'Smart approval with intelligent security checks',
|
|
106
|
+
help: 'Type /help to see available commands'
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const msg = messages[language];
|
|
111
|
+
const config = this.getModeConfig(executionMode);
|
|
112
|
+
|
|
113
|
+
this.output({
|
|
114
|
+
type: 'system',
|
|
115
|
+
subtype: 'welcome',
|
|
116
|
+
timestamp: Date.now(),
|
|
117
|
+
data: {
|
|
118
|
+
title: msg.title,
|
|
119
|
+
version: msg.version,
|
|
120
|
+
subtitle: msg.subtitle,
|
|
121
|
+
mode: {
|
|
122
|
+
name: executionMode,
|
|
123
|
+
icon: config.icon,
|
|
124
|
+
description: msg.modeDescription
|
|
125
|
+
},
|
|
126
|
+
help: msg.help
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Format and output ready signal.
|
|
133
|
+
* This is sent when the CLI is fully initialized and ready to accept requests.
|
|
134
|
+
*/
|
|
135
|
+
outputReady(): void {
|
|
136
|
+
this.output({
|
|
137
|
+
type: 'system',
|
|
138
|
+
subtype: 'ready',
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
data: {
|
|
141
|
+
status: 'initialized',
|
|
142
|
+
message: 'CLI is ready to accept requests'
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Format and output request done signal.
|
|
149
|
+
* This is sent when a user request has been fully processed.
|
|
150
|
+
*/
|
|
151
|
+
outputRequestDone(requestId: string, status: 'success' | 'cancelled' | 'error' = 'success'): void {
|
|
152
|
+
this.output({
|
|
153
|
+
type: 'result',
|
|
154
|
+
subtype: 'request_done',
|
|
155
|
+
timestamp: Date.now(),
|
|
156
|
+
data: {
|
|
157
|
+
requestId,
|
|
158
|
+
status,
|
|
159
|
+
message: status === 'success' ? 'Request completed successfully' : `Request ${status}`
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Format and output AI response.
|
|
166
|
+
*/
|
|
167
|
+
outputAssistant(content: string, reasoningContent?: string): void {
|
|
168
|
+
this.output({
|
|
169
|
+
type: 'output',
|
|
170
|
+
subtype: 'assistant',
|
|
171
|
+
timestamp: Date.now(),
|
|
172
|
+
data: {
|
|
173
|
+
content,
|
|
174
|
+
reasoningContent
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Format and output tool execution.
|
|
181
|
+
*/
|
|
182
|
+
outputToolStart(toolName: string, params: Record<string, unknown>): void {
|
|
183
|
+
this.output({
|
|
184
|
+
type: 'tool',
|
|
185
|
+
subtype: 'start',
|
|
186
|
+
timestamp: Date.now(),
|
|
187
|
+
data: {
|
|
188
|
+
tool: toolName,
|
|
189
|
+
params,
|
|
190
|
+
status: 'running'
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format and output tool result.
|
|
197
|
+
*/
|
|
198
|
+
outputToolResult(toolName: string, result: unknown, duration?: number): void {
|
|
199
|
+
this.output({
|
|
200
|
+
type: 'tool',
|
|
201
|
+
subtype: 'result',
|
|
202
|
+
timestamp: Date.now(),
|
|
203
|
+
data: {
|
|
204
|
+
tool: toolName,
|
|
205
|
+
result,
|
|
206
|
+
duration,
|
|
207
|
+
status: 'completed'
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Format and output tool error.
|
|
214
|
+
*/
|
|
215
|
+
outputToolError(toolName: string, error: string): void {
|
|
216
|
+
this.output({
|
|
217
|
+
type: 'tool',
|
|
218
|
+
subtype: 'error',
|
|
219
|
+
timestamp: Date.now(),
|
|
220
|
+
data: {
|
|
221
|
+
tool: toolName,
|
|
222
|
+
error,
|
|
223
|
+
status: 'error'
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Format and output thinking content.
|
|
230
|
+
*/
|
|
231
|
+
outputThinking(reasoningContent: string, displayMode: string = 'compact'): void {
|
|
232
|
+
const maxLength = displayMode === 'full' ? undefined : 500;
|
|
233
|
+
const truncated = maxLength && reasoningContent.length > maxLength;
|
|
234
|
+
const displayContent = truncated ? reasoningContent.substring(0, maxLength) + '... (truncated)' : reasoningContent;
|
|
235
|
+
|
|
236
|
+
this.output({
|
|
237
|
+
type: 'thinking',
|
|
238
|
+
subtype: displayMode,
|
|
239
|
+
timestamp: Date.now(),
|
|
240
|
+
data: {
|
|
241
|
+
content: displayContent,
|
|
242
|
+
originalLength: reasoningContent.length,
|
|
243
|
+
truncated,
|
|
244
|
+
displayMode
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Format and output system message.
|
|
251
|
+
*/
|
|
252
|
+
outputSystem(subtype: string, data: Record<string, unknown>): void {
|
|
253
|
+
this.output({
|
|
254
|
+
type: 'system',
|
|
255
|
+
subtype,
|
|
256
|
+
timestamp: Date.now(),
|
|
257
|
+
data
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Format and output MCP loading status.
|
|
263
|
+
*/
|
|
264
|
+
outputMCPLoading(count: number): void {
|
|
265
|
+
this.output({
|
|
266
|
+
type: 'system',
|
|
267
|
+
subtype: 'mcp_loading',
|
|
268
|
+
timestamp: Date.now(),
|
|
269
|
+
data: { count }
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Format and output MCP server registering status.
|
|
275
|
+
*/
|
|
276
|
+
outputMCPRegistering(name: string, transport: string): void {
|
|
277
|
+
this.output({
|
|
278
|
+
type: 'system',
|
|
279
|
+
subtype: 'mcp_registering',
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
data: { name, transport }
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Format and output MCP connecting status.
|
|
287
|
+
*/
|
|
288
|
+
outputMCPConnecting(count: number): void {
|
|
289
|
+
this.output({
|
|
290
|
+
type: 'system',
|
|
291
|
+
subtype: 'mcp_connecting',
|
|
292
|
+
timestamp: Date.now(),
|
|
293
|
+
data: { count }
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Format and output MCP connected result.
|
|
299
|
+
*/
|
|
300
|
+
outputMCPConnected(total: number, connected: number, toolsAvailable: number): void {
|
|
301
|
+
this.output({
|
|
302
|
+
type: 'system',
|
|
303
|
+
subtype: 'mcp_connected',
|
|
304
|
+
timestamp: Date.now(),
|
|
305
|
+
data: { total, connected, toolsAvailable }
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Format and output MCP connection failed warning.
|
|
311
|
+
*/
|
|
312
|
+
outputMCPConnectionFailed(message: string): void {
|
|
313
|
+
this.output({
|
|
314
|
+
type: 'system',
|
|
315
|
+
subtype: 'mcp_connection_failed',
|
|
316
|
+
timestamp: Date.now(),
|
|
317
|
+
data: { message }
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Format and output error message.
|
|
323
|
+
*/
|
|
324
|
+
outputError(message: string, context?: Record<string, unknown>): void {
|
|
325
|
+
this.output({
|
|
326
|
+
type: 'error',
|
|
327
|
+
subtype: 'general',
|
|
328
|
+
timestamp: Date.now(),
|
|
329
|
+
data: {
|
|
330
|
+
message,
|
|
331
|
+
...context
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Format and output warning message.
|
|
338
|
+
*/
|
|
339
|
+
outputWarning(message: string): void {
|
|
340
|
+
this.output({
|
|
341
|
+
type: 'system',
|
|
342
|
+
subtype: 'warning',
|
|
343
|
+
timestamp: Date.now(),
|
|
344
|
+
data: { message }
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Format and output success message.
|
|
350
|
+
*/
|
|
351
|
+
outputSuccess(message: string): void {
|
|
352
|
+
this.output({
|
|
353
|
+
type: 'system',
|
|
354
|
+
subtype: 'success',
|
|
355
|
+
timestamp: Date.now(),
|
|
356
|
+
data: { message }
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Format and output info message.
|
|
362
|
+
*/
|
|
363
|
+
outputInfo(message: string): void {
|
|
364
|
+
this.output({
|
|
365
|
+
type: 'system',
|
|
366
|
+
subtype: 'info',
|
|
367
|
+
timestamp: Date.now(),
|
|
368
|
+
data: { message }
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Format and output context compression notification.
|
|
374
|
+
*/
|
|
375
|
+
outputContextCompression(reason: string, originalSize: number, compressedSize: number, reductionPercent: number): void {
|
|
376
|
+
this.output({
|
|
377
|
+
type: 'system',
|
|
378
|
+
subtype: 'context_compression',
|
|
379
|
+
timestamp: Date.now(),
|
|
380
|
+
data: {
|
|
381
|
+
reason,
|
|
382
|
+
originalSize,
|
|
383
|
+
compressedSize,
|
|
384
|
+
reductionPercent
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Format and output context compression triggered.
|
|
391
|
+
*/
|
|
392
|
+
outputContextCompressionTriggered(reason: string): void {
|
|
393
|
+
this.output({
|
|
394
|
+
type: 'system',
|
|
395
|
+
subtype: 'context_compression_triggered',
|
|
396
|
+
timestamp: Date.now(),
|
|
397
|
+
data: { reason }
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Format and output context compression result.
|
|
403
|
+
*/
|
|
404
|
+
outputContextCompressionResult(
|
|
405
|
+
originalSize: number,
|
|
406
|
+
compressedSize: number,
|
|
407
|
+
reductionPercent: number,
|
|
408
|
+
originalMessageCount: number,
|
|
409
|
+
compressedMessageCount: number
|
|
410
|
+
): void {
|
|
411
|
+
this.output({
|
|
412
|
+
type: 'system',
|
|
413
|
+
subtype: 'context_compression_result',
|
|
414
|
+
timestamp: Date.now(),
|
|
415
|
+
data: {
|
|
416
|
+
originalSize,
|
|
417
|
+
compressedSize,
|
|
418
|
+
reductionPercent,
|
|
419
|
+
originalMessageCount,
|
|
420
|
+
compressedMessageCount
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Format and output context compression summary.
|
|
427
|
+
*/
|
|
428
|
+
outputContextCompressionSummary(
|
|
429
|
+
summary: string,
|
|
430
|
+
preview: string,
|
|
431
|
+
isTruncated: boolean,
|
|
432
|
+
totalLength: number
|
|
433
|
+
): void {
|
|
434
|
+
this.output({
|
|
435
|
+
type: 'system',
|
|
436
|
+
subtype: 'context_compression_summary',
|
|
437
|
+
timestamp: Date.now(),
|
|
438
|
+
data: {
|
|
439
|
+
summary,
|
|
440
|
+
preview,
|
|
441
|
+
isTruncated,
|
|
442
|
+
totalLength
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Format and output session result.
|
|
449
|
+
*/
|
|
450
|
+
outputResult(duration: number, numTurns: number, status: 'completed' | 'cancelled' | 'error'): void {
|
|
451
|
+
this.output({
|
|
452
|
+
type: 'result',
|
|
453
|
+
timestamp: Date.now(),
|
|
454
|
+
data: {
|
|
455
|
+
duration_ms: duration,
|
|
456
|
+
num_turns: numTurns,
|
|
457
|
+
status
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Format and output progress/spinner.
|
|
464
|
+
*/
|
|
465
|
+
outputProgress(text: string, status: 'start' | 'succeed' | 'fail' | 'update'): void {
|
|
466
|
+
this.output({
|
|
467
|
+
type: 'system',
|
|
468
|
+
subtype: 'progress',
|
|
469
|
+
timestamp: Date.now(),
|
|
470
|
+
data: {
|
|
471
|
+
text,
|
|
472
|
+
status
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Format and output agent switch.
|
|
479
|
+
*/
|
|
480
|
+
outputAgentSwitch(agentName: string, agentDescription?: string): void {
|
|
481
|
+
this.output({
|
|
482
|
+
type: 'system',
|
|
483
|
+
subtype: 'agent_switch',
|
|
484
|
+
timestamp: Date.now(),
|
|
485
|
+
data: {
|
|
486
|
+
agent: agentName,
|
|
487
|
+
description: agentDescription
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Format and output command execution.
|
|
494
|
+
*/
|
|
495
|
+
outputCommand(command: string, status: 'running' | 'completed' | 'error'): void {
|
|
496
|
+
this.output({
|
|
497
|
+
type: 'tool',
|
|
498
|
+
subtype: 'command',
|
|
499
|
+
timestamp: Date.now(),
|
|
500
|
+
data: {
|
|
501
|
+
command,
|
|
502
|
+
status
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// ==================== SDK Approval Request ====================
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Format and output approval request (for SDK mode).
|
|
511
|
+
* This is sent when a potentially risky operation needs user confirmation.
|
|
512
|
+
*/
|
|
513
|
+
outputApprovalRequest(params: {
|
|
514
|
+
requestId: string;
|
|
515
|
+
toolName: string;
|
|
516
|
+
params: Record<string, unknown>;
|
|
517
|
+
riskLevel: string;
|
|
518
|
+
description: string;
|
|
519
|
+
aiAnalysis?: string;
|
|
520
|
+
}): void {
|
|
521
|
+
this.output({
|
|
522
|
+
type: 'system',
|
|
523
|
+
subtype: 'approval_request',
|
|
524
|
+
timestamp: Date.now(),
|
|
525
|
+
data: {
|
|
526
|
+
requestId: params.requestId,
|
|
527
|
+
toolName: params.toolName,
|
|
528
|
+
params: params.params,
|
|
529
|
+
riskLevel: params.riskLevel,
|
|
530
|
+
description: params.description,
|
|
531
|
+
aiAnalysis: params.aiAnalysis,
|
|
532
|
+
approved: false // Default to not approved, client must respond
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Format and output approval response received (for SDK mode logging).
|
|
539
|
+
*/
|
|
540
|
+
outputApprovalResponse(requestId: string, approved: boolean): void {
|
|
541
|
+
this.output({
|
|
542
|
+
type: 'system',
|
|
543
|
+
subtype: 'approval_response',
|
|
544
|
+
timestamp: Date.now(),
|
|
545
|
+
data: {
|
|
546
|
+
requestId,
|
|
547
|
+
approved
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// ==================== SDK Question Request ====================
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Format and output question request (for SDK mode).
|
|
556
|
+
* This is sent when the agent needs to ask the user questions.
|
|
557
|
+
*/
|
|
558
|
+
outputQuestionRequest(params: {
|
|
559
|
+
requestId: string;
|
|
560
|
+
questions: Array<{
|
|
561
|
+
question: string;
|
|
562
|
+
header?: string;
|
|
563
|
+
options?: string[];
|
|
564
|
+
multiSelect?: boolean;
|
|
565
|
+
}>;
|
|
566
|
+
}): void {
|
|
567
|
+
this.output({
|
|
568
|
+
type: 'system',
|
|
569
|
+
subtype: 'question_request',
|
|
570
|
+
timestamp: Date.now(),
|
|
571
|
+
data: {
|
|
572
|
+
requestId: params.requestId,
|
|
573
|
+
questions: params.questions
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Format and output question response received (for SDK mode logging).
|
|
580
|
+
*/
|
|
581
|
+
outputQuestionResponse(requestId: string, answers: string[]): void {
|
|
582
|
+
this.output({
|
|
583
|
+
type: 'system',
|
|
584
|
+
subtype: 'question_response',
|
|
585
|
+
timestamp: Date.now(),
|
|
586
|
+
data: {
|
|
587
|
+
requestId,
|
|
588
|
+
answers
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// ==================== GUI Agent Output Methods ====================
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Format and output GUI agent start.
|
|
597
|
+
*/
|
|
598
|
+
outputGUIAgentStart(description: string, mode: 'local' | 'remote'): void {
|
|
599
|
+
this.output({
|
|
600
|
+
type: 'system',
|
|
601
|
+
subtype: 'gui_agent_start',
|
|
602
|
+
timestamp: Date.now(),
|
|
603
|
+
data: {
|
|
604
|
+
description,
|
|
605
|
+
mode
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Format and output GUI agent status update.
|
|
612
|
+
*/
|
|
613
|
+
outputGUIAgentStatus(status: GUIAgentStatus, iteration?: number, error?: string): void {
|
|
614
|
+
this.output({
|
|
615
|
+
type: 'system',
|
|
616
|
+
subtype: `gui_status_${status}`,
|
|
617
|
+
timestamp: Date.now(),
|
|
618
|
+
data: {
|
|
619
|
+
status,
|
|
620
|
+
iteration,
|
|
621
|
+
error
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Format and output GUI agent action/step.
|
|
628
|
+
*/
|
|
629
|
+
outputGUIAgentAction(iteration: number, actionType: string, cost?: number): void {
|
|
630
|
+
this.output({
|
|
631
|
+
type: 'output',
|
|
632
|
+
subtype: 'gui_action',
|
|
633
|
+
timestamp: Date.now(),
|
|
634
|
+
data: {
|
|
635
|
+
iteration,
|
|
636
|
+
actionType,
|
|
637
|
+
cost
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Format and output GUI agent conversation (screenshot).
|
|
644
|
+
*/
|
|
645
|
+
outputGUIConversation(data: {
|
|
646
|
+
iteration: number;
|
|
647
|
+
from: 'human' | 'assistant';
|
|
648
|
+
actionType?: string;
|
|
649
|
+
indentLevel?: number;
|
|
650
|
+
timing?: { start: number; end: number; cost: number };
|
|
651
|
+
}): void {
|
|
652
|
+
this.output({
|
|
653
|
+
type: 'output',
|
|
654
|
+
subtype: 'gui_conversation',
|
|
655
|
+
timestamp: Date.now(),
|
|
656
|
+
data
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Format and output GUI agent completion.
|
|
662
|
+
*/
|
|
663
|
+
outputGUIAgentComplete(description: string, iterations: number): void {
|
|
664
|
+
this.output({
|
|
665
|
+
type: 'system',
|
|
666
|
+
subtype: 'gui_complete',
|
|
667
|
+
timestamp: Date.now(),
|
|
668
|
+
data: {
|
|
669
|
+
description,
|
|
670
|
+
iterations,
|
|
671
|
+
message: `GUI task completed in ${iterations} iterations`
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Format and output GUI agent cancellation.
|
|
678
|
+
*/
|
|
679
|
+
outputGUIAgentCancelled(description: string): void {
|
|
680
|
+
this.output({
|
|
681
|
+
type: 'system',
|
|
682
|
+
subtype: 'gui_cancelled',
|
|
683
|
+
timestamp: Date.now(),
|
|
684
|
+
data: {
|
|
685
|
+
description,
|
|
686
|
+
message: 'GUI task cancelled by user'
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Format and output GUI agent error.
|
|
693
|
+
*/
|
|
694
|
+
outputGUIAgentError(description: string, error: string): void {
|
|
695
|
+
this.output({
|
|
696
|
+
type: 'error',
|
|
697
|
+
subtype: 'gui_error',
|
|
698
|
+
timestamp: Date.now(),
|
|
699
|
+
data: {
|
|
700
|
+
description,
|
|
701
|
+
error
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Create a GUI Agent output handler that maps GUIAgentOutput to SDK format.
|
|
708
|
+
* This handler can be passed directly to GUIAgent.
|
|
709
|
+
*/
|
|
710
|
+
createGUIAgentHandler(): GUIAgentHandler {
|
|
711
|
+
return (output: GUIAgentOutput) => {
|
|
712
|
+
switch (output.type) {
|
|
713
|
+
case 'action':
|
|
714
|
+
this.output({
|
|
715
|
+
type: 'system',
|
|
716
|
+
subtype: 'gui_action',
|
|
717
|
+
timestamp: output.timestamp,
|
|
718
|
+
data: output.data
|
|
719
|
+
});
|
|
720
|
+
break;
|
|
721
|
+
case 'status':
|
|
722
|
+
this.outputGUIAgentStatus(
|
|
723
|
+
output.data.status as GUIAgentStatus,
|
|
724
|
+
output.data.iteration as number | undefined,
|
|
725
|
+
output.data.error as string | undefined
|
|
726
|
+
);
|
|
727
|
+
break;
|
|
728
|
+
case 'conversation':
|
|
729
|
+
this.outputGUIConversation({
|
|
730
|
+
iteration: output.data.iteration as number,
|
|
731
|
+
from: output.data.from as 'human' | 'assistant',
|
|
732
|
+
actionType: output.data.actionType as string | undefined,
|
|
733
|
+
indentLevel: output.data.indentLevel as number | undefined,
|
|
734
|
+
timing: output.data.timing as { start: number; end: number; cost: number } | undefined
|
|
735
|
+
});
|
|
736
|
+
break;
|
|
737
|
+
case 'complete':
|
|
738
|
+
this.output({
|
|
739
|
+
type: 'system',
|
|
740
|
+
subtype: 'gui_complete',
|
|
741
|
+
timestamp: output.timestamp,
|
|
742
|
+
data: output.data
|
|
743
|
+
});
|
|
744
|
+
break;
|
|
745
|
+
case 'error':
|
|
746
|
+
this.output({
|
|
747
|
+
type: 'error',
|
|
748
|
+
subtype: 'gui_error',
|
|
749
|
+
timestamp: output.timestamp,
|
|
750
|
+
data: output.data
|
|
751
|
+
});
|
|
752
|
+
break;
|
|
753
|
+
case 'screenshot':
|
|
754
|
+
this.output({
|
|
755
|
+
type: 'output',
|
|
756
|
+
subtype: 'gui_screenshot',
|
|
757
|
+
timestamp: output.timestamp,
|
|
758
|
+
data: output.data
|
|
759
|
+
});
|
|
760
|
+
break;
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Output a raw message.
|
|
767
|
+
*/
|
|
768
|
+
output(message: SdkOutputMessage): void {
|
|
769
|
+
this.outputHandler(message);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Get mode configuration.
|
|
774
|
+
*/
|
|
775
|
+
private getModeConfig(mode: string): { color: string; icon: string; description: string } {
|
|
776
|
+
const modeConfigs: Record<string, { color: string; icon: string; description: string }> = {
|
|
777
|
+
yolo: {
|
|
778
|
+
color: 'red',
|
|
779
|
+
icon: '🔥',
|
|
780
|
+
description: 'Execute commands without confirmation'
|
|
781
|
+
},
|
|
782
|
+
accept_edits: {
|
|
783
|
+
color: 'yellow',
|
|
784
|
+
icon: '✅',
|
|
785
|
+
description: 'Accept all edits automatically'
|
|
786
|
+
},
|
|
787
|
+
plan: {
|
|
788
|
+
color: 'blue',
|
|
789
|
+
icon: '🧠',
|
|
790
|
+
description: 'Plan before executing'
|
|
791
|
+
},
|
|
792
|
+
default: {
|
|
793
|
+
color: 'green',
|
|
794
|
+
icon: '⚡',
|
|
795
|
+
description: 'Safe execution with confirmations'
|
|
796
|
+
},
|
|
797
|
+
smart: {
|
|
798
|
+
color: 'cyan',
|
|
799
|
+
icon: '✨',
|
|
800
|
+
description: 'Smart approval with intelligent security checks'
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
return modeConfigs[mode.toLowerCase()] || modeConfigs.default;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Convert a SessionInput to SDK format.
|
|
809
|
+
*/
|
|
810
|
+
static formatSessionInput(input: SessionInput): SdkOutputMessage {
|
|
811
|
+
return {
|
|
812
|
+
type: 'input',
|
|
813
|
+
timestamp: input.timestamp,
|
|
814
|
+
data: {
|
|
815
|
+
inputType: input.type,
|
|
816
|
+
content: input.content,
|
|
817
|
+
rawInput: input.rawInput,
|
|
818
|
+
filePath: input.filePath
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Convert a SessionOutput to SDK format.
|
|
825
|
+
*/
|
|
826
|
+
static formatSessionOutput(output: SessionOutput): SdkOutputMessage {
|
|
827
|
+
return {
|
|
828
|
+
type: 'output',
|
|
829
|
+
timestamp: output.timestamp,
|
|
830
|
+
data: {
|
|
831
|
+
role: output.role,
|
|
832
|
+
content: output.content,
|
|
833
|
+
toolName: output.toolName,
|
|
834
|
+
toolParams: output.toolParams,
|
|
835
|
+
toolResult: output.toolResult,
|
|
836
|
+
duration: output.duration,
|
|
837
|
+
reasoning_content: output.reasoning_content,
|
|
838
|
+
tool_calls: output.tool_calls
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
}
|