@mevdragon/vidfarm-devcli 0.20.6 → 0.20.8

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 (154) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +15 -1
  2. package/.agents/skills/vidfarm-director/SKILL.md +106 -0
  3. package/.agents/skills/vidfarm-director/recipes/find-and-fork-template.md +16 -0
  4. package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +13 -0
  5. package/.agents/skills/vidfarm-director/recipes/onboard-a-new-director.md +13 -0
  6. package/.agents/skills/vidfarm-director/recipes/retheme-template.md +17 -0
  7. package/.agents/skills/vidfarm-director/references/assets-and-sourcing.md +111 -0
  8. package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +243 -0
  9. package/.agents/skills/vidfarm-director/references/core-workflows.md +273 -0
  10. package/.agents/skills/vidfarm-director/references/editor-workflows.md +365 -0
  11. package/.agents/skills/vidfarm-director/references/onboarding.md +28 -0
  12. package/.agents/skills/vidfarm-director/references/primitives.md +265 -0
  13. package/SKILL.director.md +476 -260
  14. package/dist/src/cli.js +362 -96
  15. package/dist/src/devcli/clips.js +15 -10
  16. package/dist/src/devcli/doctor.js +2 -2
  17. package/dist/src/devcli/local-backend.js +46 -2
  18. package/dist/src/services/clip-curation/cost.js +5 -1
  19. package/dist/src/services/clip-curation/gemini.js +10 -0
  20. package/package.json +30 -10
  21. package/SKILL.platform.md +0 -432
  22. package/demo/README.md +0 -28
  23. package/demo/dist/app.css +0 -1
  24. package/demo/dist/app.js +0 -1850
  25. package/demo/dist/chunks/chunk-DXB73IDG.js +0 -1
  26. package/demo/dist/chunks/chunk-S7OWAJDS.js +0 -36
  27. package/demo/dist/chunks/chunk-VTIBZ6AN.js +0 -1
  28. package/demo/dist/chunks/dist-ADSJKBVE.js +0 -332
  29. package/demo/dist/chunks/domEditingLayers-VZMLL4AP-SGHWPND4.js +0 -1
  30. package/demo/dist/chunks/hyperframes-player-XB65TCD6.js +0 -425
  31. package/demo/dist/chunks/lib-XAQ37YOE.js +0 -1
  32. package/demo/dist/chunks/src-TJ2QYA4U.js +0 -207
  33. package/demo/dist/favicon.ico +0 -0
  34. package/demo/dist/icons/timeline/audio.svg +0 -7
  35. package/demo/dist/icons/timeline/captions.svg +0 -5
  36. package/demo/dist/icons/timeline/composition.svg +0 -12
  37. package/demo/dist/icons/timeline/image.svg +0 -18
  38. package/demo/dist/icons/timeline/music.svg +0 -10
  39. package/demo/dist/icons/timeline/text.svg +0 -3
  40. package/demo/dist/index.html +0 -15
  41. package/dist/src/account-pages-legacy.js +0 -9396
  42. package/dist/src/account-pages.js +0 -61
  43. package/dist/src/app.js +0 -21603
  44. package/dist/src/composition-runtime.js +0 -1053
  45. package/dist/src/config.js +0 -217
  46. package/dist/src/context.js +0 -447
  47. package/dist/src/dev-app-legacy.js +0 -739
  48. package/dist/src/dev-app.js +0 -6
  49. package/dist/src/devcli/migrate-local.js +0 -140
  50. package/dist/src/devcli/sync.js +0 -368
  51. package/dist/src/domain.js +0 -5
  52. package/dist/src/editor-chat-history.js +0 -82
  53. package/dist/src/editor-chat.js +0 -828
  54. package/dist/src/editor-dark-theme.js +0 -1128
  55. package/dist/src/frontend/debug.js +0 -71
  56. package/dist/src/frontend/discover-client.js +0 -130
  57. package/dist/src/frontend/discover-store.js +0 -23
  58. package/dist/src/frontend/file-directory.js +0 -1018
  59. package/dist/src/frontend/flockposter-cache-store.js +0 -124
  60. package/dist/src/frontend/homepage-client.js +0 -446
  61. package/dist/src/frontend/homepage-shared.js +0 -201
  62. package/dist/src/frontend/homepage-store.js +0 -66
  63. package/dist/src/frontend/homepage-view.js +0 -705
  64. package/dist/src/frontend/page-runtime-client.js +0 -132
  65. package/dist/src/frontend/page-runtime-store.js +0 -9
  66. package/dist/src/frontend/sentry.js +0 -42
  67. package/dist/src/frontend/template-editor-chat.js +0 -4181
  68. package/dist/src/help-page.js +0 -346
  69. package/dist/src/homepage.js +0 -1458
  70. package/dist/src/index.js +0 -16
  71. package/dist/src/instrument.js +0 -30
  72. package/dist/src/landing-page.js +0 -384
  73. package/dist/src/page-runtime.js +0 -2
  74. package/dist/src/page-shell.js +0 -1452
  75. package/dist/src/primitive-context.js +0 -416
  76. package/dist/src/primitive-registry.js +0 -3940
  77. package/dist/src/primitive-sdk.js +0 -4
  78. package/dist/src/primitives/hyperframes-media.js +0 -108
  79. package/dist/src/react-page-shell.js +0 -35
  80. package/dist/src/ready-post-schedule-component.js +0 -1540
  81. package/dist/src/registry.js +0 -296
  82. package/dist/src/reskin/agency-page.js +0 -299
  83. package/dist/src/reskin/calendar-page.js +0 -568
  84. package/dist/src/reskin/chat-page.js +0 -942
  85. package/dist/src/reskin/discover-page.js +0 -1788
  86. package/dist/src/reskin/document.js +0 -1587
  87. package/dist/src/reskin/help-page.js +0 -357
  88. package/dist/src/reskin/index-page.js +0 -62
  89. package/dist/src/reskin/inpaint-clipper-page.js +0 -890
  90. package/dist/src/reskin/inpaint-page.js +0 -2554
  91. package/dist/src/reskin/inpaint-video-page.js +0 -1339
  92. package/dist/src/reskin/job-runs-page.js +0 -477
  93. package/dist/src/reskin/library-page.js +0 -1634
  94. package/dist/src/reskin/login-page.js +0 -262
  95. package/dist/src/reskin/portfolio-page.js +0 -687
  96. package/dist/src/reskin/pricing-page.js +0 -390
  97. package/dist/src/reskin/settings-page.js +0 -732
  98. package/dist/src/reskin/theme.js +0 -711
  99. package/dist/src/runtime.js +0 -35
  100. package/dist/src/services/api-call-history.js +0 -249
  101. package/dist/src/services/auth.js +0 -152
  102. package/dist/src/services/billing-pricing.js +0 -39
  103. package/dist/src/services/billing.js +0 -241
  104. package/dist/src/services/cast.js +0 -127
  105. package/dist/src/services/chat-threads.js +0 -92
  106. package/dist/src/services/clip-records.js +0 -250
  107. package/dist/src/services/clip-search.js +0 -77
  108. package/dist/src/services/clip-vectors.js +0 -125
  109. package/dist/src/services/composition-sanitize.js +0 -124
  110. package/dist/src/services/composition-watch.js +0 -79
  111. package/dist/src/services/elevenlabs.js +0 -222
  112. package/dist/src/services/file-directory.js +0 -117
  113. package/dist/src/services/fork-access.js +0 -93
  114. package/dist/src/services/fork-manifest.js +0 -42
  115. package/dist/src/services/ghostcut.js +0 -179
  116. package/dist/src/services/hyperframes.js +0 -3654
  117. package/dist/src/services/job-capacity.js +0 -14
  118. package/dist/src/services/job-logs.js +0 -197
  119. package/dist/src/services/jobs.js +0 -136
  120. package/dist/src/services/local-dynamo.js +0 -0
  121. package/dist/src/services/media-processing.js +0 -766
  122. package/dist/src/services/primitive-media-lambda.js +0 -280
  123. package/dist/src/services/providers.js +0 -2748
  124. package/dist/src/services/rate-limits.js +0 -262
  125. package/dist/src/services/scene-annotations.js +0 -32
  126. package/dist/src/services/serverless-auth.js +0 -382
  127. package/dist/src/services/serverless-jobs.js +0 -1084
  128. package/dist/src/services/serverless-provider-keys.js +0 -409
  129. package/dist/src/services/serverless-records.js +0 -1515
  130. package/dist/src/services/serverless-template-configs.js +0 -75
  131. package/dist/src/services/storage.js +0 -461
  132. package/dist/src/services/swipe-customize.js +0 -437
  133. package/dist/src/services/template-certification.js +0 -413
  134. package/dist/src/services/template-loader.js +0 -99
  135. package/dist/src/services/template-runtime-bundles.js +0 -217
  136. package/dist/src/services/template-sources.js +0 -1017
  137. package/dist/src/services/upstream.js +0 -248
  138. package/dist/src/services/video-normalization.js +0 -2
  139. package/dist/src/services/webhooks.js +0 -62
  140. package/dist/src/template-editor-pages.js +0 -2576
  141. package/dist/src/template-editor-shell.js +0 -2893
  142. package/dist/src/template-sdk.js +0 -4
  143. package/dist/src/worker.js +0 -17
  144. package/public/assets/discover-client-app.js +0 -1
  145. package/public/assets/file-directory-app.js +0 -3
  146. package/public/assets/homepage-app.js +0 -54
  147. package/public/assets/homepage-client-app.js +0 -80
  148. package/public/assets/page-runtime-client-app.js +0 -94
  149. package/public/assets/placeholders/scene-placeholder.png +0 -0
  150. package/src/assets/SELLING_AWARENESS_STAGES.md +0 -579
  151. package/src/assets/SELLING_WITH_HOOKS.md +0 -377
  152. package/src/assets/SELLING_WITH_VSLS.md +0 -606
  153. package/src/assets/favicon.ico +0 -0
  154. package/src/assets/logo-vidfarm.png +0 -0
@@ -1,416 +0,0 @@
1
- import { readFile } from "node:fs/promises";
2
- import * as Sentry from "@sentry/node";
3
- import { config } from "./config.js";
4
- import { devErrorFields, devLog } from "./lib/dev-log.js";
5
- import { createId } from "./lib/ids.js";
6
- import { jobLogStore } from "./services/job-logs.js";
7
- import { RenderInProgressError } from "./services/hyperframes.js";
8
- import { estimateNormalizationCostUsd, normalizeVideoAsset } from "./services/video-normalization.js";
9
- export function createPrimitiveJobContext(input) {
10
- const prefix = input.storage.primitiveJobPrefix(input.primitive.id, input.customer.id, input.job.id);
11
- const buildArtifactUrl = (storageKey, fallbackUrl) => fallbackUrl ?? input.storage.getPublicUrl(storageKey) ?? buildPlatformMediaUrl(storageKey);
12
- // Billing records are written after the billable work (render, normalize,
13
- // etc.) has already succeeded. A transient billing failure must never fail
14
- // the job — the customer would retry and pay for the expensive work twice.
15
- const recordBillingNonFatal = async (record) => {
16
- try {
17
- await input.billing.record(record);
18
- }
19
- catch (error) {
20
- Sentry.captureException(error);
21
- devLog("billing.record_failed_nonfatal", {
22
- job_id: input.job.id,
23
- customer_id: input.customer.id,
24
- template_id: input.primitive.id,
25
- cost_center_slug: record.costCenterSlug ?? null,
26
- idempotency_key: record.idempotencyKey ?? null,
27
- ...devErrorFields(error)
28
- }, "warn");
29
- }
30
- };
31
- return {
32
- env: config.isProduction ? "production" : "development",
33
- customer: input.customer,
34
- logger: {
35
- debug(message, metadata = {}) {
36
- jobLogStore.addEvent({
37
- id: createId("evt"),
38
- jobId: input.job.id,
39
- level: "debug",
40
- message,
41
- metadata,
42
- progress: null,
43
- artifactKey: null
44
- });
45
- },
46
- info(message, metadata = {}) {
47
- jobLogStore.addEvent({
48
- id: createId("evt"),
49
- jobId: input.job.id,
50
- level: "info",
51
- message,
52
- metadata,
53
- progress: null,
54
- artifactKey: null
55
- });
56
- },
57
- warn(message, metadata = {}) {
58
- jobLogStore.addEvent({
59
- id: createId("evt"),
60
- jobId: input.job.id,
61
- level: "warn",
62
- message,
63
- metadata,
64
- progress: null,
65
- artifactKey: null
66
- });
67
- },
68
- error(message, metadata = {}) {
69
- jobLogStore.addEvent({
70
- id: createId("evt"),
71
- jobId: input.job.id,
72
- level: "error",
73
- message,
74
- metadata,
75
- progress: null,
76
- artifactKey: null
77
- });
78
- },
79
- progress(progress, message, metadata = {}) {
80
- jobLogStore.addEvent({
81
- id: createId("evt"),
82
- jobId: input.job.id,
83
- level: "info",
84
- message,
85
- metadata,
86
- progress,
87
- artifactKey: typeof metadata.artifactKey === "string" ? metadata.artifactKey : null
88
- });
89
- void input.jobs.updateJobStatus({
90
- id: input.job.id,
91
- status: "running",
92
- progress
93
- });
94
- }
95
- },
96
- storage: {
97
- async putJson(key, value) {
98
- const stored = await input.storage.putJson(`${prefix}/${key}`, value);
99
- const artifactUrl = buildArtifactUrl(stored.key, stored.url);
100
- await insertArtifact("json", stored.key, artifactUrl, {});
101
- return { ...stored, url: artifactUrl };
102
- },
103
- async putText(key, value, contentType = "text/plain; charset=utf-8") {
104
- const stored = await input.storage.putText(`${prefix}/${key}`, value, contentType);
105
- const artifactUrl = buildArtifactUrl(stored.key, stored.url);
106
- await insertArtifact("text", stored.key, artifactUrl, { contentType });
107
- return { ...stored, url: artifactUrl };
108
- },
109
- async putBuffer(key, value, options = {}) {
110
- const stored = await input.storage.putBuffer(`${prefix}/${key}`, value, options.contentType);
111
- const artifactUrl = buildArtifactUrl(stored.key, stored.url);
112
- await insertArtifact(options.kind ?? "binary", stored.key, artifactUrl, {
113
- ...(options.metadata ?? {}),
114
- contentType: options.contentType ?? null
115
- });
116
- return { ...stored, url: artifactUrl };
117
- },
118
- getPublicUrl(key) {
119
- return input.storage.getPublicUrl(`${prefix}/${key}`);
120
- },
121
- resolveKey(key) {
122
- return `${prefix}/${key}`;
123
- }
124
- },
125
- billing: {
126
- async record(record) {
127
- await recordBillingNonFatal({
128
- customerId: input.customer.id,
129
- jobId: input.job.id,
130
- tracer: input.job.tracer,
131
- templateId: input.primitive.id,
132
- type: record.type,
133
- costUsd: record.costUsd,
134
- chargeUsd: record.chargeUsd ?? Number((record.costUsd * 1.2).toFixed(4)),
135
- costCenterSlug: record.costCenterSlug,
136
- idempotencyKey: record.idempotencyKey,
137
- occurredAtMs: record.occurredAtMs,
138
- metadata: record.metadata
139
- });
140
- }
141
- },
142
- providers: {
143
- listAvailableProviders() {
144
- return input.providers.listAvailableProviders(input.customer.id);
145
- },
146
- async generateText(request) {
147
- return input.providers.generateText({
148
- customerId: input.customer.id,
149
- jobId: input.job.id,
150
- workerId: input.workerId,
151
- ...request
152
- });
153
- },
154
- async generateImage(request) {
155
- return input.providers.generateImage({
156
- customerId: input.customer.id,
157
- jobId: input.job.id,
158
- workerId: input.workerId,
159
- ...request
160
- });
161
- },
162
- async editImage(request) {
163
- return input.providers.editImage({
164
- customerId: input.customer.id,
165
- jobId: input.job.id,
166
- workerId: input.workerId,
167
- ...request
168
- });
169
- },
170
- async inpaintImage(request) {
171
- return input.providers.inpaintImage({
172
- customerId: input.customer.id,
173
- jobId: input.job.id,
174
- workerId: input.workerId,
175
- ...request
176
- });
177
- },
178
- async generateVideo(request) {
179
- return input.providers.generateVideo({
180
- customerId: input.customer.id,
181
- jobId: input.job.id,
182
- workerId: input.workerId,
183
- ...request
184
- });
185
- },
186
- async generateSpeech(request) {
187
- return input.providers.generateSpeech({
188
- customerId: input.customer.id,
189
- jobId: input.job.id,
190
- workerId: input.workerId,
191
- ...request
192
- });
193
- },
194
- async transcribeSpeech(request) {
195
- return input.providers.transcribeSpeech({
196
- customerId: input.customer.id,
197
- jobId: input.job.id,
198
- workerId: input.workerId,
199
- ...request
200
- });
201
- },
202
- async generateMusic(request) {
203
- return input.providers.generateMusic({
204
- customerId: input.customer.id,
205
- jobId: input.job.id,
206
- workerId: input.workerId,
207
- ...request
208
- });
209
- },
210
- async listElevenLabsVoices(request) {
211
- return input.providers.listElevenLabsVoices({
212
- customerId: input.customer.id,
213
- ...request
214
- });
215
- }
216
- },
217
- hyperframes: {
218
- async render(request) {
219
- const hyperframesOutputKey = `renders/vidfarm/primitives/${input.primitive.id}/${input.customer.id}/${input.job.id}/output.mp4`;
220
- // Re-entrant, non-blocking render: the first invocation dispatches the
221
- // render to its own Step Functions state machine and throws
222
- // RenderInProgressError so the job runner parks as `waiting_for_render`;
223
- // Step Functions waits + re-invokes, and a later invocation resumes the
224
- // SAME render (keyed by the deterministic execution name) and finalizes
225
- // once it terminates. No single Lambda holds the render open for its
226
- // 15-minute lifetime.
227
- const step = await input.hyperframes.renderStep({
228
- ...request,
229
- outputKey: hyperframesOutputKey,
230
- executionName: renderExecutionName(input.job.id)
231
- });
232
- if (step.state === "running") {
233
- throw new RenderInProgressError({
234
- executionArn: step.executionArn,
235
- renderId: step.renderId,
236
- waitSeconds: config.RENDER_POLL_WAIT_SECONDS,
237
- progressFraction: step.progressFraction
238
- });
239
- }
240
- if (step.state === "failed") {
241
- throw new Error(step.message);
242
- }
243
- const render = step;
244
- let outputUrl = render.outputUrl;
245
- let platformOutputKey = null;
246
- const localOutputLocation = typeof render.metadata.outputLocation === "string"
247
- ? render.metadata.outputLocation
248
- : null;
249
- if (render.outputS3Uri) {
250
- const output = await input.hyperframes.readRenderOutput(render.outputS3Uri);
251
- platformOutputKey = `${prefix}/${request.outputKey || "output.mp4"}`;
252
- const stored = await input.storage.putBuffer(platformOutputKey, output.bytes, output.contentType);
253
- outputUrl = buildArtifactUrl(stored.key, stored.url);
254
- await insertArtifact("video", stored.key, outputUrl, {
255
- operation: "hyperframes-render",
256
- contentType: output.contentType,
257
- renderId: render.renderId,
258
- outputS3Uri: render.outputS3Uri
259
- });
260
- }
261
- else if (localOutputLocation) {
262
- // In-process (local) render writes the MP4 to ephemeral local disk and
263
- // returns no S3 URI. On serverless boxes that disk is per-invocation
264
- // and the `renders/` prefix is not publicly served, so the raw
265
- // outputUrl 404s ("Artifact not found"). Persist the bytes into the
266
- // public job-scoped prefix — S3 on cloud, local disk on serve boxes —
267
- // exactly like the cloud branch above.
268
- const bytes = await readFile(localOutputLocation);
269
- platformOutputKey = `${prefix}/${request.outputKey || "output.mp4"}`;
270
- const stored = await input.storage.putBuffer(platformOutputKey, bytes, "video/mp4");
271
- outputUrl = buildArtifactUrl(stored.key, stored.url);
272
- await insertArtifact("video", stored.key, outputUrl, {
273
- operation: "hyperframes-render-local",
274
- contentType: "video/mp4",
275
- renderId: render.renderId,
276
- outputLocation: localOutputLocation
277
- });
278
- }
279
- const estimatedCostUsd = typeof render.metadata.estimatedCostUsd === "number" ? render.metadata.estimatedCostUsd : null;
280
- const chargeUsd = typeof render.metadata.chargeUsd === "number" ? render.metadata.chargeUsd : null;
281
- if (estimatedCostUsd !== null && estimatedCostUsd > 0) {
282
- await recordBillingNonFatal({
283
- customerId: input.customer.id,
284
- jobId: input.job.id,
285
- tracer: input.job.tracer,
286
- templateId: input.primitive.id,
287
- type: "render",
288
- costUsd: estimatedCostUsd,
289
- chargeUsd: typeof chargeUsd === "number" ? chargeUsd : undefined,
290
- costCenterSlug: "hyperframes_lambda",
291
- idempotencyKey: `hyperframes_lambda:${render.renderId}`,
292
- occurredAtMs: Date.now(),
293
- metadata: {
294
- ...render.metadata,
295
- render_id: render.renderId,
296
- output_url: outputUrl,
297
- signed_output_url: render.outputUrl,
298
- output_s3_uri: render.outputS3Uri,
299
- platform_output_key: platformOutputKey
300
- }
301
- });
302
- }
303
- return {
304
- renderId: render.renderId,
305
- outputUrl,
306
- outputS3Uri: render.outputS3Uri,
307
- metadata: {
308
- ...render.metadata,
309
- outputUrl,
310
- signedOutputUrl: render.outputUrl,
311
- platformOutputKey
312
- }
313
- };
314
- },
315
- async renderStill(request) {
316
- const extension = (request.imageFormat ?? "png") === "jpeg" ? "jpg" : (request.imageFormat ?? "png");
317
- const localOutputKey = `renders/vidfarm/primitives/${input.primitive.id}/${input.customer.id}/${input.job.id}/${request.outputKey || `output.${extension}`}`;
318
- const rendered = await input.hyperframes.renderStill({
319
- compositionHtml: request.compositionHtml,
320
- compositionId: request.compositionId,
321
- imageFormat: request.imageFormat,
322
- outputKey: localOutputKey
323
- });
324
- // renderStill writes to ephemeral local disk under the non-public
325
- // `renders/` prefix. Persist it into the public job-scoped prefix (S3 on
326
- // cloud, local disk on serve boxes) so the artifact URL resolves — same
327
- // fix as render() above.
328
- const platformKey = `${prefix}/${request.outputKey || `output.${extension}`}`;
329
- const contentType = extension === "jpg" ? "image/jpeg" : extension === "webp" ? "image/webp" : "image/png";
330
- const bytes = await readFile(rendered.outputLocation);
331
- const stored = await input.storage.putBuffer(platformKey, bytes, contentType);
332
- const outputUrl = buildArtifactUrl(stored.key, stored.url);
333
- await insertArtifact("image", stored.key, outputUrl, {
334
- operation: "hyperframes-render-still",
335
- renderId: rendered.renderId,
336
- imageFormat: request.imageFormat ?? "png"
337
- });
338
- return {
339
- renderId: rendered.renderId,
340
- outputUrl,
341
- metadata: rendered.metadata
342
- };
343
- }
344
- },
345
- media: {
346
- async normalizeVideo(request) {
347
- const normalized = await normalizeVideoAsset({
348
- sourceUrl: request.sourceUrl,
349
- maxWidth: request.maxWidth,
350
- maxHeight: request.maxHeight,
351
- crf: request.crf,
352
- preset: request.preset,
353
- maxVideoBitrateKbps: request.maxVideoBitrateKbps,
354
- audioBitrateKbps: request.audioBitrateKbps
355
- });
356
- const stored = await input.storage.putBuffer(`${prefix}/${request.outputKey}`, normalized.bytes, normalized.contentType);
357
- const artifactUrl = buildArtifactUrl(stored.key, stored.url);
358
- await insertArtifact("video", stored.key, artifactUrl, {
359
- ...(request.metadata ?? {}),
360
- operation: "normalize-video",
361
- contentType: normalized.contentType,
362
- normalization: normalized.metadata
363
- });
364
- await recordBillingNonFatal({
365
- customerId: input.customer.id,
366
- jobId: input.job.id,
367
- tracer: input.job.tracer,
368
- templateId: input.primitive.id,
369
- type: "cpu_estimate",
370
- costUsd: estimateNormalizationCostUsd(normalized.metadata),
371
- costCenterSlug: "video_normalization",
372
- idempotencyKey: `video_normalization:${input.job.id}:${request.outputKey}`,
373
- occurredAtMs: Date.now(),
374
- metadata: {
375
- ...(request.metadata ?? {}),
376
- operation: "normalize-video",
377
- source_url: request.sourceUrl,
378
- output_key: `${prefix}/${request.outputKey}`,
379
- normalization: normalized.metadata
380
- }
381
- });
382
- return {
383
- ...stored,
384
- url: artifactUrl,
385
- contentType: normalized.contentType,
386
- normalization: normalized.metadata
387
- };
388
- }
389
- }
390
- };
391
- async function insertArtifact(kind, storageKey, publicUrl, metadata) {
392
- await input.jobs.insertArtifact({
393
- id: createId("art"),
394
- jobId: input.job.id,
395
- customerId: input.customer.id,
396
- templateId: input.primitive.id,
397
- kind,
398
- storageKey,
399
- publicUrl,
400
- metadata
401
- });
402
- }
403
- }
404
- function buildPlatformMediaUrl(storageKey) {
405
- return `${config.PUBLIC_BASE_URL.replace(/\/$/, "")}/template-media?key=${encodeURIComponent(storageKey)}`;
406
- }
407
- /**
408
- * Deterministic Step Functions execution name for a job's render. Stable across
409
- * job-runner re-invocations so each poll resumes the same render execution
410
- * rather than starting a new one. Step Functions execution names allow
411
- * [A-Za-z0-9-_] and cap at 80 chars.
412
- */
413
- function renderExecutionName(jobId) {
414
- return `vfr-${jobId.replace(/[^A-Za-z0-9_-]/g, "-")}`.slice(0, 80);
415
- }
416
- //# sourceMappingURL=primitive-context.js.map