Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
963cc456 fix(ai): address otel-middleware review feedback
Critical
- C1: onUsage was a no-op in production — RUN_FINISHED closed the
iteration span before runOnUsage fired, dropping gen_ai.usage.* attrs
and the token histogram. Fix: keep the iteration span open through tool
execution and onUsage; close it on the next onConfig(beforeModel), on
onFinish, or on onError/onAbort. Token histogram is also recorded
directly from chunk.usage at RUN_FINISHED and redundantly from onUsage
so neither hook-order variant loses data.
- C3: otelMiddleware is now exported from the dedicated subpath
@tanstack/ai/middlewares/otel instead of the main middlewares barrel,
so importing toolCacheMiddleware or contentGuardMiddleware no longer
eagerly requires @opentelemetry/api.
- C4: redactor failures fail closed to the literal sentinel
"[redaction_failed]" and log a warning — raw content can no longer
leak when a PII redactor throws.
- C2: added two middleware.spec.ts scenarios that exercise otel end-to-end
through the real chat() runner (basic-text + with-tool), guarding
against the C1 regression and verifying tool-span nesting.
Important
- I1: safeCall now logs callback failures via console.warn with a label,
matching the docs' "a thrown callback becomes a log line" promise.
- I2: replaced gen_ai.completion.reason='cancelled' (not a valid semconv
attribute) with tanstack.ai.completion.reason.
- I3: onAbort now records gen_ai.client.operation.duration with
error.type='cancelled'.
- I4: docs + changeset corrected — duration histogram is per-run, token
histogram is per-iteration.
- I5: error/abort tests now assert the full onSpanEnd sequence
(iteration, tool, chat) with each span captured before .end().
- I6: tool spans still open at onFinish are swept with
tanstack.ai.tool.outcome='unknown'.
- I7: OtelSpanInfo is now a proper discriminated union; tool-only fields
narrow inside callbacks and the internal 'as OtelSpanInfo<\"tool\">'
casts are mostly gone.
- I8: iteration spans now use 'chat <model> #<iteration>' so they are
distinguishable in trace viewers.
- I9: gen_ai.response.model dropped from the duration histogram attrs
(high-cardinality).
Misc
- fake-otel: resolve parent via the explicit context arg passed to
startSpan, eliminating the ;(span as any).parent = ... test hack.
createHistogram also captures options so unit/description are assertable.
- redactException paths use 'as Exception' instead of 'as Error' so
non-Error throwables are preserved.
- OtelSpanKind kept as a deprecated alias of OtelSpanScope to avoid
shadowing OTel's built-in SpanKind.
- Public types documented with JSDoc.
- Assistant text buffer is now capped at maxContentLength (default 100k).