|
1 | | -import type { ToolCallContent } from "@agentclientprotocol/sdk"; |
| 1 | +import type { ContentBlock, ToolCallContent } from "@agentclientprotocol/sdk"; |
2 | 2 | import { applyPatch, parsePatch, reversePatch } from "diff"; |
3 | 3 | import { readFile } from "node:fs/promises"; |
4 | 4 | import path from "node:path"; |
@@ -104,6 +104,69 @@ export async function createDynamicToolCallUpdate( |
104 | 104 | return createExecuteToolCallUpdate(item, item.tool, { arguments: item.arguments }) |
105 | 105 | } |
106 | 106 |
|
| 107 | +export function createImageViewUpdate( |
| 108 | + item: ThreadItem & { type: "imageView" } |
| 109 | +): UpdateSessionEvent { |
| 110 | + const displayPath = item.path; |
| 111 | + return { |
| 112 | + sessionUpdate: "tool_call", |
| 113 | + toolCallId: item.id, |
| 114 | + kind: "read", |
| 115 | + title: `View Image ${displayPath}`, |
| 116 | + status: "completed", |
| 117 | + content: [createContent({ |
| 118 | + type: "resource_link", |
| 119 | + name: displayPath, |
| 120 | + uri: displayPath, |
| 121 | + })], |
| 122 | + locations: [{ path: item.path }], |
| 123 | + rawInput: { |
| 124 | + path: item.path, |
| 125 | + }, |
| 126 | + }; |
| 127 | +} |
| 128 | + |
| 129 | +export function createImageGenerationStartUpdate( |
| 130 | + item: ThreadItem & { type: "imageGeneration" } |
| 131 | +): UpdateSessionEvent { |
| 132 | + return { |
| 133 | + sessionUpdate: "tool_call", |
| 134 | + toolCallId: item.id, |
| 135 | + kind: "other", |
| 136 | + title: "Image generation", |
| 137 | + status: "in_progress", |
| 138 | + rawInput: { |
| 139 | + id: item.id, |
| 140 | + }, |
| 141 | + }; |
| 142 | +} |
| 143 | + |
| 144 | +export function createImageGenerationCompleteUpdate( |
| 145 | + item: ThreadItem & { type: "imageGeneration" } |
| 146 | +): UpdateSessionEvent { |
| 147 | + return { |
| 148 | + sessionUpdate: "tool_call_update", |
| 149 | + toolCallId: item.id, |
| 150 | + status: imageGenerationToolStatus(item.status), |
| 151 | + content: imageGenerationContent(item), |
| 152 | + rawOutput: imageGenerationRawOutput(item), |
| 153 | + }; |
| 154 | +} |
| 155 | + |
| 156 | +export function createImageGenerationUpdate( |
| 157 | + item: ThreadItem & { type: "imageGeneration" } |
| 158 | +): UpdateSessionEvent { |
| 159 | + return { |
| 160 | + sessionUpdate: "tool_call", |
| 161 | + toolCallId: item.id, |
| 162 | + kind: "other", |
| 163 | + title: "Image generation", |
| 164 | + status: imageGenerationToolStatus(item.status), |
| 165 | + content: imageGenerationContent(item), |
| 166 | + rawOutput: imageGenerationRawOutput(item), |
| 167 | + }; |
| 168 | +} |
| 169 | + |
107 | 170 | export async function createExecuteToolCallUpdate( |
108 | 171 | item: ThreadItem & ({ type: "mcpToolCall" } | { type: "dynamicToolCall" }), |
109 | 172 | title: string, |
@@ -257,6 +320,74 @@ function createSearchTitle(query: string | null, path: string | null): string { |
257 | 320 | return "Search"; |
258 | 321 | } |
259 | 322 |
|
| 323 | +function imageGenerationToolStatus(status: string): AcpToolCallStatus { |
| 324 | + switch (status) { |
| 325 | + case "completed": |
| 326 | + return "completed"; |
| 327 | + case "generating": |
| 328 | + case "in_progress": |
| 329 | + case "inProgress": |
| 330 | + case "incomplete": |
| 331 | + return "in_progress"; |
| 332 | + case "failed": |
| 333 | + return "failed"; |
| 334 | + default: |
| 335 | + return "completed"; |
| 336 | + } |
| 337 | +} |
| 338 | + |
| 339 | +function imageGenerationContent( |
| 340 | + item: ThreadItem & { type: "imageGeneration" } |
| 341 | +): ToolCallContent[] { |
| 342 | + const content: ToolCallContent[] = []; |
| 343 | + |
| 344 | + if (item.revisedPrompt && item.revisedPrompt.trim() !== "") { |
| 345 | + content.push(createContent({ |
| 346 | + type: "text", |
| 347 | + text: `Revised prompt: ${item.revisedPrompt}`, |
| 348 | + })); |
| 349 | + } |
| 350 | + |
| 351 | + if (item.result.trim() !== "") { |
| 352 | + const image: ContentBlock = item.savedPath && item.savedPath.trim() !== "" |
| 353 | + ? { |
| 354 | + type: "image", |
| 355 | + data: item.result, |
| 356 | + mimeType: "image/png", |
| 357 | + uri: item.savedPath, |
| 358 | + } |
| 359 | + : { |
| 360 | + type: "image", |
| 361 | + data: item.result, |
| 362 | + mimeType: "image/png", |
| 363 | + }; |
| 364 | + content.push(createContent(image)); |
| 365 | + } |
| 366 | + |
| 367 | + return content; |
| 368 | +} |
| 369 | + |
| 370 | +function imageGenerationRawOutput( |
| 371 | + item: ThreadItem & { type: "imageGeneration" } |
| 372 | +): Record<string, string | null> { |
| 373 | + const output: Record<string, string | null> = { |
| 374 | + status: item.status, |
| 375 | + revisedPrompt: item.revisedPrompt, |
| 376 | + result: item.result, |
| 377 | + }; |
| 378 | + if ("savedPath" in item) { |
| 379 | + output["savedPath"] = item.savedPath ?? null; |
| 380 | + } |
| 381 | + return output; |
| 382 | +} |
| 383 | + |
| 384 | +function createContent(content: ContentBlock): ToolCallContent { |
| 385 | + return { |
| 386 | + type: "content", |
| 387 | + content, |
| 388 | + }; |
| 389 | +} |
| 390 | + |
260 | 391 | async function createPatchContent(change: FileUpdateChange): Promise<ToolCallContent | null> { |
261 | 392 | try { |
262 | 393 | switch (change.kind.type) { |
|
0 commit comments