tanstack-ai-flowspeech 0.0.0-stage → 0.2.1

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 0.2.1 - 2026-10-27
4
+
5
+ - Use local error messages and reject reflected API credentials or private URLs in diagnostics.
6
+ - Preserve received HTTP status and Retry-After through interrupted response bodies; do not retry permanent failures.
7
+ - Restrict package contents and verify clean directory-publish metadata before release.
8
+
9
+ ## 0.2.0 - 2026-10-26
10
+
11
+ - Validate complete RIFF/WAVE chunks and 24 kHz mono 16-bit PCM data; preserve valid bytes, reject malformed downloads and allow download-only recovery.
12
+ - Correct quota documentation to canonical `subscription`, retaining optional `entitlement` compatibility.
13
+
14
+ - Replace the retired synchronous endpoint with public API v1 submit, poll and credential-free WAV download.
15
+ - Preserve the framework's buffered speech result contract and expose recovery request/job IDs.
16
+ - Add single/multi input support through the exported client, quota/voices queries, job lookup and explicit cancellation.
17
+ - Bound retries, response sizes, per-request timeouts and total deadlines; reuse submission UUID/body on retries.
18
+ - Respect five-second polling and longer Retry-After values; report failed/cancelled/deleted/malformed jobs explicitly.
19
+ - Reject unsupported legacy generation options, unsafe URLs, API credential overrides and redirects.
20
+ - Add fake-transport framework tests and build/packed-artifact smoke tests; no paid generation tests.
21
+ - Update server-only credential/subscription documentation and migration guidance.
22
+
23
+ 0.1.0 identifies the original repository code, not a verified npm release. Registry
24
+ availability was initially unverified/404 during the 2026-10-26 audit. Version
25
+ 0.2.0 was subsequently published; its historical metadata remains unchanged.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FlowSpeech contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,139 @@
1
- # Temporary Holding Version
1
+ # TanStack AI FlowSpeech Adapter
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ## 0.2.1 Security Update
4
+
5
+ HTTP and terminal-job errors use fixed local messages, including errors sent to the host logger. Bounded diagnostic tokens exclude the configured API key and API-only header values. An interrupted body retains HTTP status and Retry-After; permanent HTTP failures never retry. Errors may expose retryAfterMs alongside validated recovery IDs.
6
+
7
+ A server-side FlowSpeech public API v1 adapter for TanStack AI's `generateSpeech` activity. The adapter waits for the asynchronous job and downloads WAV audio, then encodes those bytes locally as base64 to preserve TanStack's `TTSResult`. The v1 API itself does not return base64.
8
+
9
+ ## Installation
10
+
11
+ Requires Node.js 22 or newer and `@tanstack/ai ^0.45.1`.
12
+
13
+ ```bash
14
+ npm install @tanstack/ai tanstack-ai-flowspeech@0.2.1
15
+ ```
16
+
17
+ To build and verify a source checkout:
18
+
19
+ ```bash
20
+ npm ci --ignore-scripts
21
+ npm test
22
+ npm run typecheck
23
+ npm run build
24
+ npm run test:dist
25
+ npm pack
26
+ ```
27
+
28
+ Set `FLOWSPEECH_API_KEY` in the server environment, or pass `apiKey` to the adapter. Never use browser code for API credentials.
29
+
30
+ ## Generate speech
31
+
32
+ ```ts
33
+ import { randomUUID } from 'node:crypto'
34
+ import { writeFile } from 'node:fs/promises'
35
+ import { generateSpeech } from '@tanstack/ai'
36
+ import { flowspeechSpeech, FlowSpeechClient } from 'tanstack-ai-flowspeech'
37
+
38
+ const requestId = randomUUID() // Persist this before submission.
39
+ const adapter = flowspeechSpeech('flowspeech-tts', { timeout: 600_000 })
40
+ const result = await generateSpeech({
41
+ adapter,
42
+ text: 'Here is the product update.',
43
+ voice: 'Kore',
44
+ format: 'wav',
45
+ modelOptions: { requestId },
46
+ })
47
+ await writeFile('speech.wav', Buffer.from(result.audio, 'base64'))
48
+ console.log(result.id) // The actual FlowSpeech job ID.
49
+ ```
50
+
51
+ Calling `adapter.generateSpeech` directly returns the extended `FlowSpeechTTSResult` with `requestId`, `jobId` and `creditUsage`. The framework's activity exposes its standard result type. A framework cancellation may surface as `AbortError` rather than the adapter's structured error, so persist the request UUID before starting.
52
+
53
+ ## Multiple speakers
54
+
55
+ Legacy two-voice scripts remain supported by translating labeled turns into v1 segments. Labels must be `Speaker1:` or `Speaker2:` and separated by whitespace:
56
+
57
+ ```ts
58
+ await generateSpeech({
59
+ adapter,
60
+ text: 'Speaker1: Welcome. Speaker2: Thank you.',
61
+ modelOptions: { speakerB: 'Puck', requestId: randomUUID() },
62
+ })
63
+ ```
64
+
65
+ Explicit segments are preferred for unambiguous multi-speaker scripts. Set `text: ''` and do not combine them with `speakerB`:
66
+
67
+ ```ts
68
+ await generateSpeech({
69
+ adapter,
70
+ text: '',
71
+ modelOptions: {
72
+ requestId: randomUUID(),
73
+ segments: [
74
+ { speaker: 'Alice', text: 'Welcome.', voiceName: 'Kore' },
75
+ { speaker: 'Bob', text: 'Thank you.', voiceName: 'Puck' },
76
+ ],
77
+ },
78
+ })
79
+ ```
80
+
81
+ ## Configuration and migration
82
+
83
+ Only `flowspeech-tts` is supported as a framework model identifier; it is not sent to the API. Numeric `speed`, non-WAV formats and unknown model options are rejected. `voiceName` remains a model-option fallback for the top-level voice.
84
+
85
+ Configuration accepts `apiKey`, `baseUrl`, `headers`, `fetch`, `timeoutMs` (or its retained `timeout` alias), `requestTimeoutMs`, `pollIntervalMs`, `maxRetries` and `maxAudioBytes`. `baseUrl` is now an HTTPS origin, not an endpoint path. The timeout default is now ten minutes for the entire operation. Headers are API-only; supply authentication through `apiKey` or the environment, not Authorization/Cookie header overrides.
86
+
87
+ ## v1 behavior and recovery
88
+
89
+ Requires a server-side developer API key and an active paid Basic, Pro or Scale subscription. Trials do not include API generation. Website cookies and plugin login tokens are not API credentials.
90
+
91
+ The API origin is `https://flowspeech.io`. Calls submit `{ input: ... }` to `POST /api/v1/tts/jobs` with a UUID `Idempotency-Key`, poll the returned job, then download its result. No model or legacy speaker fields are sent. Audio is WAV, 24000 Hz, mono, 16 bit. HTTP 200 from a status query is not generation success.
92
+
93
+ - Pending states: queued, running, merging, settling. Failed/cancelled jobs throw; a deleted success result throws `result_deleted`.
94
+ - Polling defaults to 5000 ms and cannot be configured faster. Longer `Retry-After` values, including HTTP dates and rate limits, take precedence.
95
+ - There are at most two transient retries per HTTP operation by default (configurable from zero to five). Submission retries preserve the exact UUID and JSON body.
96
+ - The total deadline includes submit, polling, retry waits, response-body reads and download. The general client default is 600000 ms; each request defaults to 30000 ms.
97
+ - Downloads use no API headers, Bearer token or cookies. HTTPS URLs with embedded credentials are rejected. API and storage redirects are rejected rather than followed. Downloads are bounded (64 MiB for the general client).
98
+ - Custom fetch implementations are trusted application code and must preserve the supplied abort, redirect and credential settings.
99
+ - Aborting or timing out stops local work; it does not cancel the server job or reverse a charge. Use `cancelJob` explicitly when cancellation is intended.
100
+
101
+ Each package exports `FlowSpeechClient` and `FlowSpeechError`. Save a fresh UUID before each new recording and pass it as `requestId`. Reuse it only with unchanged input. Error properties include `code`, `status`, `traceId`, `requestId` and `jobId` when known; do not automatically start a new job after a timeout or download error.
102
+
103
+ ```ts
104
+ const client = new FlowSpeechClient({ apiKey: process.env.FLOWSPEECH_API_KEY })
105
+ const quota = await client.getQuota()
106
+ console.log(quota.quota.available)
107
+ const voices = await client.listVoices()
108
+
109
+ // Use the UUID previously saved for the interrupted recording.
110
+ const job = await client.findJob(savedRequestId)
111
+ // Or: await client.getJob(savedJobId)
112
+ // Poll pending jobs no faster than five seconds, or resume generate() with
113
+ // the same UUID and unchanged input; it replays the existing job.
114
+ if (job.status === 'success') {
115
+ const bytes = await client.downloadJob(job) // never creates a recording
116
+ }
117
+ // await client.cancelJob(job.id)
118
+ ```
119
+
120
+ The quota response preserves canonical top-level `quota`, `subscription` and `limits`. An optional `entitlement` field is also retained for compatibility; it is not required. Result links grant public link access and should not be logged or shared unnecessarily. Deleting a result does not necessarily invalidate a previously copied link.
121
+
122
+ Downloads validate the actual RIFF/WAVE container, chunk lengths and padding,
123
+ PCM format (24000 Hz, mono, 16 bit), byte rate/block alignment, and complete
124
+ nonempty aligned sample data. Truncated, malformed or mismatched audio is
125
+ rejected even on HTTP 200. Bounded unknown chunks are skipped safely and valid
126
+ files are returned byte-for-byte unchanged. Validation remains within the
127
+ operation deadline; an invalid download never triggers another submission.
128
+
129
+ Full API contract: [FlowSpeech public API](https://flowspeech.io/docs/public-api).
130
+
131
+ ## Development and release status
132
+
133
+ Version 0.2.0 is the previous published API v1 release. Version 0.2.1 adds the safety fixes described above. Historical registry metadata and old installed versions are not changed by upgrading the source repository.
134
+
135
+ Install locked dependencies, then run the package checks and pack locally. Tests use only fake transports and synthetic WAV data; they do not spend generation credits. See `RELEASE_CHECKLIST.md` for maintainer release steps.
136
+
137
+ ## License
138
+
139
+ MIT
@@ -0,0 +1,119 @@
1
+ export type FlowSpeechInput = {
2
+ mode: 'single';
3
+ text: string;
4
+ voiceName: string;
5
+ } | {
6
+ mode: 'multi';
7
+ segments: Array<{
8
+ speaker: string;
9
+ text: string;
10
+ voiceName: string;
11
+ }>;
12
+ };
13
+ export interface FlowSpeechResult {
14
+ url: string;
15
+ mimeType: 'audio/wav';
16
+ sampleRate: 24000;
17
+ channels: 1;
18
+ bitsPerSample: 16;
19
+ }
20
+ export interface FlowSpeechJob {
21
+ id: string;
22
+ requestId: string;
23
+ status: 'queued' | 'running' | 'merging' | 'settling' | 'success' | 'failed' | 'cancelled';
24
+ result?: FlowSpeechResult | null;
25
+ resultDeleted?: boolean;
26
+ usage: {
27
+ billableCharacters: number;
28
+ reservedCredits: number;
29
+ chargedCredits: number;
30
+ };
31
+ error?: {
32
+ code: string;
33
+ message?: string;
34
+ retryable?: boolean;
35
+ } | null;
36
+ }
37
+ export interface FlowSpeechQuota {
38
+ quota: {
39
+ remaining: number;
40
+ reserved: number;
41
+ available: number;
42
+ };
43
+ /** Optional compatibility field; production v1 returns subscription. */
44
+ entitlement?: Record<string, unknown> | null;
45
+ /** Canonical public API v1 subscription metadata. */
46
+ subscription?: Record<string, unknown> | null;
47
+ limits: Record<string, unknown>;
48
+ }
49
+ export interface FlowSpeechVoice {
50
+ name: string;
51
+ description: string;
52
+ gender: string;
53
+ }
54
+ export interface FlowSpeechClientOptions {
55
+ apiKey?: string | undefined;
56
+ /** HTTPS API origin, not an endpoint path. */
57
+ baseUrl?: string | undefined;
58
+ /** API-only headers. Authentication, cookies and idempotency headers cannot be overridden. */
59
+ headers?: Record<string, string> | undefined;
60
+ fetch?: typeof fetch | undefined;
61
+ /** Total operation deadline, including requests, waits, retries and audio download. */
62
+ timeoutMs?: number | undefined;
63
+ requestTimeoutMs?: number | undefined;
64
+ /** At least 5000 ms. */
65
+ pollIntervalMs?: number | undefined;
66
+ /** Number of retries per HTTP operation, between zero and five. */
67
+ maxRetries?: number | undefined;
68
+ maxAudioBytes?: number | undefined;
69
+ }
70
+ export interface FlowSpeechOperationOptions {
71
+ requestId?: string | undefined;
72
+ signal?: AbortSignal | undefined;
73
+ }
74
+ export declare class FlowSpeechError extends Error {
75
+ readonly code: string;
76
+ readonly status?: number | undefined;
77
+ readonly traceId?: string | undefined;
78
+ readonly retryable: boolean;
79
+ readonly name = "FlowSpeechError";
80
+ requestId?: string;
81
+ jobId?: string;
82
+ retryAfterMs?: number;
83
+ constructor(message: string, code: string, status?: number | undefined, traceId?: string | undefined, retryable?: boolean);
84
+ }
85
+ export declare function rejectUnsupported(value: object, supported: readonly string[]): void;
86
+ export declare function normalizeApiOrigin(value?: string): string;
87
+ export declare class FlowSpeechClient {
88
+ private readonly key;
89
+ private readonly origin;
90
+ private readonly headers;
91
+ private readonly fetcher;
92
+ private readonly timeout;
93
+ private readonly requestTimeout;
94
+ private readonly interval;
95
+ private readonly retries;
96
+ private readonly maxAudio;
97
+ constructor(options?: FlowSpeechClientOptions);
98
+ private clean;
99
+ private job;
100
+ private operation;
101
+ private request;
102
+ private api;
103
+ generate(input: FlowSpeechInput, options?: FlowSpeechOperationOptions): Promise<{
104
+ audio: Uint8Array<ArrayBufferLike>;
105
+ job: FlowSpeechJob;
106
+ requestId: string;
107
+ requestBody: string;
108
+ headers: Record<string, string>;
109
+ }>;
110
+ private audio;
111
+ getJob(id: string, options?: FlowSpeechOperationOptions): Promise<FlowSpeechJob>;
112
+ findJob(requestId: string, options?: Omit<FlowSpeechOperationOptions, 'requestId'>): Promise<FlowSpeechJob>;
113
+ cancelJob(id: string, options?: FlowSpeechOperationOptions): Promise<FlowSpeechJob>;
114
+ /** Retries only the download of an existing successful job, never generation. */
115
+ downloadJob(current: FlowSpeechJob, options?: FlowSpeechOperationOptions): Promise<Uint8Array>;
116
+ getQuota(options?: FlowSpeechOperationOptions): Promise<FlowSpeechQuota>;
117
+ listVoices(options?: FlowSpeechOperationOptions): Promise<FlowSpeechVoice[]>;
118
+ }
119
+ //# sourceMappingURL=flowspeech-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowspeech-client.d.ts","sourceRoot":"","sources":["../src/flowspeech-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,503 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export class FlowSpeechError extends Error {
3
+ code;
4
+ status;
5
+ traceId;
6
+ retryable;
7
+ name = 'FlowSpeechError';
8
+ requestId;
9
+ jobId;
10
+ retryAfterMs;
11
+ constructor(message, code, status, traceId, retryable = false) {
12
+ super(message);
13
+ this.code = code;
14
+ this.status = status;
15
+ this.traceId = traceId;
16
+ this.retryable = retryable;
17
+ }
18
+ }
19
+ const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
20
+ const statuses = new Set(['queued', 'running', 'merging', 'settling', 'success', 'failed', 'cancelled']);
21
+ const forbiddenHeaders = /^(authorization|proxy-authorization|cookie|cookie2|host|idempotency-key|content-type|content-length|connection|transfer-encoding)$/i;
22
+ function fail(message, code = 'invalid_response') {
23
+ throw new FlowSpeechError(message, code);
24
+ }
25
+ function record(value) {
26
+ return !!value && typeof value === 'object' && !Array.isArray(value);
27
+ }
28
+ function uuid(value, label) {
29
+ if (typeof value !== 'string' || !uuidPattern.test(value))
30
+ fail('Invalid ' + label + ' UUID', 'invalid_request');
31
+ return value.toLowerCase();
32
+ }
33
+ function text(value, label) {
34
+ if (typeof value !== 'string' || !value.trim())
35
+ fail(label + ' must not be empty', 'invalid_request');
36
+ }
37
+ function number(value) {
38
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0;
39
+ }
40
+ function integer(value, label, min = 1, max = 2_147_483_647) {
41
+ if (!Number.isSafeInteger(value) || value < min || value > max)
42
+ fail('Invalid ' + label, 'invalid_configuration');
43
+ return value;
44
+ }
45
+ export function rejectUnsupported(value, supported) {
46
+ for (const [key, item] of Object.entries(value)) {
47
+ if (item !== undefined && !supported.includes(key))
48
+ fail('Unsupported FlowSpeech option: ' + key, 'unsupported_option');
49
+ }
50
+ }
51
+ export function normalizeApiOrigin(value = 'https://flowspeech.io') {
52
+ let url;
53
+ try {
54
+ url = new URL(value);
55
+ }
56
+ catch {
57
+ return fail('Invalid FlowSpeech baseUrl', 'invalid_configuration');
58
+ }
59
+ if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash || url.pathname !== '/') {
60
+ fail('FlowSpeech baseUrl must be an HTTPS origin without credentials, path, query or fragment', 'invalid_configuration');
61
+ }
62
+ return url.origin;
63
+ }
64
+ function audioUrl(value) {
65
+ if (typeof value !== 'string')
66
+ fail('Missing audio URL');
67
+ let url;
68
+ try {
69
+ url = new URL(value);
70
+ }
71
+ catch {
72
+ return fail('Invalid audio URL');
73
+ }
74
+ if (url.protocol !== 'https:' || url.username || url.password || url.hash)
75
+ fail('Unsafe audio URL');
76
+ return url.href;
77
+ }
78
+ function validateInput(input) {
79
+ if (!record(input))
80
+ fail('Invalid input', 'invalid_request');
81
+ if (input.mode === 'single') {
82
+ rejectUnsupported(input, ['mode', 'text', 'voiceName']);
83
+ text(input.text, 'text');
84
+ text(input.voiceName, 'voiceName');
85
+ if (input.text.length > 100_000)
86
+ fail('Text exceeds 100000 UTF-16 code units', 'invalid_request');
87
+ return { mode: 'single', text: input.text, voiceName: input.voiceName };
88
+ }
89
+ if (input.mode !== 'multi' || !Array.isArray(input.segments) || input.segments.length < 1 || input.segments.length > 1000) {
90
+ fail('Multi input requires 1 to 1000 segments', 'invalid_request');
91
+ }
92
+ rejectUnsupported(input, ['mode', 'segments']);
93
+ let length = 0;
94
+ const speakers = new Map();
95
+ const segments = input.segments.map(segment => {
96
+ if (!record(segment))
97
+ fail('Invalid segment', 'invalid_request');
98
+ rejectUnsupported(segment, ['speaker', 'text', 'voiceName']);
99
+ text(segment.speaker, 'speaker');
100
+ text(segment.text, 'text');
101
+ text(segment.voiceName, 'voiceName');
102
+ if (segment.speaker.length > 100)
103
+ fail('Speaker label exceeds 100 characters', 'invalid_request');
104
+ if (speakers.has(segment.speaker) && speakers.get(segment.speaker) !== segment.voiceName) {
105
+ fail('A speaker must use the same voice in every segment', 'invalid_request');
106
+ }
107
+ speakers.set(segment.speaker, segment.voiceName);
108
+ length += segment.text.length;
109
+ return { speaker: segment.speaker, text: segment.text, voiceName: segment.voiceName };
110
+ });
111
+ if (length > 100_000)
112
+ fail('Text exceeds 100000 UTF-16 code units', 'invalid_request');
113
+ return { mode: 'multi', segments };
114
+ }
115
+ function job(value, ctx, token) {
116
+ if (!record(value))
117
+ fail('Malformed job');
118
+ const id = uuid(value.id, 'job ID');
119
+ if (ctx.jobId && ctx.jobId !== id)
120
+ fail('Job ID changed unexpectedly');
121
+ ctx.jobId = id;
122
+ if (typeof value.requestId !== 'string' || !uuidPattern.test(value.requestId))
123
+ fail('Missing or invalid job request ID');
124
+ const requestId = value.requestId.toLowerCase();
125
+ if (ctx.requestId && ctx.requestId !== requestId)
126
+ fail('Request ID changed unexpectedly');
127
+ ctx.requestId = requestId;
128
+ if (typeof value.status !== 'string' || !statuses.has(value.status))
129
+ fail('Unknown job status');
130
+ if (!record(value.usage) || !['billableCharacters', 'reservedCredits', 'chargedCredits'].every(k => number(value.usage[k]))) {
131
+ fail('Missing or invalid job usage');
132
+ }
133
+ if (value.resultDeleted !== undefined && typeof value.resultDeleted !== 'boolean')
134
+ fail('Invalid resultDeleted flag');
135
+ if (value.status === 'success' && !(value.result === null && value.resultDeleted === true)) {
136
+ const result = value.result;
137
+ if (!record(result) || result.mimeType !== 'audio/wav' || result.sampleRate !== 24000 || result.channels !== 1 || result.bitsPerSample !== 16) {
138
+ fail('Missing or malformed WAV result');
139
+ }
140
+ audioUrl(result.url);
141
+ }
142
+ const error = value.error == null ? value.error : {
143
+ code: token(record(value.error) ? value.error.code : undefined) ?? 'job_error',
144
+ message: 'FlowSpeech job failed',
145
+ ...(record(value.error) && typeof value.error.retryable === 'boolean' ? { retryable: value.error.retryable } : {}),
146
+ };
147
+ const metadata = {};
148
+ for (const name of ['createdAt', 'updatedAt', 'deadlineAt']) {
149
+ const item = value[name];
150
+ if (typeof item === 'string' && item.length === 24 && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(item) && Number.isFinite(Date.parse(item)))
151
+ metadata[name] = item;
152
+ }
153
+ if (record(value.progress) && number(value.progress.completed) && number(value.progress.total)) {
154
+ metadata.progress = { completed: value.progress.completed, total: value.progress.total };
155
+ }
156
+ return {
157
+ ...metadata,
158
+ id, requestId, status: value.status, usage: value.usage,
159
+ ...(value.result !== undefined ? { result: value.result } : {}),
160
+ ...(value.resultDeleted !== undefined ? { resultDeleted: value.resultDeleted } : {}),
161
+ ...(value.error !== undefined ? { error } : {}),
162
+ };
163
+ }
164
+ function retryAfter(value) {
165
+ if (!value)
166
+ return 0;
167
+ const seconds = Number(value);
168
+ if (Number.isFinite(seconds) && seconds >= 0)
169
+ return seconds * 1000;
170
+ const date = Date.parse(value);
171
+ return Number.isFinite(date) ? Math.max(0, date - Date.now()) : 0;
172
+ }
173
+ async function abortable(promise, signal) {
174
+ if (signal.aborted)
175
+ throw signal.reason;
176
+ return new Promise((resolve, reject) => {
177
+ const abort = () => reject(signal.reason);
178
+ signal.addEventListener('abort', abort, { once: true });
179
+ promise.then(resolve, reject).finally(() => signal.removeEventListener('abort', abort));
180
+ });
181
+ }
182
+ async function wait(ms, signal) {
183
+ if (signal.aborted)
184
+ throw signal.reason;
185
+ let timer;
186
+ try {
187
+ await abortable(new Promise(resolve => { timer = setTimeout(resolve, Math.min(ms, 2_147_483_647)); }), signal);
188
+ }
189
+ finally {
190
+ clearTimeout(timer);
191
+ }
192
+ }
193
+ async function boundedBody(response, max, signal) {
194
+ const length = response.headers.get('content-length');
195
+ if (length && Number(length) > max) {
196
+ void response.body?.cancel().catch(() => { });
197
+ fail('FlowSpeech response exceeds ' + max + ' bytes', 'response_too_large');
198
+ }
199
+ if (!response.body)
200
+ fail('Empty response body');
201
+ const reader = response.body.getReader();
202
+ const chunks = [];
203
+ let size = 0;
204
+ try {
205
+ while (true) {
206
+ const { done, value } = await abortable(reader.read(), signal);
207
+ if (done)
208
+ break;
209
+ size += value.byteLength;
210
+ if (size > max)
211
+ fail('FlowSpeech response exceeds ' + max + ' bytes', 'response_too_large');
212
+ chunks.push(value);
213
+ }
214
+ }
215
+ catch (error) {
216
+ void reader.cancel().catch(() => { });
217
+ throw error;
218
+ }
219
+ finally {
220
+ reader.releaseLock();
221
+ }
222
+ const output = new Uint8Array(size);
223
+ let offset = 0;
224
+ for (const chunk of chunks) {
225
+ output.set(chunk, offset);
226
+ offset += chunk.byteLength;
227
+ }
228
+ return output;
229
+ }
230
+ // Validate bounded RIFF chunks without rewriting samples or discarding metadata.
231
+ async function validateWav(bytes, signal) {
232
+ const invalid = () => fail('Invalid WAV: expected complete 24000 Hz mono 16-bit PCM with nonempty aligned data', 'invalid_audio');
233
+ if (bytes.length < 12)
234
+ invalid();
235
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
236
+ const tag = (offset) => view.getUint32(offset);
237
+ if (tag(0) !== 0x52494646 || tag(8) !== 0x57415645 || view.getUint32(4, true) + 8 !== bytes.length)
238
+ invalid();
239
+ let offset = 12;
240
+ let formatSeen = false;
241
+ let dataSeen = false;
242
+ let chunks = 0;
243
+ while (offset < bytes.length) {
244
+ if (signal.aborted)
245
+ throw signal.reason;
246
+ // Let cancellation/deadline timers run even for many tiny unknown chunks.
247
+ if (++chunks % 1024 === 0)
248
+ await wait(0, signal);
249
+ if (bytes.length - offset < 8)
250
+ invalid();
251
+ const size = view.getUint32(offset + 4, true);
252
+ const start = offset + 8;
253
+ const end = start + size;
254
+ const next = end + (size & 1);
255
+ if (next > bytes.length)
256
+ invalid();
257
+ switch (tag(offset)) {
258
+ case 0x666d7420: // fmt
259
+ if (formatSeen || dataSeen || (size !== 16 && size !== 18))
260
+ invalid();
261
+ if (view.getUint16(start, true) !== 1 || view.getUint16(start + 2, true) !== 1 ||
262
+ view.getUint32(start + 4, true) !== 24000 || view.getUint32(start + 8, true) !== 48000 ||
263
+ view.getUint16(start + 12, true) !== 2 || view.getUint16(start + 14, true) !== 16 ||
264
+ (size === 18 && view.getUint16(start + 16, true) !== 0))
265
+ invalid();
266
+ formatSeen = true;
267
+ break;
268
+ case 0x64617461: // data
269
+ if (!formatSeen || dataSeen || size === 0 || size % 2 !== 0)
270
+ invalid();
271
+ dataSeen = true;
272
+ break;
273
+ }
274
+ offset = next;
275
+ }
276
+ if (!formatSeen || !dataSeen)
277
+ invalid();
278
+ if (signal.aborted)
279
+ throw signal.reason;
280
+ }
281
+ export class FlowSpeechClient {
282
+ key;
283
+ origin;
284
+ headers;
285
+ fetcher;
286
+ timeout;
287
+ requestTimeout;
288
+ interval;
289
+ retries;
290
+ maxAudio;
291
+ constructor(options = {}) {
292
+ if (typeof options !== 'object' || options === null || Array.isArray(options) || Object.values(options).some(value => value === null))
293
+ fail('Invalid FlowSpeech configuration', 'invalid_configuration');
294
+ if (options.headers !== undefined && (!record(options.headers) || Object.values(options.headers).some(value => typeof value !== 'string')))
295
+ fail('Invalid API headers', 'invalid_configuration');
296
+ const key = options.apiKey ?? process.env.FLOWSPEECH_API_KEY;
297
+ if (typeof key !== 'string' || !/^[\x21-\x7e]+$/.test(key))
298
+ fail('A valid server-side FlowSpeech API key is required', 'invalid_configuration');
299
+ this.key = key;
300
+ this.origin = normalizeApiOrigin(options.baseUrl);
301
+ this.headers = new Headers();
302
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
303
+ if (forbiddenHeaders.test(name))
304
+ fail('Reserved FlowSpeech header: ' + name, 'invalid_configuration');
305
+ try {
306
+ this.headers.set(name, value);
307
+ }
308
+ catch {
309
+ fail('Invalid API header', 'invalid_configuration');
310
+ }
311
+ }
312
+ this.fetcher = options.fetch ?? globalThis.fetch;
313
+ if (typeof this.fetcher !== 'function')
314
+ fail('A fetch implementation is required', 'invalid_configuration');
315
+ this.timeout = integer(options.timeoutMs ?? 600_000, 'timeoutMs');
316
+ this.requestTimeout = integer(options.requestTimeoutMs ?? 30_000, 'requestTimeoutMs');
317
+ this.interval = integer(options.pollIntervalMs ?? 5000, 'pollIntervalMs', 5000);
318
+ this.retries = integer(options.maxRetries ?? 2, 'maxRetries', 0, 5);
319
+ this.maxAudio = integer(options.maxAudioBytes ?? 64 * 1024 * 1024, 'maxAudioBytes');
320
+ }
321
+ clean(value) {
322
+ if (typeof value !== 'string' || value.length < 1 || value.length > 128 || /[^A-Za-z0-9_-]/.test(value) || value.includes(this.key))
323
+ return undefined;
324
+ for (const secret of this.headers.values())
325
+ if (secret && value.includes(secret))
326
+ return undefined;
327
+ return value;
328
+ }
329
+ job(value, ctx) {
330
+ return job(value, ctx, value => this.clean(value));
331
+ }
332
+ async operation(options, fn, jobId) {
333
+ const controller = new AbortController();
334
+ const cancel = () => controller.abort(new FlowSpeechError('FlowSpeech operation aborted; the server job was not cancelled', 'aborted'));
335
+ options.signal?.addEventListener('abort', cancel, { once: true });
336
+ if (options.signal?.aborted)
337
+ cancel();
338
+ const timer = setTimeout(() => controller.abort(new FlowSpeechError('FlowSpeech total deadline exceeded; recover with the same request or job ID', 'deadline_exceeded')), this.timeout);
339
+ const ctx = { signal: controller.signal };
340
+ try {
341
+ if (options.requestId !== undefined)
342
+ ctx.requestId = uuid(options.requestId, 'request ID');
343
+ if (jobId !== undefined)
344
+ ctx.jobId = uuid(jobId, 'job ID');
345
+ if (ctx.signal.aborted)
346
+ throw ctx.signal.reason;
347
+ return await abortable(fn(ctx), ctx.signal);
348
+ }
349
+ catch (error) {
350
+ const safe = error instanceof FlowSpeechError ? error : new FlowSpeechError('FlowSpeech request failed', 'network_error', undefined, undefined, true);
351
+ if (ctx.requestId)
352
+ safe.requestId = ctx.requestId;
353
+ if (ctx.jobId)
354
+ safe.jobId = ctx.jobId;
355
+ throw safe;
356
+ }
357
+ finally {
358
+ clearTimeout(timer);
359
+ options.signal?.removeEventListener('abort', cancel);
360
+ }
361
+ }
362
+ async request(url, init, ctx, download = false) {
363
+ for (let attempt = 0;; attempt++) {
364
+ if (ctx.signal.aborted)
365
+ throw ctx.signal.reason;
366
+ const controller = new AbortController();
367
+ const abort = () => controller.abort(ctx.signal.reason);
368
+ ctx.signal.addEventListener('abort', abort, { once: true });
369
+ const timer = setTimeout(() => controller.abort(new FlowSpeechError('FlowSpeech request timed out', 'request_timeout', undefined, undefined, true)), this.requestTimeout);
370
+ let delay = this.interval;
371
+ let response;
372
+ try {
373
+ response = await abortable(this.fetcher(url, {
374
+ ...init, signal: controller.signal, redirect: 'manual', credentials: 'omit', referrerPolicy: 'no-referrer',
375
+ }), controller.signal);
376
+ if (response.redirected || (response.status >= 300 && response.status < 400)) {
377
+ void response.body?.cancel().catch(() => { });
378
+ fail('Unexpected redirect rejected', 'unexpected_redirect');
379
+ }
380
+ delay = Math.max(this.interval, retryAfter(response.headers.get('retry-after')));
381
+ if (download && !response.ok) {
382
+ void response.body?.cancel().catch(() => { });
383
+ throw new FlowSpeechError('FlowSpeech audio download failed (HTTP ' + response.status + ')', 'download_error', response.status, undefined, response.status === 429 || response.status >= 500);
384
+ }
385
+ const bytes = !response.ok && !response.body ? new Uint8Array()
386
+ : await boundedBody(response, download ? this.maxAudio : 1024 * 1024, controller.signal);
387
+ if (download) {
388
+ await validateWav(bytes, controller.signal);
389
+ return bytes;
390
+ }
391
+ let value;
392
+ try {
393
+ value = JSON.parse(new TextDecoder().decode(bytes));
394
+ }
395
+ catch {
396
+ if (!response.ok)
397
+ throw new FlowSpeechError('FlowSpeech API error (HTTP ' + response.status + ')', 'http_error', response.status, undefined, response.status === 429 || response.status >= 500);
398
+ fail('Malformed API JSON');
399
+ }
400
+ if (!response.ok) {
401
+ const error = record(value) && record(value.error) ? value.error : {};
402
+ const code = this.clean(error.code) ?? 'http_error';
403
+ const traceId = record(value) ? this.clean(value.traceId) : undefined;
404
+ throw new FlowSpeechError('FlowSpeech API error (HTTP ' + response.status + ')', code, response.status, traceId, error.retryable !== false && (response.status === 429 || response.status >= 500));
405
+ }
406
+ return { value, retryAfter: delay, headers: Object.fromEntries(response.headers) };
407
+ }
408
+ catch (error) {
409
+ if (ctx.signal.aborted)
410
+ throw ctx.signal.reason;
411
+ let safe = error instanceof FlowSpeechError ? error
412
+ : controller.signal.aborted ? controller.signal.reason
413
+ : new FlowSpeechError('FlowSpeech network request failed', download ? 'download_error' : 'network_error', undefined, undefined, true);
414
+ // Headers remain authoritative even if the body stream or its cleanup fails.
415
+ if (response && safe.status === undefined) {
416
+ safe = new FlowSpeechError(safe.message, safe.code, response.status, safe.traceId, safe.retryable && (response.ok || response.status === 429 || response.status >= 500));
417
+ }
418
+ if (response)
419
+ safe.retryAfterMs = delay;
420
+ if (!safe.retryable || attempt >= this.retries)
421
+ throw safe;
422
+ }
423
+ finally {
424
+ clearTimeout(timer);
425
+ ctx.signal.removeEventListener('abort', abort);
426
+ }
427
+ await wait(delay, ctx.signal);
428
+ }
429
+ }
430
+ async api(path, ctx, body, method = 'GET') {
431
+ const headers = new Headers(this.headers);
432
+ headers.set('Authorization', 'Bearer ' + this.key);
433
+ headers.set('Accept', 'application/json');
434
+ if (body !== undefined) {
435
+ headers.set('Content-Type', 'application/json');
436
+ headers.set('Idempotency-Key', ctx.requestId);
437
+ }
438
+ return await this.request(this.origin + '/api/v1' + path, { method, headers, ...(body === undefined ? {} : { body }) }, ctx);
439
+ }
440
+ async generate(input, options = {}) {
441
+ return this.operation({ ...options, requestId: options.requestId === undefined ? randomUUID() : options.requestId }, async (ctx) => {
442
+ const body = JSON.stringify({ input: validateInput(input) });
443
+ if (Buffer.byteLength(body) > 1024 * 1024)
444
+ fail('Input JSON exceeds 1 MiB', 'invalid_request');
445
+ let response = await this.api('/tts/jobs', ctx, body, 'POST');
446
+ let current = this.job(response.value, ctx);
447
+ while (!['success', 'failed', 'cancelled'].includes(current.status)) {
448
+ await wait(response.retryAfter, ctx.signal);
449
+ response = await this.api('/tts/jobs/' + ctx.jobId, ctx);
450
+ current = this.job(response.value, ctx);
451
+ }
452
+ const audio = await this.audio(current, ctx);
453
+ return { audio, job: current, requestId: ctx.requestId, requestBody: body, headers: response.headers };
454
+ });
455
+ }
456
+ async audio(current, ctx) {
457
+ if (current.status === 'failed' || current.status === 'cancelled') {
458
+ throw new FlowSpeechError('FlowSpeech job ' + current.status, this.clean(current.error?.code) ?? ('job_' + current.status));
459
+ }
460
+ if (current.status !== 'success')
461
+ fail('Job is not ready for download', 'job_not_ready');
462
+ if (current.resultDeleted)
463
+ fail('FlowSpeech result was deleted; no audio is available', 'result_deleted');
464
+ if (!current.result)
465
+ fail('Missing result');
466
+ return await this.request(audioUrl(current.result.url), { method: 'GET' }, ctx, true);
467
+ }
468
+ async getJob(id, options = {}) {
469
+ return this.operation(options, async (ctx) => this.job((await this.api('/tts/jobs/' + ctx.jobId, ctx)).value, ctx), id);
470
+ }
471
+ async findJob(requestId, options = {}) {
472
+ return this.operation({ ...options, requestId }, async (ctx) => this.job((await this.api('/tts/jobs?requestId=' + ctx.requestId, ctx)).value, ctx));
473
+ }
474
+ async cancelJob(id, options = {}) {
475
+ return this.operation(options, async (ctx) => this.job((await this.api('/tts/jobs/' + ctx.jobId + '/cancel', ctx, undefined, 'POST')).value, ctx), id);
476
+ }
477
+ /** Retries only the download of an existing successful job, never generation. */
478
+ async downloadJob(current, options = {}) {
479
+ return this.operation({ ...options, requestId: options.requestId ?? current.requestId }, async (ctx) => this.audio(this.job(current, ctx), ctx), current.id);
480
+ }
481
+ async getQuota(options = {}) {
482
+ return this.operation(options, async (ctx) => {
483
+ const { value } = await this.api('/quota', ctx);
484
+ if (!record(value) || !record(value.quota) || !record(value.limits) ||
485
+ !['remaining', 'reserved', 'available'].every(k => number(value.quota[k])))
486
+ fail('Malformed quota response');
487
+ for (const field of ['entitlement', 'subscription']) {
488
+ if (value[field] !== undefined && value[field] !== null && !record(value[field]))
489
+ fail('Malformed subscription entitlement');
490
+ }
491
+ return value;
492
+ });
493
+ }
494
+ async listVoices(options = {}) {
495
+ return this.operation(options, async (ctx) => {
496
+ const { value } = await this.api('/voices', ctx);
497
+ if (!record(value) || !Array.isArray(value.voices) || !value.voices.every(v => record(v) && typeof v.name === 'string' && v.name.trim() && typeof v.description === 'string' && typeof v.gender === 'string'))
498
+ fail('Malformed voices response');
499
+ return value.voices;
500
+ });
501
+ }
502
+ }
503
+ //# sourceMappingURL=flowspeech-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowspeech-client.js","sourceRoot":"","sources":["../src/flowspeech-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { BaseTTSAdapter } from '@tanstack/ai/adapters';
2
+ import type { TTSOptions, TTSResult } from '@tanstack/ai';
3
+ import { type FlowSpeechClientOptions, type FlowSpeechInput } from './flowspeech-client.js';
4
+ export * from './flowspeech-client.js';
5
+ export type FlowSpeechModel = 'flowspeech-tts' | (string & {});
6
+ export interface FlowSpeechSpeechProviderOptions {
7
+ voiceName?: string;
8
+ /** Compatibility parser for scripts labeled Speaker1: and Speaker2:. */
9
+ speakerB?: string;
10
+ segments?: Extract<FlowSpeechInput, {
11
+ mode: 'multi';
12
+ }>['segments'];
13
+ requestId?: string;
14
+ }
15
+ export interface FlowSpeechAdapterConfig extends FlowSpeechClientOptions {
16
+ /** Alias for timeoutMs; total operation deadline, not just the initial request. */
17
+ timeout?: number;
18
+ }
19
+ export interface FlowSpeechTTSResult extends TTSResult {
20
+ requestId: string;
21
+ jobId: string;
22
+ creditUsage: {
23
+ billableCharacters: number;
24
+ reservedCredits: number;
25
+ chargedCredits: number;
26
+ };
27
+ }
28
+ export declare class FlowSpeechSpeechAdapter<TModel extends FlowSpeechModel> extends BaseTTSAdapter<TModel, FlowSpeechSpeechProviderOptions> {
29
+ readonly name: "flowspeech";
30
+ private readonly client;
31
+ constructor(model: TModel, config?: FlowSpeechAdapterConfig);
32
+ generateSpeech(options: TTSOptions<FlowSpeechSpeechProviderOptions>): Promise<FlowSpeechTTSResult>;
33
+ }
34
+ export declare function flowspeechSpeech<TModel extends FlowSpeechModel>(model: TModel, config?: FlowSpeechAdapterConfig): FlowSpeechSpeechAdapter<TModel>;
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAwD,KAAK,uBAAuB,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAEjJ,cAAc,wBAAwB,CAAA;AACtC,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAC9D,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC,eAAe,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,UAAU,CAAC,CAAA;IAClE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AACD,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AACD,MAAM,WAAW,mBAAoB,SAAQ,SAAS;IACpD,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE;QAAE,kBAAkB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7F;AAcD,qBAAa,uBAAuB,CAAC,MAAM,SAAS,eAAe,CAAE,SAAQ,cAAc,CAAC,MAAM,EAAE,+BAA+B,CAAC;IAClI,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAC7B,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,uBAA4B;IAMzD,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,+BAA+B,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAuBzG;AACD,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,uBAAuB,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAEjJ"}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ import { BaseTTSAdapter } from '@tanstack/ai/adapters';
2
+ import { FlowSpeechClient, FlowSpeechError, rejectUnsupported } from './flowspeech-client.js';
3
+ export * from './flowspeech-client.js';
4
+ /** Preserve the legacy two-voice script surface, but emit explicit v1 segments. */
5
+ function scriptSegments(script, voiceName, speakerB) {
6
+ if (/\bSpeaker(?![12]:)\d+:/.test(script))
7
+ throw new FlowSpeechError('Only Speaker1: and Speaker2: labels are supported; use explicit segments for other speakers', 'invalid_request');
8
+ const matches = [...script.matchAll(/(?:^|\s)(Speaker[12]):\s*/g)];
9
+ if (!matches.length || script.slice(0, matches[0].index).trim())
10
+ throw new FlowSpeechError('Two-speaker scripts must begin with Speaker1: or Speaker2:', 'invalid_request');
11
+ return matches.map((match, index) => ({
12
+ speaker: match[1],
13
+ voiceName: match[1] === 'Speaker1' ? voiceName : speakerB,
14
+ text: script.slice(match.index + match[0].length, matches[index + 1]?.index ?? script.length).trim(),
15
+ }));
16
+ }
17
+ export class FlowSpeechSpeechAdapter extends BaseTTSAdapter {
18
+ name = 'flowspeech';
19
+ client;
20
+ constructor(model, config = {}) {
21
+ super(model, config);
22
+ if (model !== 'flowspeech-tts')
23
+ throw new FlowSpeechError('Unsupported FlowSpeech model identifier', 'unsupported_option');
24
+ if (config.timeout !== undefined && config.timeoutMs !== undefined && config.timeout !== config.timeoutMs)
25
+ throw new FlowSpeechError('timeout and timeoutMs disagree', 'invalid_configuration');
26
+ this.client = new FlowSpeechClient({ ...config, timeoutMs: config.timeoutMs ?? config.timeout });
27
+ }
28
+ async generateSpeech(options) {
29
+ const { logger } = options;
30
+ logger.request('activity=generateSpeech provider=flowspeech model=' + this.model, { provider: 'flowspeech', model: this.model });
31
+ try {
32
+ if (options.model !== this.model)
33
+ throw new FlowSpeechError('TTS model does not match the adapter', 'unsupported_option');
34
+ rejectUnsupported({ speed: options.speed }, []);
35
+ if (options.format !== undefined && options.format !== 'wav')
36
+ throw new FlowSpeechError('FlowSpeech v1 only supports WAV output', 'unsupported_option');
37
+ const modelOptions = options.modelOptions ?? {};
38
+ rejectUnsupported(modelOptions, ['voiceName', 'speakerB', 'segments', 'requestId']);
39
+ const voiceName = options.voice ?? modelOptions.voiceName ?? 'Kore';
40
+ if (modelOptions.segments !== undefined && (options.text.trim() || modelOptions.speakerB !== undefined))
41
+ throw new FlowSpeechError('Explicit segments require empty text and no speakerB', 'invalid_request');
42
+ const segments = modelOptions.segments ?? (modelOptions.speakerB === undefined ? undefined : scriptSegments(options.text, voiceName, modelOptions.speakerB));
43
+ const input = segments === undefined ? { mode: 'single', text: options.text, voiceName } : { mode: 'multi', segments };
44
+ const result = await this.client.generate(input, { requestId: modelOptions.requestId, signal: options.abortSignal });
45
+ return {
46
+ id: result.job.id, jobId: result.job.id, requestId: result.requestId, model: this.model,
47
+ audio: Buffer.from(result.audio).toString('base64'), format: 'wav', contentType: 'audio/wav', creditUsage: result.job.usage,
48
+ };
49
+ }
50
+ catch (error) {
51
+ logger.errors('flowspeech.generateSpeech fatal', { error, source: 'flowspeech.generateSpeech' });
52
+ throw error;
53
+ }
54
+ }
55
+ }
56
+ export function flowspeechSpeech(model, config) {
57
+ return new FlowSpeechSpeechAdapter(model, config);
58
+ }
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,69 @@
1
1
  {
2
2
  "name": "tanstack-ai-flowspeech",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.1",
4
+ "description": "FlowSpeech public API v1 asynchronous text-to-speech adapter for TanStack AI.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/*.js",
17
+ "dist/*.d.ts",
18
+ "dist/*.js.map",
19
+ "dist/*.d.ts.map",
20
+ "README.md",
21
+ "CHANGELOG.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "check:runtime": "node scripts/check-runtime.mjs",
26
+ "test:runtime": "node --test tests/runtime-guard.mjs",
27
+ "pretest": "npm run check:runtime",
28
+ "prebuild": "npm run check:runtime",
29
+ "pretypecheck": "npm run check:runtime",
30
+ "pretest:dist": "npm run check:runtime",
31
+ "preaudit:package": "npm run check:runtime",
32
+ "build": "tsc -p tsconfig.build.json",
33
+ "test": "vitest run",
34
+ "typecheck": "tsc --noEmit",
35
+ "prepublishOnly": "npm run check:runtime && npm run test:runtime && npm test && npm run typecheck && npm run build && npm run test:dist",
36
+ "test:dist": "node --test tests/artifact-smoke.mjs",
37
+ "prepack": "npm run build && npm run test:dist",
38
+ "audit:package": "node tests/package-audit.mjs"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/waeckerlinfederowicz66-sketch/tanstack-ai-flowspeech.git"
43
+ },
44
+ "homepage": "https://flowspeech.io/",
45
+ "bugs": {
46
+ "url": "https://github.com/waeckerlinfederowicz66-sketch/tanstack-ai-flowspeech/issues"
47
+ },
48
+ "keywords": [
49
+ "tanstack",
50
+ "tanstack-ai",
51
+ "flowspeech",
52
+ "text-to-speech",
53
+ "tts",
54
+ "ai",
55
+ "voice"
56
+ ],
57
+ "peerDependencies": {
58
+ "@tanstack/ai": "^0.45.1"
59
+ },
60
+ "devDependencies": {
61
+ "@tanstack/ai": "^0.45.1",
62
+ "typescript": "^5.9.2",
63
+ "vitest": "^3.2.4",
64
+ "@types/node": "24.13.3"
65
+ },
66
+ "engines": {
67
+ "node": ">=22"
68
+ }
69
+ }