/** * MediaUnderstanding capability runner. * * Orchestrates per-attachment fallback across providers for one capability * (audio / image / video). For each attachment: * 1. Build the candidate provider list from the registry, ordered by * autoPriority (lower = first), with caller-supplied `providerOrder` * overriding when set. * 2. Try providers in order. A provider is SKIPPED when it does not declare * the requested capability OR does not implement the corresponding method. * 3. The first provider whose capability call resolves successfully wins; * its output is recorded as `chosen`. Failures are recorded as attempts * and the next provider is tried. * 4. When ALL providers for an attachment fail, the attachment task is * `failed`; when no provider was even eligible (capability not registered), * it's `disabled`. * * DECISION (per docs/voice-rearchitecture.md §5): * - This is a thin runner only. xopc v2.0 ships ONLY audio; image/video * branches exist as type-level fall-throughs (the runner happily handles * them once a provider registers describeImage / describeVideo, but no * image-specific helpers — like multi-image batching — live here yet). * - We deliberately do NOT port openclaw's `MediaAttachmentCache` (which * handles temp-file extraction, SSRF re-validation on remote URLs, etc.). * For xopc v2.0 the caller is expected to pre-load the buffer; remote URL * fetching is the caller's responsibility (typically the channel adapter * does this before invoking the runner). */ import type { AudioTranscriptionRequest, CapabilityAttachmentInput, ImageDescriptionRequest, MediaCapability, MediaUnderstandingProvider, MediaUnderstandingResult, VideoDescriptionRequest } from './types.js'; export type { CapabilityAttachmentInput } from './types.js'; export interface RunCapabilityOptions { capability: MediaCapability; attachments: readonly CapabilityAttachmentInput[]; /** Caller-supplied ordering. When set, overrides registry autoPriority. */ providerOrder?: readonly string[]; /** * Per-provider request builder. Returned shape MUST match the capability: * audio → AudioTranscriptionRequest * image → ImageDescriptionRequest * video → VideoDescriptionRequest * The runner does not synthesize api keys / urls — that's the caller's job * (typically reads from cfg.tools.media.audio.providers[providerId]). */ buildRequest: (params: { provider: MediaUnderstandingProvider; attachment: CapabilityAttachmentInput; }) => AudioTranscriptionRequest | ImageDescriptionRequest | VideoDescriptionRequest | undefined; /** Optional global timeout signal (e.g. from agent-level cancellation). */ signal?: AbortSignal; } export declare function runCapability(options: RunCapabilityOptions): Promise;