Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
69412d9
feat(ai): add Logger, DebugCategories, DebugConfig, DebugOption types
AlemTuzlak Apr 17, 2026
3042d41
fix(ai): relocate logger type tests to tests/ for vitest discovery
AlemTuzlak Apr 17, 2026
b9b70a0
docs(ai): add JSDoc to logger types and tighten type tests
AlemTuzlak Apr 17, 2026
5a1df04
feat(ai): add ConsoleLogger default logger implementation
AlemTuzlak Apr 17, 2026
a2afccb
feat(ai): add InternalLogger with per-category filtering and prefix
AlemTuzlak Apr 17, 2026
586e6cb
feat(ai): add resolveDebugOption normalizing DebugOption to InternalL…
AlemTuzlak Apr 17, 2026
c690d85
feat(ai): export Logger types publicly and InternalLogger via /adapte…
AlemTuzlak Apr 17, 2026
4316d26
feat(ai): thread InternalLogger through TextEngine, MiddlewareRunner,…
AlemTuzlak Apr 17, 2026
9732ce8
feat(ai-openai): emit request/provider/errors logs via InternalLogger…
AlemTuzlak Apr 17, 2026
d59ec6d
feat(ai-anthropic): emit request/provider/errors logs via InternalLog…
AlemTuzlak Apr 17, 2026
6847604
feat(ai-gemini): emit request/provider/errors logs via InternalLogger…
AlemTuzlak Apr 17, 2026
1fae55d
feat(ai-grok): emit request/provider/errors logs via InternalLogger i…
AlemTuzlak Apr 17, 2026
3ad4eba
feat(ai-groq): emit request/provider/errors logs via InternalLogger i…
AlemTuzlak Apr 17, 2026
997c4e0
feat(ai-ollama): emit request/provider/errors logs via InternalLogger…
AlemTuzlak Apr 17, 2026
bab3990
feat(ai-openrouter): emit request/provider/errors logs via InternalLo…
AlemTuzlak Apr 17, 2026
8b763f6
fix(ai): remove redundant top-level logger from StructuredOutputOptio…
AlemTuzlak Apr 17, 2026
c7d8b52
feat(ai-openai): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
0352402
feat(ai-anthropic): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
c89bb28
feat(ai-gemini): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
5ef5fdb
feat(ai-grok): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
07a4077
feat(ai-ollama): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
8a075ee
feat(ai-openrouter): emit logging events in summarize adapter
AlemTuzlak Apr 17, 2026
cf8db81
feat(ai): resolve debug option and thread InternalLogger through summ…
AlemTuzlak Apr 17, 2026
d271ffc
feat(ai-openai): emit logging events in image adapter
AlemTuzlak Apr 17, 2026
dc8f991
feat(ai-gemini): emit logging events in image adapter
AlemTuzlak Apr 17, 2026
2d649ee
feat(ai-grok): emit logging events in image adapter
AlemTuzlak Apr 17, 2026
84b5f5d
feat(ai-openrouter): emit logging events in image adapter
AlemTuzlak Apr 17, 2026
c5c8547
feat(ai-fal): emit logging events in image adapter
AlemTuzlak Apr 17, 2026
4a2eb91
feat(ai): resolve debug option and thread InternalLogger through gene…
AlemTuzlak Apr 17, 2026
cb0b476
feat(ai-openai): emit logging events in video adapter
AlemTuzlak Apr 17, 2026
edfe900
feat(ai-fal): emit logging events in video adapter
AlemTuzlak Apr 17, 2026
58aedbc
feat(ai): resolve debug option and thread InternalLogger through gene…
AlemTuzlak Apr 17, 2026
0545b34
feat(ai-openai): emit logging events in tts adapter
AlemTuzlak Apr 17, 2026
ac302c0
feat(ai-gemini): emit logging events in tts adapter
AlemTuzlak Apr 17, 2026
5a277c4
feat(ai): resolve debug option and thread InternalLogger through gene…
AlemTuzlak Apr 17, 2026
4cfa4ec
feat(ai-openai): emit logging events in transcription adapter
AlemTuzlak Apr 17, 2026
c39df4f
feat(ai): resolve debug option and thread InternalLogger through gene…
AlemTuzlak Apr 17, 2026
2dfbc08
feat(ai-openai): emit logging events in realtime adapter
AlemTuzlak Apr 17, 2026
ac32707
feat(ai-elevenlabs): emit logging events in realtime adapter
AlemTuzlak Apr 17, 2026
6f2a6f9
test(ai): add integration tests for debug logging across activities
AlemTuzlak Apr 17, 2026
a03c15b
fix(ai): remove redundant nullish coalescing on non-nullable result f…
AlemTuzlak Apr 17, 2026
979c736
test(e2e): debug logging emits expected prefixes for chat()
AlemTuzlak Apr 17, 2026
4f306ea
docs(advanced): add debug logging guide
AlemTuzlak Apr 17, 2026
419d0cb
docs(observability): cross-link to debug logging guide
AlemTuzlak Apr 17, 2026
2cf960f
docs(middleware): cross-link to debug logging guide
AlemTuzlak Apr 17, 2026
896112d
docs(nav): add Debug Logging entry to Advanced section
AlemTuzlak Apr 17, 2026
e89d45e
fix(ai): migrate remaining console.warn calls in realtime adapters to…
AlemTuzlak Apr 17, 2026
a6c68de
docs(advanced): fix stray comment syntax in debug-logging guide
AlemTuzlak Apr 17, 2026
acef29f
ci: apply automated fixes
autofix-ci[bot] Apr 17, 2026
0cef18b
fix: resolve eslint and knip failures from debug logging PR
AlemTuzlak Apr 20, 2026
4f9849e
ci: apply automated fixes
autofix-ci[bot] Apr 20, 2026
e72e7e7
fix(ai): suppress debug logs for internal devtools middleware
AlemTuzlak Apr 20, 2026
84f74b5
feat(ai): pretty-print deeply nested meta in ConsoleLogger on Node
AlemTuzlak Apr 20, 2026
5d8f436
ci: apply automated fixes
autofix-ci[bot] Apr 20, 2026
ff31140
refactor(ai): use console.dir with depth:null instead of util.inspect
AlemTuzlak Apr 20, 2026
616257a
feat(ai): prefix each debug category with an emoji marker
AlemTuzlak Apr 20, 2026
dcbde4b
ci: apply automated fixes
autofix-ci[bot] Apr 20, 2026
5b67acc
test: remove debug logging e2e spec
AlemTuzlak Apr 20, 2026
4a6033d
Merge remote-tracking branch 'origin/main' into worktree-calm-sleepin…
AlemTuzlak Apr 20, 2026
99eb7d7
chore: add changesets for debug logging
AlemTuzlak Apr 20, 2026
9463efa
ci: apply automated fixes
autofix-ci[bot] Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/debug-logging-adapters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@tanstack/ai-openai': patch
'@tanstack/ai-anthropic': patch
'@tanstack/ai-gemini': patch
'@tanstack/ai-ollama': patch
'@tanstack/ai-openrouter': patch
'@tanstack/ai-grok': patch
'@tanstack/ai-groq': patch
'@tanstack/ai-elevenlabs': patch
'@tanstack/ai-fal': patch
---

Wire each adapter's text, summarize, image, speech, transcription, and video paths through the new `InternalLogger` from `@tanstack/ai/adapter-internals`: `logger.request(...)` before each SDK call, `logger.provider(...)` for every chunk received, and `logger.errors(...)` in catch blocks. Migrates all pre-existing ad-hoc `console.*` calls in adapter catch blocks (including the OpenAI and ElevenLabs realtime adapters) onto the structured logger. No adapter factory or config-shape changes.
20 changes: 20 additions & 0 deletions .changeset/debug-logging-ai.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@tanstack/ai': minor
---

**Pluggable debug logging across every activity.** `chat`, `summarize`, `generateImage`, `generateVideo`, `generateSpeech`, and `generateTranscription` now accept a `debug?: DebugOption` that turns on structured per-category logs (`request`, `provider`, `output`, `middleware`, `tools`, `agentLoop`, `config`, `errors`).

```ts
chat({ adapter, messages, debug: true }) // all categories on
chat({ adapter, messages, debug: false }) // silent (incl. errors)
chat({ adapter, messages, debug: { middleware: false } }) // all except middleware
chat({ adapter, messages, debug: { logger: pino } }) // route to a custom logger
```

Additions:

- New `Logger` interface (`debug` / `info` / `warn` / `error`) and default `ConsoleLogger` that routes to matching `console.*` methods and prints nested `meta` via `console.dir(meta, { depth: null, colors: true })` so streamed provider payloads render in full.
- New `DebugCategories` / `DebugConfig` / `DebugOption` public types.
- New internal `@tanstack/ai/adapter-internals` subpath export exposing `InternalLogger` + `resolveDebugOption` so provider adapters can thread logging without leaking internals on the public surface.
- Each log line is prefixed with an emoji + `[tanstack-ai:<category>]` tag so categories are visually distinguishable in dense streams. Errors log unconditionally unless explicitly silenced.
- `TextEngine`, `MiddlewareRunner`, and every activity entry point thread a resolved `InternalLogger` through the pipeline — no globals, concurrent calls stay independent.
143 changes: 143 additions & 0 deletions docs/advanced/debug-logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
title: Debug Logging
id: debug-logging
order: 3
description: "Turn on structured, category-toggleable debug logging to see every chunk, middleware transform, and tool call inside TanStack AI."
keywords:
- tanstack ai
- debug
- logging
- logger
- pino
- troubleshooting
- chunks
- middleware debugging
---

# Debug Logging

You have a `chat()` that isn't behaving as expected — a missing chunk, a middleware that doesn't seem to fire, a tool call with wrong args. By the end of this guide, you'll have turned on debug logging and will see every chunk, middleware transform, and tool call flowing through your call.

## Turn it on

Add `debug: true` to any activity call:

```typescript
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

const stream = chat({
adapter: openaiText("gpt-4o"),
messages: [{ role: "user", content: "Hello" }],
debug: true,
});
```

Every internal event now prints to the console with a `[tanstack-ai:<category>]` prefix:

```
[tanstack-ai:request] activity=chat provider=openai model=gpt-4o messages=1 tools=0 stream=true
[tanstack-ai:agentLoop] run started
[tanstack-ai:provider] provider=openai type=response.output_text.delta
[tanstack-ai:output] type=TEXT_MESSAGE_CONTENT
...
```

## Narrow what's printed

Pass a `DebugConfig` object instead of `true`. Every unspecified category defaults to `true`, so toggle by setting specific flags to `false`:

```typescript
chat({
adapter: openaiText("gpt-4o"),
messages,
debug: { middleware: false }, // everything except middleware
});
```

If you want to see ONLY a specific set of categories, set the rest to `false` explicitly. Errors default to `true` — keep them on unless you really want total silence:

```typescript
chat({
adapter: openaiText("gpt-4o"),
messages,
debug: {
provider: true,
output: true,
middleware: false,
tools: false,
agentLoop: false,
config: false,
errors: true, // keep errors on — they're cheap and important
request: false,
},
});
```

## Pipe into your own logger

Pass a `Logger` implementation and all debug output flows through it instead of `console`:

```typescript
import type { Logger } from "@tanstack/ai";
import pino from "pino";

const pinoLogger = pino();
const logger: Logger = {
debug: (msg, meta) => pinoLogger.debug(meta, msg),
info: (msg, meta) => pinoLogger.info(meta, msg),
warn: (msg, meta) => pinoLogger.warn(meta, msg),
error: (msg, meta) => pinoLogger.error(meta, msg),
};

chat({
adapter: openaiText("gpt-4o"),
messages,
debug: { logger }, // all categories on, piped to pino
});
```

The default logger is exported as `ConsoleLogger` if you want to wrap it:

```typescript
import { ConsoleLogger } from "@tanstack/ai";
```

## Categories reference

| Category | Logs | Applies to |
|----------|------|------------|
| `request` | Outgoing call to a provider (model, message count, tool count) | All activities |
| `provider` | Every raw chunk/frame received from a provider SDK | Streaming activities (chat, realtime) |
| `output` | Every chunk or result yielded to the caller | All activities |
| `middleware` | Inputs and outputs around every middleware hook | `chat()` only |
| `tools` | Before/after tool call execution | `chat()` only |
| `agentLoop` | Agent-loop iterations and phase transitions | `chat()` only |
| `config` | Config transforms returned by middleware `onConfig` hooks | `chat()` only |
| `errors` | Every caught error anywhere in the pipeline | All activities |

## Errors are always logged

Errors flow through the logger unconditionally — even when you omit `debug`:

```typescript
chat({ adapter, messages }); // still prints [tanstack-ai:errors] ... on failure
```

To fully silence (including errors), set `debug: false` or `debug: { errors: false }`. Errors also always reach the caller via thrown exceptions or `RUN_ERROR` stream chunks — the logger is additive, not the only surface.

## Non-chat activities

The same `debug` option works on every activity:

```typescript
summarize({ adapter, text, debug: true });
generateImage({ adapter, prompt: "a cat", debug: { logger } });
generateSpeech({ adapter, text, debug: { request: true } });
```

The chat-only categories (`middleware`, `tools`, `agentLoop`, `config`) simply never fire for these activities because those concepts don't exist in their pipelines.

## Related

If you're building middleware and want to see chunks flow through it, `debug: { middleware: true }` is faster than writing a logging middleware. See [Middleware](./middleware) for writing your own middleware, or [Observability](./observability) for the programmatic event client.
2 changes: 1 addition & 1 deletion docs/advanced/extend-adapter.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Extend Adapter
id: extend-adapter
order: 7
order: 8
description: "Extend TanStack AI adapter factories with custom model IDs and fine-tuned models while keeping full type safety for input modalities and provider options."
keywords:
- tanstack ai
Expand Down
3 changes: 3 additions & 0 deletions docs/advanced/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const stream = chat({
});
```

> **Just want to see chunks flowing through your middleware during development?**
> Use `debug: { middleware: true }` on your `chat()` call — no custom middleware required. See [Debug Logging](./debug-logging).

## Lifecycle Overview

Every `chat()` invocation follows a predictable lifecycle. Middleware hooks fire at specific phases:
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/multimodal-content.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Multimodal Content
id: multimodal-content
order: 3
order: 4
description: "Send images, audio, video, and documents alongside text in TanStack AI messages with typed ContentPart primitives for multimodal models."
keywords:
- tanstack ai
Expand Down
3 changes: 3 additions & 0 deletions docs/advanced/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ The `@tanstack/ai` package offers you an event client for observability and debu
It's a fully type-safe decoupled event-driven system that emits events whenever they are internally
triggered and you can subscribe to those events for observability.

> **Looking for quick diagnostic console output instead of a programmatic event stream?**
> See [Debug Logging](./debug-logging) for turning on category-toggleable logging across every adapter and middleware hook.

Because the same event client is used for both the TanStack Devtools system and observability locally it will work
by subscribing to the event bus and emitting events to/from the event bus into the listeners by default. If you
want to subscribe to events in production as well you need to pass in a third argument to the `on` function,
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/per-model-type-safety.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Per-Model Type Safety
id: per-model-type-safety
order: 4
order: 5
description: "TanStack AI narrows modelOptions and content types to the specific model you select, enforcing capabilities at compile time."
keywords:
- tanstack ai
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/runtime-adapter-switching.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Runtime Adapter Switching
id: runtime-adapter-switching
order: 5
order: 6
description: "Let users switch between LLM providers at runtime in TanStack AI while keeping full TypeScript type safety for each adapter's model options."
keywords:
- tanstack ai
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/tree-shaking.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Tree-Shaking
id: tree-shaking
order: 6
order: 7
description: "TanStack AI's tree-shakeable architecture — import only the activities and adapters you use for minimal bundle size across chat, image, and speech."
keywords:
- tanstack ai
Expand Down
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@
"label": "Middleware",
"to": "advanced/middleware"
},
{
"label": "Debug Logging",
"to": "advanced/debug-logging"
},
{
"label": "Observability",
"to": "advanced/observability"
Expand Down
Loading
Loading