@mevdragon/vidfarm-devcli 0.2.6 → 0.2.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.
- package/GETTING_STARTED.developers.md +25 -0
- package/README.md +44 -3
- package/SKILL.developer.md +147 -11
- package/dist/src/account-pages.js +1 -1
- package/dist/src/app.js +380 -13
- package/dist/src/cli.js +246 -59
- package/dist/src/config.js +4 -5
- package/dist/src/context.js +16 -0
- package/dist/src/db.js +67 -13
- package/dist/src/homepage.js +33 -1
- package/dist/src/lib/template-paths.js +10 -4
- package/dist/src/registry.js +9 -2
- package/dist/src/services/auth.js +2 -6
- package/dist/src/services/job-logs.js +4 -4
- package/dist/src/services/providers.js +470 -0
- package/dist/src/services/storage.js +13 -0
- package/dist/src/services/template-certification.js +16 -2
- package/dist/src/services/template-loader.js +17 -1
- package/dist/src/services/template-sources.js +338 -17
- package/{templates/template_0000 → dist/templates/vidfarm_template_0000}/src/remotion/Root.js +1 -0
- package/dist/templates/{template_0000 → vidfarm_template_0000}/src/template.js +9 -3
- package/package.json +4 -3
- package/templates/{template_0000 → vidfarm_template_0000}/README.md +23 -0
- package/templates/{template_0000 → vidfarm_template_0000}/package.json +0 -1
- package/templates/{template_0000 → vidfarm_template_0000}/src/sdk.ts +18 -0
- package/templates/{template_0000 → vidfarm_template_0000}/src/template.js +9 -3
- package/templates/{template_0000 → vidfarm_template_0000}/src/template.ts +10 -3
- package/templates/vidfarm_template_0000/tmp/solobacterium-moorei-slideshow.request.json +31 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/sdk.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/style-options.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/SKILL.md +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Abel-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/DMSerifDisplay-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Montserrat[wght].ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/SourceCodePro[wght].ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/TikTokSans-SemiBold.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Yesteryear-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/composition.json +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/research/preview/.gitkeep +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/research/source_notes.md +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.ts +0 -0
- /package/{dist/templates/template_0000 → templates/vidfarm_template_0000}/src/remotion/Root.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/Root.tsx +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.tsx +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/sdk.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/style-options.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/style-options.ts +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.ts +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/template.config.json +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/tsconfig.json +0 -0
package/dist/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { execFile } from "node:child_process";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { parseArgs } from "node:util";
|
|
@@ -37,6 +37,18 @@ async function main() {
|
|
|
37
37
|
await runImportSourceProdCommand(process.argv.slice(3));
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
+
if (command === "register-source-hosted") {
|
|
41
|
+
await runRegisterSourceHostedCommand(process.argv.slice(3));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (command === "publish-update-hosted") {
|
|
45
|
+
await runPublishUpdateHostedCommand(process.argv.slice(3));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (command === "register-source-prod") {
|
|
49
|
+
await runRegisterSourceProdCommand(process.argv.slice(3));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
40
52
|
if (command === "deploy-template-cycle") {
|
|
41
53
|
await runDeployTemplateCycleCommand(process.argv.slice(3));
|
|
42
54
|
return;
|
|
@@ -249,14 +261,17 @@ async function runImportSourceCommand(argv) {
|
|
|
249
261
|
sourceId: registration.source.id,
|
|
250
262
|
commitSha: parsed.values["commit-sha"] ?? null
|
|
251
263
|
});
|
|
264
|
+
let sourceRecord = registration.source;
|
|
252
265
|
let activated = null;
|
|
253
266
|
if (parsed.values.activate) {
|
|
267
|
+
sourceRecord = sources.approveSource({ sourceId: registration.source.id });
|
|
268
|
+
sources.approveRelease({ releaseId: release.id });
|
|
254
269
|
const result = await sources.activateRelease({ releaseId: release.id });
|
|
255
270
|
templateRegistry.registerRuntimeTemplate(result.template);
|
|
256
271
|
activated = result.release;
|
|
257
272
|
}
|
|
258
273
|
console.log(JSON.stringify({
|
|
259
|
-
source:
|
|
274
|
+
source: sourceRecord,
|
|
260
275
|
registration_action: registration.action,
|
|
261
276
|
sync: registration.sync,
|
|
262
277
|
release,
|
|
@@ -357,20 +372,121 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
357
372
|
site_name: siteName,
|
|
358
373
|
research: stagedInputs,
|
|
359
374
|
template_dna_module: moduleSync,
|
|
360
|
-
dna_analysis_runs: dnaRuns
|
|
375
|
+
dna_analysis_runs: dnaRuns,
|
|
376
|
+
required_template_contract: {
|
|
377
|
+
template_fields: [
|
|
378
|
+
"id",
|
|
379
|
+
"slugId",
|
|
380
|
+
"version",
|
|
381
|
+
"about.title",
|
|
382
|
+
"about.description",
|
|
383
|
+
"about.viral_dna",
|
|
384
|
+
"about.visual_dna",
|
|
385
|
+
"about.preview_media",
|
|
386
|
+
"about.link_to_original",
|
|
387
|
+
"about.proposal_generator",
|
|
388
|
+
"about.sample_prompts",
|
|
389
|
+
"configSchema",
|
|
390
|
+
],
|
|
391
|
+
operation_fields: [
|
|
392
|
+
"operations.<name>.workflow",
|
|
393
|
+
"operations.<name>.smokeTestPayload",
|
|
394
|
+
"jobs.<workflow>",
|
|
395
|
+
],
|
|
396
|
+
files: [
|
|
397
|
+
"src/template.ts",
|
|
398
|
+
"SKILL.md",
|
|
399
|
+
],
|
|
400
|
+
},
|
|
401
|
+
next_steps: [
|
|
402
|
+
"Review src/template.ts and replace the starter proposal_generator with template-specific proposal instructions.",
|
|
403
|
+
"Review src/template.ts and replace the starter sample_prompts with prompts that fit the new format.",
|
|
404
|
+
"If DNA analysis was skipped or the source research changed, run analyze-viral-dna and analyze-visual-dna.",
|
|
405
|
+
"Update SKILL.md so the usage examples match the template's real operations and payloads.",
|
|
406
|
+
`Run validate-template against ${slugId} and launch at least one real local job before treating the template as ready.`,
|
|
407
|
+
],
|
|
408
|
+
}, null, 2));
|
|
409
|
+
}
|
|
410
|
+
async function runRegisterSourceProdCommand(argv) {
|
|
411
|
+
const input = parseProdTemplateCommandArgs(argv, {
|
|
412
|
+
envFile: ".env.production",
|
|
413
|
+
baseUrl: "https://vidfarm.cloud.zoomgtm.com",
|
|
414
|
+
activate: false
|
|
415
|
+
});
|
|
416
|
+
const registration = await registerSourceViaApi(input);
|
|
417
|
+
console.log(JSON.stringify({
|
|
418
|
+
mode: "prod-register-source",
|
|
419
|
+
base_url: input.baseUrl,
|
|
420
|
+
source: registration.source,
|
|
421
|
+
registration_action: registration.registration_action,
|
|
422
|
+
sync: registration.sync ?? null
|
|
423
|
+
}, null, 2));
|
|
424
|
+
}
|
|
425
|
+
async function runRegisterSourceHostedCommand(argv) {
|
|
426
|
+
const input = parseProdTemplateCommandArgs(argv, {
|
|
427
|
+
envFile: ".env",
|
|
428
|
+
baseUrl: process.env.VIDFARM_BASE_URL ?? "https://vidfarm.cloud.zoomgtm.com",
|
|
429
|
+
activate: false
|
|
430
|
+
});
|
|
431
|
+
const registration = await registerSourceViaApi(input);
|
|
432
|
+
console.log(JSON.stringify({
|
|
433
|
+
mode: "hosted-register-source",
|
|
434
|
+
base_url: input.baseUrl,
|
|
435
|
+
source: registration.source,
|
|
436
|
+
registration_action: registration.registration_action,
|
|
437
|
+
sync: registration.sync ?? null,
|
|
438
|
+
next_step: "Platform admin reviews the source, imports a release, approves it, and activates it."
|
|
439
|
+
}, null, 2));
|
|
440
|
+
}
|
|
441
|
+
async function runPublishUpdateHostedCommand(argv) {
|
|
442
|
+
const input = parseProdTemplateCommandArgs(argv, {
|
|
443
|
+
envFile: ".env",
|
|
444
|
+
baseUrl: process.env.VIDFARM_BASE_URL ?? "https://vidfarm.cloud.zoomgtm.com",
|
|
445
|
+
activate: false
|
|
446
|
+
});
|
|
447
|
+
if (!input.commitSha) {
|
|
448
|
+
throw new Error("publish-update-hosted requires --commit-sha.");
|
|
449
|
+
}
|
|
450
|
+
const registration = await registerSourceViaApi(input);
|
|
451
|
+
const artifact = await packageTemplateArtifact(input.repoDir, input.commitSha);
|
|
452
|
+
const presign = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/artifacts/presign`, {
|
|
453
|
+
method: "POST",
|
|
454
|
+
body: JSON.stringify({
|
|
455
|
+
commit_sha: input.commitSha
|
|
456
|
+
})
|
|
457
|
+
});
|
|
458
|
+
await uploadArtifactArchive(presign, artifact.buffer);
|
|
459
|
+
const payload = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/publish`, {
|
|
460
|
+
method: "POST",
|
|
461
|
+
body: JSON.stringify({
|
|
462
|
+
commit_sha: input.commitSha,
|
|
463
|
+
artifact_sha256: artifact.sha256
|
|
464
|
+
})
|
|
465
|
+
});
|
|
466
|
+
console.log(JSON.stringify({
|
|
467
|
+
mode: "hosted-publish-update",
|
|
468
|
+
base_url: input.baseUrl,
|
|
469
|
+
source: payload.source,
|
|
470
|
+
release: payload.release,
|
|
471
|
+
artifact: {
|
|
472
|
+
artifact_key: presign.artifact_key,
|
|
473
|
+
artifact_manifest_key: presign.artifact_manifest_key,
|
|
474
|
+
sha256: artifact.sha256
|
|
475
|
+
},
|
|
476
|
+
publish_action: payload.publish_action,
|
|
477
|
+
developer_handoff: payload.developer_handoff ?? null
|
|
361
478
|
}, null, 2));
|
|
362
479
|
}
|
|
363
480
|
async function runImportSourceProdCommand(argv) {
|
|
364
481
|
const input = parseProdTemplateCommandArgs(argv, {
|
|
365
482
|
envFile: ".env.production",
|
|
366
|
-
|
|
483
|
+
baseUrl: "https://vidfarm.cloud.zoomgtm.com",
|
|
367
484
|
activate: true
|
|
368
485
|
});
|
|
369
486
|
const result = await importSourceIntoProd(input);
|
|
370
487
|
console.log(JSON.stringify({
|
|
371
488
|
mode: "prod-import-source",
|
|
372
|
-
|
|
373
|
-
instance_id: result.instanceId,
|
|
489
|
+
base_url: input.baseUrl,
|
|
374
490
|
source: result.payload.source,
|
|
375
491
|
release: result.payload.release,
|
|
376
492
|
activated_release: result.payload.activated_release ?? null
|
|
@@ -379,9 +495,13 @@ async function runImportSourceProdCommand(argv) {
|
|
|
379
495
|
async function runDeployTemplateCycleCommand(argv) {
|
|
380
496
|
const input = parseProdTemplateCommandArgs(argv, {
|
|
381
497
|
envFile: ".env.production",
|
|
498
|
+
baseUrl: "https://vidfarm.cloud.zoomgtm.com",
|
|
382
499
|
stackName: "VidfarmProdStack",
|
|
383
500
|
activate: true
|
|
384
501
|
});
|
|
502
|
+
if (!input.stackName) {
|
|
503
|
+
throw new Error("deploy-template-cycle requires --stack-name.");
|
|
504
|
+
}
|
|
385
505
|
const importResult = await importSourceIntoProd(input);
|
|
386
506
|
const currentImage = await getProdCurrentImage({
|
|
387
507
|
stackName: input.stackName,
|
|
@@ -399,7 +519,6 @@ async function runDeployTemplateCycleCommand(argv) {
|
|
|
399
519
|
console.log(JSON.stringify({
|
|
400
520
|
mode: "deploy-template-cycle",
|
|
401
521
|
stack_name: input.stackName,
|
|
402
|
-
instance_id: importResult.instanceId,
|
|
403
522
|
release: importResult.payload.activated_release ?? importResult.payload.release,
|
|
404
523
|
restart_image: currentImage.image
|
|
405
524
|
}, null, 2));
|
|
@@ -442,7 +561,37 @@ async function runCopyReferenceTemplateCommand(argv) {
|
|
|
442
561
|
template_dir: destinationDir,
|
|
443
562
|
template_id: "4c7a7e1a-7f35-4f30-9f86-9c8a63c7f2db",
|
|
444
563
|
slug_id: "template_0000",
|
|
445
|
-
rewritten: false
|
|
564
|
+
rewritten: false,
|
|
565
|
+
required_template_contract: {
|
|
566
|
+
template_fields: [
|
|
567
|
+
"id",
|
|
568
|
+
"slugId",
|
|
569
|
+
"version",
|
|
570
|
+
"about.title",
|
|
571
|
+
"about.description",
|
|
572
|
+
"about.viral_dna",
|
|
573
|
+
"about.visual_dna",
|
|
574
|
+
"about.preview_media",
|
|
575
|
+
"about.link_to_original",
|
|
576
|
+
"about.proposal_generator",
|
|
577
|
+
"about.sample_prompts",
|
|
578
|
+
"configSchema",
|
|
579
|
+
],
|
|
580
|
+
operation_fields: [
|
|
581
|
+
"operations.<name>.workflow",
|
|
582
|
+
"operations.<name>.smokeTestPayload",
|
|
583
|
+
"jobs.<workflow>",
|
|
584
|
+
],
|
|
585
|
+
files: [
|
|
586
|
+
"src/template.ts",
|
|
587
|
+
"SKILL.md",
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
next_steps: [
|
|
591
|
+
"Treat src/template.ts as the canonical entrypoint and review the required about metadata before copying patterns into a new template.",
|
|
592
|
+
"Use the starter proposal_generator and sample_prompts as placeholders only; rewrite them for the real format you are building.",
|
|
593
|
+
"Keep the template-local SKILL.md aligned with the operations and payloads in code.",
|
|
594
|
+
],
|
|
446
595
|
}, null, 2));
|
|
447
596
|
}
|
|
448
597
|
async function runAnalyzeTemplateDnaCommand(mode, argv) {
|
|
@@ -569,7 +718,7 @@ async function runSessionCommand(argv) {
|
|
|
569
718
|
starter_style_options: {
|
|
570
719
|
fonts: STARTER_TEMPLATE_FONT_OPTIONS,
|
|
571
720
|
text_background_colors: STARTER_TEMPLATE_TEXT_BACKGROUND_COLOR_OPTIONS,
|
|
572
|
-
starter_template_file: "templates/
|
|
721
|
+
starter_template_file: "templates/vidfarm_template_0000/src/style-options.ts"
|
|
573
722
|
},
|
|
574
723
|
headers: {
|
|
575
724
|
"vidfarm-api-key": session.apiKey,
|
|
@@ -656,8 +805,8 @@ function toProjectName(folderName) {
|
|
|
656
805
|
}
|
|
657
806
|
function resolveStarterTemplateDir() {
|
|
658
807
|
const candidates = [
|
|
659
|
-
path.resolve(import.meta.dirname, "..", "templates", "
|
|
660
|
-
path.resolve(import.meta.dirname, "..", "..", "templates", "
|
|
808
|
+
path.resolve(import.meta.dirname, "..", "templates", "vidfarm_template_0000"),
|
|
809
|
+
path.resolve(import.meta.dirname, "..", "..", "templates", "vidfarm_template_0000")
|
|
661
810
|
];
|
|
662
811
|
for (const candidate of candidates) {
|
|
663
812
|
if (existsSync(candidate)) {
|
|
@@ -679,7 +828,10 @@ function parseProdTemplateCommandArgs(argv, defaults) {
|
|
|
679
828
|
"install-command": { type: "string", default: "npm install" },
|
|
680
829
|
"build-command": { type: "string", default: "npm run build" },
|
|
681
830
|
"commit-sha": { type: "string" },
|
|
831
|
+
"repo-dir": { type: "string", default: "." },
|
|
682
832
|
"env-file": { type: "string", default: defaults.envFile },
|
|
833
|
+
"base-url": { type: "string", default: defaults.baseUrl },
|
|
834
|
+
"api-key": { type: "string" },
|
|
683
835
|
"stack-name": { type: "string", default: defaults.stackName }
|
|
684
836
|
}
|
|
685
837
|
});
|
|
@@ -691,6 +843,11 @@ function parseProdTemplateCommandArgs(argv, defaults) {
|
|
|
691
843
|
throw new Error("Command requires --template-id, --slug-id, --repo-url, and --template-module-path.");
|
|
692
844
|
}
|
|
693
845
|
deriveTemplateRootDirFromModulePath(templateModulePath);
|
|
846
|
+
loadEnvFile(parsed.values["env-file"]);
|
|
847
|
+
const apiKey = parsed.values["api-key"] ?? process.env.VIDFARM_API_KEY;
|
|
848
|
+
if (!apiKey) {
|
|
849
|
+
throw new Error("Missing Vidfarm API key. Pass --api-key or set VIDFARM_API_KEY in the selected env file.");
|
|
850
|
+
}
|
|
694
851
|
return {
|
|
695
852
|
templateId,
|
|
696
853
|
slugId,
|
|
@@ -701,57 +858,93 @@ function parseProdTemplateCommandArgs(argv, defaults) {
|
|
|
701
858
|
installCommand: parsed.values["install-command"],
|
|
702
859
|
buildCommand: parsed.values["build-command"],
|
|
703
860
|
commitSha: parsed.values["commit-sha"] ?? undefined,
|
|
861
|
+
repoDir: path.resolve(process.cwd(), parsed.values["repo-dir"]),
|
|
704
862
|
envFile: parsed.values["env-file"],
|
|
705
|
-
|
|
863
|
+
baseUrl: normalizeBaseUrl(parsed.values["base-url"]),
|
|
864
|
+
apiKey,
|
|
865
|
+
stackName: parsed.values["stack-name"] || undefined,
|
|
706
866
|
activate: defaults.activate
|
|
707
867
|
};
|
|
708
868
|
}
|
|
709
869
|
async function importSourceIntoProd(input) {
|
|
710
|
-
|
|
711
|
-
const
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const stdout = await runSsmScript({
|
|
718
|
-
instanceId,
|
|
719
|
-
comment: `Vidfarm import ${input.slugId}`,
|
|
720
|
-
script: hostScript
|
|
870
|
+
const registration = await registerSourceViaApi(input);
|
|
871
|
+
const source = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/approve`, { method: "POST" });
|
|
872
|
+
const releaseResponse = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/import`, {
|
|
873
|
+
method: "POST",
|
|
874
|
+
body: JSON.stringify({
|
|
875
|
+
commit_sha: input.commitSha ?? undefined
|
|
876
|
+
})
|
|
721
877
|
});
|
|
878
|
+
const approvedRelease = await postProdTemplateApi(input, `/api/v1/templates/releases/${releaseResponse.release.id}/approve`, { method: "POST" });
|
|
879
|
+
const activatedRelease = input.activate
|
|
880
|
+
? await postProdTemplateApi(input, `/api/v1/templates/releases/${releaseResponse.release.id}/activate`, { method: "POST" })
|
|
881
|
+
: null;
|
|
722
882
|
return {
|
|
723
|
-
|
|
724
|
-
|
|
883
|
+
payload: {
|
|
884
|
+
source: source.source,
|
|
885
|
+
release: approvedRelease.release,
|
|
886
|
+
activated_release: activatedRelease?.release ?? null
|
|
887
|
+
}
|
|
725
888
|
};
|
|
726
889
|
}
|
|
727
|
-
function
|
|
728
|
-
|
|
729
|
-
"
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
890
|
+
async function registerSourceViaApi(input) {
|
|
891
|
+
return postProdTemplateApi(input, "/api/v1/templates/sources", {
|
|
892
|
+
method: "POST",
|
|
893
|
+
body: JSON.stringify({
|
|
894
|
+
template_id: input.templateId,
|
|
895
|
+
slug_id: input.slugId,
|
|
896
|
+
repo_url: input.repoUrl,
|
|
897
|
+
branch: input.branch,
|
|
898
|
+
template_module_path: input.templateModulePath,
|
|
899
|
+
skill_path: input.skillPath,
|
|
900
|
+
install_command: input.installCommand,
|
|
901
|
+
build_command: input.buildCommand
|
|
902
|
+
})
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
async function postProdTemplateApi(input, pathname, init) {
|
|
906
|
+
const response = await fetch(`${input.baseUrl}${pathname}`, {
|
|
907
|
+
...init,
|
|
908
|
+
headers: {
|
|
909
|
+
"content-type": "application/json",
|
|
910
|
+
"vidfarm-api-key": input.apiKey,
|
|
911
|
+
...(init.headers ?? {})
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
const payload = await response.json().catch(() => ({}));
|
|
915
|
+
if (!response.ok) {
|
|
916
|
+
throw new Error(typeof payload.error === "string" ? payload.error : `Request failed with ${response.status}.`);
|
|
917
|
+
}
|
|
918
|
+
return payload;
|
|
919
|
+
}
|
|
920
|
+
async function packageTemplateArtifact(repoDir, commitSha) {
|
|
921
|
+
const tempDir = mkdtempSync(path.join(os.tmpdir(), "vidfarm-template-artifact-"));
|
|
922
|
+
const repoRoot = (await execFileAsync("git", ["-C", repoDir, "rev-parse", "--show-toplevel"])).stdout.trim();
|
|
923
|
+
const artifactPath = path.join(tempDir, "template-source.tar.gz");
|
|
924
|
+
try {
|
|
925
|
+
await execFileAsync("git", ["-C", repoRoot, "archive", "--format=tar.gz", `--output=${artifactPath}`, commitSha], {
|
|
926
|
+
cwd: repoRoot
|
|
927
|
+
});
|
|
928
|
+
const buffer = readFileSync(artifactPath);
|
|
929
|
+
return {
|
|
930
|
+
buffer,
|
|
931
|
+
sha256: createHash("sha256").update(buffer).digest("hex")
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
finally {
|
|
935
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
async function uploadArtifactArchive(presign, buffer) {
|
|
939
|
+
const response = await fetch(presign.upload.url, {
|
|
940
|
+
method: presign.upload.method,
|
|
941
|
+
headers: presign.upload.headers,
|
|
942
|
+
body: new Uint8Array(buffer)
|
|
943
|
+
});
|
|
944
|
+
if (!response.ok) {
|
|
945
|
+
const body = await response.text().catch(() => "");
|
|
946
|
+
throw new Error(body || `Artifact upload failed with ${response.status}.`);
|
|
947
|
+
}
|
|
755
948
|
}
|
|
756
949
|
function loadEnvFile(envFile) {
|
|
757
950
|
const resolved = path.resolve(process.cwd(), envFile);
|
|
@@ -823,12 +1016,6 @@ function inferUploadContentType(fileName) {
|
|
|
823
1016
|
return "application/octet-stream";
|
|
824
1017
|
}
|
|
825
1018
|
}
|
|
826
|
-
function resolveGithubToken() {
|
|
827
|
-
return process.env.VIDFARM_GITHUB_TOKEN
|
|
828
|
-
?? process.env.GITHUB_TOKEN
|
|
829
|
-
?? process.env.GH_TOKEN
|
|
830
|
-
?? "";
|
|
831
|
-
}
|
|
832
1019
|
async function resolveStackOutput(stackName, outputKey) {
|
|
833
1020
|
const { stdout } = await runLocalCommand("aws", [
|
|
834
1021
|
"cloudformation",
|
package/dist/src/config.js
CHANGED
|
@@ -32,6 +32,7 @@ const schema = z.object({
|
|
|
32
32
|
GEMINI_API_KEY: z.string().optional(),
|
|
33
33
|
PERPLEXITY_API_KEY: z.string().optional(),
|
|
34
34
|
SUPERAGENCY_KEY: z.string().optional(),
|
|
35
|
+
ARTIFACT_SIGNING_SECRET: z.string().optional(),
|
|
35
36
|
REMOTION_REGION: z.string().default("us-east-1"),
|
|
36
37
|
REMOTION_BUCKET_NAME: z.string().optional(),
|
|
37
38
|
REMOTION_SITE_NAME: z.string().optional(),
|
|
@@ -43,7 +44,8 @@ const schema = z.object({
|
|
|
43
44
|
REMOTION_MODE: z.enum(["auto", "mock", "local", "lambda"]).default("auto"),
|
|
44
45
|
MOCK_PROVIDER_RESPONSES: z.string().optional(),
|
|
45
46
|
VIDFARM_ADMIN_EMAILS: z.string().default(""),
|
|
46
|
-
|
|
47
|
+
VIDFARM_GITHUB_TOKEN: z.string().optional(),
|
|
48
|
+
GITHUB_TOKEN: z.string().optional(),
|
|
47
49
|
TEMPLATE_SOURCE_ROOT: z.string().default("./data/template-sources")
|
|
48
50
|
});
|
|
49
51
|
const parsed = schema.parse(process.env);
|
|
@@ -58,6 +60,7 @@ export const config = {
|
|
|
58
60
|
VIDFARM_DATA_DIR: dataDir,
|
|
59
61
|
TEMPLATE_SOURCE_ROOT: templateSourceRoot,
|
|
60
62
|
PUBLIC_BASE_URL: publicBaseUrl,
|
|
63
|
+
ARTIFACT_SIGNING_SECRET: parsed.ARTIFACT_SIGNING_SECRET || parsed.SUPERAGENCY_KEY || "",
|
|
61
64
|
isProduction: parsed.NODE_ENV === "production",
|
|
62
65
|
mockProviders: parsed.MOCK_PROVIDER_RESPONSES === "true" ||
|
|
63
66
|
(parsed.MOCK_PROVIDER_RESPONSES == null && parsed.NODE_ENV !== "production"),
|
|
@@ -66,8 +69,4 @@ export const config = {
|
|
|
66
69
|
.split(",")
|
|
67
70
|
.map((value) => value.trim().toLowerCase())
|
|
68
71
|
.filter(Boolean),
|
|
69
|
-
developerEmails: parsed.VIDFARM_DEVELOPER_EMAILS
|
|
70
|
-
.split(",")
|
|
71
|
-
.map((value) => value.trim().toLowerCase())
|
|
72
|
-
.filter(Boolean)
|
|
73
72
|
};
|
package/dist/src/context.js
CHANGED
|
@@ -176,6 +176,14 @@ export function createTemplateJobContext(input) {
|
|
|
176
176
|
...request
|
|
177
177
|
});
|
|
178
178
|
},
|
|
179
|
+
async generateSpeech(request) {
|
|
180
|
+
return input.providers.generateSpeech({
|
|
181
|
+
customerId: input.customer.id,
|
|
182
|
+
jobId: input.job.id,
|
|
183
|
+
workerId: input.workerId,
|
|
184
|
+
...request
|
|
185
|
+
});
|
|
186
|
+
},
|
|
179
187
|
async generateImage(request) {
|
|
180
188
|
return input.providers.generateImage({
|
|
181
189
|
customerId: input.customer.id,
|
|
@@ -191,6 +199,14 @@ export function createTemplateJobContext(input) {
|
|
|
191
199
|
workerId: input.workerId,
|
|
192
200
|
...request
|
|
193
201
|
});
|
|
202
|
+
},
|
|
203
|
+
async transcribeSpeech(request) {
|
|
204
|
+
return input.providers.transcribeSpeech({
|
|
205
|
+
customerId: input.customer.id,
|
|
206
|
+
jobId: input.job.id,
|
|
207
|
+
workerId: input.workerId,
|
|
208
|
+
...request
|
|
209
|
+
});
|
|
194
210
|
}
|
|
195
211
|
},
|
|
196
212
|
remotion: {
|
package/dist/src/db.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Database from "better-sqlite3";
|
|
2
2
|
import { config } from "./config.js";
|
|
3
|
+
import { createId } from "./lib/ids.js";
|
|
3
4
|
import { parseJson, stringifyJson } from "./lib/json.js";
|
|
4
5
|
import { nowIso } from "./lib/time.js";
|
|
5
6
|
const db = new Database(config.VIDFARM_DB_PATH);
|
|
@@ -192,6 +193,8 @@ create table if not exists template_releases (
|
|
|
192
193
|
checkout_path text not null,
|
|
193
194
|
skill_path text not null,
|
|
194
195
|
module_path text not null,
|
|
196
|
+
artifact_manifest_key text,
|
|
197
|
+
artifact_key text,
|
|
195
198
|
status text not null,
|
|
196
199
|
certification_report_json text,
|
|
197
200
|
activated_at text,
|
|
@@ -235,6 +238,23 @@ db.exec(`
|
|
|
235
238
|
where slug_id is null or trim(slug_id) = '';
|
|
236
239
|
`);
|
|
237
240
|
db.exec(`create unique index if not exists idx_template_sources_slug_id on template_sources(slug_id);`);
|
|
241
|
+
db.exec(`
|
|
242
|
+
update template_sources
|
|
243
|
+
set status = 'approved'
|
|
244
|
+
where status = 'active';
|
|
245
|
+
`);
|
|
246
|
+
db.exec(`
|
|
247
|
+
update template_releases
|
|
248
|
+
set status = 'pending_approval'
|
|
249
|
+
where status = 'certified';
|
|
250
|
+
`);
|
|
251
|
+
const templateReleaseColumns = db.prepare(`pragma table_info(template_releases)`).all();
|
|
252
|
+
if (!templateReleaseColumns.some((column) => column.name === "artifact_manifest_key")) {
|
|
253
|
+
db.exec(`alter table template_releases add column artifact_manifest_key text;`);
|
|
254
|
+
}
|
|
255
|
+
if (!templateReleaseColumns.some((column) => column.name === "artifact_key")) {
|
|
256
|
+
db.exec(`alter table template_releases add column artifact_key text;`);
|
|
257
|
+
}
|
|
238
258
|
db.exec(`drop index if exists idx_job_events_job_time;`);
|
|
239
259
|
db.exec(`drop table if exists job_events;`);
|
|
240
260
|
function mapJob(row) {
|
|
@@ -288,6 +308,8 @@ function mapTemplateRelease(row) {
|
|
|
288
308
|
checkoutPath: String(row.checkout_path),
|
|
289
309
|
skillPath: String(row.skill_path),
|
|
290
310
|
modulePath: String(row.module_path),
|
|
311
|
+
artifactManifestKey: row.artifact_manifest_key ? String(row.artifact_manifest_key) : null,
|
|
312
|
+
artifactKey: row.artifact_key ? String(row.artifact_key) : null,
|
|
291
313
|
status: row.status,
|
|
292
314
|
certificationReport: parseJson(row.certification_report_json, null),
|
|
293
315
|
activatedAt: row.activated_at ? String(row.activated_at) : null,
|
|
@@ -390,6 +412,21 @@ export const database = {
|
|
|
390
412
|
where id = ?
|
|
391
413
|
`).run(isPaidPlan ? 1 : 0, nowIso(), customerId);
|
|
392
414
|
},
|
|
415
|
+
setCustomerAccessByEmail(input) {
|
|
416
|
+
const normalizedEmail = input.email.trim().toLowerCase();
|
|
417
|
+
const existing = this.getCustomerByEmail(normalizedEmail);
|
|
418
|
+
return this.upsertCustomer({
|
|
419
|
+
id: existing?.id ?? createId("cus"),
|
|
420
|
+
email: normalizedEmail,
|
|
421
|
+
name: input.name === undefined ? (existing?.name ?? null) : input.name,
|
|
422
|
+
defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
|
|
423
|
+
isDeveloper: input.isDeveloper === undefined ? (existing?.isDeveloper ?? false) : input.isDeveloper,
|
|
424
|
+
isPaidPlan: input.isPaidPlan === undefined ? (existing?.isPaidPlan ?? false) : input.isPaidPlan,
|
|
425
|
+
about: existing?.about ?? null,
|
|
426
|
+
groupchatUrl: existing?.groupchatUrl ?? null,
|
|
427
|
+
flockposterApiKey: existing?.flockposterApiKey ?? null
|
|
428
|
+
});
|
|
429
|
+
},
|
|
393
430
|
updateCustomerProfile(input) {
|
|
394
431
|
db.prepare(`
|
|
395
432
|
update customers
|
|
@@ -895,23 +932,28 @@ export const database = {
|
|
|
895
932
|
`).get(repoUrl, branch, templateModulePath);
|
|
896
933
|
return row ? mapTemplateSource(row) : null;
|
|
897
934
|
},
|
|
898
|
-
listTemplateSources() {
|
|
899
|
-
|
|
935
|
+
listTemplateSources(status) {
|
|
936
|
+
const rows = status
|
|
937
|
+
? db.prepare(`select * from template_sources where status = ? order by created_at asc`).all(status)
|
|
938
|
+
: db.prepare(`select * from template_sources order by created_at asc`).all();
|
|
939
|
+
return rows.map(mapTemplateSource);
|
|
900
940
|
},
|
|
901
941
|
createTemplateRelease(record) {
|
|
902
942
|
const timestamp = nowIso();
|
|
903
943
|
db.prepare(`
|
|
904
944
|
insert into template_releases (
|
|
905
|
-
id, source_id, template_id, branch, commit_sha, checkout_path, skill_path, module_path, status,
|
|
945
|
+
id, source_id, template_id, branch, commit_sha, checkout_path, skill_path, module_path, artifact_manifest_key, artifact_key, status,
|
|
906
946
|
certification_report_json, activated_at, created_at, updated_at
|
|
907
947
|
) values (
|
|
908
|
-
@id, @source_id, @template_id, @branch, @commit_sha, @checkout_path, @skill_path, @module_path, @status,
|
|
948
|
+
@id, @source_id, @template_id, @branch, @commit_sha, @checkout_path, @skill_path, @module_path, @artifact_manifest_key, @artifact_key, @status,
|
|
909
949
|
@certification_report_json, @activated_at, @created_at, @updated_at
|
|
910
950
|
)
|
|
911
951
|
on conflict(source_id, commit_sha) do update set
|
|
912
952
|
checkout_path = excluded.checkout_path,
|
|
913
953
|
skill_path = excluded.skill_path,
|
|
914
954
|
module_path = excluded.module_path,
|
|
955
|
+
artifact_manifest_key = excluded.artifact_manifest_key,
|
|
956
|
+
artifact_key = excluded.artifact_key,
|
|
915
957
|
status = excluded.status,
|
|
916
958
|
certification_report_json = excluded.certification_report_json,
|
|
917
959
|
activated_at = excluded.activated_at,
|
|
@@ -925,6 +967,8 @@ export const database = {
|
|
|
925
967
|
checkout_path: record.checkoutPath,
|
|
926
968
|
skill_path: record.skillPath,
|
|
927
969
|
module_path: record.modulePath,
|
|
970
|
+
artifact_manifest_key: record.artifactManifestKey ?? null,
|
|
971
|
+
artifact_key: record.artifactKey ?? null,
|
|
928
972
|
status: record.status,
|
|
929
973
|
certification_report_json: stringifyJson(record.certificationReport ?? null),
|
|
930
974
|
activated_at: record.activatedAt ?? null,
|
|
@@ -951,10 +995,16 @@ export const database = {
|
|
|
951
995
|
`).get(sourceId);
|
|
952
996
|
return row ? mapTemplateRelease(row) : null;
|
|
953
997
|
},
|
|
954
|
-
listTemplateReleases(
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
998
|
+
listTemplateReleases(input) {
|
|
999
|
+
const templateId = input?.templateId;
|
|
1000
|
+
const status = input?.status;
|
|
1001
|
+
const rows = templateId && status
|
|
1002
|
+
? db.prepare(`select * from template_releases where template_id = ? and status = ? order by created_at desc`).all(templateId, status)
|
|
1003
|
+
: templateId
|
|
1004
|
+
? db.prepare(`select * from template_releases where template_id = ? order by created_at desc`).all(templateId)
|
|
1005
|
+
: status
|
|
1006
|
+
? db.prepare(`select * from template_releases where status = ? order by created_at desc`).all(status)
|
|
1007
|
+
: db.prepare(`select * from template_releases order by created_at desc`).all();
|
|
958
1008
|
return rows.map(mapTemplateRelease);
|
|
959
1009
|
},
|
|
960
1010
|
getActiveTemplateReleases() {
|
|
@@ -979,12 +1029,16 @@ export const database = {
|
|
|
979
1029
|
updated_at: nowIso()
|
|
980
1030
|
});
|
|
981
1031
|
},
|
|
982
|
-
clearActiveTemplateReleases(templateId) {
|
|
1032
|
+
clearActiveTemplateReleases(templateId, fallbackStatus = "approved") {
|
|
983
1033
|
db.prepare(`
|
|
984
1034
|
update template_releases
|
|
985
|
-
set status = case when status = 'active' then
|
|
986
|
-
updated_at =
|
|
987
|
-
where template_id =
|
|
988
|
-
`).run(
|
|
1035
|
+
set status = case when status = 'active' then @fallback_status else status end,
|
|
1036
|
+
updated_at = @updated_at
|
|
1037
|
+
where template_id = @template_id
|
|
1038
|
+
`).run({
|
|
1039
|
+
fallback_status: fallbackStatus,
|
|
1040
|
+
updated_at: nowIso(),
|
|
1041
|
+
template_id: templateId
|
|
1042
|
+
});
|
|
989
1043
|
}
|
|
990
1044
|
};
|