@tencent-ai/agent-sdk 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/CHANGELOG.md +17 -0
- package/cli/dist/codebuddy.js +2 -2
- package/cli/package.json +1 -1
- package/cli/product.cloudhosted.json +2 -2
- package/cli/product.internal.json +2 -2
- package/cli/product.ioa.json +2 -2
- package/cli/product.json +2 -2
- package/cli/product.selfhosted.json +2 -2
- package/lib/acp/index.d.ts +6 -7
- package/lib/acp/index.d.ts.map +1 -1
- package/lib/acp/index.js +6 -10
- package/lib/acp/index.js.map +1 -1
- package/lib/acp/tool-converter.d.ts +71 -23
- package/lib/acp/tool-converter.d.ts.map +1 -1
- package/lib/acp/tool-converter.js +573 -387
- package/lib/acp/tool-converter.js.map +1 -1
- package/lib/index.d.ts +0 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -4
- package/lib/index.js.map +1 -1
- package/lib/query.d.ts.map +1 -1
- package/lib/query.js +8 -0
- package/lib/query.js.map +1 -1
- package/lib/session.d.ts +11 -0
- package/lib/session.d.ts.map +1 -1
- package/lib/session.js +129 -3
- package/lib/session.js.map +1 -1
- package/lib/transport/index.d.ts +2 -0
- package/lib/transport/index.d.ts.map +1 -1
- package/lib/transport/index.js.map +1 -1
- package/lib/transport/process-transport.d.ts.map +1 -1
- package/lib/transport/process-transport.js +3 -0
- package/lib/transport/process-transport.js.map +1 -1
- package/lib/types.d.ts +10 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/package.json +1 -1
- package/lib/acp/acp-client.d.ts +0 -62
- package/lib/acp/acp-client.d.ts.map +0 -1
- package/lib/acp/acp-client.js +0 -256
- package/lib/acp/acp-client.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* ACP Message Transformer
|
|
4
4
|
*
|
|
5
5
|
* Converts SDK internal tool formats to ACP (Agent Client Protocol) format and vice versa.
|
|
6
6
|
*
|
|
@@ -12,426 +12,612 @@
|
|
|
12
12
|
* - Tool results are preserved with error state tracking
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.
|
|
16
|
-
|
|
17
|
-
exports.extractToolUseBlocks = extractToolUseBlocks;
|
|
18
|
-
exports.extractTextContent = extractTextContent;
|
|
19
|
-
// ============= Conversion: SDK Tool Use → ACP Tool Call =============
|
|
15
|
+
exports.AcpTransformer = void 0;
|
|
16
|
+
// ============= ACP Message Transformer (Stateless Utility) =============
|
|
20
17
|
/**
|
|
21
|
-
*
|
|
22
|
-
* Preserves all input data in rawInput field
|
|
18
|
+
* Bidirectional converter between SDK internal format (JSON Lines) and ACP (Agent Client Protocol) format.
|
|
23
19
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* This is an abstract utility class with only static methods - do not instantiate.
|
|
21
|
+
*
|
|
22
|
+
* Key features:
|
|
23
|
+
* - Converts SDK tool use/result to ACP format
|
|
24
|
+
* - Converts ACP messages to SDK format
|
|
25
|
+
* - Extracts and manipulates tool/text blocks
|
|
26
|
+
* - Complete data preservation in roundtrip conversions
|
|
27
|
+
* - Type-safe message routing
|
|
26
28
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
29
|
+
class AcpTransformer {
|
|
30
|
+
// ============= Public API: SDK Tool Use ↔ ACP Tool Call =============
|
|
31
|
+
/**
|
|
32
|
+
* Convert SDK ToolUseContentBlock to ACP Tool Call
|
|
33
|
+
* Preserves all input data in rawInput field
|
|
34
|
+
*/
|
|
35
|
+
static convertSdkToolUseToAcpToolCall(toolUse) {
|
|
36
|
+
const toolName = toolUse.name;
|
|
37
|
+
const toolInput = toolUse.input;
|
|
38
|
+
return {
|
|
39
|
+
toolCallId: toolUse.id,
|
|
40
|
+
status: 'pending',
|
|
41
|
+
title: AcpTransformer.generateToolTitle(toolName, toolInput),
|
|
42
|
+
kind: AcpTransformer.getToolKind(toolName),
|
|
43
|
+
rawInput: toolInput,
|
|
44
|
+
content: AcpTransformer.generateToolContent(toolName, toolInput),
|
|
45
|
+
locations: AcpTransformer.extractToolLocations(toolName, toolInput),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// ============= Public API: Bidirectional Tool Conversion =============
|
|
49
|
+
/**
|
|
50
|
+
* Convert ACP Tool Result to SDK ToolResultContentBlock
|
|
51
|
+
* Preserves tool_use_id and ensures error state is tracked
|
|
52
|
+
*/
|
|
53
|
+
static convertAcpToolResultToSdk(toolCallId, acpResult) {
|
|
54
|
+
const isError = acpResult.status === 'failed';
|
|
55
|
+
const content = acpResult.content ? AcpTransformer.formatAcpContentForSdk(acpResult.content) : '';
|
|
56
|
+
return {
|
|
57
|
+
type: 'tool_result',
|
|
58
|
+
tool_use_id: toolCallId,
|
|
59
|
+
content: content,
|
|
60
|
+
is_error: isError,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Convert SDK ToolResultContentBlock to ACP ToolResult
|
|
65
|
+
* Enables bidirectional conversion for tool results
|
|
66
|
+
*/
|
|
67
|
+
static convertSdkToolResultToAcpToolResult(toolResult) {
|
|
68
|
+
const content = [];
|
|
69
|
+
if (toolResult.content) {
|
|
70
|
+
if (typeof toolResult.content === 'string') {
|
|
71
|
+
if (toolResult.content) {
|
|
72
|
+
content.push({
|
|
73
|
+
type: 'content',
|
|
74
|
+
content: { type: 'text', text: toolResult.content },
|
|
75
|
+
});
|
|
76
|
+
}
|
|
52
77
|
}
|
|
53
|
-
else if (
|
|
54
|
-
|
|
78
|
+
else if (Array.isArray(toolResult.content)) {
|
|
79
|
+
for (const block of toolResult.content) {
|
|
80
|
+
if ('type' in block && block.type === 'text') {
|
|
81
|
+
const textBlock = block;
|
|
82
|
+
content.push({
|
|
83
|
+
type: 'content',
|
|
84
|
+
content: { type: 'text', text: textBlock.text },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
55
88
|
}
|
|
56
|
-
return `Read ${filePath}`;
|
|
57
|
-
}
|
|
58
|
-
case 'Write':
|
|
59
|
-
case 'write': {
|
|
60
|
-
const filePath = input.file_path;
|
|
61
|
-
return filePath ? `Write ${filePath}` : 'Write';
|
|
62
|
-
}
|
|
63
|
-
case 'Edit':
|
|
64
|
-
case 'edit':
|
|
65
|
-
case 'MultiEdit': {
|
|
66
|
-
const filePath = input.file_path;
|
|
67
|
-
return filePath ? `Edit \`${filePath}\`` : 'Edit';
|
|
68
|
-
}
|
|
69
|
-
case 'Bash':
|
|
70
|
-
case 'bash': {
|
|
71
|
-
const command = input.command;
|
|
72
|
-
if (!command)
|
|
73
|
-
return 'Terminal';
|
|
74
|
-
// Escape backticks in command (replace all occurrences)
|
|
75
|
-
const escaped = command.split('`').join('\\`');
|
|
76
|
-
return `\`${escaped}\``;
|
|
77
|
-
}
|
|
78
|
-
case 'BashOutput':
|
|
79
|
-
case 'bash_output':
|
|
80
|
-
return 'Tail Logs';
|
|
81
|
-
case 'KillShell':
|
|
82
|
-
case 'kill_shell':
|
|
83
|
-
return 'Kill Process';
|
|
84
|
-
case 'Glob':
|
|
85
|
-
case 'glob': {
|
|
86
|
-
let label = 'Find';
|
|
87
|
-
const path = input.path;
|
|
88
|
-
const pattern = input.pattern;
|
|
89
|
-
if (path)
|
|
90
|
-
label += ` \`${path}\``;
|
|
91
|
-
if (pattern)
|
|
92
|
-
label += ` \`${pattern}\``;
|
|
93
|
-
return label;
|
|
94
|
-
}
|
|
95
|
-
case 'Grep':
|
|
96
|
-
case 'grep': {
|
|
97
|
-
let label = 'grep';
|
|
98
|
-
// Add flags
|
|
99
|
-
if (input['-i'])
|
|
100
|
-
label += ' -i';
|
|
101
|
-
if (input['-n'])
|
|
102
|
-
label += ' -n';
|
|
103
|
-
if (input['-C'] !== undefined)
|
|
104
|
-
label += ` -C ${input['-C']}`;
|
|
105
|
-
if (input['-A'] !== undefined)
|
|
106
|
-
label += ` -A ${input['-A']}`;
|
|
107
|
-
if (input['-B'] !== undefined)
|
|
108
|
-
label += ` -B ${input['-B']}`;
|
|
109
|
-
if (input.multiline)
|
|
110
|
-
label += ' -P';
|
|
111
|
-
if (input.glob)
|
|
112
|
-
label += ` --include="${input.glob}"`;
|
|
113
|
-
if (input.type)
|
|
114
|
-
label += ` --type=${input.type}`;
|
|
115
|
-
// Add pattern and path
|
|
116
|
-
const pattern = input.pattern;
|
|
117
|
-
const path = input.path;
|
|
118
|
-
if (pattern)
|
|
119
|
-
label += ` "${pattern}"`;
|
|
120
|
-
if (path)
|
|
121
|
-
label += ` ${path}`;
|
|
122
|
-
return label;
|
|
123
|
-
}
|
|
124
|
-
case 'WebFetch':
|
|
125
|
-
case 'web_fetch': {
|
|
126
|
-
const url = input.url;
|
|
127
|
-
return url ? `Fetch ${url}` : 'Fetch';
|
|
128
|
-
}
|
|
129
|
-
case 'WebSearch':
|
|
130
|
-
case 'web_search': {
|
|
131
|
-
const query = input.query;
|
|
132
|
-
if (!query)
|
|
133
|
-
return 'Search';
|
|
134
|
-
let label = `"${query}"`;
|
|
135
|
-
const allowedDomains = input.allowed_domains;
|
|
136
|
-
const blockedDomains = input.blocked_domains;
|
|
137
|
-
if (allowedDomains === null || allowedDomains === void 0 ? void 0 : allowedDomains.length)
|
|
138
|
-
label += ` (allowed: ${allowedDomains.join(', ')})`;
|
|
139
|
-
if (blockedDomains === null || blockedDomains === void 0 ? void 0 : blockedDomains.length)
|
|
140
|
-
label += ` (blocked: ${blockedDomains.join(', ')})`;
|
|
141
|
-
return label;
|
|
142
89
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
90
|
+
return {
|
|
91
|
+
toolCallId: toolResult.tool_use_id,
|
|
92
|
+
status: toolResult.is_error ? 'failed' : 'completed',
|
|
93
|
+
content: content.length > 0 ? content : undefined,
|
|
94
|
+
rawOutput: toolResult.content,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// ============= Public API: Message Transformation =============
|
|
98
|
+
/**
|
|
99
|
+
* Convert ACP message to SDK internal format (JSON Lines)
|
|
100
|
+
*
|
|
101
|
+
* Converts all ACP message types to corresponding SDK messages:
|
|
102
|
+
* - session/prompt: User input → UserMessage
|
|
103
|
+
* - session/cancel: Cancellation request → ControlRequest
|
|
104
|
+
* - session/update (tool_call_update): Tool result → UserMessage with tool_result block
|
|
105
|
+
*/
|
|
106
|
+
static acpToSdk(acpMessage) {
|
|
107
|
+
if (acpMessage.method === 'session/prompt') {
|
|
108
|
+
const params = acpMessage.params;
|
|
109
|
+
const sessionId = params === null || params === void 0 ? void 0 : params.sessionId;
|
|
110
|
+
const prompt = params === null || params === void 0 ? void 0 : params.prompt;
|
|
111
|
+
const content = AcpTransformer.privateExtractPromptText(prompt);
|
|
112
|
+
return {
|
|
113
|
+
type: 'user',
|
|
114
|
+
session_id: sessionId || 'unknown',
|
|
115
|
+
message: {
|
|
116
|
+
role: 'user',
|
|
117
|
+
content: content,
|
|
118
|
+
},
|
|
119
|
+
parent_tool_use_id: null,
|
|
120
|
+
};
|
|
147
121
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
122
|
+
if (acpMessage.method === 'session/cancel') {
|
|
123
|
+
return {
|
|
124
|
+
type: 'control_request',
|
|
125
|
+
request: { subtype: 'interrupt' },
|
|
126
|
+
};
|
|
152
127
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
128
|
+
// Handle session/update with tool_call_update
|
|
129
|
+
if (acpMessage.method === 'session/update') {
|
|
130
|
+
const params = acpMessage.params;
|
|
131
|
+
const sessionId = params === null || params === void 0 ? void 0 : params.sessionId;
|
|
132
|
+
const update = params === null || params === void 0 ? void 0 : params.update;
|
|
133
|
+
if ((update === null || update === void 0 ? void 0 : update.sessionUpdate) === 'tool_call_update') {
|
|
134
|
+
// Convert tool_call_update back to SDK tool result format
|
|
135
|
+
const toolCallId = update.toolCallId;
|
|
136
|
+
const status = update.status;
|
|
137
|
+
const content = update.content;
|
|
138
|
+
if (toolCallId) {
|
|
139
|
+
// Create an AcpToolResult from the update
|
|
140
|
+
const acpResult = {
|
|
141
|
+
toolCallId,
|
|
142
|
+
status: status || 'completed',
|
|
143
|
+
content: content,
|
|
144
|
+
};
|
|
145
|
+
return AcpTransformer.privateCreateToolResultMessage({ params: { sessionId } }, acpResult);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
157
148
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Convert SDK internal message to ACP format
|
|
153
|
+
*
|
|
154
|
+
* Converts all SDK message types to corresponding ACP messages:
|
|
155
|
+
* - AssistantMessage with tool_use blocks → tool_call messages
|
|
156
|
+
* - AssistantMessage with text → session/text messages
|
|
157
|
+
* - Other message types are skipped
|
|
158
|
+
*/
|
|
159
|
+
static sdkToAcp(message) {
|
|
160
|
+
const messages = [];
|
|
161
|
+
// Handle assistant messages (contain tool calls and text from the model)
|
|
162
|
+
if ('type' in message && message.type === 'assistant') {
|
|
163
|
+
const assistantMsg = message;
|
|
164
|
+
if (assistantMsg.message.content && Array.isArray(assistantMsg.message.content)) {
|
|
165
|
+
// Extract and convert tool use blocks
|
|
166
|
+
const toolUseBlocks = AcpTransformer.privateExtractToolUseBlocks(assistantMsg.message.content);
|
|
167
|
+
for (const toolUse of toolUseBlocks) {
|
|
168
|
+
const acpToolCall = AcpTransformer.convertSdkToolUseToAcpToolCall(toolUse);
|
|
169
|
+
const toolCallMsg = {
|
|
170
|
+
jsonrpc: '2.0',
|
|
171
|
+
method: 'tool_call',
|
|
172
|
+
params: acpToolCall,
|
|
173
|
+
};
|
|
174
|
+
messages.push(toolCallMsg);
|
|
175
|
+
}
|
|
176
|
+
// Extract and send text content if present
|
|
177
|
+
const textContent = AcpTransformer.privateExtractTextContent(assistantMsg.message.content);
|
|
178
|
+
if (textContent) {
|
|
179
|
+
messages.push({
|
|
180
|
+
jsonrpc: '2.0',
|
|
181
|
+
method: 'session/text',
|
|
182
|
+
params: {
|
|
183
|
+
content: textContent,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return messages;
|
|
188
|
+
}
|
|
161
189
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
190
|
+
// Handle user messages with tool results
|
|
191
|
+
if ('type' in message && message.type === 'user') {
|
|
192
|
+
const userMsg = message;
|
|
193
|
+
if (userMsg.message.content && Array.isArray(userMsg.message.content)) {
|
|
194
|
+
// Look for tool result blocks
|
|
195
|
+
const toolResultBlocks = userMsg.message.content.filter((block) => typeof block === 'object' &&
|
|
196
|
+
block !== null &&
|
|
197
|
+
'type' in block &&
|
|
198
|
+
block.type === 'tool_result');
|
|
199
|
+
// Convert tool results to ACP tool_call_update format (via session/update)
|
|
200
|
+
for (const toolResultBlock of toolResultBlocks) {
|
|
201
|
+
const acpResult = AcpTransformer.convertSdkToolResultToAcpToolResult(toolResultBlock);
|
|
202
|
+
// Wrap tool result as session/update with tool_call_update
|
|
203
|
+
const updateMsg = {
|
|
204
|
+
jsonrpc: '2.0',
|
|
205
|
+
method: 'session/update',
|
|
206
|
+
params: {
|
|
207
|
+
sessionId: userMsg.session_id || 'unknown',
|
|
208
|
+
update: {
|
|
209
|
+
sessionUpdate: 'tool_call_update',
|
|
210
|
+
toolCallId: acpResult.toolCallId,
|
|
211
|
+
status: acpResult.status,
|
|
212
|
+
content: acpResult.content,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
messages.push(updateMsg);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
169
219
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
220
|
+
// Handle result messages (marks the end of a turn)
|
|
221
|
+
if ('type' in message && message.type === 'result') {
|
|
222
|
+
messages.push({
|
|
223
|
+
jsonrpc: '2.0',
|
|
224
|
+
method: 'session/result',
|
|
225
|
+
params: {
|
|
226
|
+
sessionId: message.session_id || 'unknown',
|
|
227
|
+
result: message,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
return messages;
|
|
174
231
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
232
|
+
// Handle error messages
|
|
233
|
+
if ('type' in message && message.type === 'error') {
|
|
234
|
+
messages.push({
|
|
235
|
+
jsonrpc: '2.0',
|
|
236
|
+
method: 'session/error',
|
|
237
|
+
params: {
|
|
238
|
+
sessionId: message.session_id || 'unknown',
|
|
239
|
+
error: message.error,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
return messages;
|
|
179
243
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return 'Enter Plan Mode';
|
|
183
|
-
case 'ExitPlanMode':
|
|
184
|
-
case 'exit_plan_mode':
|
|
185
|
-
return 'Exit Plan Mode';
|
|
186
|
-
case 'TaskOutput':
|
|
187
|
-
case 'task_output':
|
|
188
|
-
return 'Get Task Output';
|
|
189
|
-
default:
|
|
190
|
-
return toolName || 'Unknown Tool';
|
|
244
|
+
// Skip system, tool_progress, stream_event (partial), compact_boundary and other internal messages
|
|
245
|
+
return messages;
|
|
191
246
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
case 'notebook_edit':
|
|
210
|
-
return 'edit';
|
|
211
|
-
case 'Bash':
|
|
212
|
-
case 'bash':
|
|
213
|
-
case 'BashOutput':
|
|
214
|
-
case 'bash_output':
|
|
215
|
-
case 'KillShell':
|
|
216
|
-
case 'kill_shell':
|
|
217
|
-
case 'TaskOutput':
|
|
218
|
-
case 'task_output':
|
|
219
|
-
return 'execute';
|
|
220
|
-
case 'Grep':
|
|
221
|
-
case 'grep':
|
|
222
|
-
case 'WebSearch':
|
|
223
|
-
case 'web_search':
|
|
224
|
-
return 'search';
|
|
225
|
-
case 'WebFetch':
|
|
226
|
-
case 'web_fetch':
|
|
227
|
-
return 'fetch';
|
|
228
|
-
case 'Task':
|
|
229
|
-
case 'task':
|
|
230
|
-
case 'TodoWrite':
|
|
231
|
-
case 'todo_write':
|
|
232
|
-
case 'EnterPlanMode':
|
|
233
|
-
case 'enter_plan_mode':
|
|
234
|
-
case 'ExitPlanMode':
|
|
235
|
-
case 'exit_plan_mode':
|
|
236
|
-
return 'think';
|
|
237
|
-
default:
|
|
238
|
-
return 'other';
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// ============= Content Generation by Tool Type =============
|
|
242
|
-
/**
|
|
243
|
-
* Generate content metadata for tool calls.
|
|
244
|
-
* Returns ToolCallContent for operations that have displayable content like:
|
|
245
|
-
* - Diff content for Edit tools (before/after comparison)
|
|
246
|
-
* - Text content for Bash/Task/WebFetch (descriptions/prompts)
|
|
247
|
-
*/
|
|
248
|
-
function generateToolContent(toolName, input) {
|
|
249
|
-
const content = [];
|
|
250
|
-
switch (toolName) {
|
|
251
|
-
case 'Edit':
|
|
252
|
-
case 'edit':
|
|
253
|
-
case 'MultiEdit': {
|
|
254
|
-
const filePath = input.file_path;
|
|
255
|
-
const oldString = input.old_string;
|
|
256
|
-
const newString = input.new_string;
|
|
257
|
-
if (filePath && oldString !== undefined && newString !== undefined) {
|
|
258
|
-
content.push({
|
|
259
|
-
type: 'diff',
|
|
260
|
-
path: filePath,
|
|
261
|
-
oldText: oldString || null,
|
|
262
|
-
newText: newString,
|
|
263
|
-
});
|
|
247
|
+
// ============= Private: Title Generation by Tool Type =============
|
|
248
|
+
static generateToolTitle(toolName, input) {
|
|
249
|
+
switch (toolName) {
|
|
250
|
+
case 'Read':
|
|
251
|
+
case 'read': {
|
|
252
|
+
const filePath = input.file_path;
|
|
253
|
+
const offset = input.offset;
|
|
254
|
+
const limit = input.limit;
|
|
255
|
+
if (!filePath)
|
|
256
|
+
return 'Read';
|
|
257
|
+
if (limit) {
|
|
258
|
+
return `Read ${filePath} (${(offset !== null && offset !== void 0 ? offset : 0) + 1} - ${(offset !== null && offset !== void 0 ? offset : 0) + limit})`;
|
|
259
|
+
}
|
|
260
|
+
else if (offset) {
|
|
261
|
+
return `Read ${filePath} (from line ${(offset !== null && offset !== void 0 ? offset : 0) + 1})`;
|
|
262
|
+
}
|
|
263
|
+
return `Read ${filePath}`;
|
|
264
264
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const description = input.description;
|
|
270
|
-
if (description) {
|
|
271
|
-
content.push({
|
|
272
|
-
type: 'content',
|
|
273
|
-
content: { type: 'text', text: description },
|
|
274
|
-
});
|
|
265
|
+
case 'Write':
|
|
266
|
+
case 'write': {
|
|
267
|
+
const filePath = input.file_path;
|
|
268
|
+
return filePath ? `Write ${filePath}` : 'Write';
|
|
275
269
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (prompt) {
|
|
282
|
-
content.push({
|
|
283
|
-
type: 'content',
|
|
284
|
-
content: { type: 'text', text: prompt },
|
|
285
|
-
});
|
|
270
|
+
case 'Edit':
|
|
271
|
+
case 'edit':
|
|
272
|
+
case 'MultiEdit': {
|
|
273
|
+
const filePath = input.file_path;
|
|
274
|
+
return filePath ? `Edit \`${filePath}\`` : 'Edit';
|
|
286
275
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
276
|
+
case 'Bash':
|
|
277
|
+
case 'bash': {
|
|
278
|
+
const command = input.command;
|
|
279
|
+
if (!command)
|
|
280
|
+
return 'Terminal';
|
|
281
|
+
const escaped = command.split('`').join('\\`');
|
|
282
|
+
return `\`${escaped}\``;
|
|
283
|
+
}
|
|
284
|
+
case 'BashOutput':
|
|
285
|
+
case 'bash_output':
|
|
286
|
+
return 'Tail Logs';
|
|
287
|
+
case 'KillShell':
|
|
288
|
+
case 'kill_shell':
|
|
289
|
+
return 'Kill Process';
|
|
290
|
+
case 'Glob':
|
|
291
|
+
case 'glob': {
|
|
292
|
+
let label = 'Find';
|
|
293
|
+
const path = input.path;
|
|
294
|
+
const pattern = input.pattern;
|
|
295
|
+
if (path)
|
|
296
|
+
label += ` \`${path}\``;
|
|
297
|
+
if (pattern)
|
|
298
|
+
label += ` \`${pattern}\``;
|
|
299
|
+
return label;
|
|
300
|
+
}
|
|
301
|
+
case 'Grep':
|
|
302
|
+
case 'grep': {
|
|
303
|
+
let label = 'grep';
|
|
304
|
+
if (input['-i'])
|
|
305
|
+
label += ' -i';
|
|
306
|
+
if (input['-n'])
|
|
307
|
+
label += ' -n';
|
|
308
|
+
if (input['-C'] !== undefined)
|
|
309
|
+
label += ` -C ${input['-C']}`;
|
|
310
|
+
if (input['-A'] !== undefined)
|
|
311
|
+
label += ` -A ${input['-A']}`;
|
|
312
|
+
if (input['-B'] !== undefined)
|
|
313
|
+
label += ` -B ${input['-B']}`;
|
|
314
|
+
if (input.multiline)
|
|
315
|
+
label += ' -P';
|
|
316
|
+
if (input.glob)
|
|
317
|
+
label += ` --include="${input.glob}"`;
|
|
318
|
+
if (input.type)
|
|
319
|
+
label += ` --type=${input.type}`;
|
|
320
|
+
const pattern = input.pattern;
|
|
321
|
+
const path = input.path;
|
|
322
|
+
if (pattern)
|
|
323
|
+
label += ` "${pattern}"`;
|
|
324
|
+
if (path)
|
|
325
|
+
label += ` ${path}`;
|
|
326
|
+
return label;
|
|
327
|
+
}
|
|
328
|
+
case 'WebFetch':
|
|
329
|
+
case 'web_fetch': {
|
|
330
|
+
const url = input.url;
|
|
331
|
+
return url ? `Fetch ${url}` : 'Fetch';
|
|
332
|
+
}
|
|
333
|
+
case 'WebSearch':
|
|
334
|
+
case 'web_search': {
|
|
335
|
+
const query = input.query;
|
|
336
|
+
if (!query)
|
|
337
|
+
return 'Search';
|
|
338
|
+
let label = `"${query}"`;
|
|
339
|
+
const allowedDomains = input.allowed_domains;
|
|
340
|
+
const blockedDomains = input.blocked_domains;
|
|
341
|
+
if (allowedDomains === null || allowedDomains === void 0 ? void 0 : allowedDomains.length)
|
|
342
|
+
label += ` (allowed: ${allowedDomains.join(', ')})`;
|
|
343
|
+
if (blockedDomains === null || blockedDomains === void 0 ? void 0 : blockedDomains.length)
|
|
344
|
+
label += ` (blocked: ${blockedDomains.join(', ')})`;
|
|
345
|
+
return label;
|
|
346
|
+
}
|
|
347
|
+
case 'NotebookRead':
|
|
348
|
+
case 'notebook_read': {
|
|
349
|
+
const path = input.notebook_path;
|
|
350
|
+
return path ? `Read Notebook ${path}` : 'Read Notebook';
|
|
351
|
+
}
|
|
352
|
+
case 'NotebookEdit':
|
|
353
|
+
case 'notebook_edit': {
|
|
354
|
+
const path = input.notebook_path;
|
|
355
|
+
return path ? `Edit Notebook ${path}` : 'Edit Notebook';
|
|
356
|
+
}
|
|
357
|
+
case 'Task':
|
|
358
|
+
case 'task': {
|
|
359
|
+
const description = input.description;
|
|
360
|
+
return description || 'Task';
|
|
361
|
+
}
|
|
362
|
+
case 'TodoWrite':
|
|
363
|
+
case 'todo_write': {
|
|
364
|
+
return 'Update TODOs';
|
|
365
|
+
}
|
|
366
|
+
case 'AskUserQuestion':
|
|
367
|
+
case 'ask_user_question':
|
|
368
|
+
return 'Ask User';
|
|
369
|
+
case 'SlashCommand':
|
|
370
|
+
case 'slash_command': {
|
|
371
|
+
const command = input.command;
|
|
372
|
+
return command ? `Run: ${command}` : 'Slash Command';
|
|
373
|
+
}
|
|
374
|
+
case 'Skill':
|
|
375
|
+
case 'skill': {
|
|
376
|
+
const command = input.command;
|
|
377
|
+
return command ? `Skill: ${command}` : 'Skill';
|
|
378
|
+
}
|
|
379
|
+
case 'LSP':
|
|
380
|
+
case 'lsp': {
|
|
381
|
+
const operation = input.operation;
|
|
382
|
+
return operation ? `LSP: ${operation}` : 'LSP';
|
|
297
383
|
}
|
|
298
|
-
|
|
384
|
+
case 'EnterPlanMode':
|
|
385
|
+
case 'enter_plan_mode':
|
|
386
|
+
return 'Enter Plan Mode';
|
|
387
|
+
case 'ExitPlanMode':
|
|
388
|
+
case 'exit_plan_mode':
|
|
389
|
+
return 'Exit Plan Mode';
|
|
390
|
+
case 'TaskOutput':
|
|
391
|
+
case 'task_output':
|
|
392
|
+
return 'Get Task Output';
|
|
393
|
+
default:
|
|
394
|
+
return toolName || 'Unknown Tool';
|
|
299
395
|
}
|
|
300
396
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
397
|
+
// ============= Private: Tool Kind Classification =============
|
|
398
|
+
static getToolKind(toolName) {
|
|
399
|
+
switch (toolName) {
|
|
400
|
+
case 'Read':
|
|
401
|
+
case 'read':
|
|
402
|
+
case 'NotebookRead':
|
|
403
|
+
case 'notebook_read':
|
|
404
|
+
case 'Glob':
|
|
405
|
+
case 'glob':
|
|
406
|
+
return 'read';
|
|
407
|
+
case 'Write':
|
|
408
|
+
case 'write':
|
|
409
|
+
case 'Edit':
|
|
410
|
+
case 'edit':
|
|
411
|
+
case 'MultiEdit':
|
|
412
|
+
case 'NotebookEdit':
|
|
413
|
+
case 'notebook_edit':
|
|
414
|
+
return 'edit';
|
|
415
|
+
case 'Bash':
|
|
416
|
+
case 'bash':
|
|
417
|
+
case 'BashOutput':
|
|
418
|
+
case 'bash_output':
|
|
419
|
+
case 'KillShell':
|
|
420
|
+
case 'kill_shell':
|
|
421
|
+
case 'TaskOutput':
|
|
422
|
+
case 'task_output':
|
|
423
|
+
return 'execute';
|
|
424
|
+
case 'Grep':
|
|
425
|
+
case 'grep':
|
|
426
|
+
case 'WebSearch':
|
|
427
|
+
case 'web_search':
|
|
428
|
+
return 'search';
|
|
429
|
+
case 'WebFetch':
|
|
430
|
+
case 'web_fetch':
|
|
431
|
+
return 'fetch';
|
|
432
|
+
case 'Task':
|
|
433
|
+
case 'task':
|
|
434
|
+
case 'TodoWrite':
|
|
435
|
+
case 'todo_write':
|
|
436
|
+
case 'EnterPlanMode':
|
|
437
|
+
case 'enter_plan_mode':
|
|
438
|
+
case 'ExitPlanMode':
|
|
439
|
+
case 'exit_plan_mode':
|
|
440
|
+
return 'think';
|
|
441
|
+
default:
|
|
442
|
+
return 'other';
|
|
443
|
+
}
|
|
322
444
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
445
|
+
// ============= Private: Content Generation by Tool Type =============
|
|
446
|
+
static generateToolContent(toolName, input) {
|
|
447
|
+
const content = [];
|
|
448
|
+
switch (toolName) {
|
|
449
|
+
case 'Edit':
|
|
450
|
+
case 'edit':
|
|
451
|
+
case 'MultiEdit': {
|
|
452
|
+
const filePath = input.file_path;
|
|
453
|
+
const oldString = input.old_string;
|
|
454
|
+
const newString = input.new_string;
|
|
455
|
+
if (filePath && oldString !== undefined && newString !== undefined) {
|
|
456
|
+
content.push({
|
|
457
|
+
type: 'diff',
|
|
458
|
+
path: filePath,
|
|
459
|
+
oldText: oldString || null,
|
|
460
|
+
newText: newString,
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
case 'Bash':
|
|
466
|
+
case 'bash': {
|
|
467
|
+
const description = input.description;
|
|
468
|
+
if (description) {
|
|
469
|
+
content.push({
|
|
470
|
+
type: 'content',
|
|
471
|
+
content: { type: 'text', text: description },
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
case 'Task':
|
|
477
|
+
case 'task': {
|
|
478
|
+
const prompt = input.prompt;
|
|
479
|
+
if (prompt) {
|
|
480
|
+
content.push({
|
|
481
|
+
type: 'content',
|
|
482
|
+
content: { type: 'text', text: prompt },
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case 'WebFetch':
|
|
488
|
+
case 'web_fetch': {
|
|
489
|
+
const prompt = input.prompt;
|
|
490
|
+
if (prompt) {
|
|
491
|
+
content.push({
|
|
492
|
+
type: 'content',
|
|
493
|
+
content: { type: 'text', text: prompt },
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return content.length > 0 ? content : undefined;
|
|
333
500
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
text: diffText,
|
|
501
|
+
// ============= Private: Location Extraction by Tool Type =============
|
|
502
|
+
static extractToolLocations(toolName, input) {
|
|
503
|
+
const locations = [];
|
|
504
|
+
const filePath = input.file_path;
|
|
505
|
+
const notebookPath = input.notebook_path;
|
|
506
|
+
const path = input.path;
|
|
507
|
+
if (filePath) {
|
|
508
|
+
locations.push({
|
|
509
|
+
path: filePath,
|
|
510
|
+
line: input.offset,
|
|
345
511
|
});
|
|
346
512
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
513
|
+
else if (notebookPath) {
|
|
514
|
+
locations.push({ path: notebookPath });
|
|
515
|
+
}
|
|
516
|
+
else if (path && (toolName === 'Glob' || toolName === 'glob')) {
|
|
517
|
+
locations.push({ path });
|
|
518
|
+
}
|
|
519
|
+
return locations.length > 0 ? locations : undefined;
|
|
520
|
+
}
|
|
521
|
+
// ============= Private: Content Format Conversion =============
|
|
522
|
+
static formatAcpContentForSdk(toolCallContent) {
|
|
523
|
+
var _a;
|
|
524
|
+
if (toolCallContent.length === 0) {
|
|
525
|
+
return '';
|
|
526
|
+
}
|
|
527
|
+
const blocks = [];
|
|
528
|
+
for (const item of toolCallContent) {
|
|
529
|
+
if (item.type === 'diff') {
|
|
530
|
+
const diff = item;
|
|
531
|
+
const diffText = `--- ${diff.path}
|
|
532
|
+
+++ ${diff.path}
|
|
533
|
+
${AcpTransformer.formatDiffHunk((_a = diff.oldText) !== null && _a !== void 0 ? _a : null, diff.newText)}`;
|
|
351
534
|
blocks.push({
|
|
352
535
|
type: 'text',
|
|
353
|
-
text:
|
|
536
|
+
text: diffText,
|
|
354
537
|
});
|
|
355
538
|
}
|
|
539
|
+
else if (item.type === 'content') {
|
|
540
|
+
const contentItem = item;
|
|
541
|
+
if (contentItem.content && contentItem.content.type === 'text' && contentItem.content.text) {
|
|
542
|
+
blocks.push({
|
|
543
|
+
type: 'text',
|
|
544
|
+
text: contentItem.content.text,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
else if (item.type === 'terminal') {
|
|
549
|
+
const terminalItem = item;
|
|
550
|
+
if (terminalItem.terminalId) {
|
|
551
|
+
blocks.push({
|
|
552
|
+
type: 'text',
|
|
553
|
+
text: `[Terminal: ${terminalItem.terminalId}]`,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
356
557
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
558
|
+
if (blocks.length === 1 && blocks[0].type === 'text') {
|
|
559
|
+
return blocks[0].text;
|
|
560
|
+
}
|
|
561
|
+
return blocks.length > 0 ? blocks : '';
|
|
562
|
+
}
|
|
563
|
+
static formatDiffHunk(oldText, newText) {
|
|
564
|
+
const oldLines = oldText ? oldText.split('\n') : [];
|
|
565
|
+
const newLines = newText.split('\n');
|
|
566
|
+
const hunks = [];
|
|
567
|
+
hunks.push(`@@ -1,${oldLines.length} +1,${newLines.length} @@`);
|
|
568
|
+
for (const line of oldLines) {
|
|
569
|
+
hunks.push(`-${line}`);
|
|
570
|
+
}
|
|
571
|
+
for (const line of newLines) {
|
|
572
|
+
hunks.push(`+${line}`);
|
|
573
|
+
}
|
|
574
|
+
return hunks.join('\n');
|
|
575
|
+
}
|
|
576
|
+
// ============= Private: Prompt and Result Helpers =============
|
|
577
|
+
static privateExtractPromptText(prompt) {
|
|
578
|
+
let content = '';
|
|
579
|
+
if (prompt && Array.isArray(prompt)) {
|
|
580
|
+
for (const block of prompt) {
|
|
581
|
+
if (block.type === 'text' && block.text) {
|
|
582
|
+
content += block.text;
|
|
583
|
+
}
|
|
365
584
|
}
|
|
366
585
|
}
|
|
586
|
+
return content;
|
|
367
587
|
}
|
|
368
|
-
//
|
|
369
|
-
|
|
370
|
-
|
|
588
|
+
// ============= Private: Content Block Extraction =============
|
|
589
|
+
static privateExtractToolUseBlocks(contentBlocks) {
|
|
590
|
+
if (!Array.isArray(contentBlocks))
|
|
591
|
+
return [];
|
|
592
|
+
return contentBlocks.filter((block) => typeof block === 'object' &&
|
|
593
|
+
block !== null &&
|
|
594
|
+
'type' in block &&
|
|
595
|
+
block.type === 'tool_use');
|
|
371
596
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
// Add old lines
|
|
383
|
-
for (const line of oldLines) {
|
|
384
|
-
hunks.push(`-${line}`);
|
|
597
|
+
static privateExtractTextContent(contentBlocks) {
|
|
598
|
+
if (!Array.isArray(contentBlocks))
|
|
599
|
+
return '';
|
|
600
|
+
return contentBlocks
|
|
601
|
+
.filter((block) => typeof block === 'object' &&
|
|
602
|
+
block !== null &&
|
|
603
|
+
'type' in block &&
|
|
604
|
+
block.type === 'text')
|
|
605
|
+
.map((block) => block.text)
|
|
606
|
+
.join('\n');
|
|
385
607
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
608
|
+
static privateCreateToolResultMessage(acpMessage, acpResult) {
|
|
609
|
+
var _a;
|
|
610
|
+
const toolResultBlock = AcpTransformer.convertAcpToolResultToSdk(acpResult.toolCallId, acpResult);
|
|
611
|
+
return {
|
|
612
|
+
type: 'user',
|
|
613
|
+
session_id: ((_a = acpMessage.params) === null || _a === void 0 ? void 0 : _a.sessionId) || 'unknown',
|
|
614
|
+
message: {
|
|
615
|
+
role: 'user',
|
|
616
|
+
content: [toolResultBlock],
|
|
617
|
+
},
|
|
618
|
+
parent_tool_use_id: acpResult.toolCallId,
|
|
619
|
+
};
|
|
389
620
|
}
|
|
390
|
-
return hunks.join('\n');
|
|
391
|
-
}
|
|
392
|
-
// ============= Conversion: ACP Tool Result → SDK Tool Result =============
|
|
393
|
-
/**
|
|
394
|
-
* Convert ACP Tool Result to SDK ToolResultContentBlock
|
|
395
|
-
* Preserves tool_use_id and ensures error state is tracked
|
|
396
|
-
*
|
|
397
|
-
* @param toolCallId - Original tool call ID
|
|
398
|
-
* @param acpResult - ACP tool result
|
|
399
|
-
* @returns SDK ToolResultContentBlock
|
|
400
|
-
*/
|
|
401
|
-
function convertAcpToolResultToSdk(toolCallId, acpResult) {
|
|
402
|
-
const isError = acpResult.status === 'failed';
|
|
403
|
-
const content = acpResult.content ? formatAcpContentForSdk(acpResult.content) : '';
|
|
404
|
-
return {
|
|
405
|
-
type: 'tool_result',
|
|
406
|
-
tool_use_id: toolCallId,
|
|
407
|
-
content: content,
|
|
408
|
-
is_error: isError,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
// ============= Helper: Extract Tool Use Blocks =============
|
|
412
|
-
/**
|
|
413
|
-
* Extract tool use blocks from content blocks array
|
|
414
|
-
*/
|
|
415
|
-
function extractToolUseBlocks(contentBlocks) {
|
|
416
|
-
if (!Array.isArray(contentBlocks))
|
|
417
|
-
return [];
|
|
418
|
-
return contentBlocks.filter((block) => typeof block === 'object' &&
|
|
419
|
-
block !== null &&
|
|
420
|
-
'type' in block &&
|
|
421
|
-
block.type === 'tool_use');
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Extract text content from content blocks array
|
|
425
|
-
*/
|
|
426
|
-
function extractTextContent(contentBlocks) {
|
|
427
|
-
if (!Array.isArray(contentBlocks))
|
|
428
|
-
return '';
|
|
429
|
-
return contentBlocks
|
|
430
|
-
.filter((block) => typeof block === 'object' &&
|
|
431
|
-
block !== null &&
|
|
432
|
-
'type' in block &&
|
|
433
|
-
block.type === 'text')
|
|
434
|
-
.map((block) => block.text)
|
|
435
|
-
.join('\n');
|
|
436
621
|
}
|
|
622
|
+
exports.AcpTransformer = AcpTransformer;
|
|
437
623
|
//# sourceMappingURL=tool-converter.js.map
|