@mevdragon/vidfarm-devcli 0.2.7 → 0.2.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.
- package/.env.example +9 -0
- package/GETTING_STARTED.developers.md +1 -30
- package/README.md +22 -5
- package/SKILL.developer.md +464 -12
- package/auto-create-templates/AUTO_CREATE_TEMPLATES.md +475 -0
- package/auto-create-templates/extractor-system-prompt.md +113 -0
- package/auto-create-templates/production-graph.schema.json +276 -0
- package/auto-create-templates/runbook.md +140 -0
- package/auto-create-templates/template-plan.schema.json +230 -0
- package/auto-create-templates/template-planner-prompt.md +75 -0
- package/dist/src/account-pages-legacy.js +9064 -0
- package/dist/src/account-pages.js +41 -620
- package/dist/src/app.js +7173 -494
- package/dist/src/cli.js +525 -29
- package/dist/src/config.js +14 -7
- package/dist/src/context.js +51 -35
- package/dist/src/db.js +1049 -55
- package/dist/src/dev-app-legacy.js +693 -0
- package/dist/src/dev-app.js +4 -904
- package/dist/src/domain.js +1 -1
- package/dist/src/editor-chat-history.js +72 -0
- package/dist/src/editor-chat.js +202 -0
- package/dist/src/frontend/flockposter-cache-store.js +116 -0
- package/dist/src/frontend/homepage-client.js +114 -0
- package/dist/src/frontend/homepage-shared.js +3 -0
- package/dist/src/frontend/homepage-store.js +27 -0
- package/dist/src/frontend/homepage-view.js +147 -0
- package/dist/src/frontend/page-runtime-client.js +100 -0
- package/dist/src/frontend/page-runtime-store.js +8 -0
- package/dist/src/frontend/template-editor-chat.js +2261 -0
- package/dist/src/homepage.js +695 -339
- package/dist/src/lib/template-paths.js +10 -4
- package/dist/src/lib/template-style-options.js +95 -15
- package/dist/src/page-runtime.js +1 -0
- package/dist/src/page-shell.js +941 -0
- package/dist/src/primitive-context.js +163 -0
- package/dist/src/primitive-registry.js +340 -0
- package/dist/src/primitive-sdk.js +3 -0
- package/dist/src/primitives/remotion/html-image.js +28 -0
- package/dist/src/react-page-shell.js +34 -0
- package/dist/src/ready-post-schedule-component.js +1514 -0
- package/dist/src/registry.js +44 -18
- package/dist/src/runtime.js +6 -1
- package/dist/src/services/api-call-history.js +245 -0
- package/dist/src/services/auth.js +27 -9
- package/dist/src/services/billing.js +248 -9
- package/dist/src/services/chat-threads.js +88 -0
- package/dist/src/services/job-logs.js +10 -3
- package/dist/src/services/jobs.js +13 -2
- package/dist/src/services/providers.js +944 -55
- package/dist/src/services/rate-limits.js +236 -0
- package/dist/src/services/remotion.js +143 -16
- package/dist/src/services/storage.js +23 -8
- package/dist/src/services/template-certification.js +26 -3
- package/dist/src/services/template-loader.js +19 -1
- package/dist/src/services/template-sources.js +316 -7
- package/dist/src/template-editor-pages.js +2309 -0
- package/dist/src/template-editor-shell.js +1507 -0
- package/dist/src/worker.js +120 -22
- package/package.json +30 -6
- package/public/assets/homepage-app.js +54 -0
- package/public/assets/homepage-client-app.js +54 -0
- package/public/assets/page-runtime-client-app.js +68 -0
- package/dist/templates/template_0000/src/lib/images.js +0 -202
- package/dist/templates/template_0000/src/remotion/Root.js +0 -33
- package/dist/templates/template_0000/src/remotion/index.js +0 -3
- package/dist/templates/template_0000/src/sdk.js +0 -3
- package/dist/templates/template_0000/src/style-options.js +0 -51
- package/dist/templates/template_0000/src/template-dna.js +0 -9
- package/dist/templates/template_0000/src/template.js +0 -1441
- package/templates/template_0000/README.md +0 -77
- package/templates/template_0000/SKILL.md +0 -225
- package/templates/template_0000/assets/Abel-Regular.ttf +0 -0
- package/templates/template_0000/assets/DMSerifDisplay-Regular.ttf +0 -0
- package/templates/template_0000/assets/Montserrat[wght].ttf +0 -0
- package/templates/template_0000/assets/SourceCodePro[wght].ttf +0 -0
- package/templates/template_0000/assets/TikTokSans-SemiBold.ttf +0 -0
- package/templates/template_0000/assets/Yesteryear-Regular.ttf +0 -0
- package/templates/template_0000/composition.json +0 -11
- package/templates/template_0000/package.json +0 -28
- package/templates/template_0000/research/preview/.gitkeep +0 -1
- package/templates/template_0000/research/source_notes.md +0 -7
- package/templates/template_0000/src/lib/images.js +0 -202
- package/templates/template_0000/src/lib/images.ts +0 -241
- package/templates/template_0000/src/remotion/Root.js +0 -33
- package/templates/template_0000/src/remotion/Root.tsx +0 -75
- package/templates/template_0000/src/remotion/index.js +0 -3
- package/templates/template_0000/src/remotion/index.tsx +0 -4
- package/templates/template_0000/src/sdk.js +0 -3
- package/templates/template_0000/src/sdk.ts +0 -122
- package/templates/template_0000/src/style-options.js +0 -51
- package/templates/template_0000/src/style-options.ts +0 -60
- package/templates/template_0000/src/template-dna.js +0 -9
- package/templates/template_0000/src/template-dna.ts +0 -15
- package/templates/template_0000/src/template.js +0 -1441
- package/templates/template_0000/src/template.ts +0 -2042
- package/templates/template_0000/template.config.json +0 -21
- package/templates/template_0000/tsconfig.json +0 -19
package/dist/src/cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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";
|
|
8
8
|
import { promisify } from "node:util";
|
|
9
9
|
import dotenv from "dotenv";
|
|
10
|
-
import { STARTER_TEMPLATE_FONT_OPTIONS, STARTER_TEMPLATE_TEXT_BACKGROUND_COLOR_OPTIONS } from "./lib/template-style-options.js";
|
|
10
|
+
import { CAPTION_STANDARD_VERSION, STARTER_TEMPLATE_FONT_OPTIONS, STARTER_TEMPLATE_TEXT_BACKGROUND_COLOR_OPTIONS, TIKTOK_CAPTION_STYLE_PRESETS } from "./lib/template-style-options.js";
|
|
11
11
|
import { analyzeTemplateDna, hasTemplatePreviewMedia, stageTemplateDnaInputs, syncTemplateDnaModule } from "./lib/template-dna.js";
|
|
12
12
|
import { assertTemplateFolderNameHasPrefix, defaultSkillPathForTemplateModule, deriveTemplateRootDirFromModulePath } from "./lib/template-paths.js";
|
|
13
13
|
const execFileAsync = promisify(execFile);
|
|
@@ -41,6 +41,10 @@ async function main() {
|
|
|
41
41
|
await runRegisterSourceHostedCommand(process.argv.slice(3));
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
+
if (command === "publish-update-hosted") {
|
|
45
|
+
await runPublishUpdateHostedCommand(process.argv.slice(3));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
44
48
|
if (command === "register-source-prod") {
|
|
45
49
|
await runRegisterSourceProdCommand(process.argv.slice(3));
|
|
46
50
|
return;
|
|
@@ -53,6 +57,10 @@ async function main() {
|
|
|
53
57
|
await runGenerateTemplateCommand(process.argv.slice(3));
|
|
54
58
|
return;
|
|
55
59
|
}
|
|
60
|
+
if (command === "autocreate-template" || command === "autocreate") {
|
|
61
|
+
await runAutocreateTemplateCommand(process.argv.slice(3));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
56
64
|
if (command === "copy-reference-template") {
|
|
57
65
|
await runCopyReferenceTemplateCommand(process.argv.slice(3));
|
|
58
66
|
return;
|
|
@@ -124,7 +132,8 @@ async function runDevCommand(argv) {
|
|
|
124
132
|
email: parsed.values.email,
|
|
125
133
|
name: parsed.values.name,
|
|
126
134
|
isDeveloper: true,
|
|
127
|
-
isPaidPlan: true
|
|
135
|
+
isPaidPlan: true,
|
|
136
|
+
planTier: "standard"
|
|
128
137
|
});
|
|
129
138
|
const rawApiKey = parsed.values["api-key"] ?? `vf_local_${Math.random().toString(36).slice(2, 12)}`;
|
|
130
139
|
database.insertApiKey({
|
|
@@ -294,9 +303,28 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
294
303
|
force: { type: "boolean", default: false }
|
|
295
304
|
}
|
|
296
305
|
});
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
const result = await generateTemplateFromStarter({
|
|
307
|
+
templateId: parsed.values["template-id"],
|
|
308
|
+
slugId: parsed.values["slug-id"],
|
|
309
|
+
templateDir: parsed.values["template-dir"],
|
|
310
|
+
projectName: parsed.values["project-name"],
|
|
311
|
+
githubRepo: parsed.values["github-repo"],
|
|
312
|
+
siteName: parsed.values["site-name"],
|
|
313
|
+
linkToOriginal: parsed.values["link-to-original"],
|
|
314
|
+
sourceNotesPath: parsed.values["source-notes-path"],
|
|
315
|
+
sourcePreviewDir: parsed.values["source-preview-dir"],
|
|
316
|
+
dnaEnvFile: parsed.values["dna-env-file"],
|
|
317
|
+
dnaModel: parsed.values["dna-model"],
|
|
318
|
+
skipDnaAnalysis: parsed.values["skip-dna-analysis"],
|
|
319
|
+
branch: parsed.values.branch,
|
|
320
|
+
force: parsed.values.force
|
|
321
|
+
});
|
|
322
|
+
console.log(JSON.stringify(result, null, 2));
|
|
323
|
+
}
|
|
324
|
+
async function generateTemplateFromStarter(input) {
|
|
325
|
+
const templateId = input.templateId ?? randomUUID();
|
|
326
|
+
const slugId = input.slugId;
|
|
327
|
+
const templateDir = input.templateDir;
|
|
300
328
|
if (!slugId || !templateDir) {
|
|
301
329
|
throw new Error("generate-template requires --slug-id and --template-dir. --template-id is optional and defaults to a new UUIDv4.");
|
|
302
330
|
}
|
|
@@ -309,7 +337,7 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
309
337
|
throw new Error(`Starter template not found: ${starterDir}`);
|
|
310
338
|
}
|
|
311
339
|
if (existsSync(destinationDir)) {
|
|
312
|
-
if (!
|
|
340
|
+
if (!input.force) {
|
|
313
341
|
throw new Error(`Destination already exists: ${destinationDir}`);
|
|
314
342
|
}
|
|
315
343
|
rmSync(destinationDir, { recursive: true, force: true });
|
|
@@ -321,9 +349,9 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
321
349
|
return ![".git", "node_modules", "dist", "package-lock.json"].includes(name);
|
|
322
350
|
}
|
|
323
351
|
});
|
|
324
|
-
const projectName =
|
|
325
|
-
const siteName =
|
|
326
|
-
const githubRepo =
|
|
352
|
+
const projectName = input.projectName ?? toProjectName(destinationFolderName);
|
|
353
|
+
const siteName = input.siteName ?? projectName.replace(/_/g, "-");
|
|
354
|
+
const githubRepo = input.githubRepo ?? `mevdragon/${projectName}`;
|
|
327
355
|
rewriteTemplateStarter(destinationDir, [
|
|
328
356
|
["mevdragon/vidfarm_template_0000", githubRepo],
|
|
329
357
|
["vidfarm_template_0000", projectName],
|
|
@@ -331,35 +359,35 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
331
359
|
["template_0000", slugId],
|
|
332
360
|
["template-0000", slugId.replace(/_/g, "-")],
|
|
333
361
|
["4c7a7e1a-7f35-4f30-9f86-9c8a63c7f2db", templateId],
|
|
334
|
-
['"production"', JSON.stringify(
|
|
362
|
+
['"production"', JSON.stringify(input.branch ?? "production")]
|
|
335
363
|
]);
|
|
336
364
|
const stagedInputs = stageTemplateDnaInputs({
|
|
337
365
|
templateDir: destinationDir,
|
|
338
|
-
sourceNotesPath:
|
|
339
|
-
sourcePreviewDir:
|
|
366
|
+
sourceNotesPath: input.sourceNotesPath,
|
|
367
|
+
sourcePreviewDir: input.sourcePreviewDir
|
|
340
368
|
});
|
|
341
369
|
const moduleSync = syncTemplateDnaModule({
|
|
342
370
|
templateDir: destinationDir,
|
|
343
|
-
linkToOriginal:
|
|
371
|
+
linkToOriginal: input.linkToOriginal
|
|
344
372
|
});
|
|
345
373
|
const dnaRuns = [];
|
|
346
|
-
if (!
|
|
374
|
+
if (!input.skipDnaAnalysis && hasTemplatePreviewMedia(destinationDir)) {
|
|
347
375
|
dnaRuns.push(await analyzeTemplateDna({
|
|
348
376
|
mode: "viral",
|
|
349
377
|
templateDir: destinationDir,
|
|
350
|
-
envFile:
|
|
351
|
-
model:
|
|
352
|
-
linkToOriginal:
|
|
378
|
+
envFile: input.dnaEnvFile ?? ".env",
|
|
379
|
+
model: input.dnaModel,
|
|
380
|
+
linkToOriginal: input.linkToOriginal
|
|
353
381
|
}));
|
|
354
382
|
dnaRuns.push(await analyzeTemplateDna({
|
|
355
383
|
mode: "visual",
|
|
356
384
|
templateDir: destinationDir,
|
|
357
|
-
envFile:
|
|
358
|
-
model:
|
|
359
|
-
linkToOriginal:
|
|
385
|
+
envFile: input.dnaEnvFile ?? ".env",
|
|
386
|
+
model: input.dnaModel,
|
|
387
|
+
linkToOriginal: input.linkToOriginal
|
|
360
388
|
}));
|
|
361
389
|
}
|
|
362
|
-
|
|
390
|
+
return {
|
|
363
391
|
template_id: templateId,
|
|
364
392
|
slug_id: slugId,
|
|
365
393
|
template_dir: destinationDir,
|
|
@@ -368,7 +396,152 @@ async function runGenerateTemplateCommand(argv) {
|
|
|
368
396
|
site_name: siteName,
|
|
369
397
|
research: stagedInputs,
|
|
370
398
|
template_dna_module: moduleSync,
|
|
371
|
-
dna_analysis_runs: dnaRuns
|
|
399
|
+
dna_analysis_runs: dnaRuns,
|
|
400
|
+
required_template_contract: {
|
|
401
|
+
template_fields: [
|
|
402
|
+
"id",
|
|
403
|
+
"slugId",
|
|
404
|
+
"version",
|
|
405
|
+
"about.title",
|
|
406
|
+
"about.description",
|
|
407
|
+
"about.viral_dna",
|
|
408
|
+
"about.visual_dna",
|
|
409
|
+
"about.preview_media",
|
|
410
|
+
"about.link_to_original",
|
|
411
|
+
"about.proposal_generator",
|
|
412
|
+
"about.skeleton_prompt",
|
|
413
|
+
"about.sample_prompts",
|
|
414
|
+
"configSchema",
|
|
415
|
+
],
|
|
416
|
+
operation_fields: [
|
|
417
|
+
"operations.<name>.workflow",
|
|
418
|
+
"operations.<name>.smokeTestPayload",
|
|
419
|
+
"jobs.<workflow>",
|
|
420
|
+
],
|
|
421
|
+
files: [
|
|
422
|
+
"src/template.ts",
|
|
423
|
+
"SKILL.md",
|
|
424
|
+
],
|
|
425
|
+
},
|
|
426
|
+
next_steps: [
|
|
427
|
+
"Review src/template.ts and replace the starter proposal_generator with template-specific proposal instructions.",
|
|
428
|
+
"Review src/template.ts and replace the starter skeleton_prompt with a fill-in-the-blanks prompt that fits the real format.",
|
|
429
|
+
"Review src/template.ts and replace the starter sample_prompts with prompts that fit the new format.",
|
|
430
|
+
"If DNA analysis was skipped or the source research changed, run analyze-viral-dna and analyze-visual-dna.",
|
|
431
|
+
"Update SKILL.md so the usage examples match the template's real operations and payloads.",
|
|
432
|
+
`Run validate-template against ${slugId} and launch at least one real local job before treating the template as ready.`,
|
|
433
|
+
],
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
async function runAutocreateTemplateCommand(argv) {
|
|
437
|
+
const parsed = parseArgs({
|
|
438
|
+
args: argv,
|
|
439
|
+
allowPositionals: true,
|
|
440
|
+
options: {
|
|
441
|
+
"input-path": { type: "string" },
|
|
442
|
+
"output-path": { type: "string" },
|
|
443
|
+
"run-id": { type: "string" },
|
|
444
|
+
"runs-dir": { type: "string", default: "auto-create-templates/runs" },
|
|
445
|
+
"harness-dir": { type: "string" },
|
|
446
|
+
"slug-id": { type: "string" },
|
|
447
|
+
"template-id": { type: "string" },
|
|
448
|
+
"project-name": { type: "string" },
|
|
449
|
+
"github-repo": { type: "string" },
|
|
450
|
+
"site-name": { type: "string" },
|
|
451
|
+
"link-to-original": { type: "string" },
|
|
452
|
+
"dna-env-file": { type: "string", default: ".env" },
|
|
453
|
+
"dna-model": { type: "string" },
|
|
454
|
+
"skip-dna-analysis": { type: "boolean", default: false },
|
|
455
|
+
"skip-scaffold": { type: "boolean", default: false },
|
|
456
|
+
"skip-media-probes": { type: "boolean", default: false },
|
|
457
|
+
"skip-harness-snapshot": { type: "boolean", default: false },
|
|
458
|
+
branch: { type: "string", default: "production" },
|
|
459
|
+
force: { type: "boolean", default: false }
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
const positionalInput = parsed.positionals[0];
|
|
463
|
+
const positionalOutput = parsed.positionals[1];
|
|
464
|
+
const inputPathRaw = parsed.values["input-path"] ?? positionalInput;
|
|
465
|
+
const outputPathRaw = parsed.values["output-path"] ?? positionalOutput;
|
|
466
|
+
if (!inputPathRaw || !outputPathRaw) {
|
|
467
|
+
throw new Error("autocreate-template requires --input-path and --output-path, or positional args: autocreate-template <input_path> <output_path>.");
|
|
468
|
+
}
|
|
469
|
+
const root = process.cwd();
|
|
470
|
+
const inputPath = path.resolve(root, inputPathRaw);
|
|
471
|
+
const outputPath = path.resolve(root, outputPathRaw);
|
|
472
|
+
if (!existsSync(inputPath)) {
|
|
473
|
+
throw new Error(`Input path not found: ${inputPath}`);
|
|
474
|
+
}
|
|
475
|
+
const outputFolderName = path.basename(outputPath);
|
|
476
|
+
assertTemplateFolderNameHasPrefix(outputFolderName);
|
|
477
|
+
const slugId = parsed.values["slug-id"] ?? toSlugId(outputFolderName);
|
|
478
|
+
const runId = parsed.values["run-id"] ?? `${toProjectName(slugId)}-${formatUtcTimestamp(new Date())}`;
|
|
479
|
+
const runsDir = path.resolve(root, parsed.values["runs-dir"]);
|
|
480
|
+
const runDir = path.join(runsDir, runId);
|
|
481
|
+
const sourceDir = path.join(runDir, "source");
|
|
482
|
+
const previewDir = path.join(sourceDir, "preview");
|
|
483
|
+
const harnessDir = parsed.values["harness-dir"]
|
|
484
|
+
? path.resolve(root, parsed.values["harness-dir"])
|
|
485
|
+
: resolveAutoCreateHarnessDir();
|
|
486
|
+
createAutoCreateRunFolders(runDir);
|
|
487
|
+
stageAutocreateSource({
|
|
488
|
+
inputPath,
|
|
489
|
+
sourceDir,
|
|
490
|
+
previewDir,
|
|
491
|
+
linkToOriginal: parsed.values["link-to-original"]
|
|
492
|
+
});
|
|
493
|
+
const mediaProbe = parsed.values["skip-media-probes"]
|
|
494
|
+
? { skipped: true, reason: "skip-media-probes was set" }
|
|
495
|
+
: await prepareAutocreateMediaArtifacts({ runDir, previewDir });
|
|
496
|
+
const harnessSnapshot = parsed.values["skip-harness-snapshot"]
|
|
497
|
+
? null
|
|
498
|
+
: snapshotAutoCreateHarness({ harnessDir, runDir });
|
|
499
|
+
const sourceNotesPath = path.join(sourceDir, "source.md");
|
|
500
|
+
const scaffold = parsed.values["skip-scaffold"]
|
|
501
|
+
? null
|
|
502
|
+
: await generateTemplateFromStarter({
|
|
503
|
+
templateId: parsed.values["template-id"],
|
|
504
|
+
slugId,
|
|
505
|
+
templateDir: path.relative(root, outputPath),
|
|
506
|
+
projectName: parsed.values["project-name"],
|
|
507
|
+
githubRepo: parsed.values["github-repo"],
|
|
508
|
+
siteName: parsed.values["site-name"],
|
|
509
|
+
linkToOriginal: parsed.values["link-to-original"],
|
|
510
|
+
sourceNotesPath,
|
|
511
|
+
sourcePreviewDir: previewDir,
|
|
512
|
+
dnaEnvFile: parsed.values["dna-env-file"],
|
|
513
|
+
dnaModel: parsed.values["dna-model"],
|
|
514
|
+
skipDnaAnalysis: parsed.values["skip-dna-analysis"],
|
|
515
|
+
branch: parsed.values.branch,
|
|
516
|
+
force: parsed.values.force
|
|
517
|
+
});
|
|
518
|
+
const agentPromptPath = path.join(runDir, "agent_prompt.md");
|
|
519
|
+
const manifest = {
|
|
520
|
+
mode: "autocreate-template",
|
|
521
|
+
harness_entry: path.join(harnessDir, "AUTO_CREATE_TEMPLATES.md"),
|
|
522
|
+
harness_snapshot: harnessSnapshot,
|
|
523
|
+
input_path: inputPath,
|
|
524
|
+
output_path: outputPath,
|
|
525
|
+
run_id: runId,
|
|
526
|
+
run_dir: runDir,
|
|
527
|
+
source_dir: sourceDir,
|
|
528
|
+
source_notes_path: sourceNotesPath,
|
|
529
|
+
source_preview_dir: previewDir,
|
|
530
|
+
slug_id: slugId,
|
|
531
|
+
scaffold,
|
|
532
|
+
media_probe: mediaProbe,
|
|
533
|
+
required_artifacts: {
|
|
534
|
+
viral_steering_and_visual_preservation: path.join(runDir, "dna", "preservation_decision.json"),
|
|
535
|
+
production_graph: path.join(runDir, "extraction", "production_graph.json"),
|
|
536
|
+
template_plan: path.join(runDir, "plan", "template_plan.json")
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
writeFileSync(path.join(runDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
540
|
+
writeFileSync(agentPromptPath, renderAutocreateAgentPrompt(manifest), "utf8");
|
|
541
|
+
console.log(JSON.stringify({
|
|
542
|
+
...manifest,
|
|
543
|
+
agent_prompt_path: agentPromptPath,
|
|
544
|
+
next_command_for_agent: `Use ${manifest.harness_entry} as the harness. Analyze ${sourceDir} as the source format, use run artifacts in ${runDir}, generate the production graph and template plan, then scaffold and implement a runnable Vidfarm template to ${outputPath}.`
|
|
372
545
|
}, null, 2));
|
|
373
546
|
}
|
|
374
547
|
async function runRegisterSourceProdCommand(argv) {
|
|
@@ -402,6 +575,45 @@ async function runRegisterSourceHostedCommand(argv) {
|
|
|
402
575
|
next_step: "Platform admin reviews the source, imports a release, approves it, and activates it."
|
|
403
576
|
}, null, 2));
|
|
404
577
|
}
|
|
578
|
+
async function runPublishUpdateHostedCommand(argv) {
|
|
579
|
+
const input = parseProdTemplateCommandArgs(argv, {
|
|
580
|
+
envFile: ".env",
|
|
581
|
+
baseUrl: process.env.VIDFARM_BASE_URL ?? "https://vidfarm.cloud.zoomgtm.com",
|
|
582
|
+
activate: false
|
|
583
|
+
});
|
|
584
|
+
if (!input.commitSha) {
|
|
585
|
+
throw new Error("publish-update-hosted requires --commit-sha.");
|
|
586
|
+
}
|
|
587
|
+
const registration = await registerSourceViaApi(input);
|
|
588
|
+
const artifact = await packageTemplateArtifact(input.repoDir, input.commitSha);
|
|
589
|
+
const presign = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/artifacts/presign`, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
body: JSON.stringify({
|
|
592
|
+
commit_sha: input.commitSha
|
|
593
|
+
})
|
|
594
|
+
});
|
|
595
|
+
await uploadArtifactArchive(presign, artifact.buffer);
|
|
596
|
+
const payload = await postProdTemplateApi(input, `/api/v1/templates/sources/${registration.source.id}/publish`, {
|
|
597
|
+
method: "POST",
|
|
598
|
+
body: JSON.stringify({
|
|
599
|
+
commit_sha: input.commitSha,
|
|
600
|
+
artifact_sha256: artifact.sha256
|
|
601
|
+
})
|
|
602
|
+
});
|
|
603
|
+
console.log(JSON.stringify({
|
|
604
|
+
mode: "hosted-publish-update",
|
|
605
|
+
base_url: input.baseUrl,
|
|
606
|
+
source: payload.source,
|
|
607
|
+
release: payload.release,
|
|
608
|
+
artifact: {
|
|
609
|
+
artifact_key: presign.artifact_key,
|
|
610
|
+
artifact_manifest_key: presign.artifact_manifest_key,
|
|
611
|
+
sha256: artifact.sha256
|
|
612
|
+
},
|
|
613
|
+
publish_action: payload.publish_action,
|
|
614
|
+
developer_handoff: payload.developer_handoff ?? null
|
|
615
|
+
}, null, 2));
|
|
616
|
+
}
|
|
405
617
|
async function runImportSourceProdCommand(argv) {
|
|
406
618
|
const input = parseProdTemplateCommandArgs(argv, {
|
|
407
619
|
envFile: ".env.production",
|
|
@@ -486,7 +698,38 @@ async function runCopyReferenceTemplateCommand(argv) {
|
|
|
486
698
|
template_dir: destinationDir,
|
|
487
699
|
template_id: "4c7a7e1a-7f35-4f30-9f86-9c8a63c7f2db",
|
|
488
700
|
slug_id: "template_0000",
|
|
489
|
-
rewritten: false
|
|
701
|
+
rewritten: false,
|
|
702
|
+
required_template_contract: {
|
|
703
|
+
template_fields: [
|
|
704
|
+
"id",
|
|
705
|
+
"slugId",
|
|
706
|
+
"version",
|
|
707
|
+
"about.title",
|
|
708
|
+
"about.description",
|
|
709
|
+
"about.viral_dna",
|
|
710
|
+
"about.visual_dna",
|
|
711
|
+
"about.preview_media",
|
|
712
|
+
"about.link_to_original",
|
|
713
|
+
"about.proposal_generator",
|
|
714
|
+
"about.skeleton_prompt",
|
|
715
|
+
"about.sample_prompts",
|
|
716
|
+
"configSchema",
|
|
717
|
+
],
|
|
718
|
+
operation_fields: [
|
|
719
|
+
"operations.<name>.workflow",
|
|
720
|
+
"operations.<name>.smokeTestPayload",
|
|
721
|
+
"jobs.<workflow>",
|
|
722
|
+
],
|
|
723
|
+
files: [
|
|
724
|
+
"src/template.ts",
|
|
725
|
+
"SKILL.md",
|
|
726
|
+
],
|
|
727
|
+
},
|
|
728
|
+
next_steps: [
|
|
729
|
+
"Treat src/template.ts as the canonical entrypoint and review the required about metadata before copying patterns into a new template.",
|
|
730
|
+
"Use the starter proposal_generator, skeleton_prompt, and sample_prompts as placeholders only; rewrite them for the real format you are building.",
|
|
731
|
+
"Keep the template-local SKILL.md aligned with the operations and payloads in code.",
|
|
732
|
+
],
|
|
490
733
|
}, null, 2));
|
|
491
734
|
}
|
|
492
735
|
async function runAnalyzeTemplateDnaCommand(mode, argv) {
|
|
@@ -611,9 +854,18 @@ async function runSessionCommand(argv) {
|
|
|
611
854
|
base_url: session.baseUrl,
|
|
612
855
|
email: session.email,
|
|
613
856
|
starter_style_options: {
|
|
857
|
+
caption_standard_version: CAPTION_STANDARD_VERSION,
|
|
614
858
|
fonts: STARTER_TEMPLATE_FONT_OPTIONS,
|
|
615
859
|
text_background_colors: STARTER_TEMPLATE_TEXT_BACKGROUND_COLOR_OPTIONS,
|
|
616
|
-
|
|
860
|
+
presets: TIKTOK_CAPTION_STYLE_PRESETS,
|
|
861
|
+
package_dependencies: [
|
|
862
|
+
"@fontsource/tiktok-sans",
|
|
863
|
+
"@fontsource/montserrat",
|
|
864
|
+
"@fontsource/source-code-pro",
|
|
865
|
+
"@fontsource/libre-baskerville"
|
|
866
|
+
],
|
|
867
|
+
standard_file: "src/lib/template-style-options.ts",
|
|
868
|
+
starter_template_file: "demos/vidfarm_template_0000/src/style-options.ts"
|
|
617
869
|
},
|
|
618
870
|
headers: {
|
|
619
871
|
"vidfarm-api-key": session.apiKey,
|
|
@@ -649,8 +901,7 @@ function seedEnvProviderKeys(input) {
|
|
|
649
901
|
customerId: input.customerId,
|
|
650
902
|
provider: entry.provider,
|
|
651
903
|
label: "Local CLI env key",
|
|
652
|
-
encryptedSecret: input.encryptString(secret, input.encryptionSecret)
|
|
653
|
-
weight: 1
|
|
904
|
+
encryptedSecret: input.encryptString(secret, input.encryptionSecret)
|
|
654
905
|
});
|
|
655
906
|
}
|
|
656
907
|
}
|
|
@@ -700,8 +951,10 @@ function toProjectName(folderName) {
|
|
|
700
951
|
}
|
|
701
952
|
function resolveStarterTemplateDir() {
|
|
702
953
|
const candidates = [
|
|
703
|
-
path.resolve(import.meta.dirname, "..", "templates", "
|
|
704
|
-
path.resolve(import.meta.dirname, "..", "..", "templates", "
|
|
954
|
+
path.resolve(import.meta.dirname, "..", "templates", "vidfarm_template_0000"),
|
|
955
|
+
path.resolve(import.meta.dirname, "..", "..", "templates", "vidfarm_template_0000"),
|
|
956
|
+
path.resolve(import.meta.dirname, "..", "demos", "vidfarm_template_0000"),
|
|
957
|
+
path.resolve(import.meta.dirname, "..", "..", "demos", "vidfarm_template_0000")
|
|
705
958
|
];
|
|
706
959
|
for (const candidate of candidates) {
|
|
707
960
|
if (existsSync(candidate)) {
|
|
@@ -710,6 +963,218 @@ function resolveStarterTemplateDir() {
|
|
|
710
963
|
}
|
|
711
964
|
return candidates[0];
|
|
712
965
|
}
|
|
966
|
+
function resolveAutoCreateHarnessDir() {
|
|
967
|
+
const candidates = [
|
|
968
|
+
path.resolve(process.cwd(), "auto-create-templates"),
|
|
969
|
+
path.resolve(import.meta.dirname, "..", "auto-create-templates"),
|
|
970
|
+
path.resolve(import.meta.dirname, "..", "..", "auto-create-templates")
|
|
971
|
+
];
|
|
972
|
+
for (const candidate of candidates) {
|
|
973
|
+
if (existsSync(path.join(candidate, "AUTO_CREATE_TEMPLATES.md"))) {
|
|
974
|
+
return candidate;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return candidates[0];
|
|
978
|
+
}
|
|
979
|
+
function createAutoCreateRunFolders(runDir) {
|
|
980
|
+
for (const name of ["source", "frames", "audio", "transcripts", "ocr", "motion", "dna", "extraction", "plan"]) {
|
|
981
|
+
mkdirSync(path.join(runDir, name), { recursive: true });
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
function stageAutocreateSource(input) {
|
|
985
|
+
mkdirSync(input.sourceDir, { recursive: true });
|
|
986
|
+
mkdirSync(input.previewDir, { recursive: true });
|
|
987
|
+
const stats = statSync(input.inputPath);
|
|
988
|
+
if (stats.isDirectory()) {
|
|
989
|
+
const inputHadPreviewDir = existsSync(path.join(input.inputPath, "preview"));
|
|
990
|
+
copyDirectoryContentsShallow(input.inputPath, input.sourceDir);
|
|
991
|
+
const existingPreviewDir = path.join(input.sourceDir, "preview");
|
|
992
|
+
if (!inputHadPreviewDir) {
|
|
993
|
+
mkdirSync(existingPreviewDir, { recursive: true });
|
|
994
|
+
for (const mediaFile of listMediaFiles(input.sourceDir)) {
|
|
995
|
+
cpSync(mediaFile, path.join(existingPreviewDir, path.basename(mediaFile)));
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
else {
|
|
1000
|
+
cpSync(input.inputPath, path.join(input.previewDir, path.basename(input.inputPath)));
|
|
1001
|
+
}
|
|
1002
|
+
const notesPath = path.join(input.sourceDir, "source.md");
|
|
1003
|
+
if (!existsSync(notesPath)) {
|
|
1004
|
+
writeFileSync(notesPath, [
|
|
1005
|
+
"# Source Notes",
|
|
1006
|
+
"",
|
|
1007
|
+
`- input path: ${input.inputPath}`,
|
|
1008
|
+
`- original format URL: ${input.linkToOriginal ?? ""}`,
|
|
1009
|
+
"- creator/account:",
|
|
1010
|
+
"- product/category being adapted:",
|
|
1011
|
+
"- what appears repeatable:",
|
|
1012
|
+
"- constraints:",
|
|
1013
|
+
""
|
|
1014
|
+
].join("\n"), "utf8");
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
async function prepareAutocreateMediaArtifacts(input) {
|
|
1018
|
+
const videoFile = listMediaFiles(input.previewDir).find((filePath) => isVideoFile(filePath));
|
|
1019
|
+
if (!videoFile) {
|
|
1020
|
+
return {
|
|
1021
|
+
skipped: true,
|
|
1022
|
+
reason: "No video file found in source preview media.",
|
|
1023
|
+
preview_files: listMediaFiles(input.previewDir)
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
const ffprobePath = path.join(input.runDir, "source", "ffprobe.json");
|
|
1027
|
+
const contactSheetPath = path.join(input.runDir, "frames", "contact-sheet.jpg");
|
|
1028
|
+
const audioPath = path.join(input.runDir, "audio", "source.wav");
|
|
1029
|
+
const steps = [];
|
|
1030
|
+
steps.push(await runOptionalLocalCommand("ffprobe", [
|
|
1031
|
+
"-v", "error",
|
|
1032
|
+
"-show_entries", "format=duration:stream=codec_type,width,height,avg_frame_rate",
|
|
1033
|
+
"-of", "json",
|
|
1034
|
+
videoFile
|
|
1035
|
+
], ffprobePath));
|
|
1036
|
+
steps.push(await runOptionalLocalCommand("ffmpeg", [
|
|
1037
|
+
"-y",
|
|
1038
|
+
"-i", videoFile,
|
|
1039
|
+
"-vf", "fps=1/2,scale=240:-1,tile=3x4",
|
|
1040
|
+
"-frames:v", "1",
|
|
1041
|
+
contactSheetPath
|
|
1042
|
+
]));
|
|
1043
|
+
steps.push(await runOptionalLocalCommand("ffmpeg", [
|
|
1044
|
+
"-y",
|
|
1045
|
+
"-i", videoFile,
|
|
1046
|
+
"-vn",
|
|
1047
|
+
"-ac", "1",
|
|
1048
|
+
"-ar", "16000",
|
|
1049
|
+
audioPath
|
|
1050
|
+
]));
|
|
1051
|
+
const result = {
|
|
1052
|
+
skipped: false,
|
|
1053
|
+
video_file: videoFile,
|
|
1054
|
+
ffprobe_path: existsSync(ffprobePath) ? ffprobePath : null,
|
|
1055
|
+
contact_sheet_path: existsSync(contactSheetPath) ? contactSheetPath : null,
|
|
1056
|
+
audio_path: existsSync(audioPath) ? audioPath : null,
|
|
1057
|
+
steps
|
|
1058
|
+
};
|
|
1059
|
+
writeFileSync(path.join(input.runDir, "source", "media_artifacts.json"), JSON.stringify(result, null, 2) + "\n", "utf8");
|
|
1060
|
+
return result;
|
|
1061
|
+
}
|
|
1062
|
+
function snapshotAutoCreateHarness(input) {
|
|
1063
|
+
if (!existsSync(path.join(input.harnessDir, "AUTO_CREATE_TEMPLATES.md"))) {
|
|
1064
|
+
throw new Error(`Auto-create harness not found: ${input.harnessDir}`);
|
|
1065
|
+
}
|
|
1066
|
+
const destinationDir = path.join(input.runDir, "harness");
|
|
1067
|
+
mkdirSync(destinationDir, { recursive: true });
|
|
1068
|
+
for (const fileName of [
|
|
1069
|
+
"AUTO_CREATE_TEMPLATES.md",
|
|
1070
|
+
"runbook.md",
|
|
1071
|
+
"extractor-system-prompt.md",
|
|
1072
|
+
"production-graph.schema.json",
|
|
1073
|
+
"template-planner-prompt.md",
|
|
1074
|
+
"template-plan.schema.json"
|
|
1075
|
+
]) {
|
|
1076
|
+
const source = path.join(input.harnessDir, fileName);
|
|
1077
|
+
if (existsSync(source)) {
|
|
1078
|
+
cpSync(source, path.join(destinationDir, fileName));
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
return {
|
|
1082
|
+
harness_dir: destinationDir,
|
|
1083
|
+
entry: path.join(destinationDir, "AUTO_CREATE_TEMPLATES.md")
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
function renderAutocreateAgentPrompt(manifest) {
|
|
1087
|
+
return [
|
|
1088
|
+
"# Vidfarm Autocreate Template Handoff",
|
|
1089
|
+
"",
|
|
1090
|
+
`Use ${manifest.harness_entry} as the harness.`,
|
|
1091
|
+
`Analyze ${manifest.source_dir} as the source format.`,
|
|
1092
|
+
`Use the run artifacts in ${manifest.run_dir}.`,
|
|
1093
|
+
`Output the runnable Vidfarm template to ${manifest.output_path}.`,
|
|
1094
|
+
"",
|
|
1095
|
+
"Required work:",
|
|
1096
|
+
"",
|
|
1097
|
+
"1. Inspect source notes and preview media.",
|
|
1098
|
+
"2. Use or create analyzer artifacts in the run folder.",
|
|
1099
|
+
"3. Run or consume viral and visual DNA analysis.",
|
|
1100
|
+
"4. Create `dna/preservation_decision.json`.",
|
|
1101
|
+
"5. Create `extraction/production_graph.json` matching the production graph schema.",
|
|
1102
|
+
"6. Create `plan/template_plan.json` matching the template plan schema.",
|
|
1103
|
+
"7. Implement the template operations, jobs, metadata, prompts, storage outputs, and template-local `SKILL.md`.",
|
|
1104
|
+
"8. Run `vidfarm-devcli validate-template` and at least one real local job before calling it done.",
|
|
1105
|
+
"",
|
|
1106
|
+
"Manifest:",
|
|
1107
|
+
"",
|
|
1108
|
+
"```json",
|
|
1109
|
+
JSON.stringify(manifest, null, 2),
|
|
1110
|
+
"```",
|
|
1111
|
+
""
|
|
1112
|
+
].join("\n");
|
|
1113
|
+
}
|
|
1114
|
+
async function runOptionalLocalCommand(command, args, outputPath) {
|
|
1115
|
+
try {
|
|
1116
|
+
const result = await execFileAsync(command, args, {
|
|
1117
|
+
maxBuffer: 20 * 1024 * 1024
|
|
1118
|
+
});
|
|
1119
|
+
if (outputPath) {
|
|
1120
|
+
writeFileSync(outputPath, result.stdout, "utf8");
|
|
1121
|
+
}
|
|
1122
|
+
return {
|
|
1123
|
+
command,
|
|
1124
|
+
ok: true,
|
|
1125
|
+
output_path: outputPath ?? null,
|
|
1126
|
+
stderr: result.stderr.trim() || null
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
catch (error) {
|
|
1130
|
+
return {
|
|
1131
|
+
command,
|
|
1132
|
+
ok: false,
|
|
1133
|
+
output_path: outputPath ?? null,
|
|
1134
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
function copyDirectoryContentsShallow(sourceDir, destinationDir) {
|
|
1139
|
+
mkdirSync(destinationDir, { recursive: true });
|
|
1140
|
+
for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {
|
|
1141
|
+
if (!entry.name.startsWith(".")) {
|
|
1142
|
+
cpSync(path.join(sourceDir, entry.name), path.join(destinationDir, entry.name), { recursive: true });
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
function listMediaFiles(dir) {
|
|
1147
|
+
if (!existsSync(dir)) {
|
|
1148
|
+
return [];
|
|
1149
|
+
}
|
|
1150
|
+
const files = [];
|
|
1151
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1152
|
+
const filePath = path.join(dir, entry.name);
|
|
1153
|
+
if (entry.name.startsWith(".")) {
|
|
1154
|
+
continue;
|
|
1155
|
+
}
|
|
1156
|
+
if (entry.isDirectory()) {
|
|
1157
|
+
files.push(...listMediaFiles(filePath));
|
|
1158
|
+
continue;
|
|
1159
|
+
}
|
|
1160
|
+
if (entry.isFile() && isMediaFile(filePath)) {
|
|
1161
|
+
files.push(filePath);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
return files.sort((a, b) => a.localeCompare(b));
|
|
1165
|
+
}
|
|
1166
|
+
function isMediaFile(filePath) {
|
|
1167
|
+
return [".png", ".jpg", ".jpeg", ".webp", ".mp4", ".mov", ".webm", ".m4v"].includes(path.extname(filePath).toLowerCase());
|
|
1168
|
+
}
|
|
1169
|
+
function isVideoFile(filePath) {
|
|
1170
|
+
return [".mp4", ".mov", ".webm", ".m4v"].includes(path.extname(filePath).toLowerCase());
|
|
1171
|
+
}
|
|
1172
|
+
function toSlugId(folderName) {
|
|
1173
|
+
return toProjectName(folderName).replace(/^vidfarm_template_/, "template_");
|
|
1174
|
+
}
|
|
1175
|
+
function formatUtcTimestamp(date) {
|
|
1176
|
+
return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
|
|
1177
|
+
}
|
|
713
1178
|
function parseProdTemplateCommandArgs(argv, defaults) {
|
|
714
1179
|
const parsed = parseArgs({
|
|
715
1180
|
args: argv,
|
|
@@ -723,6 +1188,7 @@ function parseProdTemplateCommandArgs(argv, defaults) {
|
|
|
723
1188
|
"install-command": { type: "string", default: "npm install" },
|
|
724
1189
|
"build-command": { type: "string", default: "npm run build" },
|
|
725
1190
|
"commit-sha": { type: "string" },
|
|
1191
|
+
"repo-dir": { type: "string", default: "." },
|
|
726
1192
|
"env-file": { type: "string", default: defaults.envFile },
|
|
727
1193
|
"base-url": { type: "string", default: defaults.baseUrl },
|
|
728
1194
|
"api-key": { type: "string" },
|
|
@@ -752,6 +1218,7 @@ function parseProdTemplateCommandArgs(argv, defaults) {
|
|
|
752
1218
|
installCommand: parsed.values["install-command"],
|
|
753
1219
|
buildCommand: parsed.values["build-command"],
|
|
754
1220
|
commitSha: parsed.values["commit-sha"] ?? undefined,
|
|
1221
|
+
repoDir: path.resolve(process.cwd(), parsed.values["repo-dir"]),
|
|
755
1222
|
envFile: parsed.values["env-file"],
|
|
756
1223
|
baseUrl: normalizeBaseUrl(parsed.values["base-url"]),
|
|
757
1224
|
apiKey,
|
|
@@ -810,6 +1277,35 @@ async function postProdTemplateApi(input, pathname, init) {
|
|
|
810
1277
|
}
|
|
811
1278
|
return payload;
|
|
812
1279
|
}
|
|
1280
|
+
async function packageTemplateArtifact(repoDir, commitSha) {
|
|
1281
|
+
const tempDir = mkdtempSync(path.join(os.tmpdir(), "vidfarm-template-artifact-"));
|
|
1282
|
+
const repoRoot = (await execFileAsync("git", ["-C", repoDir, "rev-parse", "--show-toplevel"])).stdout.trim();
|
|
1283
|
+
const artifactPath = path.join(tempDir, "template-source.tar.gz");
|
|
1284
|
+
try {
|
|
1285
|
+
await execFileAsync("git", ["-C", repoRoot, "archive", "--format=tar.gz", `--output=${artifactPath}`, commitSha], {
|
|
1286
|
+
cwd: repoRoot
|
|
1287
|
+
});
|
|
1288
|
+
const buffer = readFileSync(artifactPath);
|
|
1289
|
+
return {
|
|
1290
|
+
buffer,
|
|
1291
|
+
sha256: createHash("sha256").update(buffer).digest("hex")
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
finally {
|
|
1295
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
async function uploadArtifactArchive(presign, buffer) {
|
|
1299
|
+
const response = await fetch(presign.upload.url, {
|
|
1300
|
+
method: presign.upload.method,
|
|
1301
|
+
headers: presign.upload.headers,
|
|
1302
|
+
body: new Uint8Array(buffer)
|
|
1303
|
+
});
|
|
1304
|
+
if (!response.ok) {
|
|
1305
|
+
const body = await response.text().catch(() => "");
|
|
1306
|
+
throw new Error(body || `Artifact upload failed with ${response.status}.`);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
813
1309
|
function loadEnvFile(envFile) {
|
|
814
1310
|
const resolved = path.resolve(process.cwd(), envFile);
|
|
815
1311
|
if (!existsSync(resolved)) {
|