@tanstack/ai
Version:
Core TanStack AI library - Open source AI SDK
188 lines (187 loc) • 5.07 kB
JavaScript
import { aiEventClient } from "@tanstack/ai-event-client";
const kind = "video";
function createId(prefix) {
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
}
function generateVideo(options) {
if (options.stream) {
return runStreamingVideoGeneration(
options
);
}
return runCreateVideoJob(options);
}
async function runCreateVideoJob(options) {
const { adapter, prompt, size, duration, modelOptions } = options;
const model = adapter.model;
return adapter.createVideoJob({
model,
prompt,
size,
duration,
modelOptions
});
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function* runStreamingVideoGeneration(options) {
const { adapter, prompt, size, duration, modelOptions } = options;
const model = adapter.model;
const runId = options.runId ?? createId("run");
const pollingInterval = options.pollingInterval ?? 2e3;
const maxDuration = options.maxDuration ?? 6e5;
yield {
type: "RUN_STARTED",
runId,
timestamp: Date.now()
};
try {
const jobResult = await adapter.createVideoJob({
model,
prompt,
size,
duration,
modelOptions
});
yield {
type: "CUSTOM",
name: "video:job:created",
value: { jobId: jobResult.jobId },
timestamp: Date.now()
};
const startTime = Date.now();
while (Date.now() - startTime < maxDuration) {
await sleep(pollingInterval);
const statusResult = await adapter.getVideoStatus(jobResult.jobId);
yield {
type: "CUSTOM",
name: "video:status",
value: {
jobId: jobResult.jobId,
status: statusResult.status,
progress: statusResult.progress,
error: statusResult.error
},
timestamp: Date.now()
};
if (statusResult.status === "completed") {
const urlResult = await adapter.getVideoUrl(jobResult.jobId);
yield {
type: "CUSTOM",
name: "generation:result",
value: {
jobId: jobResult.jobId,
status: "completed",
url: urlResult.url,
expiresAt: urlResult.expiresAt
},
timestamp: Date.now()
};
yield {
type: "RUN_FINISHED",
runId,
finishReason: "stop",
timestamp: Date.now()
};
return;
}
if (statusResult.status === "failed") {
throw new Error(statusResult.error || "Video generation failed");
}
}
throw new Error("Video generation timed out");
} catch (error) {
yield {
type: "RUN_ERROR",
runId,
error: {
message: error.message || "Video generation failed",
code: error.code
},
timestamp: Date.now()
};
}
}
async function getVideoJobStatus(options) {
const { adapter, jobId } = options;
const requestId = createId("video-status");
const startTime = Date.now();
aiEventClient.emit("video:request:started", {
requestId,
provider: adapter.name,
model: adapter.model,
requestType: "status",
jobId,
timestamp: startTime
});
const statusResult = await adapter.getVideoStatus(jobId);
if (statusResult.status === "completed") {
try {
const urlResult = await adapter.getVideoUrl(jobId);
aiEventClient.emit("video:request:completed", {
requestId,
provider: adapter.name,
model: adapter.model,
requestType: "status",
jobId,
status: statusResult.status,
progress: statusResult.progress,
url: urlResult.url,
duration: Date.now() - startTime,
timestamp: Date.now()
});
return {
status: statusResult.status,
progress: statusResult.progress,
url: urlResult.url
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Failed to get video URL";
aiEventClient.emit("video:request:completed", {
requestId,
provider: adapter.name,
model: adapter.model,
requestType: "status",
jobId,
status: "failed",
progress: statusResult.progress,
error: errorMessage,
duration: Date.now() - startTime,
timestamp: Date.now()
});
return {
status: "failed",
progress: statusResult.progress,
error: errorMessage
};
}
}
aiEventClient.emit("video:request:completed", {
requestId,
provider: adapter.name,
model: adapter.model,
requestType: "status",
jobId,
status: statusResult.status,
progress: statusResult.progress,
error: statusResult.error,
duration: Date.now() - startTime,
timestamp: Date.now()
});
return {
status: statusResult.status,
progress: statusResult.progress,
error: statusResult.error
};
}
function createVideoOptions(options) {
return options;
}
export {
createVideoOptions,
generateVideo,
getVideoJobStatus,
kind
};
//# sourceMappingURL=index.js.map