@tanstack/ai 0.55.0 → 0.58.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 (67) hide show
  1. package/README.md +42 -16
  2. package/dist/esm/activities/chat/index.js +8 -6
  3. package/dist/esm/activities/chat/index.js.map +1 -1
  4. package/dist/esm/activities/chat/middleware/types.d.ts +4 -3
  5. package/dist/esm/activities/chat/middleware/types.js.map +1 -1
  6. package/dist/esm/activities/chat/tools/tool-calls.d.ts +2 -2
  7. package/dist/esm/activities/chat/tools/tool-calls.js +3 -2
  8. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  9. package/dist/esm/activities/evaluate/adapter.d.ts +160 -0
  10. package/dist/esm/activities/evaluate/adapter.js +23 -0
  11. package/dist/esm/activities/evaluate/adapter.js.map +1 -0
  12. package/dist/esm/activities/evaluate/index.d.ts +255 -0
  13. package/dist/esm/activities/evaluate/index.js +317 -0
  14. package/dist/esm/activities/evaluate/index.js.map +1 -0
  15. package/dist/esm/activities/generateSpeech/adapter.d.ts +39 -1
  16. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
  17. package/dist/esm/activities/generateSpeech/index.d.ts +55 -5
  18. package/dist/esm/activities/generateSpeech/index.js +53 -3
  19. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  20. package/dist/esm/activities/generateVoice/adapter.d.ts +62 -0
  21. package/dist/esm/activities/generateVoice/adapter.js +23 -0
  22. package/dist/esm/activities/generateVoice/adapter.js.map +1 -0
  23. package/dist/esm/activities/generateVoice/index.d.ts +133 -0
  24. package/dist/esm/activities/generateVoice/index.js +184 -0
  25. package/dist/esm/activities/generateVoice/index.js.map +1 -0
  26. package/dist/esm/activities/index.d.ts +10 -4
  27. package/dist/esm/activities/index.js +14 -10
  28. package/dist/esm/activities/middleware/types.d.ts +1 -1
  29. package/dist/esm/client.d.ts +3 -2
  30. package/dist/esm/client.js +21 -3
  31. package/dist/esm/client.js.map +1 -1
  32. package/dist/esm/index.d.ts +4 -2
  33. package/dist/esm/index.js +6 -3
  34. package/dist/esm/middlewares/otel.js +2 -0
  35. package/dist/esm/middlewares/otel.js.map +1 -1
  36. package/dist/esm/realtime/index.d.ts +1 -1
  37. package/dist/esm/realtime/index.js +1 -1
  38. package/dist/esm/realtime/index.js.map +1 -1
  39. package/dist/esm/stream-to-response.js +12 -6
  40. package/dist/esm/stream-to-response.js.map +1 -1
  41. package/dist/esm/strip-to-spec-middleware.js +2 -1
  42. package/dist/esm/strip-to-spec-middleware.js.map +1 -1
  43. package/dist/esm/types.d.ts +243 -3
  44. package/dist/esm/utilities/durability-batch.d.ts +8 -0
  45. package/dist/esm/utilities/durability-batch.js +45 -0
  46. package/dist/esm/utilities/durability-batch.js.map +1 -0
  47. package/package.json +3 -3
  48. package/skills/ai-core/media-generation/SKILL.md +132 -6
  49. package/src/activities/chat/index.ts +11 -5
  50. package/src/activities/chat/middleware/types.ts +8 -2
  51. package/src/activities/chat/tools/tool-calls.ts +24 -5
  52. package/src/activities/evaluate/adapter.ts +212 -0
  53. package/src/activities/evaluate/index.ts +614 -0
  54. package/src/activities/generateSpeech/adapter.ts +47 -1
  55. package/src/activities/generateSpeech/index.ts +149 -8
  56. package/src/activities/generateVoice/adapter.ts +89 -0
  57. package/src/activities/generateVoice/index.ts +371 -0
  58. package/src/activities/index.ts +69 -0
  59. package/src/activities/middleware/types.ts +2 -0
  60. package/src/client.ts +35 -8
  61. package/src/index.ts +21 -0
  62. package/src/middlewares/otel.ts +2 -0
  63. package/src/realtime/index.ts +1 -1
  64. package/src/stream-to-response.ts +16 -6
  65. package/src/strip-to-spec-middleware.ts +2 -1
  66. package/src/types.ts +269 -3
  67. package/src/utilities/durability-batch.ts +48 -0
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":[],"sources":["../../../../src/activities/generateSpeech/adapter.ts"],"sourcesContent":["import type { TTSOptions, TTSResult } from '../../types'\n\n/**\n * Configuration for TTS adapter instances\n */\nexport interface TTSAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * TTS adapter interface with pre-resolved generics.\n *\n * An adapter is created by a provider function: `provider('model')` → `adapter`\n * All type resolution happens at the provider call site, not in this interface.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'tts-1')\n * - TProviderOptions: Provider-specific options (already resolved)\n */\nexport interface TTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'tts'\n /** Adapter name identifier */\n readonly name: string\n /** The model this adapter is configured for */\n readonly model: TModel\n\n /**\n * @internal Type-only properties for inference. Not assigned at runtime.\n */\n '~types': {\n providerOptions: TProviderOptions\n }\n\n /**\n * Generate speech from text\n */\n generateSpeech: (options: TTSOptions<TProviderOptions>) => Promise<TTSResult>\n}\n\n/**\n * A TTSAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyTTSAdapter = TTSAdapter<any, any>\n\n/**\n * Abstract base class for text-to-speech adapters.\n * Extend this class to implement a TTS adapter for a specific provider.\n *\n * Generic parameters match TTSAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseTTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> implements TTSAdapter<TModel, TProviderOptions> {\n readonly kind = 'tts' as const\n abstract readonly name: string\n readonly model: TModel\n\n // Type-only property - never assigned at runtime\n declare '~types': {\n providerOptions: TProviderOptions\n }\n\n protected config: TTSAdapterConfig\n\n constructor(model: TModel, config: TTSAdapterConfig = {}) {\n this.config = config\n this.model = model\n }\n\n abstract generateSpeech(\n options: TTSOptions<TProviderOptions>,\n ): Promise<TTSResult>\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"mappings":";;;;;;;AA2DA,IAAsB,iBAAtB,MAGkD;CAChD,OAAgB;CAEhB;CAOA;CAEA,YAAY,OAAe,SAA2B,CAAC,GAAG;EACxD,KAAK,SAAS;EACd,KAAK,QAAQ;CACf;CAMA,aAA+B;EAC7B,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;CAC7E;AACF"}
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../../src/activities/generateSpeech/adapter.ts"],"sourcesContent":["import type {\n ListVoicesOptions,\n ListVoicesResult,\n TTSOptions,\n TTSResult,\n} from '../../types'\n\n/**\n * What a TTS adapter can do beyond a single voice reading a single string.\n *\n * Declared statically so `generateSpeech()` can reject an unsupported request\n * before it reaches the provider, instead of surfacing a provider 422.\n */\nexport interface TTSCapabilities {\n /**\n * Maximum number of distinct voices accepted across `turns`\n * (ElevenLabs 10, Gemini 2). Omit it when the adapter has no dialogue\n * endpoint — then `turns` is rejected outright.\n */\n maxSpeakers?: number\n /** Set when the adapter can honour `timestamps: true`. */\n timestamps?: boolean\n}\n\n/**\n * Configuration for TTS adapter instances\n */\nexport interface TTSAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * TTS adapter interface with pre-resolved generics.\n *\n * An adapter is created by a provider function: `provider('model')` → `adapter`\n * All type resolution happens at the provider call site, not in this interface.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'tts-1')\n * - TProviderOptions: Provider-specific options (already resolved)\n */\nexport interface TTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'tts'\n /** Adapter name identifier */\n readonly name: string\n /** The model this adapter is configured for */\n readonly model: TModel\n /**\n * Optional static capability declaration. Absent means \"single voice, no\n * timestamps\" — the contract every adapter had before dialogue existed.\n */\n readonly capabilities?: TTSCapabilities\n\n /**\n * @internal Type-only properties for inference. Not assigned at runtime.\n */\n '~types': {\n providerOptions: TProviderOptions\n }\n\n /**\n * Generate speech from text\n */\n generateSpeech: (options: TTSOptions<TProviderOptions>) => Promise<TTSResult>\n\n /**\n * List the voices this account can use.\n *\n * Optional, because only some providers have a catalog worth querying at\n * runtime. A provider whose voices are a fixed list known at build time\n * publishes that list from its own package instead (`GeminiTTSVoices`, or\n * the `OpenAITTSVoice` union), which is strictly better than a network\n * call. Implement this only when the catalog is per-account and can change,\n * which is the case wherever `generateVoice()` can add to it.\n */\n listVoices?: (options?: ListVoicesOptions) => Promise<ListVoicesResult>\n}\n\n/**\n * A TTSAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyTTSAdapter = TTSAdapter<any, any>\n\n/**\n * Abstract base class for text-to-speech adapters.\n * Extend this class to implement a TTS adapter for a specific provider.\n *\n * Generic parameters match TTSAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseTTSAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> implements TTSAdapter<TModel, TProviderOptions> {\n readonly kind = 'tts' as const\n abstract readonly name: string\n readonly model: TModel\n declare readonly capabilities?: TTSCapabilities\n\n // Type-only property - never assigned at runtime\n declare '~types': {\n providerOptions: TProviderOptions\n }\n\n protected config: TTSAdapterConfig\n\n constructor(model: TModel, config: TTSAdapterConfig = {}) {\n this.config = config\n this.model = model\n }\n\n abstract generateSpeech(\n options: TTSOptions<TProviderOptions>,\n ): Promise<TTSResult>\n\n /**\n * Not abstract: a provider with a fixed voice list has nothing to query and\n * should not be forced to write a stub.\n */\n listVoices?(options?: ListVoicesOptions): Promise<ListVoicesResult>\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"mappings":";;;;;;;AAkGA,IAAsB,iBAAtB,MAGkD;CAChD,OAAgB;CAEhB;CAQA;CAEA,YAAY,OAAe,SAA2B,CAAC,GAAG;EACxD,KAAK,SAAS;EACd,KAAK,QAAQ;CACf;CAYA,aAA+B;EAC7B,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;CAC7E;AACF"}
@@ -1,7 +1,7 @@
1
1
  import { DebugOption } from '../../logger/types.js';
2
2
  import { GenerationMiddleware } from '../middleware/types.js';
3
3
  import { TTSAdapter } from './adapter.js';
4
- import { StreamChunk, TTSResult } from '../../types.js';
4
+ import { ListVoicesOptions, ListVoicesResult, StreamChunk, TTSResult, TTSTurn } from '../../types.js';
5
5
  /** The adapter kind this activity handles */
6
6
  export declare const kind: "tts";
7
7
  /**
@@ -19,15 +19,37 @@ export type TTSProviderOptions<TAdapter> = TAdapter extends {
19
19
  * @template TAdapter - The TTS adapter type
20
20
  * @template TStream - Whether to stream the output
21
21
  */
22
- export interface TTSActivityOptions<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>, TStream extends boolean = false> {
22
+ export type TTSActivityOptions<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>, TStream extends boolean = false> = TTSActivityOptionsBase<TAdapter, TStream> & ({
23
+ /** The text to convert to speech */
24
+ text: string;
25
+ turns?: undefined;
26
+ } | {
27
+ text?: undefined;
28
+ /**
29
+ * Multi-voice dialogue turns, one per line of the script. Mutually
30
+ * exclusive with `text`.
31
+ *
32
+ * Only adapters that declare `capabilities.maxSpeakers` accept these
33
+ * (ElevenLabs 10 voices, Gemini 2); anything else throws before the
34
+ * request leaves the process.
35
+ */
36
+ turns: Array<TTSTurn>;
37
+ });
38
+ /** Shared half of {@link TTSActivityOptions} — everything except text/turns. */
39
+ interface TTSActivityOptionsBase<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>, TStream extends boolean = false> {
23
40
  /** The TTS adapter to use (must be created with a model) */
24
41
  adapter: TAdapter & {
25
42
  kind: typeof kind;
26
43
  };
27
- /** The text to convert to speech */
28
- text: string;
29
44
  /** The voice to use for generation */
30
45
  voice?: string;
46
+ /**
47
+ * Ask for `alignment` (character/word timings) and `segments` (per-turn
48
+ * spans) on the result. Only adapters that declare
49
+ * `capabilities.timestamps` accept it — on ElevenLabs it is a different
50
+ * endpoint, on BytePlus a different request flag, so it cannot be inferred.
51
+ */
52
+ timestamps?: boolean;
31
53
  /** The output audio format */
32
54
  format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm';
33
55
  /** The speed of the generated audio (0.25 to 4.0) */
@@ -108,9 +130,37 @@ export type TTSActivityResult<TStream extends boolean = false> = TStream extends
108
130
  * ```
109
131
  */
110
132
  export declare function generateSpeech<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>, TStream extends boolean = false>(options: TTSActivityOptions<TAdapter, TStream>): TTSActivityResult<TStream>;
133
+ /**
134
+ * Options for {@link listVoices}.
135
+ */
136
+ export interface ListVoicesActivityOptions<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>> extends ListVoicesOptions {
137
+ /** The speech adapter whose catalog to read */
138
+ adapter: TAdapter & {
139
+ kind: typeof kind;
140
+ };
141
+ }
142
+ /**
143
+ * List the voices an account can pass to `generateSpeech()`.
144
+ *
145
+ * Only providers with a per-account catalog implement this. A provider whose
146
+ * voices are a fixed list publishes that list as a const in its package, so
147
+ * import it from there rather than calling this.
148
+ *
149
+ * @example Find the voices you created
150
+ * ```ts
151
+ * import { listVoices } from '@tanstack/ai'
152
+ * import { elevenlabsSpeech } from '@tanstack/ai-elevenlabs'
153
+ *
154
+ * const { voices } = await listVoices({
155
+ * adapter: elevenlabsSpeech('eleven_v3'),
156
+ * origins: ['generated', 'cloned'],
157
+ * })
158
+ * ```
159
+ */
160
+ export declare function listVoices<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>>(options: ListVoicesActivityOptions<TAdapter>): Promise<ListVoicesResult>;
111
161
  /**
112
162
  * Create typed options for the generateSpeech() function without executing.
113
163
  */
114
164
  export declare function createSpeechOptions<TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>, TStream extends boolean = false>(options: TTSActivityOptions<TAdapter, TStream>): TTSActivityOptions<TAdapter, TStream>;
115
- export type { TTSAdapter, TTSAdapterConfig, AnyTTSAdapter } from './adapter.js';
165
+ export type { TTSAdapter, TTSAdapterConfig, TTSCapabilities, AnyTTSAdapter, } from './adapter.js';
116
166
  export { BaseTTSAdapter } from './adapter.js';
@@ -17,6 +17,30 @@ function createId(prefix) {
17
17
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
18
18
  }
19
19
  /**
20
+ * Validate the text/turns/timestamps trio against what the adapter declares,
21
+ * and return the `text` every adapter receives.
22
+ *
23
+ * For a dialogue request that text is the turn scripts joined by newlines:
24
+ * dialogue-aware adapters read `turns` and ignore it, but it keeps `text`
25
+ * non-optional on the adapter contract and gives the devtools event and the
26
+ * artifact inputs something truthful to show.
27
+ */
28
+ function resolveSpeechText(adapter, input) {
29
+ const { text, turns, timestamps } = input;
30
+ if (timestamps && !adapter.capabilities?.timestamps) throw new Error(`${adapter.name} cannot return timestamps. Drop \`timestamps: true\` — the result would have no alignment to read.`);
31
+ if (turns) {
32
+ if (text !== void 0) throw new Error("generateSpeech() takes either `text` or `turns`, not both.");
33
+ if (turns.length === 0) throw new Error("generateSpeech() `turns` must not be empty.");
34
+ const maxSpeakers = adapter.capabilities?.maxSpeakers;
35
+ if (maxSpeakers === void 0) throw new Error(`${adapter.name} cannot generate dialogue. Pass \`text\` (and \`voice\`) instead of \`turns\`.`);
36
+ const speakers = new Set(turns.map((turn) => turn.voice)).size;
37
+ if (speakers > maxSpeakers) throw new Error(`${adapter.name} accepts at most ${maxSpeakers} distinct voice${maxSpeakers === 1 ? "" : "s"} per request; received ${speakers}.`);
38
+ return turns.map((turn) => turn.text).join("\n");
39
+ }
40
+ if (text === void 0) throw new Error("generateSpeech() requires either `text` or `turns`.");
41
+ return text;
42
+ }
43
+ /**
20
44
  * TTS activity - generates speech from text.
21
45
  *
22
46
  * Uses AI text-to-speech models to create audio from natural language text.
@@ -59,6 +83,7 @@ function generateSpeech(options) {
59
83
  async function runGenerateSpeech(options) {
60
84
  const { adapter, stream: _stream, debug: _debug, middleware, threadId, runId, timeout, abortSignal: callerAbortSignal, ...rest } = options;
61
85
  const model = adapter.model;
86
+ const text = resolveSpeechText(adapter, rest);
62
87
  const requestId = createId("speech");
63
88
  const startTime = Date.now();
64
89
  const logger = resolveDebugOption(options.debug);
@@ -74,7 +99,7 @@ async function runGenerateSpeech(options) {
74
99
  model,
75
100
  modelOptions: rest.modelOptions,
76
101
  artifactInputs: {
77
- text: rest.text,
102
+ text,
78
103
  voice: rest.voice,
79
104
  format: rest.format,
80
105
  speed: rest.speed
@@ -88,7 +113,7 @@ async function runGenerateSpeech(options) {
88
113
  requestId,
89
114
  provider: adapter.name,
90
115
  model,
91
- text: rest.text,
116
+ text,
92
117
  voice: rest.voice,
93
118
  format: rest.format,
94
119
  speed: rest.speed,
@@ -102,6 +127,7 @@ async function runGenerateSpeech(options) {
102
127
  try {
103
128
  const rawResult = await raceWithAbort(adapter.generateSpeech({
104
129
  ...rest,
130
+ text,
105
131
  model,
106
132
  logger,
107
133
  ...abortControls.signal ? { abortSignal: abortControls.signal } : {}
@@ -170,12 +196,36 @@ async function runGenerateSpeech(options) {
170
196
  }
171
197
  }
172
198
  /**
199
+ * List the voices an account can pass to `generateSpeech()`.
200
+ *
201
+ * Only providers with a per-account catalog implement this. A provider whose
202
+ * voices are a fixed list publishes that list as a const in its package, so
203
+ * import it from there rather than calling this.
204
+ *
205
+ * @example Find the voices you created
206
+ * ```ts
207
+ * import { listVoices } from '@tanstack/ai'
208
+ * import { elevenlabsSpeech } from '@tanstack/ai-elevenlabs'
209
+ *
210
+ * const { voices } = await listVoices({
211
+ * adapter: elevenlabsSpeech('eleven_v3'),
212
+ * origins: ['generated', 'cloned'],
213
+ * })
214
+ * ```
215
+ */
216
+ async function listVoices(options) {
217
+ const { adapter, ...rest } = options;
218
+ const list = adapter.listVoices;
219
+ if (!list) throw new Error(`The ${adapter.name} speech adapter has no per-account voice catalog to list. Its voices are a fixed set — import the voice list or union its package exports instead (for example \`GeminiTTSVoices\` from @tanstack/ai-gemini, or the \`OpenAITTSVoice\` union from @tanstack/ai-openai).`);
220
+ return await list.call(adapter, rest);
221
+ }
222
+ /**
173
223
  * Create typed options for the generateSpeech() function without executing.
174
224
  */
175
225
  function createSpeechOptions(options) {
176
226
  return options;
177
227
  }
178
228
  //#endregion
179
- export { createSpeechOptions, generateSpeech, kind };
229
+ export { createSpeechOptions, generateSpeech, kind, listVoices };
180
230
 
181
231
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateSpeech/index.ts"],"sourcesContent":["/**\n * TTS Activity\n *\n * Generates speech audio from text using text-to-speech models.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n applyGenerationResultTransforms,\n createGenerationContext,\n runGenerationAbort,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport {\n abortReasonMessage,\n createActivityAbortControls,\n isActivityAbortError,\n raceWithAbort,\n} from '../../utilities/activity-abort'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { TTSAdapter } from './adapter'\nimport type { StreamChunk, TTSResult } from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'tts' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a TTSAdapter via ~types.\n */\nexport type TTSProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P extends object }\n}\n ? P\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the TTS activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The TTS adapter type\n * @template TStream - Whether to stream the output\n */\nexport interface TTSActivityOptions<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n> {\n /** The TTS adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /** The text to convert to speech */\n text: string\n /** The voice to use for generation */\n voice?: string\n /** The output audio format */\n format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm'\n /** The speed of the generated audio (0.25 to 4.0) */\n speed?: number\n /** Provider-specific options for TTS generation */\n modelOptions?: TTSProviderOptions<TAdapter>\n /**\n * Whether to stream the generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<TTSResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n /** Stable conversation/thread id for correlating this run when persisted. */\n threadId?: string\n /** Stable run id for correlating this run when persisted. */\n runId?: string\n /**\n * Maximum duration of this activity invocation in milliseconds.\n * No SDK-wide default — choose a value suitable for the provider and job.\n * Composed with {@link abortSignal}; the first abort wins.\n */\n timeout?: number\n /**\n * Caller cancellation signal (request disconnects, job/runtime cancellation).\n * Composed with {@link timeout} into an effective signal forwarded to the\n * adapter. Request-specific — not stored on global provider client config.\n */\n abortSignal?: AbortSignal\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the TTS activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<TTSResult>\n */\nexport type TTSActivityResult<TStream extends boolean = false> =\n TStream extends true ? AsyncIterable<StreamChunk> : Promise<TTSResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * TTS activity - generates speech from text.\n *\n * Uses AI text-to-speech models to create audio from natural language text.\n *\n * @example Generate speech from text\n * ```ts\n * import { generateSpeech } from '@tanstack/ai'\n * import { openaiSpeech } from '@tanstack/ai-openai'\n *\n * const result = await generateSpeech({\n * adapter: openaiSpeech('tts-1-hd'),\n * text: 'Hello, welcome to TanStack AI!',\n * voice: 'nova'\n * })\n *\n * console.log(result.audio) // base64-encoded audio\n * ```\n *\n * @example With format and speed options\n * ```ts\n * const result = await generateSpeech({\n * adapter: openaiSpeech('tts-1'),\n * text: 'This is slower speech.',\n * voice: 'alloy',\n * format: 'wav',\n * speed: 0.8\n * })\n * ```\n */\nexport function generateSpeech<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(options: TTSActivityOptions<TAdapter, TStream>): TTSActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(\n // Only `runId` is taken from the resolved wire identity. `threadId` stays\n // the CALLER's: `streamGenerationResult` mints one for the RUN_* chunks\n // when none was passed, and spreading that over the options would hand\n // middleware a thread id known to nobody, which persistence would then\n // file the run under. Matches `generateVideo`.\n (resolved) => runGenerateSpeech({ ...options, runId: resolved.runId }),\n options,\n ) as TTSActivityResult<TStream>\n }\n return runGenerateSpeech(options) as TTSActivityResult<TStream>\n}\n\n/**\n * Run the core TTS generation logic (non-streaming).\n */\nasync function runGenerateSpeech<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n>(options: TTSActivityOptions<TAdapter, boolean>): Promise<TTSResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n timeout,\n abortSignal: callerAbortSignal,\n ...rest\n } = options\n const model = adapter.model\n const requestId = createId('speech')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n const abortControls = createActivityAbortControls({\n timeout,\n abortSignal: callerAbortSignal,\n })\n const providerName =\n (adapter as { name?: string; provider?: string }).provider ??\n (adapter as { name?: string }).name ??\n 'unknown'\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'tts',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n artifactInputs: {\n text: rest.text,\n voice: rest.voice,\n format: rest.format,\n speed: rest.speed,\n },\n threadId,\n runId,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('speech:request:started', {\n requestId,\n provider: adapter.name,\n model,\n text: rest.text,\n voice: rest.voice,\n format: rest.format,\n speed: rest.speed,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateSpeech provider=${providerName}`, {\n provider: providerName,\n model,\n })\n\n try {\n const rawResult = await raceWithAbort(\n adapter.generateSpeech({\n ...rest,\n model,\n logger,\n ...(abortControls.signal ? { abortSignal: abortControls.signal } : {}),\n }),\n abortControls.signal,\n )\n abortControls.clear()\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('speech:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n audio: result.audio,\n format: result.format,\n audioDuration: result.duration,\n contentType: result.contentType,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('speech:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateSpeech bytes=${result.audio.length}`, {\n bytes: result.audio.length,\n contentType: result.contentType,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n abortControls.clear()\n const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('speech:request:error', {\n requestId,\n provider: adapter.name,\n model,\n error: { message: err.message, name: err.name },\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n if (isActivityAbortError(error, abortControls.signal)) {\n await runGenerationAbort(middleware, mwCtx, {\n reason: abortReasonMessage(error, abortControls.signal),\n duration,\n })\n } else {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n }\n logger.errors('generateSpeech activity failed', {\n error,\n source: 'generateSpeech',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateSpeech() function without executing.\n */\nexport function createSpeechOptions<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: TTSActivityOptions<TAdapter, TStream>,\n): TTSActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type { TTSAdapter, TTSAdapterConfig, AnyTTSAdapter } from './adapter'\nexport { BaseTTSAdapter } from './adapter'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateSpeech/index.ts"],"sourcesContent":["/**\n * TTS Activity\n *\n * Generates speech audio from text using text-to-speech models.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n applyGenerationResultTransforms,\n createGenerationContext,\n runGenerationAbort,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport {\n abortReasonMessage,\n createActivityAbortControls,\n isActivityAbortError,\n raceWithAbort,\n} from '../../utilities/activity-abort'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { TTSAdapter, TTSCapabilities } from './adapter'\nimport type {\n ListVoicesOptions,\n ListVoicesResult,\n StreamChunk,\n TTSResult,\n TTSTurn,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'tts' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a TTSAdapter via ~types.\n */\nexport type TTSProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P extends object }\n}\n ? P\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the TTS activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The TTS adapter type\n * @template TStream - Whether to stream the output\n */\nexport type TTSActivityOptions<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n> = TTSActivityOptionsBase<TAdapter, TStream> &\n (\n | {\n /** The text to convert to speech */\n text: string\n turns?: undefined\n }\n | {\n text?: undefined\n /**\n * Multi-voice dialogue turns, one per line of the script. Mutually\n * exclusive with `text`.\n *\n * Only adapters that declare `capabilities.maxSpeakers` accept these\n * (ElevenLabs 10 voices, Gemini 2); anything else throws before the\n * request leaves the process.\n */\n turns: Array<TTSTurn>\n }\n )\n\n/** Shared half of {@link TTSActivityOptions} — everything except text/turns. */\ninterface TTSActivityOptionsBase<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n> {\n /** The TTS adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /** The voice to use for generation */\n voice?: string\n /**\n * Ask for `alignment` (character/word timings) and `segments` (per-turn\n * spans) on the result. Only adapters that declare\n * `capabilities.timestamps` accept it — on ElevenLabs it is a different\n * endpoint, on BytePlus a different request flag, so it cannot be inferred.\n */\n timestamps?: boolean\n /** The output audio format */\n format?: 'mp3' | 'opus' | 'aac' | 'flac' | 'wav' | 'pcm'\n /** The speed of the generated audio (0.25 to 4.0) */\n speed?: number\n /** Provider-specific options for TTS generation */\n modelOptions?: TTSProviderOptions<TAdapter>\n /**\n * Whether to stream the generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<TTSResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n /** Stable conversation/thread id for correlating this run when persisted. */\n threadId?: string\n /** Stable run id for correlating this run when persisted. */\n runId?: string\n /**\n * Maximum duration of this activity invocation in milliseconds.\n * No SDK-wide default — choose a value suitable for the provider and job.\n * Composed with {@link abortSignal}; the first abort wins.\n */\n timeout?: number\n /**\n * Caller cancellation signal (request disconnects, job/runtime cancellation).\n * Composed with {@link timeout} into an effective signal forwarded to the\n * adapter. Request-specific — not stored on global provider client config.\n */\n abortSignal?: AbortSignal\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the TTS activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<TTSResult>\n */\nexport type TTSActivityResult<TStream extends boolean = false> =\n TStream extends true ? AsyncIterable<StreamChunk> : Promise<TTSResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n/**\n * Validate the text/turns/timestamps trio against what the adapter declares,\n * and return the `text` every adapter receives.\n *\n * For a dialogue request that text is the turn scripts joined by newlines:\n * dialogue-aware adapters read `turns` and ignore it, but it keeps `text`\n * non-optional on the adapter contract and gives the devtools event and the\n * artifact inputs something truthful to show.\n */\nfunction resolveSpeechText(\n adapter: { name: string; capabilities?: TTSCapabilities },\n input: { text?: string; turns?: Array<TTSTurn>; timestamps?: boolean },\n): string {\n const { text, turns, timestamps } = input\n\n if (timestamps && !adapter.capabilities?.timestamps) {\n throw new Error(\n `${adapter.name} cannot return timestamps. Drop \\`timestamps: true\\` — the result would have no alignment to read.`,\n )\n }\n\n if (turns) {\n if (text !== undefined) {\n throw new Error(\n 'generateSpeech() takes either `text` or `turns`, not both.',\n )\n }\n if (turns.length === 0) {\n throw new Error('generateSpeech() `turns` must not be empty.')\n }\n const maxSpeakers = adapter.capabilities?.maxSpeakers\n if (maxSpeakers === undefined) {\n throw new Error(\n `${adapter.name} cannot generate dialogue. Pass \\`text\\` (and \\`voice\\`) instead of \\`turns\\`.`,\n )\n }\n const speakers = new Set(turns.map((turn) => turn.voice)).size\n if (speakers > maxSpeakers) {\n throw new Error(\n `${adapter.name} accepts at most ${maxSpeakers} distinct voice${maxSpeakers === 1 ? '' : 's'} per request; received ${speakers}.`,\n )\n }\n return turns.map((turn) => turn.text).join('\\n')\n }\n\n if (text === undefined) {\n throw new Error('generateSpeech() requires either `text` or `turns`.')\n }\n return text\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * TTS activity - generates speech from text.\n *\n * Uses AI text-to-speech models to create audio from natural language text.\n *\n * @example Generate speech from text\n * ```ts\n * import { generateSpeech } from '@tanstack/ai'\n * import { openaiSpeech } from '@tanstack/ai-openai'\n *\n * const result = await generateSpeech({\n * adapter: openaiSpeech('tts-1-hd'),\n * text: 'Hello, welcome to TanStack AI!',\n * voice: 'nova'\n * })\n *\n * console.log(result.audio) // base64-encoded audio\n * ```\n *\n * @example With format and speed options\n * ```ts\n * const result = await generateSpeech({\n * adapter: openaiSpeech('tts-1'),\n * text: 'This is slower speech.',\n * voice: 'alloy',\n * format: 'wav',\n * speed: 0.8\n * })\n * ```\n */\nexport function generateSpeech<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(options: TTSActivityOptions<TAdapter, TStream>): TTSActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(\n // Only `runId` is taken from the resolved wire identity. `threadId` stays\n // the CALLER's: `streamGenerationResult` mints one for the RUN_* chunks\n // when none was passed, and spreading that over the options would hand\n // middleware a thread id known to nobody, which persistence would then\n // file the run under. Matches `generateVideo`.\n (resolved) => runGenerateSpeech({ ...options, runId: resolved.runId }),\n options,\n ) as TTSActivityResult<TStream>\n }\n return runGenerateSpeech(options) as TTSActivityResult<TStream>\n}\n\n/**\n * Run the core TTS generation logic (non-streaming).\n */\nasync function runGenerateSpeech<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n>(options: TTSActivityOptions<TAdapter, boolean>): Promise<TTSResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n timeout,\n abortSignal: callerAbortSignal,\n ...rest\n } = options\n const model = adapter.model\n const text = resolveSpeechText(adapter, rest)\n const requestId = createId('speech')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n const abortControls = createActivityAbortControls({\n timeout,\n abortSignal: callerAbortSignal,\n })\n const providerName =\n (adapter as { name?: string; provider?: string }).provider ??\n (adapter as { name?: string }).name ??\n 'unknown'\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'tts',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n artifactInputs: {\n text,\n voice: rest.voice,\n format: rest.format,\n speed: rest.speed,\n },\n threadId,\n runId,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('speech:request:started', {\n requestId,\n provider: adapter.name,\n model,\n text,\n voice: rest.voice,\n format: rest.format,\n speed: rest.speed,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateSpeech provider=${providerName}`, {\n provider: providerName,\n model,\n })\n\n try {\n const rawResult = await raceWithAbort(\n adapter.generateSpeech({\n ...rest,\n text,\n model,\n logger,\n ...(abortControls.signal ? { abortSignal: abortControls.signal } : {}),\n }),\n abortControls.signal,\n )\n abortControls.clear()\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('speech:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n audio: result.audio,\n format: result.format,\n audioDuration: result.duration,\n contentType: result.contentType,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('speech:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateSpeech bytes=${result.audio.length}`, {\n bytes: result.audio.length,\n contentType: result.contentType,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n abortControls.clear()\n const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('speech:request:error', {\n requestId,\n provider: adapter.name,\n model,\n error: { message: err.message, name: err.name },\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n if (isActivityAbortError(error, abortControls.signal)) {\n await runGenerationAbort(middleware, mwCtx, {\n reason: abortReasonMessage(error, abortControls.signal),\n duration,\n })\n } else {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n }\n logger.errors('generateSpeech activity failed', {\n error,\n source: 'generateSpeech',\n })\n throw error\n }\n}\n\n// ===========================\n// Voice Catalog\n// ===========================\n\n/**\n * Options for {@link listVoices}.\n */\nexport interface ListVoicesActivityOptions<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n> extends ListVoicesOptions {\n /** The speech adapter whose catalog to read */\n adapter: TAdapter & { kind: typeof kind }\n}\n\n/**\n * List the voices an account can pass to `generateSpeech()`.\n *\n * Only providers with a per-account catalog implement this. A provider whose\n * voices are a fixed list publishes that list as a const in its package, so\n * import it from there rather than calling this.\n *\n * @example Find the voices you created\n * ```ts\n * import { listVoices } from '@tanstack/ai'\n * import { elevenlabsSpeech } from '@tanstack/ai-elevenlabs'\n *\n * const { voices } = await listVoices({\n * adapter: elevenlabsSpeech('eleven_v3'),\n * origins: ['generated', 'cloned'],\n * })\n * ```\n */\nexport async function listVoices<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n>(options: ListVoicesActivityOptions<TAdapter>): Promise<ListVoicesResult> {\n const { adapter, ...rest } = options\n\n const list = adapter.listVoices\n if (!list) {\n throw new Error(\n `The ${adapter.name} speech adapter has no per-account voice catalog to list. Its voices are a fixed set — import the voice list or union its package exports instead (for example \\`GeminiTTSVoices\\` from @tanstack/ai-gemini, or the \\`OpenAITTSVoice\\` union from @tanstack/ai-openai).`,\n )\n }\n\n return await list.call(adapter, rest)\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateSpeech() function without executing.\n */\nexport function createSpeechOptions<\n TAdapter extends TTSAdapter<string, TTSProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: TTSActivityOptions<TAdapter, TStream>,\n): TTSActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n TTSAdapter,\n TTSAdapterConfig,\n TTSCapabilities,\n AnyTTSAdapter,\n} from './adapter'\nexport { BaseTTSAdapter } from './adapter'\n"],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { VoiceGenerationOptions, VoiceResult } from '../../types.js';
2
+ /**
3
+ * Configuration for voice adapter instances
4
+ */
5
+ export interface VoiceAdapterConfig {
6
+ apiKey?: string;
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ maxRetries?: number;
10
+ headers?: Record<string, string>;
11
+ }
12
+ /**
13
+ * Voice adapter interface with pre-resolved generics.
14
+ *
15
+ * An adapter is created by a provider function: `provider('model')` → `adapter`
16
+ * All type resolution happens at the provider call site, not in this interface.
17
+ *
18
+ * Generic parameters:
19
+ * - TModel: The specific model name (e.g., 'eleven_ttv_v3')
20
+ * - TProviderOptions: Provider-specific options (already resolved)
21
+ */
22
+ export interface VoiceAdapter<TModel extends string = string, TProviderOptions extends object = Record<string, unknown>> {
23
+ /** Discriminator for adapter kind - used to determine API shape */
24
+ readonly kind: 'voice';
25
+ /** Adapter name identifier */
26
+ readonly name: string;
27
+ /** The model this adapter is configured for */
28
+ readonly model: TModel;
29
+ /**
30
+ * @internal Type-only properties for inference. Not assigned at runtime.
31
+ */
32
+ '~types': {
33
+ providerOptions: TProviderOptions;
34
+ };
35
+ /**
36
+ * Create a voice from a text description and/or reference audio
37
+ */
38
+ generateVoice: (options: VoiceGenerationOptions<TProviderOptions>) => Promise<VoiceResult>;
39
+ }
40
+ /**
41
+ * A VoiceAdapter with any/unknown type parameters.
42
+ * Useful as a constraint in generic functions and interfaces.
43
+ */
44
+ export type AnyVoiceAdapter = VoiceAdapter<any, any>;
45
+ /**
46
+ * Abstract base class for voice creation adapters.
47
+ * Extend this class to implement a voice adapter for a specific provider.
48
+ *
49
+ * Generic parameters match VoiceAdapter - all pre-resolved by the provider function.
50
+ */
51
+ export declare abstract class BaseVoiceAdapter<TModel extends string = string, TProviderOptions extends object = Record<string, unknown>> implements VoiceAdapter<TModel, TProviderOptions> {
52
+ readonly kind: "voice";
53
+ abstract readonly name: string;
54
+ readonly model: TModel;
55
+ '~types': {
56
+ providerOptions: TProviderOptions;
57
+ };
58
+ protected config: VoiceAdapterConfig;
59
+ constructor(model: TModel, config?: VoiceAdapterConfig);
60
+ abstract generateVoice(options: VoiceGenerationOptions<TProviderOptions>): Promise<VoiceResult>;
61
+ protected generateId(): string;
62
+ }
@@ -0,0 +1,23 @@
1
+ //#region src/activities/generateVoice/adapter.ts
2
+ /**
3
+ * Abstract base class for voice creation adapters.
4
+ * Extend this class to implement a voice adapter for a specific provider.
5
+ *
6
+ * Generic parameters match VoiceAdapter - all pre-resolved by the provider function.
7
+ */
8
+ var BaseVoiceAdapter = class {
9
+ kind = "voice";
10
+ model;
11
+ config;
12
+ constructor(model, config = {}) {
13
+ this.config = config;
14
+ this.model = model;
15
+ }
16
+ generateId() {
17
+ return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
18
+ }
19
+ };
20
+ //#endregion
21
+ export { BaseVoiceAdapter };
22
+
23
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../../src/activities/generateVoice/adapter.ts"],"sourcesContent":["import type { VoiceGenerationOptions, VoiceResult } from '../../types'\n\n/**\n * Configuration for voice adapter instances\n */\nexport interface VoiceAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * Voice adapter interface with pre-resolved generics.\n *\n * An adapter is created by a provider function: `provider('model')` → `adapter`\n * All type resolution happens at the provider call site, not in this interface.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'eleven_ttv_v3')\n * - TProviderOptions: Provider-specific options (already resolved)\n */\nexport interface VoiceAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'voice'\n /** Adapter name identifier */\n readonly name: string\n /** The model this adapter is configured for */\n readonly model: TModel\n\n /**\n * @internal Type-only properties for inference. Not assigned at runtime.\n */\n '~types': {\n providerOptions: TProviderOptions\n }\n\n /**\n * Create a voice from a text description and/or reference audio\n */\n generateVoice: (\n options: VoiceGenerationOptions<TProviderOptions>,\n ) => Promise<VoiceResult>\n}\n\n/**\n * A VoiceAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyVoiceAdapter = VoiceAdapter<any, any>\n\n/**\n * Abstract base class for voice creation adapters.\n * Extend this class to implement a voice adapter for a specific provider.\n *\n * Generic parameters match VoiceAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseVoiceAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n> implements VoiceAdapter<TModel, TProviderOptions> {\n readonly kind = 'voice' as const\n abstract readonly name: string\n readonly model: TModel\n\n // Type-only property - never assigned at runtime\n declare '~types': {\n providerOptions: TProviderOptions\n }\n\n protected config: VoiceAdapterConfig\n\n constructor(model: TModel, config: VoiceAdapterConfig = {}) {\n this.config = config\n this.model = model\n }\n\n abstract generateVoice(\n options: VoiceGenerationOptions<TProviderOptions>,\n ): Promise<VoiceResult>\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"mappings":";;;;;;;AA6DA,IAAsB,mBAAtB,MAGoD;CAClD,OAAgB;CAEhB;CAOA;CAEA,YAAY,OAAe,SAA6B,CAAC,GAAG;EAC1D,KAAK,SAAS;EACd,KAAK,QAAQ;CACf;CAMA,aAA+B;EAC7B,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;CAC7E;AACF"}
@@ -0,0 +1,133 @@
1
+ import { DebugOption } from '../../logger/types.js';
2
+ import { GenerationMiddleware } from '../middleware/types.js';
3
+ import { VoiceAdapter } from './adapter.js';
4
+ import { StreamChunk, VoiceResult } from '../../types.js';
5
+ /** The adapter kind this activity handles */
6
+ export declare const kind: "voice";
7
+ /**
8
+ * Extract provider options from a VoiceAdapter via ~types.
9
+ */
10
+ export type VoiceProviderOptions<TAdapter> = TAdapter extends {
11
+ '~types': {
12
+ providerOptions: infer P extends object;
13
+ };
14
+ } ? P : object;
15
+ /**
16
+ * Options for the voice activity.
17
+ * The model is extracted from the adapter's model property.
18
+ *
19
+ * @template TAdapter - The voice adapter type
20
+ * @template TStream - Whether to stream the output
21
+ */
22
+ export interface VoiceActivityOptions<TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>, TStream extends boolean = false> {
23
+ /** The voice adapter to use (must be created with a model) */
24
+ adapter: TAdapter & {
25
+ kind: typeof kind;
26
+ };
27
+ /**
28
+ * Text description of the voice to create, for design-capable models
29
+ * (e.g. `'A warm, gravelly narrator in his sixties'`).
30
+ */
31
+ prompt?: string;
32
+ /**
33
+ * Reference audio of the speaker to clone, for clone-capable models.
34
+ * Accepts a base64 string, base64 data URL, File, Blob, or ArrayBuffer.
35
+ * Remote URLs are not accepted; read the file and pass the bytes.
36
+ */
37
+ referenceAudio?: string | File | Blob | ArrayBuffer;
38
+ /**
39
+ * Name to store the voice under in the provider's voice library. Check
40
+ * `saved` on each returned voice to see whether it was actually persisted.
41
+ */
42
+ name?: string;
43
+ /** Human-readable description stored alongside the voice */
44
+ description?: string;
45
+ /** Provider-specific options for voice creation */
46
+ modelOptions?: VoiceProviderOptions<TAdapter>;
47
+ /**
48
+ * Whether to stream the generation result.
49
+ * When true, returns an AsyncIterable<StreamChunk> for streaming transport.
50
+ * When false or not provided, returns a Promise<VoiceResult>.
51
+ *
52
+ * @default false
53
+ */
54
+ stream?: TStream;
55
+ /**
56
+ * Enable debug logging. Pass `true` to enable all categories, `false` to
57
+ * silence everything including errors, or a `DebugConfig` object for granular
58
+ * control and/or a custom `Logger`.
59
+ */
60
+ debug?: DebugOption;
61
+ /**
62
+ * Observe-only middleware notified on start, usage, success, and error. Pass
63
+ * `otelMiddleware()` to emit OpenTelemetry spans, or implement the
64
+ * `GenerationMiddleware` contract for a custom backend.
65
+ */
66
+ middleware?: Array<GenerationMiddleware>;
67
+ /** Stable conversation/thread id for correlating this run when persisted. */
68
+ threadId?: string;
69
+ /** Stable run id for correlating this run when persisted. */
70
+ runId?: string;
71
+ /**
72
+ * Maximum duration of this activity invocation in milliseconds.
73
+ * No SDK-wide default — choose a value suitable for the provider and job.
74
+ * Composed with {@link abortSignal}; the first abort wins.
75
+ */
76
+ timeout?: number;
77
+ /**
78
+ * Caller cancellation signal (request disconnects, job/runtime cancellation).
79
+ * Composed with {@link timeout} into an effective signal forwarded to the
80
+ * adapter. Request-specific — not stored on global provider client config.
81
+ */
82
+ abortSignal?: AbortSignal;
83
+ }
84
+ /**
85
+ * Result type for the voice activity.
86
+ * - If stream is true: AsyncIterable<StreamChunk>
87
+ * - Otherwise: Promise<VoiceResult>
88
+ */
89
+ export type VoiceActivityResult<TStream extends boolean = false> = TStream extends true ? AsyncIterable<StreamChunk> : Promise<VoiceResult>;
90
+ /**
91
+ * Voice activity - creates a reusable voice.
92
+ *
93
+ * Providers create voices in one of two ways, and some support both: design a
94
+ * new voice from a text description, or clone one from reference audio. Either
95
+ * way the result carries voice ids you pass back to `generateSpeech()`.
96
+ *
97
+ * @example Design a voice from a description
98
+ * ```ts
99
+ * import { generateVoice, generateSpeech } from '@tanstack/ai'
100
+ * import { elevenlabsVoiceDesign, elevenlabsSpeech } from '@tanstack/ai-elevenlabs'
101
+ *
102
+ * const designed = await generateVoice({
103
+ * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),
104
+ * prompt: 'A warm, gravelly narrator in his sixties with a slight Irish lilt',
105
+ * })
106
+ *
107
+ * const [preview] = designed.voices
108
+ * if (!preview) throw new Error('No voice candidates returned')
109
+ *
110
+ * const speech = await generateSpeech({
111
+ * adapter: elevenlabsSpeech('eleven_v3'),
112
+ * text: 'Once upon a time...',
113
+ * voice: preview.voiceId,
114
+ * })
115
+ * ```
116
+ *
117
+ * @example Save the voice to the provider's library
118
+ * ```ts
119
+ * const saved = await generateVoice({
120
+ * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),
121
+ * prompt: 'A bright, upbeat product demo host',
122
+ * name: 'Demo Host',
123
+ * description: 'Bright, upbeat, mid-30s',
124
+ * })
125
+ * ```
126
+ */
127
+ export declare function generateVoice<TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>, TStream extends boolean = false>(options: VoiceActivityOptions<TAdapter, TStream>): VoiceActivityResult<TStream>;
128
+ /**
129
+ * Create typed options for the generateVoice() function without executing.
130
+ */
131
+ export declare function createVoiceOptions<TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>, TStream extends boolean = false>(options: VoiceActivityOptions<TAdapter, TStream>): VoiceActivityOptions<TAdapter, TStream>;
132
+ export type { VoiceAdapter, VoiceAdapterConfig, AnyVoiceAdapter, } from './adapter.js';
133
+ export { BaseVoiceAdapter } from './adapter.js';