@vosjs/cli 0.83.0 → 0.83.2
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/README.md +2 -0
- package/dist/{assetManifest-27NKSS7N.js → assetManifest-32VI7OK7.js} +3 -3
- package/dist/{chunk-J3KHIZCH.js → chunk-EPSYIF2S.js} +36 -8
- package/dist/chunk-EPSYIF2S.js.map +1 -0
- package/dist/{chunk-5VGIQKVT.js → chunk-HDJFCTOG.js} +27 -25
- package/dist/chunk-HDJFCTOG.js.map +1 -0
- package/dist/{chunk-352AC3V6.js → chunk-M5ZBQFPG.js} +2 -2
- package/dist/{chunk-B373NVJE.js → chunk-Q47FUCYN.js} +2 -2
- package/dist/cli.js +13 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/{run-CPFCYXVL.js → run-7ZKIV6EU.js} +5 -5
- package/package.json +5 -5
- package/skills/VERSION +1 -1
- package/skills/product-video/SKILL.md +55 -3
- package/skills/product-video/references/how-to.md +7 -0
- package/skills/product-video/references/sessions.md +20 -0
- package/skills/vos-cut/SKILL.md +3 -1
- package/dist/chunk-5VGIQKVT.js.map +0 -1
- package/dist/chunk-J3KHIZCH.js.map +0 -1
- /package/dist/{assetManifest-27NKSS7N.js.map → assetManifest-32VI7OK7.js.map} +0 -0
- /package/dist/{chunk-352AC3V6.js.map → chunk-M5ZBQFPG.js.map} +0 -0
- /package/dist/{chunk-B373NVJE.js.map → chunk-Q47FUCYN.js.map} +0 -0
- /package/dist/{run-CPFCYXVL.js.map → run-7ZKIV6EU.js.map} +0 -0
package/README.md
CHANGED
|
@@ -66,6 +66,8 @@ A program that declares `size: { width, height }` renders at that size with no f
|
|
|
66
66
|
|
|
67
67
|
Configs can be local files or URLs; a platform `{ "config": … }` envelope is unwrapped. Rendering compiles the config with `@vosjs/core`, wraps it in the engine's capture template, and encodes frame by frame (WebCodecs) in headless Chromium. Same input, same video: locally, in CI, or on a server. Every engine verb takes a directory too: a take (its `doc.json` is a recording document) renders through the take pipeline, and a program directory (`config.json`, composed with the program document beside it when there is one) renders as what the studio plays. A deterministic sniff of the document, never a flag.
|
|
68
68
|
|
|
69
|
+
An output path may name folders that do not exist yet (`vos render take out/cuts/demo.mp4`): every verb that writes a file you name makes them, and makes them BEFORE the work, so a folder that cannot be made (a file already at that name, no permission) is said in words before a render starts and nothing is written.
|
|
70
|
+
|
|
69
71
|
## The take pipeline
|
|
70
72
|
|
|
71
73
|
A **take** is a directory: the recording of a scripted browser flow, its exact cursor track, and `doc.json`, the editable cut.
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
localManifestRefs,
|
|
5
5
|
pullManifest,
|
|
6
6
|
uploadManifest
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-M5ZBQFPG.js";
|
|
8
|
+
import "./chunk-EPSYIF2S.js";
|
|
9
9
|
export {
|
|
10
10
|
hostedLiteralWarnings,
|
|
11
11
|
localManifestRefs,
|
|
12
12
|
pullManifest,
|
|
13
13
|
uploadManifest
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=assetManifest-
|
|
15
|
+
//# sourceMappingURL=assetManifest-32VI7OK7.js.map
|
|
@@ -233,8 +233,9 @@ function containerMismatch(filename, head) {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
// src/plugin/safeWrite.ts
|
|
236
|
-
import { lstat, writeFile } from "fs/promises";
|
|
237
|
-
import { lstatSync, writeFileSync } from "fs";
|
|
236
|
+
import { lstat, mkdir, writeFile } from "fs/promises";
|
|
237
|
+
import { lstatSync, mkdirSync, writeFileSync } from "fs";
|
|
238
|
+
import { dirname } from "path";
|
|
238
239
|
async function writeFileSafe(path, data) {
|
|
239
240
|
await refuseSymlink(path);
|
|
240
241
|
await writeFile(path, data);
|
|
@@ -256,6 +257,30 @@ function writeFileSafeSync(path, data) {
|
|
|
256
257
|
if (link) throw new Error(symlinkRefusal(path));
|
|
257
258
|
writeFileSync(path, data);
|
|
258
259
|
}
|
|
260
|
+
async function prepareOutput(path) {
|
|
261
|
+
try {
|
|
262
|
+
await mkdir(dirname(path), { recursive: true });
|
|
263
|
+
} catch (e) {
|
|
264
|
+
throw new Error(outputDirRefusal(path, e));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async function writeOutput(path, data) {
|
|
268
|
+
await prepareOutput(path);
|
|
269
|
+
await writeFile(path, data);
|
|
270
|
+
}
|
|
271
|
+
function writeOutputSync(path, data) {
|
|
272
|
+
try {
|
|
273
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
274
|
+
} catch (e) {
|
|
275
|
+
throw new Error(outputDirRefusal(path, e));
|
|
276
|
+
}
|
|
277
|
+
writeFileSync(path, data);
|
|
278
|
+
}
|
|
279
|
+
function outputDirRefusal(path, e) {
|
|
280
|
+
const code = e.code;
|
|
281
|
+
const why = code === "EEXIST" || code === "ENOTDIR" ? "a file stands where a folder on its path would go" : code === "EACCES" || code === "EPERM" ? "this user may not create it" : e instanceof Error ? e.message : String(e);
|
|
282
|
+
return `cannot make the folder for ${path}: ${why}. Nothing was written.`;
|
|
283
|
+
}
|
|
259
284
|
function symlinkRefusal(path) {
|
|
260
285
|
return `${path} is a symbolic link, and the CLI writes only a regular file there: remove the link and run again`;
|
|
261
286
|
}
|
|
@@ -316,9 +341,9 @@ function hasFlag(flags, name) {
|
|
|
316
341
|
}
|
|
317
342
|
|
|
318
343
|
// src/plugin/platform.ts
|
|
319
|
-
import { mkdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
344
|
+
import { mkdirSync as mkdirSync2, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
320
345
|
import { homedir } from "os";
|
|
321
|
-
import { dirname, join } from "path";
|
|
346
|
+
import { dirname as dirname2, join } from "path";
|
|
322
347
|
|
|
323
348
|
// src/plugin/hostAgent.ts
|
|
324
349
|
import { existsSync } from "fs";
|
|
@@ -459,7 +484,7 @@ function requireCredential(explicit, origin) {
|
|
|
459
484
|
return key;
|
|
460
485
|
}
|
|
461
486
|
function writeCredential(key, origin = DEFAULT_ORIGIN, path = CREDENTIALS_PATH) {
|
|
462
|
-
|
|
487
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
463
488
|
writeFileSync2(path, `${key.trim()}
|
|
464
489
|
origin=${originOf(origin)}
|
|
465
490
|
`, {
|
|
@@ -607,7 +632,7 @@ import { createHash } from "crypto";
|
|
|
607
632
|
import {
|
|
608
633
|
closeSync,
|
|
609
634
|
existsSync as existsSync2,
|
|
610
|
-
mkdirSync as
|
|
635
|
+
mkdirSync as mkdirSync3,
|
|
611
636
|
openSync,
|
|
612
637
|
readSync,
|
|
613
638
|
readdirSync,
|
|
@@ -760,7 +785,7 @@ async function fetchHosted(id, opts) {
|
|
|
760
785
|
);
|
|
761
786
|
return null;
|
|
762
787
|
}
|
|
763
|
-
|
|
788
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
764
789
|
const type = (res.headers.get("content-type") ?? "").split(";")[0].trim();
|
|
765
790
|
const file = join2(dir, `${id}${extensionFor(type)}`);
|
|
766
791
|
const partial = `${file}.part`;
|
|
@@ -888,6 +913,9 @@ export {
|
|
|
888
913
|
writeFileSafe,
|
|
889
914
|
refuseSymlink,
|
|
890
915
|
writeFileSafeSync,
|
|
916
|
+
prepareOutput,
|
|
917
|
+
writeOutput,
|
|
918
|
+
writeOutputSync,
|
|
891
919
|
parseArgs2,
|
|
892
920
|
numFlag2,
|
|
893
921
|
strFlag,
|
|
@@ -919,4 +947,4 @@ export {
|
|
|
919
947
|
programAssets,
|
|
920
948
|
missingManifestFiles
|
|
921
949
|
};
|
|
922
|
-
//# sourceMappingURL=chunk-
|
|
950
|
+
//# sourceMappingURL=chunk-EPSYIF2S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/flagUse.ts","../src/args.ts","../src/plugin/container.ts","../src/plugin/safeWrite.ts","../src/plugin/args.ts","../src/plugin/platform.ts","../src/plugin/hostAgent.ts","../src/programAssets.ts"],"sourcesContent":["/**\n * Which of the flags a person gave did the verb actually READ?\n *\n * The parsers accept any `--name`, so a mistyped or misplaced flag used to be\n * swallowed: `vos frames <take> --at 3,5,8` wrote five evenly spread stills\n * and exited 0, because the flag is `--times` and nothing ever looked at\n * `at`. It looked like it worked.\n *\n * A declared list per verb would be the obvious guard and the wrong one here:\n * several verbs read their options through data (a name table, a helper three\n * calls down), so a list drifts, and the day it drifts it REFUSES a real flag\n * for every agent at once. Reading is the truth, so reading is what is\n * recorded: both parsers hand back their flags behind a proxy that notes each\n * name a verb asks for, and the CLI's one exit point compares that with what\n * was given. It cannot reject a flag a verb uses, by construction.\n *\n * The cost of being certain is that the verdict lands AFTER the verb ran, so\n * the message says so plainly: the command ran, without that flag.\n */\n\nconst given = new Set<string>()\nconst used = new Set<string>()\n\n/** A flag bag that remembers which names were asked for. */\nexport function trackFlags<T extends Record<string, unknown>>(bag: T): T {\n return new Proxy(bag, {\n get(target, key, receiver) {\n if (typeof key === 'string') used.add(key)\n return Reflect.get(target, key, receiver)\n },\n has(target, key) {\n if (typeof key === 'string') used.add(key)\n return Reflect.has(target, key)\n },\n // hasOwnProperty.call(flags, name) lands here.\n getOwnPropertyDescriptor(target, key) {\n if (typeof key === 'string') used.add(key)\n return Reflect.getOwnPropertyDescriptor(target, key)\n },\n // A spread, Object.keys or JSON.stringify hands every flag onward; what\n // happens to them after that cannot be seen, so they all count as read.\n ownKeys(target) {\n for (const key of Reflect.ownKeys(target))\n if (typeof key === 'string') used.add(key)\n return Reflect.ownKeys(target)\n },\n })\n}\n\nexport function noteGivenFlag(name: string): void {\n given.add(name)\n}\n\n/** Flags that were given and never read, in the order they were given. */\nexport function unusedFlags(): string[] {\n return [...given].filter((name) => !used.has(name) && name !== 'help')\n}\n\nexport function resetFlagUse(): void {\n given.clear()\n used.clear()\n}\n\n/**\n * The `--flags` a verb documents: its `vos <verb>` line in a help text plus\n * the indented lines that continue it.\n */\nexport function helpFlagsFor(help: string, verb: string): string[] {\n const out = new Set<string>()\n let inVerb = false\n for (const line of help.split('\\n')) {\n const head = /^\\s{2}vos\\s+(\\S+)/.exec(line)\n if (head) inVerb = head[1] === verb\n else if (!/^\\s{3,}\\S/.test(line)) inVerb = false\n if (!inVerb) continue\n for (const m of line.matchAll(/--([a-z][a-z0-9-]*)/g)) out.add(m[1])\n }\n return [...out]\n}\n\nfunction editDistance(a: string, b: string): number {\n const row = Array.from({ length: b.length + 1 }, (_, i) => i)\n for (let i = 1; i <= a.length; i++) {\n let prev = row[0]\n row[0] = i\n for (let j = 1; j <= b.length; j++) {\n const keep = row[j]\n row[j] = Math.min(\n row[j] + 1,\n row[j - 1] + 1,\n prev + (a[i - 1] === b[j - 1] ? 0 : 1),\n )\n prev = keep\n }\n }\n return row[b.length]\n}\n\n/** The documented flag a mistyped one most likely meant, or null. */\nexport function nearestFlag(name: string, candidates: string[]): string | null {\n let best: string | null = null\n let bestScore = Infinity\n for (const c of candidates) {\n if (c === name) continue\n // A candidate that contains the name (or the reverse) is as close as a\n // one-letter slip: `--zooms` for `--at-zooms`, `--body` for `--body-px`.\n const d = c.includes(name) || name.includes(c) ? 1 : editDistance(name, c)\n if (d < bestScore) {\n bestScore = d\n best = c\n }\n }\n return best !== null && bestScore <= Math.max(2, Math.floor(name.length / 3))\n ? best\n : null\n}\n\n/** The sentence for a run that ignored what it was given, or null when nothing was. */\nexport function unusedFlagsMessage(\n verb: string,\n documented: string[],\n): string | null {\n const unused = unusedFlags()\n if (!unused.length) return null\n const parts = unused.map((name) => {\n const near = nearestFlag(name, documented)\n return `--${name}${near ? ` (did you mean --${near}?)` : ''}`\n })\n const list = documented.length\n ? ` It reads: ${documented.map((f) => `--${f}`).join(' ')}.`\n : ''\n return `vos ${verb} RAN, and ignored ${parts.join(', ')}: ${unused.length > 1 ? 'they are' : 'it is'} not something this verb reads, so what it printed above was made without ${unused.length > 1 ? 'them' : 'it'}.${list}`\n}\n","/**\n * Minimal argv parser — positionals + `--flag value` / `--flag=value` /\n * boolean flags. Deliberately tiny: the CLI has a small, stable surface and\n * agents benefit from predictable, dependency-free parsing.\n */\nimport { noteGivenFlag, trackFlags } from './flagUse'\n\nexport interface ParsedArgs {\n positionals: string[]\n flags: Record<string, string | true>\n}\n\nexport class UsageError extends Error {}\n\nexport function parseArgs(\n argv: string[],\n booleanFlags: ReadonlySet<string>,\n): ParsedArgs {\n const positionals: string[] = []\n const flags: Record<string, string | true> = {}\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]\n if (arg === '--') {\n positionals.push(...argv.slice(i + 1))\n break\n }\n if (arg.startsWith('--')) {\n const eq = arg.indexOf('=')\n if (eq !== -1) {\n flags[arg.slice(2, eq)] = arg.slice(eq + 1)\n continue\n }\n const name = arg.slice(2)\n if (booleanFlags.has(name)) {\n flags[name] = true\n continue\n }\n const next = argv[i + 1]\n if (next === undefined || next.startsWith('--')) {\n throw new UsageError(`--${name} expects a value`)\n }\n flags[name] = next\n i++\n continue\n }\n positionals.push(arg)\n }\n for (const name of Object.keys(flags)) noteGivenFlag(name)\n return { positionals, flags: trackFlags(flags) }\n}\n\nexport function numFlag(\n flags: ParsedArgs['flags'],\n name: string,\n fallback: number,\n): number {\n const v = flags[name]\n if (v === undefined) return fallback\n const n = Number(v)\n if (!Number.isFinite(n))\n throw new UsageError(`--${name} expects a number, got \"${String(v)}\"`)\n return n\n}\n","/**\n * What a media file IS, read from its first bytes.\n *\n * A file's NAME and its Content-Type are both CLAIMS, and both drift from the\n * bytes: the in-page recorder remuxes a take to mp4 while keeping the name\n * `recording.webm`, and a hosted asset keeps whatever name it was uploaded\n * under. Believing a claim is how an mp4 gets uploaded as `video/webm`, and\n * every render of that version then dies inside the video element with a\n * format error — one machine and one day away from the mislabelling that\n * caused it.\n *\n * So the rule is one line: THE BYTES DECIDE. A claim is the fallback only for\n * bytes that say nothing (an SVG, a recipe, an unknown blob), which keeps the\n * override safe — a name is corrected only when the file positively contradicts\n * it, never on a guess.\n */\n\nconst OCTET_STREAM = 'application/octet-stream'\n\n/** The one extension↔type table. */\nconst TYPES_BY_EXTENSION: Record<string, string> = {\n svg: 'image/svg+xml',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n webp: 'image/webp',\n gif: 'image/gif',\n avif: 'image/avif',\n webm: 'video/webm',\n mp4: 'video/mp4',\n mov: 'video/quicktime',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n m4a: 'audio/mp4',\n glb: 'model/gltf-binary',\n}\n\n/** The extension each type is written under, where the table is many-to-one. */\nconst EXTENSION_BY_TYPE: Record<string, string> = {\n 'image/jpeg': '.jpg',\n 'video/mp4': '.mp4',\n 'audio/mp4': '.m4a',\n}\n\n/**\n * Every container a take's own media (footage, mic, cam) can come home in —\n * the name `record` writes first, so a resolver is deterministic when a stale\n * sibling is somehow present.\n */\nexport const TAKE_MEDIA_EXTENSIONS = [\n '.webm',\n '.mp4',\n '.mov',\n '.m4a',\n '.mp3',\n '.ogg',\n '.wav',\n] as const\n\n/** Enough bytes for every signature below (the longest reads 12). */\nexport const MEDIA_HEAD_BYTES = 16\n\n/**\n * ISO base media brands that are NOT plain mp4. Everything else carrying an\n * `ftyp` box (isom, mp42, avc1, iso5, dash, M4V…) is video/mp4.\n */\nconst ISO_BRANDS: Record<string, string> = {\n 'qt ': 'video/quicktime',\n 'M4A ': 'audio/mp4',\n 'M4B ': 'audio/mp4',\n avif: 'image/avif',\n avis: 'image/avif',\n}\n\n/** RIFF forms, read from the four bytes after the size field. */\nconst RIFF_FORMS: Record<string, string> = {\n WEBP: 'image/webp',\n WAVE: 'audio/wav',\n 'AVI ': 'video/x-msvideo',\n}\n\n/** The media type a file's first bytes prove, or null when they prove nothing. */\nexport function sniffMediaType(head: Uint8Array): string | null {\n const ascii = (at: number, len: number): string =>\n head.length >= at + len\n ? String.fromCharCode(...head.subarray(at, at + len))\n : ''\n const startsWith = (...bytes: number[]): boolean =>\n bytes.every((b, i) => head[i] === b)\n\n // EBML: Matroska and its WebM profile. A .mkv sniffs as webm, which is what\n // every consumer here wants — the distinction is a codec constraint, not a\n // container one.\n if (startsWith(0x1a, 0x45, 0xdf, 0xa3)) return 'video/webm'\n if (ascii(4, 4) === 'ftyp') return ISO_BRANDS[ascii(8, 4)] ?? 'video/mp4'\n if (ascii(0, 4) === 'RIFF') return RIFF_FORMS[ascii(8, 4)] ?? null\n if (startsWith(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a))\n return 'image/png'\n if (startsWith(0xff, 0xd8, 0xff)) return 'image/jpeg'\n if (ascii(0, 4) === 'GIF8') return 'image/gif'\n if (ascii(0, 4) === 'OggS') return 'audio/ogg'\n if (ascii(0, 3) === 'ID3') return 'audio/mpeg'\n // Binary glTF: the magic is the four ASCII bytes `glTF`.\n if (ascii(0, 4) === 'glTF') return 'model/gltf-binary'\n return null\n}\n\n/** A Content-Type header reduced to its bare type, or '' when it says nothing. */\nfunction bareType(value: string | null | undefined): string {\n const type = (value ?? '').split(';')[0].trim().toLowerCase()\n // `binary/octet-stream` is a common spelling of the same non-answer.\n return !type || type === OCTET_STREAM || type === 'binary/octet-stream'\n ? ''\n : type\n}\n\n/** The content type a file's NAME claims, by extension. */\nexport function mediaContentType(file: string): string {\n const ext = (/\\.([a-z0-9]+)$/i.exec(file)?.[1] ?? '').toLowerCase()\n return TYPES_BY_EXTENSION[ext] ?? OCTET_STREAM\n}\n\n/** The extension a media type is written under ('' when it has none here). */\nexport function extensionFor(contentType: string): string {\n const type = (contentType ?? '').split(';')[0].trim().toLowerCase()\n if (EXTENSION_BY_TYPE[type]) return EXTENSION_BY_TYPE[type]\n const ext = Object.keys(TYPES_BY_EXTENSION).find(\n (e) => TYPES_BY_EXTENSION[e] === type,\n )\n return ext ? `.${ext}` : ''\n}\n\nexport interface MediaTypeClaims {\n /** The file's first bytes — `MEDIA_HEAD_BYTES` is enough. */\n head?: Uint8Array | null\n /** What a server said it was serving. */\n declared?: string | null\n /** What the name claims. */\n filename?: string | null\n}\n\nexport interface ResolvedMediaType {\n type: string\n /** Which claim won, so a caller can SAY when the bytes overruled a name. */\n from: 'bytes' | 'declared' | 'filename' | 'unknown'\n}\n\n/** The type to believe: the bytes, then the server, then the name. */\nexport function resolveMediaType(claims: MediaTypeClaims): ResolvedMediaType {\n const sniffed = claims.head?.length ? sniffMediaType(claims.head) : null\n if (sniffed) return { type: sniffed, from: 'bytes' }\n const declared = bareType(claims.declared)\n if (declared) return { type: declared, from: 'declared' }\n const named = mediaContentType(claims.filename ?? '')\n if (named !== OCTET_STREAM) return { type: named, from: 'filename' }\n return { type: OCTET_STREAM, from: 'unknown' }\n}\n\n/**\n * The same name wearing the extension its type earns. Unchanged when the two\n * already agree (`.jpeg` is not churned into `.jpg`) or when the type has no\n * extension here, so a correction is always a real one.\n */\nexport function nameForType(filename: string, type: string): string {\n const ext = extensionFor(type)\n if (!ext) return filename\n const current = /\\.[a-z0-9]+$/i.exec(filename)?.[0] ?? ''\n if (current && mediaContentType(`x${current}`) === type) return filename\n return `${filename.slice(0, filename.length - current.length)}${ext}`\n}\n\n/**\n * What to say about a file whose name and bytes disagree, or null when they\n * agree or the bytes prove nothing.\n *\n * Every reader in this CLI now believes the bytes (the take server sniffs, a\n * push declares from them), so a mismatch breaks nothing here — it is still a\n * file lying about itself to every player, editor and person who opens it, and\n * the rename is one move.\n */\nexport function containerMismatch(\n filename: string,\n head: Uint8Array,\n): string | null {\n const actual = sniffMediaType(head)\n if (!actual) return null\n const claimed = mediaContentType(filename)\n if (claimed === actual) return null\n return `${filename} is ${actual}, not the ${claimed} its name claims — rename it to ${nameForType(filename, actual)}`\n}\n","import { lstat, mkdir, writeFile } from 'node:fs/promises'\nimport { lstatSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\n\n/**\n * Write a file the CLI owns into a take or program directory, never\n * through a symbolic link. `writeFile` follows a link already at the path,\n * so a `doc.json` pointing out of the directory would carry the bytes\n * wherever it points; here the path is looked at first and a link is\n * refused in words. A regular file is overwritten as before.\n */\nexport async function writeFileSafe(\n path: string,\n data: string | Uint8Array,\n): Promise<void> {\n await refuseSymlink(path)\n await writeFile(path, data)\n}\n\n/** Throws in words when a symbolic link sits at the path; nothing else. */\nexport async function refuseSymlink(path: string): Promise<void> {\n let link = false\n try {\n link = (await lstat(path)).isSymbolicLink()\n } catch {\n // nothing there yet: a plain write\n }\n if (link) throw new Error(symlinkRefusal(path))\n}\n\n/** The synchronous twin, for the writers that are synchronous. */\nexport function writeFileSafeSync(\n path: string,\n data: string | Uint8Array,\n): void {\n let link = false\n try {\n link = lstatSync(path).isSymbolicLink()\n } catch {\n // nothing there yet\n }\n if (link) throw new Error(symlinkRefusal(path))\n writeFileSync(path, data)\n}\n\n/**\n * Make the folders a path a person named lives in (`vos render take\n * out/demo.mp4`), or throw in words. Called BEFORE the work that produces\n * the bytes: a render takes minutes and its result lives only in memory\n * until it is written, so a folder that is not there yet must not be what\n * loses it, and a folder that cannot be made (a file already at its name,\n * no permission) is said before anything runs.\n */\nexport async function prepareOutput(path: string): Promise<void> {\n try {\n await mkdir(dirname(path), { recursive: true })\n } catch (e) {\n throw new Error(outputDirRefusal(path, e))\n }\n}\n\n/** Write a file a person named, making its folders first. */\nexport async function writeOutput(\n path: string,\n data: string | Uint8Array,\n): Promise<void> {\n await prepareOutput(path)\n await writeFile(path, data)\n}\n\n/** The synchronous twin of `writeOutput`. */\nexport function writeOutputSync(path: string, data: string | Uint8Array): void {\n try {\n mkdirSync(dirname(path), { recursive: true })\n } catch (e) {\n throw new Error(outputDirRefusal(path, e))\n }\n writeFileSync(path, data)\n}\n\nfunction outputDirRefusal(path: string, e: unknown): string {\n const code = (e as { code?: string }).code\n const why =\n code === 'EEXIST' || code === 'ENOTDIR'\n ? 'a file stands where a folder on its path would go'\n : code === 'EACCES' || code === 'EPERM'\n ? 'this user may not create it'\n : e instanceof Error\n ? e.message\n : String(e)\n return `cannot make the folder for ${path}: ${why}. Nothing was written.`\n}\n\nexport function symlinkRefusal(path: string): string {\n return `${path} is a symbolic link, and the CLI writes only a regular file there: remove the link and run again`\n}\n","/** Minimal argv parser — mirrors @vosjs/cli's conventions. */\nimport { noteGivenFlag, trackFlags } from '../flagUse'\nimport { UsageError } from '../args'\n\nexport interface ParsedArgs {\n positionals: string[]\n flags: Record<string, string | true>\n /** Values of flags declared repeatable (multiFlags) — accumulated in order. */\n multi: Record<string, string[]>\n}\n\n// ONE usage error for the whole CLI: a verb that reaches a shared helper\n// (outputs.ts) must be reported as a usage error on either side.\nexport { UsageError }\n\nexport function parseArgs(\n argv: string[],\n booleanFlags: ReadonlySet<string>,\n multiFlags: ReadonlySet<string> = new Set(),\n): ParsedArgs {\n const positionals: string[] = []\n const flags: Record<string, string | true> = {}\n const multi: Record<string, string[]> = {}\n const put = (name: string, value: string): void => {\n if (multiFlags.has(name)) (multi[name] ??= []).push(value)\n else flags[name] = value\n }\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]\n if (arg === '--') {\n positionals.push(...argv.slice(i + 1))\n break\n }\n if (arg.startsWith('--')) {\n const eq = arg.indexOf('=')\n if (eq !== -1) {\n put(arg.slice(2, eq), arg.slice(eq + 1))\n continue\n }\n const name = arg.slice(2)\n if (booleanFlags.has(name)) {\n flags[name] = true\n continue\n }\n if (i + 1 >= argv.length || argv[i + 1].startsWith('--')) {\n throw new UsageError(`--${name} expects a value`)\n }\n put(name, argv[i + 1])\n i++\n continue\n }\n positionals.push(arg)\n }\n for (const name of Object.keys(flags)) noteGivenFlag(name)\n for (const name of Object.keys(multi)) noteGivenFlag(name)\n return { positionals, flags: trackFlags(flags), multi: trackFlags(multi) }\n}\n\nexport function numFlag(\n flags: ParsedArgs['flags'],\n name: string,\n fallback: number,\n): number {\n const v = flags[name]\n if (typeof v !== 'string') return fallback\n const n = Number(v)\n if (!Number.isFinite(n))\n throw new UsageError(`--${name} expects a number, got \"${v}\"`)\n return n\n}\n\n/** String flag value, or undefined when absent (or boolean). */\nexport function strFlag(\n flags: ParsedArgs['flags'],\n name: string,\n): string | undefined {\n const v = flags[name]\n return typeof v === 'string' ? v : undefined\n}\n\nexport function hasFlag(flags: ParsedArgs['flags'], name: string): boolean {\n return Object.prototype.hasOwnProperty.call(flags, name)\n}\n","/**\n * vos.so platform client — THE one HTTP surface of the vos CLI.\n * Every platform verb (fetch/push/pull for programs AND takes, login) goes\n * through here: one origin resolution, one credential ladder, one sync-state\n * file, one 409 conflict shape.\n *\n * Contract notes (mirrored at https://vos.so/llms.txt):\n * - public/unlisted programs read with no auth; writes ride a bearer key\n * - credentials resolve --key → VOS_API_KEY → ~/.config/vos/credentials\n * (first line; `vos login` writes it) and are NEVER printed — not in\n * logs, not in errors, not in NDJSON events\n * - pushed configs travel as the MIGRATED object with params/presets\n * untouched; the platform validates and compiles server-side\n */\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { writeFileSafeSync } from './safeWrite'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { UsageError } from './args'\nimport { detectHostAgent } from './hostAgent'\nimport type { Env } from './hostAgent'\n\n/**\n * Origin resolution: --origin (or legacy --api) → VOS_ORIGIN → legacy\n * VOS_API_BASE (which historically carried a trailing /api) → https://vos.so.\n * Every shape converges on a bare origin; paths below carry the /api prefix.\n */\nexport function platformOrigin(\n flags: { origin?: string; api?: string } = {},\n): string {\n const legacyEnv = process.env.VOS_API_BASE?.trim()\n const raw =\n flags.origin ??\n flags.api ??\n process.env.VOS_ORIGIN?.trim() ??\n legacyEnv ??\n 'https://vos.so'\n if (!flags.origin && !flags.api && !process.env.VOS_ORIGIN && legacyEnv) {\n process.stderr.write(\n 'note: VOS_API_BASE is deprecated — set VOS_ORIGIN (an origin, no /api suffix)\\n',\n )\n }\n return raw.replace(/\\/+$/, '').replace(/\\/api$/, '')\n}\n\n/**\n * Accepts a bare vos id, a watch URL (vos.so/vos/{id}), an embed URL\n * (/embed/vos/{id}), or a studio/stage URL (?vos={id}).\n */\nexport function parseVosId(input: string): string {\n if (!/^https?:\\/\\//.test(input)) {\n if (/^[A-Za-z0-9_-]+$/.test(input)) return input\n throw new UsageError(`\"${input}\" is not a vos id or URL`)\n }\n let url: URL\n try {\n url = new URL(input)\n } catch {\n throw new UsageError(`\"${input}\" is not a valid URL`)\n }\n const query = url.searchParams.get('vos')\n if (query) return query\n const path = url.pathname.match(/\\/vos\\/([A-Za-z0-9_-]+)/)\n if (path) return path[1]\n throw new UsageError(\n `could not find a vos id in ${input} — expected /vos/{id} or ?vos={id}`,\n )\n}\n\nexport function deriveSlug(title: string): string {\n return (\n title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 50)\n .replace(/-+$/, '') || 'remix'\n )\n}\n\nexport const CREDENTIALS_PATH = join(homedir(), '.config', 'vos', 'credentials')\n\n/** The origin a credential stored with none was minted for. */\nexport const DEFAULT_ORIGIN = 'https://vos.so'\n\n/** An address's origin (`https://vos.so` for `https://vos.so/api/x`). */\nexport function originOf(url: string): string {\n try {\n return new URL(url).origin\n } catch {\n return url.replace(/\\/+$/, '')\n }\n}\n\n/**\n * The credential `vos login` stored: the key on the first line (every\n * reader of the file reads that line), then `origin=<the origin it was\n * minted for>`. A file written before the origin line is the default\n * origin's.\n */\nexport function readStoredCredential(\n path = CREDENTIALS_PATH,\n): { key: string; origin: string } | null {\n let text: string\n try {\n text = readFileSync(path, 'utf8')\n } catch {\n return null\n }\n const [first, ...rest] = text.split('\\n')\n const key = first.trim()\n if (!key) return null\n const line = rest.map((l) => l.trim()).find((l) => l.startsWith('origin='))\n const origin = line ? originOf(line.slice('origin='.length).trim()) : ''\n return { key, origin: origin || DEFAULT_ORIGIN }\n}\n\n/** Keys read from the credentials file, and the origin each belongs to. */\nconst storedFor = new Map<string, string>()\nconst warned = new Set<string>()\n\n/**\n * The full documented ladder: explicit --key → VOS_API_KEY → the\n * credential `vos login` stored. A vos_rg_ remix grant is just a key here.\n * Returns null when nothing resolves — callers decide whether auth is needed.\n * A stored key is remembered with its origin: it is only ever SENT there\n * (`bearerFor`).\n */\nexport function resolveCredential(\n explicit?: string,\n path = CREDENTIALS_PATH,\n): string | null {\n const flag = explicit?.trim()\n if (flag) return flag\n const env = process.env.VOS_API_KEY?.trim()\n if (env) return env\n const stored = readStoredCredential(path)\n if (!stored) return null\n storedFor.set(stored.key, stored.origin)\n return stored.key\n}\n\n/**\n * The authorization header for a request to `url`, or none. A key the\n * person handed this command (--key, VOS_API_KEY) goes where the command\n * goes; the stored key goes only to the origin it was minted for, and a\n * request anywhere else is sent without it, once said.\n */\nexport function bearerFor(\n key: string | null | undefined,\n url: string,\n): Record<string, string> {\n if (!key) return {}\n const bound = storedFor.get(key)\n const to = originOf(url)\n if (bound && bound !== to) {\n if (!warned.has(to)) {\n warned.add(to)\n process.stderr.write(\n `note: the credential vos login stored is for ${bound}, so it is not sent to ${to}; for ${to}, run vos login --origin ${to}, or pass --key or VOS_API_KEY\\n`,\n )\n }\n return {}\n }\n return { authorization: `Bearer ${key}` }\n}\n\n/** Where a key for `origin` is minted. */\nexport const mintAt = (origin: string = DEFAULT_ORIGIN): string =>\n `${originOf(origin)}/app/api`\n\nexport function requireCredential(explicit?: string, origin?: string): string {\n const key = resolveCredential(explicit)\n if (!key) {\n throw new Error(\n 'no credential found — pass --key, set VOS_API_KEY, or run `vos login` ' +\n `(mint a content key at ${mintAt(origin ?? platformOrigin())}; a vos_rg_ remix grant works too)`,\n )\n }\n return key\n}\n\n/**\n * `vos login` writes here: 0700 dir, 0600 file, the key on the first line\n * and the origin it was minted for on the next.\n */\nexport function writeCredential(\n key: string,\n origin: string = DEFAULT_ORIGIN,\n path = CREDENTIALS_PATH,\n): string {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 })\n writeFileSync(path, `${key.trim()}\\norigin=${originOf(origin)}\\n`, {\n mode: 0o600,\n })\n return path\n}\n\n/**\n * The self-reported client string stamped onto pushed versions (User-Agent\n * grammar). Display-only on the platform — attribution trust\n * stays with the credential. The ladder: an explicit VOS_CLIENT (e.g.\n * VOS_CLIENT=claude-code/2.1), else the coding agent this CLI was spawned by\n * (`claude-code vos-cli`, read from the environment by `detectHostAgent`),\n * else the transport alone, so history rows name the tool that pushed.\n */\nexport function clientId(\n env: Env = process.env,\n exists?: (path: string) => boolean,\n): string {\n const explicit = env.VOS_CLIENT?.trim()\n if (explicit && explicit.length <= 60 && !/[\\r\\n]/.test(explicit))\n return explicit\n const host = detectHostAgent(env, exists)\n return host ? `${host} vos-cli` : 'vos-cli'\n}\n\n/** A request that never got an answer, in words that name where it went. */\nexport function unreachable(origin: string, e: unknown): string {\n const err = e as { message?: string; cause?: { code?: string } }\n const why = [err?.message, err?.cause?.code].filter(Boolean).join(': ')\n return `could not reach ${origin}${why ? ` (${why})` : ''}; is it the origin you meant? (--origin, or VOS_ORIGIN)`\n}\n\nexport interface ApiResult {\n status: number\n body: Record<string, unknown>\n /** The origin that answered. */\n origin?: string\n}\n\nexport async function apiJson(\n origin: string,\n path: string,\n init: {\n method?: string\n key?: string | null\n body?: unknown\n /** Raw request body (uploads) — used verbatim, with `headers`. */\n raw?: Uint8Array\n headers?: Record<string, string>\n } = {},\n): Promise<ApiResult> {\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...init.headers,\n }\n Object.assign(headers, bearerFor(init.key, origin))\n if (init.body !== undefined) headers['content-type'] = 'application/json'\n const reqBody: BodyInit | undefined =\n init.raw !== undefined\n ? (init.raw as unknown as BodyInit)\n : init.body === undefined\n ? undefined\n : JSON.stringify(init.body)\n let res: Response\n try {\n res = await fetch(`${origin}${path}`, {\n method: init.method ?? 'GET',\n headers,\n body: reqBody,\n })\n } catch (e) {\n throw new Error(unreachable(origin, e))\n }\n let body: Record<string, unknown> = {}\n try {\n body = (await res.json()) as Record<string, unknown>\n } catch {\n // non-JSON error bodies stay {}\n }\n return { status: res.status, body, origin }\n}\n\n/**\n * A refusal's issue list (`details: [{ path, message }]`, the shape every\n * vos.so route answers a failed schema with), one indented line per issue.\n * Empty when the body carries none.\n */\nexport function detailLine(body: Record<string, unknown>): string {\n const details = body.details\n if (!Array.isArray(details) || !details.length) return ''\n const lines = (details as Record<string, unknown>[]).map((d) => {\n const path = Array.isArray(d.path) ? d.path.join('.') : ''\n return `${path ? `${path}: ` : ''}${String(d.message ?? JSON.stringify(d))}`\n })\n return `\\n ${lines.join('\\n ')}`\n}\n\n/**\n * Human-readable error line for a failed platform response, with the\n * issues behind a generic `error` (\"Invalid input\") on the lines below it,\n * because the generic word alone names nothing to fix. Never echoes\n * credentials.\n */\nexport function apiError(what: string, r: ApiResult): string {\n const detail =\n typeof r.body.error === 'string'\n ? r.body.error + detailLine(r.body)\n : r.body.details !== undefined\n ? JSON.stringify(r.body.details)\n : ''\n const hint =\n r.status === 401\n ? ` (run \\`vos login\\`, or set VOS_API_KEY — mint a key at ${mintAt(r.origin)})`\n : ''\n return `${what} → ${r.status}${detail ? `: ${detail}` : ''}${hint}`\n}\n\n/**\n * The next step a push without `--prompt` prints: the prompt that made a\n * vos is shown on its watch page by default, in the person's own words.\n * An agent reads a command's output and acts on it, so the push says the\n * command outright. The vos lands private, so its owner sees the prompt\n * before anyone else can.\n */\nexport function promptHint(target: string, vosId: string): string {\n return `vos push ${target} --vos ${vosId} --prompt \"<the person's prompt, as they wrote it>\"`\n}\n\n// ---------------------------------------------------------------------------\n// Sync state — ONE file (vos.json) for both artifact kinds, legacy-read\n// compatible with the two files it replaces: push.json (take dirs) and\n// meta.json (fetched program dirs).\n// ---------------------------------------------------------------------------\n\nexport const SYNC_STATE_NAME = 'vos.json'\n\nexport interface SyncState {\n vosId: string\n /** The hosted version this directory is based on — the next push's base. */\n versionId: string | null\n pushedAt?: string\n title?: string\n slug?: string\n remixOfId?: string\n /**\n * The files `vos fetch --media` brought home, by their path in the\n * directory: the hosted address each came from and its sha256 then. A\n * claimable push of the take names these originals instead of uploading,\n * and only while the bytes are unchanged.\n */\n hostedMedia?: Record<string, { ref: string; sha256: string }>\n}\n\n/** The `hostedMedia` map, read defensively (a hand-edited vos.json). */\nfunction hostedMediaOf(\n value: unknown,\n): Record<string, { ref: string; sha256: string }> | undefined {\n if (!value || typeof value !== 'object') return undefined\n const out: Record<string, { ref: string; sha256: string }> = {}\n for (const [file, entry] of Object.entries(value)) {\n const e = entry as { ref?: unknown; sha256?: unknown } | null\n if (e && typeof e.ref === 'string' && typeof e.sha256 === 'string')\n out[file] = { ref: e.ref, sha256: e.sha256 }\n }\n return Object.keys(out).length ? out : undefined\n}\n\nfunction readJsonFile(file: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(file, 'utf8')) as Record<string, unknown>\n } catch {\n return null\n }\n}\n\n/**\n * vos.json → legacy push.json ({vosId, versionId}) → legacy meta.json\n * ({id, currentVersionId} — guarded on a string `id` so a take dir's\n * RecordingMeta meta.json is never misread as sync state).\n */\nexport function readSyncState(dir: string): SyncState | null {\n const own = readJsonFile(join(dir, SYNC_STATE_NAME))\n if (own && typeof own.vosId === 'string') {\n return {\n vosId: own.vosId,\n versionId: typeof own.versionId === 'string' ? own.versionId : null,\n ...(typeof own.pushedAt === 'string' ? { pushedAt: own.pushedAt } : {}),\n ...(typeof own.title === 'string' ? { title: own.title } : {}),\n ...(typeof own.slug === 'string' ? { slug: own.slug } : {}),\n ...(typeof own.remixOfId === 'string'\n ? { remixOfId: own.remixOfId }\n : {}),\n ...(hostedMediaOf(own.hostedMedia)\n ? { hostedMedia: hostedMediaOf(own.hostedMedia) }\n : {}),\n }\n }\n const push = readJsonFile(join(dir, 'push.json'))\n if (push && typeof push.vosId === 'string') {\n return {\n vosId: push.vosId,\n versionId: typeof push.versionId === 'string' ? push.versionId : null,\n ...(typeof push.pushedAt === 'string' ? { pushedAt: push.pushedAt } : {}),\n }\n }\n const meta = readJsonFile(join(dir, 'meta.json'))\n if (meta && typeof meta.id === 'string') {\n return {\n vosId: meta.id,\n versionId:\n typeof meta.currentVersionId === 'string'\n ? meta.currentVersionId\n : null,\n ...(typeof meta.title === 'string' ? { title: meta.title } : {}),\n ...(typeof meta.slug === 'string' ? { slug: meta.slug } : {}),\n ...(typeof meta.remixOfId === 'string'\n ? { remixOfId: meta.remixOfId }\n : {}),\n }\n }\n return null\n}\n\n/** Merge-writes vos.json; the legacy files are left alone (read-only compat). */\nexport function writeSyncState(\n dir: string,\n patch: Partial<SyncState> & { vosId: string },\n): SyncState {\n const merged = {\n ...(readSyncState(dir) ?? { versionId: null }),\n ...patch,\n } as SyncState\n writeFileSafeSync(\n join(dir, SYNC_STATE_NAME),\n `${JSON.stringify(merged, null, 2)}\\n`,\n )\n return merged\n}\n\n// ---------------------------------------------------------------------------\n// The /changes payload (shape mirrored from the platform)\n// ---------------------------------------------------------------------------\n\nexport interface VersionChange {\n versionId?: string\n versionNumber?: number\n origin?: string\n label?: string | null\n note?: string | null\n summary?: string\n}\n\n/** Human lines for a changes walk — origin/label attributed, note indented. */\nexport function formatChanges(changes: readonly VersionChange[]): string[] {\n const lines: string[] = []\n for (const ch of changes) {\n const label = ch.label ? ` · ${ch.label}` : ''\n const who = ch.origin === 'studio' ? 'human' : (ch.origin ?? 'unknown')\n lines.push(\n `v${String(ch.versionNumber ?? '?')} (${who}${label}): ${ch.summary ?? ''}`,\n )\n if (ch.note) lines.push(` note: ${ch.note}`)\n }\n return lines\n}\n\n/**\n * The warnings a write came back with (a knob or Look the platform dropped),\n * one line each. A push that saved is not a push that kept everything.\n */\nexport function serverWarnings(\n body: Record<string, unknown>,\n log: (line: string) => void,\n): void {\n const warnings = Array.isArray(body.warnings) ? body.warnings : []\n for (const w of warnings) if (typeof w === 'string') log(`warning ${w}`)\n}\n","import { existsSync } from 'node:fs'\n\n/**\n * Which coding agent is driving this CLI, read from the environment the agent\n * spawned it in. Used ONLY to name the tool on a pushed version (`clientId`),\n * which the platform treats as display-only: attribution trust stays with the\n * credential, so a wrong or spoofed answer changes a label and nothing else.\n *\n * The signals follow `@vercel/detect-agent` (Apache-2.0), kept as a small\n * synchronous table because every push reads it: the cross-tool `AI_AGENT`\n * convention first, then each host's own marker. Returns a lowercase slug,\n * or null when nothing says an agent is here.\n */\nexport type Env = Record<string, string | undefined>\n\nconst SLUG = /^[a-z0-9][a-z0-9.-]{0,39}$/\n\n/** The markers each host sets in the shells it runs, in precedence order. */\nconst MARKERS: Array<[slug: string, test: (env: Env) => boolean]> = [\n ['cursor', (e) => !!e.CURSOR_TRACE_ID],\n [\n 'cursor-cli',\n (e) => !!e.CURSOR_AGENT || e.CURSOR_EXTENSION_HOST_ROLE === 'agent-exec',\n ],\n ['gemini-cli', (e) => !!e.GEMINI_CLI],\n ['codex', (e) => !!(e.CODEX_SANDBOX || e.CODEX_CI || e.CODEX_THREAD_ID)],\n ['antigravity', (e) => !!e.ANTIGRAVITY_AGENT],\n ['augment-cli', (e) => !!e.AUGMENT_AGENT],\n ['opencode', (e) => !!e.OPENCODE_CLIENT],\n [\n 'claude-code',\n (e) => !!(e.CLAUDECODE || e.CLAUDE_CODE) && !e.CLAUDE_CODE_IS_COWORK,\n ],\n ['claude-cowork', (e) => !!(e.CLAUDECODE || e.CLAUDE_CODE)],\n ['replit', (e) => !!e.REPL_ID],\n [\n 'github-copilot',\n (e) => !!(e.COPILOT_MODEL || e.COPILOT_ALLOW_ALL || e.COPILOT_GITHUB_TOKEN),\n ],\n]\n\nconst DEVIN_LOCAL_PATH = '/opt/.devin'\n\n/**\n * `AI_AGENT` is free text by convention (`claude-code_2-1-284_agent`,\n * `github-copilot`, `v0`): the tool's name is its leading run of\n * `[a-z0-9.-]`, lowercased, so a version or a role suffix never reaches the\n * label and nothing but a short slug ever leaves the machine.\n */\nexport function slugFromAiAgent(value: string): string | null {\n const head = value.trim().toLowerCase().split('_')[0] ?? ''\n if (head === 'github-copilot-cli') return 'github-copilot'\n return SLUG.test(head) ? head : null\n}\n\nexport function detectHostAgent(\n env: Env = process.env,\n exists: (path: string) => boolean = existsSync,\n): string | null {\n if (env.AI_AGENT) {\n const slug = slugFromAiAgent(env.AI_AGENT)\n if (slug) return slug\n }\n for (const [slug, test] of MARKERS) if (test(env)) return slug\n try {\n if (exists(DEVIN_LOCAL_PATH)) return 'devin'\n } catch {\n // An unreadable path is not an agent.\n }\n return null\n}\n","/**\n * The files a program declares (`config.assets`), for a LOCAL run of it.\n *\n * A capture page has an origin of its own, so a manifest entry that names a\n * file beside the config (`./logo.png`) or a hosted one (`asset:<id>`)\n * cannot be fetched from inside it as written. Each is made reachable here\n * and handed to the engine as the page's `ctx.assets`:\n *\n * - a local file is SERVED to the page from disk, under a path on the\n * page's own origin, so a video is streamed and never inlined;\n * - a hosted asset is downloaded once with the caller's credential into a\n * cache directory and served the same way;\n * - a URL is used as it is.\n *\n * A file that cannot be reached keeps its ref and is said, so the render\n * shows a missing picture with a reason instead of a silent blank.\n */\nimport { createHash } from 'node:crypto'\nimport {\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readSync,\n readdirSync,\n realpathSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { homedir } from 'node:os'\nimport { extname, join, resolve, sep } from 'node:path'\nimport { extensionFor } from './plugin/container'\nimport { bearerFor } from './plugin/platform'\n\n/** Where served files live on a page's own origin. */\nexport const ASSET_ROUTE = '/__assets/'\n\nexport interface ProgramAssetsOptions {\n /**\n * The program's directory: where the manifest's paths are read, and the\n * only place they may reach. Null for a config loaded from a URL, which\n * has no directory and reads no local file.\n */\n baseDir: string | null\n /** For a hosted ref: where it lives and who may read it. */\n origin?: string\n key?: string | null\n log: (line: string) => void\n /**\n * Where hosted files are kept between runs. Default `~/.cache/vos/assets`,\n * private to the user: a shared temp directory would leave a private\n * file readable by everyone else on the machine.\n */\n cacheDir?: string\n}\n\nexport interface ProgramAssets {\n /** Name → the URL (or URLs) the page reads as `ctx.assets.<name>`. */\n assets: Record<string, string | string[]>\n /** Served path (`/__assets/…`) → the file on disk behind it. */\n files: Record<string, string>\n}\n\nconst UUID = '[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}'\nconst HOSTED_URI = new RegExp(`^asset:(${UUID})$`)\nconst HOSTED_FILE = new RegExp(\n `^(https?://[^/?#]+)?/api/assets/(${UUID})/file(?:[?#].*)?$`,\n)\n\n/**\n * The hosted asset id a ref names, or null: `asset:<id>`, the app-relative\n * file path, or that path on one of `homeOrigins`. The same path on any\n * other host is someone else's URL and is left a URL: reading it as a\n * hosted file would name an asset that does not exist.\n */\nexport function hostedAssetId(\n ref: string,\n homeOrigins: readonly string[] = [],\n): string | null {\n const uri = HOSTED_URI.exec(ref)\n if (uri) return uri[1]\n const file = HOSTED_FILE.exec(ref)\n if (!file) return null\n return file[1] === undefined || homeOrigins.includes(file[1]) ? file[2] : null\n}\n\n/** A manifest name: an identifier, as the engine's schema holds it. */\nconst ASSET_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/\n\n/** The type a served file wears, by extension (never by its bytes here). */\nconst SERVED_TYPES: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.webp': 'image/webp',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.avif': 'image/avif',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.ogg': 'audio/ogg',\n '.wav': 'audio/wav',\n '.m4a': 'audio/mp4',\n '.glb': 'model/gltf-binary',\n '.gltf': 'model/gltf+json',\n '.woff2': 'font/woff2',\n '.woff': 'font/woff',\n '.ttf': 'font/ttf',\n '.otf': 'font/otf',\n '.json': 'application/json',\n}\n\nexport interface ServedBytes {\n status: 200 | 206 | 416\n headers: Record<string, string>\n body: Buffer\n}\n\n/**\n * A declared file as an HTTP answer, honouring `Range`. A video element\n * seeks by range and hangs forever against a server that answers only\n * 200, so both the render page's route and the preview server answer\n * through here.\n */\nexport function serveFile(file: string, range?: string | null): ServedBytes {\n const size = statSync(file).size\n const type =\n SERVED_TYPES[extname(file).toLowerCase()] ?? 'application/octet-stream'\n const base = { 'content-type': type, 'accept-ranges': 'bytes' }\n const read = (start: number, end: number): Buffer => {\n const body = Buffer.alloc(Math.max(0, end - start + 1))\n const fd = openSync(file, 'r')\n try {\n readSync(fd, body, 0, body.length, start)\n } finally {\n closeSync(fd)\n }\n return body\n }\n const m = range ? /^bytes=(\\d*)-(\\d*)$/.exec(range.trim()) : null\n if (!m || (m[1] === '' && m[2] === '')) {\n return {\n status: 200,\n headers: { ...base, 'content-length': String(size) },\n body: read(0, size - 1),\n }\n }\n // `bytes=-N` is the last N bytes; `bytes=A-` runs to the end.\n const start = m[1] === '' ? Math.max(0, size - Number(m[2])) : Number(m[1])\n const end =\n m[1] === '' || m[2] === '' ? size - 1 : Math.min(Number(m[2]), size - 1)\n if (start >= size || start > end) {\n return {\n status: 416,\n headers: { ...base, 'content-range': `bytes */${size}` },\n body: Buffer.alloc(0),\n }\n }\n return {\n status: 206,\n headers: {\n ...base,\n 'content-range': `bytes ${start}-${end}/${size}`,\n 'content-length': String(end - start + 1),\n },\n body: read(start, end),\n }\n}\n\n/**\n * The file a manifest path names, when it is the program's to read.\n *\n * A program's functions run in a page, and whatever the page is served the\n * program can read and send anywhere. So a path is honoured only inside the\n * program's own directory (links resolved): a config from somewhere else\n * cannot name a key file or a `.env` two directories up and have a render\n * or a push carry it out. The cost is that a shared file has to be copied\n * (or the config moved up); the alternative is every config being able to\n * read the disk of whoever renders it.\n */\nexport function localFile(\n ref: string,\n baseDir: string | null,\n): { file: string } | { refused: string } {\n if (baseDir === null) {\n return {\n refused:\n 'a config loaded from a URL has no directory, so it reads no local file',\n }\n }\n const file = resolve(baseDir, ref)\n if (!existsSync(file) || !statSync(file).isFile()) {\n return { refused: 'which is not a file beside the config' }\n }\n const root = realpathSync(baseDir)\n const real = realpathSync(file)\n if (!real.startsWith(root + sep)) {\n return {\n refused: `which is outside the program's directory (${root}). A program reads only files in its own directory or below: copy the file there`,\n }\n }\n return { file: real }\n}\n\n/** A ref the page can fetch as written. */\nfunction isUrl(ref: string): boolean {\n return /^(https?:|data:|blob:)/.test(ref)\n}\n\nfunction manifestOf(\n config: Record<string, unknown>,\n): Record<string, { ref: string | string[] }> | null {\n const assets = config.assets\n if (!assets || typeof assets !== 'object' || Array.isArray(assets))\n return null\n return Object.keys(assets).length > 0\n ? (assets as Record<string, { ref: string | string[] }>)\n : null\n}\n\n/** Every ref of a manifest, in declaration order, with where it sits. */\nexport function manifestRefs(\n config: Record<string, unknown>,\n): { name: string; index: number | null; ref: string }[] {\n const out: { name: string; index: number | null; ref: string }[] = []\n for (const [name, decl] of Object.entries(manifestOf(config) ?? {})) {\n // A name becomes a file name when the manifest's files come home, so\n // it is held to the engine's rule HERE, for a config that reached this\n // machine without passing a schema (a fetched document's own config).\n if (!ASSET_NAME.test(name) || !decl || typeof decl !== 'object') continue\n if (Array.isArray(decl.ref)) {\n decl.ref.forEach((ref, index) => {\n if (typeof ref === 'string') out.push({ name, index, ref })\n })\n } else if (typeof decl.ref === 'string') {\n out.push({ name, index: null, ref: decl.ref })\n }\n }\n return out\n}\n\nasync function fetchHosted(\n id: string,\n opts: ProgramAssetsOptions,\n): Promise<string | null> {\n const dir = opts.cacheDir ?? join(homedir(), '.cache', 'vos', 'assets')\n // A hosted file is immutable, so a finished copy is good forever. Only a\n // finished one: a download lands under `.part` and is renamed whole.\n const cached = existsSync(dir)\n ? readdirSync(dir).find(\n (f) => (f === id || f.startsWith(`${id}.`)) && !f.endsWith('.part'),\n )\n : undefined\n if (cached) return join(dir, cached)\n if (!opts.origin || !opts.key) {\n opts.log(\n `note: asset ${id} is hosted and no credential is set, so the render cannot load it (vos login, or keep the file beside the config and name its path)`,\n )\n return null\n }\n const res = await fetch(`${opts.origin}/api/assets/${id}/file`, {\n headers: bearerFor(opts.key, opts.origin),\n })\n if (!res.ok) {\n opts.log(\n `note: asset ${id} could not be read (${res.status}), so the render cannot load it`,\n )\n return null\n }\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n // The served type names the extension, so the page is told what it got.\n const type = (res.headers.get('content-type') ?? '').split(';')[0].trim()\n const file = join(dir, `${id}${extensionFor(type)}`)\n const partial = `${file}.part`\n try {\n writeFileSync(partial, new Uint8Array(await res.arrayBuffer()), {\n mode: 0o600,\n })\n renameSync(partial, file)\n } finally {\n rmSync(partial, { force: true })\n }\n return file\n}\n\n/**\n * The faces an HTML layer brings (`fonts` on the document, lowered into the\n * studio entry as `html.faces`), as refs a caller can re-point. The page\n * fetches each `url` itself, so a path is resolved against the page.\n */\nfunction htmlFaceRefs(config: Record<string, unknown>): {\n where: string\n url: string\n set: (next: string) => void\n drop: () => void\n}[] {\n const out: ReturnType<typeof htmlFaceRefs> = []\n const stack = Array.isArray(config.stack) ? config.stack : []\n for (const entry of stack as Record<string, unknown>[]) {\n const data = entry?.data as Record<string, unknown> | undefined\n const overlays = Array.isArray(data?.overlays) ? data.overlays : []\n for (const clip of overlays as Record<string, unknown>[]) {\n const html = clip?.html as Record<string, unknown> | undefined\n const faces = Array.isArray(html?.faces) ? html.faces : []\n for (const face of faces as Record<string, unknown>[]) {\n if (typeof face?.url !== 'string' || !face.url) continue\n out.push({\n where: `overlay ${String(clip.id)} font ${String(face.family)}`,\n url: face.url,\n set: (next) => {\n face.url = next\n },\n drop: () => {\n const at = faces.indexOf(face)\n if (at >= 0) faces.splice(at, 1)\n },\n })\n }\n }\n }\n return out\n}\n\n/** The one host a page fetches a face or an image from by URL. */\nconst FACE_HOST = /^https:\\/\\/assets\\.vos\\.so\\//\n\n/**\n * Make every declared file reachable for a local page: the manifest's, and\n * the faces an HTML layer brings from beside its document (re-pointed in\n * place, since the page fetches a face by its url). Null when there is\n * none, so a caller can leave the engine's defaults alone.\n */\nexport async function programAssets(\n config: Record<string, unknown>,\n opts: ProgramAssetsOptions,\n): Promise<ProgramAssets | null> {\n const refs = manifestRefs(config)\n const faces: ReturnType<typeof htmlFaceRefs> = []\n for (const f of htmlFaceRefs(config)) {\n const hosted = hostedAssetId(f.url, opts.origin ? [opts.origin] : [])\n if (!isUrl(f.url) || hosted) {\n faces.push(f)\n } else if (!FACE_HOST.test(f.url)) {\n // A face is fetched by the page and inlined, like its images, so it\n // is held to the same host; one on another host is dropped and said.\n opts.log(\n `note: ${f.where} names ${f.url}, which is not on https://assets.vos.so, so the render does not fetch it (a face comes from the hosted catalog, a hosted file, or a .woff2 beside the document)`,\n )\n f.drop()\n }\n }\n if (refs.length === 0 && faces.length === 0) return null\n const files: Record<string, string> = {}\n const served = new Map<string, string>()\n const serve = (file: string): string => {\n const known = served.get(file)\n if (known) return known\n // The path is a digest of the file's location plus its extension, and\n // never its name: a space or an accent in a name is percent-encoded in\n // the URL the page asks for and would miss a table keyed by the name.\n const tag = createHash('sha256').update(file).digest('hex').slice(0, 16)\n const ext = extname(file)\n const path = `${ASSET_ROUTE}${tag}${/^\\.[A-Za-z0-9]+$/.test(ext) ? ext.toLowerCase() : ''}`\n files[path] = file\n served.set(file, path)\n return path\n }\n\n const reach = async (ref: string, where: string): Promise<string> => {\n // A hosted file first, in any spelling: its absolute URL is a URL too,\n // but a private one answers only to the key, never to the page.\n const hosted = hostedAssetId(ref, opts.origin ? [opts.origin] : [])\n if (hosted) {\n const file = await fetchHosted(hosted, opts)\n return file ? serve(file) : ref\n }\n if (isUrl(ref)) return ref\n const local = localFile(ref, opts.baseDir)\n if ('refused' in local) {\n opts.log(\n `note: ${where} names ${ref}, ${local.refused}, so the render cannot load it`,\n )\n return ref\n }\n return serve(local.file)\n }\n\n for (const face of faces) face.set(await reach(face.url, face.where))\n\n const assets: Record<string, string | string[]> = {}\n for (const { name, index, ref } of refs) {\n const url = await reach(\n ref,\n index === null ? `assets.${name}` : `assets.${name}[${index}]`,\n )\n if (index === null) assets[name] = url\n else {\n const list = (assets[name] ??= []) as string[]\n list[index] = url\n }\n }\n return { assets, files }\n}\n\n/**\n * The manifest entries that name a file which is not there, for a check\n * that knows where the config lives. Hosted refs and URLs are not files.\n */\nexport function missingManifestFiles(\n config: Record<string, unknown>,\n baseDir: string,\n): string[] {\n const out: string[] = []\n for (const { name, index, ref } of manifestRefs(config)) {\n if (isUrl(ref) || hostedAssetId(ref)) continue\n const local = localFile(ref, baseDir)\n if ('file' in local) continue\n const where = index === null ? `assets.${name}` : `assets.${name}[${index}]`\n out.push(`${where} names ${ref}, ${local.refused}`)\n }\n return out\n}\n"],"mappings":"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","names":["parseArgs","numFlag","mkdirSync","writeFileSync","dirname","mkdirSync","dirname","writeFileSync","existsSync","mkdirSync","writeFileSync","homedir","join","start","end","existsSync","join","homedir","mkdirSync","writeFileSync"]}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
reencodeStill,
|
|
11
11
|
renderStill,
|
|
12
12
|
videoFormat
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-Q47FUCYN.js";
|
|
14
14
|
import {
|
|
15
15
|
PREV_DOC_NAME,
|
|
16
16
|
PasteFileRefusal,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
uploadDocRefs,
|
|
47
47
|
uploadManifest,
|
|
48
48
|
writeJson
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-M5ZBQFPG.js";
|
|
50
50
|
import {
|
|
51
51
|
CREDENTIALS_PATH,
|
|
52
52
|
MEDIA_HEAD_BYTES,
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
parseArgs2 as parseArgs,
|
|
71
71
|
parseVosId,
|
|
72
72
|
platformOrigin,
|
|
73
|
+
prepareOutput,
|
|
73
74
|
programAssets,
|
|
74
75
|
promptHint,
|
|
75
76
|
readSyncState,
|
|
@@ -82,8 +83,10 @@ import {
|
|
|
82
83
|
strFlag,
|
|
83
84
|
writeCredential,
|
|
84
85
|
writeFileSafe,
|
|
86
|
+
writeOutput,
|
|
87
|
+
writeOutputSync,
|
|
85
88
|
writeSyncState
|
|
86
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-EPSYIF2S.js";
|
|
87
90
|
import {
|
|
88
91
|
deadLine,
|
|
89
92
|
deadWarns
|
|
@@ -4017,7 +4020,7 @@ async function writeIndexJson(result) {
|
|
|
4017
4020
|
}
|
|
4018
4021
|
|
|
4019
4022
|
// src/plugin/deliver.ts
|
|
4020
|
-
import { mkdir as mkdir3, writeFile as
|
|
4023
|
+
import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
|
|
4021
4024
|
import { join as join4, relative, resolve as resolve4 } from "path";
|
|
4022
4025
|
import { existsSync as existsSync4 } from "fs";
|
|
4023
4026
|
import { readFile as readFile4 } from "fs/promises";
|
|
@@ -4034,7 +4037,6 @@ import {
|
|
|
4034
4037
|
} from "@vosjs/studio-core";
|
|
4035
4038
|
|
|
4036
4039
|
// src/plugin/renderTake.ts
|
|
4037
|
-
import { writeFile as writeFile4 } from "fs/promises";
|
|
4038
4040
|
import { compileVosConfig as compileVosConfig2 } from "@vosjs/core";
|
|
4039
4041
|
import {
|
|
4040
4042
|
audioProducerCode,
|
|
@@ -4051,6 +4053,7 @@ async function renderTake(browser, dir, outFile, opts) {
|
|
|
4051
4053
|
const take = await loadTake(dir);
|
|
4052
4054
|
if (!take.doc) throw new Error(`${dir} has no doc.json \u2014 run plan first`);
|
|
4053
4055
|
const doc = take.doc;
|
|
4056
|
+
await prepareOutput(outFile);
|
|
4054
4057
|
if (opts.overrides && hasOverrides(opts.overrides)) {
|
|
4055
4058
|
await resolveBackdropSlug(opts.overrides);
|
|
4056
4059
|
applyAndValidate(doc, opts.overrides);
|
|
@@ -4123,7 +4126,7 @@ async function renderTake(browser, dir, outFile, opts) {
|
|
|
4123
4126
|
} : void 0,
|
|
4124
4127
|
onProgress: opts.onProgress
|
|
4125
4128
|
});
|
|
4126
|
-
await
|
|
4129
|
+
await writeOutput(outFile, result.bytes);
|
|
4127
4130
|
return {
|
|
4128
4131
|
out: outFile,
|
|
4129
4132
|
bytes: result.bytes.length,
|
|
@@ -4820,7 +4823,7 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4820
4823
|
assets
|
|
4821
4824
|
};
|
|
4822
4825
|
const kitFile = join4(outDir, "kit.json");
|
|
4823
|
-
await
|
|
4826
|
+
await writeFile4(kitFile, JSON.stringify(kit, null, 2));
|
|
4824
4827
|
return { kit, kitFile, outDir };
|
|
4825
4828
|
}
|
|
4826
4829
|
|
|
@@ -4968,7 +4971,7 @@ async function handoffLogin(url, r, opts = {}) {
|
|
|
4968
4971
|
}
|
|
4969
4972
|
|
|
4970
4973
|
// src/plugin/markAsset.ts
|
|
4971
|
-
import { mkdir as mkdir4, readFile as readFile5, writeFile as
|
|
4974
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
4972
4975
|
import { existsSync as existsSync5 } from "fs";
|
|
4973
4976
|
import { isAbsolute, join as join5, resolve as resolve5 } from "path";
|
|
4974
4977
|
function markExtension(url) {
|
|
@@ -5069,7 +5072,7 @@ async function fetchBrandMarks(takeDir, roles) {
|
|
|
5069
5072
|
return null;
|
|
5070
5073
|
}
|
|
5071
5074
|
await mkdir4(join5(takeDir, "brand"), { recursive: true });
|
|
5072
|
-
await
|
|
5075
|
+
await writeFile5(join5(takeDir, "brand", `${name}.${ext2}`), bytes);
|
|
5073
5076
|
return { key: `/brand/${name}.${ext2}`, aspect };
|
|
5074
5077
|
};
|
|
5075
5078
|
out.light = await one("logoUrl", "mark");
|
|
@@ -7417,7 +7420,7 @@ import { lowerToComposition as lowerToComposition3, migrateHostedDoc as migrateH
|
|
|
7417
7420
|
|
|
7418
7421
|
// src/plugin/takeScript.ts
|
|
7419
7422
|
import { existsSync as existsSync12 } from "fs";
|
|
7420
|
-
import { readFile as readFile10, writeFile as
|
|
7423
|
+
import { readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
|
|
7421
7424
|
import { readFileSync as readFileSync2 } from "fs";
|
|
7422
7425
|
import { basename, join as join12 } from "path";
|
|
7423
7426
|
function scriptFromText(text) {
|
|
@@ -7478,7 +7481,7 @@ async function writeScriptBeside(dir, doc) {
|
|
|
7478
7481
|
const path = join12(dir, "actions.json");
|
|
7479
7482
|
const text = scriptToWrite(doc, existsSync12(path));
|
|
7480
7483
|
if (text === null) return false;
|
|
7481
|
-
await
|
|
7484
|
+
await writeFile6(path, text, "utf8");
|
|
7482
7485
|
return true;
|
|
7483
7486
|
}
|
|
7484
7487
|
async function readScript(dir) {
|
|
@@ -10335,7 +10338,7 @@ async function cmdBuild(argv) {
|
|
|
10335
10338
|
const out = resolve8(
|
|
10336
10339
|
strFlag(flags, "out") ?? join17(dirname3(file), "config.json")
|
|
10337
10340
|
);
|
|
10338
|
-
|
|
10341
|
+
writeOutputSync(out, JSON.stringify(built.config, null, 2) + "\n");
|
|
10339
10342
|
const sidecar = out.replace(/\.json$/, "") + ".sources.json";
|
|
10340
10343
|
writeFileSync2(sidecar, JSON.stringify(built.sources, null, 2) + "\n");
|
|
10341
10344
|
for (const [fn, at2] of Object.entries(built.sources)) {
|
|
@@ -12153,7 +12156,6 @@ async function cmdRecipe(argv) {
|
|
|
12153
12156
|
}
|
|
12154
12157
|
|
|
12155
12158
|
// src/plugin/brand.ts
|
|
12156
|
-
import { writeFile as writeFile8 } from "fs/promises";
|
|
12157
12159
|
import { resolve as resolve13 } from "path";
|
|
12158
12160
|
import { parseFrontmatter as parseFrontmatter2 } from "@vosjs/shared/frontmatter";
|
|
12159
12161
|
import { lookKindForGround } from "@vosjs/studio-core";
|
|
@@ -12476,6 +12478,7 @@ async function cmdBrand(argv) {
|
|
|
12476
12478
|
if (refused) throw new UsageError(refused);
|
|
12477
12479
|
const r = createReporter(flags.json === true);
|
|
12478
12480
|
const out = resolve13(strFlag(flags, "out") ?? "BRAND.md");
|
|
12481
|
+
await prepareOutput(out);
|
|
12479
12482
|
r.log(`reading ${origin}/design.md and /llms.txt\u2026`);
|
|
12480
12483
|
const [designText, llmsText] = await Promise.all([
|
|
12481
12484
|
fetchText(`${origin}/design.md`),
|
|
@@ -12509,7 +12512,7 @@ async function cmdBrand(argv) {
|
|
|
12509
12512
|
composition,
|
|
12510
12513
|
llms?.claim ?? design?.description ?? null
|
|
12511
12514
|
);
|
|
12512
|
-
await
|
|
12515
|
+
await writeOutput(out, md);
|
|
12513
12516
|
const k = composition.kit;
|
|
12514
12517
|
r.done(
|
|
12515
12518
|
{
|
|
@@ -12647,7 +12650,6 @@ async function recordHosted(input) {
|
|
|
12647
12650
|
import { urlSchemeProblem as urlSchemeProblem2 } from "@vosjs/render-core/record";
|
|
12648
12651
|
|
|
12649
12652
|
// src/plugin/agentBrowser.ts
|
|
12650
|
-
import { writeFile as writeFile9 } from "fs/promises";
|
|
12651
12653
|
import { resolve as resolve14 } from "path";
|
|
12652
12654
|
function parseAgentBrowserLog(text) {
|
|
12653
12655
|
const records = [];
|
|
@@ -13145,7 +13147,7 @@ async function cmdActions(argv) {
|
|
|
13145
13147
|
);
|
|
13146
13148
|
return EXIT_ERROR;
|
|
13147
13149
|
}
|
|
13148
|
-
await
|
|
13150
|
+
await writeOutput(out, `${JSON.stringify(result.actions, null, 2)}
|
|
13149
13151
|
`);
|
|
13150
13152
|
r.done(
|
|
13151
13153
|
{ ok: true, out, url: result.actions.url ?? null, ...summary2(result) },
|
|
@@ -13445,7 +13447,7 @@ async function cmdIngest(argv) {
|
|
|
13445
13447
|
// src/plugin/checkVideo.ts
|
|
13446
13448
|
import { createRequire as createRequire2 } from "module";
|
|
13447
13449
|
import { existsSync as existsSync23 } from "fs";
|
|
13448
|
-
import { mkdir as mkdir9, readFile as readFile14, stat as stat3, writeFile as
|
|
13450
|
+
import { mkdir as mkdir9, readFile as readFile14, stat as stat3, writeFile as writeFile7 } from "fs/promises";
|
|
13449
13451
|
import { basename as basename11, dirname as dirname8, extname as extname4, join as join24, resolve as resolve16 } from "path";
|
|
13450
13452
|
import { ALL_FORMATS as ALL_FORMATS2, FilePathSource as FilePathSource2, Input as Input2 } from "mediabunny";
|
|
13451
13453
|
|
|
@@ -13992,8 +13994,8 @@ async function checkVideo(browser, file, outDir) {
|
|
|
13992
13994
|
await mkdir9(outDir, { recursive: true });
|
|
13993
13995
|
const firstFile = join24(outDir, "first.png");
|
|
13994
13996
|
const lastFile = join24(outDir, "last.png");
|
|
13995
|
-
await
|
|
13996
|
-
await
|
|
13997
|
+
await writeFile7(firstFile, Buffer.from(done.firstPng, "base64"));
|
|
13998
|
+
await writeFile7(lastFile, Buffer.from(done.lastPng, "base64"));
|
|
13997
13999
|
const changes = sceneChanges2(
|
|
13998
14000
|
done.times,
|
|
13999
14001
|
done.changes,
|
|
@@ -14039,7 +14041,7 @@ async function checkVideo(browser, file, outDir) {
|
|
|
14039
14041
|
warnings,
|
|
14040
14042
|
outDir
|
|
14041
14043
|
};
|
|
14042
|
-
await
|
|
14044
|
+
await writeFile7(
|
|
14043
14045
|
join24(outDir, "check.json"),
|
|
14044
14046
|
`${JSON.stringify(result, null, 2)}
|
|
14045
14047
|
`
|
|
@@ -14122,7 +14124,7 @@ import {
|
|
|
14122
14124
|
mkdtemp,
|
|
14123
14125
|
readFile as readFile15,
|
|
14124
14126
|
rm as rm3,
|
|
14125
|
-
writeFile as
|
|
14127
|
+
writeFile as writeFile8
|
|
14126
14128
|
} from "fs/promises";
|
|
14127
14129
|
import { tmpdir as tmpdir2 } from "os";
|
|
14128
14130
|
import { basename as basename12, isAbsolute as isAbsolute3, join as join25, relative as relative4, resolve as resolve17, sep as sep3 } from "path";
|
|
@@ -14565,7 +14567,7 @@ async function resolveTrack(dir, ref, flags, dryRun) {
|
|
|
14565
14567
|
if (!res.ok) throw new Error(`GET ${track.url} answered ${res.status}`);
|
|
14566
14568
|
const tmp = await mkdtemp(join25(tmpdir2(), "vos-score-"));
|
|
14567
14569
|
const path = join25(tmp, basename12(new URL(track.url).pathname) || "track");
|
|
14568
|
-
await
|
|
14570
|
+
await writeFile8(path, new Uint8Array(await res.arrayBuffer()));
|
|
14569
14571
|
return {
|
|
14570
14572
|
path,
|
|
14571
14573
|
key: track.url,
|
|
@@ -16813,7 +16815,7 @@ async function cmdTakeInfo(argv) {
|
|
|
16813
16815
|
}
|
|
16814
16816
|
|
|
16815
16817
|
// src/plugin/audio.ts
|
|
16816
|
-
import { mkdtemp as mkdtemp2, rm as rm5, writeFile as
|
|
16818
|
+
import { mkdtemp as mkdtemp2, rm as rm5, writeFile as writeFile9 } from "fs/promises";
|
|
16817
16819
|
import { tmpdir as tmpdir3 } from "os";
|
|
16818
16820
|
import { basename as basename14, join as join29 } from "path";
|
|
16819
16821
|
import { clipGain as clipGain3 } from "@vosjs/studio-core";
|
|
@@ -16829,7 +16831,7 @@ async function fileFor(dir, key, fetchImpl) {
|
|
|
16829
16831
|
if (!res.ok) return { skipped: `GET ${key} answered ${res.status}` };
|
|
16830
16832
|
const tmp = await mkdtemp2(join29(tmpdir3(), "vos-audio-"));
|
|
16831
16833
|
const path = join29(tmp, basename14(new URL(key).pathname) || "audio");
|
|
16832
|
-
await
|
|
16834
|
+
await writeFile9(path, new Uint8Array(await res.arrayBuffer()));
|
|
16833
16835
|
return { path, cleanup: () => rm5(tmp, { recursive: true, force: true }) };
|
|
16834
16836
|
}
|
|
16835
16837
|
return {
|
|
@@ -20682,4 +20684,4 @@ export {
|
|
|
20682
20684
|
verbHelp,
|
|
20683
20685
|
run
|
|
20684
20686
|
};
|
|
20685
|
-
//# sourceMappingURL=chunk-
|
|
20687
|
+
//# sourceMappingURL=chunk-HDJFCTOG.js.map
|