@tanstack/ai 0.0.3 → 0.2.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.
- package/README.md +26 -0
- package/dist/esm/activities/chat/adapter.d.ts +100 -0
- package/dist/esm/activities/chat/adapter.js +14 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -0
- package/dist/esm/{utilities → activities/chat}/agent-loop-strategies.d.ts +4 -4
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +166 -0
- package/dist/esm/{core/chat.js → activities/chat/index.js} +131 -33
- package/dist/esm/activities/chat/index.js.map +1 -0
- package/dist/esm/{message-converters.d.ts → activities/chat/messages.d.ts} +1 -1
- package/dist/esm/{message-converters.js → activities/chat/messages.js} +7 -7
- package/dist/esm/activities/chat/messages.js.map +1 -0
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -0
- package/dist/esm/{stream → activities/chat/stream}/message-updaters.d.ts +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -0
- package/dist/esm/{stream → activities/chat/stream}/processor.d.ts +1 -1
- package/dist/esm/{stream → activities/chat/stream}/processor.js +1 -1
- package/dist/esm/activities/chat/stream/processor.js.map +1 -0
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -0
- package/dist/esm/{stream → activities/chat/stream}/types.d.ts +2 -9
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +116 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +115 -0
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
- package/dist/esm/{tools → activities/chat/tools}/tool-calls.d.ts +1 -1
- package/dist/esm/{tools → activities/chat/tools}/tool-calls.js +23 -30
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -0
- package/dist/esm/{tools → activities/chat/tools}/tool-definition.d.ts +22 -18
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -0
- package/dist/esm/activities/generateImage/adapter.d.ts +68 -0
- package/dist/esm/activities/generateImage/adapter.js +14 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -0
- package/dist/esm/activities/generateImage/index.d.ts +89 -0
- package/dist/esm/activities/generateImage/index.js +15 -0
- package/dist/esm/activities/generateImage/index.js.map +1 -0
- package/dist/esm/activities/generateSpeech/adapter.d.ts +62 -0
- package/dist/esm/activities/generateSpeech/adapter.js +14 -0
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -0
- package/dist/esm/activities/generateSpeech/index.d.ts +69 -0
- package/dist/esm/activities/generateSpeech/index.js +15 -0
- package/dist/esm/activities/generateSpeech/index.js.map +1 -0
- package/dist/esm/activities/generateTranscription/adapter.d.ts +62 -0
- package/dist/esm/activities/generateTranscription/adapter.js +14 -0
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -0
- package/dist/esm/activities/generateTranscription/index.d.ts +71 -0
- package/dist/esm/activities/generateTranscription/index.js +15 -0
- package/dist/esm/activities/generateTranscription/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/adapter.d.ts +80 -0
- package/dist/esm/activities/generateVideo/adapter.js +14 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -0
- package/dist/esm/activities/generateVideo/index.d.ts +136 -0
- package/dist/esm/activities/generateVideo/index.js +47 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -0
- package/dist/esm/activities/index.d.ts +22 -0
- package/dist/esm/activities/index.js +34 -0
- package/dist/esm/activities/index.js.map +1 -0
- package/dist/esm/activities/summarize/adapter.d.ts +74 -0
- package/dist/esm/activities/summarize/adapter.js +14 -0
- package/dist/esm/activities/summarize/adapter.js.map +1 -0
- package/dist/esm/activities/summarize/index.d.ts +100 -0
- package/dist/esm/activities/summarize/index.js +90 -0
- package/dist/esm/activities/summarize/index.js.map +1 -0
- package/dist/esm/event-client.d.ts +4 -18
- package/dist/esm/event-client.js.map +1 -1
- package/dist/esm/index.d.ts +16 -14
- package/dist/esm/index.js +29 -20
- package/dist/esm/stream-to-response.d.ts +95 -0
- package/dist/esm/stream-to-response.js +118 -0
- package/dist/esm/stream-to-response.js.map +1 -0
- package/dist/esm/types.d.ts +370 -133
- package/package.json +7 -6
- package/src/activities/chat/adapter.ts +150 -0
- package/src/{utilities → activities/chat}/agent-loop-strategies.ts +4 -4
- package/src/{core/chat.ts → activities/chat/index.ts} +435 -79
- package/src/{message-converters.ts → activities/chat/messages.ts} +10 -13
- package/src/{stream → activities/chat/stream}/message-updaters.ts +1 -1
- package/src/{stream → activities/chat/stream}/processor.ts +2 -5
- package/src/{stream → activities/chat/stream}/types.ts +8 -18
- package/src/activities/chat/tools/schema-converter.ts +332 -0
- package/src/{tools → activities/chat/tools}/tool-calls.ts +63 -44
- package/src/{tools → activities/chat/tools}/tool-definition.ts +51 -38
- package/src/activities/generateImage/adapter.ts +104 -0
- package/src/activities/generateImage/index.ts +162 -0
- package/src/activities/generateSpeech/adapter.ts +87 -0
- package/src/activities/generateSpeech/index.ts +122 -0
- package/src/activities/generateTranscription/adapter.ts +89 -0
- package/src/activities/generateTranscription/index.ts +132 -0
- package/src/activities/generateVideo/adapter.ts +116 -0
- package/src/activities/generateVideo/index.ts +261 -0
- package/src/activities/index.ts +164 -0
- package/src/activities/summarize/adapter.ts +107 -0
- package/src/activities/summarize/index.ts +287 -0
- package/src/event-client.ts +5 -21
- package/src/index.ts +60 -15
- package/src/stream-to-response.ts +237 -0
- package/src/types.ts +429 -284
- package/dist/esm/base-adapter.d.ts +0 -36
- package/dist/esm/base-adapter.js +0 -12
- package/dist/esm/base-adapter.js.map +0 -1
- package/dist/esm/core/chat-common-options.d.ts +0 -52
- package/dist/esm/core/chat.d.ts +0 -30
- package/dist/esm/core/chat.js.map +0 -1
- package/dist/esm/core/embedding.d.ts +0 -8
- package/dist/esm/core/embedding.js +0 -33
- package/dist/esm/core/embedding.js.map +0 -1
- package/dist/esm/core/summarize.d.ts +0 -9
- package/dist/esm/core/summarize.js +0 -36
- package/dist/esm/core/summarize.js.map +0 -1
- package/dist/esm/message-converters.js.map +0 -1
- package/dist/esm/stream/json-parser.js.map +0 -1
- package/dist/esm/stream/message-updaters.js.map +0 -1
- package/dist/esm/stream/processor.js.map +0 -1
- package/dist/esm/stream/strategies.js.map +0 -1
- package/dist/esm/tools/tool-calls.js.map +0 -1
- package/dist/esm/tools/tool-definition.js.map +0 -1
- package/dist/esm/tools/zod-converter.d.ts +0 -30
- package/dist/esm/tools/zod-converter.js +0 -36
- package/dist/esm/tools/zod-converter.js.map +0 -1
- package/dist/esm/utilities/agent-loop-strategies.js.map +0 -1
- package/dist/esm/utilities/chat-options.d.ts +0 -6
- package/dist/esm/utilities/chat-options.js +0 -7
- package/dist/esm/utilities/chat-options.js.map +0 -1
- package/dist/esm/utilities/messages.d.ts +0 -30
- package/dist/esm/utilities/messages.js +0 -7
- package/dist/esm/utilities/messages.js.map +0 -1
- package/dist/esm/utilities/stream-to-response.d.ts +0 -48
- package/dist/esm/utilities/stream-to-response.js +0 -62
- package/dist/esm/utilities/stream-to-response.js.map +0 -1
- package/src/base-adapter.ts +0 -86
- package/src/core/chat-common-options.ts +0 -55
- package/src/core/embedding.ts +0 -54
- package/src/core/summarize.ts +0 -56
- package/src/tools/zod-converter.ts +0 -85
- package/src/utilities/chat-options.ts +0 -35
- package/src/utilities/messages.ts +0 -63
- package/src/utilities/stream-to-response.ts +0 -116
- /package/dist/esm/{utilities → activities/chat}/agent-loop-strategies.js +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/index.d.ts +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/json-parser.d.ts +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/json-parser.js +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/message-updaters.js +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/strategies.d.ts +0 -0
- /package/dist/esm/{stream → activities/chat/stream}/strategies.js +0 -0
- /package/dist/esm/{tools → activities/chat/tools}/tool-definition.js +0 -0
- /package/src/{stream → activities/chat/stream}/index.ts +0 -0
- /package/src/{stream → activities/chat/stream}/json-parser.ts +0 -0
- /package/src/{stream → activities/chat/stream}/strategies.ts +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { TranscriptionOptions, TranscriptionResult } from '../../types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for transcription adapter instances
|
|
5
|
+
*/
|
|
6
|
+
export interface TranscriptionAdapterConfig {
|
|
7
|
+
apiKey?: string
|
|
8
|
+
baseUrl?: string
|
|
9
|
+
timeout?: number
|
|
10
|
+
maxRetries?: number
|
|
11
|
+
headers?: Record<string, string>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transcription adapter interface with pre-resolved generics.
|
|
16
|
+
*
|
|
17
|
+
* An adapter is created by a provider function: `provider('model')` → `adapter`
|
|
18
|
+
* All type resolution happens at the provider call site, not in this interface.
|
|
19
|
+
*
|
|
20
|
+
* Generic parameters:
|
|
21
|
+
* - TModel: The specific model name (e.g., 'whisper-1')
|
|
22
|
+
* - TProviderOptions: Provider-specific options (already resolved)
|
|
23
|
+
*/
|
|
24
|
+
export interface TranscriptionAdapter<
|
|
25
|
+
TModel extends string = string,
|
|
26
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
27
|
+
> {
|
|
28
|
+
/** Discriminator for adapter kind - used to determine API shape */
|
|
29
|
+
readonly kind: 'transcription'
|
|
30
|
+
/** Adapter name identifier */
|
|
31
|
+
readonly name: string
|
|
32
|
+
/** The model this adapter is configured for */
|
|
33
|
+
readonly model: TModel
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @internal Type-only properties for inference. Not assigned at runtime.
|
|
37
|
+
*/
|
|
38
|
+
'~types': {
|
|
39
|
+
providerOptions: TProviderOptions
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Transcribe audio to text
|
|
44
|
+
*/
|
|
45
|
+
transcribe: (
|
|
46
|
+
options: TranscriptionOptions<TProviderOptions>,
|
|
47
|
+
) => Promise<TranscriptionResult>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A TranscriptionAdapter with any/unknown type parameters.
|
|
52
|
+
* Useful as a constraint in generic functions and interfaces.
|
|
53
|
+
*/
|
|
54
|
+
export type AnyTranscriptionAdapter = TranscriptionAdapter<any, any>
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Abstract base class for audio transcription adapters.
|
|
58
|
+
* Extend this class to implement a transcription adapter for a specific provider.
|
|
59
|
+
*
|
|
60
|
+
* Generic parameters match TranscriptionAdapter - all pre-resolved by the provider function.
|
|
61
|
+
*/
|
|
62
|
+
export abstract class BaseTranscriptionAdapter<
|
|
63
|
+
TModel extends string = string,
|
|
64
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
65
|
+
> implements TranscriptionAdapter<TModel, TProviderOptions> {
|
|
66
|
+
readonly kind = 'transcription' as const
|
|
67
|
+
abstract readonly name: string
|
|
68
|
+
readonly model: TModel
|
|
69
|
+
|
|
70
|
+
// Type-only property - never assigned at runtime
|
|
71
|
+
declare '~types': {
|
|
72
|
+
providerOptions: TProviderOptions
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
protected config: TranscriptionAdapterConfig
|
|
76
|
+
|
|
77
|
+
constructor(config: TranscriptionAdapterConfig = {}, model: TModel) {
|
|
78
|
+
this.config = config
|
|
79
|
+
this.model = model
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
abstract transcribe(
|
|
83
|
+
options: TranscriptionOptions<TProviderOptions>,
|
|
84
|
+
): Promise<TranscriptionResult>
|
|
85
|
+
|
|
86
|
+
protected generateId(): string {
|
|
87
|
+
return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transcription Activity
|
|
3
|
+
*
|
|
4
|
+
* Transcribes audio to text using speech-to-text models.
|
|
5
|
+
* This is a self-contained module with implementation, types, and JSDoc.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TranscriptionAdapter } from './adapter'
|
|
9
|
+
import type { TranscriptionResult } from '../../types'
|
|
10
|
+
|
|
11
|
+
// ===========================
|
|
12
|
+
// Activity Kind
|
|
13
|
+
// ===========================
|
|
14
|
+
|
|
15
|
+
/** The adapter kind this activity handles */
|
|
16
|
+
export const kind = 'transcription' as const
|
|
17
|
+
|
|
18
|
+
// ===========================
|
|
19
|
+
// Type Extraction Helpers
|
|
20
|
+
// ===========================
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Extract provider options from a TranscriptionAdapter via ~types.
|
|
24
|
+
*/
|
|
25
|
+
export type TranscriptionProviderOptions<TAdapter> =
|
|
26
|
+
TAdapter extends TranscriptionAdapter<any, any>
|
|
27
|
+
? TAdapter['~types']['providerOptions']
|
|
28
|
+
: object
|
|
29
|
+
|
|
30
|
+
// ===========================
|
|
31
|
+
// Activity Options Type
|
|
32
|
+
// ===========================
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Options for the transcription activity.
|
|
36
|
+
* The model is extracted from the adapter's model property.
|
|
37
|
+
*
|
|
38
|
+
* @template TAdapter - The transcription adapter type
|
|
39
|
+
*/
|
|
40
|
+
export interface TranscriptionActivityOptions<
|
|
41
|
+
TAdapter extends TranscriptionAdapter<string, object>,
|
|
42
|
+
> {
|
|
43
|
+
/** The transcription adapter to use (must be created with a model) */
|
|
44
|
+
adapter: TAdapter & { kind: typeof kind }
|
|
45
|
+
/** The audio data to transcribe - can be base64 string, File, Blob, or Buffer */
|
|
46
|
+
audio: string | File | Blob | ArrayBuffer
|
|
47
|
+
/** The language of the audio in ISO-639-1 format (e.g., 'en') */
|
|
48
|
+
language?: string
|
|
49
|
+
/** An optional prompt to guide the transcription */
|
|
50
|
+
prompt?: string
|
|
51
|
+
/** The format of the transcription output */
|
|
52
|
+
responseFormat?: 'json' | 'text' | 'srt' | 'verbose_json' | 'vtt'
|
|
53
|
+
/** Provider-specific options for transcription */
|
|
54
|
+
modelOptions?: TranscriptionProviderOptions<TAdapter>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ===========================
|
|
58
|
+
// Activity Result Type
|
|
59
|
+
// ===========================
|
|
60
|
+
|
|
61
|
+
/** Result type for the transcription activity */
|
|
62
|
+
export type TranscriptionActivityResult = Promise<TranscriptionResult>
|
|
63
|
+
|
|
64
|
+
// ===========================
|
|
65
|
+
// Activity Implementation
|
|
66
|
+
// ===========================
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Transcription activity - converts audio to text.
|
|
70
|
+
*
|
|
71
|
+
* Uses AI speech-to-text models to transcribe audio content.
|
|
72
|
+
*
|
|
73
|
+
* @example Transcribe an audio file
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { generateTranscription } from '@tanstack/ai'
|
|
76
|
+
* import { openaiTranscription } from '@tanstack/ai-openai'
|
|
77
|
+
*
|
|
78
|
+
* const result = await generateTranscription({
|
|
79
|
+
* adapter: openaiTranscription('whisper-1'),
|
|
80
|
+
* audio: audioFile, // File, Blob, or base64 string
|
|
81
|
+
* language: 'en'
|
|
82
|
+
* })
|
|
83
|
+
*
|
|
84
|
+
* console.log(result.text)
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example With verbose output for timestamps
|
|
88
|
+
* ```ts
|
|
89
|
+
* const result = await generateTranscription({
|
|
90
|
+
* adapter: openaiTranscription('whisper-1'),
|
|
91
|
+
* audio: audioFile,
|
|
92
|
+
* responseFormat: 'verbose_json'
|
|
93
|
+
* })
|
|
94
|
+
*
|
|
95
|
+
* result.segments?.forEach(segment => {
|
|
96
|
+
* console.log(`[${segment.start}s - ${segment.end}s]: ${segment.text}`)
|
|
97
|
+
* })
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export async function generateTranscription<
|
|
101
|
+
TAdapter extends TranscriptionAdapter<string, object>,
|
|
102
|
+
>(
|
|
103
|
+
options: TranscriptionActivityOptions<TAdapter>,
|
|
104
|
+
): TranscriptionActivityResult {
|
|
105
|
+
const { adapter, ...rest } = options
|
|
106
|
+
const model = adapter.model
|
|
107
|
+
|
|
108
|
+
return adapter.transcribe({ ...rest, model })
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ===========================
|
|
112
|
+
// Options Factory
|
|
113
|
+
// ===========================
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Create typed options for the generateTranscription() function without executing.
|
|
117
|
+
*/
|
|
118
|
+
export function createTranscriptionOptions<
|
|
119
|
+
TAdapter extends TranscriptionAdapter<string, object>,
|
|
120
|
+
>(
|
|
121
|
+
options: TranscriptionActivityOptions<TAdapter>,
|
|
122
|
+
): TranscriptionActivityOptions<TAdapter> {
|
|
123
|
+
return options
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Re-export adapter types
|
|
127
|
+
export type {
|
|
128
|
+
TranscriptionAdapter,
|
|
129
|
+
TranscriptionAdapterConfig,
|
|
130
|
+
AnyTranscriptionAdapter,
|
|
131
|
+
} from './adapter'
|
|
132
|
+
export { BaseTranscriptionAdapter } from './adapter'
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
VideoGenerationOptions,
|
|
3
|
+
VideoJobResult,
|
|
4
|
+
VideoStatusResult,
|
|
5
|
+
VideoUrlResult,
|
|
6
|
+
} from '../../types'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for video adapter instances
|
|
10
|
+
*
|
|
11
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
12
|
+
*/
|
|
13
|
+
export interface VideoAdapterConfig {
|
|
14
|
+
apiKey?: string
|
|
15
|
+
baseUrl?: string
|
|
16
|
+
timeout?: number
|
|
17
|
+
maxRetries?: number
|
|
18
|
+
headers?: Record<string, string>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Video adapter interface with pre-resolved generics.
|
|
23
|
+
*
|
|
24
|
+
* An adapter is created by a provider function: `provider('model')` → `adapter`
|
|
25
|
+
* All type resolution happens at the provider call site, not in this interface.
|
|
26
|
+
*
|
|
27
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
28
|
+
*
|
|
29
|
+
* Generic parameters:
|
|
30
|
+
* - TModel: The specific model name (e.g., 'sora-2')
|
|
31
|
+
* - TProviderOptions: Provider-specific options (already resolved)
|
|
32
|
+
*/
|
|
33
|
+
export interface VideoAdapter<
|
|
34
|
+
TModel extends string = string,
|
|
35
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
36
|
+
> {
|
|
37
|
+
/** Discriminator for adapter kind - used to determine API shape */
|
|
38
|
+
readonly kind: 'video'
|
|
39
|
+
/** Adapter name identifier */
|
|
40
|
+
readonly name: string
|
|
41
|
+
/** The model this adapter is configured for */
|
|
42
|
+
readonly model: TModel
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @internal Type-only properties for inference. Not assigned at runtime.
|
|
46
|
+
*/
|
|
47
|
+
'~types': {
|
|
48
|
+
providerOptions: TProviderOptions
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a new video generation job.
|
|
53
|
+
* Returns a job ID that can be used to poll for status and retrieve the video.
|
|
54
|
+
*/
|
|
55
|
+
createVideoJob: (
|
|
56
|
+
options: VideoGenerationOptions<TProviderOptions>,
|
|
57
|
+
) => Promise<VideoJobResult>
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get the current status of a video generation job.
|
|
61
|
+
*/
|
|
62
|
+
getVideoStatus: (jobId: string) => Promise<VideoStatusResult>
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the URL to download/view the generated video.
|
|
66
|
+
* Should only be called after status is 'completed'.
|
|
67
|
+
*/
|
|
68
|
+
getVideoUrl: (jobId: string) => Promise<VideoUrlResult>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A VideoAdapter with any/unknown type parameters.
|
|
73
|
+
* Useful as a constraint in generic functions and interfaces.
|
|
74
|
+
*/
|
|
75
|
+
export type AnyVideoAdapter = VideoAdapter<any, any>
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Abstract base class for video generation adapters.
|
|
79
|
+
* Extend this class to implement a video adapter for a specific provider.
|
|
80
|
+
*
|
|
81
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
82
|
+
*
|
|
83
|
+
* Generic parameters match VideoAdapter - all pre-resolved by the provider function.
|
|
84
|
+
*/
|
|
85
|
+
export abstract class BaseVideoAdapter<
|
|
86
|
+
TModel extends string = string,
|
|
87
|
+
TProviderOptions extends object = Record<string, unknown>,
|
|
88
|
+
> implements VideoAdapter<TModel, TProviderOptions> {
|
|
89
|
+
readonly kind = 'video' as const
|
|
90
|
+
abstract readonly name: string
|
|
91
|
+
readonly model: TModel
|
|
92
|
+
|
|
93
|
+
// Type-only property - never assigned at runtime
|
|
94
|
+
declare '~types': {
|
|
95
|
+
providerOptions: TProviderOptions
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected config: VideoAdapterConfig
|
|
99
|
+
|
|
100
|
+
constructor(config: VideoAdapterConfig = {}, model: TModel) {
|
|
101
|
+
this.config = config
|
|
102
|
+
this.model = model
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
abstract createVideoJob(
|
|
106
|
+
options: VideoGenerationOptions<TProviderOptions>,
|
|
107
|
+
): Promise<VideoJobResult>
|
|
108
|
+
|
|
109
|
+
abstract getVideoStatus(jobId: string): Promise<VideoStatusResult>
|
|
110
|
+
|
|
111
|
+
abstract getVideoUrl(jobId: string): Promise<VideoUrlResult>
|
|
112
|
+
|
|
113
|
+
protected generateId(): string {
|
|
114
|
+
return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Activity (Experimental)
|
|
3
|
+
*
|
|
4
|
+
* Generates videos from text prompts using a jobs/polling architecture.
|
|
5
|
+
* This is a self-contained module with implementation, types, and JSDoc.
|
|
6
|
+
*
|
|
7
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { VideoAdapter } from './adapter'
|
|
11
|
+
import type {
|
|
12
|
+
VideoJobResult,
|
|
13
|
+
VideoStatusResult,
|
|
14
|
+
VideoUrlResult,
|
|
15
|
+
} from '../../types'
|
|
16
|
+
|
|
17
|
+
// ===========================
|
|
18
|
+
// Activity Kind
|
|
19
|
+
// ===========================
|
|
20
|
+
|
|
21
|
+
/** The adapter kind this activity handles */
|
|
22
|
+
export const kind = 'video' as const
|
|
23
|
+
|
|
24
|
+
// ===========================
|
|
25
|
+
// Type Extraction Helpers
|
|
26
|
+
// ===========================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Extract provider options from a VideoAdapter via ~types.
|
|
30
|
+
*/
|
|
31
|
+
export type VideoProviderOptions<TAdapter> =
|
|
32
|
+
TAdapter extends VideoAdapter<any, any>
|
|
33
|
+
? TAdapter['~types']['providerOptions']
|
|
34
|
+
: object
|
|
35
|
+
|
|
36
|
+
// ===========================
|
|
37
|
+
// Activity Options Types
|
|
38
|
+
// ===========================
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Base options shared by all video activity operations.
|
|
42
|
+
* The model is extracted from the adapter's model property.
|
|
43
|
+
*/
|
|
44
|
+
interface VideoActivityBaseOptions<
|
|
45
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
46
|
+
> {
|
|
47
|
+
/** The video adapter to use (must be created with a model) */
|
|
48
|
+
adapter: TAdapter & { kind: typeof kind }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Options for creating a new video generation job.
|
|
53
|
+
* The model is extracted from the adapter's model property.
|
|
54
|
+
*
|
|
55
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
56
|
+
*/
|
|
57
|
+
export interface VideoCreateOptions<
|
|
58
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
59
|
+
> extends VideoActivityBaseOptions<TAdapter> {
|
|
60
|
+
/** Request type - create a new job (default if not specified) */
|
|
61
|
+
request?: 'create'
|
|
62
|
+
/** Text description of the desired video */
|
|
63
|
+
prompt: string
|
|
64
|
+
/** Video size in WIDTHxHEIGHT format (e.g., "1280x720") */
|
|
65
|
+
size?: string
|
|
66
|
+
/** Video duration in seconds */
|
|
67
|
+
duration?: number
|
|
68
|
+
/** Provider-specific options for video generation */
|
|
69
|
+
modelOptions?: VideoProviderOptions<TAdapter>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Options for polling the status of a video generation job.
|
|
74
|
+
*
|
|
75
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
76
|
+
*/
|
|
77
|
+
export interface VideoStatusOptions<
|
|
78
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
79
|
+
> extends VideoActivityBaseOptions<TAdapter> {
|
|
80
|
+
/** Request type - get job status */
|
|
81
|
+
request: 'status'
|
|
82
|
+
/** The job ID to check status for */
|
|
83
|
+
jobId: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Options for getting the URL of a completed video.
|
|
88
|
+
*
|
|
89
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
90
|
+
*/
|
|
91
|
+
export interface VideoUrlOptions<
|
|
92
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
93
|
+
> extends VideoActivityBaseOptions<TAdapter> {
|
|
94
|
+
/** Request type - get video URL */
|
|
95
|
+
request: 'url'
|
|
96
|
+
/** The job ID to get URL for */
|
|
97
|
+
jobId: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Union type for all video activity options.
|
|
102
|
+
* Discriminated by the `request` field.
|
|
103
|
+
*
|
|
104
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
105
|
+
*/
|
|
106
|
+
export type VideoActivityOptions<
|
|
107
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
108
|
+
TRequest extends 'create' | 'status' | 'url' = 'create',
|
|
109
|
+
> = TRequest extends 'status'
|
|
110
|
+
? VideoStatusOptions<TAdapter>
|
|
111
|
+
: TRequest extends 'url'
|
|
112
|
+
? VideoUrlOptions<TAdapter>
|
|
113
|
+
: VideoCreateOptions<TAdapter>
|
|
114
|
+
|
|
115
|
+
// ===========================
|
|
116
|
+
// Activity Result Types
|
|
117
|
+
// ===========================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Result type for the video activity, based on request type.
|
|
121
|
+
*
|
|
122
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
123
|
+
*/
|
|
124
|
+
export type VideoActivityResult<
|
|
125
|
+
TRequest extends 'create' | 'status' | 'url' = 'create',
|
|
126
|
+
> = TRequest extends 'status'
|
|
127
|
+
? Promise<VideoStatusResult>
|
|
128
|
+
: TRequest extends 'url'
|
|
129
|
+
? Promise<VideoUrlResult>
|
|
130
|
+
: Promise<VideoJobResult>
|
|
131
|
+
|
|
132
|
+
// ===========================
|
|
133
|
+
// Activity Implementation
|
|
134
|
+
// ===========================
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Generate video - creates a video generation job from a text prompt.
|
|
138
|
+
*
|
|
139
|
+
* Uses AI video generation models to create videos based on natural language descriptions.
|
|
140
|
+
* Unlike image generation, video generation is asynchronous and requires polling for completion.
|
|
141
|
+
*
|
|
142
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
143
|
+
*
|
|
144
|
+
* @example Create a video generation job
|
|
145
|
+
* ```ts
|
|
146
|
+
* import { generateVideo } from '@tanstack/ai'
|
|
147
|
+
* import { openaiVideo } from '@tanstack/ai-openai'
|
|
148
|
+
*
|
|
149
|
+
* // Start a video generation job
|
|
150
|
+
* const { jobId } = await generateVideo({
|
|
151
|
+
* adapter: openaiVideo('sora-2'),
|
|
152
|
+
* prompt: 'A cat chasing a dog in a sunny park'
|
|
153
|
+
* })
|
|
154
|
+
*
|
|
155
|
+
* console.log('Job started:', jobId)
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export async function generateVideo<
|
|
159
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
160
|
+
>(options: VideoCreateOptions<TAdapter>): Promise<VideoJobResult> {
|
|
161
|
+
const { adapter, prompt, size, duration, modelOptions } = options
|
|
162
|
+
const model = adapter.model
|
|
163
|
+
|
|
164
|
+
return adapter.createVideoJob({
|
|
165
|
+
model,
|
|
166
|
+
prompt,
|
|
167
|
+
size,
|
|
168
|
+
duration,
|
|
169
|
+
modelOptions,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get video job status - returns the current status, progress, and URL if available.
|
|
175
|
+
*
|
|
176
|
+
* This function combines status checking and URL retrieval. If the job is completed,
|
|
177
|
+
* it will automatically fetch and include the video URL.
|
|
178
|
+
*
|
|
179
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
180
|
+
*
|
|
181
|
+
* @example Check job status
|
|
182
|
+
* ```ts
|
|
183
|
+
* import { getVideoJobStatus } from '@tanstack/ai'
|
|
184
|
+
* import { openaiVideo } from '@tanstack/ai-openai'
|
|
185
|
+
*
|
|
186
|
+
* const result = await getVideoJobStatus({
|
|
187
|
+
* adapter: openaiVideo('sora-2'),
|
|
188
|
+
* jobId: 'job-123'
|
|
189
|
+
* })
|
|
190
|
+
*
|
|
191
|
+
* console.log('Status:', result.status)
|
|
192
|
+
* console.log('Progress:', result.progress)
|
|
193
|
+
* if (result.url) {
|
|
194
|
+
* console.log('Video URL:', result.url)
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export async function getVideoJobStatus<
|
|
199
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
200
|
+
>(options: {
|
|
201
|
+
adapter: TAdapter & { kind: typeof kind }
|
|
202
|
+
jobId: string
|
|
203
|
+
}): Promise<{
|
|
204
|
+
status: 'pending' | 'processing' | 'completed' | 'failed'
|
|
205
|
+
progress?: number
|
|
206
|
+
url?: string
|
|
207
|
+
error?: string
|
|
208
|
+
}> {
|
|
209
|
+
const { adapter, jobId } = options
|
|
210
|
+
|
|
211
|
+
// Get status first
|
|
212
|
+
const statusResult = await adapter.getVideoStatus(jobId)
|
|
213
|
+
|
|
214
|
+
// If completed, also get the URL
|
|
215
|
+
if (statusResult.status === 'completed') {
|
|
216
|
+
try {
|
|
217
|
+
const urlResult = await adapter.getVideoUrl(jobId)
|
|
218
|
+
return {
|
|
219
|
+
status: statusResult.status,
|
|
220
|
+
progress: statusResult.progress,
|
|
221
|
+
url: urlResult.url,
|
|
222
|
+
}
|
|
223
|
+
} catch (error) {
|
|
224
|
+
// If URL fetch fails, still return status
|
|
225
|
+
return {
|
|
226
|
+
status: statusResult.status,
|
|
227
|
+
progress: statusResult.progress,
|
|
228
|
+
error:
|
|
229
|
+
error instanceof Error ? error.message : 'Failed to get video URL',
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Return status for non-completed jobs
|
|
235
|
+
return {
|
|
236
|
+
status: statusResult.status,
|
|
237
|
+
progress: statusResult.progress,
|
|
238
|
+
error: statusResult.error,
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ===========================
|
|
243
|
+
// Options Factory
|
|
244
|
+
// ===========================
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Create typed options for the generateVideo() function without executing.
|
|
248
|
+
*/
|
|
249
|
+
export function createVideoOptions<
|
|
250
|
+
TAdapter extends VideoAdapter<string, object>,
|
|
251
|
+
>(options: VideoCreateOptions<TAdapter>): VideoCreateOptions<TAdapter> {
|
|
252
|
+
return options
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Re-export adapter types
|
|
256
|
+
export type {
|
|
257
|
+
VideoAdapter,
|
|
258
|
+
VideoAdapterConfig,
|
|
259
|
+
AnyVideoAdapter,
|
|
260
|
+
} from './adapter'
|
|
261
|
+
export { BaseVideoAdapter } from './adapter'
|