@vosjs/cli 0.84.0 → 0.86.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 +15 -5
- package/dist/{assetManifest-32VI7OK7.js → assetManifest-QFJ7X6TT.js} +3 -3
- package/dist/{chunk-Q47FUCYN.js → chunk-2LAXJZCG.js} +2 -2
- package/dist/{chunk-OWYOJB7K.js → chunk-7A3PZARL.js} +14 -3
- package/dist/chunk-7A3PZARL.js.map +1 -0
- package/dist/{chunk-EPSYIF2S.js → chunk-PZP76YJI.js} +298 -58
- package/dist/chunk-PZP76YJI.js.map +1 -0
- package/dist/{chunk-M5ZBQFPG.js → chunk-V3RUNUNP.js} +2 -2
- package/dist/{chunk-DM7ADA77.js → chunk-ZXFO32KW.js} +722 -203
- package/dist/chunk-ZXFO32KW.js.map +1 -0
- package/dist/cli.js +7 -7
- package/dist/index.d.ts +37 -13
- package/dist/index.js +5 -5
- package/dist/manifest-OLVFUZTW.js +8 -0
- package/dist/{run-J5Z32LEB.js → run-KB36L2ZI.js} +5 -5
- package/package.json +7 -7
- package/skills/VERSION +1 -1
- package/skills/launch-kit/SKILL.md +6 -2
- package/skills/product-video/SKILL.md +13 -3
- package/skills/vos-cut/SKILL.md +6 -2
- package/skills/vos-score/SKILL.md +15 -5
- package/dist/chunk-DM7ADA77.js.map +0 -1
- package/dist/chunk-EPSYIF2S.js.map +0 -1
- package/dist/chunk-OWYOJB7K.js.map +0 -1
- package/dist/manifest-VTOIEUHJ.js +0 -8
- /package/dist/{assetManifest-32VI7OK7.js.map → assetManifest-QFJ7X6TT.js.map} +0 -0
- /package/dist/{chunk-Q47FUCYN.js.map → chunk-2LAXJZCG.js.map} +0 -0
- /package/dist/{chunk-M5ZBQFPG.js.map → chunk-V3RUNUNP.js.map} +0 -0
- /package/dist/{manifest-VTOIEUHJ.js.map → manifest-OLVFUZTW.js.map} +0 -0
- /package/dist/{run-J5Z32LEB.js.map → run-KB36L2ZI.js.map} +0 -0
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
reencodeStill,
|
|
11
11
|
renderStill,
|
|
12
12
|
videoFormat
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2LAXJZCG.js";
|
|
14
14
|
import {
|
|
15
15
|
PREV_DOC_NAME,
|
|
16
16
|
PasteFileRefusal,
|
|
@@ -46,47 +46,62 @@ import {
|
|
|
46
46
|
uploadDocRefs,
|
|
47
47
|
uploadManifest,
|
|
48
48
|
writeJson
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-V3RUNUNP.js";
|
|
50
50
|
import {
|
|
51
|
+
ACCOUNT_ENV,
|
|
51
52
|
CREDENTIALS_PATH,
|
|
53
|
+
DEFAULT_STORE,
|
|
52
54
|
MEDIA_HEAD_BYTES,
|
|
53
55
|
SYNC_STATE_NAME,
|
|
54
56
|
UsageError,
|
|
57
|
+
accountFrom,
|
|
58
|
+
accountLabel,
|
|
59
|
+
activate,
|
|
55
60
|
apiError,
|
|
56
61
|
apiJson,
|
|
57
62
|
bearerFor,
|
|
58
63
|
clientId,
|
|
59
64
|
containerMismatch,
|
|
65
|
+
credentialFlags,
|
|
60
66
|
deriveSlug,
|
|
61
67
|
detailLine,
|
|
68
|
+
findStored,
|
|
62
69
|
formatChanges,
|
|
63
70
|
hasFlag,
|
|
64
71
|
hostedAssetId,
|
|
72
|
+
isActive,
|
|
73
|
+
lastCredential,
|
|
74
|
+
listStored,
|
|
65
75
|
localFile,
|
|
66
76
|
manifestRefs,
|
|
67
77
|
mintAt,
|
|
68
78
|
nameForType,
|
|
69
79
|
numFlag2 as numFlag,
|
|
80
|
+
originOf,
|
|
70
81
|
parseArgs2 as parseArgs,
|
|
71
82
|
parseVosId,
|
|
72
83
|
platformOrigin,
|
|
73
84
|
prepareOutput,
|
|
74
85
|
programAssets,
|
|
75
86
|
promptHint,
|
|
87
|
+
readActive,
|
|
76
88
|
readSyncState,
|
|
77
89
|
refuseSymlink,
|
|
90
|
+
removeAll,
|
|
91
|
+
removeStored,
|
|
78
92
|
requireCredential,
|
|
79
93
|
resolveCredential,
|
|
80
94
|
resolveMediaType,
|
|
81
95
|
serverWarnings,
|
|
82
96
|
sniffMediaType,
|
|
83
97
|
strFlag,
|
|
98
|
+
switchTarget,
|
|
84
99
|
writeCredential,
|
|
85
100
|
writeFileSafe,
|
|
86
101
|
writeOutput,
|
|
87
102
|
writeOutputSync,
|
|
88
103
|
writeSyncState
|
|
89
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-PZP76YJI.js";
|
|
90
105
|
import {
|
|
91
106
|
deadLine,
|
|
92
107
|
deadWarns
|
|
@@ -149,8 +164,8 @@ function landedLines(l) {
|
|
|
149
164
|
|
|
150
165
|
// src/plugin/run.ts
|
|
151
166
|
import { mkdir as mkdir13, readFile as readFile19, rm as rm7 } from "fs/promises";
|
|
152
|
-
import { existsSync as
|
|
153
|
-
import { dirname as dirname12, join as join33, resolve as
|
|
167
|
+
import { existsSync as existsSync31 } from "fs";
|
|
168
|
+
import { dirname as dirname12, join as join33, resolve as resolve22 } from "path";
|
|
154
169
|
import {
|
|
155
170
|
END_CARD_FROM as END_CARD_FROM2,
|
|
156
171
|
docOutputDuration as docOutputDuration5,
|
|
@@ -4157,6 +4172,7 @@ import {
|
|
|
4157
4172
|
sameMedia,
|
|
4158
4173
|
spanOutputExtent as spanOutputExtent3
|
|
4159
4174
|
} from "@vosjs/studio-core";
|
|
4175
|
+
import { rankBeds, trackBySlug } from "@vosjs/shared/music";
|
|
4160
4176
|
|
|
4161
4177
|
// src/plugin/captionFit.ts
|
|
4162
4178
|
var CAPTION_MAX = 3;
|
|
@@ -4289,10 +4305,30 @@ function proposeTransitions(input, kind) {
|
|
|
4289
4305
|
}
|
|
4290
4306
|
return { doc, count, skipped };
|
|
4291
4307
|
}
|
|
4292
|
-
function
|
|
4308
|
+
function pickBed(catalog, ask, film) {
|
|
4293
4309
|
if (!catalog || !ask || off(ask)) return null;
|
|
4294
4310
|
const want = ask.trim().toLowerCase();
|
|
4295
|
-
|
|
4311
|
+
const exact = trackBySlug(catalog.tracks, want);
|
|
4312
|
+
if (exact) return { track: exact, via: "slug", ranked: null, runnerUp: null };
|
|
4313
|
+
if (film) {
|
|
4314
|
+
const oneWord = !/\s/.test(want);
|
|
4315
|
+
const ranked = rankBeds(catalog.tracks, {
|
|
4316
|
+
...film,
|
|
4317
|
+
...oneWord ? { mood: want } : { words: want }
|
|
4318
|
+
}).filter((r) => r.score !== null);
|
|
4319
|
+
const named = oneWord ? catalog.tracks.some(
|
|
4320
|
+
(t) => (t.mood ?? "").toLowerCase() === want || (t.tags ?? []).some((x) => x.toLowerCase() === want)
|
|
4321
|
+
) : ranked.some((r) => (r.scores?.fit ?? 0) > 0);
|
|
4322
|
+
if (!named || !ranked.length) return null;
|
|
4323
|
+
return {
|
|
4324
|
+
track: ranked[0].track,
|
|
4325
|
+
via: "ranked",
|
|
4326
|
+
ranked: ranked[0],
|
|
4327
|
+
runnerUp: ranked[1] ?? null
|
|
4328
|
+
};
|
|
4329
|
+
}
|
|
4330
|
+
const first = catalog.tracks.find((t) => (t.mood ?? "").toLowerCase() === want) ?? null;
|
|
4331
|
+
return first ? { track: first, via: "first", ranked: null, runnerUp: null } : null;
|
|
4296
4332
|
}
|
|
4297
4333
|
function clickTimes(doc, range2) {
|
|
4298
4334
|
const rated = ratedSegments4(doc);
|
|
@@ -4533,26 +4569,32 @@ function proposeMotion(input, opts) {
|
|
|
4533
4569
|
const clips = (doc.audio ?? []).filter(
|
|
4534
4570
|
(a) => a.id !== BED_ID && !a.id.startsWith(CLICK_ID_PREFIX)
|
|
4535
4571
|
);
|
|
4536
|
-
const
|
|
4537
|
-
if (
|
|
4572
|
+
const picked = pickBed(catalog, launch.music, opts.film);
|
|
4573
|
+
if (picked) {
|
|
4574
|
+
const { track } = picked;
|
|
4538
4575
|
const hasMic = !!doc.source.micKey;
|
|
4539
4576
|
const fadeOut = Math.min(2.5, length * 0.15);
|
|
4577
|
+
const place2 = picked.ranked?.placement ?? null;
|
|
4578
|
+
const start = place2 ? place2.in : 0;
|
|
4579
|
+
const covers = track.duration - start >= length;
|
|
4540
4580
|
clips.push({
|
|
4541
4581
|
id: BED_ID,
|
|
4542
4582
|
key: track.url,
|
|
4543
4583
|
name: track.title,
|
|
4544
4584
|
start: 0,
|
|
4545
|
-
in:
|
|
4546
|
-
out: Math.min(track.duration, length),
|
|
4585
|
+
in: start,
|
|
4586
|
+
out: place2 ? place2.out : Math.min(track.duration, length),
|
|
4547
4587
|
duration: track.duration,
|
|
4548
4588
|
gain: hasMic ? 0.35 : 0.5,
|
|
4549
|
-
fadeIn: 0.6,
|
|
4589
|
+
fadeIn: start > 0 ? 0.8 : 0.6,
|
|
4550
4590
|
fadeOut,
|
|
4551
|
-
loop:
|
|
4552
|
-
loopLen:
|
|
4591
|
+
loop: place2 ? place2.loop : !covers,
|
|
4592
|
+
loopLen: place2 ? place2.loopLen : !covers ? Math.round(length * 1e3) / 1e3 : void 0,
|
|
4553
4593
|
duck: hasMic
|
|
4554
4594
|
});
|
|
4555
|
-
notes.push(
|
|
4595
|
+
notes.push(
|
|
4596
|
+
picked.via === "ranked" && picked.ranked ? `bed ${track.slug} (${picked.ranked.reasons.slice(0, 2).join(", ") || "ranked"}${picked.runnerUp ? `; runner-up ${picked.runnerUp.slug}` : ""})` : `bed ${track.slug}`
|
|
4597
|
+
);
|
|
4556
4598
|
} else if (launch.music && !off(launch.music)) {
|
|
4557
4599
|
skipped.push(
|
|
4558
4600
|
`music "${launch.music}" is not a catalog track or mood${catalog ? "" : " (the catalog could not be read)"}`
|
|
@@ -4829,6 +4871,7 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4829
4871
|
|
|
4830
4872
|
// src/plugin/login.ts
|
|
4831
4873
|
import { hostname } from "os";
|
|
4874
|
+
var storeWith = (store) => store ?? ((key, origin, account) => writeCredential(key, origin, void 0, account));
|
|
4832
4875
|
var LoginUnsupportedError = class extends Error {
|
|
4833
4876
|
constructor() {
|
|
4834
4877
|
super("this origin does not support browser login");
|
|
@@ -4905,12 +4948,14 @@ async function browserLogin(origin, r, opts) {
|
|
|
4905
4948
|
continue;
|
|
4906
4949
|
}
|
|
4907
4950
|
if (res.status === 200 && status === "ok") {
|
|
4908
|
-
const
|
|
4951
|
+
const account = accountFrom(res.body.user);
|
|
4952
|
+
const path = storeWith(opts.store)(
|
|
4909
4953
|
res.body.key,
|
|
4910
|
-
origin
|
|
4954
|
+
origin,
|
|
4955
|
+
account
|
|
4911
4956
|
);
|
|
4912
4957
|
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4913
|
-
return { path, user };
|
|
4958
|
+
return { path, user, account };
|
|
4914
4959
|
}
|
|
4915
4960
|
if (res.status === 429) {
|
|
4916
4961
|
if (status === "key_limit" && !capNoted) {
|
|
@@ -4948,16 +4993,19 @@ async function handoffLogin(url, r, opts = {}) {
|
|
|
4948
4993
|
body: { token: parsed.token, hostname: hostname().slice(0, 64) }
|
|
4949
4994
|
});
|
|
4950
4995
|
if (res.status === 200 && res.body.status === "ok") {
|
|
4951
|
-
const
|
|
4996
|
+
const account = accountFrom(res.body.user);
|
|
4997
|
+
const path = storeWith(opts.store)(
|
|
4952
4998
|
res.body.key,
|
|
4953
|
-
parsed.origin
|
|
4999
|
+
parsed.origin,
|
|
5000
|
+
account
|
|
4954
5001
|
);
|
|
4955
5002
|
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4956
5003
|
return {
|
|
4957
5004
|
path,
|
|
4958
5005
|
user,
|
|
4959
5006
|
keyName: String(res.body.keyName ?? ""),
|
|
4960
|
-
origin: parsed.origin
|
|
5007
|
+
origin: parsed.origin,
|
|
5008
|
+
account
|
|
4961
5009
|
};
|
|
4962
5010
|
}
|
|
4963
5011
|
if (res.status === 404 && !res.body.status) {
|
|
@@ -6039,14 +6087,14 @@ function chromeTree(rows, pid) {
|
|
|
6039
6087
|
}
|
|
6040
6088
|
function readChromeTree(pid) {
|
|
6041
6089
|
if (process.platform === "win32") return Promise.resolve(null);
|
|
6042
|
-
return new Promise((
|
|
6090
|
+
return new Promise((resolve23) => {
|
|
6043
6091
|
execFile2(
|
|
6044
6092
|
"ps",
|
|
6045
6093
|
["-A", "-o", "pid=", "-o", "ppid=", "-o", "command="],
|
|
6046
6094
|
{ maxBuffer: 16 * 1024 * 1024, timeout: 5e3 },
|
|
6047
6095
|
(err, stdout) => {
|
|
6048
|
-
if (err)
|
|
6049
|
-
else
|
|
6096
|
+
if (err) resolve23(null);
|
|
6097
|
+
else resolve23(chromeTree(parseProcessTable(stdout), pid));
|
|
6050
6098
|
}
|
|
6051
6099
|
);
|
|
6052
6100
|
});
|
|
@@ -6148,7 +6196,7 @@ function enterPressed() {
|
|
|
6148
6196
|
} };
|
|
6149
6197
|
const rl = createInterface({ input: process.stdin });
|
|
6150
6198
|
const pressed = new Promise(
|
|
6151
|
-
(
|
|
6199
|
+
(resolve23) => rl.once("line", () => resolve23())
|
|
6152
6200
|
);
|
|
6153
6201
|
return { pressed, close: () => rl.close() };
|
|
6154
6202
|
}
|
|
@@ -6321,14 +6369,14 @@ async function openSessionWindow(opts) {
|
|
|
6321
6369
|
const child = spawn(exe, args, { stdio: "ignore" });
|
|
6322
6370
|
let failed = null;
|
|
6323
6371
|
let code = null;
|
|
6324
|
-
const exited = new Promise((
|
|
6372
|
+
const exited = new Promise((resolve23) => {
|
|
6325
6373
|
child.once("exit", (c) => {
|
|
6326
6374
|
code = c;
|
|
6327
|
-
|
|
6375
|
+
resolve23();
|
|
6328
6376
|
});
|
|
6329
6377
|
child.once("error", (e) => {
|
|
6330
6378
|
failed = e;
|
|
6331
|
-
|
|
6379
|
+
resolve23();
|
|
6332
6380
|
});
|
|
6333
6381
|
});
|
|
6334
6382
|
try {
|
|
@@ -6776,12 +6824,13 @@ async function encodeRecording(browser, takeDir, onProgress) {
|
|
|
6776
6824
|
// src/plugin/plan.ts
|
|
6777
6825
|
import { existsSync as existsSync11 } from "fs";
|
|
6778
6826
|
import { readFile as readFile9 } from "fs/promises";
|
|
6779
|
-
import { join as join11 } from "path";
|
|
6827
|
+
import { basename, join as join11 } from "path";
|
|
6780
6828
|
import {
|
|
6781
6829
|
DEFAULT_FRAME_STYLE,
|
|
6782
6830
|
STYLE_FIELDS,
|
|
6783
6831
|
copyLayout,
|
|
6784
6832
|
copyStyle,
|
|
6833
|
+
filmSummaryOf,
|
|
6785
6834
|
isRejected,
|
|
6786
6835
|
isStageClip,
|
|
6787
6836
|
layoutOf,
|
|
@@ -7382,7 +7431,10 @@ async function planTake(dir, opts = {}) {
|
|
|
7382
7431
|
withPageSound(doc, meta.media);
|
|
7383
7432
|
let motion;
|
|
7384
7433
|
if (opts.motion && (fresh || opts.motion.again)) {
|
|
7385
|
-
const proposed = proposeMotion(doc,
|
|
7434
|
+
const proposed = proposeMotion(doc, {
|
|
7435
|
+
...opts.motion,
|
|
7436
|
+
film: filmSummaryOf(doc, { seed: basename(join11(dir)) })
|
|
7437
|
+
});
|
|
7386
7438
|
doc = proposed.doc;
|
|
7387
7439
|
motion = {
|
|
7388
7440
|
notes: proposed.notes,
|
|
@@ -7415,14 +7467,14 @@ import { createHash } from "crypto";
|
|
|
7415
7467
|
import { existsSync as existsSync13, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
7416
7468
|
import { readFile as readFile11 } from "fs/promises";
|
|
7417
7469
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
7418
|
-
import { basename as
|
|
7470
|
+
import { basename as basename3, join as join14 } from "path";
|
|
7419
7471
|
import { lowerToComposition as lowerToComposition3, migrateHostedDoc as migrateHostedDoc2 } from "@vosjs/studio-core";
|
|
7420
7472
|
|
|
7421
7473
|
// src/plugin/takeScript.ts
|
|
7422
7474
|
import { existsSync as existsSync12 } from "fs";
|
|
7423
7475
|
import { readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
|
|
7424
7476
|
import { readFileSync as readFileSync2 } from "fs";
|
|
7425
|
-
import { basename, join as join12 } from "path";
|
|
7477
|
+
import { basename as basename2, join as join12 } from "path";
|
|
7426
7478
|
function scriptFromText(text) {
|
|
7427
7479
|
try {
|
|
7428
7480
|
const v = JSON.parse(text);
|
|
@@ -7468,7 +7520,7 @@ function publicPeers(peers) {
|
|
|
7468
7520
|
if (!p || typeof p !== "object") return p;
|
|
7469
7521
|
const peer = p;
|
|
7470
7522
|
if (typeof peer.storageState !== "string") return peer;
|
|
7471
|
-
return { ...peer, storageState:
|
|
7523
|
+
return { ...peer, storageState: basename2(peer.storageState) };
|
|
7472
7524
|
});
|
|
7473
7525
|
}
|
|
7474
7526
|
function embedScript(doc, dir) {
|
|
@@ -7572,7 +7624,7 @@ async function cmdList(argv) {
|
|
|
7572
7624
|
origin: strFlag(flags, "origin"),
|
|
7573
7625
|
api: strFlag(flags, "api")
|
|
7574
7626
|
});
|
|
7575
|
-
const key = requireCredential(
|
|
7627
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7576
7628
|
const rows = await listFolders(origin, key);
|
|
7577
7629
|
if (r.json) {
|
|
7578
7630
|
r.done({ folders: rows }, "");
|
|
@@ -7597,7 +7649,7 @@ async function cmdCreate(argv) {
|
|
|
7597
7649
|
origin: strFlag(flags, "origin"),
|
|
7598
7650
|
api: strFlag(flags, "api")
|
|
7599
7651
|
});
|
|
7600
|
-
const key = requireCredential(
|
|
7652
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7601
7653
|
const parentRef = strFlag(flags, "parent");
|
|
7602
7654
|
let parentId;
|
|
7603
7655
|
if (parentRef) {
|
|
@@ -7632,7 +7684,7 @@ async function cmdMove(argv) {
|
|
|
7632
7684
|
origin: strFlag(flags, "origin"),
|
|
7633
7685
|
api: strFlag(flags, "api")
|
|
7634
7686
|
});
|
|
7635
|
-
const key = requireCredential(
|
|
7687
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7636
7688
|
const folderId = toRef === "none" ? null : resolveFolder(await listFolders(origin, key), toRef).id;
|
|
7637
7689
|
let failed = 0;
|
|
7638
7690
|
const moved = [];
|
|
@@ -7692,7 +7744,7 @@ async function cmdPull(argv) {
|
|
|
7692
7744
|
origin: strFlag(flags, "origin"),
|
|
7693
7745
|
api: strFlag(flags, "api")
|
|
7694
7746
|
});
|
|
7695
|
-
const key = requireCredential(
|
|
7747
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7696
7748
|
const folder = resolveFolder(await listFolders(origin, key), ref);
|
|
7697
7749
|
const res = await apiJson(origin, `/api/folders/${folder.id}`, { key });
|
|
7698
7750
|
if (res.status !== 200)
|
|
@@ -7901,9 +7953,10 @@ function hostOf(origin) {
|
|
|
7901
7953
|
|
|
7902
7954
|
// src/plugin/sync.ts
|
|
7903
7955
|
function apiContext(flags) {
|
|
7956
|
+
const origin = platformOrigin(flags);
|
|
7904
7957
|
return {
|
|
7905
|
-
origin
|
|
7906
|
-
key: requireCredential(flags.key,
|
|
7958
|
+
origin,
|
|
7959
|
+
key: requireCredential({ key: flags.key, account: flags.account, origin })
|
|
7907
7960
|
};
|
|
7908
7961
|
}
|
|
7909
7962
|
async function api(ctx, path, init) {
|
|
@@ -8098,7 +8151,7 @@ async function pushTake(dir, flags, r) {
|
|
|
8098
8151
|
const lowered = lowerToComposition3(docForPush);
|
|
8099
8152
|
const config = { ...lowered.config, data: lowered.data };
|
|
8100
8153
|
if (!state) {
|
|
8101
|
-
const title = flags.title ?? `Take ${
|
|
8154
|
+
const title = flags.title ?? `Take ${basename3(dir)} ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
8102
8155
|
const slug = `${title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "take"}-${Date.now().toString(36)}`;
|
|
8103
8156
|
const created = await api(ctx, "/vos", {
|
|
8104
8157
|
method: "POST",
|
|
@@ -8290,7 +8343,7 @@ async function pullTake(dir, flags, r) {
|
|
|
8290
8343
|
const doc = hostedDoc;
|
|
8291
8344
|
const localRecording = takeMediaFile(dir, "recording", RECORDING_NAME);
|
|
8292
8345
|
if (existsSync13(localRecording)) {
|
|
8293
|
-
doc.source.videoKey =
|
|
8346
|
+
doc.source.videoKey = basename3(localRecording);
|
|
8294
8347
|
}
|
|
8295
8348
|
await writeJson(join14(dir, "doc.json"), doc, true);
|
|
8296
8349
|
const media = flags.media ? await pullMedia(ctx, dir, doc, r.log) : void 0;
|
|
@@ -8390,7 +8443,7 @@ async function pushTakeClaimable(dir, flags, r) {
|
|
|
8390
8443
|
}
|
|
8391
8444
|
const lowered = lowerToComposition3(docForPush);
|
|
8392
8445
|
const config = { ...lowered.config, data: lowered.data };
|
|
8393
|
-
const title = (flags.title ?? (state?.title ? `${state.title} remix` :
|
|
8446
|
+
const title = (flags.title ?? (state?.title ? `${state.title} remix` : basename3(dir))).slice(0, 200);
|
|
8394
8447
|
const body = { title, config, doc: docForPush };
|
|
8395
8448
|
if (state?.vosId) body.remixOfId = state.vosId;
|
|
8396
8449
|
if (flags.prompt) body.prompt = flags.prompt;
|
|
@@ -8418,7 +8471,7 @@ async function pushTakeClaimable(dir, flags, r) {
|
|
|
8418
8471
|
import { existsSync as existsSync15 } from "fs";
|
|
8419
8472
|
import { mkdir as mkdir7, readFile as readFile12 } from "fs/promises";
|
|
8420
8473
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
8421
|
-
import { basename as
|
|
8474
|
+
import { basename as basename5, dirname as dirname2, join as join15 } from "path";
|
|
8422
8475
|
import {
|
|
8423
8476
|
CURRENT_CONFIG_VERSION,
|
|
8424
8477
|
migrateConfig,
|
|
@@ -8427,7 +8480,7 @@ import {
|
|
|
8427
8480
|
import { lowerProgramDoc, migrateHostedDoc as migrateHostedDoc3 } from "@vosjs/studio-core";
|
|
8428
8481
|
|
|
8429
8482
|
// src/plugin/programFiles.ts
|
|
8430
|
-
import { basename as
|
|
8483
|
+
import { basename as basename4, extname as extname2, relative as relative2 } from "path";
|
|
8431
8484
|
import { existsSync as existsSync14, realpathSync as realpathSync2 } from "fs";
|
|
8432
8485
|
function isLocalName(value) {
|
|
8433
8486
|
if (/^(https?:|data:|blob:|asset:|media:)/.test(value)) return false;
|
|
@@ -8438,7 +8491,7 @@ function isLocalName(value) {
|
|
|
8438
8491
|
}
|
|
8439
8492
|
var FILE_EXT = /\.(png|jpe?g|webp|gif|avif|svg|mp4|webm|mov|mp3|m4a|ogg|wav|flac|aac|glb|gltf|woff2?|ttf|otf|hdr|exr)$/i;
|
|
8440
8493
|
function manifestName(file, taken) {
|
|
8441
|
-
const stem =
|
|
8494
|
+
const stem = basename4(file, extname2(file)).replace(/[^A-Za-z0-9_]/g, "_").replace(/^(?=[0-9])/, "_") || "file";
|
|
8442
8495
|
let name = stem;
|
|
8443
8496
|
for (let n = 2; taken.has(name); n++) name = `${stem}_${n}`;
|
|
8444
8497
|
taken.add(name);
|
|
@@ -8857,7 +8910,7 @@ async function cmdPushProgram(argv) {
|
|
|
8857
8910
|
"--claimable creates a NEW claimable vos and cannot iterate (--vos). After the human claims it, iterate with their key: vos push --vos <id>"
|
|
8858
8911
|
);
|
|
8859
8912
|
}
|
|
8860
|
-
const fallback = state?.title ? `${state.title} remix` :
|
|
8913
|
+
const fallback = state?.title ? `${state.title} remix` : basename5(source).replace(/\.json$/i, "") || "vos program";
|
|
8861
8914
|
const title2 = (strFlag(flags, "title") ?? fallback).slice(0, 100);
|
|
8862
8915
|
const files2 = await collectFiles(config, programDoc, dir, r);
|
|
8863
8916
|
let uploadToken;
|
|
@@ -8913,7 +8966,7 @@ with their key: vos push ${source} --vos ${String(created2.id ?? "<id>")}`
|
|
|
8913
8966
|
);
|
|
8914
8967
|
return EXIT_OK;
|
|
8915
8968
|
}
|
|
8916
|
-
const key = requireCredential(
|
|
8969
|
+
const key = requireCredential(credentialFlags(flags));
|
|
8917
8970
|
void flags.yes;
|
|
8918
8971
|
const files = await collectFiles(config, programDoc, dir, r);
|
|
8919
8972
|
await files.upload({ origin, key });
|
|
@@ -9031,7 +9084,7 @@ ${landedLines(landed2)}` : "")
|
|
|
9031
9084
|
return EXIT_OK;
|
|
9032
9085
|
}
|
|
9033
9086
|
const remixOfId = pushTarget.kind === "create" ? pushTarget.remixOfId : void 0;
|
|
9034
|
-
const fallbackTitle = state?.title ? `${state.title} remix` :
|
|
9087
|
+
const fallbackTitle = state?.title ? `${state.title} remix` : basename5(source).replace(/\.json$/i, "") || "vos remix";
|
|
9035
9088
|
const title = (strFlag(flags, "title") ?? fallbackTitle).slice(0, 100);
|
|
9036
9089
|
const pushFolder = folderRef ? await resolvePushFolder(origin, key, folderRef) : void 0;
|
|
9037
9090
|
const folderId = pushFolder?.id;
|
|
@@ -9128,7 +9181,7 @@ async function cmdPullProgram(argv) {
|
|
|
9128
9181
|
`no base version in ${dir}/vos.json \u2014 pass --since <versionId>`
|
|
9129
9182
|
);
|
|
9130
9183
|
}
|
|
9131
|
-
const key = requireCredential(
|
|
9184
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9132
9185
|
const res = await apiJson(
|
|
9133
9186
|
origin,
|
|
9134
9187
|
`/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`,
|
|
@@ -9227,16 +9280,21 @@ async function cmdLogin(argv) {
|
|
|
9227
9280
|
});
|
|
9228
9281
|
const handoffUrl = strFlag(flags, "handoff");
|
|
9229
9282
|
if (handoffUrl) {
|
|
9283
|
+
const before = await nameActiveCredential(
|
|
9284
|
+
parseHandoffUrl(handoffUrl)?.origin ?? origin
|
|
9285
|
+
);
|
|
9230
9286
|
const done = await handoffLogin(handoffUrl, r);
|
|
9231
9287
|
r.done(
|
|
9232
9288
|
{
|
|
9233
9289
|
path: done.path,
|
|
9234
9290
|
origin: done.origin,
|
|
9235
9291
|
user: done.user,
|
|
9292
|
+
account: done.account,
|
|
9236
9293
|
keyName: done.keyName,
|
|
9294
|
+
...setAsideFacts(before, done.account),
|
|
9237
9295
|
next_step: "the link is spent; vos push when you want the work hosted"
|
|
9238
9296
|
},
|
|
9239
|
-
`Signed in${done.user
|
|
9297
|
+
`Signed in${signedAs(done.user, done.account)} \u2014 key "${done.keyName}" stored at ${done.path} (used by every vos platform verb). The link is spent.${setAsideLine(before, done.account)}`
|
|
9240
9298
|
);
|
|
9241
9299
|
return EXIT_OK;
|
|
9242
9300
|
}
|
|
@@ -9244,13 +9302,14 @@ async function cmdLogin(argv) {
|
|
|
9244
9302
|
if (explicit) return storeKey(explicit, origin, r);
|
|
9245
9303
|
try {
|
|
9246
9304
|
const openBrowser = process.stdout.isTTY === true && !process.env.SSH_CONNECTION && !process.env.SSH_TTY && flags.json !== true && flags["no-browser"] !== true;
|
|
9247
|
-
const
|
|
9305
|
+
const before = await nameActiveCredential(origin);
|
|
9306
|
+
const { path, user, account } = await browserLogin(origin, r, {
|
|
9248
9307
|
label: strFlag(flags, "label"),
|
|
9249
9308
|
openBrowser
|
|
9250
9309
|
});
|
|
9251
9310
|
r.done(
|
|
9252
|
-
{ path, origin, user },
|
|
9253
|
-
`Signed in${user
|
|
9311
|
+
{ path, origin, user, account, ...setAsideFacts(before, account) },
|
|
9312
|
+
`Signed in${signedAs(user, account)} \u2014 key stored at ${path} (used by every vos platform verb).${setAsideLine(before, account)}`
|
|
9254
9313
|
);
|
|
9255
9314
|
return EXIT_OK;
|
|
9256
9315
|
} catch (e) {
|
|
@@ -9268,17 +9327,57 @@ async function cmdLogin(argv) {
|
|
|
9268
9327
|
return storeKey(key, origin, r);
|
|
9269
9328
|
}
|
|
9270
9329
|
async function storeKey(key, origin, r) {
|
|
9271
|
-
const
|
|
9272
|
-
if (
|
|
9273
|
-
throw new Error(apiError("validate key",
|
|
9330
|
+
const who = await apiJson(origin, "/api/user/whoami", { key });
|
|
9331
|
+
if (who.status === 401 || who.status === 403) {
|
|
9332
|
+
throw new Error(apiError("validate key", who));
|
|
9333
|
+
}
|
|
9334
|
+
let account = null;
|
|
9335
|
+
if (who.status === 200) account = accountFrom(who.body.user);
|
|
9336
|
+
else {
|
|
9337
|
+
const probe3 = await apiJson(origin, "/api/folders", { key });
|
|
9338
|
+
if (probe3.status === 401 || probe3.status === 403) {
|
|
9339
|
+
throw new Error(apiError("validate key", probe3));
|
|
9340
|
+
}
|
|
9274
9341
|
}
|
|
9275
|
-
const
|
|
9342
|
+
const before = await nameActiveCredential(origin);
|
|
9343
|
+
const path = writeCredential(key, origin, void 0, account);
|
|
9276
9344
|
r.done(
|
|
9277
|
-
{ path, origin },
|
|
9278
|
-
`Signed in \u2014 key stored at ${path} (used by every vos platform verb)`
|
|
9345
|
+
{ path, origin, account, ...setAsideFacts(before, account) },
|
|
9346
|
+
`Signed in${signedAs("", account)} \u2014 key stored at ${path} (used by every vos platform verb).${setAsideLine(before, account)}`
|
|
9279
9347
|
);
|
|
9280
9348
|
return EXIT_OK;
|
|
9281
9349
|
}
|
|
9350
|
+
function signedAs(user, account) {
|
|
9351
|
+
if (account) return ` as ${accountLabel(account)}`;
|
|
9352
|
+
return user ? ` as ${user}` : "";
|
|
9353
|
+
}
|
|
9354
|
+
async function nameActiveCredential(origin) {
|
|
9355
|
+
const active = readActive(DEFAULT_STORE);
|
|
9356
|
+
if (!active || active.origin !== originOf(origin)) return active;
|
|
9357
|
+
if (active.account) return active;
|
|
9358
|
+
try {
|
|
9359
|
+
const who = await apiJson(origin, "/api/user/whoami", { key: active.key });
|
|
9360
|
+
const account = who.status === 200 ? accountFrom(who.body.user) : null;
|
|
9361
|
+
if (!account) return active;
|
|
9362
|
+
const named = { ...active, account };
|
|
9363
|
+
activate(DEFAULT_STORE, named);
|
|
9364
|
+
return named;
|
|
9365
|
+
} catch {
|
|
9366
|
+
return active;
|
|
9367
|
+
}
|
|
9368
|
+
}
|
|
9369
|
+
function setAsideFacts(before, account) {
|
|
9370
|
+
if (!before || account && before.account?.id === account.id) return {};
|
|
9371
|
+
return before.account ? { setAside: before.account } : { replaced: true };
|
|
9372
|
+
}
|
|
9373
|
+
function setAsideLine(before, account) {
|
|
9374
|
+
const facts = setAsideFacts(before, account);
|
|
9375
|
+
if (facts.setAside)
|
|
9376
|
+
return ` ${accountLabel(facts.setAside)} stays stored; vos switch ${facts.setAside.handle ?? facts.setAside.id} when you need it.`;
|
|
9377
|
+
if (facts.replaced)
|
|
9378
|
+
return " The credential stored before had no name on file and was replaced.";
|
|
9379
|
+
return "";
|
|
9380
|
+
}
|
|
9282
9381
|
function isTakeDir(target) {
|
|
9283
9382
|
return directoryKind(target) === "take";
|
|
9284
9383
|
}
|
|
@@ -9357,7 +9456,7 @@ async function writeProgramDoc(dir, hosted) {
|
|
|
9357
9456
|
// src/plugin/asset.ts
|
|
9358
9457
|
import { createHash as createHash2 } from "crypto";
|
|
9359
9458
|
import { readFileSync as readFileSync4 } from "fs";
|
|
9360
|
-
import { basename as
|
|
9459
|
+
import { basename as basename6 } from "path";
|
|
9361
9460
|
|
|
9362
9461
|
// src/plugin/assetWords.ts
|
|
9363
9462
|
function hostedFile(raw) {
|
|
@@ -9594,7 +9693,7 @@ async function cmdRename(argv) {
|
|
|
9594
9693
|
origin: strFlag(flags, "origin"),
|
|
9595
9694
|
api: strFlag(flags, "api")
|
|
9596
9695
|
});
|
|
9597
|
-
const key = requireCredential(
|
|
9696
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9598
9697
|
const res = await apiJson(origin, `/api/assets/${assetId}`, {
|
|
9599
9698
|
method: "PATCH",
|
|
9600
9699
|
key,
|
|
@@ -9617,12 +9716,12 @@ async function cmdPush(argv) {
|
|
|
9617
9716
|
origin: strFlag(flags, "origin"),
|
|
9618
9717
|
api: strFlag(flags, "api")
|
|
9619
9718
|
});
|
|
9620
|
-
const key = requireCredential(
|
|
9719
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9621
9720
|
const folderRef = strFlag(flags, "folder");
|
|
9622
9721
|
const folder = folderRef ? resolveFolder(await listFolders(origin, key), folderRef) : null;
|
|
9623
9722
|
const uploaded = [];
|
|
9624
9723
|
for (const file of positionals) {
|
|
9625
|
-
const name =
|
|
9724
|
+
const name = basename6(file);
|
|
9626
9725
|
const body = readFileSync4(file);
|
|
9627
9726
|
const media = resolveMediaType({
|
|
9628
9727
|
head: body.subarray(0, MEDIA_HEAD_BYTES),
|
|
@@ -9698,7 +9797,7 @@ async function cmdImport(argv) {
|
|
|
9698
9797
|
origin: strFlag(flags, "origin"),
|
|
9699
9798
|
api: strFlag(flags, "api")
|
|
9700
9799
|
});
|
|
9701
|
-
const key = requireCredential(
|
|
9800
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9702
9801
|
const folderRef = strFlag(flags, "folder");
|
|
9703
9802
|
const folder = folderRef ? resolveFolder(await listFolders(origin, key), folderRef) : null;
|
|
9704
9803
|
const refused = fetchRefusal(url);
|
|
@@ -9782,7 +9881,7 @@ async function cmdList2(argv) {
|
|
|
9782
9881
|
origin: strFlag(flags, "origin"),
|
|
9783
9882
|
api: strFlag(flags, "api")
|
|
9784
9883
|
});
|
|
9785
|
-
const key = requireCredential(
|
|
9884
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9786
9885
|
const params = new URLSearchParams({
|
|
9787
9886
|
limit: String(Math.min(200, Math.max(1, numFlag(flags, "limit", 50))))
|
|
9788
9887
|
});
|
|
@@ -9815,7 +9914,7 @@ async function cmdUsage(argv) {
|
|
|
9815
9914
|
origin: strFlag(flags, "origin"),
|
|
9816
9915
|
api: strFlag(flags, "api")
|
|
9817
9916
|
});
|
|
9818
|
-
const key = requireCredential(
|
|
9917
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9819
9918
|
const res = await apiJson(origin, "/api/user/usage", { key });
|
|
9820
9919
|
if (res.status !== 200) throw new Error(apiError("read usage", res));
|
|
9821
9920
|
const usage = res.body.usage ?? {};
|
|
@@ -9842,7 +9941,7 @@ async function cmdWhy(argv) {
|
|
|
9842
9941
|
origin: strFlag(flags, "origin"),
|
|
9843
9942
|
api: strFlag(flags, "api")
|
|
9844
9943
|
});
|
|
9845
|
-
const key = requireCredential(
|
|
9944
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9846
9945
|
const res = await apiJson(origin, `/api/assets/${assetId}`, { key });
|
|
9847
9946
|
if (res.status !== 200) throw new Error(apiError(`read ${assetId}`, res));
|
|
9848
9947
|
const asset = hostedFile(res.body.asset);
|
|
@@ -9937,7 +10036,7 @@ function context(flags) {
|
|
|
9937
10036
|
origin: strFlag(flags, "origin"),
|
|
9938
10037
|
api: strFlag(flags, "api")
|
|
9939
10038
|
}).replace(/\/+$/, "");
|
|
9940
|
-
return { origin, key: requireCredential(
|
|
10039
|
+
return { origin, key: requireCredential(credentialFlags(flags)) };
|
|
9941
10040
|
}
|
|
9942
10041
|
async function readTrash(ctx) {
|
|
9943
10042
|
const res = await apiJson(ctx.origin, "/api/trash", { key: ctx.key });
|
|
@@ -10065,7 +10164,7 @@ async function cmdDelete(argv) {
|
|
|
10065
10164
|
origin: strFlag(flags, "origin"),
|
|
10066
10165
|
api: strFlag(flags, "api")
|
|
10067
10166
|
}).replace(/\/+$/, "");
|
|
10068
|
-
const key = requireCredential(
|
|
10167
|
+
const key = requireCredential(credentialFlags(flags));
|
|
10069
10168
|
const dir = existsSync16(target) && statSync3(target).isDirectory() ? target : null;
|
|
10070
10169
|
const vosId = dir ? readSyncState(dir)?.vosId : parseVosId(target);
|
|
10071
10170
|
if (!vosId)
|
|
@@ -10140,7 +10239,7 @@ function trackingCwd(vosId) {
|
|
|
10140
10239
|
|
|
10141
10240
|
// src/plugin/buildProgram.ts
|
|
10142
10241
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
10143
|
-
import { basename as
|
|
10242
|
+
import { basename as basename7, dirname as dirname3, join as join17, resolve as resolve8 } from "path";
|
|
10144
10243
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
10145
10244
|
import { parse } from "acorn";
|
|
10146
10245
|
import { fullAncestor } from "acorn-walk";
|
|
@@ -10348,7 +10447,7 @@ async function cmdBuild(argv) {
|
|
|
10348
10447
|
throw new UsageError(
|
|
10349
10448
|
`${source} exports no program: \`export default { version: 2, duration, camera, createContent, createTimeline, \u2026 }\``
|
|
10350
10449
|
);
|
|
10351
|
-
const built = buildProgram(program,
|
|
10450
|
+
const built = buildProgram(program, basename7(file), text);
|
|
10352
10451
|
for (const p of built.problems) r.log(`error ${p.fn}: ${p.message}`);
|
|
10353
10452
|
if (built.problems.length) {
|
|
10354
10453
|
r.done(
|
|
@@ -10583,7 +10682,7 @@ import { findFontFamily as findFontFamily3 } from "@vosjs/shared";
|
|
|
10583
10682
|
import { existsSync as existsSync18, readFileSync as readFileSync6, readdirSync as readdirSync3, statSync as statSync5 } from "fs";
|
|
10584
10683
|
import { createServer as createServer2 } from "http";
|
|
10585
10684
|
import { createRequire } from "module";
|
|
10586
|
-
import { basename as
|
|
10685
|
+
import { basename as basename8, extname as extname3, join as join19 } from "path";
|
|
10587
10686
|
function themeColors(sources) {
|
|
10588
10687
|
const out = {};
|
|
10589
10688
|
const re = /\bconst\s+([A-Za-z_$][\w$]*)\s*(?::\s*string\s*)?=\s*['"](#[0-9a-fA-F]{3,8})['"]/g;
|
|
@@ -10863,7 +10962,7 @@ async function readRemotion(dir, log) {
|
|
|
10863
10962
|
const sources = sourceTexts(dir);
|
|
10864
10963
|
const publicDir = join19(dir, "public");
|
|
10865
10964
|
const media = tree.audio.map((a) => {
|
|
10866
|
-
const name =
|
|
10965
|
+
const name = basename8(a.src.split("?")[0]);
|
|
10867
10966
|
const local = existsSync18(join19(publicDir, name)) ? `public/${name}` : a.src;
|
|
10868
10967
|
return {
|
|
10869
10968
|
kind: "audio",
|
|
@@ -11366,7 +11465,7 @@ async function readInventory(source, opts) {
|
|
|
11366
11465
|
// src/plugin/portScaffold.ts
|
|
11367
11466
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
11368
11467
|
import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
11369
|
-
import { basename as
|
|
11468
|
+
import { basename as basename9, dirname as dirname6, join as join21, resolve as resolve11 } from "path";
|
|
11370
11469
|
import { findFontFamily as findFontFamily4, fontFaceUrl, nearestFontWeight } from "@vosjs/shared";
|
|
11371
11470
|
|
|
11372
11471
|
// src/plugin/painterLib.ts
|
|
@@ -11776,7 +11875,7 @@ function planScaffold(inv, opts) {
|
|
|
11776
11875
|
const copies = [];
|
|
11777
11876
|
inv.media.filter((m) => m.kind === "audio" && m.src).forEach((m, i) => {
|
|
11778
11877
|
const from = resolve11(opts.sourceDir, m.src);
|
|
11779
|
-
const name =
|
|
11878
|
+
const name = basename9(from);
|
|
11780
11879
|
if (!existsSync20(from)) {
|
|
11781
11880
|
report.push(
|
|
11782
11881
|
`- the audio ${m.src} is not in the source folder; add it to doc.json by hand`
|
|
@@ -11929,7 +12028,7 @@ ${sceneTodos}${springHint}
|
|
|
11929
12028
|
}
|
|
11930
12029
|
function reportText(inv, r) {
|
|
11931
12030
|
const lines = [
|
|
11932
|
-
`# Port report: ${inv.source === "." && inv.root ?
|
|
12031
|
+
`# Port report: ${inv.source === "." && inv.root ? basename9(inv.root) : inv.source}`,
|
|
11933
12032
|
"",
|
|
11934
12033
|
`${inv.engine} piece, ${inv.width}\xD7${inv.height}${inv.fps ? ` at ${inv.fps} fps` : ""}, ${inv.duration ?? "?"} s. A program has no size of its own: render it with \`--width ${inv.width} --height ${inv.height}\`.`,
|
|
11935
12034
|
"",
|
|
@@ -12093,11 +12192,11 @@ function scaffoldSourceDir(inv) {
|
|
|
12093
12192
|
// src/plugin/recipe.ts
|
|
12094
12193
|
import { createHash as createHash3 } from "crypto";
|
|
12095
12194
|
import { readFileSync as readFileSync9 } from "fs";
|
|
12096
|
-
import { basename as
|
|
12195
|
+
import { basename as basename10 } from "path";
|
|
12097
12196
|
var BOOLEAN_FLAGS9 = /* @__PURE__ */ new Set(["json", "help"]);
|
|
12098
12197
|
var USAGE = "vos recipe push <file.md> (--folder <folderId|slug> | --asset <assetId>)";
|
|
12099
12198
|
function recipeFilename(file) {
|
|
12100
|
-
const name =
|
|
12199
|
+
const name = basename10(file);
|
|
12101
12200
|
if (!/\.md$/i.test(name)) {
|
|
12102
12201
|
throw new UsageError(`a recipe is a markdown file \u2014 ${name} is not .md`);
|
|
12103
12202
|
}
|
|
@@ -12118,7 +12217,7 @@ async function cmdPush2(argv) {
|
|
|
12118
12217
|
origin: strFlag(flags, "origin"),
|
|
12119
12218
|
api: strFlag(flags, "api")
|
|
12120
12219
|
});
|
|
12121
|
-
const key = requireCredential(
|
|
12220
|
+
const key = requireCredential(credentialFlags(flags));
|
|
12122
12221
|
if (assetId) {
|
|
12123
12222
|
const res = await apiJson(origin, `/api/assets/${assetId}/file`, {
|
|
12124
12223
|
method: "PUT",
|
|
@@ -13203,7 +13302,7 @@ async function cmdActionsScript(input, flags) {
|
|
|
13203
13302
|
// src/plugin/ingest.ts
|
|
13204
13303
|
import { existsSync as existsSync22 } from "fs";
|
|
13205
13304
|
import { copyFile, mkdir as mkdir8, readFile as readFile13, stat as stat2 } from "fs/promises";
|
|
13206
|
-
import { basename as
|
|
13305
|
+
import { basename as basename11, join as join23, resolve as resolve15 } from "path";
|
|
13207
13306
|
|
|
13208
13307
|
// src/plugin/traceInflate.ts
|
|
13209
13308
|
import { inflateRawSync } from "zlib";
|
|
@@ -13330,7 +13429,7 @@ async function copyRecording(src, dest, ext2) {
|
|
|
13330
13429
|
}
|
|
13331
13430
|
}
|
|
13332
13431
|
async function readTraceFile(path, offsetMs) {
|
|
13333
|
-
const kind = traceKindOf(
|
|
13432
|
+
const kind = traceKindOf(basename11(path));
|
|
13334
13433
|
if (!kind) {
|
|
13335
13434
|
throw new UsageError(
|
|
13336
13435
|
`${path}: not a trace the recorder reads (trace.zip, .trace, .jsonl, .json or .csv)`
|
|
@@ -13351,7 +13450,7 @@ async function readTraceFile(path, offsetMs) {
|
|
|
13351
13450
|
return cursorFromPlaywrightTrace(text2, { offsetMs });
|
|
13352
13451
|
}
|
|
13353
13452
|
const text = await readFile13(path, "utf8");
|
|
13354
|
-
return cursorFromTrace(
|
|
13453
|
+
return cursorFromTrace(basename11(path), text, { offsetMs });
|
|
13355
13454
|
}
|
|
13356
13455
|
function parseViewport(v) {
|
|
13357
13456
|
if (!v) return null;
|
|
@@ -13382,7 +13481,7 @@ async function cmdIngest(argv) {
|
|
|
13382
13481
|
"note: finished footage opens bare, so --background is not used (pass --as take for the screen-recording card and its ground)"
|
|
13383
13482
|
);
|
|
13384
13483
|
const backdrop = footage ? null : await takeBackdrop(flags, r);
|
|
13385
|
-
r.log(`probing ${
|
|
13484
|
+
r.log(`probing ${basename11(videoPath)}\u2026`);
|
|
13386
13485
|
const probed = await probeVideoFile(videoPath);
|
|
13387
13486
|
if (!(probed.durationMs > 0)) {
|
|
13388
13487
|
throw new UsageError(
|
|
@@ -13431,13 +13530,13 @@ async function cmdIngest(argv) {
|
|
|
13431
13530
|
const clicks = events.filter((e) => e.type === "down").length;
|
|
13432
13531
|
const seconds = (probed.durationMs / 1e3).toFixed(1);
|
|
13433
13532
|
const facts = `${seconds}s, ${probed.width}\xD7${probed.height} @ ${meta.fps} fps${probed.hasAudio ? ", audio" : ", no audio"}${remuxed ? "" : ", copied as is"}`;
|
|
13434
|
-
const cursorLine = trace ? `${events.length} cursor events (${clicks} clicks) from ${
|
|
13533
|
+
const cursorLine = trace ? `${events.length} cursor events (${clicks} clicks) from ${basename11(cursorPath)}${trace.dropped ? `, ${trace.dropped} not placed` : ""}; ${plan.zoomAuto} zoom${plan.zoomAuto === 1 ? "" : "s"} planned` : "no cursor track, so nothing was planned";
|
|
13435
13534
|
const opened = footage ? `opened as finished footage: no card, no browser bar, no drawn cursor, ${meta.fps > 30 ? 60 : 30} fps export (--as take for a screen recording's card)` : `opened as a screen recording: the card, its ground and the drawn cursor (--as footage to open it bare)`;
|
|
13436
13535
|
const next = footage && !trace ? `Next: vos push ${outDir} --wait \u2014 it lands as it is; trim or add to it in the studio` : 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`;
|
|
13437
13536
|
r.done(
|
|
13438
13537
|
{
|
|
13439
13538
|
out: outDir,
|
|
13440
|
-
recording:
|
|
13539
|
+
recording: basename11(recording),
|
|
13441
13540
|
durationMs: probed.durationMs,
|
|
13442
13541
|
width: probed.width,
|
|
13443
13542
|
height: probed.height,
|
|
@@ -13446,7 +13545,7 @@ async function cmdIngest(argv) {
|
|
|
13446
13545
|
hasAudio: probed.hasAudio,
|
|
13447
13546
|
remuxed,
|
|
13448
13547
|
cursor: trace ? {
|
|
13449
|
-
file:
|
|
13548
|
+
file: basename11(cursorPath),
|
|
13450
13549
|
kind: trace.kind,
|
|
13451
13550
|
events: events.length,
|
|
13452
13551
|
clicks,
|
|
@@ -13458,7 +13557,7 @@ async function cmdIngest(argv) {
|
|
|
13458
13557
|
backdrop: plan.backdrop ?? null,
|
|
13459
13558
|
as: footage ? "footage" : "take"
|
|
13460
13559
|
},
|
|
13461
|
-
`Ingested ${
|
|
13560
|
+
`Ingested ${basename11(videoPath)} \u2192 ${outDir}/${basename11(recording)} (${facts})
|
|
13462
13561
|
${opened}
|
|
13463
13562
|
${cursorLine}
|
|
13464
13563
|
${next}`
|
|
@@ -13470,7 +13569,7 @@ async function cmdIngest(argv) {
|
|
|
13470
13569
|
import { createRequire as createRequire2 } from "module";
|
|
13471
13570
|
import { existsSync as existsSync23 } from "fs";
|
|
13472
13571
|
import { mkdir as mkdir9, readFile as readFile14, stat as stat3, writeFile as writeFile7 } from "fs/promises";
|
|
13473
|
-
import { basename as
|
|
13572
|
+
import { basename as basename12, dirname as dirname8, extname as extname4, join as join24, resolve as resolve16 } from "path";
|
|
13474
13573
|
import { ALL_FORMATS as ALL_FORMATS2, FilePathSource as FilePathSource2, Input as Input2 } from "mediabunny";
|
|
13475
13574
|
|
|
13476
13575
|
// src/plugin/videoChecks.ts
|
|
@@ -13992,7 +14091,7 @@ async function checkVideo(browser, file, outDir) {
|
|
|
13992
14091
|
void page.evaluate(decodeInPage, {
|
|
13993
14092
|
mbCode: await mediabunnyBundle(),
|
|
13994
14093
|
meterSrc: String(createLoudnessMeter),
|
|
13995
|
-
videoUrl: `/${encodeURIComponent(
|
|
14094
|
+
videoUrl: `/${encodeURIComponent(basename12(file))}`,
|
|
13996
14095
|
sampleFps,
|
|
13997
14096
|
thumbW: side(facts.width),
|
|
13998
14097
|
thumbH: side(facts.height),
|
|
@@ -14100,7 +14199,7 @@ async function cmdCheckVideo(argv) {
|
|
|
14100
14199
|
const r = createReporter(flags.json === true);
|
|
14101
14200
|
const strict = flags.strict === true;
|
|
14102
14201
|
const outDir = resolve16(
|
|
14103
|
-
strFlag(flags, "out") ?? join24(dirname8(file), `${
|
|
14202
|
+
strFlag(flags, "out") ?? join24(dirname8(file), `${basename12(file, extname4(file))}-check`)
|
|
14104
14203
|
);
|
|
14105
14204
|
const browser = await launchBrowser();
|
|
14106
14205
|
try {
|
|
@@ -14118,7 +14217,7 @@ async function cmdCheckVideo(argv) {
|
|
|
14118
14217
|
import { existsSync as existsSync26, readdirSync as readdirSync5, statSync as statSync7 } from "fs";
|
|
14119
14218
|
import { copyFile as copyFile3, mkdir as mkdir11, readFile as readFile17, rm as rm4 } from "fs/promises";
|
|
14120
14219
|
import {
|
|
14121
|
-
basename as
|
|
14220
|
+
basename as basename14,
|
|
14122
14221
|
dirname as dirname9,
|
|
14123
14222
|
isAbsolute as isAbsolute4,
|
|
14124
14223
|
join as join27,
|
|
@@ -14149,13 +14248,15 @@ import {
|
|
|
14149
14248
|
writeFile as writeFile8
|
|
14150
14249
|
} from "fs/promises";
|
|
14151
14250
|
import { tmpdir as tmpdir2 } from "os";
|
|
14152
|
-
import { basename as
|
|
14251
|
+
import { basename as basename13, isAbsolute as isAbsolute3, join as join25, relative as relative4, resolve as resolve17, sep as sep3 } from "path";
|
|
14252
|
+
import { rankBeds as rankBeds2 } from "@vosjs/shared/music";
|
|
14153
14253
|
import {
|
|
14154
14254
|
NORMALIZE_MAX_LUFS as NORMALIZE_MAX_LUFS2,
|
|
14155
14255
|
NORMALIZE_MIN_LUFS as NORMALIZE_MIN_LUFS2,
|
|
14156
14256
|
clipGain as clipGain2,
|
|
14157
14257
|
docMediaList,
|
|
14158
14258
|
docOutputDuration as docOutputDuration3,
|
|
14259
|
+
filmSummaryOf as filmSummaryOf2,
|
|
14159
14260
|
findStep as findStep2,
|
|
14160
14261
|
ratedSegments as ratedSegments7,
|
|
14161
14262
|
resolveAnchor as resolveAnchor4
|
|
@@ -14464,7 +14565,7 @@ async function measureInBrowser(path) {
|
|
|
14464
14565
|
const bytes = await readFile15(path);
|
|
14465
14566
|
if (bytes.length > BROWSER_DECODE_MAX_BYTES)
|
|
14466
14567
|
throw new Error(
|
|
14467
|
-
`${
|
|
14568
|
+
`${basename13(path)} is ${Math.round(bytes.length / 1048576)} MB, past the ${BROWSER_DECODE_MAX_BYTES / 1048576} MB the browser decode takes whole`
|
|
14468
14569
|
);
|
|
14469
14570
|
const browser = await launchBrowser();
|
|
14470
14571
|
try {
|
|
@@ -14568,12 +14669,12 @@ async function resolveTrack(dir, ref, flags, dryRun) {
|
|
|
14568
14669
|
if (existsSync24(local)) {
|
|
14569
14670
|
const rel = relative4(resolve17(dir), local);
|
|
14570
14671
|
const inside = !!rel && !rel.startsWith(`..${sep3}`) && rel !== ".." && !isAbsolute3(rel);
|
|
14571
|
-
const key = inside ? rel.split(sep3).join("/") : `music/${
|
|
14672
|
+
const key = inside ? rel.split(sep3).join("/") : `music/${basename13(local)}`;
|
|
14572
14673
|
if (!inside && !dryRun) {
|
|
14573
14674
|
await mkdir10(join25(dir, "music"), { recursive: true });
|
|
14574
14675
|
await copyFile2(local, join25(dir, key));
|
|
14575
14676
|
}
|
|
14576
|
-
return { path: local, key, name:
|
|
14677
|
+
return { path: local, key, name: basename13(local) };
|
|
14577
14678
|
}
|
|
14578
14679
|
const origin = platformOrigin({
|
|
14579
14680
|
origin: strFlag(flags, "origin"),
|
|
@@ -14588,7 +14689,7 @@ async function resolveTrack(dir, ref, flags, dryRun) {
|
|
|
14588
14689
|
const res = await fetch(track.url);
|
|
14589
14690
|
if (!res.ok) throw new Error(`GET ${track.url} answered ${res.status}`);
|
|
14590
14691
|
const tmp = await mkdtemp(join25(tmpdir2(), "vos-score-"));
|
|
14591
|
-
const path = join25(tmp,
|
|
14692
|
+
const path = join25(tmp, basename13(new URL(track.url).pathname) || "track");
|
|
14592
14693
|
await writeFile8(path, new Uint8Array(await res.arrayBuffer()));
|
|
14593
14694
|
return {
|
|
14594
14695
|
path,
|
|
@@ -14598,7 +14699,7 @@ async function resolveTrack(dir, ref, flags, dryRun) {
|
|
|
14598
14699
|
};
|
|
14599
14700
|
}
|
|
14600
14701
|
var BOOLEAN_FLAGS12 = /* @__PURE__ */ new Set(["json", "help", "dry-run"]);
|
|
14601
|
-
var USAGE2 =
|
|
14702
|
+
var USAGE2 = 'vos score <take> --track <slug|file|best> [--at <step id|output seconds>] [--mood <slug|tag>] [--words "\u2026"] [--gain 0..1] [--normalize <lufs|off>] [--fade-in <s>] [--fade-out <s>] [--dry-run] [--json]';
|
|
14602
14703
|
async function cmdScore(argv) {
|
|
14603
14704
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS12);
|
|
14604
14705
|
const dir = positionals[0];
|
|
@@ -14625,8 +14726,39 @@ async function cmdScore(argv) {
|
|
|
14625
14726
|
throw new UsageError(`${dir} has no doc.json; run vos plan first`);
|
|
14626
14727
|
const doc = take.doc;
|
|
14627
14728
|
const atRaw = strFlag(flags, "at");
|
|
14628
|
-
|
|
14629
|
-
|
|
14729
|
+
let at2 = atRaw !== void 0 ? resolveAt(doc, atRaw) : null;
|
|
14730
|
+
let chosen = trackRef;
|
|
14731
|
+
if (trackRef === "best") {
|
|
14732
|
+
const origin = platformOrigin({
|
|
14733
|
+
origin: strFlag(flags, "origin"),
|
|
14734
|
+
api: strFlag(flags, "api")
|
|
14735
|
+
});
|
|
14736
|
+
const catalog = await fetchMusicCatalog(origin);
|
|
14737
|
+
const film2 = filmSummaryOf2(doc, {
|
|
14738
|
+
seed: readSyncState(dir)?.vosId ?? basename13(resolve17(dir)),
|
|
14739
|
+
...at2 ? { payoff: at2.at } : {},
|
|
14740
|
+
mood: strFlag(flags, "mood"),
|
|
14741
|
+
words: strFlag(flags, "words")
|
|
14742
|
+
});
|
|
14743
|
+
const ranked = rankBeds2(catalog.tracks, film2).filter(
|
|
14744
|
+
(x) => x.score !== null
|
|
14745
|
+
);
|
|
14746
|
+
const best = ranked[0];
|
|
14747
|
+
if (!best)
|
|
14748
|
+
throw new UsageError(
|
|
14749
|
+
`no bed in the library fits this ${film2.duration.toFixed(1)}s film (every track refused); compose a score instead, or name a track with --track <slug>`
|
|
14750
|
+
);
|
|
14751
|
+
chosen = best.slug;
|
|
14752
|
+
if (!at2 && film2.payoff !== void 0)
|
|
14753
|
+
at2 = {
|
|
14754
|
+
at: film2.payoff,
|
|
14755
|
+
via: `the film's payoff (${film2.payoff.toFixed(2)}s)`
|
|
14756
|
+
};
|
|
14757
|
+
r.log(
|
|
14758
|
+
`picked ${best.slug} (${best.reasons.join("; ") || "ranked first"})${ranked[1] ? `; runner-up ${ranked[1].slug}` : ""}`
|
|
14759
|
+
);
|
|
14760
|
+
}
|
|
14761
|
+
const track = await resolveTrack(dir, chosen, flags, dryRun);
|
|
14630
14762
|
let measured;
|
|
14631
14763
|
try {
|
|
14632
14764
|
r.log(`measuring ${track.name}\u2026`);
|
|
@@ -16220,7 +16352,7 @@ function joinDocs(parts, opts = {}) {
|
|
|
16220
16352
|
{
|
|
16221
16353
|
id,
|
|
16222
16354
|
key: d.source.videoKey,
|
|
16223
|
-
name:
|
|
16355
|
+
name: basename14(part.file.path),
|
|
16224
16356
|
start: round33(at2.start),
|
|
16225
16357
|
in: round33(seg.in),
|
|
16226
16358
|
out: round33(seg.out),
|
|
@@ -16465,7 +16597,7 @@ async function cmdJoin(argv) {
|
|
|
16465
16597
|
const remuxed = await copyRecording(c.from, to, c.remux);
|
|
16466
16598
|
if (!remuxed && c.remux !== "mov")
|
|
16467
16599
|
plan.notes.push(
|
|
16468
|
-
`could not read ${
|
|
16600
|
+
`could not read ${basename14(c.from)}'s audio in Node, so it was copied as it is; its length comes from the container`
|
|
16469
16601
|
);
|
|
16470
16602
|
} else await copyFile3(c.from, to);
|
|
16471
16603
|
}
|
|
@@ -16839,7 +16971,7 @@ async function cmdTakeInfo(argv) {
|
|
|
16839
16971
|
// src/plugin/audio.ts
|
|
16840
16972
|
import { mkdtemp as mkdtemp2, rm as rm5, writeFile as writeFile9 } from "fs/promises";
|
|
16841
16973
|
import { tmpdir as tmpdir3 } from "os";
|
|
16842
|
-
import { basename as
|
|
16974
|
+
import { basename as basename15, join as join29 } from "path";
|
|
16843
16975
|
import { clipGain as clipGain3 } from "@vosjs/studio-core";
|
|
16844
16976
|
var USAGE4 = "vos audio measure <take> [--json]";
|
|
16845
16977
|
async function fileFor(dir, key, fetchImpl) {
|
|
@@ -16852,7 +16984,7 @@ async function fileFor(dir, key, fetchImpl) {
|
|
|
16852
16984
|
const res = await fetchImpl(key);
|
|
16853
16985
|
if (!res.ok) return { skipped: `GET ${key} answered ${res.status}` };
|
|
16854
16986
|
const tmp = await mkdtemp2(join29(tmpdir3(), "vos-audio-"));
|
|
16855
|
-
const path = join29(tmp,
|
|
16987
|
+
const path = join29(tmp, basename15(new URL(key).pathname) || "audio");
|
|
16856
16988
|
await writeFile9(path, new Uint8Array(await res.arrayBuffer()));
|
|
16857
16989
|
return { path, cleanup: () => rm5(tmp, { recursive: true, force: true }) };
|
|
16858
16990
|
}
|
|
@@ -16932,11 +17064,238 @@ async function cmdAudio(argv) {
|
|
|
16932
17064
|
return failed.length ? EXIT_ERROR : EXIT_OK;
|
|
16933
17065
|
}
|
|
16934
17066
|
|
|
17067
|
+
// src/plugin/musicCmd.ts
|
|
17068
|
+
import { existsSync as existsSync27, readFileSync as readFileSync10, statSync as statSync8 } from "fs";
|
|
17069
|
+
import { basename as basename16, resolve as resolve20 } from "path";
|
|
17070
|
+
import { rankBeds as rankBeds3, trackBySlug as trackBySlug2 } from "@vosjs/shared/music";
|
|
17071
|
+
import { filmSummaryOf as filmSummaryOf3, musicSlugsOfDoc } from "@vosjs/studio-core";
|
|
17072
|
+
var BOOLEAN_FLAGS14 = /* @__PURE__ */ new Set([
|
|
17073
|
+
"json",
|
|
17074
|
+
"help",
|
|
17075
|
+
"loops",
|
|
17076
|
+
"voice",
|
|
17077
|
+
"no-voice",
|
|
17078
|
+
"fade-in"
|
|
17079
|
+
]);
|
|
17080
|
+
var MULTI_FLAGS3 = /* @__PURE__ */ new Set(["like"]);
|
|
17081
|
+
var USAGE5 = 'vos music ls [--mood <slug>] [--vocals none|chops|lead] [--loops] [--bpm <lo>-<hi>] [--min-length <s>] [--q <words>] [--json]\nvos music pick <take|config.json> [--at <step id|seconds>] [--mood <slug|tag>] [--words "\u2026"] [--voice|--no-voice] [--like <vos id|slug>]... [--top <n>] [--json]';
|
|
17082
|
+
var mmss = (s) => {
|
|
17083
|
+
const whole = Math.round(s);
|
|
17084
|
+
return `${Math.floor(whole / 60)}:${String(whole % 60).padStart(2, "0")}`;
|
|
17085
|
+
};
|
|
17086
|
+
var VOCAL_WORDS = {
|
|
17087
|
+
none: "no vocals",
|
|
17088
|
+
chops: "vocal chops",
|
|
17089
|
+
lead: "sung lead"
|
|
17090
|
+
};
|
|
17091
|
+
function trackLine(t) {
|
|
17092
|
+
const bpm = t.bpm === null || t.bpm === void 0 ? "\u2014" : `${t.bpm} bpm${t.beatConfidence === "low" ? "?" : t.beatConfidence === "confirmed" ? "" : ""}`;
|
|
17093
|
+
return [
|
|
17094
|
+
t.slug.padEnd(26),
|
|
17095
|
+
(t.mood ?? "").padEnd(10),
|
|
17096
|
+
mmss(t.duration).padStart(5),
|
|
17097
|
+
bpm.padStart(10),
|
|
17098
|
+
VOCAL_WORDS[t.vocals ?? "none"].padEnd(11),
|
|
17099
|
+
t.loops ? "loops" : " ",
|
|
17100
|
+
t.description ? JSON.stringify(t.description) : ""
|
|
17101
|
+
].join(" ");
|
|
17102
|
+
}
|
|
17103
|
+
function bpmRange(raw) {
|
|
17104
|
+
if (!raw) return null;
|
|
17105
|
+
const m = /^(\d+(?:\.\d+)?)\s*-\s*(\d+(?:\.\d+)?)$/.exec(raw.trim());
|
|
17106
|
+
if (m) return [Number(m[1]), Number(m[2])];
|
|
17107
|
+
const one = Number(raw);
|
|
17108
|
+
if (Number.isFinite(one)) return [one, Infinity];
|
|
17109
|
+
throw new UsageError(`--bpm expects <lo>-<hi>, got "${raw}"`);
|
|
17110
|
+
}
|
|
17111
|
+
function filterTracks(tracks, f) {
|
|
17112
|
+
const q = f.q?.toLowerCase().trim();
|
|
17113
|
+
const words2 = q ? q.split(/\s+/).filter(Boolean) : [];
|
|
17114
|
+
return tracks.filter((t) => {
|
|
17115
|
+
if (t.removedAt) return false;
|
|
17116
|
+
if (f.mood && (t.mood ?? "").toLowerCase() !== f.mood.toLowerCase()) {
|
|
17117
|
+
if (!(t.tags ?? []).some((x) => x.toLowerCase() === f.mood.toLowerCase()))
|
|
17118
|
+
return false;
|
|
17119
|
+
}
|
|
17120
|
+
if (f.vocals && (t.vocals ?? "none") !== f.vocals) return false;
|
|
17121
|
+
if (f.loops && !t.loops) return false;
|
|
17122
|
+
if (f.bpm) {
|
|
17123
|
+
if (t.bpm === null || t.bpm === void 0) return false;
|
|
17124
|
+
if (t.bpm < f.bpm[0] || t.bpm > f.bpm[1]) return false;
|
|
17125
|
+
}
|
|
17126
|
+
if (f.minLength !== void 0 && t.duration < f.minLength && !t.loops)
|
|
17127
|
+
return false;
|
|
17128
|
+
if (words2.length) {
|
|
17129
|
+
const hay = [
|
|
17130
|
+
t.slug,
|
|
17131
|
+
t.title,
|
|
17132
|
+
t.artist ?? "",
|
|
17133
|
+
t.mood ?? "",
|
|
17134
|
+
...t.tags ?? [],
|
|
17135
|
+
t.description ?? ""
|
|
17136
|
+
].join(" ").toLowerCase();
|
|
17137
|
+
if (!words2.every((w) => hay.includes(w))) return false;
|
|
17138
|
+
}
|
|
17139
|
+
return true;
|
|
17140
|
+
});
|
|
17141
|
+
}
|
|
17142
|
+
async function loadFilm(ref) {
|
|
17143
|
+
const path = resolve20(ref);
|
|
17144
|
+
if (!existsSync27(path)) throw new UsageError(`${ref}: no such take or file`);
|
|
17145
|
+
if (statSync8(path).isDirectory()) {
|
|
17146
|
+
const take = await loadTake(path);
|
|
17147
|
+
if (!take.doc)
|
|
17148
|
+
throw new UsageError(`${ref} has no doc.json; run vos plan first`);
|
|
17149
|
+
const sync = readSyncState(path);
|
|
17150
|
+
return { doc: take.doc, seed: sync?.vosId ?? basename16(path), dir: path };
|
|
17151
|
+
}
|
|
17152
|
+
let config;
|
|
17153
|
+
try {
|
|
17154
|
+
config = JSON.parse(readFileSync10(path, "utf8"));
|
|
17155
|
+
} catch {
|
|
17156
|
+
throw new UsageError(`${ref}: not a take directory or a JSON config`);
|
|
17157
|
+
}
|
|
17158
|
+
if (!config || typeof config !== "object" || !("version" in config))
|
|
17159
|
+
throw new UsageError(`${ref}: a program's config.json carries a version`);
|
|
17160
|
+
const doc = {
|
|
17161
|
+
program: { config },
|
|
17162
|
+
audio: [],
|
|
17163
|
+
overlays: [],
|
|
17164
|
+
objects: []
|
|
17165
|
+
};
|
|
17166
|
+
return { doc, seed: basename16(path, ".json"), dir: null };
|
|
17167
|
+
}
|
|
17168
|
+
async function likedSlugs(refs, origin) {
|
|
17169
|
+
const slugs = /* @__PURE__ */ new Set();
|
|
17170
|
+
const notes = [];
|
|
17171
|
+
for (const ref of refs) {
|
|
17172
|
+
const id = parseVosId(ref);
|
|
17173
|
+
if (!id) {
|
|
17174
|
+
slugs.add(ref.toLowerCase());
|
|
17175
|
+
continue;
|
|
17176
|
+
}
|
|
17177
|
+
try {
|
|
17178
|
+
const vos = await (await fetch(`${origin}/api/vos/${id}`)).json();
|
|
17179
|
+
if (!vos.currentVersionId) throw new Error("no version");
|
|
17180
|
+
const doc = await (await fetch(
|
|
17181
|
+
`${origin}/api/vos/${id}/versions/${vos.currentVersionId}/doc`
|
|
17182
|
+
)).json();
|
|
17183
|
+
for (const s of musicSlugsOfDoc(doc)) slugs.add(s);
|
|
17184
|
+
} catch {
|
|
17185
|
+
notes.push(
|
|
17186
|
+
`--like ${ref}: could not read that vos's document (is it public?)`
|
|
17187
|
+
);
|
|
17188
|
+
}
|
|
17189
|
+
}
|
|
17190
|
+
return { slugs: [...slugs], notes };
|
|
17191
|
+
}
|
|
17192
|
+
function scoreLine(take, r, film) {
|
|
17193
|
+
const at2 = r.placement?.swellAt ?? film.payoff;
|
|
17194
|
+
return `vos score ${take ?? "<take>"} --track ${r.slug}${at2 !== void 0 && at2 !== null ? ` --at ${at2}` : ""}`;
|
|
17195
|
+
}
|
|
17196
|
+
function pickWords(picks, all, film, take) {
|
|
17197
|
+
const refused = all.filter((r) => r.score === null);
|
|
17198
|
+
const head = `${film.duration.toFixed(1)}s film, ${film.cuts.length} cut${film.cuts.length === 1 ? "" : "s"}${film.payoff !== void 0 ? `, payoff at ${mmss(film.payoff)}` : ""}${film.voice ? ", a voice" : ""}${film.mood ? `, asked ${film.mood}` : ""}${film.words ? `, asked "${film.words}"` : ""}`;
|
|
17199
|
+
if (!picks.length) {
|
|
17200
|
+
return `${head}
|
|
17201
|
+
No bed in the library fits: ${refused.length} refused (${[...new Set(refused.map((r) => r.refused))].slice(0, 3).join("; ")}). Compose a score instead (the vos-score skill), or ask with --words.`;
|
|
17202
|
+
}
|
|
17203
|
+
const lines = picks.map((r, i) => {
|
|
17204
|
+
const t = r.track;
|
|
17205
|
+
const facts = [
|
|
17206
|
+
t.mood,
|
|
17207
|
+
t.bpm !== null && t.bpm !== void 0 ? `${t.bpm} bpm${t.beatConfidence === "low" ? "?" : ""}` : null,
|
|
17208
|
+
VOCAL_WORDS[t.vocals ?? "none"],
|
|
17209
|
+
t.loops ? "loops" : null
|
|
17210
|
+
].filter(Boolean).join(", ");
|
|
17211
|
+
return ` ${i + 1}. ${r.slug} ${t.title} ${(r.score ?? 0).toFixed(2)} (${facts})
|
|
17212
|
+
${r.reasons.join("; ") || "fits"}
|
|
17213
|
+
${scoreLine(take, r, film)}`;
|
|
17214
|
+
});
|
|
17215
|
+
const tail = refused.length ? `
|
|
17216
|
+
${refused.length} refused: ${refused.slice(0, 4).map((r) => `${r.slug} (${r.refused})`).join("; ")}${refused.length > 4 ? "; \u2026" : ""}` : "";
|
|
17217
|
+
return `${head}
|
|
17218
|
+
${lines.join("\n")}${tail}`;
|
|
17219
|
+
}
|
|
17220
|
+
async function cmdMusic(argv) {
|
|
17221
|
+
const { positionals, flags, multi } = parseArgs(
|
|
17222
|
+
argv,
|
|
17223
|
+
BOOLEAN_FLAGS14,
|
|
17224
|
+
MULTI_FLAGS3
|
|
17225
|
+
);
|
|
17226
|
+
const verb = positionals[0];
|
|
17227
|
+
if (flags.help === true || !verb || !["ls", "pick"].includes(verb))
|
|
17228
|
+
throw new UsageError(USAGE5);
|
|
17229
|
+
const r = createReporter(flags.json === true);
|
|
17230
|
+
const origin = platformOrigin({
|
|
17231
|
+
origin: strFlag(flags, "origin"),
|
|
17232
|
+
api: strFlag(flags, "api")
|
|
17233
|
+
});
|
|
17234
|
+
const catalog = await fetchMusicCatalog(origin);
|
|
17235
|
+
if (verb === "ls") {
|
|
17236
|
+
const vocals = strFlag(flags, "vocals");
|
|
17237
|
+
if (vocals && !["none", "chops", "lead"].includes(vocals))
|
|
17238
|
+
throw new UsageError("--vocals expects none, chops or lead");
|
|
17239
|
+
const kept = filterTracks(catalog.tracks, {
|
|
17240
|
+
mood: strFlag(flags, "mood"),
|
|
17241
|
+
vocals,
|
|
17242
|
+
loops: flags.loops === true,
|
|
17243
|
+
bpm: bpmRange(strFlag(flags, "bpm")),
|
|
17244
|
+
minLength: strFlag(flags, "min-length") !== void 0 ? numFlag(flags, "min-length", 0) : void 0,
|
|
17245
|
+
q: strFlag(flags, "q")
|
|
17246
|
+
});
|
|
17247
|
+
r.done(
|
|
17248
|
+
{ origin, tracks: kept, total: catalog.tracks.length },
|
|
17249
|
+
kept.length ? kept.map(trackLine).join("\n") : `No track matches; the library holds ${catalog.tracks.length} (GET ${origin}/api/music).`
|
|
17250
|
+
);
|
|
17251
|
+
return EXIT_OK;
|
|
17252
|
+
}
|
|
17253
|
+
const ref = positionals[1];
|
|
17254
|
+
if (!ref) throw new UsageError(USAGE5);
|
|
17255
|
+
const { doc, seed, dir } = await loadFilm(ref);
|
|
17256
|
+
const atRaw = strFlag(flags, "at");
|
|
17257
|
+
const at2 = atRaw !== void 0 ? resolveAt(doc, atRaw) : null;
|
|
17258
|
+
if (flags.voice === true && flags["no-voice"] === true)
|
|
17259
|
+
throw new UsageError("--voice and --no-voice together say nothing");
|
|
17260
|
+
const liked = await likedSlugs(multi.like ?? [], origin);
|
|
17261
|
+
const film = filmSummaryOf3(doc, {
|
|
17262
|
+
seed,
|
|
17263
|
+
...at2 ? { payoff: at2.at } : {},
|
|
17264
|
+
...flags.voice === true ? { voice: true } : flags["no-voice"] === true ? { voice: false } : {},
|
|
17265
|
+
mood: strFlag(flags, "mood"),
|
|
17266
|
+
words: strFlag(flags, "words"),
|
|
17267
|
+
like: liked.slugs,
|
|
17268
|
+
fadeIn: flags["fade-in"] === true
|
|
17269
|
+
});
|
|
17270
|
+
const top = Math.max(1, Math.round(numFlag(flags, "top", 3)));
|
|
17271
|
+
const all = rankBeds3(catalog.tracks, film);
|
|
17272
|
+
const picks = all.filter((x) => x.score !== null).slice(0, top);
|
|
17273
|
+
for (const n of liked.notes) r.warn(n);
|
|
17274
|
+
const asked = strFlag(flags, "mood");
|
|
17275
|
+
if (asked && trackBySlug2(catalog.tracks, asked))
|
|
17276
|
+
r.warn(
|
|
17277
|
+
`--mood ${asked} is a track's slug; to place that track, run vos score --track ${asked}`
|
|
17278
|
+
);
|
|
17279
|
+
r.done(
|
|
17280
|
+
{
|
|
17281
|
+
origin,
|
|
17282
|
+
film,
|
|
17283
|
+
picks: picks.map((x) => ({
|
|
17284
|
+
...x,
|
|
17285
|
+
command: scoreLine(dir ? ref : null, x, film)
|
|
17286
|
+
})),
|
|
17287
|
+
all
|
|
17288
|
+
},
|
|
17289
|
+
pickWords(picks, all, film, dir ? ref : null)
|
|
17290
|
+
);
|
|
17291
|
+
return EXIT_OK;
|
|
17292
|
+
}
|
|
17293
|
+
|
|
16935
17294
|
// src/plugin/look.ts
|
|
16936
17295
|
import { mkdir as mkdir12, mkdtemp as mkdtemp3, readFile as readFile18, rm as rm6 } from "fs/promises";
|
|
16937
|
-
import { existsSync as
|
|
17296
|
+
import { existsSync as existsSync28 } from "fs";
|
|
16938
17297
|
import { tmpdir as tmpdir4 } from "os";
|
|
16939
|
-
import { dirname as dirname10, join as join30, resolve as
|
|
17298
|
+
import { dirname as dirname10, join as join30, resolve as resolve21 } from "path";
|
|
16940
17299
|
import { headersFor, urlSchemeProblem } from "@vosjs/render-core/record";
|
|
16941
17300
|
function quote(value) {
|
|
16942
17301
|
return `"${value.replace(/\s+/g, " ").replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -17455,7 +17814,7 @@ async function inspectPage(page, opts) {
|
|
|
17455
17814
|
settled
|
|
17456
17815
|
};
|
|
17457
17816
|
}
|
|
17458
|
-
var
|
|
17817
|
+
var USAGE6 = "vos look <url> [--session <name> | --storage-state <file>] [--viewport WxH] [--headed] [--click <selector>]... [--type <selector>=<text>]... [--wait <ms>] [--out <dir>] [--json]\n vos look [url] --actions actions.json --until <step id> [--session <name> | --storage-state <file>] [--viewport WxH] [--headed] [--wait <ms>] [--out <dir>] [--json]";
|
|
17459
17818
|
function untilProblem(given, steps) {
|
|
17460
17819
|
if (given.until !== void 0 && given.actions === void 0)
|
|
17461
17820
|
return "--until names a step of a script: pass the script with --actions actions.json";
|
|
@@ -17514,7 +17873,7 @@ async function cmdLook(argv) {
|
|
|
17514
17873
|
if (early) throw new UsageError(early);
|
|
17515
17874
|
let actions;
|
|
17516
17875
|
if (actionsArg) {
|
|
17517
|
-
actions = await loadLookActions(
|
|
17876
|
+
actions = await loadLookActions(resolve21(actionsArg));
|
|
17518
17877
|
const bad = untilProblem(
|
|
17519
17878
|
{ actions: actionsArg, until: untilId, clicks: 0 },
|
|
17520
17879
|
actions.steps
|
|
@@ -17522,21 +17881,21 @@ async function cmdLook(argv) {
|
|
|
17522
17881
|
if (bad) throw new UsageError(bad);
|
|
17523
17882
|
}
|
|
17524
17883
|
const url = positionals[0] ?? actions?.url;
|
|
17525
|
-
if (!url) throw new UsageError(
|
|
17884
|
+
if (!url) throw new UsageError(USAGE6);
|
|
17526
17885
|
const scheme = urlSchemeProblem(url);
|
|
17527
17886
|
if (scheme) throw new UsageError(scheme);
|
|
17528
17887
|
const r = createReporter(flags.json === true);
|
|
17529
17888
|
const viewportFlag = strFlag(flags, "viewport");
|
|
17530
17889
|
const viewport = !viewportFlag && actions?.viewport ? actions.viewport : parseViewport2(viewportFlag);
|
|
17531
|
-
const outDir =
|
|
17890
|
+
const outDir = resolve21(strFlag(flags, "out") ?? "look");
|
|
17532
17891
|
const headed = flags.headed === true;
|
|
17533
17892
|
const waitRaw = strFlag(flags, "wait");
|
|
17534
17893
|
const waitMs = waitRaw === void 0 ? 0 : Number(waitRaw);
|
|
17535
17894
|
if (!Number.isFinite(waitMs) || waitMs < 0 || waitMs > 6e4)
|
|
17536
17895
|
throw new UsageError("--wait expects milliseconds, 0 to 60000");
|
|
17537
17896
|
const storageRaw = strFlag(flags, "storage-state");
|
|
17538
|
-
const storageState = storageRaw ?
|
|
17539
|
-
if (storageState && !
|
|
17897
|
+
const storageState = storageRaw ? resolve21(storageRaw) : void 0;
|
|
17898
|
+
if (storageState && !existsSync28(storageState))
|
|
17540
17899
|
throw new UsageError(`--storage-state: no such file: ${storageState}`);
|
|
17541
17900
|
const sessionName = strFlag(flags, "session");
|
|
17542
17901
|
if (sessionName) {
|
|
@@ -17546,7 +17905,7 @@ async function cmdLook(argv) {
|
|
|
17546
17905
|
throw new UsageError(
|
|
17547
17906
|
"--session and --storage-state are two doors to one page: a persistent profile cannot take a storage state. Pass one"
|
|
17548
17907
|
);
|
|
17549
|
-
if (!
|
|
17908
|
+
if (!existsSync28(sessionDir(sessionName)))
|
|
17550
17909
|
throw new UsageError(
|
|
17551
17910
|
`no session "${sessionName}". Make one: vos session open <url> --name ${sessionName} (a Chrome window opens; sign in and close it)`
|
|
17552
17911
|
);
|
|
@@ -17563,7 +17922,7 @@ async function cmdLook(argv) {
|
|
|
17563
17922
|
r,
|
|
17564
17923
|
url,
|
|
17565
17924
|
actions,
|
|
17566
|
-
actionsPath:
|
|
17925
|
+
actionsPath: resolve21(actionsArg),
|
|
17567
17926
|
untilId,
|
|
17568
17927
|
viewport,
|
|
17569
17928
|
outDir,
|
|
@@ -17727,10 +18086,9 @@ async function lookUntil(o) {
|
|
|
17727
18086
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
17728
18087
|
import {
|
|
17729
18088
|
cpSync,
|
|
17730
|
-
existsSync as
|
|
18089
|
+
existsSync as existsSync30,
|
|
17731
18090
|
mkdirSync as mkdirSync6,
|
|
17732
|
-
readFileSync as
|
|
17733
|
-
rmSync as rmSync3,
|
|
18091
|
+
readFileSync as readFileSync12,
|
|
17734
18092
|
writeFileSync as writeFileSync6
|
|
17735
18093
|
} from "fs";
|
|
17736
18094
|
import { homedir as homedir2 } from "os";
|
|
@@ -17738,7 +18096,7 @@ import { join as join32 } from "path";
|
|
|
17738
18096
|
import { chromium as chromium2 } from "playwright";
|
|
17739
18097
|
|
|
17740
18098
|
// src/plugin/machine.ts
|
|
17741
|
-
import { existsSync as
|
|
18099
|
+
import { existsSync as existsSync29, readFileSync as readFileSync11, readdirSync as readdirSync6, statSync as statSync9 } from "fs";
|
|
17742
18100
|
import { dirname as dirname11, join as join31 } from "path";
|
|
17743
18101
|
var AGENT_NAMES = [
|
|
17744
18102
|
"claude",
|
|
@@ -17759,7 +18117,7 @@ var HOME_DIRS = {
|
|
|
17759
18117
|
copilot: [".copilot"]
|
|
17760
18118
|
};
|
|
17761
18119
|
function detectAgents(root, opts = {}) {
|
|
17762
|
-
const exists = opts.exists ??
|
|
18120
|
+
const exists = opts.exists ?? existsSync29;
|
|
17763
18121
|
const out = [];
|
|
17764
18122
|
for (const agent of AGENT_NAMES) {
|
|
17765
18123
|
for (const rel of PROJECT_DIRS[agent]) {
|
|
@@ -17806,7 +18164,7 @@ function skillsDirFor(home) {
|
|
|
17806
18164
|
function fallbackSkillsHome(root) {
|
|
17807
18165
|
return { agent: "codex", dir: join31(root, ".agents"), scope: "project" };
|
|
17808
18166
|
}
|
|
17809
|
-
function installedSkills(dir, exists =
|
|
18167
|
+
function installedSkills(dir, exists = existsSync29, list = (p) => {
|
|
17810
18168
|
try {
|
|
17811
18169
|
return readdirSync6(p);
|
|
17812
18170
|
} catch {
|
|
@@ -17824,7 +18182,7 @@ var RULES_BODY = `## Product videos (vosso)
|
|
|
17824
18182
|
- Hand back: vos open take serves the take into the studio at vos.so, doc.json intact
|
|
17825
18183
|
- Local by default: vos push only when asked for a link, the shelf or a cloud render
|
|
17826
18184
|
- Deleting: vos delete moves a vos to Trash and vos restore brings it back; if you deleted by mistake, restore it and say so. Only the person can delete forever, at vos.so/app/trash
|
|
17827
|
-
- Credentials: VOS_API_KEY, then ~/.config/vos/credentials, then vos login; never print one
|
|
18185
|
+
- Credentials: VOS_API_KEY, then the account in use at ~/.config/vos/credentials (vos whoami says which; vos switch <handle> changes it), then vos login; never print one
|
|
17828
18186
|
- Reference: https://vos.so/llms-full.txt`;
|
|
17829
18187
|
var RULES_BLOCK = `${RULES_BEGIN}
|
|
17830
18188
|
${RULES_BODY}
|
|
@@ -17847,7 +18205,7 @@ ${RULES_BLOCK}
|
|
|
17847
18205
|
}
|
|
17848
18206
|
return { text, changed: text !== current };
|
|
17849
18207
|
}
|
|
17850
|
-
function rulesFileFor(root, exists =
|
|
18208
|
+
function rulesFileFor(root, exists = existsSync29) {
|
|
17851
18209
|
const agents = join31(root, "AGENTS.md");
|
|
17852
18210
|
if (exists(agents)) return agents;
|
|
17853
18211
|
const claude = join31(root, "CLAUDE.md");
|
|
@@ -17904,6 +18262,18 @@ var NODE_MIN_MAJOR = 18;
|
|
|
17904
18262
|
function major(version) {
|
|
17905
18263
|
return parseInt(version.split(".")[0] ?? "0", 10);
|
|
17906
18264
|
}
|
|
18265
|
+
function credentialLine(facts) {
|
|
18266
|
+
const accounts = facts.accounts ?? [];
|
|
18267
|
+
const active = accounts.find((a) => a.active);
|
|
18268
|
+
const others = accounts.filter((a) => !a.active).map((a) => a.label);
|
|
18269
|
+
if (active) {
|
|
18270
|
+
return `${active.label} \u2713${others.length ? ` (also ${others.join(", ")})` : ""}`;
|
|
18271
|
+
}
|
|
18272
|
+
if (facts.credential) {
|
|
18273
|
+
return `present \u2713${others.length ? ` (stored: ${others.join(", ")}; vos switch to use one)` : ""}`;
|
|
18274
|
+
}
|
|
18275
|
+
return `absent (vos login when you need hosting)${others.length ? `; stored: ${others.join(", ")}, vos switch to use one` : ""}`;
|
|
18276
|
+
}
|
|
17907
18277
|
function doctorReport(facts) {
|
|
17908
18278
|
const lines = [];
|
|
17909
18279
|
const nodeOk = major(facts.node) >= NODE_MIN_MAJOR;
|
|
@@ -17929,9 +18299,7 @@ function doctorReport(facts) {
|
|
|
17929
18299
|
} else {
|
|
17930
18300
|
lines.push("skills none \u2717 run: npx vos setup");
|
|
17931
18301
|
}
|
|
17932
|
-
lines.push(
|
|
17933
|
-
`credential ${facts.credential ? "present \u2713" : "absent (vos login when you need hosting)"}`
|
|
17934
|
-
);
|
|
18302
|
+
lines.push(`credential ${credentialLine(facts)}`);
|
|
17935
18303
|
if (facts.devServer) {
|
|
17936
18304
|
const d = facts.devServer;
|
|
17937
18305
|
lines.push(
|
|
@@ -17952,7 +18320,7 @@ function doctorReport(facts) {
|
|
|
17952
18320
|
}
|
|
17953
18321
|
function bundledSkillsVersion(dir) {
|
|
17954
18322
|
try {
|
|
17955
|
-
const v =
|
|
18323
|
+
const v = readFileSync11(join31(dir, "VERSION"), "utf8").trim();
|
|
17956
18324
|
return /^\d+\.\d+\.\d+$/.test(v) ? v : null;
|
|
17957
18325
|
} catch {
|
|
17958
18326
|
return null;
|
|
@@ -17962,12 +18330,12 @@ function bundledSkillsDir(from) {
|
|
|
17962
18330
|
let dir = dirname11(from);
|
|
17963
18331
|
for (let i = 0; i < 6; i++) {
|
|
17964
18332
|
const pkg = join31(dir, "package.json");
|
|
17965
|
-
if (
|
|
18333
|
+
if (existsSync29(pkg)) {
|
|
17966
18334
|
try {
|
|
17967
|
-
const name = JSON.parse(
|
|
18335
|
+
const name = JSON.parse(readFileSync11(pkg, "utf8")).name;
|
|
17968
18336
|
if (name === "@vosjs/cli") {
|
|
17969
18337
|
const skills = join31(dir, "skills");
|
|
17970
|
-
return
|
|
18338
|
+
return existsSync29(skills) && statSync9(skills).isDirectory() ? skills : null;
|
|
17971
18339
|
}
|
|
17972
18340
|
} catch {
|
|
17973
18341
|
}
|
|
@@ -17980,7 +18348,7 @@ function bundledSkillsDir(from) {
|
|
|
17980
18348
|
}
|
|
17981
18349
|
|
|
17982
18350
|
// src/plugin/machineCmd.ts
|
|
17983
|
-
var
|
|
18351
|
+
var BOOLEAN_FLAGS15 = /* @__PURE__ */ new Set([
|
|
17984
18352
|
"json",
|
|
17985
18353
|
"help",
|
|
17986
18354
|
"global",
|
|
@@ -17989,6 +18357,7 @@ var BOOLEAN_FLAGS14 = /* @__PURE__ */ new Set([
|
|
|
17989
18357
|
"no-rules",
|
|
17990
18358
|
"no-browser"
|
|
17991
18359
|
]);
|
|
18360
|
+
var LOGOUT_FLAGS = /* @__PURE__ */ new Set([...BOOLEAN_FLAGS15, "all"]);
|
|
17992
18361
|
var SKILLS_SOURCE = "vosjs/skills";
|
|
17993
18362
|
var SKILLS_CLI_VERSION = "1.7.2";
|
|
17994
18363
|
function skillsCatalogAt(version) {
|
|
@@ -18003,7 +18372,7 @@ function npx() {
|
|
|
18003
18372
|
function bundledChromium() {
|
|
18004
18373
|
try {
|
|
18005
18374
|
const p = chromium2.executablePath();
|
|
18006
|
-
return p &&
|
|
18375
|
+
return p && existsSync30(p) ? p : null;
|
|
18007
18376
|
} catch {
|
|
18008
18377
|
return null;
|
|
18009
18378
|
}
|
|
@@ -18012,7 +18381,7 @@ function probe2() {
|
|
|
18012
18381
|
return probeBrowser({
|
|
18013
18382
|
platform: process.platform,
|
|
18014
18383
|
env: process.env,
|
|
18015
|
-
exists:
|
|
18384
|
+
exists: existsSync30,
|
|
18016
18385
|
bundled: bundledChromium
|
|
18017
18386
|
});
|
|
18018
18387
|
}
|
|
@@ -18058,12 +18427,26 @@ async function doctorFacts(opts) {
|
|
|
18058
18427
|
browser: probe2(),
|
|
18059
18428
|
ffmpeg: ffmpegVersion(),
|
|
18060
18429
|
skills: skillsFacts(opts.homes),
|
|
18061
|
-
credential:
|
|
18430
|
+
credential: safeResolve() !== null,
|
|
18431
|
+
accounts: storedAccounts(platformOrigin()),
|
|
18062
18432
|
...opts.url ? { devServer: await devServerFact(opts.url) } : {}
|
|
18063
18433
|
};
|
|
18064
18434
|
}
|
|
18435
|
+
function safeResolve() {
|
|
18436
|
+
try {
|
|
18437
|
+
return resolveCredential();
|
|
18438
|
+
} catch {
|
|
18439
|
+
return null;
|
|
18440
|
+
}
|
|
18441
|
+
}
|
|
18442
|
+
function storedAccounts(origin, store = DEFAULT_STORE) {
|
|
18443
|
+
return listStored(store, origin).map((c) => ({
|
|
18444
|
+
label: accountLabel(c.account),
|
|
18445
|
+
active: isActive(c, store)
|
|
18446
|
+
}));
|
|
18447
|
+
}
|
|
18065
18448
|
async function cmdSetup(argv) {
|
|
18066
|
-
const { flags } = parseArgs(argv,
|
|
18449
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18067
18450
|
const r = reporterFor(flags);
|
|
18068
18451
|
const root = process.cwd();
|
|
18069
18452
|
const global = flags.global === true;
|
|
@@ -18165,7 +18548,7 @@ async function cmdSetup(argv) {
|
|
|
18165
18548
|
let rules = null;
|
|
18166
18549
|
if (!noRules) {
|
|
18167
18550
|
const file = rulesFileFor(root);
|
|
18168
|
-
const existing =
|
|
18551
|
+
const existing = existsSync30(file) ? readFileSync12(file, "utf8") : null;
|
|
18169
18552
|
const { text, changed } = applyRulesBlock(existing);
|
|
18170
18553
|
if (changed) writeFileSync6(file, text);
|
|
18171
18554
|
rules = { file, changed };
|
|
@@ -18196,7 +18579,7 @@ Next: ${report.next_step}`
|
|
|
18196
18579
|
return report.ok ? EXIT_OK : EXIT_NO_BROWSER;
|
|
18197
18580
|
}
|
|
18198
18581
|
async function cmdDoctor(argv) {
|
|
18199
|
-
const { flags } = parseArgs(argv,
|
|
18582
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18200
18583
|
const r = reporterFor(flags);
|
|
18201
18584
|
const root = process.cwd();
|
|
18202
18585
|
const homes = detectAgents(root, { home: homedir2(), global: true });
|
|
@@ -18215,35 +18598,48 @@ Next: ${report.next_step}`
|
|
|
18215
18598
|
return report.ok ? EXIT_OK : EXIT_NO_BROWSER;
|
|
18216
18599
|
}
|
|
18217
18600
|
async function cmdWhoami(argv) {
|
|
18218
|
-
const { flags } = parseArgs(argv,
|
|
18601
|
+
const { flags } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18219
18602
|
const r = reporterFor(flags);
|
|
18220
18603
|
const origin = platformOrigin({
|
|
18221
18604
|
origin: strFlag(flags, "origin"),
|
|
18222
18605
|
api: strFlag(flags, "api")
|
|
18223
18606
|
});
|
|
18224
|
-
const
|
|
18607
|
+
const stored = storedAccounts(origin);
|
|
18608
|
+
const others = stored.filter((a) => !a.active).map((a) => a.label);
|
|
18609
|
+
const alsoStored = others.length ? ` Also stored: ${others.join(", ")}; vos switch <name> to use one.` : "";
|
|
18610
|
+
const key = resolveCredential({
|
|
18611
|
+
key: strFlag(flags, "key"),
|
|
18612
|
+
account: strFlag(flags, "account"),
|
|
18613
|
+
origin
|
|
18614
|
+
});
|
|
18225
18615
|
if (!key) {
|
|
18226
18616
|
r.done(
|
|
18227
18617
|
{
|
|
18228
18618
|
signedIn: false,
|
|
18229
18619
|
origin,
|
|
18620
|
+
accounts: stored,
|
|
18230
18621
|
next_step: "vos login (only needed for hosting, sharing or cloud rendering)"
|
|
18231
18622
|
},
|
|
18232
|
-
`Not signed in to ${origin}. Recording and rendering need no account; vos login when you want a link
|
|
18623
|
+
`Not signed in to ${origin}. Recording and rendering need no account; vos login when you want a link.${alsoStored}`
|
|
18233
18624
|
);
|
|
18234
18625
|
return EXIT_ERROR;
|
|
18235
18626
|
}
|
|
18627
|
+
const resolved = lastCredential();
|
|
18628
|
+
const via = resolved?.via ?? "stored";
|
|
18629
|
+
const viaLine = via === "flag" ? " (the key passed as --key)" : via === "env" ? " (from VOS_API_KEY, which outranks the stored credential)" : via === "account-flag" ? " (--account)" : via === "account-env" ? ` (${ACCOUNT_ENV})` : "";
|
|
18236
18630
|
const res = await apiJson(origin, "/api/user/whoami", { key });
|
|
18237
18631
|
if (res.status === 404) {
|
|
18238
18632
|
r.done(
|
|
18239
18633
|
{
|
|
18240
18634
|
signedIn: true,
|
|
18241
18635
|
origin,
|
|
18636
|
+
via,
|
|
18242
18637
|
user: null,
|
|
18243
18638
|
key: null,
|
|
18639
|
+
accounts: stored,
|
|
18244
18640
|
next_step: "vos push when you want the work hosted"
|
|
18245
18641
|
},
|
|
18246
|
-
`A credential is present for ${origin} (this origin cannot say whose)
|
|
18642
|
+
`A credential is present for ${origin}${viaLine} (this origin cannot say whose).${alsoStored}`
|
|
18247
18643
|
);
|
|
18248
18644
|
return EXIT_OK;
|
|
18249
18645
|
}
|
|
@@ -18252,50 +18648,156 @@ async function cmdWhoami(argv) {
|
|
|
18252
18648
|
{
|
|
18253
18649
|
signedIn: false,
|
|
18254
18650
|
origin,
|
|
18651
|
+
via,
|
|
18255
18652
|
error: apiError("whoami", res),
|
|
18653
|
+
accounts: stored,
|
|
18256
18654
|
next_step: "vos login"
|
|
18257
18655
|
},
|
|
18258
|
-
`The stored credential is refused by ${origin}: ${apiError("whoami", res)}. Run vos login
|
|
18656
|
+
`The stored credential is refused by ${origin}${viaLine}: ${apiError("whoami", res)}. Run vos login.${alsoStored}`
|
|
18259
18657
|
);
|
|
18260
18658
|
return EXIT_ERROR;
|
|
18261
18659
|
}
|
|
18262
18660
|
if (res.status !== 200) throw new Error(apiError("whoami", res));
|
|
18263
18661
|
const user = res.body.user;
|
|
18662
|
+
const actor = res.body.actor;
|
|
18264
18663
|
const k = res.body.key;
|
|
18265
18664
|
const who = user?.username ? `@${user.username}` : user?.name ?? "an account";
|
|
18665
|
+
const orgLine = user?.kind === "org" ? ` (an organization${actor ? `, ${actor.username ? `@${actor.username}` : actor.name ?? "you"} recorded as the person behind it` : ""})` : "";
|
|
18266
18666
|
const keyLine = k ? `key "${k.name ?? ""}" (${k.prefix ?? "\u2026"}, ${(k.scopes ?? []).join(", ") || "no scopes"})` : "a session, not a key";
|
|
18667
|
+
if (via === "stored" && resolved && !resolved.account && user?.id) {
|
|
18668
|
+
const active = readActive(DEFAULT_STORE);
|
|
18669
|
+
if (active && active.key === key) {
|
|
18670
|
+
activate(DEFAULT_STORE, {
|
|
18671
|
+
...active,
|
|
18672
|
+
account: {
|
|
18673
|
+
id: user.id,
|
|
18674
|
+
kind: user.kind === "org" ? "org" : "person",
|
|
18675
|
+
handle: user.username ?? null
|
|
18676
|
+
}
|
|
18677
|
+
});
|
|
18678
|
+
}
|
|
18679
|
+
}
|
|
18267
18680
|
r.done(
|
|
18268
18681
|
{
|
|
18269
18682
|
signedIn: true,
|
|
18270
18683
|
origin,
|
|
18684
|
+
via,
|
|
18271
18685
|
user,
|
|
18686
|
+
actor: actor ?? null,
|
|
18272
18687
|
key: k,
|
|
18688
|
+
accounts: storedAccounts(origin),
|
|
18273
18689
|
next_step: "vos push when you want the work hosted"
|
|
18274
18690
|
},
|
|
18275
|
-
`Signed in to ${origin} as ${who}, with ${keyLine}
|
|
18691
|
+
`Signed in to ${origin} as ${who}${orgLine}, with ${keyLine}${viaLine}.${alsoStored}`
|
|
18692
|
+
);
|
|
18693
|
+
return EXIT_OK;
|
|
18694
|
+
}
|
|
18695
|
+
function cmdSwitch(argv) {
|
|
18696
|
+
const { flags, positionals } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18697
|
+
const r = reporterFor(flags);
|
|
18698
|
+
const origin = platformOrigin({
|
|
18699
|
+
origin: strFlag(flags, "origin"),
|
|
18700
|
+
api: strFlag(flags, "api")
|
|
18701
|
+
});
|
|
18702
|
+
const store = DEFAULT_STORE;
|
|
18703
|
+
const stored = listStored(store, origin);
|
|
18704
|
+
const active = readActive(store);
|
|
18705
|
+
const target = switchTarget(
|
|
18706
|
+
stored,
|
|
18707
|
+
active?.key ?? null,
|
|
18708
|
+
positionals[0],
|
|
18709
|
+
origin
|
|
18710
|
+
);
|
|
18711
|
+
if (!target.ok) throw new UsageError(target.error);
|
|
18712
|
+
const to = target.to;
|
|
18713
|
+
if (active && active.key === to.key) {
|
|
18714
|
+
r.done(
|
|
18715
|
+
{
|
|
18716
|
+
origin,
|
|
18717
|
+
account: to.account,
|
|
18718
|
+
changed: false,
|
|
18719
|
+
accounts: storedAccounts(origin, store),
|
|
18720
|
+
next_step: "vos push when you want the work hosted"
|
|
18721
|
+
},
|
|
18722
|
+
`${accountLabel(to.account)} is already the account in use on ${origin}.`
|
|
18723
|
+
);
|
|
18724
|
+
return EXIT_OK;
|
|
18725
|
+
}
|
|
18726
|
+
activate(store, to);
|
|
18727
|
+
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
18728
|
+
r.done(
|
|
18729
|
+
{
|
|
18730
|
+
origin,
|
|
18731
|
+
account: to.account,
|
|
18732
|
+
changed: true,
|
|
18733
|
+
accounts: storedAccounts(origin, store),
|
|
18734
|
+
next_step: envKey ? "unset VOS_API_KEY; it outranks the stored credential" : "vos push when you want the work hosted"
|
|
18735
|
+
},
|
|
18736
|
+
`Now ${accountLabel(to.account)} on ${origin}${active?.account ? ` (${accountLabel(active.account)} stays stored)` : ""}.${envKey ? " VOS_API_KEY is set in this shell and still outranks it." : ""}`
|
|
18276
18737
|
);
|
|
18277
18738
|
return EXIT_OK;
|
|
18278
18739
|
}
|
|
18279
18740
|
function cmdLogout(argv) {
|
|
18280
|
-
const { flags } = parseArgs(argv,
|
|
18741
|
+
const { flags, positionals } = parseArgs(argv, LOGOUT_FLAGS);
|
|
18281
18742
|
const r = reporterFor(flags);
|
|
18282
|
-
const
|
|
18283
|
-
|
|
18743
|
+
const origin = platformOrigin({
|
|
18744
|
+
origin: strFlag(flags, "origin"),
|
|
18745
|
+
api: strFlag(flags, "api")
|
|
18746
|
+
});
|
|
18747
|
+
const store = DEFAULT_STORE;
|
|
18284
18748
|
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
18749
|
+
const envNote = envKey ? " VOS_API_KEY is still set in this shell and still resolves." : "";
|
|
18750
|
+
const envStep = envKey ? "unset VOS_API_KEY as well; it still resolves" : "vos login when you next need hosting";
|
|
18751
|
+
if (flags.all === true) {
|
|
18752
|
+
const { had } = removeAll(store);
|
|
18753
|
+
r.done(
|
|
18754
|
+
{
|
|
18755
|
+
path: CREDENTIALS_PATH,
|
|
18756
|
+
removed: had,
|
|
18757
|
+
all: true,
|
|
18758
|
+
envCredential: envKey,
|
|
18759
|
+
next_step: envStep
|
|
18760
|
+
},
|
|
18761
|
+
(had ? "Removed every stored credential." : "Nothing was stored.") + envNote
|
|
18762
|
+
);
|
|
18763
|
+
return EXIT_OK;
|
|
18764
|
+
}
|
|
18765
|
+
const ref = positionals[0];
|
|
18766
|
+
const target = ref ? findStored(store, origin, ref) : readActive(store);
|
|
18767
|
+
if (!target) {
|
|
18768
|
+
const have = storedAccounts(origin, store);
|
|
18769
|
+
r.done(
|
|
18770
|
+
{
|
|
18771
|
+
path: CREDENTIALS_PATH,
|
|
18772
|
+
removed: false,
|
|
18773
|
+
envCredential: envKey,
|
|
18774
|
+
accounts: have,
|
|
18775
|
+
next_step: envStep
|
|
18776
|
+
},
|
|
18777
|
+
(ref ? `Nothing stored for ${ref.startsWith("@") ? ref : `@${ref}`} on ${origin}.` : `Nothing stored at ${CREDENTIALS_PATH}.`) + (have.length ? ` Stored: ${have.map((a) => a.label).join(", ")}.` : "") + envNote
|
|
18778
|
+
);
|
|
18779
|
+
return EXIT_OK;
|
|
18780
|
+
}
|
|
18781
|
+
const { wasActive } = removeStored(store, target);
|
|
18782
|
+
const left = storedAccounts(origin, store);
|
|
18783
|
+
const leftLine = left.length ? wasActive ? ` Still stored: ${left.map((a) => a.label).join(", ")}; vos switch <name> to use one.` : ` ${left.find((a) => a.active)?.label ?? "another account"} stays in use.` : "";
|
|
18285
18784
|
r.done(
|
|
18286
18785
|
{
|
|
18287
18786
|
path: CREDENTIALS_PATH,
|
|
18288
|
-
removed:
|
|
18787
|
+
removed: true,
|
|
18788
|
+
account: target.account,
|
|
18789
|
+
wasActive,
|
|
18289
18790
|
envCredential: envKey,
|
|
18290
|
-
|
|
18791
|
+
accounts: left,
|
|
18792
|
+
next_step: left.length && wasActive ? "vos switch <name>" : envStep
|
|
18291
18793
|
},
|
|
18292
|
-
|
|
18794
|
+
`Removed ${accountLabel(target.account)} (${target.origin}).${leftLine}${envNote}`
|
|
18293
18795
|
);
|
|
18294
18796
|
return EXIT_OK;
|
|
18295
18797
|
}
|
|
18296
18798
|
|
|
18297
18799
|
// src/plugin/run.ts
|
|
18298
|
-
var
|
|
18800
|
+
var BOOLEAN_FLAGS16 = /* @__PURE__ */ new Set([
|
|
18299
18801
|
"json",
|
|
18300
18802
|
"help",
|
|
18301
18803
|
"wait",
|
|
@@ -18359,8 +18861,12 @@ Take pipeline
|
|
|
18359
18861
|
vos join <take> <take|file.mp4>... --out <dir> [--keep-edits|--force] [--captions] [--zooms per-beat] [--mute <file>]... [--json]
|
|
18360
18862
|
several takes (and plain video files) as ONE take, cut in argument order: the first is the primary (its frame, cursor, export and sound), each next one a media m1, m2, \u2026 with its footage copied, its spans tagged and renamed, its layers moved to where it now starts; a file opens full-bleed and its own sound plays as an audio clip (--mute <file> leaves it out). --captions lands every step's caption anchored to its step, starting as the step begins (anchor.at "start"), each ending with its clip. --zooms per-beat keeps a beat's zoom on its steps marked "zoom": true (as vos plan --zooms per-beat). The result must pass vos validate before anything is written
|
|
18361
18863
|
--keep-edits joins again over an edited joined take and keeps its edits: inputs are matched to their media by source file (join.json records each input's path and footage hash), a kept input keeps its id and everything on it (segments in their edited order, spans, rejections, anchored layers, its sound), the frame, export, styles and still stay, a new input is joined fresh under a new id (and only it is captioned or re-planned), a re-recorded input (changed footage at its path, or the same script at a new one) keeps its edits re-timed by its steps as vos plan --reuse does, and an input that is gone takes its edits with it, each named. A new input's segments go before the next kept input's; reordering the kept inputs regroups the segments in argument order. The first input must stay the primary. --force replaces the take instead
|
|
18362
|
-
vos
|
|
18363
|
-
the
|
|
18864
|
+
vos music ls [--mood <slug>] [--vocals none|chops|lead] [--loops] [--bpm <lo>-<hi>] [--min-length <s>] [--q <words>] [--json]
|
|
18865
|
+
the library as an agent reads it, one line per track: slug, genre, length, tempo (a ? on an uncertain beat), vocals, loops, the sentence a person wrote. The facts are GET /api/music's
|
|
18866
|
+
vos music pick <take|config.json> [--at <step id|seconds>] [--mood <slug|tag>] [--words "\u2026"] [--voice|--no-voice] [--like <vos id|slug>]... [--top 3] [--json]
|
|
18867
|
+
the beds that fit THIS film, best first, each with its reasons and the vos score line that places it: the film's length, its cuts (captions, joins, page changes, zoom marks), its payoff (--at, else the last step marked "zoom": true, else the last cut) and its voice are read from the document and every track is scored (a swell on the payoff, cuts on the beat, the asked mood or words, calm under a voice, an ending that meets the film's) after the hard rules (covers the film or loops, no quiet intro under frame one, no sung lead under a voice). --json carries every track, the refused with their reason. Ties fall to the take, so two films asking the same thing get different beds
|
|
18868
|
+
vos score <take> --track <slug|file|best> [--at <step id|output seconds>] [--mood <slug|tag>] [--words "\u2026"] [--gain 0..1] [--normalize <lufs|off>] [--fade-in <s>] [--fade-out <s>] [--dry-run] [--json]
|
|
18869
|
+
the film's music as one audio clip (id score): reads the track's loudness, finds its strongest swell and offsets the track so the swell lands at --at (a step, resolved through the cut, or output seconds); without --at it starts where the track first rises above its median level. --track best runs vos music pick and places its first pick, its payoff as --at unless one is given. The clip carries its measured loudness and a target, --normalize (default -16 LUFS), with --gain (default 0.5) a trim on it; --normalize off plays it at --gain alone
|
|
18364
18870
|
vos audio measure <take> [--json]
|
|
18365
18871
|
every audio clip's loudness (BS.1770 integrated LUFS and sample peak, the meter check-video reads a render with), written beside it in doc.json as loudness { lufs, peakDb, at, src }; a clip's normalize (a target in LUFS, -30..-6) plays it at the gain that reaches it, past 1 if need be, capped so its peak stays under -1 dBFS, and only once it is measured for its own key
|
|
18366
18872
|
vos port inventory <page.html|project dir> [--render <their render.mp4>] [--out port] [--json]
|
|
@@ -18394,15 +18900,22 @@ This machine (no account)
|
|
|
18394
18900
|
agent, a credential (present or absent, never printed), and the
|
|
18395
18901
|
dev server when --url names one. Exit 3 when no browser
|
|
18396
18902
|
vos whoami [--json]
|
|
18397
|
-
the key's name
|
|
18398
|
-
|
|
18399
|
-
|
|
18903
|
+
the account in use (its key's name, which rung resolved it) and
|
|
18904
|
+
every other account stored for the origin, never a key
|
|
18905
|
+
vos switch [<handle>] [--json]
|
|
18906
|
+
use another stored account (with two stored, the other one);
|
|
18907
|
+
vos login once per account, approving as it, stores them all
|
|
18908
|
+
vos logout [<handle>] [--all] [--json]
|
|
18909
|
+
forget the account in use, a named one, or every stored
|
|
18910
|
+
credential (VOS_API_KEY still resolves)
|
|
18400
18911
|
|
|
18401
18912
|
Platform (vos.so) \u2014 fetch, edit, push, pull, repeat
|
|
18402
18913
|
vos login [--key <vos_sk_\u2026>] [--handoff <url>] [--label <name>] [--no-browser]
|
|
18403
18914
|
sign in via the browser (approve at vos.so/cli/auth; works
|
|
18404
18915
|
headless \u2014 print the URL, a human approves, the key stores
|
|
18405
18916
|
itself). --key skips the browser (mint at vos.so/app/api).
|
|
18917
|
+
Additive: the person picks the account on the approval page,
|
|
18918
|
+
and every account signed in stays stored (vos switch).
|
|
18406
18919
|
--handoff https://vos.so/h/\u2026 exchanges the setup link a
|
|
18407
18920
|
signed-in person's line carries for a key, once, no click
|
|
18408
18921
|
vos fetch <vosId|watch-url> [--out dir] [--media] [--json]
|
|
@@ -18466,7 +18979,8 @@ Platform (vos.so) \u2014 fetch, edit, push, pull, repeat
|
|
|
18466
18979
|
kept) or the take's doc.json. ALWAYS pull before editing pushed work.
|
|
18467
18980
|
--media also downloads the recording (+ mic/cam sidecars) beside
|
|
18468
18981
|
the doc and re-anchors it, so digest/frames/render run locally
|
|
18469
|
-
auth: --key, VOS_API_KEY, or
|
|
18982
|
+
auth: --key, --account <handle>, VOS_API_KEY, VOS_ACCOUNT, or the
|
|
18983
|
+
stored account in use (~/.config/vos/credentials); keys can
|
|
18470
18984
|
never publish (visibility stays private; humans publish on vos.so)
|
|
18471
18985
|
vos folder list
|
|
18472
18986
|
vos folder create <name> [--parent <folderId|slug>] [--desc <text>]
|
|
@@ -18667,9 +19181,10 @@ doc.json edits arrive intact; a human can drag every zoom span. Keeps
|
|
|
18667
19181
|
serving until Ctrl-C. The studio is https://vos.so by default (VOS_ORIGIN
|
|
18668
19182
|
moves it; --studio http://localhost:6060 for a dev server).
|
|
18669
19183
|
|
|
18670
|
-
push/pull \u2014 the hosted iteration loop (credentials: --key,
|
|
18671
|
-
|
|
18672
|
-
|
|
19184
|
+
push/pull \u2014 the hosted iteration loop (credentials: --key, --account <handle>,
|
|
19185
|
+
VOS_API_KEY, VOS_ACCOUNT, or the account in use at ~/.config/vos/credentials
|
|
19186
|
+
via vos login, one sign-in per account and vos switch between them; origin
|
|
19187
|
+
via VOS_ORIGIN, default https://vos.so). A take push uploads the recording ONCE (content-addressed),
|
|
18673
19188
|
lowers doc.json, and creates a private vos (first push asks; --yes for
|
|
18674
19189
|
headless) or a new version against the base in vos.json \u2014 a stale base
|
|
18675
19190
|
prints the human's typed changelog and exits 1 (run pull, re-apply, push
|
|
@@ -18860,8 +19375,8 @@ function takeBrowserArgs(multi) {
|
|
|
18860
19375
|
function takeStorageState(flags) {
|
|
18861
19376
|
const raw = strFlag(flags, "storage-state");
|
|
18862
19377
|
if (!raw) return void 0;
|
|
18863
|
-
const path =
|
|
18864
|
-
if (!
|
|
19378
|
+
const path = resolve22(raw);
|
|
19379
|
+
if (!existsSync31(path))
|
|
18865
19380
|
throw new UsageError(`--storage-state: no such file: ${path}`);
|
|
18866
19381
|
return path;
|
|
18867
19382
|
}
|
|
@@ -18874,7 +19389,7 @@ function takeSessionName(flags, storageState) {
|
|
|
18874
19389
|
throw new UsageError(
|
|
18875
19390
|
"--session and --storage-state are two doors to one take: a persistent profile cannot take a storage state. Pass one"
|
|
18876
19391
|
);
|
|
18877
|
-
if (!
|
|
19392
|
+
if (!existsSync31(sessionDir(name)))
|
|
18878
19393
|
throw new UsageError(
|
|
18879
19394
|
`no session "${name}". Make one: vos session open <url> --name ${name} (a Chrome window opens; sign in and close it)`
|
|
18880
19395
|
);
|
|
@@ -18892,14 +19407,14 @@ async function inSession(name, actions, fn) {
|
|
|
18892
19407
|
}
|
|
18893
19408
|
function reRecord(outDir, flags, r) {
|
|
18894
19409
|
const wantsReuse = flags.reuse === true;
|
|
18895
|
-
if (wantsReuse && !
|
|
19410
|
+
if (wantsReuse && !existsSync31(join33(outDir, "doc.json")))
|
|
18896
19411
|
throw new UsageError(
|
|
18897
19412
|
`--reuse: ${outDir} has no cut to keep (no doc.json); record without --reuse`
|
|
18898
19413
|
);
|
|
18899
19414
|
let previousCut = null;
|
|
18900
19415
|
return {
|
|
18901
19416
|
prepare: async () => {
|
|
18902
|
-
if (
|
|
19417
|
+
if (existsSync31(join33(outDir, "meta.json"))) {
|
|
18903
19418
|
const { prevDoc, kept } = await prepareReRecord(outDir);
|
|
18904
19419
|
if (prevDoc) previousCut = join33(outDir, PREV_DOC_NAME);
|
|
18905
19420
|
r.log(
|
|
@@ -18987,7 +19502,7 @@ function wallGate(flags, r, opts) {
|
|
|
18987
19502
|
async function cmdRecord(argv) {
|
|
18988
19503
|
const { positionals, flags, multi } = parseArgs(
|
|
18989
19504
|
argv,
|
|
18990
|
-
|
|
19505
|
+
BOOLEAN_FLAGS16,
|
|
18991
19506
|
MULTI_FLAGS2
|
|
18992
19507
|
);
|
|
18993
19508
|
const actionsPath = strFlag(flags, "actions") ?? positionals[0];
|
|
@@ -19003,7 +19518,7 @@ async function cmdRecord(argv) {
|
|
|
19003
19518
|
const scheme = urlSchemeProblem2(url);
|
|
19004
19519
|
if (scheme) throw new UsageError(scheme);
|
|
19005
19520
|
announceEnvNames(actions, r);
|
|
19006
|
-
const outDir =
|
|
19521
|
+
const outDir = resolve22(strFlag(flags, "out") ?? "take");
|
|
19007
19522
|
const storageState = takeStorageState(flags);
|
|
19008
19523
|
const sessionName = takeSessionName(flags, storageState);
|
|
19009
19524
|
const browserArgs = takeBrowserArgs(multi);
|
|
@@ -19023,7 +19538,7 @@ async function cmdRecord(argv) {
|
|
|
19023
19538
|
);
|
|
19024
19539
|
const hostedActions = await scriptForHost(
|
|
19025
19540
|
actions,
|
|
19026
|
-
dirname12(
|
|
19541
|
+
dirname12(resolve22(actionsPath))
|
|
19027
19542
|
).catch((e) => {
|
|
19028
19543
|
throw new UsageError(e instanceof Error ? e.message : String(e));
|
|
19029
19544
|
});
|
|
@@ -19133,7 +19648,7 @@ async function cmdRecord(argv) {
|
|
|
19133
19648
|
sessionName,
|
|
19134
19649
|
actions,
|
|
19135
19650
|
(context2) => recordTake(browser2, url, actions, takePaths(outDir), r.log, {
|
|
19136
|
-
actionsDir: dirname12(
|
|
19651
|
+
actionsDir: dirname12(resolve22(actionsPath)),
|
|
19137
19652
|
storageState,
|
|
19138
19653
|
headers,
|
|
19139
19654
|
context: context2,
|
|
@@ -19199,7 +19714,7 @@ async function cmdRecord(argv) {
|
|
|
19199
19714
|
...flags["allow-wall"] === true ? ["--allow-wall"] : [],
|
|
19200
19715
|
...confirm.map((c) => `--confirm ${c}`),
|
|
19201
19716
|
// A take that already has a cut keeps it on the new footage.
|
|
19202
|
-
...
|
|
19717
|
+
...existsSync31(join33(outDir, "doc.json")) ? ["--reuse"] : []
|
|
19203
19718
|
].join(" ");
|
|
19204
19719
|
const nextOut = strFlag(flags, "out") ?? "take";
|
|
19205
19720
|
const guardNote = !unconfirmed.ok ? unconfirmed.unconfirmed.length ? ` (it refuses until you add ${unconfirmed.unconfirmed.map((id) => `--confirm ${id}`).join(" ")}: ${unconfirmed.unconfirmed.length === 1 ? "that step spends" : "those steps spend"} something real)` : ` (${unconfirmed.unknown.map((c) => `--confirm ${c}`).join(", ")} names no guarded step)` : "";
|
|
@@ -19241,7 +19756,7 @@ ${lines.join("\n")}
|
|
|
19241
19756
|
sessionName,
|
|
19242
19757
|
actions,
|
|
19243
19758
|
(context2) => recordTake(browser, url, actions, paths, r.log, {
|
|
19244
|
-
actionsDir: dirname12(
|
|
19759
|
+
actionsDir: dirname12(resolve22(actionsPath)),
|
|
19245
19760
|
maxDurationSeconds,
|
|
19246
19761
|
storageState,
|
|
19247
19762
|
headers,
|
|
@@ -19339,7 +19854,7 @@ ${lines.join("\n")}
|
|
|
19339
19854
|
async function cmdCreate2(argv) {
|
|
19340
19855
|
const { positionals, flags, multi } = parseArgs(
|
|
19341
19856
|
argv,
|
|
19342
|
-
|
|
19857
|
+
BOOLEAN_FLAGS16,
|
|
19343
19858
|
MULTI_FLAGS2
|
|
19344
19859
|
);
|
|
19345
19860
|
const actionsPath = strFlag(flags, "actions");
|
|
@@ -19356,7 +19871,7 @@ async function cmdCreate2(argv) {
|
|
|
19356
19871
|
const scheme = urlSchemeProblem2(url);
|
|
19357
19872
|
if (scheme) throw new UsageError(scheme);
|
|
19358
19873
|
announceEnvNames(actions, r);
|
|
19359
|
-
const outDir =
|
|
19874
|
+
const outDir = resolve22(strFlag(flags, "out") ?? "take");
|
|
19360
19875
|
const format = videoFormat(strFlag(flags, "format"), positionals[0]);
|
|
19361
19876
|
const out = positionals[0] ?? join33(outDir, `out.${format}`);
|
|
19362
19877
|
const parallel = numFlag(flags, "parallel", 1);
|
|
@@ -19380,7 +19895,7 @@ async function cmdCreate2(argv) {
|
|
|
19380
19895
|
sessionName,
|
|
19381
19896
|
actions,
|
|
19382
19897
|
(context2) => recordTake(browser, url, actions, paths, r.log, {
|
|
19383
|
-
actionsDir: dirname12(
|
|
19898
|
+
actionsDir: dirname12(resolve22(actionsPath)),
|
|
19384
19899
|
maxDurationSeconds,
|
|
19385
19900
|
storageState,
|
|
19386
19901
|
headers,
|
|
@@ -19497,7 +20012,7 @@ async function cmdPlan(argvIn) {
|
|
|
19497
20012
|
const argv = bareCaptionsFlag(argvIn);
|
|
19498
20013
|
const { positionals, flags, multi } = parseArgs(
|
|
19499
20014
|
argv,
|
|
19500
|
-
|
|
20015
|
+
BOOLEAN_FLAGS16,
|
|
19501
20016
|
/* @__PURE__ */ new Set(["with"])
|
|
19502
20017
|
);
|
|
19503
20018
|
const dir = positionals[0];
|
|
@@ -19512,8 +20027,8 @@ async function cmdPlan(argvIn) {
|
|
|
19512
20027
|
}
|
|
19513
20028
|
let reuse;
|
|
19514
20029
|
if (flags.reuse === true) {
|
|
19515
|
-
const from =
|
|
19516
|
-
if (!
|
|
20030
|
+
const from = resolve22(strFlag(flags, "from") ?? join33(dir, PREV_DOC_NAME));
|
|
20031
|
+
if (!existsSync31(from)) {
|
|
19517
20032
|
throw new UsageError(
|
|
19518
20033
|
`--reuse: ${from} does not exist \u2014 a re-record into this take writes doc.prev.json, or pass --from <doc.json>`
|
|
19519
20034
|
);
|
|
@@ -19524,7 +20039,7 @@ async function cmdPlan(argvIn) {
|
|
|
19524
20039
|
};
|
|
19525
20040
|
}
|
|
19526
20041
|
const style = await resolveStyleRef(flags);
|
|
19527
|
-
const hasDoc =
|
|
20042
|
+
const hasDoc = existsSync31(join33(dir, "doc.json"));
|
|
19528
20043
|
const backdrop = hasDoc ? null : await takeBackdrop(flags, r);
|
|
19529
20044
|
const release = await releaseInputs(dir, flags, r, multi.with ?? []);
|
|
19530
20045
|
const stepCaptions = strFlag(flags, "captions") === "steps";
|
|
@@ -19604,7 +20119,7 @@ async function cmdPlan(argvIn) {
|
|
|
19604
20119
|
${s.reuse.flagged.join("\n ")}` : "") : "";
|
|
19605
20120
|
r.done(
|
|
19606
20121
|
{
|
|
19607
|
-
take:
|
|
20122
|
+
take: resolve22(dir),
|
|
19608
20123
|
fresh: s.fresh,
|
|
19609
20124
|
cursorKept: s.cursorKept,
|
|
19610
20125
|
zoomAuto,
|
|
@@ -19733,7 +20248,7 @@ async function releaseInputs(dir, flags, r, withRefs = []) {
|
|
|
19733
20248
|
async function cmdRender(argv) {
|
|
19734
20249
|
const { positionals, flags, multi } = parseArgs(
|
|
19735
20250
|
argv,
|
|
19736
|
-
|
|
20251
|
+
BOOLEAN_FLAGS16,
|
|
19737
20252
|
MULTI_FLAGS2
|
|
19738
20253
|
);
|
|
19739
20254
|
const dir = positionals[0];
|
|
@@ -19801,7 +20316,7 @@ async function cmdRender(argv) {
|
|
|
19801
20316
|
async function cmdFrames(argv) {
|
|
19802
20317
|
const { positionals, flags, multi } = parseArgs(
|
|
19803
20318
|
argv,
|
|
19804
|
-
|
|
20319
|
+
BOOLEAN_FLAGS16,
|
|
19805
20320
|
MULTI_FLAGS2
|
|
19806
20321
|
);
|
|
19807
20322
|
const dir = positionals[0];
|
|
@@ -19884,7 +20399,7 @@ async function cmdFrames(argv) {
|
|
|
19884
20399
|
async function cmdDeliver(argv) {
|
|
19885
20400
|
const { positionals, flags, multi } = parseArgs(
|
|
19886
20401
|
argv,
|
|
19887
|
-
|
|
20402
|
+
BOOLEAN_FLAGS16,
|
|
19888
20403
|
MULTI_FLAGS2
|
|
19889
20404
|
);
|
|
19890
20405
|
const dir = positionals[0];
|
|
@@ -19984,11 +20499,11 @@ async function resolveStyleRef(flags) {
|
|
|
19984
20499
|
}
|
|
19985
20500
|
async function resolveDocRef(ref, flags, what) {
|
|
19986
20501
|
const styleRef = ref;
|
|
19987
|
-
const file =
|
|
20502
|
+
const file = existsSync31(styleRef) ? resolve22(
|
|
19988
20503
|
styleRef,
|
|
19989
|
-
|
|
20504
|
+
existsSync31(join33(styleRef, "doc.json")) ? "doc.json" : ""
|
|
19990
20505
|
) : null;
|
|
19991
|
-
if (file &&
|
|
20506
|
+
if (file && existsSync31(file)) {
|
|
19992
20507
|
return {
|
|
19993
20508
|
from: file,
|
|
19994
20509
|
doc: migrateHostedDoc4(
|
|
@@ -20034,7 +20549,7 @@ async function officialTemplate(origin, ref) {
|
|
|
20034
20549
|
}
|
|
20035
20550
|
}
|
|
20036
20551
|
async function cmdDigest(argv) {
|
|
20037
|
-
const { positionals, flags } = parseArgs(argv,
|
|
20552
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS16);
|
|
20038
20553
|
const dir = positionals[0];
|
|
20039
20554
|
if (!dir)
|
|
20040
20555
|
throw new UsageError(
|
|
@@ -20098,19 +20613,19 @@ async function cmdDigest(argv) {
|
|
|
20098
20613
|
}
|
|
20099
20614
|
}
|
|
20100
20615
|
async function cmdOpen(argv) {
|
|
20101
|
-
const { positionals, flags } = parseArgs(argv,
|
|
20616
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS16);
|
|
20102
20617
|
const dir = positionals[0];
|
|
20103
20618
|
if (!dir) throw new UsageError("vos open <take> [--studio <url>]");
|
|
20104
20619
|
const r = createReporter(flags.json === true);
|
|
20105
20620
|
const take = await loadTake(dir);
|
|
20106
|
-
if (!
|
|
20621
|
+
if (!existsSync31(take.paths.recording)) {
|
|
20107
20622
|
throw new UsageError(`${dir} has no recording \u2014 re-run record`);
|
|
20108
20623
|
}
|
|
20109
20624
|
const studio = (strFlag(flags, "studio") ?? platformOrigin()).replace(
|
|
20110
20625
|
/\/+$/,
|
|
20111
20626
|
""
|
|
20112
20627
|
);
|
|
20113
|
-
const server = await startTakeServer(
|
|
20628
|
+
const server = await startTakeServer(resolve22(dir), {});
|
|
20114
20629
|
const url = `${studio}/studio?take=${encodeURIComponent(server.base)}`;
|
|
20115
20630
|
r.event({ event: "open", server: server.base, url });
|
|
20116
20631
|
r.log(`take served at ${server.base}`);
|
|
@@ -20133,7 +20648,7 @@ async function cmdOpen(argv) {
|
|
|
20133
20648
|
return EXIT_OK;
|
|
20134
20649
|
}
|
|
20135
20650
|
async function cmdCallout(argv) {
|
|
20136
|
-
const { positionals, flags } = parseArgs(argv,
|
|
20651
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS16);
|
|
20137
20652
|
const dir = positionals[0];
|
|
20138
20653
|
const shape = positionals[1];
|
|
20139
20654
|
if (!dir || !shape || !isCalloutShape(shape))
|
|
@@ -20232,11 +20747,11 @@ async function cmdCallout(argv) {
|
|
|
20232
20747
|
return EXIT_OK;
|
|
20233
20748
|
}
|
|
20234
20749
|
async function cmdValidate(argv) {
|
|
20235
|
-
const { positionals, flags } = parseArgs(argv,
|
|
20750
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS16);
|
|
20236
20751
|
const target = positionals[0];
|
|
20237
20752
|
if (!target) throw new UsageError("vos validate <actions.json|take>");
|
|
20238
20753
|
const r = createReporter(flags.json === true);
|
|
20239
|
-
const kitTarget = target.endsWith("kit.json") ? target :
|
|
20754
|
+
const kitTarget = target.endsWith("kit.json") ? target : existsSync31(join33(target, "kit.json")) && !isTakeDir(target) ? join33(target, "kit.json") : null;
|
|
20240
20755
|
if (kitTarget) {
|
|
20241
20756
|
const picture = flags.picture === true;
|
|
20242
20757
|
const verdict = await validateKit(kitTarget, { picture });
|
|
@@ -20268,7 +20783,7 @@ async function cmdValidate(argv) {
|
|
|
20268
20783
|
r.done({ valid: true, target }, `${target}: valid actions file`);
|
|
20269
20784
|
return EXIT_OK;
|
|
20270
20785
|
}
|
|
20271
|
-
if (!isTakeDir(target) &&
|
|
20786
|
+
if (!isTakeDir(target) && existsSync31(join33(target, "config.json"))) {
|
|
20272
20787
|
const parsed = JSON.parse(
|
|
20273
20788
|
await readFile19(join33(target, "config.json"), "utf8")
|
|
20274
20789
|
);
|
|
@@ -20312,7 +20827,7 @@ async function cmdValidate(argv) {
|
|
|
20312
20827
|
const problems = [];
|
|
20313
20828
|
const warnings = [];
|
|
20314
20829
|
const notes = [];
|
|
20315
|
-
if (!
|
|
20830
|
+
if (!existsSync31(take.paths.recording)) {
|
|
20316
20831
|
problems.push("missing recording (re-run record)");
|
|
20317
20832
|
} else {
|
|
20318
20833
|
const mismatch = containerMismatch(
|
|
@@ -20353,7 +20868,7 @@ async function cmdValidate(argv) {
|
|
|
20353
20868
|
const found = localFile(rel, target);
|
|
20354
20869
|
if (!("refused" in found)) continue;
|
|
20355
20870
|
problems.push(
|
|
20356
|
-
|
|
20871
|
+
existsSync31(resolve22(target, rel)) ? `doc.json: ${ref.where}: ${ref.key} ${found.refused}` : `doc.json: ${ref.where}: ${ref.key} is not a file in the take, so a render plays the film without it (put the file there, or fix the key)`
|
|
20357
20872
|
);
|
|
20358
20873
|
}
|
|
20359
20874
|
if (flags.picture === true && (take.doc.overlays ?? []).some((o) => o.kind === "html")) {
|
|
@@ -20422,7 +20937,7 @@ async function cmdValidate(argv) {
|
|
|
20422
20937
|
async function cmdPush3(argv) {
|
|
20423
20938
|
const { positionals, flags, multi } = parseArgs(
|
|
20424
20939
|
argv,
|
|
20425
|
-
|
|
20940
|
+
BOOLEAN_FLAGS16,
|
|
20426
20941
|
MULTI_FLAGS2
|
|
20427
20942
|
);
|
|
20428
20943
|
const dir = positionals[0];
|
|
@@ -20432,7 +20947,7 @@ async function cmdPush3(argv) {
|
|
|
20432
20947
|
);
|
|
20433
20948
|
const refusal = takePushRefusal({
|
|
20434
20949
|
vos: strFlag(flags, "vos"),
|
|
20435
|
-
trackedVosId: readSyncState(
|
|
20950
|
+
trackedVosId: readSyncState(resolve22(dir))?.vosId ?? null,
|
|
20436
20951
|
programOnly: ["slug", "tags", "base", "remix-of", "still"].filter(
|
|
20437
20952
|
(name) => hasFlag(flags, name)
|
|
20438
20953
|
)
|
|
@@ -20451,7 +20966,7 @@ async function cmdPush3(argv) {
|
|
|
20451
20966
|
`--claimable creates a NEW claimable vos; ${iterating.map((f) => `--${f}`).join(", ")} ${iterating.length > 1 ? "apply" : "applies"} to a keyed push`
|
|
20452
20967
|
);
|
|
20453
20968
|
const claim = await pushTakeClaimable(
|
|
20454
|
-
|
|
20969
|
+
resolve22(dir),
|
|
20455
20970
|
{
|
|
20456
20971
|
api: strFlag(flags, "api"),
|
|
20457
20972
|
origin: strFlag(flags, "origin"),
|
|
@@ -20475,7 +20990,7 @@ reference and the only credential.`
|
|
|
20475
20990
|
}
|
|
20476
20991
|
const overrides = multi.override;
|
|
20477
20992
|
const result = await pushTake(
|
|
20478
|
-
|
|
20993
|
+
resolve22(dir),
|
|
20479
20994
|
{
|
|
20480
20995
|
key: strFlag(flags, "key"),
|
|
20481
20996
|
api: strFlag(flags, "api"),
|
|
@@ -20499,7 +21014,7 @@ reference and the only credential.`
|
|
|
20499
21014
|
}).replace(/\/+$/, "");
|
|
20500
21015
|
const landed = flags.wait === true ? await waitForLanded({
|
|
20501
21016
|
origin: pushedTo,
|
|
20502
|
-
key: requireCredential(
|
|
21017
|
+
key: requireCredential(credentialFlags(flags)),
|
|
20503
21018
|
vosId: result.vosId,
|
|
20504
21019
|
versionId: result.versionId ?? null,
|
|
20505
21020
|
log: (l) => r.log(l)
|
|
@@ -20527,11 +21042,11 @@ ${landedLines(landed)}` : "")
|
|
|
20527
21042
|
return EXIT_OK;
|
|
20528
21043
|
}
|
|
20529
21044
|
async function cmdPull2(argv) {
|
|
20530
|
-
const { positionals, flags } = parseArgs(argv,
|
|
21045
|
+
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS16, MULTI_FLAGS2);
|
|
20531
21046
|
const dir = positionals[0] ?? ".";
|
|
20532
21047
|
const r = createReporter(flags.json === true);
|
|
20533
21048
|
const result = await pullTake(
|
|
20534
|
-
|
|
21049
|
+
resolve22(dir),
|
|
20535
21050
|
{
|
|
20536
21051
|
key: strFlag(flags, "key"),
|
|
20537
21052
|
api: strFlag(flags, "api"),
|
|
@@ -20620,6 +21135,8 @@ async function run(argv) {
|
|
|
20620
21135
|
return await cmdWhoami(rest);
|
|
20621
21136
|
case "logout":
|
|
20622
21137
|
return cmdLogout(rest);
|
|
21138
|
+
case "switch":
|
|
21139
|
+
return cmdSwitch(rest);
|
|
20623
21140
|
case "push": {
|
|
20624
21141
|
const target = rest.find((a) => !a.startsWith("-"));
|
|
20625
21142
|
if (target && isTakeDir(target)) return await cmdPush3(rest);
|
|
@@ -20666,6 +21183,8 @@ async function run(argv) {
|
|
|
20666
21183
|
return await cmdScore(rest);
|
|
20667
21184
|
case "audio":
|
|
20668
21185
|
return await cmdAudio(rest);
|
|
21186
|
+
case "music":
|
|
21187
|
+
return await cmdMusic(rest);
|
|
20669
21188
|
case "look":
|
|
20670
21189
|
return await cmdLook(rest);
|
|
20671
21190
|
default:
|
|
@@ -20708,7 +21227,7 @@ function verdictExit(v, strict, none) {
|
|
|
20708
21227
|
async function cmdSession(argv) {
|
|
20709
21228
|
const { positionals, flags } = parseArgs(
|
|
20710
21229
|
argv,
|
|
20711
|
-
/* @__PURE__ */ new Set([...
|
|
21230
|
+
/* @__PURE__ */ new Set([...BOOLEAN_FLAGS16, "headed"])
|
|
20712
21231
|
);
|
|
20713
21232
|
const [sub, arg] = positionals;
|
|
20714
21233
|
const r = createReporter(flags.json === true);
|
|
@@ -20753,7 +21272,7 @@ async function cmdSession(argv) {
|
|
|
20753
21272
|
if (!arg) throw new UsageError(usage);
|
|
20754
21273
|
const bad = sessionNameVerdict(arg);
|
|
20755
21274
|
if (bad) throw new UsageError(bad);
|
|
20756
|
-
if (!
|
|
21275
|
+
if (!existsSync31(sessionDir(arg)))
|
|
20757
21276
|
throw new UsageError(`no session "${arg}" (vos session list)`);
|
|
20758
21277
|
const summary3 = await summarizeSession(arg);
|
|
20759
21278
|
const url = strFlag(flags, "url");
|
|
@@ -20787,7 +21306,7 @@ async function cmdSession(argv) {
|
|
|
20787
21306
|
if (!arg || !scriptPath) throw new UsageError(usage);
|
|
20788
21307
|
const bad = sessionNameVerdict(arg);
|
|
20789
21308
|
if (bad) throw new UsageError(bad);
|
|
20790
|
-
if (!
|
|
21309
|
+
if (!existsSync31(sessionDir(arg)))
|
|
20791
21310
|
throw new UsageError(`no session "${arg}" (vos session list)`);
|
|
20792
21311
|
const url = strFlag(flags, "url");
|
|
20793
21312
|
if (url && !/^https?:\/\//.test(url))
|
|
@@ -20880,4 +21399,4 @@ export {
|
|
|
20880
21399
|
verbHelp,
|
|
20881
21400
|
run
|
|
20882
21401
|
};
|
|
20883
|
-
//# sourceMappingURL=chunk-
|
|
21402
|
+
//# sourceMappingURL=chunk-ZXFO32KW.js.map
|