"use strict"; import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { Type } from "typebox"; import { getConfig } from "../config"; import { processImage } from "../media"; import { visionCompletion } from "../client"; import { GENERAL_IMAGE_ANALYSIS } from "../prompts"; import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, truncateHead, } from "@earendil-works/pi-coding-agent"; export function registerImageAnalysisTool(pi: ExtensionAPI) { pi.registerTool({ name: "image_analysis", label: "Image Analysis", description: "Analyze any image and provide detailed description, object identification, context understanding, or answer specific questions about visual content. Supports local files (png, jpg) and HTTP(S) URLs.", promptSnippet: "Analyze images with GLM-4.6V vision — describe/identify/extract/answer based on user prompt", promptGuidelines: [ "Use image_analysis when the user asks you to describe an image, identify objects, or answer questions about visual content. This is the general-purpose vision tool — use it when no more specific vision tool (extract_text_from_screenshot, diagnose_error_screenshot, etc.) fits the task.", ], parameters: Type.Object({ imagePath: Type.String({ description: "Path to the image file (relative to cwd, supports @ prefix) or an HTTP(S) URL.", }), prompt: Type.String({ description: "What should the AI analyze or answer about this image? Be specific about what you want to know.", }), }), async execute(_toolCallId, params, signal, onUpdate, ctx) { const config = getConfig(); onUpdate?.({ content: [{ type: "text", text: "正在调用 GLM-4.6V 分析图片..." }], }); const image = processImage(params.imagePath, ctx.cwd, config.maxImageSizeMB); const result = await visionCompletion( config, GENERAL_IMAGE_ANALYSIS, [image], params.prompt, signal ); const truncated = truncateHead(result, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES, }); let text = truncated.content; if (truncated.truncated) { text += `\n\n[输出已截断: ${truncated.outputLines}/${truncated.totalLines} 行]`; } return { content: [{ type: "text", text }], details: { raw: result }, }; }, }); }