@mevdragon/vidfarm-devcli 0.20.6 → 0.20.9

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 (157) 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 +117 -0
  8. package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +245 -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 +308 -0
  13. package/SKILL.director.md +517 -250
  14. package/dist/src/cli.js +563 -99
  15. package/dist/src/devcli/clips.js +29 -12
  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 +14 -2
  20. package/dist/src/services/clip-curation/hunt.js +56 -0
  21. package/dist/src/services/clip-curation/index.js +1 -1
  22. package/dist/src/services/clip-curation/scan.js +5 -3
  23. package/package.json +30 -10
  24. package/SKILL.platform.md +0 -432
  25. package/demo/README.md +0 -28
  26. package/demo/dist/app.css +0 -1
  27. package/demo/dist/app.js +0 -1850
  28. package/demo/dist/chunks/chunk-DXB73IDG.js +0 -1
  29. package/demo/dist/chunks/chunk-S7OWAJDS.js +0 -36
  30. package/demo/dist/chunks/chunk-VTIBZ6AN.js +0 -1
  31. package/demo/dist/chunks/dist-ADSJKBVE.js +0 -332
  32. package/demo/dist/chunks/domEditingLayers-VZMLL4AP-SGHWPND4.js +0 -1
  33. package/demo/dist/chunks/hyperframes-player-XB65TCD6.js +0 -425
  34. package/demo/dist/chunks/lib-XAQ37YOE.js +0 -1
  35. package/demo/dist/chunks/src-TJ2QYA4U.js +0 -207
  36. package/demo/dist/favicon.ico +0 -0
  37. package/demo/dist/icons/timeline/audio.svg +0 -7
  38. package/demo/dist/icons/timeline/captions.svg +0 -5
  39. package/demo/dist/icons/timeline/composition.svg +0 -12
  40. package/demo/dist/icons/timeline/image.svg +0 -18
  41. package/demo/dist/icons/timeline/music.svg +0 -10
  42. package/demo/dist/icons/timeline/text.svg +0 -3
  43. package/demo/dist/index.html +0 -15
  44. package/dist/src/account-pages-legacy.js +0 -9396
  45. package/dist/src/account-pages.js +0 -61
  46. package/dist/src/app.js +0 -21603
  47. package/dist/src/composition-runtime.js +0 -1053
  48. package/dist/src/config.js +0 -217
  49. package/dist/src/context.js +0 -447
  50. package/dist/src/dev-app-legacy.js +0 -739
  51. package/dist/src/dev-app.js +0 -6
  52. package/dist/src/devcli/migrate-local.js +0 -140
  53. package/dist/src/devcli/sync.js +0 -368
  54. package/dist/src/domain.js +0 -5
  55. package/dist/src/editor-chat-history.js +0 -82
  56. package/dist/src/editor-chat.js +0 -828
  57. package/dist/src/editor-dark-theme.js +0 -1128
  58. package/dist/src/frontend/debug.js +0 -71
  59. package/dist/src/frontend/discover-client.js +0 -130
  60. package/dist/src/frontend/discover-store.js +0 -23
  61. package/dist/src/frontend/file-directory.js +0 -1018
  62. package/dist/src/frontend/flockposter-cache-store.js +0 -124
  63. package/dist/src/frontend/homepage-client.js +0 -446
  64. package/dist/src/frontend/homepage-shared.js +0 -201
  65. package/dist/src/frontend/homepage-store.js +0 -66
  66. package/dist/src/frontend/homepage-view.js +0 -705
  67. package/dist/src/frontend/page-runtime-client.js +0 -132
  68. package/dist/src/frontend/page-runtime-store.js +0 -9
  69. package/dist/src/frontend/sentry.js +0 -42
  70. package/dist/src/frontend/template-editor-chat.js +0 -4181
  71. package/dist/src/help-page.js +0 -346
  72. package/dist/src/homepage.js +0 -1458
  73. package/dist/src/index.js +0 -16
  74. package/dist/src/instrument.js +0 -30
  75. package/dist/src/landing-page.js +0 -384
  76. package/dist/src/page-runtime.js +0 -2
  77. package/dist/src/page-shell.js +0 -1452
  78. package/dist/src/primitive-context.js +0 -416
  79. package/dist/src/primitive-registry.js +0 -3940
  80. package/dist/src/primitive-sdk.js +0 -4
  81. package/dist/src/primitives/hyperframes-media.js +0 -108
  82. package/dist/src/react-page-shell.js +0 -35
  83. package/dist/src/ready-post-schedule-component.js +0 -1540
  84. package/dist/src/registry.js +0 -296
  85. package/dist/src/reskin/agency-page.js +0 -299
  86. package/dist/src/reskin/calendar-page.js +0 -568
  87. package/dist/src/reskin/chat-page.js +0 -942
  88. package/dist/src/reskin/discover-page.js +0 -1788
  89. package/dist/src/reskin/document.js +0 -1587
  90. package/dist/src/reskin/help-page.js +0 -357
  91. package/dist/src/reskin/index-page.js +0 -62
  92. package/dist/src/reskin/inpaint-clipper-page.js +0 -890
  93. package/dist/src/reskin/inpaint-page.js +0 -2554
  94. package/dist/src/reskin/inpaint-video-page.js +0 -1339
  95. package/dist/src/reskin/job-runs-page.js +0 -477
  96. package/dist/src/reskin/library-page.js +0 -1634
  97. package/dist/src/reskin/login-page.js +0 -262
  98. package/dist/src/reskin/portfolio-page.js +0 -687
  99. package/dist/src/reskin/pricing-page.js +0 -390
  100. package/dist/src/reskin/settings-page.js +0 -732
  101. package/dist/src/reskin/theme.js +0 -711
  102. package/dist/src/runtime.js +0 -35
  103. package/dist/src/services/api-call-history.js +0 -249
  104. package/dist/src/services/auth.js +0 -152
  105. package/dist/src/services/billing-pricing.js +0 -39
  106. package/dist/src/services/billing.js +0 -241
  107. package/dist/src/services/cast.js +0 -127
  108. package/dist/src/services/chat-threads.js +0 -92
  109. package/dist/src/services/clip-records.js +0 -250
  110. package/dist/src/services/clip-search.js +0 -77
  111. package/dist/src/services/clip-vectors.js +0 -125
  112. package/dist/src/services/composition-sanitize.js +0 -124
  113. package/dist/src/services/composition-watch.js +0 -79
  114. package/dist/src/services/elevenlabs.js +0 -222
  115. package/dist/src/services/file-directory.js +0 -117
  116. package/dist/src/services/fork-access.js +0 -93
  117. package/dist/src/services/fork-manifest.js +0 -42
  118. package/dist/src/services/ghostcut.js +0 -179
  119. package/dist/src/services/hyperframes.js +0 -3654
  120. package/dist/src/services/job-capacity.js +0 -14
  121. package/dist/src/services/job-logs.js +0 -197
  122. package/dist/src/services/jobs.js +0 -136
  123. package/dist/src/services/local-dynamo.js +0 -0
  124. package/dist/src/services/media-processing.js +0 -766
  125. package/dist/src/services/primitive-media-lambda.js +0 -280
  126. package/dist/src/services/providers.js +0 -2748
  127. package/dist/src/services/rate-limits.js +0 -262
  128. package/dist/src/services/scene-annotations.js +0 -32
  129. package/dist/src/services/serverless-auth.js +0 -382
  130. package/dist/src/services/serverless-jobs.js +0 -1084
  131. package/dist/src/services/serverless-provider-keys.js +0 -409
  132. package/dist/src/services/serverless-records.js +0 -1515
  133. package/dist/src/services/serverless-template-configs.js +0 -75
  134. package/dist/src/services/storage.js +0 -461
  135. package/dist/src/services/swipe-customize.js +0 -437
  136. package/dist/src/services/template-certification.js +0 -413
  137. package/dist/src/services/template-loader.js +0 -99
  138. package/dist/src/services/template-runtime-bundles.js +0 -217
  139. package/dist/src/services/template-sources.js +0 -1017
  140. package/dist/src/services/upstream.js +0 -248
  141. package/dist/src/services/video-normalization.js +0 -2
  142. package/dist/src/services/webhooks.js +0 -62
  143. package/dist/src/template-editor-pages.js +0 -2576
  144. package/dist/src/template-editor-shell.js +0 -2893
  145. package/dist/src/template-sdk.js +0 -4
  146. package/dist/src/worker.js +0 -17
  147. package/public/assets/discover-client-app.js +0 -1
  148. package/public/assets/file-directory-app.js +0 -3
  149. package/public/assets/homepage-app.js +0 -54
  150. package/public/assets/homepage-client-app.js +0 -80
  151. package/public/assets/page-runtime-client-app.js +0 -94
  152. package/public/assets/placeholders/scene-placeholder.png +0 -0
  153. package/src/assets/SELLING_AWARENESS_STAGES.md +0 -579
  154. package/src/assets/SELLING_WITH_HOOKS.md +0 -377
  155. package/src/assets/SELLING_WITH_VSLS.md +0 -606
  156. package/src/assets/favicon.ico +0 -0
  157. 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