@tanstack/ai 0.41.0 → 0.43.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 +15 -1
- package/dist/esm/activities/chat/adapter.js +23 -16
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/agent-loop-strategies.d.ts +10 -4
- package/dist/esm/activities/chat/agent-loop-strategies.js +75 -17
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
- package/dist/esm/activities/chat/cancel.d.ts +40 -0
- package/dist/esm/activities/chat/cancel.js +54 -0
- package/dist/esm/activities/chat/cancel.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +28 -16
- package/dist/esm/activities/chat/index.js +2100 -1744
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/mcp/manager.d.ts +2 -2
- package/dist/esm/activities/chat/mcp/manager.js +90 -77
- package/dist/esm/activities/chat/mcp/manager.js.map +1 -1
- package/dist/esm/activities/chat/mcp/types.d.ts +2 -2
- package/dist/esm/activities/chat/messages.js +397 -346
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/builder.js +17 -15
- package/dist/esm/activities/chat/middleware/builder.js.map +1 -1
- package/dist/esm/activities/chat/middleware/capabilities.js +78 -43
- package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +94 -1
- package/dist/esm/activities/chat/middleware/compose.js +623 -531
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/define.js +12 -5
- package/dist/esm/activities/chat/middleware/define.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +5 -1
- package/dist/esm/activities/chat/middleware/locks.d.ts +50 -0
- package/dist/esm/activities/chat/middleware/locks.js +71 -0
- package/dist/esm/activities/chat/middleware/locks.js.map +1 -0
- package/dist/esm/activities/chat/middleware/pending-turn.d.ts +15 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js +35 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.d.ts +23 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js +42 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-store.d.ts +283 -0
- package/dist/esm/activities/chat/middleware/run-store.js +176 -0
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -0
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js +14 -8
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +79 -70
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +59 -2
- package/dist/esm/activities/chat/middleware/validate.js +23 -28
- package/dist/esm/activities/chat/middleware/validate.js.map +1 -1
- package/dist/esm/activities/chat/stream/json-parser.js +39 -25
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +275 -234
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +24 -4
- package/dist/esm/activities/chat/stream/processor.js +1341 -1542
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/stream/strategies.js +69 -53
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -1
- package/dist/esm/activities/chat/tools/approval-schema.d.ts +19 -0
- package/dist/esm/activities/chat/tools/approval-schema.js +117 -0
- package/dist/esm/activities/chat/tools/approval-schema.js.map +1 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +164 -191
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
- package/dist/esm/activities/chat/tools/lazy-tools.js +24 -12
- package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +293 -146
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +18 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +522 -531
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +75 -16
- package/dist/esm/activities/chat/tools/tool-definition.js +95 -23
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/error-payload.js +85 -47
- package/dist/esm/activities/error-payload.js.map +1 -1
- package/dist/esm/activities/generateAudio/adapter.js +22 -15
- package/dist/esm/activities/generateAudio/adapter.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.d.ts +4 -0
- package/dist/esm/activities/generateAudio/index.js +141 -105
- package/dist/esm/activities/generateAudio/index.js.map +1 -1
- package/dist/esm/activities/generateImage/adapter.js +22 -15
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.d.ts +4 -0
- package/dist/esm/activities/generateImage/index.js +155 -111
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/adapter.js +22 -15
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +4 -0
- package/dist/esm/activities/generateSpeech/index.js +159 -110
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/adapter.js +22 -15
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +4 -0
- package/dist/esm/activities/generateTranscription/index.js +159 -100
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.js +36 -29
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +143 -19
- package/dist/esm/activities/generateVideo/index.js +456 -279
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/snap.js +60 -48
- package/dist/esm/activities/generateVideo/snap.js.map +1 -1
- package/dist/esm/activities/index.js +8 -34
- package/dist/esm/activities/middleware/index.d.ts +1 -1
- package/dist/esm/activities/middleware/run.d.ts +10 -0
- package/dist/esm/activities/middleware/run.js +53 -29
- package/dist/esm/activities/middleware/run.js.map +1 -1
- package/dist/esm/activities/middleware/types.d.ts +44 -6
- package/dist/esm/activities/stream-generation-result.d.ts +4 -1
- package/dist/esm/activities/stream-generation-result.js +79 -44
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/activities/summarize/adapter.js +22 -15
- package/dist/esm/activities/summarize/adapter.js.map +1 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.js +252 -202
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.d.ts +27 -0
- package/dist/esm/activities/summarize/index.js +268 -102
- package/dist/esm/activities/summarize/index.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +2 -1
- package/dist/esm/adapter-internals.js +4 -11
- package/dist/esm/client.d.ts +25 -3
- package/dist/esm/client.js +131 -64
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/custom-events.d.ts +76 -0
- package/dist/esm/custom-events.js +37 -0
- package/dist/esm/custom-events.js.map +1 -0
- package/dist/esm/delivery-detach.d.ts +50 -0
- package/dist/esm/delivery-detach.js +71 -0
- package/dist/esm/delivery-detach.js.map +1 -0
- package/dist/esm/delivery-disconnect.d.ts +62 -0
- package/dist/esm/delivery-disconnect.js +81 -0
- package/dist/esm/delivery-disconnect.js.map +1 -0
- package/dist/esm/extend-adapter.js +19 -17
- package/dist/esm/extend-adapter.js.map +1 -1
- package/dist/esm/index.d.ts +23 -5
- package/dist/esm/index.js +30 -97
- package/dist/esm/interrupt-resume.d.ts +71 -0
- package/dist/esm/interrupt-resume.js +438 -0
- package/dist/esm/interrupt-resume.js.map +1 -0
- package/dist/esm/interrupt-serialization.d.ts +12 -0
- package/dist/esm/interrupt-serialization.js +178 -0
- package/dist/esm/interrupt-serialization.js.map +1 -0
- package/dist/esm/interrupts.d.ts +84 -0
- package/dist/esm/interrupts.js +31 -0
- package/dist/esm/interrupts.js.map +1 -0
- package/dist/esm/locks.d.ts +10 -0
- package/dist/esm/locks.js +2 -0
- package/dist/esm/logger/console-logger.js +101 -78
- package/dist/esm/logger/console-logger.js.map +1 -1
- package/dist/esm/logger/internal-logger.js +104 -89
- package/dist/esm/logger/internal-logger.js.map +1 -1
- package/dist/esm/logger/resolve.js +54 -49
- package/dist/esm/logger/resolve.js.map +1 -1
- package/dist/esm/logger/types.d.ts +1 -1
- package/dist/esm/middlewares/content-guard.js +142 -148
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/middlewares/index.js +2 -6
- package/dist/esm/middlewares/otel.js +598 -732
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/middlewares/usage-attributes.js +47 -40
- package/dist/esm/middlewares/usage-attributes.js.map +1 -1
- package/dist/esm/realtime/event-emitter.js +24 -25
- package/dist/esm/realtime/event-emitter.js.map +1 -1
- package/dist/esm/realtime/index.d.ts +5 -9
- package/dist/esm/realtime/index.js +29 -6
- package/dist/esm/realtime/index.js.map +1 -1
- package/dist/esm/scope.d.ts +47 -0
- package/dist/esm/stream-durability.d.ts +171 -0
- package/dist/esm/stream-durability.js +295 -0
- package/dist/esm/stream-durability.js.map +1 -0
- package/dist/esm/stream-to-response.d.ts +178 -13
- package/dist/esm/stream-to-response.js +663 -115
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +30 -16
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/system-prompts.js +27 -21
- package/dist/esm/system-prompts.js.map +1 -1
- package/dist/esm/tool-registry.js +72 -45
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/tools/provider-tool.js +14 -5
- package/dist/esm/tools/provider-tool.js.map +1 -1
- package/dist/esm/types.d.ts +332 -21
- package/dist/esm/types.js +2 -0
- package/dist/esm/utilities/ag-ui-wire.js +79 -93
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/chat-params.d.ts +26 -4
- package/dist/esm/utilities/chat-params.js +218 -92
- package/dist/esm/utilities/chat-params.js.map +1 -1
- package/dist/esm/utilities/errors.js +28 -18
- package/dist/esm/utilities/errors.js.map +1 -1
- package/dist/esm/utilities/media-prompt.js +46 -41
- package/dist/esm/utilities/media-prompt.js.map +1 -1
- package/dist/esm/utilities/numbers.js +13 -10
- package/dist/esm/utilities/numbers.js.map +1 -1
- package/dist/esm/utilities/provider-executed.js +20 -11
- package/dist/esm/utilities/provider-executed.js.map +1 -1
- package/dist/esm/utilities/sampling-keys.js +31 -19
- package/dist/esm/utilities/sampling-keys.js.map +1 -1
- package/dist/esm/utilities/tool-result.js +42 -30
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/dist/esm/utilities/usage.js +27 -9
- package/dist/esm/utilities/usage.js.map +1 -1
- package/dist/esm/utils.js +26 -18
- package/dist/esm/utils.js.map +1 -1
- package/package.json +10 -6
- package/skills/ai-core/SKILL.md +69 -18
- package/skills/ai-core/adapter-configuration/SKILL.md +44 -21
- package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +1 -3
- package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +148 -0
- package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/groq-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/openai-adapter.md +1 -3
- package/skills/ai-core/ag-ui-protocol/SKILL.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +156 -11
- package/skills/ai-core/client-persistence/SKILL.md +277 -0
- package/skills/ai-core/custom-backend-integration/SKILL.md +1 -1
- package/skills/ai-core/debug-logging/SKILL.md +1 -1
- package/skills/ai-core/locks/SKILL.md +143 -0
- package/skills/ai-core/media-generation/SKILL.md +144 -12
- package/skills/ai-core/middleware/SKILL.md +258 -33
- package/skills/ai-core/structured-outputs/SKILL.md +1 -1
- package/skills/ai-core/tool-calling/SKILL.md +54 -59
- package/src/activities/chat/agent-loop-strategies.ts +10 -4
- package/src/activities/chat/cancel.ts +81 -0
- package/src/activities/chat/index.ts +1152 -153
- package/src/activities/chat/mcp/manager.ts +4 -4
- package/src/activities/chat/mcp/types.ts +2 -2
- package/src/activities/chat/messages.ts +5 -3
- package/src/activities/chat/middleware/builder.ts +1 -1
- package/src/activities/chat/middleware/compose.ts +186 -9
- package/src/activities/chat/middleware/index.ts +26 -0
- package/src/activities/chat/middleware/locks.ts +102 -0
- package/src/activities/chat/middleware/pending-turn.ts +47 -0
- package/src/activities/chat/middleware/run-disconnect.ts +62 -0
- package/src/activities/chat/middleware/run-store.ts +412 -0
- package/src/activities/chat/middleware/types.ts +62 -1
- package/src/activities/chat/stream/processor.ts +189 -5
- package/src/activities/chat/tools/approval-schema.ts +205 -0
- package/src/activities/chat/tools/tool-calls.ts +106 -13
- package/src/activities/chat/tools/tool-definition.ts +210 -39
- package/src/activities/generateAudio/index.ts +20 -3
- package/src/activities/generateImage/index.ts +20 -3
- package/src/activities/generateSpeech/index.ts +25 -3
- package/src/activities/generateTranscription/index.ts +26 -3
- package/src/activities/generateVideo/index.ts +345 -82
- package/src/activities/middleware/index.ts +2 -0
- package/src/activities/middleware/run.ts +31 -0
- package/src/activities/middleware/types.ts +49 -5
- package/src/activities/stream-generation-result.ts +30 -2
- package/src/activities/summarize/chat-stream-summarize.ts +5 -0
- package/src/activities/summarize/index.ts +200 -10
- package/src/adapter-internals.ts +10 -1
- package/src/client.ts +244 -0
- package/src/custom-events.ts +107 -0
- package/src/delivery-detach.ts +72 -0
- package/src/delivery-disconnect.ts +84 -0
- package/src/index.ts +138 -0
- package/src/interrupt-resume.ts +824 -0
- package/src/interrupt-serialization.ts +183 -0
- package/src/interrupts.ts +146 -0
- package/src/locks.ts +17 -0
- package/src/logger/types.ts +1 -1
- package/src/middlewares/otel.ts +1 -0
- package/src/realtime/index.ts +5 -9
- package/src/scope.ts +47 -0
- package/src/stream-durability.ts +598 -0
- package/src/stream-to-response.ts +1051 -95
- package/src/strip-to-spec-middleware.ts +3 -3
- package/src/types.ts +416 -24
- package/src/utilities/chat-params.ts +245 -55
- package/dist/esm/activities/index.js.map +0 -1
- package/dist/esm/adapter-internals.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/middlewares/index.js.map +0 -1
|
@@ -1,109 +1,168 @@
|
|
|
1
|
-
import { aiEventClient } from "@tanstack/ai-event-client";
|
|
2
|
-
import { streamGenerationResult } from "../stream-generation-result.js";
|
|
3
1
|
import { resolveDebugOption } from "../../logger/resolve.js";
|
|
4
|
-
import {
|
|
5
|
-
|
|
2
|
+
import { streamGenerationResult } from "../stream-generation-result.js";
|
|
3
|
+
import { applyGenerationResultTransforms, createGenerationContext, runGenerationError, runGenerationFinish, runGenerationStart, runGenerationUsage } from "../middleware/run.js";
|
|
4
|
+
import "./adapter.js";
|
|
5
|
+
import { aiEventClient } from "@tanstack/ai-event-client";
|
|
6
|
+
//#region src/activities/generateTranscription/index.ts
|
|
7
|
+
/**
|
|
8
|
+
* Transcription Activity
|
|
9
|
+
*
|
|
10
|
+
* Transcribes audio to text using speech-to-text models.
|
|
11
|
+
* This is a self-contained module with implementation, types, and JSDoc.
|
|
12
|
+
*/
|
|
13
|
+
/** The adapter kind this activity handles */
|
|
14
|
+
var kind = "transcription";
|
|
6
15
|
function createId(prefix) {
|
|
7
|
-
|
|
16
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
8
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Transcription activity - converts audio to text.
|
|
20
|
+
*
|
|
21
|
+
* Uses AI speech-to-text models to transcribe audio content.
|
|
22
|
+
*
|
|
23
|
+
* @example Transcribe an audio file
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { generateTranscription } from '@tanstack/ai'
|
|
26
|
+
* import { openaiTranscription } from '@tanstack/ai-openai'
|
|
27
|
+
*
|
|
28
|
+
* const result = await generateTranscription({
|
|
29
|
+
* adapter: openaiTranscription('whisper-1'),
|
|
30
|
+
* audio: audioFile, // File, Blob, or base64 string
|
|
31
|
+
* language: 'en'
|
|
32
|
+
* })
|
|
33
|
+
*
|
|
34
|
+
* console.log(result.text)
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example With verbose output for timestamps
|
|
38
|
+
* ```ts
|
|
39
|
+
* const result = await generateTranscription({
|
|
40
|
+
* adapter: openaiTranscription('whisper-1'),
|
|
41
|
+
* audio: audioFile,
|
|
42
|
+
* responseFormat: 'verbose_json'
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* result.segments?.forEach(segment => {
|
|
46
|
+
* console.log(`[${segment.start}s - ${segment.end}s]: ${segment.text}`)
|
|
47
|
+
* })
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Streaming transcription result
|
|
51
|
+
* ```ts
|
|
52
|
+
* for await (const chunk of generateTranscription({
|
|
53
|
+
* adapter: openaiTranscription('whisper-1'),
|
|
54
|
+
* audio: audioFile,
|
|
55
|
+
* stream: true
|
|
56
|
+
* })) {
|
|
57
|
+
* console.log(chunk)
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
9
61
|
function generateTranscription(options) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return runGenerateTranscription(
|
|
16
|
-
options
|
|
17
|
-
);
|
|
62
|
+
if (options.stream) return streamGenerationResult((resolved) => runGenerateTranscription({
|
|
63
|
+
...options,
|
|
64
|
+
runId: resolved.runId
|
|
65
|
+
}), options);
|
|
66
|
+
return runGenerateTranscription(options);
|
|
18
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Run non-streaming transcription
|
|
70
|
+
*/
|
|
19
71
|
async function runGenerateTranscription(options) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
72
|
+
const { adapter, stream: _stream, debug: _debug, middleware, threadId, runId, ...rest } = options;
|
|
73
|
+
const model = adapter.model;
|
|
74
|
+
const requestId = createId("transcription");
|
|
75
|
+
const startTime = Date.now();
|
|
76
|
+
const logger = resolveDebugOption(options.debug);
|
|
77
|
+
const providerName = adapter.provider ?? adapter.name ?? "unknown";
|
|
78
|
+
const mwCtx = createGenerationContext({
|
|
79
|
+
requestId,
|
|
80
|
+
activity: "transcription",
|
|
81
|
+
provider: adapter.name,
|
|
82
|
+
model,
|
|
83
|
+
modelOptions: rest.modelOptions,
|
|
84
|
+
artifactInputs: {
|
|
85
|
+
audio: rest.audio,
|
|
86
|
+
language: rest.language,
|
|
87
|
+
prompt: rest.prompt,
|
|
88
|
+
responseFormat: rest.responseFormat
|
|
89
|
+
},
|
|
90
|
+
threadId,
|
|
91
|
+
runId,
|
|
92
|
+
createId
|
|
93
|
+
});
|
|
94
|
+
await runGenerationStart(middleware, mwCtx);
|
|
95
|
+
aiEventClient.emit("transcription:request:started", {
|
|
96
|
+
requestId,
|
|
97
|
+
provider: adapter.name,
|
|
98
|
+
model,
|
|
99
|
+
language: rest.language,
|
|
100
|
+
prompt: rest.prompt,
|
|
101
|
+
responseFormat: rest.responseFormat,
|
|
102
|
+
modelOptions: rest.modelOptions,
|
|
103
|
+
timestamp: startTime
|
|
104
|
+
});
|
|
105
|
+
logger.request(`activity=generateTranscription provider=${providerName}`, {
|
|
106
|
+
provider: providerName,
|
|
107
|
+
model
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
const result = await applyGenerationResultTransforms(mwCtx, await adapter.transcribe({
|
|
111
|
+
...rest,
|
|
112
|
+
model,
|
|
113
|
+
logger
|
|
114
|
+
}));
|
|
115
|
+
const duration = Date.now() - startTime;
|
|
116
|
+
aiEventClient.emit("transcription:request:completed", {
|
|
117
|
+
requestId,
|
|
118
|
+
provider: adapter.name,
|
|
119
|
+
model,
|
|
120
|
+
text: result.text,
|
|
121
|
+
language: result.language,
|
|
122
|
+
duration,
|
|
123
|
+
modelOptions: rest.modelOptions,
|
|
124
|
+
timestamp: Date.now()
|
|
125
|
+
});
|
|
126
|
+
logger.output(`activity=generateTranscription length=${result.text.length}`, { hasText: !!result.text });
|
|
127
|
+
if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage);
|
|
128
|
+
await runGenerationFinish(middleware, mwCtx, {
|
|
129
|
+
duration,
|
|
130
|
+
usage: result.usage
|
|
131
|
+
});
|
|
132
|
+
return result;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
const duration = Date.now() - startTime;
|
|
135
|
+
const err = error;
|
|
136
|
+
aiEventClient.emit("transcription:request:error", {
|
|
137
|
+
requestId,
|
|
138
|
+
provider: adapter.name,
|
|
139
|
+
model,
|
|
140
|
+
error: {
|
|
141
|
+
message: err.message,
|
|
142
|
+
name: err.name
|
|
143
|
+
},
|
|
144
|
+
duration,
|
|
145
|
+
modelOptions: rest.modelOptions,
|
|
146
|
+
timestamp: Date.now()
|
|
147
|
+
});
|
|
148
|
+
await runGenerationError(middleware, mwCtx, {
|
|
149
|
+
error,
|
|
150
|
+
duration
|
|
151
|
+
});
|
|
152
|
+
logger.errors("generateTranscription activity failed", {
|
|
153
|
+
error,
|
|
154
|
+
source: "generateTranscription"
|
|
155
|
+
});
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
100
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Create typed options for the generateTranscription() function without executing.
|
|
161
|
+
*/
|
|
101
162
|
function createTranscriptionOptions(options) {
|
|
102
|
-
|
|
163
|
+
return options;
|
|
103
164
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
};
|
|
109
|
-
//# sourceMappingURL=index.js.map
|
|
165
|
+
//#endregion
|
|
166
|
+
export { createTranscriptionOptions, generateTranscription, kind };
|
|
167
|
+
|
|
168
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/activities/generateTranscription/index.ts"],"sourcesContent":["/**\n * Transcription Activity\n *\n * Transcribes audio to text using speech-to-text 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 createGenerationContext,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { TranscriptionAdapter } from './adapter'\nimport type {\n StreamChunk,\n TranscriptionResponseFormat,\n TranscriptionResult,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'transcription' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a TranscriptionAdapter via ~types.\n */\nexport type TranscriptionProviderOptions<TAdapter> =\n TAdapter extends TranscriptionAdapter<any, any>\n ? TAdapter['~types']['providerOptions']\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the transcription activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The transcription adapter type\n * @template TStream - Whether to stream the output\n */\nexport interface TranscriptionActivityOptions<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n> {\n /** The transcription adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /** The audio data to transcribe - can be base64 string, File, Blob, or Buffer */\n audio: string | File | Blob | ArrayBuffer\n /** The language of the audio in ISO-639-1 format (e.g., 'en') */\n language?: string\n /** An optional prompt to guide the transcription */\n prompt?: string\n /** The format of the transcription output */\n responseFormat?: TranscriptionResponseFormat\n /** Provider-specific options for transcription */\n modelOptions?: TranscriptionProviderOptions<TAdapter>\n /**\n * Whether to stream the transcription result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<TranscriptionResult>.\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}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the transcription activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<TranscriptionResult>\n */\nexport type TranscriptionActivityResult<TStream extends boolean = false> =\n TStream extends true\n ? AsyncIterable<StreamChunk>\n : Promise<TranscriptionResult>\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 * Transcription activity - converts audio to text.\n *\n * Uses AI speech-to-text models to transcribe audio content.\n *\n * @example Transcribe an audio file\n * ```ts\n * import { generateTranscription } from '@tanstack/ai'\n * import { openaiTranscription } from '@tanstack/ai-openai'\n *\n * const result = await generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile, // File, Blob, or base64 string\n * language: 'en'\n * })\n *\n * console.log(result.text)\n * ```\n *\n * @example With verbose output for timestamps\n * ```ts\n * const result = await generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile,\n * responseFormat: 'verbose_json'\n * })\n *\n * result.segments?.forEach(segment => {\n * console.log(`[${segment.start}s - ${segment.end}s]: ${segment.text}`)\n * })\n * ```\n *\n * @example Streaming transcription result\n * ```ts\n * for await (const chunk of generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile,\n * stream: true\n * })) {\n * console.log(chunk)\n * }\n * ```\n */\nexport function generateTranscription<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n>(\n options: TranscriptionActivityOptions<TAdapter, TStream>,\n): TranscriptionActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(() =>\n runGenerateTranscription(options),\n ) as TranscriptionActivityResult<TStream>\n }\n\n return runGenerateTranscription(\n options,\n ) as TranscriptionActivityResult<TStream>\n}\n\n/**\n * Run non-streaming transcription\n */\nasync function runGenerateTranscription<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n>(\n options: TranscriptionActivityOptions<TAdapter, boolean>,\n): Promise<TranscriptionResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n ...rest\n } = options\n const model = adapter.model\n const requestId = createId('transcription')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\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: 'transcription',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('transcription:request:started', {\n requestId,\n provider: adapter.name,\n model,\n language: rest.language,\n prompt: rest.prompt,\n responseFormat: rest.responseFormat,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateTranscription provider=${providerName}`, {\n provider: providerName,\n model,\n })\n\n try {\n const result = await adapter.transcribe({ ...rest, model, logger })\n const duration = Date.now() - startTime\n\n aiEventClient.emit('transcription:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n text: result.text,\n language: result.language,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n logger.output(\n `activity=generateTranscription length=${result.text.length}`,\n { hasText: !!result.text },\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 const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('transcription: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 await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n logger.errors('generateTranscription activity failed', {\n error,\n source: 'generateTranscription',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateTranscription() function without executing.\n */\nexport function createTranscriptionOptions<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n>(\n options: TranscriptionActivityOptions<TAdapter, TStream>,\n): TranscriptionActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n TranscriptionAdapter,\n TranscriptionAdapterConfig,\n AnyTranscriptionAdapter,\n} from './adapter'\nexport { BaseTranscriptionAdapter } from './adapter'\n"],"names":[],"mappings":";;;;AAgCO,MAAM,OAAO;AAgFpB,SAAS,SAAS,QAAwB;AACxC,SAAO,GAAG,MAAM,IAAI,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC1E;AAiDO,SAAS,sBAOd,SACsC;AACtC,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA,MAAuB,MAC5B,yBAAyB,OAAO;AAAA,IAAA;AAAA,EAEpC;AAEA,SAAO;AAAA,IACL;AAAA,EAAA;AAEJ;AAKA,eAAe,yBAMb,SAC8B;AAC9B,QAAM;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AACJ,QAAM,QAAQ,QAAQ;AACtB,QAAM,YAAY,SAAS,eAAe;AAC1C,QAAM,YAAY,KAAK,IAAA;AACvB,QAAM,SAAyB,mBAAmB,QAAQ,KAAK;AAC/D,QAAM,eACH,QAAiD,YACjD,QAA8B,QAC/B;AAEF,QAAM,QAAQ,wBAAwB;AAAA,IACpC;AAAA,IACA,UAAU;AAAA,IACV,UAAU,QAAQ;AAAA,IAClB;AAAA,IACA,cAAc,KAAK;AAAA,IACnB;AAAA,EAAA,CACD;AAED,QAAM,mBAAmB,YAAY,KAAK;AAE1C,gBAAc,KAAK,iCAAiC;AAAA,IAClD;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB;AAAA,IACA,UAAU,KAAK;AAAA,IACf,QAAQ,KAAK;AAAA,IACb,gBAAgB,KAAK;AAAA,IACrB,cAAc,KAAK;AAAA,IACnB,WAAW;AAAA,EAAA,CACZ;AAED,SAAO,QAAQ,2CAA2C,YAAY,IAAI;AAAA,IACxE,UAAU;AAAA,IACV;AAAA,EAAA,CACD;AAED,MAAI;AACF,UAAM,SAAS,MAAM,QAAQ,WAAW,EAAE,GAAG,MAAM,OAAO,QAAQ;AAClE,UAAM,WAAW,KAAK,IAAA,IAAQ;AAE9B,kBAAc,KAAK,mCAAmC;AAAA,MACpD;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB;AAAA,MACA,MAAM,OAAO;AAAA,MACb,UAAU,OAAO;AAAA,MACjB;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,WAAW,KAAK,IAAA;AAAA,IAAI,CACrB;AAED,WAAO;AAAA,MACL,yCAAyC,OAAO,KAAK,MAAM;AAAA,MAC3D,EAAE,SAAS,CAAC,CAAC,OAAO,KAAA;AAAA,IAAK;AAG3B,QAAI,OAAO,MAAO,OAAM,mBAAmB,YAAY,OAAO,OAAO,KAAK;AAC1E,UAAM,oBAAoB,YAAY,OAAO;AAAA,MAC3C;AAAA,MACA,OAAO,OAAO;AAAA,IAAA,CACf;AAED,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,WAAW,KAAK,IAAA,IAAQ;AAC9B,UAAM,MAAM;AACZ,kBAAc,KAAK,+BAA+B;AAAA,MAChD;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB;AAAA,MACA,OAAO,EAAE,SAAS,IAAI,SAAS,MAAM,IAAI,KAAA;AAAA,MACzC;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,WAAW,KAAK,IAAA;AAAA,IAAI,CACrB;AACD,UAAM,mBAAmB,YAAY,OAAO;AAAA,MAC1C;AAAA,MACA;AAAA,IAAA,CACD;AACD,WAAO,OAAO,yCAAyC;AAAA,MACrD;AAAA,MACA,QAAQ;AAAA,IAAA,CACT;AACD,UAAM;AAAA,EACR;AACF;AASO,SAAS,2BAOd,SACiD;AACjD,SAAO;AACT;"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateTranscription/index.ts"],"sourcesContent":["/**\n * Transcription Activity\n *\n * Transcribes audio to text using speech-to-text 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 runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { TranscriptionAdapter } from './adapter'\nimport type {\n StreamChunk,\n TranscriptionResponseFormat,\n TranscriptionResult,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'transcription' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a TranscriptionAdapter via ~types.\n */\nexport type TranscriptionProviderOptions<TAdapter> =\n TAdapter extends TranscriptionAdapter<any, any>\n ? TAdapter['~types']['providerOptions']\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the transcription activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The transcription adapter type\n * @template TStream - Whether to stream the output\n */\nexport interface TranscriptionActivityOptions<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n> {\n /** The transcription adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /** The audio data to transcribe - can be base64 string, File, Blob, or Buffer */\n audio: string | File | Blob | ArrayBuffer\n /** The language of the audio in ISO-639-1 format (e.g., 'en') */\n language?: string\n /** An optional prompt to guide the transcription */\n prompt?: string\n /** The format of the transcription output */\n responseFormat?: TranscriptionResponseFormat\n /** Provider-specific options for transcription */\n modelOptions?: TranscriptionProviderOptions<TAdapter>\n /**\n * Whether to stream the transcription result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<TranscriptionResult>.\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\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the transcription activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<TranscriptionResult>\n */\nexport type TranscriptionActivityResult<TStream extends boolean = false> =\n TStream extends true\n ? AsyncIterable<StreamChunk>\n : Promise<TranscriptionResult>\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 * Transcription activity - converts audio to text.\n *\n * Uses AI speech-to-text models to transcribe audio content.\n *\n * @example Transcribe an audio file\n * ```ts\n * import { generateTranscription } from '@tanstack/ai'\n * import { openaiTranscription } from '@tanstack/ai-openai'\n *\n * const result = await generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile, // File, Blob, or base64 string\n * language: 'en'\n * })\n *\n * console.log(result.text)\n * ```\n *\n * @example With verbose output for timestamps\n * ```ts\n * const result = await generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile,\n * responseFormat: 'verbose_json'\n * })\n *\n * result.segments?.forEach(segment => {\n * console.log(`[${segment.start}s - ${segment.end}s]: ${segment.text}`)\n * })\n * ```\n *\n * @example Streaming transcription result\n * ```ts\n * for await (const chunk of generateTranscription({\n * adapter: openaiTranscription('whisper-1'),\n * audio: audioFile,\n * stream: true\n * })) {\n * console.log(chunk)\n * }\n * ```\n */\nexport function generateTranscription<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n>(\n options: TranscriptionActivityOptions<TAdapter, TStream>,\n): TranscriptionActivityResult<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) =>\n runGenerateTranscription({ ...options, runId: resolved.runId }),\n options,\n ) as TranscriptionActivityResult<TStream>\n }\n\n return runGenerateTranscription(\n options,\n ) as TranscriptionActivityResult<TStream>\n}\n\n/**\n * Run non-streaming transcription\n */\nasync function runGenerateTranscription<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n>(\n options: TranscriptionActivityOptions<TAdapter, boolean>,\n): Promise<TranscriptionResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n ...rest\n } = options\n const model = adapter.model\n const requestId = createId('transcription')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\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: 'transcription',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n artifactInputs: {\n audio: rest.audio,\n language: rest.language,\n prompt: rest.prompt,\n responseFormat: rest.responseFormat,\n },\n threadId,\n runId,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('transcription:request:started', {\n requestId,\n provider: adapter.name,\n model,\n language: rest.language,\n prompt: rest.prompt,\n responseFormat: rest.responseFormat,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateTranscription provider=${providerName}`, {\n provider: providerName,\n model,\n })\n\n try {\n const rawResult = await adapter.transcribe({ ...rest, model, logger })\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('transcription:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n text: result.text,\n language: result.language,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n logger.output(\n `activity=generateTranscription length=${result.text.length}`,\n { hasText: !!result.text },\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 const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('transcription: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 await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n logger.errors('generateTranscription activity failed', {\n error,\n source: 'generateTranscription',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateTranscription() function without executing.\n */\nexport function createTranscriptionOptions<\n TAdapter extends TranscriptionAdapter<\n string,\n TranscriptionProviderOptions<TAdapter>\n >,\n TStream extends boolean = false,\n>(\n options: TranscriptionActivityOptions<TAdapter, TStream>,\n): TranscriptionActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n TranscriptionAdapter,\n TranscriptionAdapterConfig,\n AnyTranscriptionAdapter,\n} from './adapter'\nexport { BaseTranscriptionAdapter } from './adapter'\n"],"mappings":";;;;;;;;;;;;;AAiCA,IAAa,OAAO;AAoFpB,SAAS,SAAS,QAAwB;CACxC,OAAO,GAAG,OAAO,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;AACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAgB,sBAOd,SACsC;CACtC,IAAI,QAAQ,QACV,OAAO,wBAMJ,aACC,yBAAyB;EAAE,GAAG;EAAS,OAAO,SAAS;CAAM,CAAC,GAChE,OACF;CAGF,OAAO,yBACL,OACF;AACF;;;;AAKA,eAAe,yBAMb,SAC8B;CAC9B,MAAM,EACJ,SACA,QAAQ,SACR,OAAO,QACP,YACA,UACA,OACA,GAAG,SACD;CACJ,MAAM,QAAQ,QAAQ;CACtB,MAAM,YAAY,SAAS,eAAe;CAC1C,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,SAAyB,mBAAmB,QAAQ,KAAK;CAC/D,MAAM,eACH,QAAiD,YACjD,QAA8B,QAC/B;CAEF,MAAM,QAAQ,wBAAwB;EACpC;EACA,UAAU;EACV,UAAU,QAAQ;EAClB;EACA,cAAc,KAAK;EACnB,gBAAgB;GACd,OAAO,KAAK;GACZ,UAAU,KAAK;GACf,QAAQ,KAAK;GACb,gBAAgB,KAAK;EACvB;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,mBAAmB,YAAY,KAAK;CAE1C,cAAc,KAAK,iCAAiC;EAClD;EACA,UAAU,QAAQ;EAClB;EACA,UAAU,KAAK;EACf,QAAQ,KAAK;EACb,gBAAgB,KAAK;EACrB,cAAc,KAAK;EACnB,WAAW;CACb,CAAC;CAED,OAAO,QAAQ,2CAA2C,gBAAgB;EACxE,UAAU;EACV;CACF,CAAC;CAED,IAAI;EAEF,MAAM,SAAS,MAAM,gCAAgC,OAAO,MADpC,QAAQ,WAAW;GAAE,GAAG;GAAM;GAAO;EAAO,CAAC,CACA;EACrE,MAAM,WAAW,KAAK,IAAI,IAAI;EAE9B,cAAc,KAAK,mCAAmC;GACpD;GACA,UAAU,QAAQ;GAClB;GACA,MAAM,OAAO;GACb,UAAU,OAAO;GACjB;GACA,cAAc,KAAK;GACnB,WAAW,KAAK,IAAI;EACtB,CAAC;EAED,OAAO,OACL,yCAAyC,OAAO,KAAK,UACrD,EAAE,SAAS,CAAC,CAAC,OAAO,KAAK,CAC3B;EAEA,IAAI,OAAO,OAAO,MAAM,mBAAmB,YAAY,OAAO,OAAO,KAAK;EAC1E,MAAM,oBAAoB,YAAY,OAAO;GAC3C;GACA,OAAO,OAAO;EAChB,CAAC;EAED,OAAO;CACT,SAAS,OAAO;EACd,MAAM,WAAW,KAAK,IAAI,IAAI;EAC9B,MAAM,MAAM;EACZ,cAAc,KAAK,+BAA+B;GAChD;GACA,UAAU,QAAQ;GAClB;GACA,OAAO;IAAE,SAAS,IAAI;IAAS,MAAM,IAAI;GAAK;GAC9C;GACA,cAAc,KAAK;GACnB,WAAW,KAAK,IAAI;EACtB,CAAC;EACD,MAAM,mBAAmB,YAAY,OAAO;GAC1C;GACA;EACF,CAAC;EACD,OAAO,OAAO,yCAAyC;GACrD;GACA,QAAQ;EACV,CAAC;EACD,MAAM;CACR;AACF;;;;AASA,SAAgB,2BAOd,SACiD;CACjD,OAAO;AACT"}
|
|
@@ -1,30 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
//#region src/activities/generateVideo/adapter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for video generation adapters.
|
|
4
|
+
* Extend this class to implement a video adapter for a specific provider.
|
|
5
|
+
*
|
|
6
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
7
|
+
*
|
|
8
|
+
* Generic parameters match VideoAdapter - all pre-resolved by the provider function.
|
|
9
|
+
*/
|
|
10
|
+
var BaseVideoAdapter = class {
|
|
11
|
+
kind = "video";
|
|
12
|
+
model;
|
|
13
|
+
config;
|
|
14
|
+
constructor(config = {}, model) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.model = model;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Default implementation returns `{ kind: 'none' }`. Adapters that have
|
|
20
|
+
* declared their per-model duration map should override this.
|
|
21
|
+
*/
|
|
22
|
+
availableDurations() {
|
|
23
|
+
return { kind: "none" };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default implementation returns `undefined`. Adapters that have declared
|
|
27
|
+
* their per-model duration map should override.
|
|
28
|
+
*/
|
|
29
|
+
snapDuration(_seconds) {}
|
|
30
|
+
generateId() {
|
|
31
|
+
return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
32
|
+
}
|
|
29
33
|
};
|
|
30
|
-
//#
|
|
34
|
+
//#endregion
|
|
35
|
+
export { BaseVideoAdapter };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sources":["../../../../src/activities/generateVideo/adapter.ts"],"sourcesContent":["import type {\n ModelInputModalitiesByName,\n VideoGenerationOptions,\n VideoJobResult,\n VideoStatusResult,\n VideoUrlResult,\n} from '../../types'\n\n/**\n * Structured description of the durations a video model accepts.\n *\n * Tagged union so the same shape can express discrete enums (OpenAI Sora,\n * Veo), continuous ranges, mixed shapes, and models with no duration field.\n * Consumed by `VideoAdapter.availableDurations()`.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type DurationOptions<T extends string | number | undefined> =\n | { kind: 'discrete'; values: ReadonlyArray<NonNullable<T>> }\n | { kind: 'range'; min: number; max: number; step?: number; unit: 'seconds' }\n | {\n kind: 'mixed'\n values: ReadonlyArray<NonNullable<T>>\n range?: { min: number; max: number; step?: number }\n }\n | { kind: 'none' }\n\n/**\n * Configuration for video adapter instances\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface VideoAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * Video 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 * @experimental Video generation is an experimental feature and may change.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'sora-2')\n * - TProviderOptions: Provider-specific options (already resolved)\n * - TModelProviderOptionsByName: Map from model name to its specific provider options\n * - TModelSizeByName: Map from model name to its supported sizes\n * - TModelInputModalitiesByName: Map from model name to the non-text prompt\n * modalities it accepts (constrains the `prompt` part types at compile time)\n * - TModelDurationByName: Map from model name to its supported duration\n * union. Defaults to `Record<string, number>` so adapters that haven't\n * declared a map keep today's `duration?: number` typing.\n */\nexport interface VideoAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,\n TModelSizeByName extends Record<string, string | undefined> = Record<\n string,\n string\n >,\n TModelInputModalitiesByName extends ModelInputModalitiesByName =\n ModelInputModalitiesByName,\n TModelDurationByName extends Record<string, string | number | undefined> =\n Record<string, number>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'video'\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 modelProviderOptionsByName: TModelProviderOptionsByName\n modelSizeByName: TModelSizeByName\n modelInputModalitiesByName: TModelInputModalitiesByName\n modelDurationByName: TModelDurationByName\n }\n\n /**\n * Create a new video generation job.\n * Returns a job ID that can be used to poll for status and retrieve the video.\n */\n createVideoJob: (\n options: VideoGenerationOptions<\n TProviderOptions,\n TModelSizeByName[TModel],\n TModelDurationByName[TModel]\n >,\n ) => Promise<VideoJobResult>\n\n /**\n * Get the current status of a video generation job.\n */\n getVideoStatus: (jobId: string) => Promise<VideoStatusResult>\n\n /**\n * Get the URL to download/view the generated video.\n * Should only be called after status is 'completed'.\n */\n getVideoUrl: (jobId: string) => Promise<VideoUrlResult>\n\n /**\n * Describe the durations this adapter's model accepts. Returns a tagged\n * union so consumers can render UI / coerce input without provider-specific\n * knowledge.\n */\n availableDurations: () => DurationOptions<TModelDurationByName[TModel]>\n\n /**\n * Coerce a raw seconds value to the closest valid duration for this model.\n * Returns `undefined` for models with no duration field.\n */\n snapDuration: (seconds: number) => TModelDurationByName[TModel] | undefined\n}\n\n/**\n * A VideoAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyVideoAdapter = VideoAdapter<any, any, any, any, any, any>\n\n/**\n * Abstract base class for video generation adapters.\n * Extend this class to implement a video adapter for a specific provider.\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * Generic parameters match VideoAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseVideoAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,\n TModelSizeByName extends Record<string, string | undefined> = Record<\n string,\n string\n >,\n TModelInputModalitiesByName extends ModelInputModalitiesByName =\n ModelInputModalitiesByName,\n TModelDurationByName extends Record<string, string | number | undefined> =\n Record<string, number>,\n> implements VideoAdapter<\n TModel,\n TProviderOptions,\n TModelProviderOptionsByName,\n TModelSizeByName,\n TModelInputModalitiesByName,\n TModelDurationByName\n> {\n readonly kind = 'video' 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 modelProviderOptionsByName: TModelProviderOptionsByName\n modelSizeByName: TModelSizeByName\n modelInputModalitiesByName: TModelInputModalitiesByName\n modelDurationByName: TModelDurationByName\n }\n\n protected config: VideoAdapterConfig\n\n constructor(config: VideoAdapterConfig = {}, model: TModel) {\n this.config = config\n this.model = model\n }\n\n abstract createVideoJob(\n options: VideoGenerationOptions<\n TProviderOptions,\n TModelSizeByName[TModel],\n TModelDurationByName[TModel]\n >,\n ): Promise<VideoJobResult>\n\n abstract getVideoStatus(jobId: string): Promise<VideoStatusResult>\n\n abstract getVideoUrl(jobId: string): Promise<VideoUrlResult>\n\n /**\n * Default implementation returns `{ kind: 'none' }`. Adapters that have\n * declared their per-model duration map should override this.\n */\n availableDurations(): DurationOptions<TModelDurationByName[TModel]> {\n return { kind: 'none' }\n }\n\n /**\n * Default implementation returns `undefined`. Adapters that have declared\n * their per-model duration map should override.\n */\n snapDuration(_seconds: number): TModelDurationByName[TModel] | undefined {\n return undefined\n }\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"
|
|
1
|
+
{"version":3,"file":"adapter.js","names":[],"sources":["../../../../src/activities/generateVideo/adapter.ts"],"sourcesContent":["import type {\n ModelInputModalitiesByName,\n VideoGenerationOptions,\n VideoJobResult,\n VideoStatusResult,\n VideoUrlResult,\n} from '../../types'\n\n/**\n * Structured description of the durations a video model accepts.\n *\n * Tagged union so the same shape can express discrete enums (OpenAI Sora,\n * Veo), continuous ranges, mixed shapes, and models with no duration field.\n * Consumed by `VideoAdapter.availableDurations()`.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type DurationOptions<T extends string | number | undefined> =\n | { kind: 'discrete'; values: ReadonlyArray<NonNullable<T>> }\n | { kind: 'range'; min: number; max: number; step?: number; unit: 'seconds' }\n | {\n kind: 'mixed'\n values: ReadonlyArray<NonNullable<T>>\n range?: { min: number; max: number; step?: number }\n }\n | { kind: 'none' }\n\n/**\n * Configuration for video adapter instances\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface VideoAdapterConfig {\n apiKey?: string\n baseUrl?: string\n timeout?: number\n maxRetries?: number\n headers?: Record<string, string>\n}\n\n/**\n * Video 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 * @experimental Video generation is an experimental feature and may change.\n *\n * Generic parameters:\n * - TModel: The specific model name (e.g., 'sora-2')\n * - TProviderOptions: Provider-specific options (already resolved)\n * - TModelProviderOptionsByName: Map from model name to its specific provider options\n * - TModelSizeByName: Map from model name to its supported sizes\n * - TModelInputModalitiesByName: Map from model name to the non-text prompt\n * modalities it accepts (constrains the `prompt` part types at compile time)\n * - TModelDurationByName: Map from model name to its supported duration\n * union. Defaults to `Record<string, number>` so adapters that haven't\n * declared a map keep today's `duration?: number` typing.\n */\nexport interface VideoAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,\n TModelSizeByName extends Record<string, string | undefined> = Record<\n string,\n string\n >,\n TModelInputModalitiesByName extends ModelInputModalitiesByName =\n ModelInputModalitiesByName,\n TModelDurationByName extends Record<string, string | number | undefined> =\n Record<string, number>,\n> {\n /** Discriminator for adapter kind - used to determine API shape */\n readonly kind: 'video'\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 modelProviderOptionsByName: TModelProviderOptionsByName\n modelSizeByName: TModelSizeByName\n modelInputModalitiesByName: TModelInputModalitiesByName\n modelDurationByName: TModelDurationByName\n }\n\n /**\n * Create a new video generation job.\n * Returns a job ID that can be used to poll for status and retrieve the video.\n */\n createVideoJob: (\n options: VideoGenerationOptions<\n TProviderOptions,\n TModelSizeByName[TModel],\n TModelDurationByName[TModel]\n >,\n ) => Promise<VideoJobResult>\n\n /**\n * Get the current status of a video generation job.\n */\n getVideoStatus: (jobId: string) => Promise<VideoStatusResult>\n\n /**\n * Get the URL to download/view the generated video.\n * Should only be called after status is 'completed'.\n */\n getVideoUrl: (jobId: string) => Promise<VideoUrlResult>\n\n /**\n * Describe the durations this adapter's model accepts. Returns a tagged\n * union so consumers can render UI / coerce input without provider-specific\n * knowledge.\n */\n availableDurations: () => DurationOptions<TModelDurationByName[TModel]>\n\n /**\n * Coerce a raw seconds value to the closest valid duration for this model.\n * Returns `undefined` for models with no duration field.\n */\n snapDuration: (seconds: number) => TModelDurationByName[TModel] | undefined\n}\n\n/**\n * A VideoAdapter with any/unknown type parameters.\n * Useful as a constraint in generic functions and interfaces.\n */\nexport type AnyVideoAdapter = VideoAdapter<any, any, any, any, any, any>\n\n/**\n * Abstract base class for video generation adapters.\n * Extend this class to implement a video adapter for a specific provider.\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * Generic parameters match VideoAdapter - all pre-resolved by the provider function.\n */\nexport abstract class BaseVideoAdapter<\n TModel extends string = string,\n TProviderOptions extends object = Record<string, unknown>,\n TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,\n TModelSizeByName extends Record<string, string | undefined> = Record<\n string,\n string\n >,\n TModelInputModalitiesByName extends ModelInputModalitiesByName =\n ModelInputModalitiesByName,\n TModelDurationByName extends Record<string, string | number | undefined> =\n Record<string, number>,\n> implements VideoAdapter<\n TModel,\n TProviderOptions,\n TModelProviderOptionsByName,\n TModelSizeByName,\n TModelInputModalitiesByName,\n TModelDurationByName\n> {\n readonly kind = 'video' 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 modelProviderOptionsByName: TModelProviderOptionsByName\n modelSizeByName: TModelSizeByName\n modelInputModalitiesByName: TModelInputModalitiesByName\n modelDurationByName: TModelDurationByName\n }\n\n protected config: VideoAdapterConfig\n\n constructor(config: VideoAdapterConfig = {}, model: TModel) {\n this.config = config\n this.model = model\n }\n\n abstract createVideoJob(\n options: VideoGenerationOptions<\n TProviderOptions,\n TModelSizeByName[TModel],\n TModelDurationByName[TModel]\n >,\n ): Promise<VideoJobResult>\n\n abstract getVideoStatus(jobId: string): Promise<VideoStatusResult>\n\n abstract getVideoUrl(jobId: string): Promise<VideoUrlResult>\n\n /**\n * Default implementation returns `{ kind: 'none' }`. Adapters that have\n * declared their per-model duration map should override this.\n */\n availableDurations(): DurationOptions<TModelDurationByName[TModel]> {\n return { kind: 'none' }\n }\n\n /**\n * Default implementation returns `undefined`. Adapters that have declared\n * their per-model duration map should override.\n */\n snapDuration(_seconds: number): TModelDurationByName[TModel] | undefined {\n return undefined\n }\n\n protected generateId(): string {\n return `${this.name}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n }\n}\n"],"mappings":";;;;;;;;;AA6IA,IAAsB,mBAAtB,MAmBE;CACA,OAAgB;CAEhB;CAWA;CAEA,YAAY,SAA6B,CAAC,GAAG,OAAe;EAC1D,KAAK,SAAS;EACd,KAAK,QAAQ;CACf;;;;;CAkBA,qBAAoE;EAClE,OAAO,EAAE,MAAM,OAAO;CACxB;;;;;CAMA,aAAa,UAA4D,CAEzE;CAEA,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 { VideoAdapter } from './adapter.js';
|
|
4
|
-
import { MediaPrompt, MediaPromptFor, StreamChunk, TokenUsage, VideoJobResult, VideoStatusResult, VideoUrlResult } from '../../types.js';
|
|
4
|
+
import { MediaPrompt, MediaPromptFor, PersistedArtifactRef, StreamChunk, TokenUsage, VideoJobResult, VideoStatusResult, VideoUrlResult } from '../../types.js';
|
|
5
5
|
/** The adapter kind this activity handles */
|
|
6
6
|
export declare const kind: "video";
|
|
7
7
|
/**
|
|
@@ -79,8 +79,28 @@ export type VideoCreateOptions<TAdapter extends VideoAdapter<string, any, any, a
|
|
|
79
79
|
pollingInterval?: number;
|
|
80
80
|
/** Maximum time to wait before timing out in milliseconds (stream mode only). @default 600000 */
|
|
81
81
|
maxDuration?: number;
|
|
82
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Custom run id (stream mode only) — the id stamped on the emitted
|
|
84
|
+
* `RUN_STARTED` / `RUN_FINISHED` chunks.
|
|
85
|
+
*
|
|
86
|
+
* IGNORED by a non-streaming submit. That run spans two calls, and its id is
|
|
87
|
+
* derived from the provider's job instead, so {@link getVideoJobStatus} can
|
|
88
|
+
* recompute it from the `jobId` you already have to poll with. Honoring a
|
|
89
|
+
* custom id here would reintroduce the failure this avoids: a caller who set
|
|
90
|
+
* it on the submit and forgot it on the poll would silently open a second
|
|
91
|
+
* record while the first sat unfinished forever.
|
|
92
|
+
*/
|
|
83
93
|
runId?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Stable conversation/thread id for correlating this run when persisted.
|
|
96
|
+
*
|
|
97
|
+
* Also the `threadId` stamped on the emitted `RUN_STARTED` / `RUN_FINISHED`
|
|
98
|
+
* chunks; when omitted a throwaway id is minted for those chunks only, and
|
|
99
|
+
* the persisted run record carries NO thread link rather than a fabricated
|
|
100
|
+
* one. Pass it whenever persistence is on — it is the slot a reloading client
|
|
101
|
+
* hydrates by, so a run stored without it can only be fetched by run id.
|
|
102
|
+
*/
|
|
103
|
+
threadId?: string;
|
|
84
104
|
/**
|
|
85
105
|
* Enable debug logging. Pass `true` to enable all categories, `false` to
|
|
86
106
|
* silence everything including errors, or a `DebugConfig` object for granular
|
|
@@ -89,10 +109,29 @@ export type VideoCreateOptions<TAdapter extends VideoAdapter<string, any, any, a
|
|
|
89
109
|
debug?: DebugOption;
|
|
90
110
|
/**
|
|
91
111
|
* Observe-only middleware notified on start, usage, success, and error. Pass
|
|
92
|
-
* `otelMiddleware()` to emit OpenTelemetry spans,
|
|
93
|
-
* `GenerationMiddleware` contract for a
|
|
94
|
-
*
|
|
95
|
-
*
|
|
112
|
+
* `otelMiddleware()` to emit OpenTelemetry spans, `withGenerationPersistence()`
|
|
113
|
+
* to persist the run, or implement the `GenerationMiddleware` contract for a
|
|
114
|
+
* custom backend.
|
|
115
|
+
*
|
|
116
|
+
* In streaming mode one run covers the full create→poll→complete lifecycle:
|
|
117
|
+
* `onStart` at submission, a terminal `onFinish`/`onError` when the job
|
|
118
|
+
* settles, and `onAbort` if the consumer abandons the stream.
|
|
119
|
+
*
|
|
120
|
+
* In NON-streaming mode the call only SUBMITS the job, so it only opens the
|
|
121
|
+
* run: no terminal hook fires here, because the video does not exist yet.
|
|
122
|
+
* Pass the same `middleware` and `threadId` to {@link getVideoJobStatus}; the
|
|
123
|
+
* poll that observes a terminal job state finishes the run and is where the
|
|
124
|
+
* result and its artifacts are recorded. Nothing else has to be threaded
|
|
125
|
+
* through — both calls derive the run id from the provider's `jobId`, the one
|
|
126
|
+
* id a poller cannot be missing.
|
|
127
|
+
*
|
|
128
|
+
* Because the job id only exists once the provider accepts the job, `onStart`
|
|
129
|
+
* fires AFTER the submit request rather than before it — an observer's span
|
|
130
|
+
* therefore covers the run from acceptance onward, not the submit round-trip.
|
|
131
|
+
* A submission that FAILS has no job to key on, so it opens and immediately
|
|
132
|
+
* fails a run under this call's `requestId`: the thread's latest run reports
|
|
133
|
+
* the failure (a client hydrating the slot sees it) even though there is no
|
|
134
|
+
* job to resume.
|
|
96
135
|
*/
|
|
97
136
|
middleware?: Array<GenerationMiddleware>;
|
|
98
137
|
} & ({} extends VideoProviderOptions<TAdapter> ? {
|
|
@@ -150,7 +189,7 @@ export type VideoActivityResult<TRequest extends 'create' | 'status' | 'url' = '
|
|
|
150
189
|
*
|
|
151
190
|
* @example Create a video generation job
|
|
152
191
|
* ```ts
|
|
153
|
-
* import { generateVideo } from '@tanstack/ai'
|
|
192
|
+
* import { generateVideo, getVideoJobStatus } from '@tanstack/ai'
|
|
154
193
|
* import { openaiVideo } from '@tanstack/ai-openai'
|
|
155
194
|
*
|
|
156
195
|
* // Start a video generation job
|
|
@@ -160,6 +199,14 @@ export type VideoActivityResult<TRequest extends 'create' | 'status' | 'url' = '
|
|
|
160
199
|
* })
|
|
161
200
|
*
|
|
162
201
|
* console.log('Job started:', jobId)
|
|
202
|
+
*
|
|
203
|
+
* // The submission only OPENS the run; the poll that sees a terminal state is
|
|
204
|
+
* // what completes it. The `jobId` is the whole correlation — pass the same
|
|
205
|
+
* // `middleware` and `threadId` when you use them.
|
|
206
|
+
* const status = await getVideoJobStatus({
|
|
207
|
+
* adapter: openaiVideo('sora-2'),
|
|
208
|
+
* jobId,
|
|
209
|
+
* })
|
|
163
210
|
* ```
|
|
164
211
|
*
|
|
165
212
|
* @example Stream the full video generation lifecycle
|
|
@@ -178,12 +225,71 @@ export type VideoActivityResult<TRequest extends 'create' | 'status' | 'url' = '
|
|
|
178
225
|
* ```
|
|
179
226
|
*/
|
|
180
227
|
export declare function generateVideo<TAdapter extends VideoAdapter<string, any, any, any, any, any>, TStream extends boolean = false>(options: VideoCreateOptions<TAdapter, TStream>): VideoActivityResult<'create', TStream>;
|
|
228
|
+
/**
|
|
229
|
+
* Options for {@link getVideoJobStatus}.
|
|
230
|
+
*
|
|
231
|
+
* The run this poll finishes is identified by `adapter` + `jobId` alone — the
|
|
232
|
+
* same pair the submitting `generateVideo()` call derived it from — so there is
|
|
233
|
+
* no run id to thread through. Pass the submission's `threadId` and the same
|
|
234
|
+
* `middleware`.
|
|
235
|
+
*
|
|
236
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
237
|
+
*/
|
|
238
|
+
export interface VideoJobStatusOptions<TAdapter extends VideoAdapter<string, any, any, any, any, any>> {
|
|
239
|
+
/** The video adapter to use (must be created with a model) */
|
|
240
|
+
adapter: TAdapter & {
|
|
241
|
+
kind: typeof kind;
|
|
242
|
+
};
|
|
243
|
+
/** The job ID to check status for */
|
|
244
|
+
jobId: string;
|
|
245
|
+
/**
|
|
246
|
+
* The scope the run is filed under. Must match the submission's `threadId` —
|
|
247
|
+
* generation persistence REFUSES a run without a scope (a run filed under
|
|
248
|
+
* none can never be hydrated by one), so omitting it throws rather than
|
|
249
|
+
* quietly filing the finished video somewhere unreachable.
|
|
250
|
+
*/
|
|
251
|
+
threadId?: string;
|
|
252
|
+
/**
|
|
253
|
+
* Observe-only middleware. Hooks fire ONLY on the poll that observes a
|
|
254
|
+
* terminal job state: `onStart` (resuming the submission's run), then the
|
|
255
|
+
* result transforms — which is where persistence copies the video into a blob
|
|
256
|
+
* store and rewrites `url` to a durable one, so the returned result carries
|
|
257
|
+
* the same urls as the stored record — then `onFinish`, or `onError` when the
|
|
258
|
+
* job failed. Intermediate polls invoke nothing, so a middleware is not
|
|
259
|
+
* charged for the wait.
|
|
260
|
+
*/
|
|
261
|
+
middleware?: Array<GenerationMiddleware>;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The status of a video job, plus the video itself once the job completed.
|
|
265
|
+
*
|
|
266
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
267
|
+
*/
|
|
268
|
+
export interface VideoJobStatusResult {
|
|
269
|
+
/** Job identifier */
|
|
270
|
+
jobId: string;
|
|
271
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
272
|
+
progress?: number;
|
|
273
|
+
url?: string;
|
|
274
|
+
/** When the provider url expires, if it reported one. */
|
|
275
|
+
expiresAt?: Date;
|
|
276
|
+
error?: string;
|
|
277
|
+
usage?: TokenUsage;
|
|
278
|
+
/** Durable artifact references, when generation persistence is wired. */
|
|
279
|
+
artifacts?: Array<PersistedArtifactRef>;
|
|
280
|
+
}
|
|
181
281
|
/**
|
|
182
282
|
* Get video job status - returns the current status, progress, and URL if available.
|
|
183
283
|
*
|
|
184
284
|
* This function combines status checking and URL retrieval. If the job is completed,
|
|
185
285
|
* it will automatically fetch and include the video URL.
|
|
186
286
|
*
|
|
287
|
+
* It is also where a non-streaming `generateVideo()` run ENDS: pass the same
|
|
288
|
+
* `middleware` and `threadId`, and the poll that first sees a terminal job state
|
|
289
|
+
* finishes the run (recording the result and its artifacts) or fails it. The run
|
|
290
|
+
* is identified by `adapter` + `jobId`, exactly what the submission derived it
|
|
291
|
+
* from, so there is nothing else to carry between the two calls.
|
|
292
|
+
*
|
|
187
293
|
* @experimental Video generation is an experimental feature and may change.
|
|
188
294
|
*
|
|
189
295
|
* @example Check job status
|
|
@@ -202,19 +308,37 @@ export declare function generateVideo<TAdapter extends VideoAdapter<string, any,
|
|
|
202
308
|
* console.log('Video URL:', result.url)
|
|
203
309
|
* }
|
|
204
310
|
* ```
|
|
311
|
+
*
|
|
312
|
+
* @example Submit and poll one persisted run
|
|
313
|
+
* ```ts
|
|
314
|
+
* import { generateVideo, getVideoJobStatus } from '@tanstack/ai'
|
|
315
|
+
* import { withGenerationPersistence } from '@tanstack/ai-persistence'
|
|
316
|
+
* import { openaiVideo } from '@tanstack/ai-openai'
|
|
317
|
+
*
|
|
318
|
+
* const adapter = openaiVideo('sora-2')
|
|
319
|
+
* const middleware = [withGenerationPersistence(persistence)]
|
|
320
|
+
*
|
|
321
|
+
* // Opens the run (status `running`, jobId recorded). Its run id is derived
|
|
322
|
+
* // from the provider job, so nothing has to be stored to resume it.
|
|
323
|
+
* const { jobId } = await generateVideo({
|
|
324
|
+
* adapter,
|
|
325
|
+
* prompt: 'A cat chasing a dog in a sunny park',
|
|
326
|
+
* threadId,
|
|
327
|
+
* middleware,
|
|
328
|
+
* })
|
|
329
|
+
*
|
|
330
|
+
* // Completes the SAME run once the job settles — this is what writes the
|
|
331
|
+
* // video, its artifacts, and the terminal status. Works from a different
|
|
332
|
+
* // request or process: the jobId is the only correlation.
|
|
333
|
+
* const status = await getVideoJobStatus({
|
|
334
|
+
* adapter,
|
|
335
|
+
* jobId,
|
|
336
|
+
* threadId,
|
|
337
|
+
* middleware,
|
|
338
|
+
* })
|
|
339
|
+
* ```
|
|
205
340
|
*/
|
|
206
|
-
export declare function getVideoJobStatus<TAdapter extends VideoAdapter<string, any, any, any, any, any>>(options:
|
|
207
|
-
adapter: TAdapter & {
|
|
208
|
-
kind: typeof kind;
|
|
209
|
-
};
|
|
210
|
-
jobId: string;
|
|
211
|
-
}): Promise<{
|
|
212
|
-
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
213
|
-
progress?: number;
|
|
214
|
-
url?: string;
|
|
215
|
-
error?: string;
|
|
216
|
-
usage?: TokenUsage;
|
|
217
|
-
}>;
|
|
341
|
+
export declare function getVideoJobStatus<TAdapter extends VideoAdapter<string, any, any, any, any, any>>(options: VideoJobStatusOptions<TAdapter>): Promise<VideoJobStatusResult>;
|
|
218
342
|
/**
|
|
219
343
|
* Create typed options for the generateVideo() function without executing.
|
|
220
344
|
*/
|