@tanstack/ai 0.36.0 → 0.38.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/dist/esm/activities/chat/adapter.d.ts +163 -0
- package/dist/esm/activities/chat/adapter.js +17 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -0
- package/dist/esm/activities/chat/agent-loop-strategies.d.ts +59 -0
- package/dist/esm/activities/chat/agent-loop-strategies.js +23 -0
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +270 -0
- package/dist/esm/activities/chat/index.js +1724 -0
- package/dist/esm/activities/chat/index.js.map +1 -0
- package/dist/esm/activities/chat/mcp/manager.d.ts +25 -0
- package/dist/esm/activities/chat/mcp/manager.js +80 -0
- package/dist/esm/activities/chat/mcp/manager.js.map +1 -0
- package/dist/esm/activities/chat/mcp/types.d.ts +78 -0
- package/dist/esm/activities/chat/messages.d.ts +78 -0
- package/dist/esm/activities/chat/messages.js +374 -0
- package/dist/esm/activities/chat/messages.js.map +1 -0
- package/dist/esm/activities/chat/middleware/builder.d.ts +46 -0
- package/dist/esm/activities/chat/middleware/builder.js +17 -0
- package/dist/esm/activities/chat/middleware/builder.js.map +1 -0
- package/dist/esm/activities/chat/middleware/capabilities.d.ts +93 -0
- package/dist/esm/activities/chat/middleware/capabilities.js +45 -0
- package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -0
- package/dist/esm/activities/chat/middleware/compose.d.ts +87 -0
- package/dist/esm/activities/chat/middleware/compose.js +510 -0
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -0
- package/dist/esm/activities/chat/middleware/define.d.ts +20 -0
- package/dist/esm/activities/chat/middleware/define.js +7 -0
- package/dist/esm/activities/chat/middleware/define.js.map +1 -0
- package/dist/esm/activities/chat/middleware/index.d.ts +10 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.d.ts +89 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +76 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -0
- package/dist/esm/activities/chat/middleware/types.d.ts +405 -0
- package/dist/esm/activities/chat/middleware/validate.d.ts +19 -0
- package/dist/esm/activities/chat/middleware/validate.js +30 -0
- package/dist/esm/activities/chat/middleware/validate.js.map +1 -0
- package/dist/esm/activities/chat/runtime-context-types.d.ts +43 -0
- package/dist/esm/activities/chat/stream/index.d.ts +11 -0
- package/dist/esm/activities/chat/stream/json-parser.d.ts +38 -0
- package/dist/esm/activities/chat/stream/json-parser.js +28 -0
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -0
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +81 -0
- package/dist/esm/activities/chat/stream/message-updaters.js +253 -0
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -0
- package/dist/esm/activities/chat/stream/processor.d.ts +439 -0
- package/dist/esm/activities/chat/stream/processor.js +1449 -0
- package/dist/esm/activities/chat/stream/processor.js.map +1 -0
- package/dist/esm/activities/chat/stream/strategies.d.ts +43 -0
- package/dist/esm/activities/chat/stream/strategies.js +54 -0
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -0
- package/dist/esm/activities/chat/stream/types.d.ts +90 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.d.ts +82 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +194 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -0
- package/dist/esm/activities/chat/tools/lazy-tools.d.ts +15 -0
- package/dist/esm/activities/chat/tools/lazy-tools.js +16 -0
- package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -0
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +140 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +167 -0
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +145 -0
- package/dist/esm/activities/chat/tools/tool-calls.js +548 -0
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -0
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +135 -0
- package/dist/esm/activities/chat/tools/tool-definition.js +25 -0
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -0
- package/dist/esm/activities/error-payload.d.ts +30 -0
- package/dist/esm/activities/error-payload.js +54 -0
- package/dist/esm/activities/error-payload.js.map +1 -0
- package/dist/esm/activities/generateAudio/adapter.d.ts +62 -0
- package/dist/esm/activities/generateAudio/adapter.js +16 -0
- package/dist/esm/activities/generateAudio/adapter.js.map +1 -0
- package/dist/esm/activities/generateAudio/index.d.ts +85 -0
- package/dist/esm/activities/generateAudio/index.js +114 -0
- package/dist/esm/activities/generateAudio/index.js.map +1 -0
- package/dist/esm/activities/generateImage/adapter.d.ts +78 -0
- package/dist/esm/activities/generateImage/adapter.js +16 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -0
- package/dist/esm/activities/generateImage/index.d.ts +134 -0
- package/dist/esm/activities/generateImage/index.js +121 -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 +16 -0
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -0
- package/dist/esm/activities/generateSpeech/index.d.ts +96 -0
- package/dist/esm/activities/generateSpeech/index.js +119 -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 +16 -0
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -0
- package/dist/esm/activities/generateTranscription/index.d.ts +109 -0
- package/dist/esm/activities/generateTranscription/index.js +109 -0
- package/dist/esm/activities/generateTranscription/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/adapter.d.ts +145 -0
- package/dist/esm/activities/generateVideo/adapter.js +30 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -0
- package/dist/esm/activities/generateVideo/index.d.ts +223 -0
- package/dist/esm/activities/generateVideo/index.js +295 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/snap.d.ts +14 -0
- package/dist/esm/activities/generateVideo/snap.js +54 -0
- package/dist/esm/activities/generateVideo/snap.js.map +1 -0
- package/dist/esm/activities/index.d.ts +27 -0
- package/dist/esm/activities/index.js +43 -0
- package/dist/esm/activities/index.js.map +1 -0
- package/dist/esm/activities/middleware/index.d.ts +2 -0
- package/dist/esm/activities/middleware/run.d.ts +20 -0
- package/dist/esm/activities/middleware/run.js +42 -0
- package/dist/esm/activities/middleware/run.js.map +1 -0
- package/dist/esm/activities/middleware/types.d.ts +118 -0
- package/dist/esm/activities/stream-generation-result.d.ts +15 -0
- package/dist/esm/activities/stream-generation-result.js +49 -0
- package/dist/esm/activities/stream-generation-result.js.map +1 -0
- package/dist/esm/activities/summarize/adapter.d.ts +74 -0
- package/dist/esm/activities/summarize/adapter.js +16 -0
- package/dist/esm/activities/summarize/adapter.js.map +1 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +45 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +212 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -0
- package/dist/esm/activities/summarize/index.d.ts +108 -0
- package/dist/esm/activities/summarize/index.js +113 -0
- package/dist/esm/activities/summarize/index.js.map +1 -0
- package/dist/esm/adapter-internals.d.ts +5 -0
- package/dist/esm/adapter-internals.js +10 -0
- package/dist/esm/adapter-internals.js.map +1 -0
- package/dist/esm/client.d.ts +44 -0
- package/dist/esm/client.js +67 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/extend-adapter.d.ts +152 -0
- package/dist/esm/extend-adapter.js +21 -0
- package/dist/esm/extend-adapter.js.map +1 -0
- package/dist/esm/index.d.ts +45 -0
- package/dist/esm/index.js +109 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logger/console-logger.d.ts +29 -0
- package/dist/esm/logger/console-logger.js +83 -0
- package/dist/esm/logger/console-logger.js.map +1 -0
- package/dist/esm/logger/internal-logger.d.ts +41 -0
- package/dist/esm/logger/internal-logger.js +86 -0
- package/dist/esm/logger/internal-logger.js.map +1 -0
- package/dist/esm/logger/resolve.d.ts +14 -0
- package/dist/esm/logger/resolve.js +54 -0
- package/dist/esm/logger/resolve.js.map +1 -0
- package/dist/esm/logger/types.d.ts +75 -0
- package/dist/esm/middlewares/content-guard.d.ts +77 -0
- package/dist/esm/middlewares/content-guard.js +156 -0
- package/dist/esm/middlewares/content-guard.js.map +1 -0
- package/dist/esm/middlewares/index.d.ts +2 -0
- package/dist/esm/middlewares/index.js +7 -0
- package/dist/esm/middlewares/index.js.map +1 -0
- package/dist/esm/middlewares/otel.d.ts +81 -0
- package/dist/esm/middlewares/otel.js +745 -0
- package/dist/esm/middlewares/otel.js.map +1 -0
- package/dist/esm/middlewares/tool-cache.d.ts +1 -0
- package/dist/esm/middlewares/usage-attributes.d.ts +24 -0
- package/dist/esm/middlewares/usage-attributes.js +43 -0
- package/dist/esm/middlewares/usage-attributes.js.map +1 -0
- package/dist/esm/realtime/index.d.ts +28 -0
- package/dist/esm/realtime/index.js +8 -0
- package/dist/esm/realtime/index.js.map +1 -0
- package/dist/esm/realtime/types.d.ts +282 -0
- package/dist/esm/stream-to-response.d.ts +102 -0
- package/dist/esm/stream-to-response.js +121 -0
- package/dist/esm/stream-to-response.js.map +1 -0
- package/dist/esm/strip-to-spec-middleware.d.ts +18 -0
- package/dist/esm/strip-to-spec-middleware.js +20 -0
- package/dist/esm/strip-to-spec-middleware.js.map +1 -0
- package/dist/esm/system-prompts.d.ts +66 -0
- package/dist/esm/system-prompts.js +23 -0
- package/dist/esm/system-prompts.js.map +1 -0
- package/dist/esm/tool-registry.d.ts +81 -0
- package/dist/esm/tool-registry.js +49 -0
- package/dist/esm/tool-registry.js.map +1 -0
- package/dist/esm/tools/provider-tool.d.ts +30 -0
- package/dist/esm/tools/provider-tool.js +7 -0
- package/dist/esm/tools/provider-tool.js.map +1 -0
- package/dist/esm/types.d.ts +1627 -0
- package/dist/esm/utilities/ag-ui-wire.d.ts +44 -0
- package/dist/esm/utilities/ag-ui-wire.js +107 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -0
- package/dist/esm/utilities/chat-params.d.ts +85 -0
- package/dist/esm/utilities/chat-params.js +100 -0
- package/dist/esm/utilities/chat-params.js.map +1 -0
- package/dist/esm/utilities/errors.d.ts +13 -0
- package/dist/esm/utilities/errors.js +22 -0
- package/dist/esm/utilities/errors.js.map +1 -0
- package/dist/esm/utilities/media-prompt.d.ts +35 -0
- package/dist/esm/utilities/media-prompt.js +43 -0
- package/dist/esm/utilities/media-prompt.js.map +1 -0
- package/dist/esm/utilities/numbers.d.ts +8 -0
- package/dist/esm/utilities/numbers.js +12 -0
- package/dist/esm/utilities/numbers.js.map +1 -0
- package/dist/esm/utilities/sampling-keys.d.ts +20 -0
- package/dist/esm/utilities/sampling-keys.js +20 -0
- package/dist/esm/utilities/sampling-keys.js.map +1 -0
- package/dist/esm/utilities/tool-result.d.ts +21 -0
- package/dist/esm/utilities/tool-result.js +37 -0
- package/dist/esm/utilities/tool-result.js.map +1 -0
- package/dist/esm/utilities/usage.d.ts +31 -0
- package/dist/esm/utilities/usage.js +11 -0
- package/dist/esm/utilities/usage.js.map +1 -0
- package/dist/esm/utils.d.ts +17 -0
- package/dist/esm/utils.js +20 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +3 -3
- package/skills/ai-core/chat-experience/SKILL.md +30 -2
- package/skills/ai-core/media-generation/SKILL.md +13 -0
- package/skills/ai-core/tool-calling/SKILL.md +10 -3
- package/src/activities/chat/mcp/manager.ts +31 -1
- package/src/activities/chat/mcp/types.ts +23 -0
- package/src/activities/chat/messages.ts +5 -0
- package/src/activities/chat/stream/processor.ts +42 -0
- package/src/activities/chat/tools/tool-calls.ts +96 -2
- package/src/client.ts +1 -0
- package/src/types.ts +31 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { aiEventClient } from "@tanstack/ai-event-client";
|
|
2
|
+
import { toRunErrorPayload } from "../error-payload.js";
|
|
3
|
+
import { resolveDebugOption } from "../../logger/resolve.js";
|
|
4
|
+
import { createGenerationContext, runGenerationStart, runGenerationUsage, runGenerationFinish, runGenerationError, runGenerationAbort } from "../middleware/run.js";
|
|
5
|
+
const kind = "video";
|
|
6
|
+
function createId(prefix) {
|
|
7
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
8
|
+
}
|
|
9
|
+
function generateVideo(options) {
|
|
10
|
+
if (options.stream) {
|
|
11
|
+
return runStreamingVideoGeneration(
|
|
12
|
+
options
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return runCreateVideoJob(options);
|
|
16
|
+
}
|
|
17
|
+
async function runCreateVideoJob(options) {
|
|
18
|
+
const { adapter, prompt, size, duration, modelOptions, middleware } = options;
|
|
19
|
+
const model = adapter.model;
|
|
20
|
+
const requestId = createId("video");
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const logger = resolveDebugOption(options.debug);
|
|
23
|
+
const providerName = adapter.provider ?? adapter.name ?? "unknown";
|
|
24
|
+
const mwCtx = createGenerationContext({
|
|
25
|
+
requestId,
|
|
26
|
+
activity: "video",
|
|
27
|
+
provider: adapter.name,
|
|
28
|
+
model,
|
|
29
|
+
modelOptions,
|
|
30
|
+
createId
|
|
31
|
+
});
|
|
32
|
+
await runGenerationStart(middleware, mwCtx);
|
|
33
|
+
logger.request(`activity=generateVideo provider=${providerName}`, {
|
|
34
|
+
provider: providerName,
|
|
35
|
+
model
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const result = await adapter.createVideoJob({
|
|
39
|
+
model,
|
|
40
|
+
prompt,
|
|
41
|
+
size,
|
|
42
|
+
duration,
|
|
43
|
+
modelOptions,
|
|
44
|
+
logger
|
|
45
|
+
});
|
|
46
|
+
logger.output(`activity=generateVideo jobId=${result.jobId}`, {
|
|
47
|
+
jobId: result.jobId,
|
|
48
|
+
model: result.model
|
|
49
|
+
});
|
|
50
|
+
await runGenerationFinish(middleware, mwCtx, {
|
|
51
|
+
duration: Date.now() - startTime
|
|
52
|
+
});
|
|
53
|
+
return result;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
await runGenerationError(middleware, mwCtx, {
|
|
56
|
+
error,
|
|
57
|
+
duration: Date.now() - startTime
|
|
58
|
+
});
|
|
59
|
+
logger.errors("generateVideo activity failed", {
|
|
60
|
+
error,
|
|
61
|
+
source: "generateVideo"
|
|
62
|
+
});
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function sleep(ms) {
|
|
67
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
68
|
+
}
|
|
69
|
+
async function* runStreamingVideoGeneration(options) {
|
|
70
|
+
const { adapter, prompt, size, duration, modelOptions, middleware } = options;
|
|
71
|
+
const model = adapter.model;
|
|
72
|
+
const runId = options.runId ?? createId("run");
|
|
73
|
+
const requestId = createId("video");
|
|
74
|
+
const obsStartTime = Date.now();
|
|
75
|
+
const pollingInterval = options.pollingInterval ?? 2e3;
|
|
76
|
+
const maxDuration = options.maxDuration ?? 6e5;
|
|
77
|
+
const logger = resolveDebugOption(options.debug);
|
|
78
|
+
const providerName = adapter.provider ?? adapter.name ?? "unknown";
|
|
79
|
+
const threadId = createId("thread");
|
|
80
|
+
yield {
|
|
81
|
+
type: "RUN_STARTED",
|
|
82
|
+
runId,
|
|
83
|
+
threadId,
|
|
84
|
+
timestamp: Date.now()
|
|
85
|
+
};
|
|
86
|
+
const mwCtx = createGenerationContext({
|
|
87
|
+
requestId,
|
|
88
|
+
activity: "video",
|
|
89
|
+
provider: adapter.name,
|
|
90
|
+
model,
|
|
91
|
+
modelOptions,
|
|
92
|
+
createId
|
|
93
|
+
});
|
|
94
|
+
await runGenerationStart(middleware, mwCtx);
|
|
95
|
+
logger.request(
|
|
96
|
+
`activity=generateVideo provider=${providerName} stream=true`,
|
|
97
|
+
{
|
|
98
|
+
provider: providerName,
|
|
99
|
+
model
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
let settled = false;
|
|
103
|
+
try {
|
|
104
|
+
const jobResult = await adapter.createVideoJob({
|
|
105
|
+
model,
|
|
106
|
+
prompt,
|
|
107
|
+
size,
|
|
108
|
+
duration,
|
|
109
|
+
modelOptions,
|
|
110
|
+
logger
|
|
111
|
+
});
|
|
112
|
+
yield {
|
|
113
|
+
type: "CUSTOM",
|
|
114
|
+
name: "video:job:created",
|
|
115
|
+
value: { jobId: jobResult.jobId },
|
|
116
|
+
timestamp: Date.now()
|
|
117
|
+
};
|
|
118
|
+
const startTime = Date.now();
|
|
119
|
+
while (Date.now() - startTime < maxDuration) {
|
|
120
|
+
await sleep(pollingInterval);
|
|
121
|
+
const statusResult = await adapter.getVideoStatus(jobResult.jobId);
|
|
122
|
+
yield {
|
|
123
|
+
type: "CUSTOM",
|
|
124
|
+
name: "video:status",
|
|
125
|
+
value: {
|
|
126
|
+
jobId: jobResult.jobId,
|
|
127
|
+
status: statusResult.status,
|
|
128
|
+
progress: statusResult.progress,
|
|
129
|
+
error: statusResult.error
|
|
130
|
+
},
|
|
131
|
+
timestamp: Date.now()
|
|
132
|
+
};
|
|
133
|
+
if (statusResult.status === "completed") {
|
|
134
|
+
const urlResult = await adapter.getVideoUrl(jobResult.jobId);
|
|
135
|
+
logger.output(
|
|
136
|
+
`activity=generateVideo jobId=${jobResult.jobId} status=completed`,
|
|
137
|
+
{
|
|
138
|
+
jobId: jobResult.jobId,
|
|
139
|
+
url: urlResult.url
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
if (urlResult.usage)
|
|
143
|
+
await runGenerationUsage(middleware, mwCtx, urlResult.usage);
|
|
144
|
+
await runGenerationFinish(middleware, mwCtx, {
|
|
145
|
+
duration: Date.now() - obsStartTime,
|
|
146
|
+
usage: urlResult.usage
|
|
147
|
+
});
|
|
148
|
+
settled = true;
|
|
149
|
+
yield {
|
|
150
|
+
type: "CUSTOM",
|
|
151
|
+
name: "generation:result",
|
|
152
|
+
value: {
|
|
153
|
+
jobId: jobResult.jobId,
|
|
154
|
+
status: "completed",
|
|
155
|
+
url: urlResult.url,
|
|
156
|
+
expiresAt: urlResult.expiresAt,
|
|
157
|
+
...urlResult.usage ? { usage: urlResult.usage } : {}
|
|
158
|
+
},
|
|
159
|
+
timestamp: Date.now()
|
|
160
|
+
};
|
|
161
|
+
yield {
|
|
162
|
+
type: "RUN_FINISHED",
|
|
163
|
+
runId,
|
|
164
|
+
threadId,
|
|
165
|
+
finishReason: "stop",
|
|
166
|
+
timestamp: Date.now()
|
|
167
|
+
};
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (statusResult.status === "failed") {
|
|
171
|
+
throw new Error(statusResult.error || "Video generation failed");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
throw new Error("Video generation timed out");
|
|
175
|
+
} catch (error) {
|
|
176
|
+
const payload = toRunErrorPayload(error, "Video generation failed");
|
|
177
|
+
settled = true;
|
|
178
|
+
await runGenerationError(middleware, mwCtx, {
|
|
179
|
+
error,
|
|
180
|
+
duration: Date.now() - obsStartTime
|
|
181
|
+
});
|
|
182
|
+
logger.errors("generateVideo activity failed", {
|
|
183
|
+
message: payload.message,
|
|
184
|
+
code: payload.code,
|
|
185
|
+
source: "generateVideo"
|
|
186
|
+
});
|
|
187
|
+
yield {
|
|
188
|
+
type: "RUN_ERROR",
|
|
189
|
+
runId,
|
|
190
|
+
threadId,
|
|
191
|
+
message: payload.message,
|
|
192
|
+
code: payload.code,
|
|
193
|
+
error: payload,
|
|
194
|
+
timestamp: Date.now()
|
|
195
|
+
};
|
|
196
|
+
} finally {
|
|
197
|
+
if (!settled) {
|
|
198
|
+
await runGenerationAbort(middleware, mwCtx, {
|
|
199
|
+
reason: "Video generation stream abandoned before completion",
|
|
200
|
+
duration: Date.now() - obsStartTime
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function getVideoJobStatus(options) {
|
|
206
|
+
const { adapter, jobId } = options;
|
|
207
|
+
const requestId = createId("video-status");
|
|
208
|
+
const startTime = Date.now();
|
|
209
|
+
aiEventClient.emit("video:request:started", {
|
|
210
|
+
requestId,
|
|
211
|
+
provider: adapter.name,
|
|
212
|
+
model: adapter.model,
|
|
213
|
+
requestType: "status",
|
|
214
|
+
jobId,
|
|
215
|
+
timestamp: startTime
|
|
216
|
+
});
|
|
217
|
+
const statusResult = await adapter.getVideoStatus(jobId);
|
|
218
|
+
if (statusResult.status === "completed") {
|
|
219
|
+
try {
|
|
220
|
+
const urlResult = await adapter.getVideoUrl(jobId);
|
|
221
|
+
aiEventClient.emit("video:request:completed", {
|
|
222
|
+
requestId,
|
|
223
|
+
provider: adapter.name,
|
|
224
|
+
model: adapter.model,
|
|
225
|
+
requestType: "status",
|
|
226
|
+
jobId,
|
|
227
|
+
status: statusResult.status,
|
|
228
|
+
progress: statusResult.progress,
|
|
229
|
+
url: urlResult.url,
|
|
230
|
+
duration: Date.now() - startTime,
|
|
231
|
+
timestamp: Date.now()
|
|
232
|
+
});
|
|
233
|
+
if (urlResult.usage) {
|
|
234
|
+
aiEventClient.emit("video:usage", {
|
|
235
|
+
requestId,
|
|
236
|
+
model: adapter.model,
|
|
237
|
+
usage: urlResult.usage,
|
|
238
|
+
timestamp: Date.now()
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
status: statusResult.status,
|
|
243
|
+
progress: statusResult.progress,
|
|
244
|
+
url: urlResult.url,
|
|
245
|
+
...urlResult.usage ? { usage: urlResult.usage } : {}
|
|
246
|
+
};
|
|
247
|
+
} catch (error) {
|
|
248
|
+
const errorMessage = error instanceof Error ? error.message : "Failed to get video URL";
|
|
249
|
+
aiEventClient.emit("video:request:completed", {
|
|
250
|
+
requestId,
|
|
251
|
+
provider: adapter.name,
|
|
252
|
+
model: adapter.model,
|
|
253
|
+
requestType: "status",
|
|
254
|
+
jobId,
|
|
255
|
+
status: "failed",
|
|
256
|
+
progress: statusResult.progress,
|
|
257
|
+
error: errorMessage,
|
|
258
|
+
duration: Date.now() - startTime,
|
|
259
|
+
timestamp: Date.now()
|
|
260
|
+
});
|
|
261
|
+
return {
|
|
262
|
+
status: "failed",
|
|
263
|
+
progress: statusResult.progress,
|
|
264
|
+
error: errorMessage
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
aiEventClient.emit("video:request:completed", {
|
|
269
|
+
requestId,
|
|
270
|
+
provider: adapter.name,
|
|
271
|
+
model: adapter.model,
|
|
272
|
+
requestType: "status",
|
|
273
|
+
jobId,
|
|
274
|
+
status: statusResult.status,
|
|
275
|
+
progress: statusResult.progress,
|
|
276
|
+
error: statusResult.error,
|
|
277
|
+
duration: Date.now() - startTime,
|
|
278
|
+
timestamp: Date.now()
|
|
279
|
+
});
|
|
280
|
+
return {
|
|
281
|
+
status: statusResult.status,
|
|
282
|
+
progress: statusResult.progress,
|
|
283
|
+
error: statusResult.error
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function createVideoOptions(options) {
|
|
287
|
+
return options;
|
|
288
|
+
}
|
|
289
|
+
export {
|
|
290
|
+
createVideoOptions,
|
|
291
|
+
generateVideo,
|
|
292
|
+
getVideoJobStatus,
|
|
293
|
+
kind
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/activities/generateVideo/index.ts"],"sourcesContent":["/**\n * Video Activity (Experimental)\n *\n * Generates videos from text prompts using a jobs/polling architecture.\n * This is a self-contained module with implementation, types, and JSDoc.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { toRunErrorPayload } from '../error-payload'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n createGenerationContext,\n runGenerationAbort,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware'\nimport type { VideoAdapter } from './adapter'\nimport type {\n MediaPrompt,\n MediaPromptFor,\n StreamChunk,\n TokenUsage,\n VideoJobResult,\n VideoStatusResult,\n VideoUrlResult,\n} from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'video' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a VideoAdapter via ~types.\n */\nexport type VideoProviderOptions<TAdapter> =\n TAdapter extends VideoAdapter<any, any, any, any>\n ? TAdapter['~types']['providerOptions']\n : object\n\n/**\n * Extract the size type for a VideoAdapter's model via ~types.\n */\nexport type VideoSizeForAdapter<TAdapter> =\n TAdapter extends VideoAdapter<infer TModel, any, any, infer TSizeMap>\n ? TModel extends keyof TSizeMap\n ? TSizeMap[TModel]\n : string\n : string\n\n/**\n * Extract the prompt type a model accepts from a VideoAdapter via ~types.\n * Mirrors `ImagePromptForModel`: models in the adapter's input-modality map\n * get a `prompt` narrowed to text + their supported part types; adapters\n * without a map fall back to the full MediaPrompt.\n */\nexport type VideoPromptForAdapter<TAdapter> =\n TAdapter extends VideoAdapter<infer TModel, any, any, any, infer ModsByName>\n ? string extends keyof ModsByName\n ? MediaPrompt\n : TModel extends keyof ModsByName\n ? MediaPromptFor<ModsByName[TModel][number]>\n : MediaPrompt\n : MediaPrompt\n\n/**\n * Extract the duration type for a VideoAdapter's model via ~types.\n * Mirrors `VideoSizeForAdapter`. Falls back to `number` for adapters that\n * haven't declared per-model duration constraints.\n */\nexport type VideoDurationForAdapter<TAdapter> =\n TAdapter extends VideoAdapter<\n infer TModel,\n any,\n any,\n any,\n any,\n infer TDurationMap\n >\n ? TModel extends keyof TDurationMap\n ? TDurationMap[TModel]\n : number\n : number\n\n// ===========================\n// Activity Options Types\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n// ===========================\n\n/**\n * Base options shared by all video activity operations.\n * The model is extracted from the adapter's model property.\n */\ninterface VideoActivityBaseOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n> {\n /** The video adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n}\n\n/**\n * Options for creating a new video generation job.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The video adapter type\n * @template TStream - Whether to stream the output\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type VideoCreateOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n TStream extends boolean = false,\n> = VideoActivityBaseOptions<TAdapter> & {\n /** Request type - create a new job (default if not specified) */\n request?: 'create'\n /**\n * Description of the desired video. Either a plain string, or — for models\n * that support image-conditioned generation — an ordered array of content\n * parts interleaving text with image inputs. Image parts may carry\n * `metadata.role` (`'start_frame' | 'end_frame' | 'reference' |\n * 'character'`) to disambiguate intent; positional fallback otherwise. The\n * accepted part types are narrowed per model via the adapter's\n * input-modality map.\n */\n prompt: VideoPromptForAdapter<TAdapter>\n /** Video size — format depends on the provider (e.g., \"16:9\", \"1280x720\") */\n size?: VideoSizeForAdapter<TAdapter>\n /**\n * Video duration in seconds. Adapters that declare a per-model duration\n * map narrow this to the model's valid union (e.g. `4 | 6 | 8` for Veo 3).\n * Pass `adapter.snapDuration(seconds)` to coerce raw seconds to a valid\n * value.\n */\n duration?: VideoDurationForAdapter<TAdapter>\n /**\n * Whether to stream the video generation lifecycle.\n * When true, returns an AsyncIterable<StreamChunk> that handles the full\n * job lifecycle: create job, poll for status, yield updates, and yield final result.\n * When false or not provided, returns a Promise<VideoJobResult>.\n *\n * @default false\n */\n stream?: TStream\n /** Polling interval in milliseconds (stream mode only). @default 2000 */\n pollingInterval?: number\n /** Maximum time to wait before timing out in milliseconds (stream mode only). @default 600000 */\n maxDuration?: number\n /** Custom run ID (stream mode only) */\n runId?: string\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. In streaming mode the\n * span covers the full create→poll→complete lifecycle; in non-streaming mode\n * it covers job submission. An abandoned stream fires `onAbort`.\n */\n middleware?: Array<GenerationMiddleware>\n} & ({} extends VideoProviderOptions<TAdapter>\n ? {\n /** Provider-specific options for video generation */ modelOptions?: VideoProviderOptions<TAdapter>\n }\n : {\n /** Provider-specific options for video generation */ modelOptions: VideoProviderOptions<TAdapter>\n })\n\n/**\n * Options for polling the status of a video generation job.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface VideoStatusOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n> extends VideoActivityBaseOptions<TAdapter> {\n /** Request type - get job status */\n request: 'status'\n /** The job ID to check status for */\n jobId: string\n}\n\n/**\n * Options for getting the URL of a completed video.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface VideoUrlOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n> extends VideoActivityBaseOptions<TAdapter> {\n /** Request type - get video URL */\n request: 'url'\n /** The job ID to get URL for */\n jobId: string\n}\n\n/**\n * Union type for all video activity options.\n * Discriminated by the `request` field.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type VideoActivityOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n TRequest extends 'create' | 'status' | 'url' = 'create',\n TStream extends boolean = false,\n> = TRequest extends 'status'\n ? VideoStatusOptions<TAdapter>\n : TRequest extends 'url'\n ? VideoUrlOptions<TAdapter>\n : VideoCreateOptions<TAdapter, TStream>\n\n// ===========================\n// Activity Result Types\n// ===========================\n\n/**\n * Result type for the video activity, based on request type and streaming.\n * - If stream is true (create request): AsyncIterable<StreamChunk>\n * - Otherwise: Promise<VideoJobResult | VideoStatusResult | VideoUrlResult>\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type VideoActivityResult<\n TRequest extends 'create' | 'status' | 'url' = 'create',\n TStream extends boolean = false,\n> = TRequest extends 'status'\n ? Promise<VideoStatusResult>\n : TRequest extends 'url'\n ? Promise<VideoUrlResult>\n : TStream extends true\n ? AsyncIterable<StreamChunk>\n : Promise<VideoJobResult>\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Generate video - creates a video generation job from a text prompt.\n *\n * Uses AI video generation models to create videos based on natural language descriptions.\n * Unlike image generation, video generation is asynchronous and requires polling for completion.\n *\n * When `stream: true` is passed, handles the full job lifecycle automatically:\n * create job → poll for status → stream updates → yield final result.\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * @example Create a video generation job\n * ```ts\n * import { generateVideo } from '@tanstack/ai'\n * import { openaiVideo } from '@tanstack/ai-openai'\n *\n * // Start a video generation job\n * const { jobId } = await generateVideo({\n * adapter: openaiVideo('sora-2'),\n * prompt: 'A cat chasing a dog in a sunny park'\n * })\n *\n * console.log('Job started:', jobId)\n * ```\n *\n * @example Stream the full video generation lifecycle\n * ```ts\n * import { generateVideo, toServerSentEventsResponse } from '@tanstack/ai'\n * import { openaiVideo } from '@tanstack/ai-openai'\n *\n * const stream = generateVideo({\n * adapter: openaiVideo('sora-2'),\n * prompt: 'A cat chasing a dog in a sunny park',\n * stream: true,\n * pollingInterval: 3000,\n * })\n *\n * return toServerSentEventsResponse(stream)\n * ```\n */\nexport function generateVideo<\n TAdapter extends VideoAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: VideoCreateOptions<TAdapter, TStream>,\n): VideoActivityResult<'create', TStream> {\n if (options.stream) {\n return runStreamingVideoGeneration(\n options as VideoCreateOptions<TAdapter, true>,\n ) as VideoActivityResult<'create', TStream>\n }\n\n return runCreateVideoJob(options) as VideoActivityResult<'create', TStream>\n}\n\n/**\n * Internal implementation of non-streaming video job creation.\n */\nasync function runCreateVideoJob<\n TAdapter extends VideoAdapter<string, any, any, any>,\n>(options: VideoCreateOptions<TAdapter, boolean>): Promise<VideoJobResult> {\n const { adapter, prompt, size, duration, modelOptions, middleware } = options\n const model = adapter.model\n const requestId = createId('video')\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: 'video',\n provider: adapter.name,\n model,\n modelOptions,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n logger.request(`activity=generateVideo provider=${providerName}`, {\n provider: providerName,\n model,\n })\n\n try {\n const result = await adapter.createVideoJob({\n model,\n prompt,\n size,\n duration,\n modelOptions,\n logger,\n })\n logger.output(`activity=generateVideo jobId=${result.jobId}`, {\n jobId: result.jobId,\n model: result.model,\n })\n // Non-streaming create only submits the job; usage isn't known until the\n // job completes via polling, so the span covers submission only.\n await runGenerationFinish(middleware, mwCtx, {\n duration: Date.now() - startTime,\n })\n return result\n } catch (error) {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration: Date.now() - startTime,\n })\n logger.errors('generateVideo activity failed', {\n error,\n source: 'generateVideo',\n })\n throw error\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Internal streaming implementation for video generation.\n * Handles the full job lifecycle: create job → poll for status → stream updates → yield final result.\n */\nasync function* runStreamingVideoGeneration<\n TAdapter extends VideoAdapter<string, any, any, any>,\n>(options: VideoCreateOptions<TAdapter, true>): AsyncIterable<StreamChunk> {\n const { adapter, prompt, size, duration, modelOptions, middleware } = options\n const model = adapter.model\n const runId = options.runId ?? createId('run')\n const requestId = createId('video')\n const obsStartTime = Date.now()\n const pollingInterval = options.pollingInterval ?? 2000\n const maxDuration = options.maxDuration ?? 600_000\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 threadId = createId('thread')\n\n yield {\n type: 'RUN_STARTED',\n runId,\n threadId,\n timestamp: Date.now(),\n } as StreamChunk\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'video',\n provider: adapter.name,\n model,\n modelOptions,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n logger.request(\n `activity=generateVideo provider=${providerName} stream=true`,\n {\n provider: providerName,\n model,\n },\n )\n\n // Tracks whether a terminal observer event (finish/error) has already fired,\n // so the `finally` below can fire one on abandonment without double-firing.\n let settled = false\n try {\n // Create the video generation job\n const jobResult = await adapter.createVideoJob({\n model,\n prompt,\n size,\n duration,\n modelOptions,\n logger,\n })\n\n yield {\n type: 'CUSTOM',\n name: 'video:job:created',\n value: { jobId: jobResult.jobId },\n timestamp: Date.now(),\n } as StreamChunk\n\n // Poll for completion\n const startTime = Date.now()\n while (Date.now() - startTime < maxDuration) {\n await sleep(pollingInterval)\n\n const statusResult = await adapter.getVideoStatus(jobResult.jobId)\n\n yield {\n type: 'CUSTOM',\n name: 'video:status',\n value: {\n jobId: jobResult.jobId,\n status: statusResult.status,\n progress: statusResult.progress,\n error: statusResult.error,\n },\n timestamp: Date.now(),\n } as StreamChunk\n\n if (statusResult.status === 'completed') {\n const urlResult = await adapter.getVideoUrl(jobResult.jobId)\n\n logger.output(\n `activity=generateVideo jobId=${jobResult.jobId} status=completed`,\n {\n jobId: jobResult.jobId,\n url: urlResult.url,\n },\n )\n\n // Fire finish before yielding the terminal chunks: the generation has\n // succeeded, so a consumer that stops reading after `generation:result`\n // (without pulling `RUN_FINISHED`) must not trip the abandonment path in\n // `finally`, which would otherwise report a spurious cancellation.\n if (urlResult.usage)\n await runGenerationUsage(middleware, mwCtx, urlResult.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration: Date.now() - obsStartTime,\n usage: urlResult.usage,\n })\n settled = true\n\n yield {\n type: 'CUSTOM',\n name: 'generation:result',\n value: {\n jobId: jobResult.jobId,\n status: 'completed',\n url: urlResult.url,\n expiresAt: urlResult.expiresAt,\n ...(urlResult.usage ? { usage: urlResult.usage } : {}),\n },\n timestamp: Date.now(),\n } as StreamChunk\n\n yield {\n type: 'RUN_FINISHED',\n runId,\n threadId,\n finishReason: 'stop',\n timestamp: Date.now(),\n } as StreamChunk\n return\n }\n\n if (statusResult.status === 'failed') {\n throw new Error(statusResult.error || 'Video generation failed')\n }\n }\n\n throw new Error('Video generation timed out')\n } catch (error: unknown) {\n const payload = toRunErrorPayload(error, 'Video generation failed')\n // Mark settled before firing onError: if a user error-hook throws, the\n // `finally` below must still not double-fire onAbort over the same op\n // (which would mask the original error and end the span twice).\n settled = true\n await runGenerationError(middleware, mwCtx, {\n error,\n duration: Date.now() - obsStartTime,\n })\n logger.errors('generateVideo activity failed', {\n message: payload.message,\n code: payload.code,\n source: 'generateVideo',\n })\n yield {\n type: 'RUN_ERROR',\n runId,\n threadId,\n message: payload.message,\n code: payload.code,\n error: payload,\n timestamp: Date.now(),\n } as StreamChunk\n } finally {\n if (!settled) {\n // The consumer abandoned the stream (broke the `for await` loop or\n // disconnected) before completion, so the generator is being unwound at\n // a `yield` without reaching finish/error. Fire `onAbort` — a cancel, not\n // an error — so otelMiddleware ends its span instead of leaking it.\n await runGenerationAbort(middleware, mwCtx, {\n reason: 'Video generation stream abandoned before completion',\n duration: Date.now() - obsStartTime,\n })\n }\n }\n}\n\n/**\n * Get video job status - returns the current status, progress, and URL if available.\n *\n * This function combines status checking and URL retrieval. If the job is completed,\n * it will automatically fetch and include the video URL.\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * @example Check job status\n * ```ts\n * import { getVideoJobStatus } from '@tanstack/ai'\n * import { openaiVideo } from '@tanstack/ai-openai'\n *\n * const result = await getVideoJobStatus({\n * adapter: openaiVideo('sora-2'),\n * jobId: 'job-123'\n * })\n *\n * console.log('Status:', result.status)\n * console.log('Progress:', result.progress)\n * if (result.url) {\n * console.log('Video URL:', result.url)\n * }\n * ```\n */\nexport async function getVideoJobStatus<\n TAdapter extends VideoAdapter<string, any, any, any>,\n>(options: {\n adapter: TAdapter & { kind: typeof kind }\n jobId: string\n}): Promise<{\n status: 'pending' | 'processing' | 'completed' | 'failed'\n progress?: number\n url?: string\n error?: string\n usage?: TokenUsage\n}> {\n const { adapter, jobId } = options\n const requestId = createId('video-status')\n const startTime = Date.now()\n\n aiEventClient.emit('video:request:started', {\n requestId,\n provider: adapter.name,\n model: adapter.model,\n requestType: 'status',\n jobId,\n timestamp: startTime,\n })\n\n // Get status first\n const statusResult = await adapter.getVideoStatus(jobId)\n\n // If completed, also get the URL\n if (statusResult.status === 'completed') {\n try {\n const urlResult = await adapter.getVideoUrl(jobId)\n aiEventClient.emit('video:request:completed', {\n requestId,\n provider: adapter.name,\n model: adapter.model,\n requestType: 'status',\n jobId,\n status: statusResult.status,\n progress: statusResult.progress,\n url: urlResult.url,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n })\n if (urlResult.usage) {\n aiEventClient.emit('video:usage', {\n requestId,\n model: adapter.model,\n usage: urlResult.usage,\n timestamp: Date.now(),\n })\n }\n return {\n status: statusResult.status,\n progress: statusResult.progress,\n url: urlResult.url,\n ...(urlResult.usage ? { usage: urlResult.usage } : {}),\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to get video URL'\n aiEventClient.emit('video:request:completed', {\n requestId,\n provider: adapter.name,\n model: adapter.model,\n requestType: 'status',\n jobId,\n status: 'failed',\n progress: statusResult.progress,\n error: errorMessage,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n })\n // Provider reported completed but result fetch failed — treat as failed\n return {\n status: 'failed' as const,\n progress: statusResult.progress,\n error: errorMessage,\n }\n }\n }\n\n aiEventClient.emit('video:request:completed', {\n requestId,\n provider: adapter.name,\n model: adapter.model,\n requestType: 'status',\n jobId,\n status: statusResult.status,\n progress: statusResult.progress,\n error: statusResult.error,\n duration: Date.now() - startTime,\n timestamp: Date.now(),\n })\n\n // Return status for non-completed jobs\n return {\n status: statusResult.status,\n progress: statusResult.progress,\n error: statusResult.error,\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateVideo() function without executing.\n */\nexport function createVideoOptions<\n TAdapter extends VideoAdapter<string, any, any, any>,\n TStream extends boolean = false,\n>(\n options: VideoCreateOptions<TAdapter, TStream>,\n): VideoCreateOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n VideoAdapter,\n VideoAdapterConfig,\n AnyVideoAdapter,\n} from './adapter'\nexport { BaseVideoAdapter } from './adapter'\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DurationOptions } from './adapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Snap a raw seconds value to the closest valid duration for a model's
|
|
4
|
+
* `DurationOptions`.
|
|
5
|
+
*
|
|
6
|
+
* - `none` → `undefined`
|
|
7
|
+
* - `discrete` → closest numeric-parseable entry; if none parse,
|
|
8
|
+
* returns `values[0]` (keyword-only models like 'auto')
|
|
9
|
+
* - `range` → clamped to [min, max] and rounded to `step` (default 1)
|
|
10
|
+
* - `mixed` → closest of (discrete numerics ∪ range values)
|
|
11
|
+
*
|
|
12
|
+
* @experimental Video generation is an experimental feature and may change.
|
|
13
|
+
*/
|
|
14
|
+
export declare function snapToDurationOption<T extends string | number | undefined>(seconds: number, options: DurationOptions<T>): T | undefined;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function entryToSeconds(entry) {
|
|
2
|
+
if (typeof entry === "number") {
|
|
3
|
+
return Number.isFinite(entry) ? entry : null;
|
|
4
|
+
}
|
|
5
|
+
const stripped = entry.endsWith("s") ? entry.slice(0, -1) : entry;
|
|
6
|
+
const parsed = Number(stripped);
|
|
7
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
8
|
+
}
|
|
9
|
+
function snapToDurationOption(seconds, options) {
|
|
10
|
+
switch (options.kind) {
|
|
11
|
+
case "none":
|
|
12
|
+
return void 0;
|
|
13
|
+
case "discrete": {
|
|
14
|
+
return pickClosestDiscrete(seconds, options.values);
|
|
15
|
+
}
|
|
16
|
+
case "range": {
|
|
17
|
+
const step = options.step ?? 1;
|
|
18
|
+
const clamped = Math.min(options.max, Math.max(options.min, seconds));
|
|
19
|
+
const snapped = Math.round((clamped - options.min) / step) * step + options.min;
|
|
20
|
+
return Math.min(options.max, Math.max(options.min, snapped));
|
|
21
|
+
}
|
|
22
|
+
case "mixed": {
|
|
23
|
+
const discreteCandidate = pickClosestDiscrete(seconds, options.values);
|
|
24
|
+
if (!options.range) return discreteCandidate;
|
|
25
|
+
const { min, max, step = 1 } = options.range;
|
|
26
|
+
const clamped = Math.min(max, Math.max(min, seconds));
|
|
27
|
+
const rangeValue = Math.min(
|
|
28
|
+
max,
|
|
29
|
+
Math.max(min, Math.round((clamped - min) / step) * step + min)
|
|
30
|
+
);
|
|
31
|
+
const discreteSeconds = typeof discreteCandidate === "number" ? discreteCandidate : discreteCandidate !== void 0 ? entryToSeconds(discreteCandidate) ?? Infinity : Infinity;
|
|
32
|
+
return Math.abs(discreteSeconds - seconds) <= Math.abs(rangeValue - seconds) ? discreteCandidate : rangeValue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function pickClosestDiscrete(seconds, values) {
|
|
37
|
+
if (values.length === 0) return void 0;
|
|
38
|
+
let best;
|
|
39
|
+
let bestDistance = Infinity;
|
|
40
|
+
for (const value of values) {
|
|
41
|
+
const v = entryToSeconds(value);
|
|
42
|
+
if (v === null) continue;
|
|
43
|
+
const distance = Math.abs(v - seconds);
|
|
44
|
+
if (distance < bestDistance) {
|
|
45
|
+
bestDistance = distance;
|
|
46
|
+
best = value;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return best ?? values[0];
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
snapToDurationOption
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=snap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snap.js","sources":["../../../../src/activities/generateVideo/snap.ts"],"sourcesContent":["import type { DurationOptions } from './adapter'\n\n/**\n * Extract a numeric seconds value from a `DurationOptions` entry. Returns\n * `null` for entries that don't parse as a number — e.g. `'auto'`.\n *\n * Handles the keyword-with-unit form FAL uses for Luma/Veo (`'8s'`, `'9s'`)\n * by stripping a trailing `s`. Pure-numeric strings (`'5'`, `'10'`) parse via\n * Number(). Numbers pass through.\n */\nfunction entryToSeconds(entry: string | number): number | null {\n if (typeof entry === 'number') {\n return Number.isFinite(entry) ? entry : null\n }\n const stripped = entry.endsWith('s') ? entry.slice(0, -1) : entry\n const parsed = Number(stripped)\n return Number.isFinite(parsed) ? parsed : null\n}\n\n/**\n * Snap a raw seconds value to the closest valid duration for a model's\n * `DurationOptions`.\n *\n * - `none` → `undefined`\n * - `discrete` → closest numeric-parseable entry; if none parse,\n * returns `values[0]` (keyword-only models like 'auto')\n * - `range` → clamped to [min, max] and rounded to `step` (default 1)\n * - `mixed` → closest of (discrete numerics ∪ range values)\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport function snapToDurationOption<T extends string | number | undefined>(\n seconds: number,\n options: DurationOptions<T>,\n): T | undefined {\n switch (options.kind) {\n case 'none':\n return undefined\n\n case 'discrete': {\n return pickClosestDiscrete(seconds, options.values)\n }\n\n case 'range': {\n const step = options.step ?? 1\n const clamped = Math.min(options.max, Math.max(options.min, seconds))\n const snapped =\n Math.round((clamped - options.min) / step) * step + options.min\n return Math.min(options.max, Math.max(options.min, snapped)) as T\n }\n\n case 'mixed': {\n const discreteCandidate = pickClosestDiscrete(seconds, options.values)\n if (!options.range) return discreteCandidate\n\n const { min, max, step = 1 } = options.range\n const clamped = Math.min(max, Math.max(min, seconds))\n const rangeValue = Math.min(\n max,\n Math.max(min, Math.round((clamped - min) / step) * step + min),\n )\n\n // Compare distance; range value is numeric, discrete may have non-numeric\n // first-entry fallback (return distance Infinity for non-numerics).\n const discreteSeconds =\n typeof discreteCandidate === 'number'\n ? discreteCandidate\n : discreteCandidate !== undefined\n ? (entryToSeconds(discreteCandidate) ?? Infinity)\n : Infinity\n\n return Math.abs(discreteSeconds - seconds) <=\n Math.abs(rangeValue - seconds)\n ? discreteCandidate\n : (rangeValue as T)\n }\n }\n}\n\nfunction pickClosestDiscrete<T extends string | number>(\n seconds: number,\n values: ReadonlyArray<T>,\n): T | undefined {\n if (values.length === 0) return undefined\n\n let best: T | undefined\n let bestDistance = Infinity\n for (const value of values) {\n const v = entryToSeconds(value)\n if (v === null) continue\n const distance = Math.abs(v - seconds)\n if (distance < bestDistance) {\n bestDistance = distance\n best = value\n }\n }\n\n // Keyword-only set (no numeric-parseable entries) — fall back to first entry.\n return best ?? values[0]\n}\n"],"names":[],"mappings":"AAUA,SAAS,eAAe,OAAuC;AAC7D,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC1C;AACA,QAAM,WAAW,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI;AAC5D,QAAM,SAAS,OAAO,QAAQ;AAC9B,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;AAcO,SAAS,qBACd,SACA,SACe;AACf,UAAQ,QAAQ,MAAA;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IAET,KAAK,YAAY;AACf,aAAO,oBAAoB,SAAS,QAAQ,MAAM;AAAA,IACpD;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,OAAO,QAAQ,QAAQ;AAC7B,YAAM,UAAU,KAAK,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;AACpE,YAAM,UACJ,KAAK,OAAO,UAAU,QAAQ,OAAO,IAAI,IAAI,OAAO,QAAQ;AAC9D,aAAO,KAAK,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,IAC7D;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,oBAAoB,oBAAoB,SAAS,QAAQ,MAAM;AACrE,UAAI,CAAC,QAAQ,MAAO,QAAO;AAE3B,YAAM,EAAE,KAAK,KAAK,OAAO,EAAA,IAAM,QAAQ;AACvC,YAAM,UAAU,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,OAAO,CAAC;AACpD,YAAM,aAAa,KAAK;AAAA,QACtB;AAAA,QACA,KAAK,IAAI,KAAK,KAAK,OAAO,UAAU,OAAO,IAAI,IAAI,OAAO,GAAG;AAAA,MAAA;AAK/D,YAAM,kBACJ,OAAO,sBAAsB,WACzB,oBACA,sBAAsB,SACnB,eAAe,iBAAiB,KAAK,WACtC;AAER,aAAO,KAAK,IAAI,kBAAkB,OAAO,KACvC,KAAK,IAAI,aAAa,OAAO,IAC3B,oBACC;AAAA,IACP;AAAA,EAAA;AAEJ;AAEA,SAAS,oBACP,SACA,QACe;AACf,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,MAAI;AACJ,MAAI,eAAe;AACnB,aAAW,SAAS,QAAQ;AAC1B,UAAM,IAAI,eAAe,KAAK;AAC9B,QAAI,MAAM,KAAM;AAChB,UAAM,WAAW,KAAK,IAAI,IAAI,OAAO;AACrC,QAAI,WAAW,cAAc;AAC3B,qBAAe;AACf,aAAO;AAAA,IACT;AAAA,EACF;AAGA,SAAO,QAAQ,OAAO,CAAC;AACzB;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AnyTextAdapter } from './chat/adapter.js';
|
|
2
|
+
import { AnySummarizeAdapter } from './summarize/adapter.js';
|
|
3
|
+
import { AnyImageAdapter } from './generateImage/adapter.js';
|
|
4
|
+
import { AnyAudioAdapter } from './generateAudio/adapter.js';
|
|
5
|
+
import { AnyVideoAdapter } from './generateVideo/adapter.js';
|
|
6
|
+
import { AnyTTSAdapter } from './generateSpeech/adapter.js';
|
|
7
|
+
import { AnyTranscriptionAdapter } from './generateTranscription/adapter.js';
|
|
8
|
+
export { kind as textKind, chat, type TextActivityOptions, type TextActivityResult, } from './chat/index.js';
|
|
9
|
+
export { BaseTextAdapter, type AnyTextAdapter, type TextAdapter, type TextAdapterConfig, type StructuredOutputOptions, type StructuredOutputResult, } from './chat/adapter.js';
|
|
10
|
+
export { kind as summarizeKind, summarize, type SummarizeActivityOptions, type SummarizeActivityResult, type SummarizeProviderOptions, } from './summarize/index.js';
|
|
11
|
+
export { BaseSummarizeAdapter, type SummarizeAdapter, type SummarizeAdapterConfig, type AnySummarizeAdapter, } from './summarize/adapter.js';
|
|
12
|
+
export { ChatStreamSummarizeAdapter, type ChatStreamCapable, type InferTextProviderOptions, } from './summarize/chat-stream-summarize.js';
|
|
13
|
+
export { kind as imageKind, generateImage, type ImageActivityOptions, type ImageActivityResult, type ImageProviderOptionsForModel, type ImageSizeForModel, } from './generateImage/index.js';
|
|
14
|
+
export { BaseImageAdapter, type ImageAdapter, type ImageAdapterConfig, type AnyImageAdapter, } from './generateImage/adapter.js';
|
|
15
|
+
export { kind as audioKind, generateAudio, type AudioActivityOptions, type AudioActivityResult, type AudioProviderOptions, } from './generateAudio/index.js';
|
|
16
|
+
export { BaseAudioAdapter, type AudioAdapter, type AudioAdapterConfig, type AnyAudioAdapter, } from './generateAudio/adapter.js';
|
|
17
|
+
export { kind as videoKind, generateVideo, getVideoJobStatus, type VideoActivityOptions, type VideoActivityResult, type VideoProviderOptions, type VideoCreateOptions, type VideoStatusOptions, type VideoUrlOptions, type VideoDurationForAdapter, } from './generateVideo/index.js';
|
|
18
|
+
export { BaseVideoAdapter, type VideoAdapter, type VideoAdapterConfig, type AnyVideoAdapter, type DurationOptions, } from './generateVideo/adapter.js';
|
|
19
|
+
export { snapToDurationOption } from './generateVideo/snap.js';
|
|
20
|
+
export { kind as ttsKind, generateSpeech, type TTSActivityOptions, type TTSActivityResult, type TTSProviderOptions, } from './generateSpeech/index.js';
|
|
21
|
+
export { BaseTTSAdapter, type TTSAdapter, type TTSAdapterConfig, type AnyTTSAdapter, } from './generateSpeech/adapter.js';
|
|
22
|
+
export { kind as transcriptionKind, generateTranscription, type TranscriptionActivityOptions, type TranscriptionActivityResult, type TranscriptionProviderOptions, } from './generateTranscription/index.js';
|
|
23
|
+
export { BaseTranscriptionAdapter, type TranscriptionAdapter, type TranscriptionAdapterConfig, type AnyTranscriptionAdapter, } from './generateTranscription/adapter.js';
|
|
24
|
+
/** Union of all adapter types that can be passed to chat() */
|
|
25
|
+
export type AIAdapter = AnyTextAdapter | AnySummarizeAdapter | AnyImageAdapter | AnyAudioAdapter | AnyVideoAdapter | AnyTTSAdapter | AnyTranscriptionAdapter;
|
|
26
|
+
/** Union type of all adapter kinds */
|
|
27
|
+
export type AdapterKind = 'text' | 'summarize' | 'image' | 'audio' | 'video' | 'tts' | 'transcription';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { chat, kind } from "./chat/index.js";
|
|
2
|
+
import { BaseTextAdapter } from "./chat/adapter.js";
|
|
3
|
+
import { summarize, kind as kind2 } from "./summarize/index.js";
|
|
4
|
+
import { BaseSummarizeAdapter } from "./summarize/adapter.js";
|
|
5
|
+
import { ChatStreamSummarizeAdapter } from "./summarize/chat-stream-summarize.js";
|
|
6
|
+
import { generateImage, kind as kind3 } from "./generateImage/index.js";
|
|
7
|
+
import { BaseImageAdapter } from "./generateImage/adapter.js";
|
|
8
|
+
import { kind as kind4, generateAudio } from "./generateAudio/index.js";
|
|
9
|
+
import { BaseAudioAdapter } from "./generateAudio/adapter.js";
|
|
10
|
+
import { generateVideo, getVideoJobStatus, kind as kind5 } from "./generateVideo/index.js";
|
|
11
|
+
import { BaseVideoAdapter } from "./generateVideo/adapter.js";
|
|
12
|
+
import { snapToDurationOption } from "./generateVideo/snap.js";
|
|
13
|
+
import { generateSpeech, kind as kind6 } from "./generateSpeech/index.js";
|
|
14
|
+
import { BaseTTSAdapter } from "./generateSpeech/adapter.js";
|
|
15
|
+
import { generateTranscription, kind as kind7 } from "./generateTranscription/index.js";
|
|
16
|
+
import { BaseTranscriptionAdapter } from "./generateTranscription/adapter.js";
|
|
17
|
+
export {
|
|
18
|
+
BaseAudioAdapter,
|
|
19
|
+
BaseImageAdapter,
|
|
20
|
+
BaseSummarizeAdapter,
|
|
21
|
+
BaseTTSAdapter,
|
|
22
|
+
BaseTextAdapter,
|
|
23
|
+
BaseTranscriptionAdapter,
|
|
24
|
+
BaseVideoAdapter,
|
|
25
|
+
ChatStreamSummarizeAdapter,
|
|
26
|
+
kind4 as audioKind,
|
|
27
|
+
chat,
|
|
28
|
+
generateAudio,
|
|
29
|
+
generateImage,
|
|
30
|
+
generateSpeech,
|
|
31
|
+
generateTranscription,
|
|
32
|
+
generateVideo,
|
|
33
|
+
getVideoJobStatus,
|
|
34
|
+
kind3 as imageKind,
|
|
35
|
+
snapToDurationOption,
|
|
36
|
+
summarize,
|
|
37
|
+
kind2 as summarizeKind,
|
|
38
|
+
kind as textKind,
|
|
39
|
+
kind7 as transcriptionKind,
|
|
40
|
+
kind6 as ttsKind,
|
|
41
|
+
kind5 as videoKind
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { GenerationActivity, GenerationMiddleware, GenerationMiddlewareContext, GenerationUsageInfo, GenerationFinishInfo, GenerationAbortInfo, GenerationErrorInfo, AnyGenerationMiddleware, } from './types.js';
|
|
2
|
+
export { createGenerationContext, runGenerationStart, runGenerationUsage, runGenerationFinish, runGenerationAbort, runGenerationError, } from './run.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GenerationAbortInfo, GenerationErrorInfo, GenerationFinishInfo, GenerationMiddleware, GenerationMiddlewareContext, GenerationUsageInfo } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build the stable context for a single media-activity call.
|
|
4
|
+
*
|
|
5
|
+
* Media activities are always server-side and carry no user runtime context,
|
|
6
|
+
* so `source` is fixed to `'server'` and `context` to `undefined`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createGenerationContext(args: {
|
|
9
|
+
requestId: string;
|
|
10
|
+
activity: GenerationMiddlewareContext['activity'];
|
|
11
|
+
provider: string;
|
|
12
|
+
model: string;
|
|
13
|
+
modelOptions?: unknown;
|
|
14
|
+
createId: (prefix: string) => string;
|
|
15
|
+
}): GenerationMiddlewareContext;
|
|
16
|
+
export declare function runGenerationStart(middleware: ReadonlyArray<GenerationMiddleware> | undefined, ctx: GenerationMiddlewareContext): Promise<void>;
|
|
17
|
+
export declare function runGenerationUsage(middleware: ReadonlyArray<GenerationMiddleware> | undefined, ctx: GenerationMiddlewareContext, usage: GenerationUsageInfo): Promise<void>;
|
|
18
|
+
export declare function runGenerationFinish(middleware: ReadonlyArray<GenerationMiddleware> | undefined, ctx: GenerationMiddlewareContext, info: GenerationFinishInfo): Promise<void>;
|
|
19
|
+
export declare function runGenerationAbort(middleware: ReadonlyArray<GenerationMiddleware> | undefined, ctx: GenerationMiddlewareContext, info: GenerationAbortInfo): Promise<void>;
|
|
20
|
+
export declare function runGenerationError(middleware: ReadonlyArray<GenerationMiddleware> | undefined, ctx: GenerationMiddlewareContext, info: GenerationErrorInfo): Promise<void>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function createGenerationContext(args) {
|
|
2
|
+
return {
|
|
3
|
+
requestId: args.requestId,
|
|
4
|
+
activity: args.activity,
|
|
5
|
+
provider: args.provider,
|
|
6
|
+
model: args.model,
|
|
7
|
+
modelOptions: args.modelOptions,
|
|
8
|
+
source: "server",
|
|
9
|
+
createId: args.createId,
|
|
10
|
+
context: void 0
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
async function run(middleware, invoke) {
|
|
14
|
+
if (!middleware || middleware.length === 0) return;
|
|
15
|
+
for (const mw of middleware) {
|
|
16
|
+
await invoke(mw);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function runGenerationStart(middleware, ctx) {
|
|
20
|
+
return run(middleware, (mw) => mw.onStart?.(ctx));
|
|
21
|
+
}
|
|
22
|
+
function runGenerationUsage(middleware, ctx, usage) {
|
|
23
|
+
return run(middleware, (mw) => mw.onUsage?.(ctx, usage));
|
|
24
|
+
}
|
|
25
|
+
function runGenerationFinish(middleware, ctx, info) {
|
|
26
|
+
return run(middleware, (mw) => mw.onFinish?.(ctx, info));
|
|
27
|
+
}
|
|
28
|
+
function runGenerationAbort(middleware, ctx, info) {
|
|
29
|
+
return run(middleware, (mw) => mw.onAbort?.(ctx, info));
|
|
30
|
+
}
|
|
31
|
+
function runGenerationError(middleware, ctx, info) {
|
|
32
|
+
return run(middleware, (mw) => mw.onError?.(ctx, info));
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
createGenerationContext,
|
|
36
|
+
runGenerationAbort,
|
|
37
|
+
runGenerationError,
|
|
38
|
+
runGenerationFinish,
|
|
39
|
+
runGenerationStart,
|
|
40
|
+
runGenerationUsage
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sources":["../../../../src/activities/middleware/run.ts"],"sourcesContent":["import type {\n GenerationAbortInfo,\n GenerationErrorInfo,\n GenerationFinishInfo,\n GenerationMiddleware,\n GenerationMiddlewareContext,\n GenerationUsageInfo,\n} from './types'\n\n/**\n * Build the stable context for a single media-activity call.\n *\n * Media activities are always server-side and carry no user runtime context,\n * so `source` is fixed to `'server'` and `context` to `undefined`.\n */\nexport function createGenerationContext(args: {\n requestId: string\n activity: GenerationMiddlewareContext['activity']\n provider: string\n model: string\n modelOptions?: unknown\n createId: (prefix: string) => string\n}): GenerationMiddlewareContext {\n return {\n requestId: args.requestId,\n activity: args.activity,\n provider: args.provider,\n model: args.model,\n modelOptions: args.modelOptions,\n source: 'server',\n createId: args.createId,\n context: undefined,\n }\n}\n\n/**\n * Run a single lifecycle hook across each middleware in registration order,\n * awaiting each. Exceptions PROPAGATE (matching `chat()` middleware) — a\n * broken middleware fails the activity rather than being silently swallowed.\n */\nasync function run(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n invoke: (mw: GenerationMiddleware) => void | Promise<void>,\n): Promise<void> {\n if (!middleware || middleware.length === 0) return\n for (const mw of middleware) {\n await invoke(mw)\n }\n}\n\nexport function runGenerationStart(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n ctx: GenerationMiddlewareContext,\n): Promise<void> {\n return run(middleware, (mw) => mw.onStart?.(ctx))\n}\n\nexport function runGenerationUsage(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n ctx: GenerationMiddlewareContext,\n usage: GenerationUsageInfo,\n): Promise<void> {\n return run(middleware, (mw) => mw.onUsage?.(ctx, usage))\n}\n\nexport function runGenerationFinish(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n ctx: GenerationMiddlewareContext,\n info: GenerationFinishInfo,\n): Promise<void> {\n return run(middleware, (mw) => mw.onFinish?.(ctx, info))\n}\n\nexport function runGenerationAbort(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n ctx: GenerationMiddlewareContext,\n info: GenerationAbortInfo,\n): Promise<void> {\n return run(middleware, (mw) => mw.onAbort?.(ctx, info))\n}\n\nexport function runGenerationError(\n middleware: ReadonlyArray<GenerationMiddleware> | undefined,\n ctx: GenerationMiddlewareContext,\n info: GenerationErrorInfo,\n): Promise<void> {\n return run(middleware, (mw) => mw.onError?.(ctx, info))\n}\n"],"names":[],"mappings":"AAeO,SAAS,wBAAwB,MAOR;AAC9B,SAAO;AAAA,IACL,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,IACf,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,cAAc,KAAK;AAAA,IACnB,QAAQ;AAAA,IACR,UAAU,KAAK;AAAA,IACf,SAAS;AAAA,EAAA;AAEb;AAOA,eAAe,IACb,YACA,QACe;AACf,MAAI,CAAC,cAAc,WAAW,WAAW,EAAG;AAC5C,aAAW,MAAM,YAAY;AAC3B,UAAM,OAAO,EAAE;AAAA,EACjB;AACF;AAEO,SAAS,mBACd,YACA,KACe;AACf,SAAO,IAAI,YAAY,CAAC,OAAO,GAAG,UAAU,GAAG,CAAC;AAClD;AAEO,SAAS,mBACd,YACA,KACA,OACe;AACf,SAAO,IAAI,YAAY,CAAC,OAAO,GAAG,UAAU,KAAK,KAAK,CAAC;AACzD;AAEO,SAAS,oBACd,YACA,KACA,MACe;AACf,SAAO,IAAI,YAAY,CAAC,OAAO,GAAG,WAAW,KAAK,IAAI,CAAC;AACzD;AAEO,SAAS,mBACd,YACA,KACA,MACe;AACf,SAAO,IAAI,YAAY,CAAC,OAAO,GAAG,UAAU,KAAK,IAAI,CAAC;AACxD;AAEO,SAAS,mBACd,YACA,KACA,MACe;AACf,SAAO,IAAI,YAAY,CAAC,OAAO,GAAG,UAAU,KAAK,IAAI,CAAC;AACxD;"}
|