@tanstack/ai 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/esm/activities/chat/adapter.d.ts +6 -1
  2. package/dist/esm/activities/chat/adapter.js.map +1 -1
  3. package/dist/esm/activities/chat/index.d.ts +8 -0
  4. package/dist/esm/activities/chat/index.js +78 -17
  5. package/dist/esm/activities/chat/index.js.map +1 -1
  6. package/dist/esm/activities/chat/middleware/compose.d.ts +3 -1
  7. package/dist/esm/activities/chat/middleware/compose.js +79 -1
  8. package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
  9. package/dist/esm/activities/error-payload.d.ts +12 -0
  10. package/dist/esm/activities/error-payload.js +25 -0
  11. package/dist/esm/activities/error-payload.js.map +1 -0
  12. package/dist/esm/activities/generateAudio/adapter.d.ts +62 -0
  13. package/dist/esm/activities/generateAudio/adapter.js +14 -0
  14. package/dist/esm/activities/generateAudio/adapter.js.map +1 -0
  15. package/dist/esm/activities/generateAudio/index.d.ts +74 -0
  16. package/dist/esm/activities/generateAudio/index.js +80 -0
  17. package/dist/esm/activities/generateAudio/index.js.map +1 -0
  18. package/dist/esm/activities/generateImage/adapter.d.ts +1 -1
  19. package/dist/esm/activities/generateImage/adapter.js +1 -1
  20. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  21. package/dist/esm/activities/generateImage/index.d.ts +7 -0
  22. package/dist/esm/activities/generateImage/index.js +19 -3
  23. package/dist/esm/activities/generateImage/index.js.map +1 -1
  24. package/dist/esm/activities/generateSpeech/adapter.d.ts +1 -1
  25. package/dist/esm/activities/generateSpeech/adapter.js +1 -1
  26. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
  27. package/dist/esm/activities/generateSpeech/index.d.ts +10 -3
  28. package/dist/esm/activities/generateSpeech/index.js +32 -3
  29. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  30. package/dist/esm/activities/generateTranscription/adapter.d.ts +1 -1
  31. package/dist/esm/activities/generateTranscription/adapter.js +1 -1
  32. package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
  33. package/dist/esm/activities/generateTranscription/index.d.ts +10 -3
  34. package/dist/esm/activities/generateTranscription/index.js +43 -13
  35. package/dist/esm/activities/generateTranscription/index.js.map +1 -1
  36. package/dist/esm/activities/generateVideo/index.d.ts +7 -0
  37. package/dist/esm/activities/generateVideo/index.js +55 -13
  38. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  39. package/dist/esm/activities/index.d.ts +5 -2
  40. package/dist/esm/activities/index.js +11 -6
  41. package/dist/esm/activities/index.js.map +1 -1
  42. package/dist/esm/activities/stream-generation-result.js +5 -6
  43. package/dist/esm/activities/stream-generation-result.js.map +1 -1
  44. package/dist/esm/activities/summarize/index.d.ts +7 -0
  45. package/dist/esm/activities/summarize/index.js +54 -19
  46. package/dist/esm/activities/summarize/index.js.map +1 -1
  47. package/dist/esm/adapter-internals.d.ts +4 -0
  48. package/dist/esm/adapter-internals.js +9 -0
  49. package/dist/esm/adapter-internals.js.map +1 -0
  50. package/dist/esm/index.d.ts +5 -2
  51. package/dist/esm/index.js +5 -0
  52. package/dist/esm/index.js.map +1 -1
  53. package/dist/esm/logger/console-logger.d.ts +11 -0
  54. package/dist/esm/logger/console-logger.js +27 -0
  55. package/dist/esm/logger/console-logger.js.map +1 -0
  56. package/dist/esm/logger/internal-logger.d.ts +33 -0
  57. package/dist/esm/logger/internal-logger.js +69 -0
  58. package/dist/esm/logger/internal-logger.js.map +1 -0
  59. package/dist/esm/logger/resolve.d.ts +14 -0
  60. package/dist/esm/logger/resolve.js +54 -0
  61. package/dist/esm/logger/resolve.js.map +1 -0
  62. package/dist/esm/logger/types.d.ts +75 -0
  63. package/dist/esm/stream-to-response.js +3 -8
  64. package/dist/esm/stream-to-response.js.map +1 -1
  65. package/dist/esm/types.d.ts +97 -6
  66. package/package.json +6 -2
  67. package/skills/ai-core/SKILL.md +5 -3
  68. package/skills/ai-core/debug-logging/SKILL.md +263 -0
  69. package/skills/ai-core/media-generation/SKILL.md +154 -10
  70. package/src/activities/chat/adapter.ts +6 -1
  71. package/src/activities/chat/index.ts +104 -22
  72. package/src/activities/chat/middleware/compose.ts +84 -1
  73. package/src/activities/error-payload.ts +35 -0
  74. package/src/activities/generateAudio/adapter.ts +89 -0
  75. package/src/activities/generateAudio/index.ts +224 -0
  76. package/src/activities/generateImage/adapter.ts +1 -1
  77. package/src/activities/generateImage/index.ts +29 -3
  78. package/src/activities/generateSpeech/adapter.ts +1 -1
  79. package/src/activities/generateSpeech/index.ts +51 -9
  80. package/src/activities/generateTranscription/adapter.ts +1 -1
  81. package/src/activities/generateTranscription/index.ts +72 -17
  82. package/src/activities/generateVideo/index.ts +72 -13
  83. package/src/activities/index.ts +22 -0
  84. package/src/activities/stream-generation-result.ts +6 -7
  85. package/src/activities/summarize/index.ts +66 -20
  86. package/src/adapter-internals.ts +8 -0
  87. package/src/index.ts +13 -0
  88. package/src/logger/console-logger.ts +49 -0
  89. package/src/logger/internal-logger.ts +107 -0
  90. package/src/logger/resolve.ts +72 -0
  91. package/src/logger/types.ts +78 -0
  92. package/src/stream-to-response.ts +5 -10
  93. package/src/types.ts +110 -5
@@ -7,6 +7,9 @@
7
7
 
8
8
  import { aiEventClient } from '@tanstack/ai-event-client'
9
9
  import { streamGenerationResult } from '../stream-generation-result.js'
10
+ import { resolveDebugOption } from '../../logger/resolve'
11
+ import type { InternalLogger } from '../../logger/internal-logger'
12
+ import type { DebugOption } from '../../logger/types'
10
13
  import type { TranscriptionAdapter } from './adapter'
11
14
  import type { StreamChunk, TranscriptionResult } from '../../types'
12
15
 
@@ -41,7 +44,10 @@ export type TranscriptionProviderOptions<TAdapter> =
41
44
  * @template TStream - Whether to stream the output
42
45
  */
43
46
  export interface TranscriptionActivityOptions<
44
- TAdapter extends TranscriptionAdapter<string, object>,
47
+ TAdapter extends TranscriptionAdapter<
48
+ string,
49
+ TranscriptionProviderOptions<TAdapter>
50
+ >,
45
51
  TStream extends boolean = false,
46
52
  > {
47
53
  /** The transcription adapter to use (must be created with a model) */
@@ -64,6 +70,12 @@ export interface TranscriptionActivityOptions<
64
70
  * @default false
65
71
  */
66
72
  stream?: TStream
73
+ /**
74
+ * Enable debug logging. Pass `true` to enable all categories, `false` to
75
+ * silence everything including errors, or a `DebugConfig` object for granular
76
+ * control and/or a custom `Logger`.
77
+ */
78
+ debug?: DebugOption
67
79
  }
68
80
 
69
81
  // ===========================
@@ -132,7 +144,10 @@ function createId(prefix: string): string {
132
144
  * ```
133
145
  */
134
146
  export function generateTranscription<
135
- TAdapter extends TranscriptionAdapter<string, object>,
147
+ TAdapter extends TranscriptionAdapter<
148
+ string,
149
+ TranscriptionProviderOptions<TAdapter>
150
+ >,
136
151
  TStream extends boolean = false,
137
152
  >(
138
153
  options: TranscriptionActivityOptions<TAdapter, TStream>,
@@ -152,14 +167,22 @@ export function generateTranscription<
152
167
  * Run non-streaming transcription
153
168
  */
154
169
  async function runGenerateTranscription<
155
- TAdapter extends TranscriptionAdapter<string, object>,
170
+ TAdapter extends TranscriptionAdapter<
171
+ string,
172
+ TranscriptionProviderOptions<TAdapter>
173
+ >,
156
174
  >(
157
175
  options: TranscriptionActivityOptions<TAdapter, boolean>,
158
176
  ): Promise<TranscriptionResult> {
159
- const { adapter, stream: _stream, ...rest } = options
177
+ const { adapter, stream: _stream, debug: _debug, ...rest } = options
160
178
  const model = adapter.model
161
179
  const requestId = createId('transcription')
162
180
  const startTime = Date.now()
181
+ const logger: InternalLogger = resolveDebugOption(options.debug)
182
+ const providerName =
183
+ (adapter as { name?: string; provider?: string }).provider ??
184
+ (adapter as { name?: string }).name ??
185
+ 'unknown'
163
186
 
164
187
  aiEventClient.emit('transcription:request:started', {
165
188
  requestId,
@@ -172,21 +195,50 @@ async function runGenerateTranscription<
172
195
  timestamp: startTime,
173
196
  })
174
197
 
175
- const result = await adapter.transcribe({ ...rest, model })
176
- const duration = Date.now() - startTime
177
-
178
- aiEventClient.emit('transcription:request:completed', {
179
- requestId,
180
- provider: adapter.name,
198
+ logger.request(`activity=generateTranscription provider=${providerName}`, {
199
+ provider: providerName,
181
200
  model,
182
- text: result.text,
183
- language: result.language,
184
- duration,
185
- modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
186
- timestamp: Date.now(),
187
201
  })
188
202
 
189
- return result
203
+ try {
204
+ const result = await adapter.transcribe({ ...rest, model, logger })
205
+ const duration = Date.now() - startTime
206
+
207
+ aiEventClient.emit('transcription:request:completed', {
208
+ requestId,
209
+ provider: adapter.name,
210
+ model,
211
+ text: result.text,
212
+ language: result.language,
213
+ duration,
214
+ modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
215
+ timestamp: Date.now(),
216
+ })
217
+
218
+ logger.output(
219
+ `activity=generateTranscription length=${result.text.length}`,
220
+ { hasText: !!result.text },
221
+ )
222
+
223
+ return result
224
+ } catch (error) {
225
+ const duration = Date.now() - startTime
226
+ const err = error as Error
227
+ aiEventClient.emit('transcription:request:error', {
228
+ requestId,
229
+ provider: adapter.name,
230
+ model,
231
+ error: { message: err.message, name: err.name },
232
+ duration,
233
+ modelOptions: rest.modelOptions as Record<string, unknown> | undefined,
234
+ timestamp: Date.now(),
235
+ })
236
+ logger.errors('generateTranscription activity failed', {
237
+ error,
238
+ source: 'generateTranscription',
239
+ })
240
+ throw error
241
+ }
190
242
  }
191
243
 
192
244
  // ===========================
@@ -197,7 +249,10 @@ async function runGenerateTranscription<
197
249
  * Create typed options for the generateTranscription() function without executing.
198
250
  */
199
251
  export function createTranscriptionOptions<
200
- TAdapter extends TranscriptionAdapter<string, object>,
252
+ TAdapter extends TranscriptionAdapter<
253
+ string,
254
+ TranscriptionProviderOptions<TAdapter>
255
+ >,
201
256
  TStream extends boolean = false,
202
257
  >(
203
258
  options: TranscriptionActivityOptions<TAdapter, TStream>,
@@ -8,6 +8,10 @@
8
8
  */
9
9
 
10
10
  import { aiEventClient } from '@tanstack/ai-event-client'
11
+ import { toRunErrorPayload } from '../error-payload'
12
+ import { resolveDebugOption } from '../../logger/resolve'
13
+ import type { InternalLogger } from '../../logger/internal-logger'
14
+ import type { DebugOption } from '../../logger/types'
11
15
  import type { VideoAdapter } from './adapter'
12
16
  import type {
13
17
  StreamChunk,
@@ -100,6 +104,12 @@ export type VideoCreateOptions<
100
104
  maxDuration?: number
101
105
  /** Custom run ID (stream mode only) */
102
106
  runId?: string
107
+ /**
108
+ * Enable debug logging. Pass `true` to enable all categories, `false` to
109
+ * silence everything including errors, or a `DebugConfig` object for granular
110
+ * control and/or a custom `Logger`.
111
+ */
112
+ debug?: DebugOption
103
113
  } & ({} extends VideoProviderOptions<TAdapter>
104
114
  ? {
105
115
  /** Provider-specific options for video generation */ modelOptions?: VideoProviderOptions<TAdapter>
@@ -241,14 +251,38 @@ async function runCreateVideoJob<
241
251
  >(options: VideoCreateOptions<TAdapter, boolean>): Promise<VideoJobResult> {
242
252
  const { adapter, prompt, size, duration, modelOptions } = options
243
253
  const model = adapter.model
244
-
245
- return adapter.createVideoJob({
254
+ const logger: InternalLogger = resolveDebugOption(options.debug)
255
+ const providerName =
256
+ (adapter as { name?: string; provider?: string }).provider ??
257
+ (adapter as { name?: string }).name ??
258
+ 'unknown'
259
+
260
+ logger.request(`activity=generateVideo provider=${providerName}`, {
261
+ provider: providerName,
246
262
  model,
247
- prompt,
248
- size,
249
- duration,
250
- modelOptions,
251
263
  })
264
+
265
+ try {
266
+ const result = await adapter.createVideoJob({
267
+ model,
268
+ prompt,
269
+ size,
270
+ duration,
271
+ modelOptions,
272
+ logger,
273
+ })
274
+ logger.output(`activity=generateVideo jobId=${result.jobId}`, {
275
+ jobId: result.jobId,
276
+ model: result.model,
277
+ })
278
+ return result
279
+ } catch (error) {
280
+ logger.errors('generateVideo activity failed', {
281
+ error,
282
+ source: 'generateVideo',
283
+ })
284
+ throw error
285
+ }
252
286
  }
253
287
 
254
288
  function sleep(ms: number): Promise<void> {
@@ -267,6 +301,11 @@ async function* runStreamingVideoGeneration<
267
301
  const runId = options.runId ?? createId('run')
268
302
  const pollingInterval = options.pollingInterval ?? 2000
269
303
  const maxDuration = options.maxDuration ?? 600_000
304
+ const logger: InternalLogger = resolveDebugOption(options.debug)
305
+ const providerName =
306
+ (adapter as { name?: string; provider?: string }).provider ??
307
+ (adapter as { name?: string }).name ??
308
+ 'unknown'
270
309
 
271
310
  const threadId = createId('thread')
272
311
 
@@ -277,6 +316,14 @@ async function* runStreamingVideoGeneration<
277
316
  timestamp: Date.now(),
278
317
  } as StreamChunk
279
318
 
319
+ logger.request(
320
+ `activity=generateVideo provider=${providerName} stream=true`,
321
+ {
322
+ provider: providerName,
323
+ model,
324
+ },
325
+ )
326
+
280
327
  try {
281
328
  // Create the video generation job
282
329
  const jobResult = await adapter.createVideoJob({
@@ -285,6 +332,7 @@ async function* runStreamingVideoGeneration<
285
332
  size,
286
333
  duration,
287
334
  modelOptions,
335
+ logger,
288
336
  })
289
337
 
290
338
  yield {
@@ -316,6 +364,14 @@ async function* runStreamingVideoGeneration<
316
364
  if (statusResult.status === 'completed') {
317
365
  const urlResult = await adapter.getVideoUrl(jobResult.jobId)
318
366
 
367
+ logger.output(
368
+ `activity=generateVideo jobId=${jobResult.jobId} status=completed`,
369
+ {
370
+ jobId: jobResult.jobId,
371
+ url: urlResult.url,
372
+ },
373
+ )
374
+
319
375
  yield {
320
376
  type: 'CUSTOM',
321
377
  name: 'generation:result',
@@ -344,17 +400,20 @@ async function* runStreamingVideoGeneration<
344
400
  }
345
401
 
346
402
  throw new Error('Video generation timed out')
347
- } catch (error: any) {
403
+ } catch (error: unknown) {
404
+ const payload = toRunErrorPayload(error, 'Video generation failed')
405
+ logger.errors('generateVideo activity failed', {
406
+ message: payload.message,
407
+ code: payload.code,
408
+ source: 'generateVideo',
409
+ })
348
410
  yield {
349
411
  type: 'RUN_ERROR',
350
412
  runId,
351
413
  threadId,
352
- message: error.message || 'Video generation failed',
353
- code: error.code,
354
- error: {
355
- message: error.message || 'Video generation failed',
356
- code: error.code,
357
- },
414
+ message: payload.message,
415
+ code: payload.code,
416
+ error: payload,
358
417
  timestamp: Date.now(),
359
418
  } as StreamChunk
360
419
  }
@@ -17,6 +17,7 @@
17
17
  import type { AnyTextAdapter } from './chat/adapter'
18
18
  import type { AnySummarizeAdapter } from './summarize/adapter'
19
19
  import type { AnyImageAdapter } from './generateImage/adapter'
20
+ import type { AnyAudioAdapter } from './generateAudio/adapter'
20
21
  import type { AnyVideoAdapter } from './generateVideo/adapter'
21
22
  import type { AnyTTSAdapter } from './generateSpeech/adapter'
22
23
  import type { AnyTranscriptionAdapter } from './generateTranscription/adapter'
@@ -80,6 +81,25 @@ export {
80
81
  type AnyImageAdapter,
81
82
  } from './generateImage/adapter'
82
83
 
84
+ // ===========================
85
+ // Audio Activity
86
+ // ===========================
87
+
88
+ export {
89
+ kind as audioKind,
90
+ generateAudio,
91
+ type AudioActivityOptions,
92
+ type AudioActivityResult,
93
+ type AudioProviderOptions,
94
+ } from './generateAudio/index'
95
+
96
+ export {
97
+ BaseAudioAdapter,
98
+ type AudioAdapter,
99
+ type AudioAdapterConfig,
100
+ type AnyAudioAdapter,
101
+ } from './generateAudio/adapter'
102
+
83
103
  // ===========================
84
104
  // Video Activity (Experimental)
85
105
  // ===========================
@@ -150,6 +170,7 @@ export type AIAdapter =
150
170
  | AnyTextAdapter
151
171
  | AnySummarizeAdapter
152
172
  | AnyImageAdapter
173
+ | AnyAudioAdapter
153
174
  | AnyVideoAdapter
154
175
  | AnyTTSAdapter
155
176
  | AnyTranscriptionAdapter
@@ -159,6 +180,7 @@ export type AdapterKind =
159
180
  | 'text'
160
181
  | 'summarize'
161
182
  | 'image'
183
+ | 'audio'
162
184
  | 'video'
163
185
  | 'tts'
164
186
  | 'transcription'
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { EventType } from '@ag-ui/core'
8
+ import { toRunErrorPayload } from './error-payload'
8
9
  import type { StreamChunk } from '../types'
9
10
 
10
11
  function createId(prefix: string): string {
@@ -52,18 +53,16 @@ export async function* streamGenerationResult<TResult>(
52
53
  finishReason: 'stop',
53
54
  timestamp: Date.now(),
54
55
  } as StreamChunk
55
- } catch (error: any) {
56
+ } catch (error: unknown) {
57
+ const payload = toRunErrorPayload(error, 'Generation failed')
56
58
  yield {
57
59
  type: EventType.RUN_ERROR,
58
60
  runId,
59
61
  threadId,
60
- message: error.message || 'Generation failed',
61
- code: error.code,
62
+ message: payload.message,
63
+ code: payload.code,
62
64
  // Deprecated nested form for backward compatibility
63
- error: {
64
- message: error.message || 'Generation failed',
65
- code: error.code,
66
- },
65
+ error: payload,
67
66
  timestamp: Date.now(),
68
67
  } as StreamChunk
69
68
  }
@@ -7,6 +7,9 @@
7
7
 
8
8
  import { aiEventClient } from '@tanstack/ai-event-client'
9
9
  import { streamGenerationResult } from '../stream-generation-result.js'
10
+ import { resolveDebugOption } from '../../logger/resolve'
11
+ import type { InternalLogger } from '../../logger/internal-logger'
12
+ import type { DebugOption } from '../../logger/types'
10
13
  import type { SummarizeAdapter } from './adapter'
11
14
  import type {
12
15
  StreamChunk,
@@ -66,6 +69,12 @@ export interface SummarizeActivityOptions<
66
69
  * @default false
67
70
  */
68
71
  stream?: TStream
72
+ /**
73
+ * Enable debug logging. Pass `true` to enable all categories, `false` to
74
+ * silence everything including errors, or a `DebugConfig` object for granular
75
+ * control and/or a custom `Logger`.
76
+ */
77
+ debug?: DebugOption
69
78
  }
70
79
 
71
80
  // ===========================
@@ -180,6 +189,7 @@ async function runSummarize(
180
189
  const requestId = createId('summarize')
181
190
  const inputLength = text.length
182
191
  const startTime = Date.now()
192
+ const logger: InternalLogger = resolveDebugOption(options.debug)
183
193
 
184
194
  aiEventClient.emit('summarize:request:started', {
185
195
  requestId,
@@ -189,30 +199,50 @@ async function runSummarize(
189
199
  timestamp: startTime,
190
200
  })
191
201
 
202
+ logger.request(`activity=summarize provider=${adapter.name}`, {
203
+ provider: adapter.name,
204
+ model,
205
+ inputLength,
206
+ })
207
+
192
208
  const summarizeOptions: SummarizationOptions = {
193
209
  model,
194
210
  text,
195
211
  maxLength,
196
212
  style,
197
213
  focus,
214
+ logger,
198
215
  }
199
216
 
200
- const result = await adapter.summarize(summarizeOptions)
217
+ try {
218
+ const result = await adapter.summarize(summarizeOptions)
201
219
 
202
- const duration = Date.now() - startTime
203
- const outputLength = result.summary.length
220
+ const duration = Date.now() - startTime
221
+ const outputLength = result.summary.length
204
222
 
205
- aiEventClient.emit('summarize:request:completed', {
206
- requestId,
207
- provider: adapter.name,
208
- model,
209
- inputLength,
210
- outputLength,
211
- duration,
212
- timestamp: Date.now(),
213
- })
223
+ aiEventClient.emit('summarize:request:completed', {
224
+ requestId,
225
+ provider: adapter.name,
226
+ model,
227
+ inputLength,
228
+ outputLength,
229
+ duration,
230
+ timestamp: Date.now(),
231
+ })
232
+
233
+ logger.output(`activity=summarize length=${outputLength}`, {
234
+ hasSummary: !!result.summary,
235
+ outputLength,
236
+ })
214
237
 
215
- return result
238
+ return result
239
+ } catch (error) {
240
+ logger.errors('summarize activity failed', {
241
+ error,
242
+ source: 'summarize',
243
+ })
244
+ throw error
245
+ }
216
246
  }
217
247
 
218
248
  /**
@@ -225,6 +255,13 @@ async function* runStreamingSummarize(
225
255
  ): AsyncIterable<StreamChunk> {
226
256
  const { adapter, text, maxLength, style, focus } = options
227
257
  const model = adapter.model
258
+ const logger: InternalLogger = resolveDebugOption(options.debug)
259
+
260
+ logger.request(`activity=summarize provider=${adapter.name}`, {
261
+ provider: adapter.name,
262
+ model,
263
+ stream: true,
264
+ })
228
265
 
229
266
  const summarizeOptions: SummarizationOptions = {
230
267
  model,
@@ -232,16 +269,25 @@ async function* runStreamingSummarize(
232
269
  maxLength,
233
270
  style,
234
271
  focus,
272
+ logger,
235
273
  }
236
274
 
237
- // Use real streaming if the adapter supports it
238
- if (adapter.summarizeStream) {
239
- yield* adapter.summarizeStream(summarizeOptions)
240
- return
241
- }
275
+ try {
276
+ // Use real streaming if the adapter supports it
277
+ if (adapter.summarizeStream) {
278
+ yield* adapter.summarizeStream(summarizeOptions)
279
+ return
280
+ }
242
281
 
243
- // Fall back to non-streaming — wrap result with streamGenerationResult
244
- yield* streamGenerationResult(() => adapter.summarize(summarizeOptions))
282
+ // Fall back to non-streaming — wrap result with streamGenerationResult
283
+ yield* streamGenerationResult(() => adapter.summarize(summarizeOptions))
284
+ } catch (error) {
285
+ logger.errors('summarize activity failed', {
286
+ error,
287
+ source: 'summarize',
288
+ })
289
+ throw error
290
+ }
245
291
  }
246
292
 
247
293
  // ===========================
@@ -0,0 +1,8 @@
1
+ // NOTE: This module is exposed ONLY via the `@tanstack/ai/adapter-internals`
2
+ // subpath export. It gives provider adapter packages access to the internal
3
+ // logger plumbing without leaking those symbols to end users.
4
+
5
+ export type { ResolvedCategories } from './logger/internal-logger'
6
+ export { InternalLogger } from './logger/internal-logger'
7
+ export { resolveDebugOption } from './logger/resolve'
8
+ export { toRunErrorPayload } from './activities/error-payload'
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export {
3
3
  chat,
4
4
  summarize,
5
5
  generateImage,
6
+ generateAudio,
6
7
  generateVideo,
7
8
  getVideoJobStatus,
8
9
  generateSpeech,
@@ -13,6 +14,7 @@ export {
13
14
  export { createChatOptions } from './activities/chat/index'
14
15
  export { createSummarizeOptions } from './activities/summarize/index'
15
16
  export { createImageOptions } from './activities/generateImage/index'
17
+ export { createAudioOptions } from './activities/generateAudio/index'
16
18
  export { createVideoOptions } from './activities/generateVideo/index'
17
19
  export { createSpeechOptions } from './activities/generateSpeech/index'
18
20
  export { createTranscriptionOptions } from './activities/generateTranscription/index'
@@ -26,6 +28,8 @@ export type {
26
28
  AnyTextAdapter,
27
29
  AnySummarizeAdapter,
28
30
  SummarizeAdapter,
31
+ AnyAudioAdapter,
32
+ AudioAdapter,
29
33
  AnyTTSAdapter,
30
34
  TTSAdapter,
31
35
  AnyTranscriptionAdapter,
@@ -167,3 +171,12 @@ export type {
167
171
  // Adapter extension utilities
168
172
  export { createModel, extendAdapter } from './extend-adapter'
169
173
  export type { ExtendedModelDef } from './extend-adapter'
174
+
175
+ // Logger
176
+ export type {
177
+ Logger,
178
+ DebugCategories,
179
+ DebugConfig,
180
+ DebugOption,
181
+ } from './logger/types'
182
+ export { ConsoleLogger } from './logger/console-logger'
@@ -0,0 +1,49 @@
1
+ import type { Logger } from './types'
2
+
3
+ /**
4
+ * Default `Logger` implementation that routes each level to the matching
5
+ * `console` method:
6
+ *
7
+ * - `debug` → `console.debug`
8
+ * - `info` → `console.info`
9
+ * - `warn` → `console.warn`
10
+ * - `error` → `console.error`
11
+ *
12
+ * When a `meta` object is supplied, the message is logged first and the meta
13
+ * object is then printed via `console.dir(meta, { depth: null, colors: true })`
14
+ * so deeply nested structures (e.g. provider chunk payloads with `usage`,
15
+ * `output`, `reasoning`, `tools`) render in full instead of truncating to
16
+ * `[Object]` / `[Array]`. On Node this produces a depth-unlimited inspect
17
+ * dump; browsers present the object as an interactive tree (extra options
18
+ * are ignored).
19
+ *
20
+ * This is the logger used when `debug` is enabled on any activity and no
21
+ * custom `logger` is supplied via `debug: { logger }`.
22
+ */
23
+ const DIR_OPTIONS = { depth: null, colors: true } as const
24
+
25
+ export class ConsoleLogger implements Logger {
26
+ /** Log a debug-level message; forwards to `console.debug`. */
27
+ debug(message: string, meta?: Record<string, unknown>): void {
28
+ console.debug(message)
29
+ if (meta !== undefined) console.dir(meta, DIR_OPTIONS)
30
+ }
31
+
32
+ /** Log an info-level message; forwards to `console.info`. */
33
+ info(message: string, meta?: Record<string, unknown>): void {
34
+ console.info(message)
35
+ if (meta !== undefined) console.dir(meta, DIR_OPTIONS)
36
+ }
37
+
38
+ /** Log a warning-level message; forwards to `console.warn`. */
39
+ warn(message: string, meta?: Record<string, unknown>): void {
40
+ console.warn(message)
41
+ if (meta !== undefined) console.dir(meta, DIR_OPTIONS)
42
+ }
43
+
44
+ /** Log an error-level message; forwards to `console.error`. */
45
+ error(message: string, meta?: Record<string, unknown>): void {
46
+ console.error(message)
47
+ if (meta !== undefined) console.dir(meta, DIR_OPTIONS)
48
+ }
49
+ }