@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.
Files changed (41) hide show
  1. package/cli/CHANGELOG.md +17 -0
  2. package/cli/dist/codebuddy.js +2 -2
  3. package/cli/package.json +1 -1
  4. package/cli/product.cloudhosted.json +2 -2
  5. package/cli/product.internal.json +2 -2
  6. package/cli/product.ioa.json +2 -2
  7. package/cli/product.json +2 -2
  8. package/cli/product.selfhosted.json +2 -2
  9. package/lib/acp/index.d.ts +6 -7
  10. package/lib/acp/index.d.ts.map +1 -1
  11. package/lib/acp/index.js +6 -10
  12. package/lib/acp/index.js.map +1 -1
  13. package/lib/acp/tool-converter.d.ts +71 -23
  14. package/lib/acp/tool-converter.d.ts.map +1 -1
  15. package/lib/acp/tool-converter.js +573 -387
  16. package/lib/acp/tool-converter.js.map +1 -1
  17. package/lib/index.d.ts +0 -2
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +1 -4
  20. package/lib/index.js.map +1 -1
  21. package/lib/query.d.ts.map +1 -1
  22. package/lib/query.js +8 -0
  23. package/lib/query.js.map +1 -1
  24. package/lib/session.d.ts +11 -0
  25. package/lib/session.d.ts.map +1 -1
  26. package/lib/session.js +129 -3
  27. package/lib/session.js.map +1 -1
  28. package/lib/transport/index.d.ts +2 -0
  29. package/lib/transport/index.d.ts.map +1 -1
  30. package/lib/transport/index.js.map +1 -1
  31. package/lib/transport/process-transport.d.ts.map +1 -1
  32. package/lib/transport/process-transport.js +3 -0
  33. package/lib/transport/process-transport.js.map +1 -1
  34. package/lib/types.d.ts +10 -0
  35. package/lib/types.d.ts.map +1 -1
  36. package/lib/types.js.map +1 -1
  37. package/package.json +1 -1
  38. package/lib/acp/acp-client.d.ts +0 -62
  39. package/lib/acp/acp-client.d.ts.map +0 -1
  40. package/lib/acp/acp-client.js +0 -256
  41. package/lib/acp/acp-client.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * Tool Converter Utility
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.convertSdkToolUseToAcpToolCall = convertSdkToolUseToAcpToolCall;
16
- exports.convertAcpToolResultToSdk = convertAcpToolResultToSdk;
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
- * Convert SDK ToolUseContentBlock to ACP Tool Call
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
- * @param toolUse - SDK tool use block
25
- * @returns ACP tool call with complete data preservation
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
- function convertSdkToolUseToAcpToolCall(toolUse) {
28
- const toolName = toolUse.name;
29
- const toolInput = toolUse.input;
30
- return {
31
- toolCallId: toolUse.id,
32
- status: 'pending',
33
- title: generateToolTitle(toolName, toolInput),
34
- kind: getToolKind(toolName),
35
- rawInput: toolInput,
36
- content: generateToolContent(toolName, toolInput),
37
- locations: extractToolLocations(toolName, toolInput),
38
- };
39
- }
40
- // ============= Title Generation by Tool Type =============
41
- function generateToolTitle(toolName, input) {
42
- switch (toolName) {
43
- case 'Read':
44
- case 'read': {
45
- const filePath = input.file_path;
46
- const offset = input.offset;
47
- const limit = input.limit;
48
- if (!filePath)
49
- return 'Read';
50
- if (limit) {
51
- return `Read ${filePath} (${(offset !== null && offset !== void 0 ? offset : 0) + 1} - ${(offset !== null && offset !== void 0 ? offset : 0) + limit})`;
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 (offset) {
54
- return `Read ${filePath} (from line ${(offset !== null && offset !== void 0 ? offset : 0) + 1})`;
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
- case 'NotebookRead':
144
- case 'notebook_read': {
145
- const path = input.notebook_path;
146
- return path ? `Read Notebook ${path}` : 'Read Notebook';
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
- case 'NotebookEdit':
149
- case 'notebook_edit': {
150
- const path = input.notebook_path;
151
- return path ? `Edit Notebook ${path}` : 'Edit Notebook';
122
+ if (acpMessage.method === 'session/cancel') {
123
+ return {
124
+ type: 'control_request',
125
+ request: { subtype: 'interrupt' },
126
+ };
152
127
  }
153
- case 'Task':
154
- case 'task': {
155
- const description = input.description;
156
- return description || 'Task';
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
- case 'TodoWrite':
159
- case 'todo_write': {
160
- return 'Update TODOs';
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
- case 'AskUserQuestion':
163
- case 'ask_user_question':
164
- return 'Ask User';
165
- case 'SlashCommand':
166
- case 'slash_command': {
167
- const command = input.command;
168
- return command ? `Run: ${command}` : 'Slash Command';
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
- case 'Skill':
171
- case 'skill': {
172
- const command = input.command;
173
- return command ? `Skill: ${command}` : 'Skill';
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
- case 'LSP':
176
- case 'lsp': {
177
- const operation = input.operation;
178
- return operation ? `LSP: ${operation}` : 'LSP';
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
- case 'EnterPlanMode':
181
- case 'enter_plan_mode':
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
- // ============= Tool Kind Classification =============
194
- function getToolKind(toolName) {
195
- switch (toolName) {
196
- case 'Read':
197
- case 'read':
198
- case 'NotebookRead':
199
- case 'notebook_read':
200
- case 'Glob':
201
- case 'glob':
202
- return 'read';
203
- case 'Write':
204
- case 'write':
205
- case 'Edit':
206
- case 'edit':
207
- case 'MultiEdit':
208
- case 'NotebookEdit':
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
- break;
266
- }
267
- case 'Bash':
268
- case 'bash': {
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
- break;
277
- }
278
- case 'Task':
279
- case 'task': {
280
- const prompt = input.prompt;
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
- break;
288
- }
289
- case 'WebFetch':
290
- case 'web_fetch': {
291
- const prompt = input.prompt;
292
- if (prompt) {
293
- content.push({
294
- type: 'content',
295
- content: { type: 'text', text: prompt },
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
- break;
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
- return content.length > 0 ? content : undefined;
302
- }
303
- // ============= Location Extraction by Tool Type =============
304
- function extractToolLocations(toolName, input) {
305
- const locations = [];
306
- // File path based tools
307
- const filePath = input.file_path;
308
- const notebookPath = input.notebook_path;
309
- const path = input.path;
310
- // Add file location if present
311
- if (filePath) {
312
- locations.push({
313
- path: filePath,
314
- line: input.offset,
315
- });
316
- }
317
- else if (notebookPath) {
318
- locations.push({ path: notebookPath });
319
- }
320
- else if (path && (toolName === 'Glob' || toolName === 'glob')) {
321
- locations.push({ path });
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
- return locations.length > 0 ? locations : undefined;
324
- }
325
- // ============= Content Format Conversion =============
326
- /**
327
- * Convert ACP content format to SDK content format for tool results
328
- */
329
- function formatAcpContentForSdk(toolCallContent) {
330
- var _a;
331
- if (toolCallContent.length === 0) {
332
- return '';
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
- const blocks = [];
335
- for (const item of toolCallContent) {
336
- // Handle diff content
337
- if (item.type === 'diff') {
338
- const diff = item;
339
- const diffText = `--- ${diff.path}
340
- +++ ${diff.path}
341
- ${formatDiffHunk((_a = diff.oldText) !== null && _a !== void 0 ? _a : null, diff.newText)}`;
342
- blocks.push({
343
- type: 'text',
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
- // Handle regular content (text, image, etc.)
348
- else if (item.type === 'content') {
349
- const contentItem = item;
350
- if (contentItem.content && contentItem.content.type === 'text' && contentItem.content.text) {
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: contentItem.content.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
- // Handle terminal content
358
- else if (item.type === 'terminal') {
359
- const terminalItem = item;
360
- if (terminalItem.terminalId) {
361
- blocks.push({
362
- type: 'text',
363
- text: `[Terminal: ${terminalItem.terminalId}]`,
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
- // If all content was text, return as string for simplicity
369
- if (blocks.length === 1 && blocks[0].type === 'text') {
370
- return blocks[0].text;
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
- return blocks.length > 0 ? blocks : '';
373
- }
374
- /**
375
- * Format diff hunks for display
376
- */
377
- function formatDiffHunk(oldText, newText) {
378
- const oldLines = oldText ? oldText.split('\n') : [];
379
- const newLines = newText.split('\n');
380
- const hunks = [];
381
- hunks.push(`@@ -1,${oldLines.length} +1,${newLines.length} @@`);
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
- // Add new lines
387
- for (const line of newLines) {
388
- hunks.push(`+${line}`);
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