ai
Version:
AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.
432 lines (391 loc) • 15.4 kB
text/typescript
import type { ToolSet } from '@ai-sdk/provider-utils';
import type {
EmbedEndEvent,
EmbedStartEvent,
EmbeddingModelCallEndEvent,
EmbeddingModelCallStartEvent,
} from '../embed/embed-events';
import type {
DecideEndEvent,
DecideStartEvent,
DecisionModelCallEndEvent,
DecisionModelCallStartEvent,
} from '../decide/decide-events';
import type {
GenerateObjectEndEvent,
GenerateObjectStartEvent,
GenerateObjectStepEndEvent,
GenerateObjectStepStartEvent,
} from '../generate-object/structured-output-events';
import type {
GenerateTextAbortEvent,
GenerateTextEndEvent,
GenerateTextStartEvent,
GenerateTextStepEndEvent,
GenerateTextStepErrorEvent,
GenerateTextStepStartEvent,
} from '../generate-text/generate-text-events';
import type {
LanguageModelCallEndEvent,
LanguageModelCallStartEvent,
OnLanguageModelCallEndCallback,
OnLanguageModelCallStartCallback,
} from '../generate-text/language-model-events';
import type {
ToolExecutionEndEvent,
ToolExecutionStartEvent,
} from '../generate-text/tool-execution-events';
import type {
RerankEndEvent,
RerankStartEvent,
RerankingModelCallEndEvent,
RerankingModelCallStartEvent,
} from '../rerank/rerank-events';
import type {
GenerateSpeechEndEvent,
GenerateSpeechStartEvent,
} from '../generate-speech/speech-events';
import type {
StreamTranscriptionEndEvent,
StreamTranscriptionStartEvent,
TranscriptionEndEvent,
TranscriptionStartEvent,
} from '../transcribe/transcription-events';
import type { Callback } from '../util/callback';
import type { TelemetryOptions } from '../telemetry/telemetry-options';
import type { TelemetryTracingEventType } from './tracing-channel';
import type { TracingChannelContext } from './tracing-channel-publisher';
/** Serializable tracing identity shared by the processes of a durable run. */
export type DurableTelemetryContext = {
traceId: string;
rootSpanId: string;
/** The integration's root-span data, reused when the run is reported. */
rootSpanName?: string;
rootAttributes?: Record<
string,
| string
| number
| boolean
| Array<string | null | undefined>
| Array<number | null | undefined>
| Array<boolean | null | undefined>
| undefined
>;
traceFlags: number;
traceState?: string;
samplingDecision: 0 | 1 | 2;
parentSpanContext?: {
traceId: string;
spanId: string;
traceFlags: number;
traceState?: string;
};
};
/** Identifies live model events and the run events reported after completion. */
export type DurableTelemetryEventContext = {
run: DurableTelemetryContext;
stepNumber?: number;
phase: 'live' | 'replay';
/** Context has already been filtered before crossing the step boundary. */
runtimeContext?: Record<string, unknown>;
headers?: Record<string, string | undefined>;
};
export type InferTelemetryEvent<EVENT> = EVENT &
Omit<
TelemetryOptions,
'integrations' | 'isEnabled' | 'includeRuntimeContext'
> & {
/**
* The version of the `ai` package that emitted this event.
* Absent in older releases.
*/
readonly aiVersion?: string;
/**
* Time at which the event occurred, in milliseconds since the Unix epoch.
*
* Set when events are reported after they happened, for example when a
* durable workflow reports a run that spanned several processes.
* Integrations should use it instead of the current time when present.
*/
readonly timestamp?: number;
readonly durableContext?: DurableTelemetryEventContext;
};
type BivariantCallback<EVENT> = {
bivarianceHack(event: EVENT): PromiseLike<void> | void;
}['bivarianceHack'];
type OperationStartEvent =
| GenerateTextStartEvent
| GenerateObjectStartEvent
| EmbedStartEvent
| RerankStartEvent
| GenerateSpeechStartEvent
| TranscriptionStartEvent;
type OperationEndEvent =
| GenerateTextEndEvent<ToolSet>
| GenerateObjectEndEvent<unknown>
| EmbedEndEvent
| RerankEndEvent
| GenerateSpeechEndEvent
| TranscriptionEndEvent;
export interface TelemetryDispatcher {
/**
* Runs awaited work inside a diagnostics-channel tracing span.
*/
runInTracingChannelSpan?: <T>(options: {
type: TelemetryTracingEventType;
event: unknown;
execute: () => PromiseLike<T>;
}) => Promise<T>;
/**
* Opens a tracing span context whose completion is observed separately.
* This is used by streamed operations that must preserve stream timing while
* still creating child spans with the correct parent.
*/
startTracingChannelContext?: (options: {
type: TelemetryTracingEventType;
event: unknown;
completion: PromiseLike<unknown>;
}) => TracingChannelContext | undefined;
onStart?: Callback<OperationStartEvent>;
onStepStart?: Callback<GenerateTextStepStartEvent>;
onLanguageModelCallStart?: OnLanguageModelCallStartCallback;
onLanguageModelCallEnd?: OnLanguageModelCallEndCallback;
onToolExecutionStart?: Callback<ToolExecutionStartEvent>;
onToolExecutionEnd?: Callback<ToolExecutionEndEvent>;
onStepEnd?: Callback<GenerateTextStepEndEvent>;
/** @deprecated Use `onStepEnd` instead. */
onStepFinish?: Callback<GenerateTextStepEndEvent>;
onStepError?: Callback<GenerateTextStepErrorEvent>;
onObjectStepStart?: Callback<GenerateObjectStepStartEvent>;
onObjectStepEnd?: Callback<GenerateObjectStepEndEvent>;
onEmbedStart?: Callback<EmbeddingModelCallStartEvent>;
onEmbedEnd?: Callback<EmbeddingModelCallEndEvent>;
onRerankStart?: Callback<RerankingModelCallStartEvent>;
onRerankEnd?: Callback<RerankingModelCallEndEvent>;
experimental_onDecideStart?: Callback<DecideStartEvent>;
experimental_onDecisionModelCallStart?: Callback<DecisionModelCallStartEvent>;
experimental_onDecisionModelCallEnd?: Callback<DecisionModelCallEndEvent>;
experimental_onDecideEnd?: Callback<DecideEndEvent>;
experimental_onStreamTranscriptionStart?: Callback<StreamTranscriptionStartEvent>;
experimental_onStreamTranscriptionEnd?: Callback<StreamTranscriptionEndEvent>;
onEnd?: Callback<OperationEndEvent>;
onAbort?: Callback<GenerateTextAbortEvent<ToolSet>>;
onError?: Callback<unknown>;
executeLanguageModelCall?: Telemetry['executeLanguageModelCall'];
executeTool?: Telemetry['executeTool'];
}
/**
* Implement this interface to create custom telemetry integrations.
* Methods can be sync or return a PromiseLike.
*/
export interface Telemetry {
/**
* Capture a serializable tracing identity before a durable run's model calls.
* Return undefined to preserve live per-model operations when the integration
* cannot reconstruct a run span across processes. Integrations without this
* hook receive the recorded lifecycle after completion.
*/
experimental_durable?: {
captureContext: (
event: InferTelemetryEvent<GenerateTextStartEvent>,
) =>
| DurableTelemetryContext
| undefined
| PromiseLike<DurableTelemetryContext | undefined>;
};
/**
* Called when an operation begins. Fired for text generation
* (generateText/streamText), object generation (generateObject/streamObject),
* embedding (embed/embedMany), reranking, speech generation, and
* non-streaming transcription operations.
*
* Use the `operationId` field to distinguish between operation types.
*/
onStart?: BivariantCallback<InferTelemetryEvent<OperationStartEvent>>;
/**
* Called when an individual step (single LLM invocation) begins.
* A generation may consist of multiple steps (e.g. when tool calls trigger
* follow-up LLM calls). Use this to create per-step spans or record
* step-level inputs.
*
* The event includes the step number, accumulated previous step results,
* and the messages that will be sent to the model.
*/
onStepStart?: Callback<InferTelemetryEvent<GenerateTextStepStartEvent>>;
/**
* Called immediately before the provider model call begins.
* Unlike `onStepStart`, this callback is scoped to model work only and
* excludes any later client-side tool execution.
*/
onLanguageModelCallStart?: Callback<
InferTelemetryEvent<LanguageModelCallStartEvent>
>;
/**
* Called after the model response has been normalized and parsed, but before
* any client-side tool execution begins.
*/
onLanguageModelCallEnd?: Callback<
InferTelemetryEvent<LanguageModelCallEndEvent>
>;
/**
* Called when a tool execution begins, before the tool's `execute` function
* is invoked. Use this to create tool-level spans or log tool invocations.
*/
onToolExecutionStart?: Callback<InferTelemetryEvent<ToolExecutionStartEvent>>;
/**
* Called when a tool execution completes, either successfully or with an error.
* The event uses a discriminated union on the `success` field — check
* `event.success` to determine whether `output` or `error` is available.
*
* The event includes execution time (`toolExecutionMs`) for performance tracking.
*/
onToolExecutionEnd?: Callback<InferTelemetryEvent<ToolExecutionEndEvent>>;
/**
* Called when an individual step (single LLM invocation) completes.
* The event is a `StepResult` containing the model's response, tool calls
* and results, usage statistics, finish reason, and optional request/response
* bodies.
*/
onStepEnd?: Callback<InferTelemetryEvent<GenerateTextStepEndEvent>>;
/**
* Called when an individual step (single LLM invocation) completes.
*
* @deprecated Use `onStepEnd` instead.
*/
onStepFinish?: Callback<InferTelemetryEvent<GenerateTextStepEndEvent>>;
/**
* Called when a step that started fails before it produces a step result.
* Use it to close step-level spans. The call then ends with `onError`.
*/
onStepError?: Callback<InferTelemetryEvent<GenerateTextStepErrorEvent>>;
/**
* Called when an object generation step (single LLM invocation) begins.
* For generateObject/streamObject there is always exactly one step.
*
* @deprecated
*/
onObjectStepStart?: Callback<
InferTelemetryEvent<GenerateObjectStepStartEvent>
>;
/**
* Called when an object generation step (single LLM invocation) completes,
* with the raw result before JSON parsing and schema validation.
*
* @deprecated
*/
onObjectStepEnd?: Callback<InferTelemetryEvent<GenerateObjectStepEndEvent>>;
/**
* Called when an individual embedding model call (doEmbed) begins.
* For `embed`, there is one call. For `embedMany`, there may be multiple
* calls when values are chunked.
*/
onEmbedStart?: Callback<InferTelemetryEvent<EmbeddingModelCallStartEvent>>;
/**
* Called when an individual embedding model call (doEmbed) completes.
* Contains the embeddings, usage, and any warnings from the model response.
*/
onEmbedEnd?: Callback<InferTelemetryEvent<EmbeddingModelCallEndEvent>>;
/**
* Called when an individual reranking model call (doRerank) begins.
* There is one call per `rerank` invocation.
*/
onRerankStart?: Callback<InferTelemetryEvent<RerankingModelCallStartEvent>>;
/**
* Called when an individual reranking model call (doRerank) completes.
* Contains the ranking results from the model response.
*/
onRerankEnd?: Callback<InferTelemetryEvent<RerankingModelCallEndEvent>>;
/** @deprecated Use `experimental_onDecideStart` instead. */
experimental_onEvaluateStart?: Callback<
InferTelemetryEvent<DecideStartEvent>
>;
/** @deprecated Use `experimental_onDecisionModelCallStart` instead. */
experimental_onEvaluationModelCallStart?: Callback<
InferTelemetryEvent<DecisionModelCallStartEvent>
>;
/** @deprecated Use `experimental_onDecisionModelCallEnd` instead. */
experimental_onEvaluationModelCallEnd?: Callback<
InferTelemetryEvent<DecisionModelCallEndEvent>
>;
/** @deprecated Use `experimental_onDecideEnd` instead. */
experimental_onEvaluateEnd?: Callback<InferTelemetryEvent<DecideEndEvent>>;
/** Called when an experimental decision operation begins. */
experimental_onDecideStart?: Callback<InferTelemetryEvent<DecideStartEvent>>;
/**
* Called immediately before an experimental decision model call begins.
* The logical model call includes any provider retries.
*/
experimental_onDecisionModelCallStart?: Callback<
InferTelemetryEvent<DecisionModelCallStartEvent>
>;
/**
* Called after an experimental decision model response has been validated.
* The logical model call includes any provider retries.
*/
experimental_onDecisionModelCallEnd?: Callback<
InferTelemetryEvent<DecisionModelCallEndEvent>
>;
/** Called when an experimental decision operation completes. */
experimental_onDecideEnd?: Callback<InferTelemetryEvent<DecideEndEvent>>;
/** Called when an experimental streaming transcription operation begins. */
experimental_onStreamTranscriptionStart?: Callback<
InferTelemetryEvent<StreamTranscriptionStartEvent>
>;
/** Called when an experimental streaming transcription operation completes. */
experimental_onStreamTranscriptionEnd?: Callback<
InferTelemetryEvent<StreamTranscriptionEndEvent>
>;
/**
* Called when an operation completes. Fired for text generation
* (generateText/streamText), object generation (generateObject/streamObject),
* embedding (embed/embedMany), reranking, speech generation, and
* non-streaming transcription operations.
*
* Use the event shape or `operationId` to distinguish between operation types.
*/
onEnd?: BivariantCallback<InferTelemetryEvent<OperationEndEvent>>;
/**
* Called when a streaming text generation operation is aborted before it
* completes.
*/
onAbort?: Callback<InferTelemetryEvent<GenerateTextAbortEvent<ToolSet>>>;
/**
* Called when an unrecoverable error occurs during the generation lifecycle.
* The error value is untyped — it may be an `Error` instance, an `AISDKError`,
* or any thrown value.
*
* Use this to record error details on telemetry spans and set error status.
*/
onError?: Callback<unknown>;
/**
* Optionally runs the language model call in a telemetry-integration-specific context. This enables
* auto-instrumented model provider requests to become children of the current
* model-call span.
*
* The options carry the model-call start-event content as context (the event
* fields are optional), alongside the always-present `callId` and the
* `execute` function that performs the model call.
*/
executeLanguageModelCall?: <T>(
options: Partial<InferTelemetryEvent<LanguageModelCallStartEvent>> & {
callId: string;
execute: () => PromiseLike<T>;
},
) => PromiseLike<T>;
/**
* Optionally runs the tool execute function in a telemetry-integration-specific context. This enables
* nested traces — e.g. when a tool's `execute` function calls `generateText`,
* the inner call's spans become children of the tool span.
*
* The options carry the tool-execution start-event content as context (the
* event fields are optional), alongside the always-present `callId`,
* `toolCallId`, and the `execute` function to run.
*/
executeTool?: <T>(
options: Partial<InferTelemetryEvent<ToolExecutionStartEvent>> & {
callId: string;
toolCallId: string;
execute: () => PromiseLike<T>;
},
) => PromiseLike<T>;
}