eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
175 lines (174 loc) • 7.73 kB
TypeScript
/**
* Instrumentation authoring helpers for `agent/instrumentation.ts` and, with
* `experimental.instrumentationProviders` on, `agent/instrumentation/`.
*/
import type { ModelMessage, SystemModelMessage } from "ai";
import type { SessionAuthContext, SessionParent } from "#channel/types.js";
import type { InstrumentationChannel } from "#public/channels/index.js";
import { PROVIDER, type ProviderDefinition, type ProviderSetupContext } from "#public/instrumentation/provider.js";
import type { JsonObject } from "#shared/json.js";
export * from "#public/instrumentation/provider.js";
export { isChannel, type InstrumentationChannel, type InstrumentationChannelForChannel, type InstrumentationChannelForKind, type InstrumentationChannelKind, type InstrumentationChannelMetadata, } from "#public/channels/index.js";
/**
* Context passed to the {@link InstrumentationDefinition.setup} callback.
*
* The same context both layouts receive. Keeping one type is what gives
* {@link defineInstrumentation}'s union a contextual signature for `setup`;
* two divergent ones would leave every authored `setup(context)` parameter an
* implicit `any`.
*/
export interface InstrumentationSetupContext extends ProviderSetupContext {
}
/**
* User-authored runtime context values attached to AI SDK telemetry spans.
*
* Keys beginning with `eve.` are reserved for framework-owned context
* and are ignored when returned from authored instrumentation.
*/
export type InstrumentationRuntimeContext = JsonObject;
/**
* Session lineage and auth snapshot exposed to instrumentation callbacks.
*
* `auth.current` is the caller principal for this turn (null when the
* request carried no credentials). `auth.initiator` is the principal that
* started the root session, falling back to `auth.current` for root
* sessions. `parent` is present only for delegated subagent sessions.
*/
export interface InstrumentationSession {
readonly auth: {
readonly current: SessionAuthContext | null;
readonly initiator: SessionAuthContext | null;
};
readonly id: string;
readonly parent?: SessionParent;
}
/**
* Identifies the turn in progress when an instrumentation event fires.
* `id` is the turn identifier; `sequence` is its zero-based position
* within the session.
*/
export interface InstrumentationTurn {
readonly id: string;
readonly sequence: number;
}
/**
* The step (model-call attempt) in progress for an instrumentation event.
* `index` is the zero-based step index within the current turn.
*/
export interface InstrumentationStep {
readonly index: number;
}
/**
* Final model input assembled for one model-call attempt, snapshotted for
* instrumentation. `instructions` is the resolved system prompt (a string,
* a system message with provider options, or undefined when there is none).
* `messages` is the non-system conversation passed to the model.
*/
export interface InstrumentationModelInput {
readonly instructions: string | SystemModelMessage | undefined;
readonly messages: readonly ModelMessage[];
}
/**
* Input passed to `events["step.started"]` and to a provider's
* `runtimeContext` resolver. eve builds it after assembling the final model
* input for this attempt and before constructing the AI SDK model call.
*/
export interface InstrumentationStepStartedEventInput {
readonly channel: InstrumentationChannel;
readonly modelInput: InstrumentationModelInput;
readonly session: InstrumentationSession;
readonly step: InstrumentationStep;
readonly turn: InstrumentationTurn;
}
/**
* Input passed to a provider's `runtimeContext` resolver. Same shape as
* {@link InstrumentationStepStartedEventInput}: channel, session, model input,
* step, and turn coordinates.
*/
export type InstrumentationRuntimeContextInput = InstrumentationStepStartedEventInput;
/**
* Result of a `step.started` callback. eve merges `runtimeContext` into the
* AI SDK telemetry span; child spans inherit the values. Keys beginning with
* `eve.` and non-JSON-serializable values are dropped. Return `undefined` to
* contribute no context.
*/
export interface InstrumentationStepStartedEventResult {
/**
* Additional runtime context merged into AI SDK telemetry spans.
*/
readonly runtimeContext: InstrumentationRuntimeContext;
}
/**
* Event hooks accepted by {@link defineInstrumentation}.
*/
export interface InstrumentationEvents {
/**
* Resolve per-attempt runtime context before the model call. The AI SDK
* child spans inherit the returned values.
*/
readonly "step.started"?: (input: InstrumentationStepStartedEventInput) => InstrumentationStepStartedEventResult | undefined;
}
/**
* Authored instrumentation settings accepted by `defineInstrumentation`.
*
* The presence of a `defineInstrumentation` export implicitly enables
* telemetry. There is no separate `isEnabled` toggle.
*/
export interface InstrumentationDefinition {
/**
* Override the function identifier attached to telemetry spans
* (`ai.telemetry.functionId`). Defaults to the agent name; omitted when
* neither is set.
*/
readonly functionId?: string;
/**
* Instrumentation event hooks.
*/
readonly events?: InstrumentationEvents;
/**
* Whether to record full model inputs in telemetry spans. Defaults to
* `false`. Set `true` only when the destination is approved to receive
* input content.
*/
readonly recordInputs?: boolean;
/**
* Whether to record full model outputs in telemetry spans. Defaults to
* `false`. Set `true` only when the destination is approved to receive
* output content.
*/
readonly recordOutputs?: boolean;
/**
* Whether to emit an eve-owned HTTP `SERVER` span around each channel
* request. In the authored hierarchy, this span parents the turn trace. In
* the provider layout, a one-to-one activation remains a separate trace
* root and links to this span; when disabled, it links to any already-active
* upstream request or function span instead. Defaults to `false`.
*/
readonly traceChannelRequests?: boolean;
/**
* Setup callback invoked at server startup, before the first request. Use it
* to call `registerOTel` or other OTel provider setup; `context.agentName`
* comes from `defineAgent`. A returned promise is awaited.
*/
readonly setup?: (context: InstrumentationSetupContext) => void | PromiseLike<void>;
}
/**
* Declares instrumentation, in either of eve's two layouts.
*
* Export the result as the default export of `agent/instrumentation.ts`, or —
* with `experimental.instrumentationProviders` on — of one file under
* `agent/instrumentation/`. The layout decides how eve reads the value; the two
* are mutually exclusive builds, so only one can apply. `setup` runs at server
* startup, not during this call.
*
* The parameter is a union because a provider and a legacy config overlap on
* `events` and `setup`, so no value-level check separates them. One consequence
* is that excess-property checking is weaker here than it was against the
* config shape alone, and a misspelled key can reach `eve build` rather than
* failing at `tsc`.
*/
export declare function defineInstrumentation<const TDefinition extends InstrumentationDefinition | ProviderDefinition>(definition: TDefinition): InstrumentationDeclaration<TDefinition>;
/** The branded result of {@link defineInstrumentation}. */
export type InstrumentationDeclaration<TDefinition extends InstrumentationDefinition | ProviderDefinition = InstrumentationDefinition | ProviderDefinition> = TDefinition & {
readonly [PROVIDER]: true;
};