import { ORPCError } from '@orpc/client' import type { MarketClient } from './client.js' import type { AgentResult } from './schemas.js' export class AgentError extends Error { constructor(message: string) { super(message) this.name = 'AgentError' } } export interface AgentInput { goal: string /** Reference images, each an http(s) URL or a data:image URI. */ referenceImages?: string[] } // The server bounds a run well under this; it only guards against a run that // never settles at all. const RUN_TIMEOUT_MS = 5 * 60 * 1000 /** * Start an agent run and wait for its result. `status` long-polls — it blocks * server-side until the run settles or a heartbeat window elapses — so we * re-request immediately with no client-side delay and no polling interval. */ export async function agentAndWait(client: MarketClient, input: AgentInput): Promise { const { runId } = await client.asset.agent.start(input) const deadline = Date.now() + RUN_TIMEOUT_MS for (;;) { const status = await pollStatus(client, runId) if (status.status === 'completed') return status.result if (status.status === 'failed') throw new AgentError(status.error) if (Date.now() > deadline) throw new AgentError('Agent run timed out') } } async function pollStatus(client: MarketClient, runId: string) { try { return await client.asset.agent.status({ runId }) } catch (error) { // Runs live only in worker memory; a 404 for a run we just started means the // worker restarted mid-run and the run is gone. if (error instanceof ORPCError && error.status === 404) { throw new AgentError('Agent run was interrupted by a server restart; run it again.') } throw error } }