@tencent-ai/agent-sdk 0.3.11 → 0.3.12

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.
@@ -1,806 +0,0 @@
1
- "use strict";
2
- /**
3
- * ACP Message Transformer
4
- *
5
- * Converts SDK internal tool formats to ACP (Agent Client Protocol) format and vice versa.
6
- *
7
- * Uses official @agentclientprotocol/sdk types for compatibility with the ACP specification.
8
- *
9
- * Critical Design Principle: NO DATA LOSS
10
- * - SDK tool inputs are preserved completely in rawInput
11
- * - Tool IDs are maintained throughout the conversion
12
- * - Tool results are preserved with error state tracking
13
- */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.AcpTransformer = void 0;
16
- // ============= ACP Message Transformer (Stateless Utility) =============
17
- /**
18
- * Bidirectional converter between SDK internal format (JSON Lines) and ACP (Agent Client Protocol) format.
19
- *
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
28
- */
29
- class AcpTransformer {
30
- // ============= Public API: SDK Tool Use ↔ ACP Tool Call =============
31
- /**
32
- * Convert SDK ToolUseContentBlock to complete session/update params
33
- * Returns an object that can be spread directly into AcpMessage params
34
- *
35
- * This is the preferred method for creating tool call messages that comply with ACP spec.
36
- *
37
- * @param toolUse - SDK tool use block
38
- * @param sessionId - Session ID for the message
39
- * @param messageId - Optional message ID (defaults to toolUse.id)
40
- * @returns Complete params object ready to be used in session/update message
41
- */
42
- static convertSdkToolUseToSessionUpdate(toolUse, sessionId, messageId) {
43
- const toolName = toolUse.name;
44
- const toolInput = toolUse.input;
45
- return {
46
- sessionId,
47
- update: {
48
- sessionUpdate: 'tool_call',
49
- toolCallId: toolUse.id,
50
- status: 'pending',
51
- title: AcpTransformer.generateToolTitle(toolName, toolInput),
52
- kind: AcpTransformer.getToolKind(toolName),
53
- rawInput: toolInput,
54
- content: AcpTransformer.generateToolContent(toolName, toolInput),
55
- locations: AcpTransformer.extractToolLocations(toolName, toolInput),
56
- },
57
- _meta: {
58
- 'codebuddy.ai': {
59
- toolName,
60
- messageId: messageId || toolUse.id,
61
- },
62
- }
63
- };
64
- }
65
- // ============= Public API: Bidirectional Tool Conversion =============
66
- /**
67
- * Convert ACP Tool Result to SDK ToolResultContentBlock
68
- * Preserves tool_use_id and ensures error state is tracked
69
- */
70
- static convertAcpToolResultToSdk(toolCallId, acpResult) {
71
- const isError = acpResult.status === 'failed';
72
- const content = acpResult.content ? AcpTransformer.formatAcpContentForSdk(acpResult.content) : '';
73
- return {
74
- type: 'tool_result',
75
- tool_use_id: toolCallId,
76
- content: content,
77
- is_error: isError,
78
- };
79
- }
80
- /**
81
- * Convert SDK ToolResultContentBlock to ACP ToolResult
82
- * Enables bidirectional conversion for tool results
83
- */
84
- static convertSdkToolResultToAcpToolResult(toolResult) {
85
- const content = [];
86
- if (toolResult.content) {
87
- if (typeof toolResult.content === 'string') {
88
- content.push({
89
- type: 'content',
90
- content: { type: 'text', text: toolResult.content },
91
- });
92
- }
93
- else if (Array.isArray(toolResult.content)) {
94
- for (const block of toolResult.content) {
95
- if ('type' in block && block.type === 'text') {
96
- const textBlock = block;
97
- content.push({
98
- type: 'content',
99
- content: { type: 'text', text: textBlock.text },
100
- });
101
- }
102
- }
103
- }
104
- }
105
- return {
106
- toolCallId: toolResult.tool_use_id,
107
- status: toolResult.is_error ? 'failed' : 'completed',
108
- content: content.length > 0 ? content : undefined,
109
- rawOutput: toolResult.content,
110
- };
111
- }
112
- // ============= Public API: Message Transformation =============
113
- /**
114
- * Convert ACP message to SDK internal format (JSON Lines)
115
- *
116
- * Converts all ACP message types to corresponding SDK messages:
117
- * - session/prompt: User input → UserMessage
118
- * - session/cancel: Cancellation request → ControlRequest
119
- * - session/update (tool_call_update): Tool result → UserMessage with tool_result block
120
- */
121
- static acpToSdk(acpMessage) {
122
- if (acpMessage.method === 'session/prompt') {
123
- const params = acpMessage.params;
124
- const sessionId = params === null || params === void 0 ? void 0 : params.sessionId;
125
- const prompt = params === null || params === void 0 ? void 0 : params.prompt;
126
- const content = AcpTransformer.privateExtractPromptText(prompt);
127
- return {
128
- type: 'user',
129
- session_id: sessionId || 'unknown',
130
- message: {
131
- role: 'user',
132
- content: content,
133
- },
134
- parent_tool_use_id: null,
135
- };
136
- }
137
- if (acpMessage.method === 'session/cancel') {
138
- return {
139
- type: 'control_request',
140
- request: { subtype: 'interrupt' },
141
- };
142
- }
143
- // Handle session/update with tool_call_update
144
- if (acpMessage.method === 'session/update') {
145
- const params = acpMessage.params;
146
- const sessionId = params === null || params === void 0 ? void 0 : params.sessionId;
147
- const update = params === null || params === void 0 ? void 0 : params.update;
148
- if ((update === null || update === void 0 ? void 0 : update.sessionUpdate) === 'tool_call_update') {
149
- // Convert tool_call_update back to SDK tool result format
150
- const toolCallId = update.toolCallId;
151
- const status = update.status;
152
- const content = update.content;
153
- if (toolCallId) {
154
- // Create an AcpToolResult from the update
155
- const acpResult = {
156
- toolCallId,
157
- status: status || 'completed',
158
- content: content,
159
- };
160
- return AcpTransformer.privateCreateToolResultMessage({ params: { sessionId } }, acpResult);
161
- }
162
- }
163
- }
164
- return null;
165
- }
166
- /**
167
- * Convert SDK internal message to ACP format
168
- *
169
- * @param message - SDK message to convert
170
- * @param mode - Conversion mode:
171
- * - 'stream': Real-time streaming mode (session/prompt) - converts to incremental chunks
172
- * - 'history': History replay mode (session/load) - converts to complete messages
173
- *
174
- * Converts all SDK message types to corresponding ACP messages:
175
- * - Stream mode: PartialAssistantMessage (stream_event) → streaming text/tool deltas
176
- * - History mode: AssistantMessage/UserMessage → complete message objects
177
- */
178
- static sdkToAcp(message, mode = 'stream') {
179
- const messages = [];
180
- // ============= Stream Mode: Handle Real-time Streaming Events =============
181
- if (mode === 'stream') {
182
- // Process stream_event for incremental updates
183
- if ('type' in message && message.type === 'stream_event') {
184
- const partialMsg = message;
185
- const streamEvent = partialMsg.event;
186
- // Handle content_block_start: process the initial content_block (aligned with Zed)
187
- if (streamEvent.type === 'content_block_start' && 'content_block' in streamEvent) {
188
- const block = streamEvent.content_block;
189
- // Handle tool_use blocks at start
190
- if (block.type === 'tool_use') {
191
- const toolMsg = {
192
- jsonrpc: '2.0',
193
- method: 'session/update',
194
- params: AcpTransformer.convertSdkToolUseToSessionUpdate(block, partialMsg.session_id || 'unknown', partialMsg.uuid),
195
- };
196
- messages.push(toolMsg);
197
- }
198
- // Handle text blocks at start (initial empty text block)
199
- else if (block.type === 'text') {
200
- messages.push({
201
- jsonrpc: '2.0',
202
- method: 'session/update',
203
- params: {
204
- sessionId: partialMsg.session_id || 'unknown',
205
- update: {
206
- sessionUpdate: 'agent_message_chunk',
207
- content: {
208
- type: 'text',
209
- text: block.text || '',
210
- },
211
- },
212
- _meta: {
213
- 'codebuddy.ai': {
214
- messageId: partialMsg.uuid,
215
- },
216
- }
217
- },
218
- });
219
- }
220
- }
221
- // Handle content_block_delta: process incremental updates (aligned with Zed)
222
- else if (streamEvent.type === 'content_block_delta') {
223
- if ('delta' in streamEvent && streamEvent.delta.type === 'text_delta') {
224
- // Convert text deltas to agent_message_chunk format (Zed naming convention)
225
- messages.push({
226
- jsonrpc: '2.0',
227
- method: 'session/update',
228
- params: {
229
- sessionId: partialMsg.session_id || 'unknown',
230
- update: {
231
- sessionUpdate: 'agent_message_chunk',
232
- content: {
233
- type: 'text',
234
- text: streamEvent.delta.text,
235
- },
236
- },
237
- _meta: {
238
- 'codebuddy.ai': {
239
- messageId: partialMsg.uuid,
240
- },
241
- },
242
- },
243
- });
244
- }
245
- }
246
- }
247
- // Handle user messages with tool results in stream mode
248
- // Tool results don't stream - they arrive as complete messages
249
- if ('type' in message && message.type === 'user') {
250
- const userMsg = message;
251
- const messageId = userMsg.uuid;
252
- if (userMsg.message.content && Array.isArray(userMsg.message.content)) {
253
- // Look for tool result blocks
254
- const toolResultBlocks = userMsg.message.content.filter((block) => typeof block === 'object' &&
255
- block !== null &&
256
- 'type' in block &&
257
- block.type === 'tool_result');
258
- // Convert tool results to ACP tool_call_update format
259
- for (const toolResultBlock of toolResultBlocks) {
260
- const acpResult = AcpTransformer.convertSdkToolResultToAcpToolResult(toolResultBlock);
261
- const updateMsg = {
262
- jsonrpc: '2.0',
263
- method: 'session/update',
264
- params: {
265
- sessionId: userMsg.session_id || 'unknown',
266
- update: {
267
- sessionUpdate: 'tool_call_update',
268
- toolCallId: acpResult.toolCallId,
269
- status: acpResult.status,
270
- content: acpResult.content,
271
- },
272
- _meta: {
273
- 'codebuddy.ai': {
274
- messageId: messageId,
275
- },
276
- }
277
- },
278
- };
279
- messages.push(updateMsg);
280
- }
281
- }
282
- }
283
- // Skip system, tool_progress, assistant (handled by stream_event), and other internal messages in stream mode
284
- return messages;
285
- }
286
- else {
287
- // ============= History Mode: Handle Complete Messages =============
288
- // Convert complete messages for history replay (for session/load)
289
- // Handle assistant messages (contain tool calls and text from the model)
290
- if ('type' in message && message.type === 'assistant') {
291
- const assistantMsg = message;
292
- const messageId = assistantMsg.message.id;
293
- if (assistantMsg.message.content && Array.isArray(assistantMsg.message.content)) {
294
- // Extract and convert tool use blocks
295
- const toolUseBlocks = AcpTransformer.privateExtractToolUseBlocks(assistantMsg.message.content);
296
- for (const toolUse of toolUseBlocks) {
297
- const toolCallMsg = {
298
- jsonrpc: '2.0',
299
- method: 'session/update',
300
- params: AcpTransformer.convertSdkToolUseToSessionUpdate(toolUse, assistantMsg.session_id || 'unknown', messageId),
301
- };
302
- messages.push(toolCallMsg);
303
- }
304
- // Extract and send text content if present
305
- const textContent = AcpTransformer.privateExtractTextContent(assistantMsg.message.content);
306
- if (textContent) {
307
- messages.push({
308
- jsonrpc: '2.0',
309
- method: 'session/update',
310
- params: {
311
- sessionId: assistantMsg.session_id || 'unknown',
312
- update: {
313
- sessionUpdate: 'agent_message_chunk',
314
- content: {
315
- type: 'text',
316
- text: textContent,
317
- },
318
- },
319
- _meta: {
320
- 'codebuddy.ai': {
321
- messageId: messageId,
322
- },
323
- }
324
- },
325
- });
326
- }
327
- }
328
- }
329
- // Handle user messages with tool results or text content
330
- if ('type' in message && message.type === 'user') {
331
- const userMsg = message;
332
- const messageId = userMsg.uuid;
333
- if (userMsg.message.content) {
334
- // Handle array content (tool results and text blocks)
335
- if (Array.isArray(userMsg.message.content)) {
336
- // Look for tool result blocks
337
- const toolResultBlocks = userMsg.message.content.filter((block) => typeof block === 'object' &&
338
- block !== null &&
339
- 'type' in block &&
340
- block.type === 'tool_result');
341
- // Convert tool results to ACP tool_call_update format (via session/update)
342
- for (const toolResultBlock of toolResultBlocks) {
343
- const acpResult = AcpTransformer.convertSdkToolResultToAcpToolResult(toolResultBlock);
344
- // Wrap tool result as session/update with tool_call_update
345
- const updateMsg = {
346
- jsonrpc: '2.0',
347
- method: 'session/update',
348
- params: {
349
- sessionId: userMsg.session_id || 'unknown',
350
- update: {
351
- sessionUpdate: 'tool_call_update',
352
- toolCallId: acpResult.toolCallId,
353
- status: acpResult.status,
354
- content: acpResult.content,
355
- },
356
- _meta: {
357
- 'codebuddy.ai': {
358
- messageId: messageId,
359
- },
360
- }
361
- },
362
- };
363
- messages.push(updateMsg);
364
- }
365
- // Extract and send text content if present (for resume history)
366
- const textContent = AcpTransformer.privateExtractTextContent(userMsg.message.content);
367
- if (textContent) {
368
- messages.push({
369
- jsonrpc: '2.0',
370
- method: 'session/prompt',
371
- params: {
372
- sessionId: userMsg.session_id || 'unknown',
373
- prompt: [{ type: 'text', text: textContent }],
374
- _meta: {
375
- 'codebuddy.ai': {
376
- messageId: messageId,
377
- },
378
- }
379
- },
380
- });
381
- }
382
- }
383
- else if (typeof userMsg.message.content === 'string' && userMsg.message.content) {
384
- // Handle string content (for resume history)
385
- messages.push({
386
- jsonrpc: '2.0',
387
- method: 'session/prompt',
388
- params: {
389
- sessionId: userMsg.session_id || 'unknown',
390
- prompt: [{ type: 'text', text: userMsg.message.content }],
391
- _meta: {
392
- 'codebuddy.ai': {
393
- messageId: messageId,
394
- },
395
- }
396
- },
397
- });
398
- }
399
- }
400
- }
401
- // Handle result messages (marks the end of a turn)
402
- if ('type' in message && message.type === 'result') {
403
- messages.push({
404
- jsonrpc: '2.0',
405
- method: 'session/result',
406
- params: {
407
- sessionId: message.session_id || 'unknown',
408
- result: message,
409
- },
410
- });
411
- }
412
- // Handle error messages
413
- if ('type' in message && message.type === 'error') {
414
- messages.push({
415
- jsonrpc: '2.0',
416
- method: 'session/error',
417
- params: {
418
- sessionId: message.session_id || 'unknown',
419
- error: message.error,
420
- },
421
- });
422
- }
423
- }
424
- // Skip system, tool_progress, stream_event (partial), compact_boundary and other internal messages
425
- return messages;
426
- }
427
- // ============= Private: Title Generation by Tool Type =============
428
- static generateToolTitle(toolName, input) {
429
- switch (toolName) {
430
- case 'Read':
431
- case 'read': {
432
- const filePath = input.file_path;
433
- const offset = input.offset;
434
- const limit = input.limit;
435
- if (!filePath)
436
- return 'Read';
437
- if (limit) {
438
- const startLine = (offset !== null && offset !== void 0 ? offset : 0) + 1;
439
- const endLine = startLine + limit - 1;
440
- return `Read ${filePath} (${startLine}-${endLine})`;
441
- }
442
- else if (offset) {
443
- return `Read ${filePath} (from line ${(offset !== null && offset !== void 0 ? offset : 0) + 1})`;
444
- }
445
- return `Read ${filePath}`;
446
- }
447
- case 'Write':
448
- case 'write': {
449
- const filePath = input.file_path;
450
- return filePath ? `Write ${filePath}` : 'Write';
451
- }
452
- case 'Edit':
453
- case 'edit':
454
- case 'MultiEdit': {
455
- const filePath = input.file_path;
456
- return filePath ? `Edit \`${filePath}\`` : 'Edit';
457
- }
458
- case 'Bash':
459
- case 'bash': {
460
- const command = input.command;
461
- if (!command)
462
- return 'Terminal';
463
- const escaped = command.split('`').join('\\`');
464
- return `\`${escaped}\``;
465
- }
466
- case 'BashOutput':
467
- case 'bash_output':
468
- return 'Tail Logs';
469
- case 'KillShell':
470
- case 'kill_shell':
471
- return 'Kill Process';
472
- case 'Glob':
473
- case 'glob': {
474
- let label = 'Find';
475
- const path = input.path;
476
- const pattern = input.pattern;
477
- if (path)
478
- label += ` \`${path}\``;
479
- if (pattern)
480
- label += ` \`${pattern}\``;
481
- return label;
482
- }
483
- case 'Grep':
484
- case 'grep': {
485
- let label = 'grep';
486
- if (input['-i'])
487
- label += ' -i';
488
- if (input['-n'])
489
- label += ' -n';
490
- if (input['-C'] !== undefined)
491
- label += ` -C ${input['-C']}`;
492
- if (input['-A'] !== undefined)
493
- label += ` -A ${input['-A']}`;
494
- if (input['-B'] !== undefined)
495
- label += ` -B ${input['-B']}`;
496
- if (input.multiline)
497
- label += ' -P';
498
- if (input.glob)
499
- label += ` --include="${input.glob}"`;
500
- if (input.type)
501
- label += ` --type=${input.type}`;
502
- const pattern = input.pattern;
503
- const path = input.path;
504
- if (pattern)
505
- label += ` "${pattern}"`;
506
- if (path)
507
- label += ` ${path}`;
508
- return label;
509
- }
510
- case 'WebFetch':
511
- case 'web_fetch': {
512
- const url = input.url;
513
- return url ? `Fetch ${url}` : 'Fetch';
514
- }
515
- case 'WebSearch':
516
- case 'web_search': {
517
- const query = input.query;
518
- if (!query)
519
- return 'Search';
520
- let label = `"${query}"`;
521
- const allowedDomains = input.allowed_domains;
522
- const blockedDomains = input.blocked_domains;
523
- if (allowedDomains === null || allowedDomains === void 0 ? void 0 : allowedDomains.length)
524
- label += ` (allowed: ${allowedDomains.join(', ')})`;
525
- if (blockedDomains === null || blockedDomains === void 0 ? void 0 : blockedDomains.length)
526
- label += ` (blocked: ${blockedDomains.join(', ')})`;
527
- return label;
528
- }
529
- case 'NotebookRead':
530
- case 'notebook_read': {
531
- const path = input.notebook_path;
532
- return path ? `Read Notebook ${path}` : 'Read Notebook';
533
- }
534
- case 'NotebookEdit':
535
- case 'notebook_edit': {
536
- const path = input.notebook_path;
537
- return path ? `Edit Notebook ${path}` : 'Edit Notebook';
538
- }
539
- case 'Task':
540
- case 'task': {
541
- const description = input.description;
542
- return description || 'Task';
543
- }
544
- case 'TodoWrite':
545
- case 'todo_write': {
546
- return 'Update TODOs';
547
- }
548
- case 'AskUserQuestion':
549
- case 'ask_user_question':
550
- return 'Ask User';
551
- case 'SlashCommand':
552
- case 'slash_command': {
553
- const command = input.command;
554
- return command ? `Run: ${command}` : 'Slash Command';
555
- }
556
- case 'Skill':
557
- case 'skill': {
558
- const command = input.command;
559
- return command ? `Skill: ${command}` : 'Skill';
560
- }
561
- case 'LSP':
562
- case 'lsp': {
563
- const operation = input.operation;
564
- return operation ? `LSP: ${operation}` : 'LSP';
565
- }
566
- case 'EnterPlanMode':
567
- case 'enter_plan_mode':
568
- return 'Enter Plan Mode';
569
- case 'ExitPlanMode':
570
- case 'exit_plan_mode':
571
- return 'Exit Plan Mode';
572
- case 'TaskOutput':
573
- case 'task_output':
574
- return 'Get Task Output';
575
- default:
576
- return toolName || 'Unknown Tool';
577
- }
578
- }
579
- // ============= Private: Tool Kind Classification =============
580
- static getToolKind(toolName) {
581
- switch (toolName) {
582
- case 'Read':
583
- case 'read':
584
- case 'NotebookRead':
585
- case 'notebook_read':
586
- case 'Glob':
587
- case 'glob':
588
- return 'read';
589
- case 'Write':
590
- case 'write':
591
- case 'Edit':
592
- case 'edit':
593
- case 'MultiEdit':
594
- case 'NotebookEdit':
595
- case 'notebook_edit':
596
- return 'edit';
597
- case 'Bash':
598
- case 'bash':
599
- case 'BashOutput':
600
- case 'bash_output':
601
- case 'KillShell':
602
- case 'kill_shell':
603
- case 'TaskOutput':
604
- case 'task_output':
605
- return 'execute';
606
- case 'Grep':
607
- case 'grep':
608
- case 'WebSearch':
609
- case 'web_search':
610
- return 'search';
611
- case 'WebFetch':
612
- case 'web_fetch':
613
- return 'fetch';
614
- case 'Task':
615
- case 'task':
616
- case 'TodoWrite':
617
- case 'todo_write':
618
- case 'EnterPlanMode':
619
- case 'enter_plan_mode':
620
- case 'ExitPlanMode':
621
- case 'exit_plan_mode':
622
- return 'think';
623
- default:
624
- return 'other';
625
- }
626
- }
627
- // ============= Private: Content Generation by Tool Type =============
628
- static generateToolContent(toolName, input) {
629
- const content = [];
630
- switch (toolName) {
631
- case 'Edit':
632
- case 'edit':
633
- case 'MultiEdit': {
634
- const filePath = input.file_path;
635
- const oldString = input.old_string;
636
- const newString = input.new_string;
637
- if (filePath && oldString !== undefined && newString !== undefined) {
638
- content.push({
639
- type: 'diff',
640
- path: filePath,
641
- oldText: oldString || null,
642
- newText: newString,
643
- });
644
- }
645
- break;
646
- }
647
- case 'Bash':
648
- case 'bash': {
649
- const description = input.description;
650
- if (description) {
651
- content.push({
652
- type: 'content',
653
- content: { type: 'text', text: description },
654
- });
655
- }
656
- break;
657
- }
658
- case 'Task':
659
- case 'task': {
660
- const prompt = input.prompt;
661
- if (prompt) {
662
- content.push({
663
- type: 'content',
664
- content: { type: 'text', text: prompt },
665
- });
666
- }
667
- break;
668
- }
669
- case 'WebFetch':
670
- case 'web_fetch': {
671
- const prompt = input.prompt;
672
- if (prompt) {
673
- content.push({
674
- type: 'content',
675
- content: { type: 'text', text: prompt },
676
- });
677
- }
678
- break;
679
- }
680
- }
681
- return content.length > 0 ? content : undefined;
682
- }
683
- // ============= Private: Location Extraction by Tool Type =============
684
- static extractToolLocations(toolName, input) {
685
- const locations = [];
686
- const filePath = input.file_path;
687
- const notebookPath = input.notebook_path;
688
- const path = input.path;
689
- if (filePath) {
690
- // For file operations, only include path, not line number
691
- // Line numbers should be added by specific operations that target specific lines
692
- locations.push({
693
- path: filePath,
694
- });
695
- }
696
- else if (notebookPath) {
697
- locations.push({ path: notebookPath });
698
- }
699
- else if (path && (toolName === 'Glob' || toolName === 'glob')) {
700
- locations.push({ path });
701
- }
702
- return locations.length > 0 ? locations : undefined;
703
- }
704
- // ============= Private: Content Format Conversion =============
705
- static formatAcpContentForSdk(toolCallContent) {
706
- var _a;
707
- if (toolCallContent.length === 0) {
708
- return '';
709
- }
710
- const blocks = [];
711
- for (const item of toolCallContent) {
712
- if (item.type === 'diff') {
713
- const diff = item;
714
- const diffText = `--- ${diff.path}
715
- +++ ${diff.path}
716
- ${AcpTransformer.formatDiffHunk((_a = diff.oldText) !== null && _a !== void 0 ? _a : null, diff.newText)}`;
717
- blocks.push({
718
- type: 'text',
719
- text: diffText,
720
- });
721
- }
722
- else if (item.type === 'content') {
723
- const contentItem = item;
724
- if (contentItem.content && contentItem.content.type === 'text' && contentItem.content.text) {
725
- blocks.push({
726
- type: 'text',
727
- text: contentItem.content.text,
728
- });
729
- }
730
- }
731
- else if (item.type === 'terminal') {
732
- const terminalItem = item;
733
- if (terminalItem.terminalId) {
734
- blocks.push({
735
- type: 'text',
736
- text: `[Terminal: ${terminalItem.terminalId}]`,
737
- });
738
- }
739
- }
740
- }
741
- if (blocks.length === 1 && blocks[0].type === 'text') {
742
- return blocks[0].text;
743
- }
744
- return blocks.length > 0 ? blocks : '';
745
- }
746
- static formatDiffHunk(oldText, newText) {
747
- const oldLines = oldText ? oldText.split('\n') : [];
748
- const newLines = newText.split('\n');
749
- const hunks = [];
750
- hunks.push(`@@ -1,${oldLines.length} +1,${newLines.length} @@`);
751
- for (const line of oldLines) {
752
- hunks.push(`-${line}`);
753
- }
754
- for (const line of newLines) {
755
- hunks.push(`+${line}`);
756
- }
757
- return hunks.join('\n');
758
- }
759
- // ============= Private: Prompt and Result Helpers =============
760
- static privateExtractPromptText(prompt) {
761
- let content = '';
762
- if (prompt && Array.isArray(prompt)) {
763
- for (const block of prompt) {
764
- if (block.type === 'text' && block.text) {
765
- content += block.text;
766
- }
767
- }
768
- }
769
- return content;
770
- }
771
- // ============= Private: Content Block Extraction =============
772
- static privateExtractToolUseBlocks(contentBlocks) {
773
- if (!Array.isArray(contentBlocks))
774
- return [];
775
- return contentBlocks.filter((block) => typeof block === 'object' &&
776
- block !== null &&
777
- 'type' in block &&
778
- block.type === 'tool_use');
779
- }
780
- static privateExtractTextContent(contentBlocks) {
781
- if (!Array.isArray(contentBlocks))
782
- return '';
783
- return contentBlocks
784
- .filter((block) => typeof block === 'object' &&
785
- block !== null &&
786
- 'type' in block &&
787
- block.type === 'text')
788
- .map((block) => block.text)
789
- .join('\n');
790
- }
791
- static privateCreateToolResultMessage(acpMessage, acpResult) {
792
- var _a;
793
- const toolResultBlock = AcpTransformer.convertAcpToolResultToSdk(acpResult.toolCallId, acpResult);
794
- return {
795
- type: 'user',
796
- session_id: ((_a = acpMessage.params) === null || _a === void 0 ? void 0 : _a.sessionId) || 'unknown',
797
- message: {
798
- role: 'user',
799
- content: [toolResultBlock],
800
- },
801
- parent_tool_use_id: acpResult.toolCallId,
802
- };
803
- }
804
- }
805
- exports.AcpTransformer = AcpTransformer;
806
- //# sourceMappingURL=tool-converter.js.map