/** @file Tools progress module. */ import type { PiToolShell, ProgressChecklistItem, ProgressCounts, ProgressDetails, ProgressState, TimingInfo, } from "../../types.ts"; import type { ToolUpdate } from "./define.ts"; export interface ProgressOptions { state: ProgressState; message?: string; url?: string; current?: number; total?: number; timing?: Partial; data?: TData; checklist?: ProgressChecklistItem[]; counts?: ProgressCounts; } export function progressShell( options: ProgressOptions, ): PiToolShell> { return { content: [{ type: "text", text: progressText(options) }], details: { _progress: true, state: options.state, message: options.message, url: options.url, current: options.current, total: options.total, timing: options.timing, data: options.data, checklist: options.checklist, counts: options.counts, }, }; } export async function emitProgress( onUpdate: ToolUpdate | undefined, options: ProgressOptions, ): Promise { try { await onUpdate?.(progressShell(options)); } catch { /* progress is best-effort; swallow host-handler rejections */ } } function progressText(options: ProgressOptions): string { const count = options.total ? ` ${options.current ?? 0}/${options.total}` : ""; const url = options.url ? ` · ${options.url}` : ""; return `${options.state}${count}${url}${options.message ? ` · ${options.message}` : ""}`; }