@amaster.ai/pi-video-gen 0.1.2-beta.48

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.
Files changed (85) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +196 -0
  3. package/dist/compose.d.ts +43 -0
  4. package/dist/compose.d.ts.map +1 -0
  5. package/dist/compose.js +308 -0
  6. package/dist/compose.js.map +1 -0
  7. package/dist/config.d.ts +29 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +305 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/errors.d.ts +50 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +99 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/ffmpeg.d.ts +64 -0
  16. package/dist/ffmpeg.d.ts.map +1 -0
  17. package/dist/ffmpeg.js +292 -0
  18. package/dist/ffmpeg.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +837 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/jobs/store.d.ts +124 -0
  24. package/dist/jobs/store.d.ts.map +1 -0
  25. package/dist/jobs/store.js +386 -0
  26. package/dist/jobs/store.js.map +1 -0
  27. package/dist/providers/ark.d.ts +26 -0
  28. package/dist/providers/ark.d.ts.map +1 -0
  29. package/dist/providers/ark.js +178 -0
  30. package/dist/providers/ark.js.map +1 -0
  31. package/dist/providers/dashscope.d.ts +28 -0
  32. package/dist/providers/dashscope.d.ts.map +1 -0
  33. package/dist/providers/dashscope.js +200 -0
  34. package/dist/providers/dashscope.js.map +1 -0
  35. package/dist/providers/kling.d.ts +46 -0
  36. package/dist/providers/kling.d.ts.map +1 -0
  37. package/dist/providers/kling.js +245 -0
  38. package/dist/providers/kling.js.map +1 -0
  39. package/dist/providers/models.d.ts +16 -0
  40. package/dist/providers/models.d.ts.map +1 -0
  41. package/dist/providers/models.js +152 -0
  42. package/dist/providers/models.js.map +1 -0
  43. package/dist/providers/newapi.d.ts +3 -0
  44. package/dist/providers/newapi.d.ts.map +1 -0
  45. package/dist/providers/newapi.js +203 -0
  46. package/dist/providers/newapi.js.map +1 -0
  47. package/dist/providers/openrouter.d.ts +21 -0
  48. package/dist/providers/openrouter.d.ts.map +1 -0
  49. package/dist/providers/openrouter.js +169 -0
  50. package/dist/providers/openrouter.js.map +1 -0
  51. package/dist/providers/request.d.ts +4 -0
  52. package/dist/providers/request.d.ts.map +1 -0
  53. package/dist/providers/request.js +20 -0
  54. package/dist/providers/request.js.map +1 -0
  55. package/dist/providers/task.d.ts +53 -0
  56. package/dist/providers/task.d.ts.map +1 -0
  57. package/dist/providers/task.js +209 -0
  58. package/dist/providers/task.js.map +1 -0
  59. package/dist/render.d.ts +53 -0
  60. package/dist/render.d.ts.map +1 -0
  61. package/dist/render.js +480 -0
  62. package/dist/render.js.map +1 -0
  63. package/dist/text-layer.d.ts +18 -0
  64. package/dist/text-layer.d.ts.map +1 -0
  65. package/dist/text-layer.js +168 -0
  66. package/dist/text-layer.js.map +1 -0
  67. package/dist/timeline-render.d.ts +33 -0
  68. package/dist/timeline-render.d.ts.map +1 -0
  69. package/dist/timeline-render.js +1051 -0
  70. package/dist/timeline-render.js.map +1 -0
  71. package/dist/timeline.d.ts +64 -0
  72. package/dist/timeline.d.ts.map +1 -0
  73. package/dist/timeline.js +246 -0
  74. package/dist/timeline.js.map +1 -0
  75. package/dist/tts/edge-tts.d.ts +22 -0
  76. package/dist/tts/edge-tts.d.ts.map +1 -0
  77. package/dist/tts/edge-tts.js +55 -0
  78. package/dist/tts/edge-tts.js.map +1 -0
  79. package/dist/types.d.ts +161 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +13 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +93 -0
  84. package/preview.png +0 -0
  85. package/skills/video-gen/SKILL.md +284 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"newapi.js","sourceRoot":"","sources":["../../src/providers/newapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { VideoProviderAdapter } from '../types.js';
2
+ /**
3
+ * OpenRouter video generation (google/veo-3.1 and friends).
4
+ *
5
+ * POST {baseUrl}/videos → 202 { id, generation_id, polling_url, status }
6
+ * GET {baseUrl}/videos/{id} → { status, unsigned_urls[], error }
7
+ * GET {unsigned_urls[0]} → the mp4 itself
8
+ *
9
+ * Verified against the official docs (openrouter.ai/docs, 2026-07):
10
+ * - Frames ride in `frame_images` with `frame_type: first_frame|last_frame`;
11
+ * extra references go in `input_references` (image/audio/video urls).
12
+ * - `generate_audio` toggles native audio (default false upstream — we send it
13
+ * explicitly from the caller's capability decision).
14
+ * - Status enum: pending | in_progress | completed | failed | cancelled |
15
+ * expired. completed ⇒ download from `unsigned_urls` immediately.
16
+ * - No client idempotency key is documented, so ambiguous submit failures get
17
+ * the "check the console before retrying" treatment (same as Ark/DashScope).
18
+ */
19
+ export declare const OPENROUTER_DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
20
+ export declare const openrouterAdapter: VideoProviderAdapter;
21
+ //# sourceMappingURL=openrouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,2BAA2B,iCAAiC,CAAC;AAoC1E,eAAO,MAAM,iBAAiB,EAAE,oBAgJ/B,CAAC"}
@@ -0,0 +1,169 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { extname } from 'node:path';
3
+ import { AmbiguousSubmitError, httpStatusError, missingKeyError, networkError, safeBasename, VideoGenError, } from '../errors.js';
4
+ import { requestFingerprint } from './request.js';
5
+ import { downloadFile } from './task.js';
6
+ /**
7
+ * OpenRouter video generation (google/veo-3.1 and friends).
8
+ *
9
+ * POST {baseUrl}/videos → 202 { id, generation_id, polling_url, status }
10
+ * GET {baseUrl}/videos/{id} → { status, unsigned_urls[], error }
11
+ * GET {unsigned_urls[0]} → the mp4 itself
12
+ *
13
+ * Verified against the official docs (openrouter.ai/docs, 2026-07):
14
+ * - Frames ride in `frame_images` with `frame_type: first_frame|last_frame`;
15
+ * extra references go in `input_references` (image/audio/video urls).
16
+ * - `generate_audio` toggles native audio (default false upstream — we send it
17
+ * explicitly from the caller's capability decision).
18
+ * - Status enum: pending | in_progress | completed | failed | cancelled |
19
+ * expired. completed ⇒ download from `unsigned_urls` immediately.
20
+ * - No client idempotency key is documented, so ambiguous submit failures get
21
+ * the "check the console before retrying" treatment (same as Ark/DashScope).
22
+ */
23
+ export const OPENROUTER_DEFAULT_BASE_URL = 'https://openrouter.ai/api/v1';
24
+ const MIME_BY_EXT = {
25
+ '.png': 'image/png',
26
+ '.jpg': 'image/jpeg',
27
+ '.jpeg': 'image/jpeg',
28
+ '.webp': 'image/webp',
29
+ };
30
+ async function imageFileToDataUri(path) {
31
+ const mime = MIME_BY_EXT[extname(path).toLowerCase()];
32
+ if (!mime) {
33
+ throw new VideoGenError(`Reference image must be png/jpg/webp: ${safeBasename(path)}`, 'openrouter: unsupported image extension');
34
+ }
35
+ let bytes;
36
+ try {
37
+ bytes = await readFile(path);
38
+ }
39
+ catch {
40
+ throw new VideoGenError(`Reference image is not readable: ${safeBasename(path)}`, 'openrouter: image unreadable');
41
+ }
42
+ return `data:${mime};base64,${bytes.toString('base64')}`;
43
+ }
44
+ function ambiguousSubmitError() {
45
+ return new AmbiguousSubmitError('Task creation failed with an ambiguous result (network error or server 5xx). The provider MAY have created a paid task — check OpenRouter activity before retrying to avoid double billing.', 'openrouter submit: ambiguous outcome');
46
+ }
47
+ export const openrouterAdapter = {
48
+ async submit(provider, remoteModelId, params, fetchImpl, signal) {
49
+ if (!provider.apiKey) {
50
+ throw missingKeyError('openrouter', 'OPENROUTER_API_KEY', provider.apiKeyPath);
51
+ }
52
+ const body = { model: remoteModelId, prompt: params.prompt };
53
+ if (params.durationSec != null)
54
+ body.duration = params.durationSec;
55
+ if (params.resolution)
56
+ body.resolution = params.resolution;
57
+ if (params.aspectRatio)
58
+ body.aspect_ratio = params.aspectRatio;
59
+ if (params.generateAudio != null)
60
+ body.generate_audio = params.generateAudio;
61
+ const frameImages = [];
62
+ if (params.firstFramePath) {
63
+ frameImages.push({
64
+ type: 'image_url',
65
+ image_url: { url: await imageFileToDataUri(params.firstFramePath) },
66
+ frame_type: 'first_frame',
67
+ });
68
+ }
69
+ if (params.lastFramePath) {
70
+ frameImages.push({
71
+ type: 'image_url',
72
+ image_url: { url: await imageFileToDataUri(params.lastFramePath) },
73
+ frame_type: 'last_frame',
74
+ });
75
+ }
76
+ if (frameImages.length > 0)
77
+ body.frame_images = frameImages;
78
+ if (params.referenceImagePaths?.length) {
79
+ body.input_references = await Promise.all(params.referenceImagePaths.map(async (path) => ({
80
+ type: 'image_url',
81
+ image_url: { url: await imageFileToDataUri(path) },
82
+ })));
83
+ }
84
+ let res;
85
+ try {
86
+ res = await fetchImpl(`${provider.baseUrl}/videos`, {
87
+ method: 'POST',
88
+ headers: {
89
+ authorization: `Bearer ${provider.apiKey}`,
90
+ 'content-type': 'application/json',
91
+ },
92
+ body: JSON.stringify(body),
93
+ signal: signal ?? null,
94
+ });
95
+ }
96
+ catch {
97
+ throw ambiguousSubmitError();
98
+ }
99
+ if (!res.ok) {
100
+ if (res.status >= 500)
101
+ throw ambiguousSubmitError();
102
+ throw httpStatusError('openrouter', 'submit', res.status);
103
+ }
104
+ let taskId;
105
+ try {
106
+ const json = (await res.json());
107
+ taskId = json.id;
108
+ }
109
+ catch {
110
+ throw ambiguousSubmitError();
111
+ }
112
+ if (!taskId) {
113
+ // 2xx but no id: the task MAY exist server-side — this is ambiguous,
114
+ // not a clean failure, and must park the shot rather than re-submit.
115
+ throw new AmbiguousSubmitError('The provider accepted the request but returned no task id. Not retrying automatically; check OpenRouter activity.', 'openrouter submit: no task id');
116
+ }
117
+ return {
118
+ taskId,
119
+ submittedAt: new Date().toISOString(),
120
+ requestFingerprint: requestFingerprint(remoteModelId, params),
121
+ };
122
+ },
123
+ async inspect(provider, handle, fetchImpl, signal) {
124
+ if (!provider.apiKey) {
125
+ throw missingKeyError('openrouter', 'OPENROUTER_API_KEY', provider.apiKeyPath);
126
+ }
127
+ let res;
128
+ try {
129
+ res = await fetchImpl(`${provider.baseUrl}/videos/${encodeURIComponent(handle.taskId)}`, {
130
+ headers: { authorization: `Bearer ${provider.apiKey}` },
131
+ signal: signal ?? null,
132
+ });
133
+ }
134
+ catch {
135
+ throw networkError('openrouter', 'inspect');
136
+ }
137
+ if (!res.ok)
138
+ throw httpStatusError('openrouter', 'inspect', res.status);
139
+ const json = (await res.json());
140
+ switch (json.status) {
141
+ case 'pending':
142
+ return { phase: 'pending' };
143
+ case 'in_progress':
144
+ return { phase: 'running' };
145
+ case 'completed': {
146
+ const videoUrl = json.unsigned_urls?.[0];
147
+ if (!videoUrl) {
148
+ throw new VideoGenError('The task completed but returned no video URL. Report this with the task id.', 'openrouter inspect: completed without url');
149
+ }
150
+ return { phase: 'succeeded', videoUrl };
151
+ }
152
+ case 'failed':
153
+ case 'cancelled':
154
+ case 'expired': {
155
+ const message = typeof json.error === 'string'
156
+ ? json.error
157
+ : (json.error?.message ?? `task ${json.status}`);
158
+ return { phase: 'failed', message };
159
+ }
160
+ default:
161
+ throw new VideoGenError(`The provider returned an unknown task status. Task id kept for support: ${handle.taskId}.`, 'openrouter inspect: unknown status');
162
+ }
163
+ },
164
+ async downloadTo(_provider, _handle, videoUrl, destPath, fetchImpl, signal) {
165
+ return downloadFile({ url: videoUrl, destPath, fetchImpl, signal });
166
+ },
167
+ // cancel: not covered by the submitted docs; local stops are polling_stopped.
168
+ };
169
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { GenerateVideoParams } from '../types.js';
2
+ /** Stable identity shared by orchestration and every provider adapter. */
3
+ export declare function requestFingerprint(remoteModelId: string, params: GenerateVideoParams): string;
4
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/providers/request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAkB7F"}
@@ -0,0 +1,20 @@
1
+ import { createHash } from 'node:crypto';
2
+ /** Stable identity shared by orchestration and every provider adapter. */
3
+ export function requestFingerprint(remoteModelId, params) {
4
+ return createHash('sha256')
5
+ .update(JSON.stringify({
6
+ model: remoteModelId,
7
+ requestId: params.requestId,
8
+ prompt: params.prompt,
9
+ firstFramePath: params.firstFramePath,
10
+ lastFramePath: params.lastFramePath,
11
+ referenceImagePaths: params.referenceImagePaths,
12
+ durationSec: params.durationSec,
13
+ aspectRatio: params.aspectRatio,
14
+ resolution: params.resolution,
15
+ generateAudio: params.generateAudio,
16
+ }))
17
+ .digest('hex')
18
+ .slice(0, 16);
19
+ }
20
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/providers/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,aAAqB,EAAE,MAA2B;IACnF,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CACL,IAAI,CAAC,SAAS,CAAC;QACb,KAAK,EAAE,aAAa;QACpB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CACH;SACA,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { VideoGenError } from '../errors.js';
2
+ import type { RemoteTaskStatus, VideoFileMeta } from '../types.js';
3
+ /**
4
+ * Shared machinery for task-style video APIs: poll-with-limits, streaming
5
+ * download with guards, and a sliding-window rate limiter. Adapters only build
6
+ * requests and parse responses; everything here is signal-driven so a tool
7
+ * cancellation propagates into polling loops and downloads.
8
+ */
9
+ /**
10
+ * Provider failure messages are UNTRUSTED input: they can be unbounded, carry
11
+ * signed URLs, or attempt prompt injection into the LLM that reads the tool
12
+ * result. Collapse to one line, drop URLs, cap length.
13
+ */
14
+ export declare function sanitizeProviderMessage(raw: string): string;
15
+ export declare class CancelledError extends VideoGenError {
16
+ constructor();
17
+ }
18
+ /**
19
+ * Poll `check` until the task succeeds, fails, or the budget runs out.
20
+ * Defaults to a 2s interval, 300 attempts, and at most 5 consecutive
21
+ * transport errors.
22
+ */
23
+ export declare function pollTask(opts: {
24
+ check: () => Promise<RemoteTaskStatus>;
25
+ signal?: AbortSignal | undefined;
26
+ intervalMs?: number | undefined;
27
+ maxAttempts?: number | undefined;
28
+ maxConsecutiveErrors?: number | undefined;
29
+ onTick?: ((attempt: number, phase: string) => void) | undefined;
30
+ }): Promise<Extract<RemoteTaskStatus, {
31
+ phase: 'succeeded';
32
+ }>>;
33
+ export declare function downloadFile(opts: {
34
+ url: string;
35
+ destPath: string;
36
+ fetchImpl: typeof fetch;
37
+ signal?: AbortSignal | undefined;
38
+ maxBytes?: number | undefined;
39
+ timeoutMs?: number | undefined;
40
+ }): Promise<VideoFileMeta>;
41
+ /**
42
+ * Process-local sliding-window rate limiter (per provider). Daily caps are
43
+ * tracked for the process lifetime only — good enough to protect a single
44
+ * render run; persistent quota accounting is the provider dashboard's job.
45
+ */
46
+ export declare class RateLimiter {
47
+ private readonly maxPerMinute?;
48
+ private readonly maxPerDay?;
49
+ private readonly calls;
50
+ constructor(maxPerMinute?: number | undefined, maxPerDay?: number | undefined);
51
+ acquire(signal?: AbortSignal): Promise<void>;
52
+ }
53
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/providers/task.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,aAAa,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE;;;;;GAKG;AAEH;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D;AAwBD,qBAAa,cAAe,SAAQ,aAAa;;CAIhD;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACnC,KAAK,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACjE,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,CA8C7D;AAeD,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGzB;AAED;;;;GAIG;AACH,qBAAa,WAAW;IAIpB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAJ7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;gBAGnB,YAAY,CAAC,EAAE,MAAM,YAAA,EACrB,SAAS,CAAC,EAAE,MAAM,YAAA;IAG/B,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBnD"}
@@ -0,0 +1,209 @@
1
+ import { createWriteStream, existsSync } from 'node:fs';
2
+ import { lstat, rename, unlink } from 'node:fs/promises';
3
+ import { Readable, Transform } from 'node:stream';
4
+ import { pipeline } from 'node:stream/promises';
5
+ import { RemoteTaskFailedError, RetryableProviderError, safeBasename, VideoGenError, } from '../errors.js';
6
+ /**
7
+ * Shared machinery for task-style video APIs: poll-with-limits, streaming
8
+ * download with guards, and a sliding-window rate limiter. Adapters only build
9
+ * requests and parse responses; everything here is signal-driven so a tool
10
+ * cancellation propagates into polling loops and downloads.
11
+ */
12
+ /**
13
+ * Provider failure messages are UNTRUSTED input: they can be unbounded, carry
14
+ * signed URLs, or attempt prompt injection into the LLM that reads the tool
15
+ * result. Collapse to one line, drop URLs, cap length.
16
+ */
17
+ export function sanitizeProviderMessage(raw) {
18
+ const oneLine = raw.split(/[\r\n]/, 1)[0] ?? '';
19
+ const noUrls = oneLine.replace(/https?:\/\/\S+/g, '<url>');
20
+ return noUrls.length > 200 ? `${noUrls.slice(0, 200)}…` : noUrls;
21
+ }
22
+ const DEFAULT_POLL_INTERVAL_MS = 2000;
23
+ const DEFAULT_MAX_POLL_ATTEMPTS = 300;
24
+ const DEFAULT_MAX_CONSECUTIVE_ERRORS = 5;
25
+ function sleep(ms, signal) {
26
+ return new Promise((resolve, reject) => {
27
+ const timer = setTimeout(() => {
28
+ signal?.removeEventListener('abort', onAbort);
29
+ resolve();
30
+ }, ms);
31
+ const onAbort = () => {
32
+ clearTimeout(timer);
33
+ reject(new VideoGenError('Cancelled.', 'cancelled'));
34
+ };
35
+ if (signal?.aborted) {
36
+ onAbort();
37
+ return;
38
+ }
39
+ signal?.addEventListener('abort', onAbort, { once: true });
40
+ });
41
+ }
42
+ export class CancelledError extends VideoGenError {
43
+ constructor() {
44
+ super('Cancelled.', 'cancelled');
45
+ }
46
+ }
47
+ /**
48
+ * Poll `check` until the task succeeds, fails, or the budget runs out.
49
+ * Defaults to a 2s interval, 300 attempts, and at most 5 consecutive
50
+ * transport errors.
51
+ */
52
+ export async function pollTask(opts) {
53
+ const intervalMs = opts.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
54
+ const maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;
55
+ const maxConsecutiveErrors = opts.maxConsecutiveErrors ?? DEFAULT_MAX_CONSECUTIVE_ERRORS;
56
+ let consecutiveErrors = 0;
57
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
58
+ if (opts.signal?.aborted)
59
+ throw new CancelledError();
60
+ let status;
61
+ try {
62
+ status = await opts.check();
63
+ consecutiveErrors = 0;
64
+ }
65
+ catch (error) {
66
+ if (error instanceof VideoGenError && error.logSummary === 'cancelled')
67
+ throw error;
68
+ if (!(error instanceof RetryableProviderError))
69
+ throw error;
70
+ consecutiveErrors++;
71
+ if (consecutiveErrors >= maxConsecutiveErrors) {
72
+ throw new VideoGenError('Lost contact with the video provider while polling (repeated network errors). The remote task may still be running and billable; check usage before retrying.', 'poll: consecutive transport errors');
73
+ }
74
+ await sleep(intervalMs, opts.signal);
75
+ continue;
76
+ }
77
+ opts.onTick?.(attempt, status.phase);
78
+ if (status.phase === 'succeeded')
79
+ return status;
80
+ if (status.phase === 'failed') {
81
+ // Provider text is UNTRUSTED: it stays off the LLM channel entirely
82
+ // (errors.ts contract). The sanitized one-liner goes to stderr/manifest
83
+ // via logSummary; the user gets a vetted, actionable message.
84
+ throw new RemoteTaskFailedError('Video generation failed on the provider side. Retry once; if it persists, adjust the prompt or model. The job manifest records the (sanitized) provider reason.', 'poll: task failed', sanitizeProviderMessage(status.message));
85
+ }
86
+ await sleep(intervalMs, opts.signal);
87
+ }
88
+ throw new VideoGenError('Video generation did not finish within the polling budget. The remote task may still complete later and be billable; check provider usage before retrying.', 'poll: max attempts exceeded');
89
+ }
90
+ const DEFAULT_MAX_DOWNLOAD_BYTES = 2 * 1024 * 1024 * 1024; // 2 GiB ceiling for 4K clips
91
+ /** MP4 files carry an `ftyp` box at offset 4; reject anything else (error pages, XML). */
92
+ function looksLikeMp4(header) {
93
+ return header.length >= 8 && header.subarray(4, 8).toString('ascii') === 'ftyp';
94
+ }
95
+ /**
96
+ * Stream `url` to `destPath` with guards: temp file in the same directory,
97
+ * byte ceiling, mp4 magic-byte check, atomic rename into place.
98
+ */
99
+ const DEFAULT_DOWNLOAD_TIMEOUT_MS = 10 * 60 * 1000; // 10 min overall deadline
100
+ export async function downloadFile(opts) {
101
+ const maxBytes = opts.maxBytes ?? DEFAULT_MAX_DOWNLOAD_BYTES;
102
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS;
103
+ // EXCLUSIVELY-created temp (O_EXCL 'wx' — a pre-placed symlink fails
104
+ // EEXIST instead of being followed) + atomic rename at the end.
105
+ let tmpPath = '';
106
+ for (let i = 0;; i++) {
107
+ const candidate = `${opts.destPath}.tmp-${process.pid}-${i}`;
108
+ if (existsSync(candidate))
109
+ continue;
110
+ tmpPath = candidate;
111
+ break;
112
+ }
113
+ // Overall deadline, combined with the caller's cancellation signal — a
114
+ // never-ending response stream must not park the foreground tool forever.
115
+ const signal = AbortSignal.any([
116
+ ...(opts.signal ? [opts.signal] : []),
117
+ AbortSignal.timeout(timeoutMs),
118
+ ]);
119
+ // Destination symlink defense: refuse anything pre-existing at the final
120
+ // name that is not a regular file (belt-and-suspenders — the unique temp
121
+ // name + atomic rename already prevent following links).
122
+ {
123
+ const st = await lstat(opts.destPath).catch(() => null);
124
+ if (st && (st.isSymbolicLink() || !st.isFile())) {
125
+ throw new VideoGenError(`Refusing to write ${safeBasename(opts.destPath)} — it already exists and is not a regular file (symlink?). Remove it and retry.`, 'download: destination not a file');
126
+ }
127
+ }
128
+ let res;
129
+ try {
130
+ res = await opts.fetchImpl(opts.url, { signal });
131
+ }
132
+ catch {
133
+ throw new VideoGenError('Downloading the finished video failed: network error. The video URL may have expired — rerun to regenerate.', 'download: network error');
134
+ }
135
+ if (!res.ok || !res.body) {
136
+ throw new VideoGenError(`Downloading the finished video failed with HTTP ${res.status}. The video URL may have expired — rerun to regenerate.`, `download: HTTP ${res.status}`);
137
+ }
138
+ let bytes = 0;
139
+ let headerBytes = 0;
140
+ const headerChunks = [];
141
+ const counting = new Transform({
142
+ transform(chunk, _enc, cb) {
143
+ bytes += chunk.length;
144
+ if (bytes > maxBytes) {
145
+ cb(new VideoGenError('Video file exceeds the size ceiling.', 'download: too large'));
146
+ return;
147
+ }
148
+ if (headerBytes < 16) {
149
+ headerChunks.push(Buffer.from(chunk.subarray(0, 16)));
150
+ headerBytes += chunk.length;
151
+ }
152
+ cb(null, chunk);
153
+ },
154
+ });
155
+ try {
156
+ await pipeline(Readable.fromWeb(res.body), counting, createWriteStream(tmpPath, { flags: 'wx' }));
157
+ }
158
+ catch (error) {
159
+ await unlink(tmpPath).catch(() => { });
160
+ if (error instanceof VideoGenError)
161
+ throw error;
162
+ if (opts.signal?.aborted)
163
+ throw new CancelledError();
164
+ if (signal.aborted) {
165
+ throw new VideoGenError('Downloading the video timed out. Retry once — the clip is large or the connection slow.', 'download: timeout');
166
+ }
167
+ throw new VideoGenError('Downloading the finished video failed mid-stream. Retry once.', 'download: stream error');
168
+ }
169
+ const header = Buffer.concat(headerChunks);
170
+ if (!looksLikeMp4(header)) {
171
+ await unlink(tmpPath).catch(() => { });
172
+ throw new VideoGenError('The provider returned a file that is not an mp4. Not saving it; check the model and prompt.', 'download: not mp4');
173
+ }
174
+ await rename(tmpPath, opts.destPath);
175
+ return { path: opts.destPath, bytes };
176
+ }
177
+ /**
178
+ * Process-local sliding-window rate limiter (per provider). Daily caps are
179
+ * tracked for the process lifetime only — good enough to protect a single
180
+ * render run; persistent quota accounting is the provider dashboard's job.
181
+ */
182
+ export class RateLimiter {
183
+ maxPerMinute;
184
+ maxPerDay;
185
+ calls = [];
186
+ constructor(maxPerMinute, maxPerDay) {
187
+ this.maxPerMinute = maxPerMinute;
188
+ this.maxPerDay = maxPerDay;
189
+ }
190
+ async acquire(signal) {
191
+ for (;;) {
192
+ const now = Date.now();
193
+ const minuteAgo = now - 60_000;
194
+ const dayAgo = now - 86_400_000;
195
+ while (this.calls.length > 0 && this.calls[0] < dayAgo)
196
+ this.calls.shift();
197
+ const inLastMinute = this.calls.filter((t) => t >= minuteAgo).length;
198
+ const minuteOk = this.maxPerMinute == null || inLastMinute < this.maxPerMinute;
199
+ const dayOk = this.maxPerDay == null || this.calls.length < this.maxPerDay;
200
+ if (minuteOk && dayOk) {
201
+ this.calls.push(now);
202
+ return;
203
+ }
204
+ const waitMs = minuteOk ? 60_000 : Math.max(1000, 60_000 - (now - (this.calls[0] ?? now)));
205
+ await sleep(Math.min(waitMs, 60_000), signal);
206
+ }
207
+ }
208
+ }
209
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/providers/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { errorMessageForUser } from './errors.js';
2
+ import { concatVideos } from './ffmpeg.js';
3
+ import { type ActiveJobs } from './jobs/store.js';
4
+ import { type RateLimiter } from './providers/task.js';
5
+ import type { ResolvedModel, VideoGenSettings, VideoProviderAdapter } from './types.js';
6
+ /**
7
+ * Multi-shot render orchestration (`video_render`).
8
+ *
9
+ * Contract (design review):
10
+ * - input is `<jobDir>/render-input.json`; the parent directory IS the job and
11
+ * must live under the video-gen output dir;
12
+ * - the spec is immutable per job: resume verifies a fingerprint over
13
+ * spec + frame contents + model/provider and REFUSES on drift (revisions
14
+ * go in a new job directory);
15
+ * - remote task handles persist to the manifest the moment submit() returns;
16
+ * reruns resume via inspect() and never re-bill finished shots;
17
+ * - foreground execution with onUpdate progress; signal cancels locally
18
+ * (`polling_stopped` — the remote task may keep billing).
19
+ */
20
+ export type RenderShotInput = {
21
+ id: string;
22
+ videoPrompt: string;
23
+ firstFramePath: string;
24
+ lastFramePath?: string | undefined;
25
+ durationSec?: number | undefined;
26
+ };
27
+ export type RenderInput = {
28
+ title?: string | undefined;
29
+ aspectRatio?: string | undefined;
30
+ shots: RenderShotInput[];
31
+ };
32
+ export type RenderRunResult = {
33
+ jobId: string;
34
+ finalVideoPath: string;
35
+ shotsDone: number;
36
+ degraded: string[];
37
+ };
38
+ export declare function runRender(opts: {
39
+ renderSpecPath: string;
40
+ allowDegradations?: string[] | undefined;
41
+ settings: VideoGenSettings;
42
+ cwd: string;
43
+ resolved: ResolvedModel;
44
+ adapter: VideoProviderAdapter;
45
+ activeJobs: ActiveJobs;
46
+ rateLimiter: RateLimiter;
47
+ ffmpegPath: string;
48
+ signal?: AbortSignal | undefined;
49
+ onUpdate?: ((msg: string) => void) | undefined;
50
+ concatImpl?: typeof concatVideos | undefined;
51
+ }): Promise<RenderRunResult>;
52
+ export { errorMessageForUser };
53
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,mBAAmB,EAMpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,KAAK,UAAU,EAOhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAA4B,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAGV,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAwHF,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACzC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,YAAY,GAAG,SAAS,CAAC;CAC9C,GAAG,OAAO,CAAC,eAAe,CAAC,CA+c3B;AAeD,OAAO,EAAE,mBAAmB,EAAE,CAAC"}