@vosjs/cli 0.50.4 → 0.51.0
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 +1 -1
- package/dist/{chunk-D6AP7Y3G.js → chunk-JVINOGJG.js} +118 -70
- package/dist/chunk-JVINOGJG.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/index.js +1 -1
- package/dist/{run-TA44SOE5.js → run-AV3X2454.js} +2 -2
- package/package.json +4 -4
- package/dist/chunk-D6AP7Y3G.js.map +0 -1
- /package/dist/{run-TA44SOE5.js.map → run-AV3X2454.js.map} +0 -0
package/README.md
CHANGED
|
@@ -336,7 +336,7 @@ vos push /tmp/take --label "$TAG launch" --yes --json # VOS_API_KEY as a r
|
|
|
336
336
|
- **`--max-duration <s>`** on `record` and `create` defaults to the hosted recording cap, read live from `GET /api/limits` (2 s, fail-open to 30 min when the origin is unreachable): the capture stops there and the done event says so. Cut the flow rather than raising the cap; the platform refuses a longer take.
|
|
337
337
|
- **`create`** is the one-shot verb: record, auto-plan and render in one command and one browser session. The take directory still lands on disk, so the full loop (frames, edit `doc.json`, re-render) stays open afterwards.
|
|
338
338
|
- **`vos validate <thing>`** takes an `actions.json`, a take directory, a program directory (`config.json`, plus its program document when present), or a `kit.json`; exit 1 on any problem.
|
|
339
|
-
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports). `vos voila <verb>` is still accepted as an alias of `vos <verb>` and says so.
|
|
339
|
+
- **Environment.** `VOS_ORIGIN` (the platform, and the studio `vos open` opens), `VOS_API_KEY`, `VOS_BROWSER_PATH`, `VOS_CLIENT` (the client string a push self-reports; unset, a push names the coding agent that spawned the CLI, read from its environment the way `@vercel/detect-agent` reads it, e.g. `claude-code vos-cli`, else `vos-cli`). `vos voila <verb>` is still accepted as an alias of `vos <verb>` and says so.
|
|
340
340
|
|
|
341
341
|
## Programmatic use
|
|
342
342
|
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
|
|
14
14
|
// src/plugin/run.ts
|
|
15
15
|
import { mkdir as mkdir11, readFile as readFile16, rm as rm5 } from "fs/promises";
|
|
16
|
-
import { existsSync as
|
|
16
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17
17
|
import { join as join22, resolve as resolve10 } from "path";
|
|
18
18
|
import {
|
|
19
19
|
END_CARD_FROM as END_CARD_FROM2,
|
|
@@ -3497,7 +3497,7 @@ async function writeIndexJson(result) {
|
|
|
3497
3497
|
import { mkdir as mkdir5, mkdtemp, rename as rename5, rm as rm4, stat as stat2, writeFile as writeFile7 } from "fs/promises";
|
|
3498
3498
|
import { tmpdir } from "os";
|
|
3499
3499
|
import { join as join8, relative, resolve as resolve4 } from "path";
|
|
3500
|
-
import { existsSync as
|
|
3500
|
+
import { existsSync as existsSync8 } from "fs";
|
|
3501
3501
|
import { readFile as readFile6 } from "fs/promises";
|
|
3502
3502
|
import { parseFrontmatter } from "@vosjs/shared/frontmatter";
|
|
3503
3503
|
import {
|
|
@@ -4477,7 +4477,7 @@ function isLightHexGround(hex2) {
|
|
|
4477
4477
|
}
|
|
4478
4478
|
|
|
4479
4479
|
// src/plugin/posterDoc.ts
|
|
4480
|
-
import { existsSync as
|
|
4480
|
+
import { existsSync as existsSync7 } from "fs";
|
|
4481
4481
|
import { readFile as readFile5 } from "fs/promises";
|
|
4482
4482
|
import { isAbsolute, join as join7, resolve as resolve3 } from "path";
|
|
4483
4483
|
import {
|
|
@@ -4492,6 +4492,52 @@ import {
|
|
|
4492
4492
|
import { mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
4493
4493
|
import { homedir } from "os";
|
|
4494
4494
|
import { join as join6 } from "path";
|
|
4495
|
+
|
|
4496
|
+
// src/plugin/hostAgent.ts
|
|
4497
|
+
import { existsSync as existsSync6 } from "fs";
|
|
4498
|
+
var SLUG = /^[a-z0-9][a-z0-9.-]{0,39}$/;
|
|
4499
|
+
var MARKERS = [
|
|
4500
|
+
["cursor", (e) => !!e.CURSOR_TRACE_ID],
|
|
4501
|
+
[
|
|
4502
|
+
"cursor-cli",
|
|
4503
|
+
(e) => !!e.CURSOR_AGENT || e.CURSOR_EXTENSION_HOST_ROLE === "agent-exec"
|
|
4504
|
+
],
|
|
4505
|
+
["gemini-cli", (e) => !!e.GEMINI_CLI],
|
|
4506
|
+
["codex", (e) => !!(e.CODEX_SANDBOX || e.CODEX_CI || e.CODEX_THREAD_ID)],
|
|
4507
|
+
["antigravity", (e) => !!e.ANTIGRAVITY_AGENT],
|
|
4508
|
+
["augment-cli", (e) => !!e.AUGMENT_AGENT],
|
|
4509
|
+
["opencode", (e) => !!e.OPENCODE_CLIENT],
|
|
4510
|
+
[
|
|
4511
|
+
"claude-code",
|
|
4512
|
+
(e) => !!(e.CLAUDECODE || e.CLAUDE_CODE) && !e.CLAUDE_CODE_IS_COWORK
|
|
4513
|
+
],
|
|
4514
|
+
["claude-cowork", (e) => !!(e.CLAUDECODE || e.CLAUDE_CODE)],
|
|
4515
|
+
["replit", (e) => !!e.REPL_ID],
|
|
4516
|
+
[
|
|
4517
|
+
"github-copilot",
|
|
4518
|
+
(e) => !!(e.COPILOT_MODEL || e.COPILOT_ALLOW_ALL || e.COPILOT_GITHUB_TOKEN)
|
|
4519
|
+
]
|
|
4520
|
+
];
|
|
4521
|
+
var DEVIN_LOCAL_PATH = "/opt/.devin";
|
|
4522
|
+
function slugFromAiAgent(value) {
|
|
4523
|
+
const head = value.trim().toLowerCase().split("_")[0] ?? "";
|
|
4524
|
+
if (head === "github-copilot-cli") return "github-copilot";
|
|
4525
|
+
return SLUG.test(head) ? head : null;
|
|
4526
|
+
}
|
|
4527
|
+
function detectHostAgent(env = process.env, exists = existsSync6) {
|
|
4528
|
+
if (env.AI_AGENT) {
|
|
4529
|
+
const slug = slugFromAiAgent(env.AI_AGENT);
|
|
4530
|
+
if (slug) return slug;
|
|
4531
|
+
}
|
|
4532
|
+
for (const [slug, test] of MARKERS) if (test(env)) return slug;
|
|
4533
|
+
try {
|
|
4534
|
+
if (exists(DEVIN_LOCAL_PATH)) return "devin";
|
|
4535
|
+
} catch {
|
|
4536
|
+
}
|
|
4537
|
+
return null;
|
|
4538
|
+
}
|
|
4539
|
+
|
|
4540
|
+
// src/plugin/platform.ts
|
|
4495
4541
|
function platformOrigin(flags = {}) {
|
|
4496
4542
|
const legacyEnv = process.env.VOS_API_BASE?.trim();
|
|
4497
4543
|
const raw = flags.origin ?? flags.api ?? process.env.VOS_ORIGIN?.trim() ?? legacyEnv ?? "https://vos.so";
|
|
@@ -4552,10 +4598,12 @@ function writeCredential(key) {
|
|
|
4552
4598
|
`, { mode: 384 });
|
|
4553
4599
|
return CREDENTIALS_PATH;
|
|
4554
4600
|
}
|
|
4555
|
-
function clientId() {
|
|
4556
|
-
const
|
|
4557
|
-
if (
|
|
4558
|
-
|
|
4601
|
+
function clientId(env = process.env, exists) {
|
|
4602
|
+
const explicit = env.VOS_CLIENT?.trim();
|
|
4603
|
+
if (explicit && explicit.length <= 60 && !/[\r\n]/.test(explicit))
|
|
4604
|
+
return explicit;
|
|
4605
|
+
const host = detectHostAgent(env, exists);
|
|
4606
|
+
return host ? `${host} vos-cli` : "vos-cli";
|
|
4559
4607
|
}
|
|
4560
4608
|
async function apiJson(origin, path, init = {}) {
|
|
4561
4609
|
const headers = {
|
|
@@ -4667,9 +4715,9 @@ var roleFor = (cls) => `poster-${cls}`;
|
|
|
4667
4715
|
async function readPosterAt(cls, path, takeDir, from) {
|
|
4668
4716
|
let file = path;
|
|
4669
4717
|
let docDir = path;
|
|
4670
|
-
if (
|
|
4718
|
+
if (existsSync7(join7(path, "doc.json"))) {
|
|
4671
4719
|
file = join7(path, "doc.json");
|
|
4672
|
-
} else if (!/\.json$/i.test(path) || !
|
|
4720
|
+
} else if (!/\.json$/i.test(path) || !existsSync7(path)) {
|
|
4673
4721
|
return null;
|
|
4674
4722
|
} else {
|
|
4675
4723
|
docDir = resolve3(path, "..");
|
|
@@ -4686,7 +4734,7 @@ async function readPosterAt(cls, path, takeDir, from) {
|
|
|
4686
4734
|
const doc = migrateHostedDoc(
|
|
4687
4735
|
raw
|
|
4688
4736
|
);
|
|
4689
|
-
const ownFootage =
|
|
4737
|
+
const ownFootage = existsSync7(join7(docDir, "meta.json")) && existsSync7(join7(docDir, source.videoKey));
|
|
4690
4738
|
const sync = readSyncState(docDir);
|
|
4691
4739
|
return {
|
|
4692
4740
|
cls,
|
|
@@ -4810,7 +4858,7 @@ function resolveChannels(raw) {
|
|
|
4810
4858
|
async function readBrandBesideTake(dir, explicit) {
|
|
4811
4859
|
const candidates = explicit ? [explicit] : [join8(dir, "BRAND.md"), join8(dir, "..", "BRAND.md")];
|
|
4812
4860
|
for (const file of candidates) {
|
|
4813
|
-
if (!
|
|
4861
|
+
if (!existsSync8(file)) continue;
|
|
4814
4862
|
const roles = parseFrontmatter(await readFile6(file, "utf8"));
|
|
4815
4863
|
return { file, roles };
|
|
4816
4864
|
}
|
|
@@ -4819,7 +4867,7 @@ async function readBrandBesideTake(dir, explicit) {
|
|
|
4819
4867
|
async function readLaunchBesideTake(dir, explicit) {
|
|
4820
4868
|
const candidates = explicit ? [explicit] : [join8(dir, "LAUNCH.md"), join8(dir, "..", "LAUNCH.md")];
|
|
4821
4869
|
for (const file of candidates) {
|
|
4822
|
-
if (!
|
|
4870
|
+
if (!existsSync8(file)) continue;
|
|
4823
4871
|
return { file, roles: parseFrontmatter(await readFile6(file, "utf8")) };
|
|
4824
4872
|
}
|
|
4825
4873
|
return null;
|
|
@@ -5206,7 +5254,7 @@ async function deliverTake(browser, dir, opts) {
|
|
|
5206
5254
|
|
|
5207
5255
|
// src/plugin/markAsset.ts
|
|
5208
5256
|
import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
|
|
5209
|
-
import { existsSync as
|
|
5257
|
+
import { existsSync as existsSync9 } from "fs";
|
|
5210
5258
|
import { isAbsolute as isAbsolute2, join as join9, resolve as resolve5 } from "path";
|
|
5211
5259
|
function markExtension(url) {
|
|
5212
5260
|
const m = /\.(svg|png|webp|jpe?g)(?:[?#]|$)/i.exec(url);
|
|
@@ -5289,7 +5337,7 @@ async function fetchBrandMarks(takeDir, roles) {
|
|
|
5289
5337
|
bytes = new Uint8Array(await res.arrayBuffer());
|
|
5290
5338
|
} else {
|
|
5291
5339
|
const file = isAbsolute2(src) ? src : resolve5(takeDir, src);
|
|
5292
|
-
if (!
|
|
5340
|
+
if (!existsSync9(file)) throw new Error("no such file");
|
|
5293
5341
|
bytes = new Uint8Array(await readFile7(file));
|
|
5294
5342
|
}
|
|
5295
5343
|
} catch (e) {
|
|
@@ -5342,7 +5390,7 @@ async function fetchMusicCatalog(origin) {
|
|
|
5342
5390
|
}
|
|
5343
5391
|
|
|
5344
5392
|
// src/plugin/judge.ts
|
|
5345
|
-
import { existsSync as
|
|
5393
|
+
import { existsSync as existsSync10 } from "fs";
|
|
5346
5394
|
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile9 } from "fs/promises";
|
|
5347
5395
|
import { dirname as dirname2, isAbsolute as isAbsolute3, join as join10, resolve as resolve6 } from "path";
|
|
5348
5396
|
import { DESTINATIONS as DESTINATIONS2 } from "@vosjs/studio-core";
|
|
@@ -5529,14 +5577,14 @@ async function judgeKit(kitPath, manifestPath, outDir) {
|
|
|
5529
5577
|
const loadRef = async (file) => {
|
|
5530
5578
|
if (refCache.has(file)) return refCache.get(file) ?? null;
|
|
5531
5579
|
const p = join10(manifestDir, file);
|
|
5532
|
-
const img =
|
|
5580
|
+
const img = existsSync10(p) ? decodePng(new Uint8Array(await readFile8(p))) : null;
|
|
5533
5581
|
refCache.set(file, img);
|
|
5534
5582
|
return img;
|
|
5535
5583
|
};
|
|
5536
5584
|
for (const a of kit.assets) {
|
|
5537
5585
|
if (!/\.png$/i.test(a.path)) continue;
|
|
5538
|
-
const file = isAbsolute3(a.path) &&
|
|
5539
|
-
const img =
|
|
5586
|
+
const file = isAbsolute3(a.path) && existsSync10(a.path) ? a.path : join10(kitDir, a.path.split("/").pop() ?? a.path);
|
|
5587
|
+
const img = existsSync10(file) ? decodePng(new Uint8Array(await readFile8(file))) : null;
|
|
5540
5588
|
if (!img) {
|
|
5541
5589
|
skipped.push(`${a.destination ?? a.path}: unreadable`);
|
|
5542
5590
|
continue;
|
|
@@ -5598,7 +5646,7 @@ async function judgeKit(kitPath, manifestPath, outDir) {
|
|
|
5598
5646
|
});
|
|
5599
5647
|
}
|
|
5600
5648
|
const verdictFile = join10(out, "judge.json");
|
|
5601
|
-
if (!
|
|
5649
|
+
if (!existsSync10(verdictFile)) {
|
|
5602
5650
|
await writeFile9(
|
|
5603
5651
|
verdictFile,
|
|
5604
5652
|
JSON.stringify(
|
|
@@ -5650,7 +5698,7 @@ function catalogFamily(family) {
|
|
|
5650
5698
|
}
|
|
5651
5699
|
|
|
5652
5700
|
// src/plugin/callout.ts
|
|
5653
|
-
import { existsSync as
|
|
5701
|
+
import { existsSync as existsSync11 } from "fs";
|
|
5654
5702
|
import { readFile as readFile9 } from "fs/promises";
|
|
5655
5703
|
import { join as join11 } from "path";
|
|
5656
5704
|
import { lerpArray, sample } from "@vosjs/timeline";
|
|
@@ -5852,7 +5900,7 @@ async function footageFrames(browser, dir, doc, times, framesTake2) {
|
|
|
5852
5900
|
const outDir = join11(dir, ".ground-check");
|
|
5853
5901
|
const res = await framesTake2(browser, dir, { times, outDir, doc: bare });
|
|
5854
5902
|
for (const f of res.frames) {
|
|
5855
|
-
if (!
|
|
5903
|
+
if (!existsSync11(f.file)) continue;
|
|
5856
5904
|
out.set(
|
|
5857
5905
|
+f.time.toFixed(3),
|
|
5858
5906
|
decodePng(new Uint8Array(await readFile9(f.file)))
|
|
@@ -6233,7 +6281,7 @@ function formatFinding(f) {
|
|
|
6233
6281
|
}
|
|
6234
6282
|
|
|
6235
6283
|
// src/plugin/validateKit.ts
|
|
6236
|
-
import { existsSync as
|
|
6284
|
+
import { existsSync as existsSync12 } from "fs";
|
|
6237
6285
|
import { readFile as readFile11, stat as stat3 } from "fs/promises";
|
|
6238
6286
|
import { dirname as dirname3, isAbsolute as isAbsolute4, join as join12 } from "path";
|
|
6239
6287
|
import { DESTINATIONS as DESTINATIONS3 } from "@vosjs/studio-core";
|
|
@@ -6294,7 +6342,7 @@ async function validateKit(kitPath, opts = {}) {
|
|
|
6294
6342
|
}
|
|
6295
6343
|
const base = dirname3(kitPath);
|
|
6296
6344
|
const resolvePath = (p) => {
|
|
6297
|
-
if (isAbsolute4(p) &&
|
|
6345
|
+
if (isAbsolute4(p) && existsSync12(p)) return p;
|
|
6298
6346
|
const beside = join12(base, p.split("/").pop() ?? p);
|
|
6299
6347
|
return beside;
|
|
6300
6348
|
};
|
|
@@ -6493,7 +6541,7 @@ import {
|
|
|
6493
6541
|
|
|
6494
6542
|
// src/plugin/session.ts
|
|
6495
6543
|
import { spawn } from "child_process";
|
|
6496
|
-
import { existsSync as
|
|
6544
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync2, readdirSync as readdirSync2, rmSync, statSync as statSync3 } from "fs";
|
|
6497
6545
|
import { homedir as homedir2 } from "os";
|
|
6498
6546
|
import { join as join14 } from "path";
|
|
6499
6547
|
import { chromium } from "playwright";
|
|
@@ -6531,7 +6579,7 @@ function systemChromePath() {
|
|
|
6531
6579
|
"/usr/bin/google-chrome-stable",
|
|
6532
6580
|
"/opt/google/chrome/chrome"
|
|
6533
6581
|
];
|
|
6534
|
-
const found = candidates.find((c) =>
|
|
6582
|
+
const found = candidates.find((c) => existsSync13(c));
|
|
6535
6583
|
if (!found)
|
|
6536
6584
|
throw new Error(
|
|
6537
6585
|
"no Google Chrome found: a session needs the system Chrome (the bundled Chromium cannot read a profile Chrome wrote). Install Chrome, or set VOS_BROWSER_PATH"
|
|
@@ -6562,7 +6610,7 @@ async function openSession(name, url, opts = { log: () => {
|
|
|
6562
6610
|
}
|
|
6563
6611
|
async function withSession(name, fn, opts = {}) {
|
|
6564
6612
|
const dir = sessionDir(name);
|
|
6565
|
-
if (!
|
|
6613
|
+
if (!existsSync13(dir))
|
|
6566
6614
|
throw new Error(`no session "${name}" (vos session list)`);
|
|
6567
6615
|
const explicit = process.env.VOS_BROWSER_PATH;
|
|
6568
6616
|
const ctx = await chromium.launchPersistentContext(dir, {
|
|
@@ -6611,7 +6659,7 @@ function summaryLine(s) {
|
|
|
6611
6659
|
return `session "${s.name}" holds cookies for ${hosts}${more}; ${exp}`;
|
|
6612
6660
|
}
|
|
6613
6661
|
function listSessions() {
|
|
6614
|
-
if (!
|
|
6662
|
+
if (!existsSync13(SESSIONS_DIR)) return [];
|
|
6615
6663
|
return readdirSync2(SESSIONS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory() && NAME.test(d.name)).map((d) => {
|
|
6616
6664
|
const st = statSync3(join14(SESSIONS_DIR, d.name));
|
|
6617
6665
|
return {
|
|
@@ -6624,7 +6672,7 @@ function listSessions() {
|
|
|
6624
6672
|
}
|
|
6625
6673
|
function removeSession(name) {
|
|
6626
6674
|
const dir = sessionDir(name);
|
|
6627
|
-
if (!
|
|
6675
|
+
if (!existsSync13(dir)) return false;
|
|
6628
6676
|
rmSync(dir, { recursive: true, force: true });
|
|
6629
6677
|
return true;
|
|
6630
6678
|
}
|
|
@@ -6689,7 +6737,7 @@ async function encodeRecording(browser, takeDir, onProgress) {
|
|
|
6689
6737
|
}
|
|
6690
6738
|
|
|
6691
6739
|
// src/plugin/plan.ts
|
|
6692
|
-
import { existsSync as
|
|
6740
|
+
import { existsSync as existsSync14 } from "fs";
|
|
6693
6741
|
import { readFile as readFile12 } from "fs/promises";
|
|
6694
6742
|
import { join as join15 } from "path";
|
|
6695
6743
|
import {
|
|
@@ -6914,7 +6962,7 @@ function retimeCut(prev, newSteps, newDurationMs) {
|
|
|
6914
6962
|
var overlaps = (a, b) => a.in < b.out && b.in < a.out;
|
|
6915
6963
|
async function readDigestActivity(dir) {
|
|
6916
6964
|
const file = join15(dir, "digest", "digest.json");
|
|
6917
|
-
if (!
|
|
6965
|
+
if (!existsSync14(file)) return null;
|
|
6918
6966
|
try {
|
|
6919
6967
|
const d = JSON.parse(await readFile12(file, "utf8"));
|
|
6920
6968
|
return Array.isArray(d.activity) && d.activity.every((v) => typeof v === "number") ? d.activity : null;
|
|
@@ -7130,7 +7178,7 @@ async function planTake(dir, opts = {}) {
|
|
|
7130
7178
|
|
|
7131
7179
|
// src/plugin/sync.ts
|
|
7132
7180
|
import { createHash } from "crypto";
|
|
7133
|
-
import { existsSync as
|
|
7181
|
+
import { existsSync as existsSync15, readFileSync as readFileSync3, readdirSync as readdirSync3 } from "fs";
|
|
7134
7182
|
import { readFile as readFile13 } from "fs/promises";
|
|
7135
7183
|
import { createInterface } from "readline/promises";
|
|
7136
7184
|
import { basename as basename3, join as join17 } from "path";
|
|
@@ -7656,7 +7704,7 @@ async function pushTake(dir, flags, r) {
|
|
|
7656
7704
|
throw new Error(`doc.json fails lint:
|
|
7657
7705
|
${lint.problems.join("\n ")}`);
|
|
7658
7706
|
}
|
|
7659
|
-
if (!
|
|
7707
|
+
if (!existsSync15(take.paths.recording)) {
|
|
7660
7708
|
throw new Error(
|
|
7661
7709
|
"no recording in this take \u2014 record it, or `vos pull --media` to bring it home"
|
|
7662
7710
|
);
|
|
@@ -7749,7 +7797,7 @@ async function pushTake(dir, flags, r) {
|
|
|
7749
7797
|
}
|
|
7750
7798
|
for (const ref of docMediaRefs(docForPush)) {
|
|
7751
7799
|
const file = join17(dir, takeRelativeFile(ref.key));
|
|
7752
|
-
if (!
|
|
7800
|
+
if (!existsSync15(file)) {
|
|
7753
7801
|
r.log(` ${ref.where}: ${ref.key} is not in the take \u2014 left as is`);
|
|
7754
7802
|
continue;
|
|
7755
7803
|
}
|
|
@@ -7893,7 +7941,7 @@ async function pullTake(dir, flags, r) {
|
|
|
7893
7941
|
};
|
|
7894
7942
|
}
|
|
7895
7943
|
let media2;
|
|
7896
|
-
if (flags.media &&
|
|
7944
|
+
if (flags.media && existsSync15(join17(dir, "doc.json"))) {
|
|
7897
7945
|
const local = JSON.parse(
|
|
7898
7946
|
await readFile13(join17(dir, "doc.json"), "utf8")
|
|
7899
7947
|
);
|
|
@@ -7956,7 +8004,7 @@ async function pullTake(dir, flags, r) {
|
|
|
7956
8004
|
const hostedDoc = migrateHostedDoc3(docRes.json);
|
|
7957
8005
|
const doc = hostedDoc;
|
|
7958
8006
|
const localRecording = takeMediaFile(dir, "recording", RECORDING_NAME);
|
|
7959
|
-
if (
|
|
8007
|
+
if (existsSync15(localRecording)) {
|
|
7960
8008
|
doc.source.videoKey = basename3(localRecording);
|
|
7961
8009
|
}
|
|
7962
8010
|
await writeJson(join17(dir, "doc.json"), doc, true);
|
|
@@ -7978,7 +8026,7 @@ async function pullTake(dir, flags, r) {
|
|
|
7978
8026
|
}
|
|
7979
8027
|
|
|
7980
8028
|
// src/plugin/program.ts
|
|
7981
|
-
import { existsSync as
|
|
8029
|
+
import { existsSync as existsSync16 } from "fs";
|
|
7982
8030
|
import { mkdir as mkdir9, readFile as readFile14, writeFile as writeFile11 } from "fs/promises";
|
|
7983
8031
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
7984
8032
|
import { basename as basename4, dirname as dirname4, join as join18 } from "path";
|
|
@@ -8187,7 +8235,7 @@ function preflightConfig(parsed) {
|
|
|
8187
8235
|
function resolveConfigPath(target) {
|
|
8188
8236
|
if (target.endsWith(".json")) return target;
|
|
8189
8237
|
const inDir = join18(target, "config.json");
|
|
8190
|
-
if (
|
|
8238
|
+
if (existsSync16(inDir)) return inDir;
|
|
8191
8239
|
throw new UsageError(
|
|
8192
8240
|
`${target} has no config.json (and is not a take \u2014 no doc.json)`
|
|
8193
8241
|
);
|
|
@@ -8610,7 +8658,7 @@ async function cmdPullProgram(argv) {
|
|
|
8610
8658
|
throw new Error(apiError(`fetch head config for ${vosId}`, cfg));
|
|
8611
8659
|
const configPath = join18(dir, "config.json");
|
|
8612
8660
|
let backedUp = false;
|
|
8613
|
-
if (
|
|
8661
|
+
if (existsSync16(configPath)) {
|
|
8614
8662
|
await writeFile11(join18(dir, "config.backup.json"), await readFile14(configPath));
|
|
8615
8663
|
backedUp = true;
|
|
8616
8664
|
}
|
|
@@ -8722,7 +8770,7 @@ function storedProgramConfig(config, programDoc) {
|
|
|
8722
8770
|
}
|
|
8723
8771
|
async function readProgramDoc(dir, config) {
|
|
8724
8772
|
const docPath = join18(dir, "doc.json");
|
|
8725
|
-
if (!
|
|
8773
|
+
if (!existsSync16(docPath)) return null;
|
|
8726
8774
|
const parsed = JSON.parse(await readFile14(docPath, "utf8"));
|
|
8727
8775
|
if (typeof parsed !== "object" || parsed === null || "source" in parsed)
|
|
8728
8776
|
return null;
|
|
@@ -9940,7 +9988,7 @@ async function cmdActionsScript(input, flags) {
|
|
|
9940
9988
|
}
|
|
9941
9989
|
|
|
9942
9990
|
// src/plugin/ingest.ts
|
|
9943
|
-
import { existsSync as
|
|
9991
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9944
9992
|
import { copyFile, mkdir as mkdir10, readFile as readFile15, stat as stat4 } from "fs/promises";
|
|
9945
9993
|
import { basename as basename7, join as join19, resolve as resolve9 } from "path";
|
|
9946
9994
|
import { inflateRawSync } from "zlib";
|
|
@@ -10060,7 +10108,7 @@ async function cmdIngest(argv) {
|
|
|
10060
10108
|
"vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]"
|
|
10061
10109
|
);
|
|
10062
10110
|
const videoPath = resolve9(source);
|
|
10063
|
-
if (!
|
|
10111
|
+
if (!existsSync17(videoPath)) throw new UsageError(`${source}: no such file`);
|
|
10064
10112
|
const r = createReporter(flags.json === true);
|
|
10065
10113
|
const outDir = resolve9(strFlag(flags, "out") ?? "take");
|
|
10066
10114
|
const offsetMs = numFlag(flags, "offset", 0);
|
|
@@ -10079,7 +10127,7 @@ async function cmdIngest(argv) {
|
|
|
10079
10127
|
trace = await readTraceFile(resolve9(cursorPath), offsetMs);
|
|
10080
10128
|
for (const n of trace.notes) r.log(`note: ${n}`);
|
|
10081
10129
|
}
|
|
10082
|
-
if (
|
|
10130
|
+
if (existsSync17(join19(outDir, "meta.json"))) {
|
|
10083
10131
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
10084
10132
|
r.log(
|
|
10085
10133
|
`note: re-ingesting into ${outDir}; kept ${kept.length ? kept.join(", ") : "nothing"}` + (prevDoc ? `; apply the previous cut with: vos plan ${outDir} --reuse` : "")
|
|
@@ -10152,7 +10200,7 @@ async function cmdIngest(argv) {
|
|
|
10152
10200
|
import { spawnSync } from "child_process";
|
|
10153
10201
|
import {
|
|
10154
10202
|
cpSync,
|
|
10155
|
-
existsSync as
|
|
10203
|
+
existsSync as existsSync19,
|
|
10156
10204
|
mkdirSync as mkdirSync3,
|
|
10157
10205
|
readFileSync as readFileSync7,
|
|
10158
10206
|
rmSync as rmSync2,
|
|
@@ -10163,7 +10211,7 @@ import { join as join21 } from "path";
|
|
|
10163
10211
|
import { chromium as chromium2 } from "playwright";
|
|
10164
10212
|
|
|
10165
10213
|
// src/plugin/machine.ts
|
|
10166
|
-
import { existsSync as
|
|
10214
|
+
import { existsSync as existsSync18, readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
|
|
10167
10215
|
import { dirname as dirname5, join as join20 } from "path";
|
|
10168
10216
|
var AGENT_NAMES = [
|
|
10169
10217
|
"claude",
|
|
@@ -10184,7 +10232,7 @@ var HOME_DIRS = {
|
|
|
10184
10232
|
copilot: [".copilot"]
|
|
10185
10233
|
};
|
|
10186
10234
|
function detectAgents(root, opts = {}) {
|
|
10187
|
-
const exists = opts.exists ??
|
|
10235
|
+
const exists = opts.exists ?? existsSync18;
|
|
10188
10236
|
const out = [];
|
|
10189
10237
|
for (const agent of AGENT_NAMES) {
|
|
10190
10238
|
for (const rel of PROJECT_DIRS[agent]) {
|
|
@@ -10231,7 +10279,7 @@ function skillsDirFor(home) {
|
|
|
10231
10279
|
function fallbackSkillsHome(root) {
|
|
10232
10280
|
return { agent: "codex", dir: join20(root, ".agents"), scope: "project" };
|
|
10233
10281
|
}
|
|
10234
|
-
function installedSkills(dir, exists =
|
|
10282
|
+
function installedSkills(dir, exists = existsSync18, list = (p) => {
|
|
10235
10283
|
try {
|
|
10236
10284
|
return readdirSync4(p);
|
|
10237
10285
|
} catch {
|
|
@@ -10271,7 +10319,7 @@ ${RULES_BLOCK}
|
|
|
10271
10319
|
}
|
|
10272
10320
|
return { text, changed: text !== current };
|
|
10273
10321
|
}
|
|
10274
|
-
function rulesFileFor(root, exists =
|
|
10322
|
+
function rulesFileFor(root, exists = existsSync18) {
|
|
10275
10323
|
const agents = join20(root, "AGENTS.md");
|
|
10276
10324
|
if (exists(agents)) return agents;
|
|
10277
10325
|
const claude = join20(root, "CLAUDE.md");
|
|
@@ -10378,12 +10426,12 @@ function bundledSkillsDir(from) {
|
|
|
10378
10426
|
let dir = dirname5(from);
|
|
10379
10427
|
for (let i = 0; i < 6; i++) {
|
|
10380
10428
|
const pkg = join20(dir, "package.json");
|
|
10381
|
-
if (
|
|
10429
|
+
if (existsSync18(pkg)) {
|
|
10382
10430
|
try {
|
|
10383
10431
|
const name = JSON.parse(readFileSync6(pkg, "utf8")).name;
|
|
10384
10432
|
if (name === "@vosjs/cli") {
|
|
10385
10433
|
const skills = join20(dir, "skills");
|
|
10386
|
-
return
|
|
10434
|
+
return existsSync18(skills) && statSync4(skills).isDirectory() ? skills : null;
|
|
10387
10435
|
}
|
|
10388
10436
|
} catch {
|
|
10389
10437
|
}
|
|
@@ -10414,7 +10462,7 @@ function npx() {
|
|
|
10414
10462
|
function bundledChromium() {
|
|
10415
10463
|
try {
|
|
10416
10464
|
const p = chromium2.executablePath();
|
|
10417
|
-
return p &&
|
|
10465
|
+
return p && existsSync19(p) ? p : null;
|
|
10418
10466
|
} catch {
|
|
10419
10467
|
return null;
|
|
10420
10468
|
}
|
|
@@ -10423,7 +10471,7 @@ function probe() {
|
|
|
10423
10471
|
return probeBrowser({
|
|
10424
10472
|
platform: process.platform,
|
|
10425
10473
|
env: process.env,
|
|
10426
|
-
exists:
|
|
10474
|
+
exists: existsSync19,
|
|
10427
10475
|
bundled: bundledChromium
|
|
10428
10476
|
});
|
|
10429
10477
|
}
|
|
@@ -10562,7 +10610,7 @@ async function cmdSetup(argv) {
|
|
|
10562
10610
|
let rules = null;
|
|
10563
10611
|
if (!noRules) {
|
|
10564
10612
|
const file = rulesFileFor(root);
|
|
10565
|
-
const existing =
|
|
10613
|
+
const existing = existsSync19(file) ? readFileSync7(file, "utf8") : null;
|
|
10566
10614
|
const { text, changed } = applyRulesBlock(existing);
|
|
10567
10615
|
if (changed) writeFileSync3(file, text);
|
|
10568
10616
|
rules = { file, changed };
|
|
@@ -10676,7 +10724,7 @@ async function cmdWhoami(argv) {
|
|
|
10676
10724
|
function cmdLogout(argv) {
|
|
10677
10725
|
const { flags } = parseArgs(argv, BOOLEAN_FLAGS6);
|
|
10678
10726
|
const r = reporterFor(flags);
|
|
10679
|
-
const had =
|
|
10727
|
+
const had = existsSync19(CREDENTIALS_PATH);
|
|
10680
10728
|
rmSync2(CREDENTIALS_PATH, { force: true });
|
|
10681
10729
|
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
10682
10730
|
r.done(
|
|
@@ -11057,7 +11105,7 @@ function takeStorageState(flags) {
|
|
|
11057
11105
|
const raw = strFlag(flags, "storage-state");
|
|
11058
11106
|
if (!raw) return void 0;
|
|
11059
11107
|
const path = resolve10(raw);
|
|
11060
|
-
if (!
|
|
11108
|
+
if (!existsSync20(path))
|
|
11061
11109
|
throw new UsageError(`--storage-state: no such file: ${path}`);
|
|
11062
11110
|
return path;
|
|
11063
11111
|
}
|
|
@@ -11070,7 +11118,7 @@ function takeSessionName(flags, storageState) {
|
|
|
11070
11118
|
throw new UsageError(
|
|
11071
11119
|
"--session and --storage-state are two doors to one take: a persistent profile cannot take a storage state. Pass one"
|
|
11072
11120
|
);
|
|
11073
|
-
if (!
|
|
11121
|
+
if (!existsSync20(sessionDir(name)))
|
|
11074
11122
|
throw new UsageError(
|
|
11075
11123
|
`no session "${name}". Make one: vos session open <url> --name ${name} (a Chrome window opens; sign in and close it)`
|
|
11076
11124
|
);
|
|
@@ -11293,7 +11341,7 @@ ${lines.join("\n")}
|
|
|
11293
11341
|
}
|
|
11294
11342
|
const paths = takePaths(outDir);
|
|
11295
11343
|
const prepare = async () => {
|
|
11296
|
-
if (
|
|
11344
|
+
if (existsSync20(join22(outDir, "meta.json"))) {
|
|
11297
11345
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
11298
11346
|
r.log(
|
|
11299
11347
|
`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" : "")
|
|
@@ -11400,7 +11448,7 @@ async function cmdCreate2(argv) {
|
|
|
11400
11448
|
const headers = takeHeaders(multi);
|
|
11401
11449
|
const paths = takePaths(outDir);
|
|
11402
11450
|
const prepare = async () => {
|
|
11403
|
-
if (
|
|
11451
|
+
if (existsSync20(join22(outDir, "meta.json"))) {
|
|
11404
11452
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
11405
11453
|
r.log(
|
|
11406
11454
|
`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" : "")
|
|
@@ -11513,7 +11561,7 @@ async function cmdPlan(argv) {
|
|
|
11513
11561
|
let reuse;
|
|
11514
11562
|
if (flags.reuse === true) {
|
|
11515
11563
|
const from = resolve10(strFlag(flags, "from") ?? join22(dir, PREV_DOC_NAME));
|
|
11516
|
-
if (!
|
|
11564
|
+
if (!existsSync20(from)) {
|
|
11517
11565
|
throw new UsageError(
|
|
11518
11566
|
`--reuse: ${from} does not exist \u2014 a re-record into this take writes doc.prev.json, or pass --from <doc.json>`
|
|
11519
11567
|
);
|
|
@@ -11524,7 +11572,7 @@ async function cmdPlan(argv) {
|
|
|
11524
11572
|
};
|
|
11525
11573
|
}
|
|
11526
11574
|
const style = await resolveStyleRef(flags);
|
|
11527
|
-
const hasDoc =
|
|
11575
|
+
const hasDoc = existsSync20(join22(dir, "doc.json"));
|
|
11528
11576
|
const backdrop = hasDoc ? null : await takeBackdrop(flags, r);
|
|
11529
11577
|
const release = await releaseInputs(dir, flags, r, multi.with ?? []);
|
|
11530
11578
|
const motionWanted = !hasDoc || flags.motion === true || flags.fresh === true;
|
|
@@ -11955,11 +12003,11 @@ async function resolveStyleRef(flags) {
|
|
|
11955
12003
|
}
|
|
11956
12004
|
async function resolveDocRef(ref, flags, what) {
|
|
11957
12005
|
const styleRef = ref;
|
|
11958
|
-
const file =
|
|
12006
|
+
const file = existsSync20(styleRef) ? resolve10(
|
|
11959
12007
|
styleRef,
|
|
11960
|
-
|
|
12008
|
+
existsSync20(join22(styleRef, "doc.json")) ? "doc.json" : ""
|
|
11961
12009
|
) : null;
|
|
11962
|
-
if (file &&
|
|
12010
|
+
if (file && existsSync20(file)) {
|
|
11963
12011
|
return {
|
|
11964
12012
|
from: file,
|
|
11965
12013
|
doc: migrateHostedDoc5(
|
|
@@ -12074,7 +12122,7 @@ async function cmdOpen(argv) {
|
|
|
12074
12122
|
if (!dir) throw new UsageError("vos open <take> [--studio <url>]");
|
|
12075
12123
|
const r = createReporter(flags.json === true);
|
|
12076
12124
|
const take = await loadTake(dir);
|
|
12077
|
-
if (!
|
|
12125
|
+
if (!existsSync20(take.paths.recording)) {
|
|
12078
12126
|
throw new UsageError(`${dir} has no recording \u2014 re-run record`);
|
|
12079
12127
|
}
|
|
12080
12128
|
const studio = (strFlag(flags, "studio") ?? platformOrigin()).replace(
|
|
@@ -12116,8 +12164,8 @@ async function cmdJudge(argv) {
|
|
|
12116
12164
|
);
|
|
12117
12165
|
const r = createReporter(flags.json === true);
|
|
12118
12166
|
const kitFile = target.endsWith("kit.json") ? target : join22(target, "kit.json");
|
|
12119
|
-
if (!
|
|
12120
|
-
if (!
|
|
12167
|
+
if (!existsSync20(kitFile)) throw new UsageError(`${kitFile}: no kit manifest`);
|
|
12168
|
+
if (!existsSync20(against))
|
|
12121
12169
|
throw new UsageError(`${against}: no reference manifest`);
|
|
12122
12170
|
const result = await judgeKit(kitFile, against, strFlag(flags, "out"));
|
|
12123
12171
|
const verdicts = JSON.parse(await readFile16(result.verdictFile, "utf8")).verdicts;
|
|
@@ -12239,7 +12287,7 @@ async function cmdValidate(argv) {
|
|
|
12239
12287
|
const target = positionals[0];
|
|
12240
12288
|
if (!target) throw new UsageError("vos validate <actions.json|take>");
|
|
12241
12289
|
const r = createReporter(flags.json === true);
|
|
12242
|
-
const kitTarget = target.endsWith("kit.json") ? target :
|
|
12290
|
+
const kitTarget = target.endsWith("kit.json") ? target : existsSync20(join22(target, "kit.json")) && !isTakeDir(target) ? join22(target, "kit.json") : null;
|
|
12243
12291
|
if (kitTarget) {
|
|
12244
12292
|
const picture = flags.picture === true;
|
|
12245
12293
|
const verdict = await validateKit(kitTarget, { picture });
|
|
@@ -12271,7 +12319,7 @@ async function cmdValidate(argv) {
|
|
|
12271
12319
|
r.done({ valid: true, target }, `${target}: valid actions file`);
|
|
12272
12320
|
return EXIT_OK;
|
|
12273
12321
|
}
|
|
12274
|
-
if (!isTakeDir(target) &&
|
|
12322
|
+
if (!isTakeDir(target) && existsSync20(join22(target, "config.json"))) {
|
|
12275
12323
|
const parsed = JSON.parse(
|
|
12276
12324
|
await readFile16(join22(target, "config.json"), "utf8")
|
|
12277
12325
|
);
|
|
@@ -12314,7 +12362,7 @@ async function cmdValidate(argv) {
|
|
|
12314
12362
|
const take = await loadTake(target);
|
|
12315
12363
|
const problems = [];
|
|
12316
12364
|
const warnings = [];
|
|
12317
|
-
if (!
|
|
12365
|
+
if (!existsSync20(take.paths.recording)) {
|
|
12318
12366
|
problems.push("missing recording (re-run record)");
|
|
12319
12367
|
} else {
|
|
12320
12368
|
const mismatch = containerMismatch(
|
|
@@ -12637,7 +12685,7 @@ async function cmdSession(argv) {
|
|
|
12637
12685
|
if (!arg) throw new UsageError(usage);
|
|
12638
12686
|
const bad = sessionNameVerdict(arg);
|
|
12639
12687
|
if (bad) throw new UsageError(bad);
|
|
12640
|
-
if (!
|
|
12688
|
+
if (!existsSync20(sessionDir(arg)))
|
|
12641
12689
|
throw new UsageError(`no session "${arg}" (vos session list)`);
|
|
12642
12690
|
const summary2 = await summarizeSession(arg);
|
|
12643
12691
|
const url = strFlag(flags, "url");
|
|
@@ -12748,4 +12796,4 @@ export {
|
|
|
12748
12796
|
verbHelp,
|
|
12749
12797
|
run
|
|
12750
12798
|
};
|
|
12751
|
-
//# sourceMappingURL=chunk-
|
|
12799
|
+
//# sourceMappingURL=chunk-JVINOGJG.js.map
|