@tanstack/ai
Version:
Core TanStack AI library - Open source AI SDK
76 lines (75 loc) • 3.34 kB
TypeScript
import { AttributeValue, Meter, Span, SpanOptions, Tracer } from '@opentelemetry/api';
import { ChatMiddleware, ChatMiddlewareContext } from '../activities/chat/middleware/types.js';
/**
* Scope (role) of an OTel span emitted by this middleware.
*
* - `chat` — the root span for a single `chat()` call
* - `iteration` — one per agent-loop iteration (one model call)
* - `tool` — one per tool execution inside an iteration
*/
export type OtelSpanScope = 'chat' | 'iteration' | 'tool';
/**
* Alias retained for backwards compatibility. Prefer {@link OtelSpanScope}.
*
* @deprecated Use `OtelSpanScope` instead — the name shadows OTel's built-in
* `SpanKind` which is also imported by integrations of this middleware.
*/
export type OtelSpanKind = OtelSpanScope;
/**
* Span metadata passed to `spanNameFormatter`, `attributeEnricher`,
* `onBeforeSpanStart`, and `onSpanEnd`. Discriminated by `kind` so that
* tool-only fields narrow automatically inside callback bodies.
*/
export type OtelSpanInfo<TScope extends OtelSpanScope = OtelSpanScope> = TScope extends 'chat' ? {
kind: 'chat';
ctx: ChatMiddlewareContext;
} : TScope extends 'iteration' ? {
kind: 'iteration';
ctx: ChatMiddlewareContext;
iteration: number;
} : TScope extends 'tool' ? {
kind: 'tool';
ctx: ChatMiddlewareContext;
iteration: number;
toolName: string;
toolCallId: string;
} : never;
export interface OtelMiddlewareOptions {
/** OTel `Tracer` used to start root, iteration, and tool spans. */
tracer: Tracer;
/**
* Optional OTel `Meter`. When provided, the middleware records
* `gen_ai.client.operation.duration` and `gen_ai.client.token.usage`
* histograms. Omit to disable metrics without disabling tracing.
*/
meter?: Meter;
/**
* When `true`, prompt and completion content is attached to iteration spans
* as `gen_ai.*.message` / `gen_ai.choice` events. Defaults to `false` so
* that PII never lands on a span by accident.
*/
captureContent?: boolean;
/**
* Invoked on every captured content string before it lands on a span.
* Return a redacted version. If this function throws, the middleware emits
* the literal sentinel `"[redaction_failed]"` instead of the original text
* — it never falls back to raw content.
*/
redact?: (text: string) => string;
/**
* Maximum characters kept in the per-iteration assistant text buffer used
* to emit `gen_ai.choice` events. Extra characters are truncated with a
* trailing `"…"` marker. Defaults to 100 000. Set to `0` to disable the
* cap. Exporters typically truncate long attribute values anyway.
*/
maxContentLength?: number;
/** Override the default span name for each `kind`. */
spanNameFormatter?: (info: OtelSpanInfo) => string;
/** Add extra attributes to each span. */
attributeEnricher?: (info: OtelSpanInfo) => Record<string, AttributeValue>;
/** Mutate `SpanOptions` immediately before `tracer.startSpan(...)`. */
onBeforeSpanStart?: (info: OtelSpanInfo, options: SpanOptions) => SpanOptions;
/** Fires just before every `span.end()`. */
onSpanEnd?: (info: OtelSpanInfo, span: Span) => void;
}
export declare function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware;