@vosjs/cli 0.49.0 → 0.50.1
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 +12 -0
- package/dist/{chunk-P3X5KVA6.js → chunk-2EHIFIYC.js} +5 -1
- package/dist/chunk-2EHIFIYC.js.map +1 -0
- package/dist/{chunk-72ADTMWW.js → chunk-6XPFWQKP.js} +4 -1
- package/dist/{chunk-72ADTMWW.js.map → chunk-6XPFWQKP.js.map} +1 -1
- package/dist/{chunk-TAWRT7UM.js → chunk-D6AP7Y3G.js} +317 -103
- package/dist/chunk-D6AP7Y3G.js.map +1 -0
- package/dist/cli.js +4 -4
- package/dist/index.js +3 -3
- package/dist/manifest-IG2WSARS.js +8 -0
- package/dist/{run-EQZXEPXZ.js → run-TA44SOE5.js} +5 -3
- package/dist/{shotList-IYFDHSIK.js → shotList-KH6FTX4L.js} +2 -2
- package/package.json +6 -6
- package/schema/digest.schema.json +4 -1
- package/dist/chunk-P3X5KVA6.js.map +0 -1
- package/dist/chunk-TAWRT7UM.js.map +0 -1
- package/dist/manifest-A4R367EM.js +0 -8
- /package/dist/{manifest-A4R367EM.js.map → manifest-IG2WSARS.js.map} +0 -0
- /package/dist/{run-EQZXEPXZ.js.map → run-TA44SOE5.js.map} +0 -0
- /package/dist/{shotList-IYFDHSIK.js.map → shotList-KH6FTX4L.js.map} +0 -0
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
deadLine,
|
|
11
11
|
deadWarns
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-6XPFWQKP.js";
|
|
13
13
|
|
|
14
14
|
// src/plugin/run.ts
|
|
15
|
-
import { mkdir as
|
|
16
|
-
import { existsSync as
|
|
17
|
-
import { join as
|
|
15
|
+
import { mkdir as mkdir11, readFile as readFile16, rm as rm5 } from "fs/promises";
|
|
16
|
+
import { existsSync as existsSync19 } from "fs";
|
|
17
|
+
import { join as join22, resolve as resolve10 } from "path";
|
|
18
18
|
import {
|
|
19
19
|
END_CARD_FROM as END_CARD_FROM2,
|
|
20
20
|
docOutputDuration as docOutputDuration3,
|
|
@@ -2213,10 +2213,10 @@ function startTakeServer(rootDir, pages) {
|
|
|
2213
2213
|
res.writeHead(404).end();
|
|
2214
2214
|
});
|
|
2215
2215
|
return new Promise(
|
|
2216
|
-
(
|
|
2216
|
+
(resolve11) => server.listen(0, () => {
|
|
2217
2217
|
const addr = server.address();
|
|
2218
2218
|
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
2219
|
-
|
|
2219
|
+
resolve11({ base: `http://localhost:${port}`, close: () => server.close() });
|
|
2220
2220
|
})
|
|
2221
2221
|
);
|
|
2222
2222
|
}
|
|
@@ -6554,10 +6554,10 @@ async function openSession(name, url, opts = { log: () => {
|
|
|
6554
6554
|
opts.log(
|
|
6555
6555
|
`a Chrome window opened on session "${name}": sign in to ${new URL(url).host}, ${leave}`
|
|
6556
6556
|
);
|
|
6557
|
-
return new Promise((
|
|
6557
|
+
return new Promise((resolve11, reject) => {
|
|
6558
6558
|
const child = spawn(exe, args, { stdio: "ignore" });
|
|
6559
6559
|
child.on("error", reject);
|
|
6560
|
-
child.on("exit", (code) =>
|
|
6560
|
+
child.on("exit", (code) => resolve11({ code }));
|
|
6561
6561
|
});
|
|
6562
6562
|
}
|
|
6563
6563
|
async function withSession(name, fn, opts = {}) {
|
|
@@ -9890,8 +9890,8 @@ async function cmdActions(argv) {
|
|
|
9890
9890
|
if (!m) throw new UsageError("--viewport expects WxH, e.g. 1280x720");
|
|
9891
9891
|
viewport = { width: Number(m[1]), height: Number(m[2]) };
|
|
9892
9892
|
}
|
|
9893
|
-
const { readFile:
|
|
9894
|
-
const text = await
|
|
9893
|
+
const { readFile: readFile17 } = await import("fs/promises");
|
|
9894
|
+
const text = await readFile17(resolve8(input), "utf8");
|
|
9895
9895
|
const { records, problems } = parseAgentBrowserLog(text);
|
|
9896
9896
|
for (const p of problems) r.log(` ${p}`);
|
|
9897
9897
|
const result = convertAgentBrowser(records, {
|
|
@@ -9928,9 +9928,9 @@ function summary(result) {
|
|
|
9928
9928
|
}
|
|
9929
9929
|
async function cmdActionsScript(input, flags) {
|
|
9930
9930
|
const r = createReporter(flags.json === true);
|
|
9931
|
-
const { readFile:
|
|
9932
|
-
const { shotList, formatShotList } = await import("./shotList-
|
|
9933
|
-
const raw = JSON.parse(await
|
|
9931
|
+
const { readFile: readFile17 } = await import("fs/promises");
|
|
9932
|
+
const { shotList, formatShotList } = await import("./shotList-KH6FTX4L.js");
|
|
9933
|
+
const raw = JSON.parse(await readFile17(resolve8(input), "utf8"));
|
|
9934
9934
|
const errors = validateActions(raw);
|
|
9935
9935
|
if (errors.length) throw new UsageError(`${input}:
|
|
9936
9936
|
${errors.join("\n ")}`);
|
|
@@ -9939,23 +9939,232 @@ async function cmdActionsScript(input, flags) {
|
|
|
9939
9939
|
return EXIT_OK;
|
|
9940
9940
|
}
|
|
9941
9941
|
|
|
9942
|
+
// src/plugin/ingest.ts
|
|
9943
|
+
import { existsSync as existsSync16 } from "fs";
|
|
9944
|
+
import { copyFile, mkdir as mkdir10, readFile as readFile15, stat as stat4 } from "fs/promises";
|
|
9945
|
+
import { basename as basename7, join as join19, resolve as resolve9 } from "path";
|
|
9946
|
+
import { inflateRawSync } from "zlib";
|
|
9947
|
+
import {
|
|
9948
|
+
cursorFromPlaywrightTrace,
|
|
9949
|
+
cursorFromTrace,
|
|
9950
|
+
playwrightTraceEntry,
|
|
9951
|
+
traceKindOf,
|
|
9952
|
+
zipEntries,
|
|
9953
|
+
zipEntryBytes
|
|
9954
|
+
} from "@vosjs/studio-core";
|
|
9955
|
+
import {
|
|
9956
|
+
ALL_FORMATS,
|
|
9957
|
+
Conversion,
|
|
9958
|
+
FilePathSource,
|
|
9959
|
+
FilePathTarget,
|
|
9960
|
+
Input,
|
|
9961
|
+
Mp4OutputFormat,
|
|
9962
|
+
Output,
|
|
9963
|
+
WebMOutputFormat
|
|
9964
|
+
} from "mediabunny";
|
|
9965
|
+
var BOOLEAN_FLAGS5 = /* @__PURE__ */ new Set(["json", "help"]);
|
|
9966
|
+
async function probeVideoFile(path) {
|
|
9967
|
+
const input = new Input({
|
|
9968
|
+
source: new FilePathSource(path),
|
|
9969
|
+
formats: ALL_FORMATS
|
|
9970
|
+
});
|
|
9971
|
+
try {
|
|
9972
|
+
const format = await input.getFormat();
|
|
9973
|
+
const video = await input.getPrimaryVideoTrack();
|
|
9974
|
+
if (!video) throw new UsageError(`${path} has no video track`);
|
|
9975
|
+
const [duration, stats, audio] = await Promise.all([
|
|
9976
|
+
input.computeDuration(),
|
|
9977
|
+
video.computePacketStats(240),
|
|
9978
|
+
input.getPrimaryAudioTrack()
|
|
9979
|
+
]);
|
|
9980
|
+
const mimeType = format.mimeType;
|
|
9981
|
+
const ext = mimeType.includes("mp4") ? "mp4" : mimeType.includes("quicktime") ? "mov" : "webm";
|
|
9982
|
+
return {
|
|
9983
|
+
width: video.displayWidth,
|
|
9984
|
+
height: video.displayHeight,
|
|
9985
|
+
durationMs: Math.round(duration * 1e3),
|
|
9986
|
+
fps: Math.round(stats.averagePacketRate * 100) / 100,
|
|
9987
|
+
hasAudio: !!audio,
|
|
9988
|
+
mimeType,
|
|
9989
|
+
ext
|
|
9990
|
+
};
|
|
9991
|
+
} finally {
|
|
9992
|
+
await input.dispose?.();
|
|
9993
|
+
}
|
|
9994
|
+
}
|
|
9995
|
+
async function copyRecording(src, dest, ext) {
|
|
9996
|
+
if (ext === "mov") {
|
|
9997
|
+
await copyFile(src, dest);
|
|
9998
|
+
return false;
|
|
9999
|
+
}
|
|
10000
|
+
const input = new Input({
|
|
10001
|
+
source: new FilePathSource(src),
|
|
10002
|
+
formats: ALL_FORMATS
|
|
10003
|
+
});
|
|
10004
|
+
const target = new FilePathTarget(dest);
|
|
10005
|
+
const output = new Output({
|
|
10006
|
+
format: ext === "mp4" ? new Mp4OutputFormat({ fastStart: "in-memory" }) : new WebMOutputFormat(),
|
|
10007
|
+
target
|
|
10008
|
+
});
|
|
10009
|
+
try {
|
|
10010
|
+
const conversion = await Conversion.init({ input, output });
|
|
10011
|
+
if (!conversion.isValid || conversion.discardedTracks.length > 0) {
|
|
10012
|
+
await conversion.cancel?.();
|
|
10013
|
+
await copyFile(src, dest);
|
|
10014
|
+
return false;
|
|
10015
|
+
}
|
|
10016
|
+
await conversion.execute();
|
|
10017
|
+
return true;
|
|
10018
|
+
} catch {
|
|
10019
|
+
await copyFile(src, dest);
|
|
10020
|
+
return false;
|
|
10021
|
+
} finally {
|
|
10022
|
+
await input.dispose?.();
|
|
10023
|
+
}
|
|
10024
|
+
}
|
|
10025
|
+
async function readTraceFile(path, offsetMs) {
|
|
10026
|
+
const kind = traceKindOf(basename7(path));
|
|
10027
|
+
if (!kind) {
|
|
10028
|
+
throw new UsageError(
|
|
10029
|
+
`${path}: not a trace the recorder reads (trace.zip, .trace, .jsonl, .json or .csv)`
|
|
10030
|
+
);
|
|
10031
|
+
}
|
|
10032
|
+
if (kind === "zip") {
|
|
10033
|
+
const bytes = new Uint8Array(await readFile15(path));
|
|
10034
|
+
const entry = playwrightTraceEntry(zipEntries(bytes));
|
|
10035
|
+
if (!entry) {
|
|
10036
|
+
throw new UsageError(
|
|
10037
|
+
`${path}: no trace.trace inside; a Playwright trace.zip is what --cursor reads as a zip`
|
|
10038
|
+
);
|
|
10039
|
+
}
|
|
10040
|
+
const raw = zipEntryBytes(bytes, entry);
|
|
10041
|
+
const text2 = new TextDecoder().decode(
|
|
10042
|
+
entry.method === 8 ? new Uint8Array(inflateRawSync(raw)) : raw
|
|
10043
|
+
);
|
|
10044
|
+
return cursorFromPlaywrightTrace(text2, { offsetMs });
|
|
10045
|
+
}
|
|
10046
|
+
const text = await readFile15(path, "utf8");
|
|
10047
|
+
return cursorFromTrace(basename7(path), text, { offsetMs });
|
|
10048
|
+
}
|
|
10049
|
+
function parseViewport(v) {
|
|
10050
|
+
if (!v) return null;
|
|
10051
|
+
const m = /^(\d+)x(\d+)$/i.exec(v.trim());
|
|
10052
|
+
if (!m) throw new UsageError("--viewport expects WxH, like 1280x720");
|
|
10053
|
+
return { width: Number(m[1]), height: Number(m[2]) };
|
|
10054
|
+
}
|
|
10055
|
+
async function cmdIngest(argv) {
|
|
10056
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS5, MULTI_FLAGS2);
|
|
10057
|
+
const source = positionals[0];
|
|
10058
|
+
if (!source)
|
|
10059
|
+
throw new UsageError(
|
|
10060
|
+
"vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]"
|
|
10061
|
+
);
|
|
10062
|
+
const videoPath = resolve9(source);
|
|
10063
|
+
if (!existsSync16(videoPath)) throw new UsageError(`${source}: no such file`);
|
|
10064
|
+
const r = createReporter(flags.json === true);
|
|
10065
|
+
const outDir = resolve9(strFlag(flags, "out") ?? "take");
|
|
10066
|
+
const offsetMs = numFlag(flags, "offset", 0);
|
|
10067
|
+
const viewportFlag = parseViewport(strFlag(flags, "viewport"));
|
|
10068
|
+
const cursorPath = strFlag(flags, "cursor");
|
|
10069
|
+
const backdrop = await takeBackdrop(flags, r);
|
|
10070
|
+
r.log(`probing ${basename7(videoPath)}\u2026`);
|
|
10071
|
+
const probed = await probeVideoFile(videoPath);
|
|
10072
|
+
if (!(probed.durationMs > 0)) {
|
|
10073
|
+
throw new UsageError(
|
|
10074
|
+
`${source}: the file reports no duration; a stream-shaped recording needs its container fixed first (ffmpeg -i in.webm -c copy out.webm)`
|
|
10075
|
+
);
|
|
10076
|
+
}
|
|
10077
|
+
let trace = null;
|
|
10078
|
+
if (cursorPath) {
|
|
10079
|
+
trace = await readTraceFile(resolve9(cursorPath), offsetMs);
|
|
10080
|
+
for (const n of trace.notes) r.log(`note: ${n}`);
|
|
10081
|
+
}
|
|
10082
|
+
if (existsSync16(join19(outDir, "meta.json"))) {
|
|
10083
|
+
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
10084
|
+
r.log(
|
|
10085
|
+
`note: re-ingesting into ${outDir}; kept ${kept.length ? kept.join(", ") : "nothing"}` + (prevDoc ? `; apply the previous cut with: vos plan ${outDir} --reuse` : "")
|
|
10086
|
+
);
|
|
10087
|
+
}
|
|
10088
|
+
await mkdir10(outDir, { recursive: true });
|
|
10089
|
+
const paths = await ensureTakeDir(outDir);
|
|
10090
|
+
const recording = join19(outDir, `recording.${probed.ext}`);
|
|
10091
|
+
r.log("copying the recording\u2026");
|
|
10092
|
+
const remuxed = await copyRecording(videoPath, recording, probed.ext);
|
|
10093
|
+
const viewport = viewportFlag ?? trace?.viewport ?? {
|
|
10094
|
+
width: probed.width,
|
|
10095
|
+
height: probed.height
|
|
10096
|
+
};
|
|
10097
|
+
const events = trace?.events ?? [];
|
|
10098
|
+
const fileStat = await stat4(videoPath);
|
|
10099
|
+
const meta = {
|
|
10100
|
+
dpr: 1,
|
|
10101
|
+
zoom: 1,
|
|
10102
|
+
t0: trace?.t0 ?? Math.round(fileStat.mtimeMs),
|
|
10103
|
+
durationMs: probed.durationMs,
|
|
10104
|
+
width: viewport.width,
|
|
10105
|
+
height: viewport.height,
|
|
10106
|
+
captureWidth: probed.width,
|
|
10107
|
+
captureHeight: probed.height,
|
|
10108
|
+
fps: probed.fps > 0 ? probed.fps : 30,
|
|
10109
|
+
hasAudio: probed.hasAudio,
|
|
10110
|
+
producer: "ingest",
|
|
10111
|
+
...events.length ? { captureSurface: "tab" } : {}
|
|
10112
|
+
};
|
|
10113
|
+
await writeJson(paths.meta, meta, true);
|
|
10114
|
+
if (events.length) await writeJson(paths.cursor, events);
|
|
10115
|
+
const plan = await planTake(outDir, { backdrop });
|
|
10116
|
+
const clicks = events.filter((e) => e.type === "down").length;
|
|
10117
|
+
const seconds = (probed.durationMs / 1e3).toFixed(1);
|
|
10118
|
+
const facts = `${seconds}s, ${probed.width}\xD7${probed.height} @ ${meta.fps} fps${probed.hasAudio ? ", audio" : ", no audio"}${remuxed ? "" : ", copied as is"}`;
|
|
10119
|
+
const cursorLine = trace ? `${events.length} cursor events (${clicks} clicks) from ${basename7(cursorPath)}${trace.dropped ? `, ${trace.dropped} not placed` : ""}; ${plan.zoomAuto} zoom${plan.zoomAuto === 1 ? "" : "s"} planned` : "no cursor track, so nothing was planned";
|
|
10120
|
+
const next = trace ? `Next: vos digest ${outDir} \u2014 look before you cut; edit doc.json; vos push ${outDir}` : `Add --cursor <trace> recorded beside the video (a Playwright trace.zip, stamped JSON records, or a t,x,y,type CSV) to plan zooms from its clicks; else place them by eye: vos frames ${outDir} --times 0,25%,50%,75%,100%, then edit doc.json`;
|
|
10121
|
+
r.done(
|
|
10122
|
+
{
|
|
10123
|
+
out: outDir,
|
|
10124
|
+
recording: basename7(recording),
|
|
10125
|
+
durationMs: probed.durationMs,
|
|
10126
|
+
width: probed.width,
|
|
10127
|
+
height: probed.height,
|
|
10128
|
+
viewport,
|
|
10129
|
+
fps: meta.fps,
|
|
10130
|
+
hasAudio: probed.hasAudio,
|
|
10131
|
+
remuxed,
|
|
10132
|
+
cursor: trace ? {
|
|
10133
|
+
file: basename7(cursorPath),
|
|
10134
|
+
kind: trace.kind,
|
|
10135
|
+
events: events.length,
|
|
10136
|
+
clicks,
|
|
10137
|
+
placed: trace.placed,
|
|
10138
|
+
dropped: trace.dropped,
|
|
10139
|
+
notes: trace.notes
|
|
10140
|
+
} : null,
|
|
10141
|
+
zooms: plan.zoomAuto,
|
|
10142
|
+
backdrop: plan.backdrop ?? null
|
|
10143
|
+
},
|
|
10144
|
+
`Ingested ${basename7(videoPath)} \u2192 ${outDir}/${basename7(recording)} (${facts})
|
|
10145
|
+
${cursorLine}
|
|
10146
|
+
${next}`
|
|
10147
|
+
);
|
|
10148
|
+
return EXIT_OK;
|
|
10149
|
+
}
|
|
10150
|
+
|
|
9942
10151
|
// src/plugin/machineCmd.ts
|
|
9943
10152
|
import { spawnSync } from "child_process";
|
|
9944
10153
|
import {
|
|
9945
10154
|
cpSync,
|
|
9946
|
-
existsSync as
|
|
10155
|
+
existsSync as existsSync18,
|
|
9947
10156
|
mkdirSync as mkdirSync3,
|
|
9948
10157
|
readFileSync as readFileSync7,
|
|
9949
10158
|
rmSync as rmSync2,
|
|
9950
10159
|
writeFileSync as writeFileSync3
|
|
9951
10160
|
} from "fs";
|
|
9952
10161
|
import { homedir as homedir3 } from "os";
|
|
9953
|
-
import { join as
|
|
10162
|
+
import { join as join21 } from "path";
|
|
9954
10163
|
import { chromium as chromium2 } from "playwright";
|
|
9955
10164
|
|
|
9956
10165
|
// src/plugin/machine.ts
|
|
9957
|
-
import { existsSync as
|
|
9958
|
-
import { dirname as dirname5, join as
|
|
10166
|
+
import { existsSync as existsSync17, readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
|
|
10167
|
+
import { dirname as dirname5, join as join20 } from "path";
|
|
9959
10168
|
var AGENT_NAMES = [
|
|
9960
10169
|
"claude",
|
|
9961
10170
|
"cursor",
|
|
@@ -9975,17 +10184,17 @@ var HOME_DIRS = {
|
|
|
9975
10184
|
copilot: [".copilot"]
|
|
9976
10185
|
};
|
|
9977
10186
|
function detectAgents(root, opts = {}) {
|
|
9978
|
-
const exists = opts.exists ??
|
|
10187
|
+
const exists = opts.exists ?? existsSync17;
|
|
9979
10188
|
const out = [];
|
|
9980
10189
|
for (const agent of AGENT_NAMES) {
|
|
9981
10190
|
for (const rel of PROJECT_DIRS[agent]) {
|
|
9982
|
-
const dir =
|
|
10191
|
+
const dir = join20(root, rel);
|
|
9983
10192
|
if (exists(dir)) out.push({ agent, dir, scope: "project" });
|
|
9984
10193
|
}
|
|
9985
|
-
if (agent === "copilot" && !out.some((h) => h.agent === "copilot") && exists(
|
|
10194
|
+
if (agent === "copilot" && !out.some((h) => h.agent === "copilot") && exists(join20(root, ".github", "copilot-instructions.md"))) {
|
|
9986
10195
|
out.push({
|
|
9987
10196
|
agent,
|
|
9988
|
-
dir:
|
|
10197
|
+
dir: join20(root, ".github", "copilot"),
|
|
9989
10198
|
scope: "project"
|
|
9990
10199
|
});
|
|
9991
10200
|
}
|
|
@@ -9993,7 +10202,7 @@ function detectAgents(root, opts = {}) {
|
|
|
9993
10202
|
if (opts.global && opts.home) {
|
|
9994
10203
|
for (const agent of AGENT_NAMES) {
|
|
9995
10204
|
for (const rel of HOME_DIRS[agent]) {
|
|
9996
|
-
const dir =
|
|
10205
|
+
const dir = join20(opts.home, rel);
|
|
9997
10206
|
if (exists(dir)) out.push({ agent, dir, scope: "global" });
|
|
9998
10207
|
}
|
|
9999
10208
|
}
|
|
@@ -10011,18 +10220,18 @@ function agentsFromFlag(value, root) {
|
|
|
10011
10220
|
return {
|
|
10012
10221
|
homes: wanted.map((agent) => ({
|
|
10013
10222
|
agent,
|
|
10014
|
-
dir:
|
|
10223
|
+
dir: join20(root, PROJECT_DIRS[agent][0]),
|
|
10015
10224
|
scope: "project"
|
|
10016
10225
|
}))
|
|
10017
10226
|
};
|
|
10018
10227
|
}
|
|
10019
10228
|
function skillsDirFor(home) {
|
|
10020
|
-
return
|
|
10229
|
+
return join20(home.dir, "skills");
|
|
10021
10230
|
}
|
|
10022
10231
|
function fallbackSkillsHome(root) {
|
|
10023
|
-
return { agent: "codex", dir:
|
|
10232
|
+
return { agent: "codex", dir: join20(root, ".agents"), scope: "project" };
|
|
10024
10233
|
}
|
|
10025
|
-
function installedSkills(dir, exists =
|
|
10234
|
+
function installedSkills(dir, exists = existsSync17, list = (p) => {
|
|
10026
10235
|
try {
|
|
10027
10236
|
return readdirSync4(p);
|
|
10028
10237
|
} catch {
|
|
@@ -10030,7 +10239,7 @@ function installedSkills(dir, exists = existsSync16, list = (p) => {
|
|
|
10030
10239
|
}
|
|
10031
10240
|
}) {
|
|
10032
10241
|
if (!exists(dir)) return [];
|
|
10033
|
-
return list(dir).filter((name) => exists(
|
|
10242
|
+
return list(dir).filter((name) => exists(join20(dir, name, "SKILL.md"))).sort();
|
|
10034
10243
|
}
|
|
10035
10244
|
var RULES_BEGIN = "<!-- vos:begin (written by vos setup; the block is replaced on the next run) -->";
|
|
10036
10245
|
var RULES_END = "<!-- vos:end -->";
|
|
@@ -10062,10 +10271,10 @@ ${RULES_BLOCK}
|
|
|
10062
10271
|
}
|
|
10063
10272
|
return { text, changed: text !== current };
|
|
10064
10273
|
}
|
|
10065
|
-
function rulesFileFor(root, exists =
|
|
10066
|
-
const agents =
|
|
10274
|
+
function rulesFileFor(root, exists = existsSync17) {
|
|
10275
|
+
const agents = join20(root, "AGENTS.md");
|
|
10067
10276
|
if (exists(agents)) return agents;
|
|
10068
|
-
const claude =
|
|
10277
|
+
const claude = join20(root, "CLAUDE.md");
|
|
10069
10278
|
if (exists(claude)) return claude;
|
|
10070
10279
|
return agents;
|
|
10071
10280
|
}
|
|
@@ -10074,14 +10283,14 @@ function chromeCandidates(platform, env) {
|
|
|
10074
10283
|
return ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"];
|
|
10075
10284
|
if (platform === "win32")
|
|
10076
10285
|
return [
|
|
10077
|
-
|
|
10286
|
+
join20(
|
|
10078
10287
|
env["PROGRAMFILES"] ?? "C:\\Program Files",
|
|
10079
10288
|
"Google",
|
|
10080
10289
|
"Chrome",
|
|
10081
10290
|
"Application",
|
|
10082
10291
|
"chrome.exe"
|
|
10083
10292
|
),
|
|
10084
|
-
|
|
10293
|
+
join20(
|
|
10085
10294
|
env["LOCALAPPDATA"] ?? "",
|
|
10086
10295
|
"Google",
|
|
10087
10296
|
"Chrome",
|
|
@@ -10168,13 +10377,13 @@ function doctorReport(facts) {
|
|
|
10168
10377
|
function bundledSkillsDir(from) {
|
|
10169
10378
|
let dir = dirname5(from);
|
|
10170
10379
|
for (let i = 0; i < 6; i++) {
|
|
10171
|
-
const pkg =
|
|
10172
|
-
if (
|
|
10380
|
+
const pkg = join20(dir, "package.json");
|
|
10381
|
+
if (existsSync17(pkg)) {
|
|
10173
10382
|
try {
|
|
10174
10383
|
const name = JSON.parse(readFileSync6(pkg, "utf8")).name;
|
|
10175
10384
|
if (name === "@vosjs/cli") {
|
|
10176
|
-
const skills =
|
|
10177
|
-
return
|
|
10385
|
+
const skills = join20(dir, "skills");
|
|
10386
|
+
return existsSync17(skills) && statSync4(skills).isDirectory() ? skills : null;
|
|
10178
10387
|
}
|
|
10179
10388
|
} catch {
|
|
10180
10389
|
}
|
|
@@ -10187,7 +10396,7 @@ function bundledSkillsDir(from) {
|
|
|
10187
10396
|
}
|
|
10188
10397
|
|
|
10189
10398
|
// src/plugin/machineCmd.ts
|
|
10190
|
-
var
|
|
10399
|
+
var BOOLEAN_FLAGS6 = /* @__PURE__ */ new Set([
|
|
10191
10400
|
"json",
|
|
10192
10401
|
"help",
|
|
10193
10402
|
"global",
|
|
@@ -10205,7 +10414,7 @@ function npx() {
|
|
|
10205
10414
|
function bundledChromium() {
|
|
10206
10415
|
try {
|
|
10207
10416
|
const p = chromium2.executablePath();
|
|
10208
|
-
return p &&
|
|
10417
|
+
return p && existsSync18(p) ? p : null;
|
|
10209
10418
|
} catch {
|
|
10210
10419
|
return null;
|
|
10211
10420
|
}
|
|
@@ -10214,7 +10423,7 @@ function probe() {
|
|
|
10214
10423
|
return probeBrowser({
|
|
10215
10424
|
platform: process.platform,
|
|
10216
10425
|
env: process.env,
|
|
10217
|
-
exists:
|
|
10426
|
+
exists: existsSync18,
|
|
10218
10427
|
bundled: bundledChromium
|
|
10219
10428
|
});
|
|
10220
10429
|
}
|
|
@@ -10265,7 +10474,7 @@ async function doctorFacts(opts) {
|
|
|
10265
10474
|
};
|
|
10266
10475
|
}
|
|
10267
10476
|
async function cmdSetup(argv) {
|
|
10268
|
-
const { flags } = parseArgs(argv,
|
|
10477
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS6);
|
|
10269
10478
|
const r = reporterFor(flags);
|
|
10270
10479
|
const root = process.cwd();
|
|
10271
10480
|
const global = flags.global === true;
|
|
@@ -10318,7 +10527,7 @@ async function cmdSetup(argv) {
|
|
|
10318
10527
|
const dest = skillsDirFor(home);
|
|
10319
10528
|
mkdirSync3(dest, { recursive: true });
|
|
10320
10529
|
for (const name of installedSkills(bundled)) {
|
|
10321
|
-
cpSync(
|
|
10530
|
+
cpSync(join21(bundled, name), join21(dest, name), { recursive: true });
|
|
10322
10531
|
}
|
|
10323
10532
|
}
|
|
10324
10533
|
skillsVia = "bundled";
|
|
@@ -10353,7 +10562,7 @@ async function cmdSetup(argv) {
|
|
|
10353
10562
|
let rules = null;
|
|
10354
10563
|
if (!noRules) {
|
|
10355
10564
|
const file = rulesFileFor(root);
|
|
10356
|
-
const existing =
|
|
10565
|
+
const existing = existsSync18(file) ? readFileSync7(file, "utf8") : null;
|
|
10357
10566
|
const { text, changed } = applyRulesBlock(existing);
|
|
10358
10567
|
if (changed) writeFileSync3(file, text);
|
|
10359
10568
|
rules = { file, changed };
|
|
@@ -10384,7 +10593,7 @@ Next: ${report.next_step}`
|
|
|
10384
10593
|
return report.ok ? EXIT_OK : EXIT_NO_BROWSER;
|
|
10385
10594
|
}
|
|
10386
10595
|
async function cmdDoctor(argv) {
|
|
10387
|
-
const { flags } = parseArgs(argv,
|
|
10596
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS6);
|
|
10388
10597
|
const r = reporterFor(flags);
|
|
10389
10598
|
const root = process.cwd();
|
|
10390
10599
|
const homes = detectAgents(root, { home: homedir3(), global: true });
|
|
@@ -10403,7 +10612,7 @@ Next: ${report.next_step}`
|
|
|
10403
10612
|
return report.ok ? EXIT_OK : EXIT_NO_BROWSER;
|
|
10404
10613
|
}
|
|
10405
10614
|
async function cmdWhoami(argv) {
|
|
10406
|
-
const { flags } = parseArgs(argv,
|
|
10615
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS6);
|
|
10407
10616
|
const r = reporterFor(flags);
|
|
10408
10617
|
const origin = platformOrigin({
|
|
10409
10618
|
origin: strFlag(flags, "origin"),
|
|
@@ -10465,9 +10674,9 @@ async function cmdWhoami(argv) {
|
|
|
10465
10674
|
return EXIT_OK;
|
|
10466
10675
|
}
|
|
10467
10676
|
function cmdLogout(argv) {
|
|
10468
|
-
const { flags } = parseArgs(argv,
|
|
10677
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS6);
|
|
10469
10678
|
const r = reporterFor(flags);
|
|
10470
|
-
const had =
|
|
10679
|
+
const had = existsSync18(CREDENTIALS_PATH);
|
|
10471
10680
|
rmSync2(CREDENTIALS_PATH, { force: true });
|
|
10472
10681
|
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
10473
10682
|
r.done(
|
|
@@ -10483,7 +10692,7 @@ function cmdLogout(argv) {
|
|
|
10483
10692
|
}
|
|
10484
10693
|
|
|
10485
10694
|
// src/plugin/run.ts
|
|
10486
|
-
var
|
|
10695
|
+
var BOOLEAN_FLAGS7 = /* @__PURE__ */ new Set([
|
|
10487
10696
|
"json",
|
|
10488
10697
|
"help",
|
|
10489
10698
|
"picture",
|
|
@@ -10526,6 +10735,8 @@ Take pipeline
|
|
|
10526
10735
|
vos validate <actions.json|take|kit.json> [--picture] [--json]
|
|
10527
10736
|
vos judge <kit.json> --against <MANIFEST.json> [--out dir] [--json]
|
|
10528
10737
|
vos actions from-agent-browser <steps.jsonl> [--out actions.json] [--url <url>] [--viewport WxH] [--json]
|
|
10738
|
+
vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]
|
|
10739
|
+
a take from a recording someone else made (a cloud agent's PR video, a Playwright run's video, a Loom export): the file becomes recording.<container>, meta.json from its own dimensions and duration, and a trace beside it becomes cursor.json so the planner has clicks to zoom on; without one, nothing is planned and the done event says so
|
|
10529
10740
|
vos session open <url> --name <app> a plain Chrome window on a vos-owned profile; sign in, close it
|
|
10530
10741
|
vos session check <name> [--url <url>] headless: does the session still open the page? exit 0/4
|
|
10531
10742
|
vos session list | rm <name> what exists and how old; delete one
|
|
@@ -10783,7 +10994,7 @@ lint-gated, so a bad override fails like a bad doc.json):
|
|
|
10783
10994
|
first ready loop (the house backdrop the studio opens on), or a flat ground offline
|
|
10784
10995
|
`;
|
|
10785
10996
|
async function loadActions(file) {
|
|
10786
|
-
const raw = JSON.parse(await
|
|
10997
|
+
const raw = JSON.parse(await readFile16(file, "utf8"));
|
|
10787
10998
|
const errors = validateActions(raw);
|
|
10788
10999
|
if (errors.length)
|
|
10789
11000
|
throw new UsageError(`invalid actions file:
|
|
@@ -10845,8 +11056,8 @@ function takeBrowserArgs(multi) {
|
|
|
10845
11056
|
function takeStorageState(flags) {
|
|
10846
11057
|
const raw = strFlag(flags, "storage-state");
|
|
10847
11058
|
if (!raw) return void 0;
|
|
10848
|
-
const path =
|
|
10849
|
-
if (!
|
|
11059
|
+
const path = resolve10(raw);
|
|
11060
|
+
if (!existsSync19(path))
|
|
10850
11061
|
throw new UsageError(`--storage-state: no such file: ${path}`);
|
|
10851
11062
|
return path;
|
|
10852
11063
|
}
|
|
@@ -10859,7 +11070,7 @@ function takeSessionName(flags, storageState) {
|
|
|
10859
11070
|
throw new UsageError(
|
|
10860
11071
|
"--session and --storage-state are two doors to one take: a persistent profile cannot take a storage state. Pass one"
|
|
10861
11072
|
);
|
|
10862
|
-
if (!
|
|
11073
|
+
if (!existsSync19(sessionDir(name)))
|
|
10863
11074
|
throw new UsageError(
|
|
10864
11075
|
`no session "${name}". Make one: vos session open <url> --name ${name} (a Chrome window opens; sign in and close it)`
|
|
10865
11076
|
);
|
|
@@ -10915,7 +11126,7 @@ function wallGate(flags, r, opts) {
|
|
|
10915
11126
|
async function cmdRecord(argv) {
|
|
10916
11127
|
const { positionals, flags, multi } = parseArgs(
|
|
10917
11128
|
argv,
|
|
10918
|
-
|
|
11129
|
+
BOOLEAN_FLAGS7,
|
|
10919
11130
|
MULTI_FLAGS2
|
|
10920
11131
|
);
|
|
10921
11132
|
const actionsPath = strFlag(flags, "actions") ?? positionals[0];
|
|
@@ -10928,7 +11139,7 @@ async function cmdRecord(argv) {
|
|
|
10928
11139
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
10929
11140
|
if (!url)
|
|
10930
11141
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
10931
|
-
const outDir =
|
|
11142
|
+
const outDir = resolve10(strFlag(flags, "out") ?? "take");
|
|
10932
11143
|
const storageState = takeStorageState(flags);
|
|
10933
11144
|
const sessionName = takeSessionName(flags, storageState);
|
|
10934
11145
|
const browserArgs = takeBrowserArgs(multi);
|
|
@@ -11082,13 +11293,13 @@ ${lines.join("\n")}
|
|
|
11082
11293
|
}
|
|
11083
11294
|
const paths = takePaths(outDir);
|
|
11084
11295
|
const prepare = async () => {
|
|
11085
|
-
if (
|
|
11296
|
+
if (existsSync19(join22(outDir, "meta.json"))) {
|
|
11086
11297
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
11087
11298
|
r.log(
|
|
11088
11299
|
`note: re-recording ${outDir} \u2014 kept ${kept.length ? kept.join(", ") : "nothing"}` + (prevDoc ? "; apply the previous cut to the new footage with: vos plan " + outDir + " --reuse" : "")
|
|
11089
11300
|
);
|
|
11090
11301
|
}
|
|
11091
|
-
await
|
|
11302
|
+
await mkdir11(outDir, { recursive: true });
|
|
11092
11303
|
await ensureTakeDir(outDir);
|
|
11093
11304
|
};
|
|
11094
11305
|
const browser = await launchBrowser(browserArgs);
|
|
@@ -11147,7 +11358,7 @@ ${lines.join("\n")}
|
|
|
11147
11358
|
},
|
|
11148
11359
|
strictFail ? `STRICT: take recorded but incomplete \u2014 ${strictReason(rec)}; fix the flow and re-record.${skippedNote}${exposureNote(rec)}` : `Take ready: ${outDir}
|
|
11149
11360
|
${(rec.meta.durationMs / 1e3).toFixed(1)}s \xB7 ${rec.frames.length} frames \xB7 ${rec.events.length} cursor events \xB7 ${clicks} clicks \xB7 ${plan.doc.zoom.length} zoom spans planned \xB7 ${rec.freezePct}% frozen \xB7 ${rec.dead.pct}% dead${deadWarns(rec.dead) ? " \u26A0 " + deadLine(rec.dead) : ""}${skippedNote}
|
|
11150
|
-
Next: edit ${
|
|
11361
|
+
Next: edit ${join22(outDir, "doc.json")} (optional), then: vos render ${outDir}${exposureNote(rec)}`
|
|
11151
11362
|
);
|
|
11152
11363
|
return strictFail ? EXIT_USAGE : EXIT_OK;
|
|
11153
11364
|
} finally {
|
|
@@ -11157,7 +11368,7 @@ ${lines.join("\n")}
|
|
|
11157
11368
|
async function cmdCreate2(argv) {
|
|
11158
11369
|
const { positionals, flags, multi } = parseArgs(
|
|
11159
11370
|
argv,
|
|
11160
|
-
|
|
11371
|
+
BOOLEAN_FLAGS7,
|
|
11161
11372
|
MULTI_FLAGS2
|
|
11162
11373
|
);
|
|
11163
11374
|
const actionsPath = strFlag(flags, "actions");
|
|
@@ -11171,12 +11382,12 @@ async function cmdCreate2(argv) {
|
|
|
11171
11382
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
11172
11383
|
if (!url)
|
|
11173
11384
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
11174
|
-
const outDir =
|
|
11385
|
+
const outDir = resolve10(strFlag(flags, "out") ?? "take");
|
|
11175
11386
|
const fmtRaw = strFlag(flags, "format") ?? "webm";
|
|
11176
11387
|
if (fmtRaw !== "webm" && fmtRaw !== "mp4")
|
|
11177
11388
|
throw new UsageError("--format must be webm or mp4");
|
|
11178
11389
|
const format = fmtRaw;
|
|
11179
|
-
const out = positionals[0] ??
|
|
11390
|
+
const out = positionals[0] ?? join22(outDir, `out.${format}`);
|
|
11180
11391
|
const parallel = numFlag(flags, "parallel", 1);
|
|
11181
11392
|
if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {
|
|
11182
11393
|
throw new UsageError("--parallel expects an integer between 1 and 16");
|
|
@@ -11189,13 +11400,13 @@ async function cmdCreate2(argv) {
|
|
|
11189
11400
|
const headers = takeHeaders(multi);
|
|
11190
11401
|
const paths = takePaths(outDir);
|
|
11191
11402
|
const prepare = async () => {
|
|
11192
|
-
if (
|
|
11403
|
+
if (existsSync19(join22(outDir, "meta.json"))) {
|
|
11193
11404
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
11194
11405
|
r.log(
|
|
11195
11406
|
`note: re-recording ${outDir} \u2014 kept ${kept.length ? kept.join(", ") : "nothing"}` + (prevDoc ? "; apply the previous cut to the new footage with: vos plan " + outDir + " --reuse" : "")
|
|
11196
11407
|
);
|
|
11197
11408
|
}
|
|
11198
|
-
await
|
|
11409
|
+
await mkdir11(outDir, { recursive: true });
|
|
11199
11410
|
await ensureTakeDir(outDir);
|
|
11200
11411
|
};
|
|
11201
11412
|
const browser = await launchBrowser(browserArgs);
|
|
@@ -11286,7 +11497,7 @@ async function cmdCreate2(argv) {
|
|
|
11286
11497
|
async function cmdPlan(argv) {
|
|
11287
11498
|
const { positionals, flags, multi } = parseArgs(
|
|
11288
11499
|
argv,
|
|
11289
|
-
|
|
11500
|
+
BOOLEAN_FLAGS7,
|
|
11290
11501
|
/* @__PURE__ */ new Set(["with"])
|
|
11291
11502
|
);
|
|
11292
11503
|
const dir = positionals[0];
|
|
@@ -11296,24 +11507,24 @@ async function cmdPlan(argv) {
|
|
|
11296
11507
|
);
|
|
11297
11508
|
const r = createReporter(flags.json === true);
|
|
11298
11509
|
if (flags.fresh === true) {
|
|
11299
|
-
await rm5(
|
|
11510
|
+
await rm5(join22(dir, "doc.json"), { force: true });
|
|
11300
11511
|
r.log("note: --fresh discarded the existing doc.json");
|
|
11301
11512
|
}
|
|
11302
11513
|
let reuse;
|
|
11303
11514
|
if (flags.reuse === true) {
|
|
11304
|
-
const from =
|
|
11305
|
-
if (!
|
|
11515
|
+
const from = resolve10(strFlag(flags, "from") ?? join22(dir, PREV_DOC_NAME));
|
|
11516
|
+
if (!existsSync19(from)) {
|
|
11306
11517
|
throw new UsageError(
|
|
11307
11518
|
`--reuse: ${from} does not exist \u2014 a re-record into this take writes doc.prev.json, or pass --from <doc.json>`
|
|
11308
11519
|
);
|
|
11309
11520
|
}
|
|
11310
11521
|
reuse = {
|
|
11311
11522
|
from,
|
|
11312
|
-
doc: JSON.parse(await
|
|
11523
|
+
doc: JSON.parse(await readFile16(from, "utf8"))
|
|
11313
11524
|
};
|
|
11314
11525
|
}
|
|
11315
11526
|
const style = await resolveStyleRef(flags);
|
|
11316
|
-
const hasDoc =
|
|
11527
|
+
const hasDoc = existsSync19(join22(dir, "doc.json"));
|
|
11317
11528
|
const backdrop = hasDoc ? null : await takeBackdrop(flags, r);
|
|
11318
11529
|
const release = await releaseInputs(dir, flags, r, multi.with ?? []);
|
|
11319
11530
|
const motionWanted = !hasDoc || flags.motion === true || flags.fresh === true;
|
|
@@ -11359,7 +11570,7 @@ async function cmdPlan(argv) {
|
|
|
11359
11570
|
${s.reuse.flagged.join("\n ")}` : "") : "";
|
|
11360
11571
|
r.done(
|
|
11361
11572
|
{
|
|
11362
|
-
take:
|
|
11573
|
+
take: resolve10(dir),
|
|
11363
11574
|
fresh: s.fresh,
|
|
11364
11575
|
cursorKept: s.cursorKept,
|
|
11365
11576
|
zoomAuto: s.zoomAuto,
|
|
@@ -11371,7 +11582,7 @@ async function cmdPlan(argv) {
|
|
|
11371
11582
|
...s.motion ? { motion: s.motion } : {},
|
|
11372
11583
|
...s.reuse ? { reuse: s.reuse } : {}
|
|
11373
11584
|
},
|
|
11374
|
-
`${s.reuse ? "Reused" : s.fresh ? "Planned" : "Refreshed"} ${
|
|
11585
|
+
`${s.reuse ? "Reused" : s.fresh ? "Planned" : "Refreshed"} ${join22(dir, "doc.json")}: ${s.zoomAuto} auto + ${s.zoomManual} manual zoom spans${s.cursorKept ? "" : " (cursor track dropped)"}${layoutLines}${motionLines}${reuseLines}`
|
|
11375
11586
|
);
|
|
11376
11587
|
return EXIT_OK;
|
|
11377
11588
|
}
|
|
@@ -11484,7 +11695,7 @@ async function releaseInputs(dir, flags, r, withRefs = []) {
|
|
|
11484
11695
|
async function cmdRender(argv) {
|
|
11485
11696
|
const { positionals, flags, multi } = parseArgs(
|
|
11486
11697
|
argv,
|
|
11487
|
-
|
|
11698
|
+
BOOLEAN_FLAGS7,
|
|
11488
11699
|
MULTI_FLAGS2
|
|
11489
11700
|
);
|
|
11490
11701
|
const dir = positionals[0];
|
|
@@ -11497,7 +11708,7 @@ async function cmdRender(argv) {
|
|
|
11497
11708
|
if (fmtRaw !== "webm" && fmtRaw !== "mp4")
|
|
11498
11709
|
throw new UsageError("--format must be webm or mp4");
|
|
11499
11710
|
const format = fmtRaw;
|
|
11500
|
-
const out = positionals[1] ??
|
|
11711
|
+
const out = positionals[1] ?? join22(dir, `out.${format}`);
|
|
11501
11712
|
const parallel = numFlag(flags, "parallel", 1);
|
|
11502
11713
|
if (!Number.isInteger(parallel) || parallel < 1 || parallel > 16) {
|
|
11503
11714
|
throw new UsageError("--parallel expects an integer between 1 and 16");
|
|
@@ -11555,7 +11766,7 @@ async function cmdRender(argv) {
|
|
|
11555
11766
|
async function cmdFrames(argv) {
|
|
11556
11767
|
const { positionals, flags, multi } = parseArgs(
|
|
11557
11768
|
argv,
|
|
11558
|
-
|
|
11769
|
+
BOOLEAN_FLAGS7,
|
|
11559
11770
|
MULTI_FLAGS2
|
|
11560
11771
|
);
|
|
11561
11772
|
const dir = positionals[0];
|
|
@@ -11628,7 +11839,7 @@ async function cmdFrames(argv) {
|
|
|
11628
11839
|
async function cmdDeliver(argv) {
|
|
11629
11840
|
const { positionals, flags, multi } = parseArgs(
|
|
11630
11841
|
argv,
|
|
11631
|
-
|
|
11842
|
+
BOOLEAN_FLAGS7,
|
|
11632
11843
|
MULTI_FLAGS2
|
|
11633
11844
|
);
|
|
11634
11845
|
const dir = positionals[0];
|
|
@@ -11744,15 +11955,15 @@ async function resolveStyleRef(flags) {
|
|
|
11744
11955
|
}
|
|
11745
11956
|
async function resolveDocRef(ref, flags, what) {
|
|
11746
11957
|
const styleRef = ref;
|
|
11747
|
-
const file =
|
|
11958
|
+
const file = existsSync19(styleRef) ? resolve10(
|
|
11748
11959
|
styleRef,
|
|
11749
|
-
|
|
11960
|
+
existsSync19(join22(styleRef, "doc.json")) ? "doc.json" : ""
|
|
11750
11961
|
) : null;
|
|
11751
|
-
if (file &&
|
|
11962
|
+
if (file && existsSync19(file)) {
|
|
11752
11963
|
return {
|
|
11753
11964
|
from: file,
|
|
11754
11965
|
doc: migrateHostedDoc5(
|
|
11755
|
-
JSON.parse(await
|
|
11966
|
+
JSON.parse(await readFile16(file, "utf8"))
|
|
11756
11967
|
)
|
|
11757
11968
|
};
|
|
11758
11969
|
}
|
|
@@ -11794,7 +12005,7 @@ async function officialTemplate(origin, ref) {
|
|
|
11794
12005
|
}
|
|
11795
12006
|
}
|
|
11796
12007
|
async function cmdDigest(argv) {
|
|
11797
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12008
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
11798
12009
|
const dir = positionals[0];
|
|
11799
12010
|
if (!dir)
|
|
11800
12011
|
throw new UsageError(
|
|
@@ -11804,7 +12015,7 @@ async function cmdDigest(argv) {
|
|
|
11804
12015
|
const take = await loadTake(dir);
|
|
11805
12016
|
if (!take.doc) throw new UsageError(`${dir} has no doc.json \u2014 run plan first`);
|
|
11806
12017
|
const transcriptPath = strFlag(flags, "transcript");
|
|
11807
|
-
const transcript = transcriptPath ? parseTranscript(JSON.parse(await
|
|
12018
|
+
const transcript = transcriptPath ? parseTranscript(JSON.parse(await readFile16(transcriptPath, "utf8"))) : null;
|
|
11808
12019
|
const style = await resolveStyleRef(flags);
|
|
11809
12020
|
const noFrames = flags["no-frames"] === true;
|
|
11810
12021
|
let browser = null;
|
|
@@ -11835,7 +12046,7 @@ async function cmdDigest(argv) {
|
|
|
11835
12046
|
kinds,
|
|
11836
12047
|
frames: d.images.full,
|
|
11837
12048
|
crops: d.images.crop,
|
|
11838
|
-
sheet: d.images.sheet ?
|
|
12049
|
+
sheet: d.images.sheet ? join22(result.outDir, d.images.sheet) : null,
|
|
11839
12050
|
scenes: kinds.scene ?? 0,
|
|
11840
12051
|
sourceDuration: d.take.sourceDuration,
|
|
11841
12052
|
outputDuration: d.take.outputDuration,
|
|
@@ -11858,19 +12069,19 @@ async function cmdDigest(argv) {
|
|
|
11858
12069
|
}
|
|
11859
12070
|
}
|
|
11860
12071
|
async function cmdOpen(argv) {
|
|
11861
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12072
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
11862
12073
|
const dir = positionals[0];
|
|
11863
12074
|
if (!dir) throw new UsageError("vos open <take> [--studio <url>]");
|
|
11864
12075
|
const r = createReporter(flags.json === true);
|
|
11865
12076
|
const take = await loadTake(dir);
|
|
11866
|
-
if (!
|
|
12077
|
+
if (!existsSync19(take.paths.recording)) {
|
|
11867
12078
|
throw new UsageError(`${dir} has no recording \u2014 re-run record`);
|
|
11868
12079
|
}
|
|
11869
12080
|
const studio = (strFlag(flags, "studio") ?? platformOrigin()).replace(
|
|
11870
12081
|
/\/+$/,
|
|
11871
12082
|
""
|
|
11872
12083
|
);
|
|
11873
|
-
const server = await startTakeServer(
|
|
12084
|
+
const server = await startTakeServer(resolve10(dir), {});
|
|
11874
12085
|
const url = `${studio}/studio?take=${encodeURIComponent(server.base)}`;
|
|
11875
12086
|
r.event({ event: "open", server: server.base, url });
|
|
11876
12087
|
r.log(`take served at ${server.base}`);
|
|
@@ -11896,7 +12107,7 @@ async function cmdOpen(argv) {
|
|
|
11896
12107
|
return EXIT_OK;
|
|
11897
12108
|
}
|
|
11898
12109
|
async function cmdJudge(argv) {
|
|
11899
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12110
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
11900
12111
|
const target = positionals[0];
|
|
11901
12112
|
const against = strFlag(flags, "against");
|
|
11902
12113
|
if (!target || !against)
|
|
@@ -11904,12 +12115,12 @@ async function cmdJudge(argv) {
|
|
|
11904
12115
|
"vos judge <kit.json> --against <MANIFEST.json> [--out dir] [--json]\n(the manifest names the reference set: id, file, role, layout, facts, rule per asset)"
|
|
11905
12116
|
);
|
|
11906
12117
|
const r = createReporter(flags.json === true);
|
|
11907
|
-
const kitFile = target.endsWith("kit.json") ? target :
|
|
11908
|
-
if (!
|
|
11909
|
-
if (!
|
|
12118
|
+
const kitFile = target.endsWith("kit.json") ? target : join22(target, "kit.json");
|
|
12119
|
+
if (!existsSync19(kitFile)) throw new UsageError(`${kitFile}: no kit manifest`);
|
|
12120
|
+
if (!existsSync19(against))
|
|
11910
12121
|
throw new UsageError(`${against}: no reference manifest`);
|
|
11911
12122
|
const result = await judgeKit(kitFile, against, strFlag(flags, "out"));
|
|
11912
|
-
const verdicts = JSON.parse(await
|
|
12123
|
+
const verdicts = JSON.parse(await readFile16(result.verdictFile, "utf8")).verdicts;
|
|
11913
12124
|
const rate = winRate(verdicts);
|
|
11914
12125
|
const lines = result.sheets.map(
|
|
11915
12126
|
(s) => `${s.asset} vs ${s.reference}: ${s.sheetA}, ${s.sheetB}, ${s.rubric}`
|
|
@@ -11925,7 +12136,7 @@ Win rate so far: ${rate.wins} win(s), ${rate.ties} tie(s) of ${rate.judged} judg
|
|
|
11925
12136
|
return EXIT_OK;
|
|
11926
12137
|
}
|
|
11927
12138
|
async function cmdCallout(argv) {
|
|
11928
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12139
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
11929
12140
|
const dir = positionals[0];
|
|
11930
12141
|
const shape = positionals[1];
|
|
11931
12142
|
if (!dir || !shape || !isCalloutShape(shape))
|
|
@@ -11949,7 +12160,7 @@ async function cmdCallout(argv) {
|
|
|
11949
12160
|
`no register: put a BRAND.md beside the take (vos brand <url> --out BRAND.md; its bgA and accent are the ground and the accent), or pass --ground #hex --accent #hex`
|
|
11950
12161
|
);
|
|
11951
12162
|
const codeFile = strFlag(flags, "code-file");
|
|
11952
|
-
const code = codeFile ? await
|
|
12163
|
+
const code = codeFile ? await readFile16(codeFile, "utf8") : strFlag(flags, "code");
|
|
11953
12164
|
const words = {
|
|
11954
12165
|
kicker: strFlag(flags, "kicker"),
|
|
11955
12166
|
title: strFlag(flags, "title"),
|
|
@@ -12024,11 +12235,11 @@ async function cmdCallout(argv) {
|
|
|
12024
12235
|
return EXIT_OK;
|
|
12025
12236
|
}
|
|
12026
12237
|
async function cmdValidate(argv) {
|
|
12027
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12238
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
12028
12239
|
const target = positionals[0];
|
|
12029
12240
|
if (!target) throw new UsageError("vos validate <actions.json|take>");
|
|
12030
12241
|
const r = createReporter(flags.json === true);
|
|
12031
|
-
const kitTarget = target.endsWith("kit.json") ? target :
|
|
12242
|
+
const kitTarget = target.endsWith("kit.json") ? target : existsSync19(join22(target, "kit.json")) && !isTakeDir(target) ? join22(target, "kit.json") : null;
|
|
12032
12243
|
if (kitTarget) {
|
|
12033
12244
|
const picture = flags.picture === true;
|
|
12034
12245
|
const verdict = await validateKit(kitTarget, { picture });
|
|
@@ -12060,9 +12271,9 @@ async function cmdValidate(argv) {
|
|
|
12060
12271
|
r.done({ valid: true, target }, `${target}: valid actions file`);
|
|
12061
12272
|
return EXIT_OK;
|
|
12062
12273
|
}
|
|
12063
|
-
if (!isTakeDir(target) &&
|
|
12274
|
+
if (!isTakeDir(target) && existsSync19(join22(target, "config.json"))) {
|
|
12064
12275
|
const parsed = JSON.parse(
|
|
12065
|
-
await
|
|
12276
|
+
await readFile16(join22(target, "config.json"), "utf8")
|
|
12066
12277
|
);
|
|
12067
12278
|
const pre = preflightConfig(parsed);
|
|
12068
12279
|
const problems2 = pre.ok ? [] : pre.issues.map((i) => `config.json: ${i}`);
|
|
@@ -12103,7 +12314,7 @@ async function cmdValidate(argv) {
|
|
|
12103
12314
|
const take = await loadTake(target);
|
|
12104
12315
|
const problems = [];
|
|
12105
12316
|
const warnings = [];
|
|
12106
|
-
if (!
|
|
12317
|
+
if (!existsSync19(take.paths.recording)) {
|
|
12107
12318
|
problems.push("missing recording (re-run record)");
|
|
12108
12319
|
} else {
|
|
12109
12320
|
const mismatch = containerMismatch(
|
|
@@ -12186,7 +12397,7 @@ async function cmdValidate(argv) {
|
|
|
12186
12397
|
async function cmdPush3(argv) {
|
|
12187
12398
|
const { positionals, flags, multi } = parseArgs(
|
|
12188
12399
|
argv,
|
|
12189
|
-
|
|
12400
|
+
BOOLEAN_FLAGS7,
|
|
12190
12401
|
MULTI_FLAGS2
|
|
12191
12402
|
);
|
|
12192
12403
|
const dir = positionals[0];
|
|
@@ -12196,7 +12407,7 @@ async function cmdPush3(argv) {
|
|
|
12196
12407
|
);
|
|
12197
12408
|
const refusal = takePushRefusal({
|
|
12198
12409
|
vos: strFlag(flags, "vos"),
|
|
12199
|
-
trackedVosId: readSyncState(
|
|
12410
|
+
trackedVosId: readSyncState(resolve10(dir))?.vosId ?? null,
|
|
12200
12411
|
programOnly: ["slug", "desc", "tags", "base", "remix-of"].filter(
|
|
12201
12412
|
(name) => hasFlag(flags, name)
|
|
12202
12413
|
)
|
|
@@ -12205,7 +12416,7 @@ async function cmdPush3(argv) {
|
|
|
12205
12416
|
const r = createReporter(flags.json === true);
|
|
12206
12417
|
const overrides = multi.override;
|
|
12207
12418
|
const result = await pushTake(
|
|
12208
|
-
|
|
12419
|
+
resolve10(dir),
|
|
12209
12420
|
{
|
|
12210
12421
|
key: strFlag(flags, "key"),
|
|
12211
12422
|
api: strFlag(flags, "api"),
|
|
@@ -12233,11 +12444,11 @@ async function cmdPush3(argv) {
|
|
|
12233
12444
|
return EXIT_OK;
|
|
12234
12445
|
}
|
|
12235
12446
|
async function cmdPull2(argv) {
|
|
12236
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12447
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7, MULTI_FLAGS2);
|
|
12237
12448
|
const dir = positionals[0] ?? ".";
|
|
12238
12449
|
const r = createReporter(flags.json === true);
|
|
12239
12450
|
const result = await pullTake(
|
|
12240
|
-
|
|
12451
|
+
resolve10(dir),
|
|
12241
12452
|
{
|
|
12242
12453
|
key: strFlag(flags, "key"),
|
|
12243
12454
|
api: strFlag(flags, "api"),
|
|
@@ -12356,6 +12567,8 @@ async function run(argv) {
|
|
|
12356
12567
|
return await cmdSession(rest);
|
|
12357
12568
|
case "actions":
|
|
12358
12569
|
return await cmdActions(rest);
|
|
12570
|
+
case "ingest":
|
|
12571
|
+
return await cmdIngest(rest);
|
|
12359
12572
|
default:
|
|
12360
12573
|
throw new UsageError(`unknown command "${cmd}" \u2014 run: vos help`);
|
|
12361
12574
|
}
|
|
@@ -12388,7 +12601,7 @@ async function run(argv) {
|
|
|
12388
12601
|
}
|
|
12389
12602
|
}
|
|
12390
12603
|
async function cmdSession(argv) {
|
|
12391
|
-
const { positionals, flags } = parseArgs(argv,
|
|
12604
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS7);
|
|
12392
12605
|
const [sub, arg] = positionals;
|
|
12393
12606
|
const r = createReporter(flags.json === true);
|
|
12394
12607
|
const usage = "vos session open <url> --name <app> | check <name> [--url <url>] | list | rm <name>";
|
|
@@ -12424,7 +12637,7 @@ async function cmdSession(argv) {
|
|
|
12424
12637
|
if (!arg) throw new UsageError(usage);
|
|
12425
12638
|
const bad = sessionNameVerdict(arg);
|
|
12426
12639
|
if (bad) throw new UsageError(bad);
|
|
12427
|
-
if (!
|
|
12640
|
+
if (!existsSync19(sessionDir(arg)))
|
|
12428
12641
|
throw new UsageError(`no session "${arg}" (vos session list)`);
|
|
12429
12642
|
const summary2 = await summarizeSession(arg);
|
|
12430
12643
|
const url = strFlag(flags, "url");
|
|
@@ -12531,7 +12744,8 @@ export {
|
|
|
12531
12744
|
MULTI_FLAGS2 as MULTI_FLAGS,
|
|
12532
12745
|
HELP,
|
|
12533
12746
|
takeBrowserArgs,
|
|
12747
|
+
takeBackdrop,
|
|
12534
12748
|
verbHelp,
|
|
12535
12749
|
run
|
|
12536
12750
|
};
|
|
12537
|
-
//# sourceMappingURL=chunk-
|
|
12751
|
+
//# sourceMappingURL=chunk-D6AP7Y3G.js.map
|