eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
813 lines (812 loc) • 27.3 kB
TypeScript
import type { FileUIPart, ProviderMetadata, TextUIPart, UserContent } from "ai";
import type { ConnectionAuthorizationChallenge } from "#public/connections/errors.js";
import type { RuntimeActionRequest, RuntimeActionResult } from "#runtime/actions/types.js";
import type { InputRequest, InputResponse } from "#runtime/input/types.js";
import type { JsonObject, JsonValue } from "#shared/json.js";
export declare const EVE_SESSION_ID_HEADER = "x-eve-session-id";
export declare const EVE_STREAM_FORMAT_HEADER = "x-eve-stream-format";
export declare const EVE_STREAM_VERSION_HEADER = "x-eve-stream-version";
export declare const EVE_MESSAGE_STREAM_CONTENT_TYPE = "application/x-ndjson; charset=utf-8";
export declare const EVE_MESSAGE_STREAM_FORMAT = "ndjson";
export declare const EVE_MESSAGE_STREAM_VERSION = "19";
/**
* eve-owned finish reason for one completed assistant step.
*
* `tool-calls` is the only non-terminal assistant step in the current
* tool-loop harness. All other values indicate the assistant step ended the
* current turn.
*/
export type AssistantStepFinishReason = "content-filter" | "error" | "length" | "other" | "stop" | "tool-calls";
type ProviderMetadataEntry = NonNullable<ProviderMetadata[string]>;
type GatewayGenerationId = Extract<ProviderMetadataEntry["generationId"], string>;
export interface StepCompletedProviderMetadata {
readonly gateway: {
readonly generationId: GatewayGenerationId;
};
}
/**
* Durable metadata attached to one persisted session stream event.
*
* Runtime code stamps this immediately before writing the event to the
* workflow-owned stream so replay preserves the original timing.
*/
export interface HandleMessageStreamEventMeta {
readonly at: string;
}
/**
* Normalized completion status for one emitted runtime action result.
*
* `rejected` marks a tool call the user (or a policy) denied at a HITL
* approval gate: it never executed, so it is neither a success nor a
* runtime failure.
*/
export type ActionResultStatus = "completed" | "failed" | "rejected";
/**
* Stable failure payload projected onto `action.result`.
*
* This keeps UI consumers from having to parse provider- or tool-specific
* output strings just to determine whether a tool call failed.
*/
export interface ActionResultError {
readonly code: string;
readonly message: string;
}
/**
* Invocation metadata attached to the `session.started` event for one child
* subagent workflow session.
*/
export interface SubagentSessionInvocationMetadata {
readonly kind: "subagent";
readonly parentCallId: string;
readonly parentSessionId: string;
readonly parentTurnId: string;
readonly name: string;
}
/**
* Runtime identity metadata attached to the `session.started` event.
*
* The server populates this at run time so remote eval processes and
* reporters receive authoritative metadata about the eve instance
* serving the run.
*/
export interface RuntimeIdentity {
readonly agentId: string;
readonly agentName?: string;
readonly eveVersion: string;
readonly build?: {
readonly deployedAt?: string;
readonly gitBranch?: string;
readonly gitSha?: string;
};
/** Configured model id; dynamic-model agents report `dynamic:<fallback id>`. */
readonly modelId: string;
}
/**
* JSON request accepted by the canonical message route.
*
* `message` is either a plain text string or an AI SDK `UserContent`
* array (mixing `text`, `image`, and `file` parts). Clients pass
* multimodal attachments with the same shape AI SDK's `useChat`
* `sendMessage({ files })` produces. `clientContext` is one-turn
* client/page context; the channel converts it into internal model context.
*/
export type HandleMessageRequestBody = {
readonly message: string | UserContent;
readonly clientContext?: string | readonly string[] | JsonObject;
readonly outputSchema?: JsonObject;
} | {
readonly continuationToken: string;
readonly message: string | UserContent;
readonly clientContext?: string | readonly string[] | JsonObject;
readonly outputSchema?: JsonObject;
} | {
readonly continuationToken: string;
readonly inputResponses: readonly InputResponse[];
readonly clientContext?: string | readonly string[] | JsonObject;
readonly outputSchema?: JsonObject;
} | {
readonly continuationToken: string;
readonly inputResponses: readonly InputResponse[];
readonly message: string | UserContent;
readonly clientContext?: string | readonly string[] | JsonObject;
readonly outputSchema?: JsonObject;
};
/**
* Stream event emitted when the durable message workflow session starts.
*/
export interface SessionStartedStreamEvent {
data: {
invocation?: SubagentSessionInvocationMetadata;
runtime?: RuntimeIdentity;
};
type: "session.started";
}
/**
* Stream event emitted when one runtime turn starts.
*/
export interface TurnStartedStreamEvent {
data: {
sequence: number;
turnId: string;
};
type: "turn.started";
}
/**
* Stream event emitted when the runtime receives one normalized user message.
*
* `message` is the existing flattened text summary. `parts` carries the
* structured projection current emitters provide for clients that render
* attachments.
*/
export interface MessageReceivedStreamEvent {
data: {
message: string;
parts?: readonly MessageReceivedPart[];
sequence: number;
turnId: string;
};
type: "message.received";
}
/**
* One structured part of a received user message.
*
* This mirrors the AI SDK UI text/file part surface, narrowed to renderable
* metadata only. Raw bytes and framework-internal sandbox paths are never
* projected; `url` is optional because it is present only for client-resolvable
* `http(s)` and `data:` URLs.
*/
export type MessageReceivedPart = Readonly<Pick<TextUIPart, "text" | "type">> | (Readonly<Pick<FileUIPart, "filename" | "mediaType" | "type">> & {
readonly size?: number;
readonly url?: FileUIPart["url"];
});
/**
* Stream event emitted when the model requests one or more actions.
*
* A `tool-call` is one action kind, alongside `load-skill` and subagent calls.
* Calls may arrive incrementally before execution, so consumers must correlate
* action lifecycles by call ID rather than assume one event contains every call
* from an assistant step.
*/
export interface ActionsRequestedStreamEvent {
data: {
actions: readonly RuntimeActionRequest[];
sequence: number;
stepIndex: number;
turnId: string;
};
type: "actions.requested";
}
/**
* Stream event emitted when the harness needs human input before it can
* continue the run.
*/
export interface InputRequestedStreamEvent {
data: {
requests: readonly InputRequest[];
sequence: number;
stepIndex: number;
turnId: string;
};
type: "input.requested";
}
/**
* Stream event emitted for each runtime action result projected back into the
* session loop.
*/
export interface ActionResultStreamEvent {
data: {
error?: ActionResultError;
result: RuntimeActionResult;
sequence: number;
stepIndex: number;
status: ActionResultStatus;
turnId: string;
};
type: "action.result";
}
/**
* Stream event emitted when the parent workflow starts a child subagent session.
*/
export interface SubagentCalledStreamEvent {
data: {
callId: string;
childSessionId: string;
sessionId: string;
sequence: number;
name: string;
remote?: {
url: string;
};
toolName: string;
turnId: string;
workflowId: string;
};
type: "subagent.called";
}
/**
* Stream event emitted when an inline subagent execution starts.
*/
export interface SubagentStartedStreamEvent {
data: {
callId: string;
subagentName: string;
};
type: "subagent.started";
}
/**
* Stream event (`type: "subagent.event"`) wrapping one child stream event
* produced by an inline subagent, under `data.event`, tagged with the
* originating `data.callId` and `data.subagentName`.
*/
export interface SubagentChildEventStreamEvent {
data: {
callId: string;
event: HandleMessageStreamEvent;
subagentName: string;
};
type: "subagent.event";
}
/**
* Stream event emitted when an inline subagent completes.
*/
export interface SubagentCompletedStreamEvent {
data: {
callId: string;
output: string;
subagentName: string;
};
type: "subagent.completed";
}
/**
* Stream event emitted when one assistant text delta is appended to the
* current message for the current step.
*/
export interface MessageAppendedStreamEvent {
data: {
messageDelta: string;
messageSoFar: string;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "message.appended";
}
/**
* Stream event emitted when one reasoning delta is appended to the current
* reasoning block for the current step.
*/
export interface ReasoningAppendedStreamEvent {
data: {
reasoningDelta: string;
reasoningSoFar: string;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "reasoning.appended";
}
/**
* Stream event emitted when one assistant step completes with visible text.
*
* Events preserve the order of the underlying model response messages. A
* single turn may emit more than one completed assistant message when the
* model replies before requesting a tool call. `data.finishReason` describes
* why that assistant message boundary completed.
*/
export interface MessageCompletedStreamEvent {
data: {
finishReason: AssistantStepFinishReason;
message: string | null;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "message.completed";
}
/**
* Stream event emitted when one completed reasoning block is available for the
* current step.
*/
export interface ReasoningCompletedStreamEvent {
data: {
reasoning: string;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "reasoning.completed";
}
/**
* Stream event emitted when the harness finalized a structured result that
* matches the requested output schema.
*/
export interface ResultCompletedStreamEvent {
data: {
result: JsonValue;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "result.completed";
}
/**
* Stream event emitted when one model call starts inside the current turn.
*/
export interface StepStartedStreamEvent {
data: {
sequence: number;
stepIndex: number;
turnId: string;
};
type: "step.started";
}
/**
* Stream event emitted when one model call completes successfully.
*/
export interface StepCompletedStreamEvent {
data: {
finishReason: AssistantStepFinishReason;
providerMetadata?: StepCompletedProviderMetadata;
sequence: number;
stepIndex: number;
turnId: string;
usage?: {
readonly costUsd?: number;
readonly inputTokens?: number;
readonly outputTokens?: number;
readonly cacheReadTokens?: number;
readonly cacheWriteTokens?: number;
};
};
type: "step.completed";
}
/**
* Stream event emitted when one model call fails.
*/
export interface StepFailedStreamEvent {
data: {
code: string;
details?: JsonObject;
message: string;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "step.failed";
}
/**
* Stream event emitted when one turn reaches a terminal successful outcome.
*/
export interface TurnCompletedStreamEvent {
data: {
sequence: number;
turnId: string;
};
type: "turn.completed";
}
/**
* Stream event emitted when one turn fails.
*/
export interface TurnFailedStreamEvent {
data: {
code: string;
details?: JsonObject;
message: string;
sequence: number;
turnId: string;
};
type: "turn.failed";
}
/**
* Stream event emitted when one turn is cancelled before reaching a
* terminal outcome. Cancellation is not failure: the turn ends without
* `turn.failed`/`session.failed`, is followed by `session.waiting`, and
* the session accepts the next message normally.
*/
export interface TurnCancelledStreamEvent {
data: {
sequence: number;
turnId: string;
};
type: "turn.cancelled";
}
/**
* Stream event emitted when the workflow decides to compact the current
* visible session history before the next model fragment runs.
*/
export interface CompactionRequestedStreamEvent {
data: {
modelId: string;
sequence: number;
sessionId: string;
turnId: string;
usageInputTokens: number | null;
};
type: "compaction.requested";
}
/**
* Stream event emitted after one compaction checkpoint message has been
* appended to the durable session history.
*/
export interface CompactionCompletedStreamEvent {
data: {
modelId: string;
sequence: number;
sessionId: string;
turnId: string;
};
type: "compaction.completed";
}
/**
* Stream event emitted when a connection or tool needs user authorization
* before it can continue.
*/
export interface AuthorizationRequiredStreamEvent {
data: {
authorization?: ConnectionAuthorizationChallenge;
description: string;
name: string;
sequence: number;
stepIndex: number;
turnId: string;
webhookUrl?: string;
};
type: "authorization.required";
}
/**
* Outcome of one completed authorization attempt, emitted on
* {@link AuthorizationCompletedStreamEvent}.
*/
export type AuthorizationOutcome = "authorized" | "declined" | "failed" | "timed-out";
/**
* @deprecated Use {@link AuthorizationOutcome}.
*/
export type ConnectionAuthorizationOutcome = AuthorizationOutcome;
/**
* Stream event emitted once `completeAuthorization` has resolved
* (successfully or otherwise) for one pending authorization. Carries a
* stable `outcome` plus an optional human-readable `reason`.
*
* Emitted when the tool completes authorization on resume, before the
* model's next fragment streams in.
*/
export interface AuthorizationCompletedStreamEvent {
data: {
/**
* The challenge from the matching `authorization.required` event,
* journaled across the park. Lets channels keep rendering the
* challenge's `displayName` in completion status text.
*/
authorization?: ConnectionAuthorizationChallenge;
name: string;
outcome: AuthorizationOutcome;
reason?: string;
sequence: number;
stepIndex: number;
turnId: string;
};
type: "authorization.completed";
}
/**
* Stream event emitted when the session parks waiting for the next user
* message.
*/
export interface SessionWaitingStreamEvent {
data: {
/** Channel-owned resume handle for the next user turn. */
continuationToken: string;
wait: "next-user-message";
};
type: "session.waiting";
}
/**
* Stream event emitted when the session fails.
*/
export interface SessionFailedStreamEvent {
data: {
code: string;
details?: JsonObject;
message: string;
sessionId: string;
};
type: "session.failed";
}
/**
* Stream event emitted when the session completes successfully.
*/
export interface SessionCompletedStreamEvent {
type: "session.completed";
}
/**
* Serializable stream event union for the durable message session flow.
*/
export type HandleMessageStreamEvent = (CompactionCompletedStreamEvent | CompactionRequestedStreamEvent | AuthorizationCompletedStreamEvent | AuthorizationRequiredStreamEvent | MessageAppendedStreamEvent | MessageCompletedStreamEvent | MessageReceivedStreamEvent | ReasoningAppendedStreamEvent | SessionCompletedStreamEvent | SessionFailedStreamEvent | SessionStartedStreamEvent | SessionWaitingStreamEvent | ResultCompletedStreamEvent | SubagentCalledStreamEvent | SubagentChildEventStreamEvent | SubagentCompletedStreamEvent | SubagentStartedStreamEvent | ActionsRequestedStreamEvent | InputRequestedStreamEvent | ActionResultStreamEvent | ReasoningCompletedStreamEvent | StepCompletedStreamEvent | StepFailedStreamEvent | StepStartedStreamEvent | TurnCancelledStreamEvent | TurnCompletedStreamEvent | TurnFailedStreamEvent | TurnStartedStreamEvent) & {
readonly meta?: HandleMessageStreamEventMeta;
};
/**
* Stream events that represent an unrecovered turn/session failure.
*/
export type TurnFailureStreamEvent = SessionFailedStreamEvent | StepFailedStreamEvent | TurnFailedStreamEvent;
/**
* One public session stream event after runtime metadata has been stamped.
*
* Runtime/execution code owns this stamping boundary. Replays must preserve the
* original `meta.at` value instead of recomputing it.
*/
export type TimedHandleMessageStreamEvent = HandleMessageStreamEvent & {
readonly meta: HandleMessageStreamEventMeta;
};
/**
* Returns true when the current stream has reached a turn boundary or terminal
* session outcome.
*/
export declare function isCurrentTurnBoundaryEvent(event: HandleMessageStreamEvent): boolean;
/**
* Narrows a stream event to the failure events that terminate or poison a turn.
*/
export declare function isTurnFailureEvent(event: HandleMessageStreamEvent): event is TurnFailureStreamEvent;
/**
* Creates the `session.started` event for one session.
*/
export declare function createSessionStartedEvent(input?: {
readonly invocation?: SubagentSessionInvocationMetadata;
readonly runtime?: RuntimeIdentity;
}): SessionStartedStreamEvent;
/**
* Creates the `turn.started` event for one prepared runtime turn.
*/
export declare function createTurnStartedEvent(input: {
readonly sequence: number;
readonly turnId: string;
}): TurnStartedStreamEvent;
/**
* Creates the `message.received` event for one normalized user message.
*
* When the message is a structured `UserContent` array (e.g. text + file
* parts), the event surfaces a text summary: concatenated text parts with
* `[file: filename (mediaType)]` placeholders for non-text parts. This
* keeps the wire event as a simple string for dev-REPL and web
* consumers while preserving the authored turn content upstream.
*/
export declare function createMessageReceivedEvent(input: {
readonly message: string | UserContent;
readonly sequence: number;
readonly turnId: string;
}): MessageReceivedStreamEvent;
/**
* Creates the `actions.requested` event for one observed group of model action
* requests.
*/
export declare function createActionsRequestedEvent(input: {
readonly actions: readonly RuntimeActionRequest[];
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): ActionsRequestedStreamEvent;
/**
* Creates the `authorization.required` event for one authorization source
* that needs user authorization before it can continue.
*
* `authorization` and `webhookUrl` are present together when the runtime
* has suspended the turn on a framework-owned webhook; both are absent
* for `getToken`-only authorization sources that authorize out of band.
*/
export declare function createAuthorizationRequiredEvent(input: {
readonly authorization?: ConnectionAuthorizationChallenge;
readonly description: string;
readonly name: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
readonly webhookUrl?: string;
}): AuthorizationRequiredStreamEvent;
/**
* Creates the `authorization.completed` event emitted once per
* authorization source after `completeAuthorization` has resolved or the
* authorization deadline has expired.
*/
export declare function createAuthorizationCompletedEvent(input: {
readonly authorization?: ConnectionAuthorizationChallenge;
readonly name: string;
readonly outcome: AuthorizationOutcome;
readonly reason?: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): AuthorizationCompletedStreamEvent;
/**
* Creates the `input.requested` event for one pending HITL batch.
*/
export declare function createInputRequestedEvent(input: {
readonly requests: readonly InputRequest[];
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): InputRequestedStreamEvent;
/**
* Creates the `action.result` event for one runtime action result.
*
* Pass `rejected: true` for a tool call denied at a HITL approval gate. The
* call never executed, so the outcome is forced to `rejected` rather than
* derived from the synthesized denial output.
*/
export declare function createActionResultEvent(input: {
readonly rejected?: boolean;
readonly result: RuntimeActionResult;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): ActionResultStreamEvent;
/**
* Creates the `subagent.called` event for one started child workflow session.
*/
export declare function createSubagentCalledEvent(input: {
readonly callId: string;
readonly childSessionId: string;
readonly sessionId: string;
readonly sequence: number;
readonly name: string;
readonly remote?: {
readonly url: string;
};
readonly toolName: string;
readonly turnId: string;
readonly workflowId: string;
}): SubagentCalledStreamEvent;
/**
* Creates the `message.appended` event for one streamed assistant text delta.
*/
export declare function createMessageAppendedEvent(input: {
readonly messageDelta: string;
readonly messageSoFar: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): MessageAppendedStreamEvent;
/**
* Creates the `reasoning.appended` event for one streamed reasoning delta.
*/
export declare function createReasoningAppendedEvent(input: {
readonly reasoningDelta: string;
readonly reasoningSoFar: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): ReasoningAppendedStreamEvent;
/**
* Creates the `message.completed` event for one completed assistant text chunk.
*/
export declare function createMessageCompletedEvent(input: {
readonly finishReason?: AssistantStepFinishReason;
readonly message: string | null;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): MessageCompletedStreamEvent;
/**
* Creates the `reasoning.completed` event for one completed reasoning block.
*/
export declare function createReasoningCompletedEvent(input: {
readonly reasoning: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): ReasoningCompletedStreamEvent;
/**
* Creates the `result.completed` event for one finalized structured result.
*/
export declare function createResultCompletedEvent(input: {
readonly result: JsonValue;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): ResultCompletedStreamEvent;
/**
* Creates the `step.started` event for one model call.
*/
export declare function createStepStartedEvent(input: {
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): StepStartedStreamEvent;
/**
* Creates the `step.completed` event for one completed model call.
*/
export declare function createStepCompletedEvent(input: {
readonly finishReason: AssistantStepFinishReason;
readonly providerMetadata?: StepCompletedProviderMetadata;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
readonly usage?: {
readonly costUsd?: number;
readonly inputTokens?: number;
readonly outputTokens?: number;
readonly cacheReadTokens?: number;
readonly cacheWriteTokens?: number;
};
}): StepCompletedStreamEvent;
/**
* Creates the `step.failed` event for one failed model call.
*/
export declare function createStepFailedEvent(input: {
readonly code: string;
readonly details?: JsonObject;
readonly message: string;
readonly sequence: number;
readonly stepIndex: number;
readonly turnId: string;
}): StepFailedStreamEvent;
/**
* Creates the `turn.completed` event for one terminal successful turn.
*/
export declare function createTurnCompletedEvent(input: {
readonly sequence: number;
readonly turnId: string;
}): TurnCompletedStreamEvent;
/**
* Creates the `turn.failed` event for one failed turn.
*/
export declare function createTurnFailedEvent(input: {
readonly code: string;
readonly details?: JsonObject;
readonly message: string;
readonly sequence: number;
readonly turnId: string;
}): TurnFailedStreamEvent;
/** Creates the `turn.cancelled` event for one cancelled turn. */
export declare function createTurnCancelledEvent(input: {
readonly sequence: number;
readonly turnId: string;
}): TurnCancelledStreamEvent;
/**
* Creates the `compaction.requested` event for one runtime compaction pass.
*/
export declare function createCompactionRequestedEvent(input: {
readonly modelId: string;
readonly sequence: number;
readonly sessionId: string;
readonly turnId: string;
readonly usageInputTokens: number | undefined;
}): CompactionRequestedStreamEvent;
/**
* Creates the `compaction.completed` event for one appended checkpoint.
*/
export declare function createCompactionCompletedEvent(input: {
readonly modelId: string;
readonly sequence: number;
readonly sessionId: string;
readonly turnId: string;
}): CompactionCompletedStreamEvent;
/**
* Creates the `session.waiting` event for the only supported between-turn
* wait.
*/
export declare function createSessionWaitingEvent(namespacedContinuationToken: string): SessionWaitingStreamEvent;
/**
* Creates the `session.failed` event for one terminal session failure.
*/
export declare function createSessionFailedEvent(input: {
readonly code: string;
readonly details?: JsonObject;
readonly message: string;
readonly sessionId: string;
}): SessionFailedStreamEvent;
/**
* Creates the `session.completed` event for one terminal session completion.
*/
export declare function createSessionCompletedEvent(): SessionCompletedStreamEvent;
/**
* Stamps one session event with durable timing metadata immediately before it
* is written to the workflow-owned stream.
*
* Only runtime/execution code should call this. Keeping one stamping seam
* ensures every persisted event shares the same clock contract and replay never
* invents new timestamps.
*/
export declare function timestampHandleMessageStreamEvent(event: HandleMessageStreamEvent, at?: string): TimedHandleMessageStreamEvent;
/**
* Encodes one message stream event as newline-delimited JSON.
*/
export declare function encodeMessageStreamEvent(event: TimedHandleMessageStreamEvent): Uint8Array;
export {};