import { HarnessV1Prompt, HarnessV1ResumeSessionState, HarnessV1ContinueTurnState } from '@ai-sdk/harness'; import { HarnessAgentSession } from '@ai-sdk/harness/agent'; type HarnessWorkflowModelMessage = { readonly role: 'system'; readonly content: any; } | { readonly role: 'user'; readonly content: any; } | { readonly role: 'assistant'; readonly content: any; } | { readonly role: 'tool'; readonly content: any; }; /** * Where a workflow-driven harness run is in its execution loop. * * - `not_started` — fresh state, no workflow step has run yet. * - `ready_for_next_step` — the turn remains unfinished and `continueFrom` * carries the cursor for the next workflow step. * - `awaiting_tool_approval` — the turn emitted one or more tool approval * requests and `continueFrom` carries the suspended turn. * - `finished` — the agent turn completed on its own; `finalResult` is set. * - `failed` — the turn errored; `error` is set. */ type HarnessWorkflowStatus = 'not_started' | 'ready_for_next_step' | 'awaiting_tool_approval' | 'finished' | 'failed' /** @deprecated Use `ready_for_next_step` instead. */ | 'timed_out'; interface HarnessWorkflowUsageSummary { readonly inputTokens?: number; readonly outputTokens?: number; } interface HarnessWorkflowFinalResult { readonly sessionId: string; readonly finishReason: string; readonly usage?: HarnessWorkflowUsageSummary; } interface HarnessWorkflowSerializedChunk { readonly type: string; readonly [key: string]: unknown; } interface HarnessWorkflowStreamContext { readonly activeTextParts?: Record; readonly activeReasoningParts?: Record; readonly pendingToolInputs?: Record; } /** * Serializable state machine threaded between workflow steps. A `'use step'` * returns the next value of this object, and the Workflow DevKit persists that * return value — so this is the entire durable state of a harness run. Every * field must be JSON-serializable. * * Two independent lifecycle states drive the engine: * * - `resumeFrom` reattaches to a warm session before starting this run's new * user turn. * - `continueFrom` reattaches to a suspended turn from this same run and * continues it without sending `prompt` again. */ interface HarnessWorkflowState { /** * Stable harness session id; doubles as the sandbox name across processes. * Reuse the chat/conversation id so every user turn resumes the same warm * session and the agent retains prior-turn context. */ readonly sessionId: string; /** * The new user turn for this run — a plain string or a single * `UserModelMessage` (the harness's own {@link HarnessV1Prompt}), so * structured content survives instead of being flattened to text. Sent once, * on the execution that starts the turn. */ readonly prompt: HarnessV1Prompt; /** * Full AI SDK model messages for continuing a suspended approval turn. When * present, the next execution sends these to `HarnessAgent.stream()` so * approval responses can resume the suspended turn. */ readonly messages?: HarnessWorkflowModelMessage[]; readonly status: HarnessWorkflowStatus; /** * Resume coordinates for the next user turn. Absent only on the first turn of * a brand-new conversation or when the sandbox was destroyed after finish. */ readonly resumeFrom?: HarnessV1ResumeSessionState; /** * Continuation coordinates for this run's current suspended turn. When * present, the next execution continues the turn rather than sending `prompt` * again. */ readonly continueFrom?: HarnessV1ContinueTurnState; readonly streamContext?: HarnessWorkflowStreamContext; readonly finalResult?: HarnessWorkflowFinalResult; readonly error?: string; } /** * Input for one user turn — the argument to {@link createHarnessWorkflowState} * and the natural shape for a workflow function's input. `sessionId` is required * (and must be caller-supplied, since the workflow runtime forbids * non-deterministic id generation inside a step) — reuse the conversation id so * the sandbox name is stable across turns. Pass `resumeFrom` (the handle * persisted after the previous turn) to resume the warm conversation; omit it * only for the first turn of a new conversation. */ interface HarnessWorkflowInput { prompt?: HarnessV1Prompt; messages?: HarnessWorkflowModelMessage[]; sessionId: string; resumeFrom?: HarnessV1ResumeSessionState; continueFrom?: HarnessV1ContinueTurnState; } /** Initial state for one user turn (see {@link HarnessWorkflowInput}). */ declare function createHarnessWorkflowState(input: HarnessWorkflowInput): HarnessWorkflowState; /** * Collapse a terminal state into its result. Throws if the run failed; returns * the captured `finalResult` when finished, or a best-effort result otherwise. */ declare function finalizeHarnessWorkflow(state: HarnessWorkflowState): HarnessWorkflowFinalResult; /** The non-string arm of {@link HarnessV1Prompt} — a single `UserModelMessage`. */ type HarnessV1UserMessage = Exclude; /** A UI-message-stream chunk. Kept structural so this package need not depend on `ai`. */ interface HarnessWorkflowChunk { readonly type: string; readonly [key: string]: unknown; } /** * The subset of a harness `stream()` / `continueStream()` result the runner uses. * `StreamTextResult` satisfies it structurally. */ interface HarnessWorkflowStreamResult { toUIMessageStream(): ReadableStream; readonly finishReason: PromiseLike; readonly totalUsage: PromiseLike; } /** * The subset of `HarnessAgent` the runner drives. Declared structurally so * the engine is decoupled from the concrete agent generics and easy to mock. */ interface HarnessWorkflowAgent { createSession(options?: { sessionId?: string; resumeFrom?: HarnessV1ResumeSessionState; continueFrom?: HarnessV1ContinueTurnState; }): Promise; stream(options: { session: HarnessAgentSession; /** * The new user turn. A string or an array of user messages — the shape * `HarnessAgent.stream` accepts (it collapses an array to its last user * entry). The engine passes the run's single {@link HarnessV1Prompt}. */ prompt: string | HarnessV1UserMessage[]; messages?: undefined; } | { session: HarnessAgentSession; prompt?: undefined; messages: HarnessWorkflowModelMessage[]; }): Promise; continueStream(options: { session: HarnessAgentSession; }): Promise; } interface RunHarnessAgentOptions { readonly agent: HarnessWorkflowAgent; readonly state: HarnessWorkflowState; readonly timeSliceSeconds?: number; /** * When the turn finishes, whether to destroy the sandbox. Defaults to `false`: * the session is parked or stopped and a fresh resume state is returned in * `resumeFrom`, so the next user turn reattaches to the same conversation * (multi-turn chat). Set `true` for a one-shot run that should release the * sandbox when the turn completes. */ readonly destroyOnFinish?: boolean; /** * Where to write the turn's UI-message chunks. Defaults to the workflow's * output stream (`getWritable()` from `workflow`). Inject a stream in tests * to run the engine without a workflow runtime. */ readonly writable?: WritableStream; } type RunHarnessAgentStepOptions = Omit; /** * Run a harness agent until its next semantic step boundary. * * Configure the agent with a `stopWhen` condition such as `isStepCount(1)`. * When that condition completes a result while the underlying turn remains * unfinished, the returned state has status `ready_for_next_step` and carries * the continuation state for the next workflow step. */ declare function runHarnessAgentStep(options: RunHarnessAgentStepOptions): Promise; interface RunHarnessAgentTimeSliceOptions extends Omit { /** * Wall-clock budget for one time slice. Defaults to 750 seconds. */ readonly timeSliceSeconds?: number; } /** * Run one time-boxed slice of a durable harness agent turn. * * When the time slice completes before the turn, the returned state has status * `ready_for_next_step` and carries the continuation state for the next slice. */ declare function runHarnessAgentTimeSlice(options: RunHarnessAgentTimeSliceOptions): Promise; interface RunHarnessAgentSliceOptions extends Omit { readonly timeSliceSeconds?: number; /** * @deprecated Use `timeSliceSeconds` instead. */ readonly sliceTimeoutSeconds?: number; } /** * @deprecated Use {@link runHarnessAgentTimeSlice} instead. */ declare function runHarnessAgentSlice(options: RunHarnessAgentSliceOptions): Promise; export { type HarnessWorkflowAgent, type HarnessWorkflowChunk, type HarnessWorkflowFinalResult, type HarnessWorkflowInput, type HarnessWorkflowModelMessage, type HarnessWorkflowState, type HarnessWorkflowStatus, type HarnessWorkflowStreamResult, type HarnessWorkflowUsageSummary, type RunHarnessAgentSliceOptions, type RunHarnessAgentStepOptions, type RunHarnessAgentTimeSliceOptions, createHarnessWorkflowState, finalizeHarnessWorkflow, runHarnessAgentSlice, runHarnessAgentStep, runHarnessAgentTimeSlice };