@vosjs/cli 0.75.1 → 0.77.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 +3 -3
- package/dist/{assetManifest-LOPDTP47.js → assetManifest-MQ7HO7RZ.js} +3 -3
- package/dist/{chunk-FL3E27WE.js → chunk-B4U4URE3.js} +52 -7
- package/dist/chunk-B4U4URE3.js.map +1 -0
- package/dist/{chunk-YZAM4W7B.js → chunk-KDIRW72G.js} +2 -2
- package/dist/{chunk-X6NQNBDF.js → chunk-SB622PZM.js} +302 -70
- package/dist/chunk-SB622PZM.js.map +1 -0
- package/dist/{chunk-M3QIN457.js → chunk-UY2N42P2.js} +23 -16
- package/dist/chunk-UY2N42P2.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/index.js +4 -4
- package/dist/{run-XZ2UPHMO.js → run-2TY7KEKT.js} +5 -5
- package/package.json +4 -4
- package/schema/doc.schema.json +1 -1
- package/dist/chunk-FL3E27WE.js.map +0 -1
- package/dist/chunk-M3QIN457.js.map +0 -1
- package/dist/chunk-X6NQNBDF.js.map +0 -1
- /package/dist/{assetManifest-LOPDTP47.js.map → assetManifest-MQ7HO7RZ.js.map} +0 -0
- /package/dist/{chunk-YZAM4W7B.js.map → chunk-KDIRW72G.js.map} +0 -0
- /package/dist/{run-XZ2UPHMO.js.map → run-2TY7KEKT.js.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
reencodeStill,
|
|
10
10
|
renderStill,
|
|
11
11
|
videoFormat
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KDIRW72G.js";
|
|
13
13
|
import {
|
|
14
14
|
PREV_DOC_NAME,
|
|
15
15
|
RECORDING_NAME,
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
readJson,
|
|
29
29
|
readMediaHead,
|
|
30
30
|
recordHostedMedia,
|
|
31
|
+
safePathName,
|
|
31
32
|
sourceSidecarRefs,
|
|
32
33
|
takeMediaFile,
|
|
33
34
|
takePaths,
|
|
@@ -36,7 +37,7 @@ import {
|
|
|
36
37
|
uploadDocRefs,
|
|
37
38
|
uploadManifest,
|
|
38
39
|
writeJson
|
|
39
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-UY2N42P2.js";
|
|
40
41
|
import {
|
|
41
42
|
CREDENTIALS_PATH,
|
|
42
43
|
MEDIA_HEAD_BYTES,
|
|
@@ -68,8 +69,9 @@ import {
|
|
|
68
69
|
sniffMediaType,
|
|
69
70
|
strFlag,
|
|
70
71
|
writeCredential,
|
|
72
|
+
writeFileSafe,
|
|
71
73
|
writeSyncState
|
|
72
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-B4U4URE3.js";
|
|
73
75
|
import {
|
|
74
76
|
deadLine,
|
|
75
77
|
deadWarns
|
|
@@ -366,10 +368,13 @@ var EPS = 1e-3;
|
|
|
366
368
|
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
367
369
|
var isObj = (v) => typeof v === "object" && v !== null;
|
|
368
370
|
function htmlFontUrlProblem(url) {
|
|
369
|
-
if (/^https
|
|
371
|
+
if (/^https:\/\/assets\.vos\.so\//.test(url)) return null;
|
|
370
372
|
if (/^\/api\/assets\/[^/]+\/file$/.test(url)) return null;
|
|
373
|
+
if (/^https?:\/\//i.test(url)) {
|
|
374
|
+
return `names ${url}: a face is fetched from https://assets.vos.so (the host a layer's images are held to), a hosted file (/api/assets/<id>/file) or a .woff2 beside the document, never another host`;
|
|
375
|
+
}
|
|
371
376
|
if (/^(data:|blob:)/.test(url) || url.startsWith("/")) {
|
|
372
|
-
return `must be an https URL, a hosted file (/api/assets/<id>/file) or a .woff2 beside the document (got ${url})`;
|
|
377
|
+
return `must be an https://assets.vos.so URL, a hosted file (/api/assets/<id>/file) or a .woff2 beside the document (got ${url})`;
|
|
373
378
|
}
|
|
374
379
|
if (url.split(/[\\/]/).includes("..")) {
|
|
375
380
|
return `names ${url}, outside the document's directory: copy the font beside doc.json`;
|
|
@@ -6205,7 +6210,7 @@ async function writeScriptBeside(dir, doc) {
|
|
|
6205
6210
|
}
|
|
6206
6211
|
|
|
6207
6212
|
// src/plugin/folder.ts
|
|
6208
|
-
import { mkdir as mkdir5
|
|
6213
|
+
import { mkdir as mkdir5 } from "fs/promises";
|
|
6209
6214
|
import { join as join12 } from "path";
|
|
6210
6215
|
import { recipeHints } from "@vosjs/shared/frontmatter";
|
|
6211
6216
|
import { migrateHostedDoc } from "@vosjs/studio-core";
|
|
@@ -6394,7 +6399,6 @@ function recipeLine(filename, body) {
|
|
|
6394
6399
|
].filter(Boolean);
|
|
6395
6400
|
return `${filename}${facts.length ? ` (${facts.join(" \xB7 ")})` : ""}`;
|
|
6396
6401
|
}
|
|
6397
|
-
var safeName = (v) => v.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) || "file";
|
|
6398
6402
|
async function cmdPull(argv) {
|
|
6399
6403
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS);
|
|
6400
6404
|
const ref = positionals[0];
|
|
@@ -6413,26 +6417,27 @@ async function cmdPull(argv) {
|
|
|
6413
6417
|
if (res.status !== 200)
|
|
6414
6418
|
throw new Error(apiError(`pull folder ${folder.slug}`, res));
|
|
6415
6419
|
const payload = res.body;
|
|
6416
|
-
const
|
|
6420
|
+
const safeName = (v, id) => safePathName((v ?? "").toLowerCase(), id);
|
|
6421
|
+
const out = strFlag(flags, "out") ?? safeName(folder.slug, folder.id);
|
|
6417
6422
|
await mkdir5(join12(out, "recipes"), { recursive: true });
|
|
6418
6423
|
const lines = [];
|
|
6419
6424
|
const recipes = [];
|
|
6420
6425
|
for (const rec of payload.recipes) {
|
|
6421
|
-
const path = join12(out, "recipes", safeName(rec.filename));
|
|
6422
|
-
await
|
|
6426
|
+
const path = join12(out, "recipes", safeName(rec.filename, rec.id));
|
|
6427
|
+
await writeFileSafe(path, rec.body ?? "");
|
|
6423
6428
|
recipes.push({ path, line: recipeLine(rec.filename, rec.body ?? "") });
|
|
6424
6429
|
}
|
|
6425
6430
|
for (const rec of payload.inheritedRecipes) {
|
|
6426
|
-
const from = safeName(rec.folderSlug ?? "inherited");
|
|
6431
|
+
const from = safeName(rec.folderSlug ?? "inherited", "inherited");
|
|
6427
6432
|
await mkdir5(join12(out, "recipes", "_inherited", from), { recursive: true });
|
|
6428
6433
|
const path = join12(
|
|
6429
6434
|
out,
|
|
6430
6435
|
"recipes",
|
|
6431
6436
|
"_inherited",
|
|
6432
6437
|
from,
|
|
6433
|
-
safeName(rec.filename)
|
|
6438
|
+
safeName(rec.filename, rec.id)
|
|
6434
6439
|
);
|
|
6435
|
-
await
|
|
6440
|
+
await writeFileSafe(path, rec.body ?? "");
|
|
6436
6441
|
recipes.push({
|
|
6437
6442
|
path,
|
|
6438
6443
|
line: `${recipeLine(rec.filename, rec.body ?? "")} [inherited from ${rec.folderName ?? from}]`
|
|
@@ -6440,14 +6445,14 @@ async function cmdPull(argv) {
|
|
|
6440
6445
|
}
|
|
6441
6446
|
const members = [];
|
|
6442
6447
|
for (const v of payload.voses) {
|
|
6443
|
-
const dir = join12(out, "members", safeName(v.slug || v.title
|
|
6448
|
+
const dir = join12(out, "members", safeName(v.slug || v.title, v.id));
|
|
6444
6449
|
await mkdir5(dir, { recursive: true });
|
|
6445
6450
|
const cfg = await apiJson(origin, `/api/vos/${v.id}/config`, { key });
|
|
6446
6451
|
if (cfg.status !== 200) {
|
|
6447
6452
|
lines.push(`skipped ${v.title}: ${apiError("fetch config", cfg)}`);
|
|
6448
6453
|
continue;
|
|
6449
6454
|
}
|
|
6450
|
-
await
|
|
6455
|
+
await writeFileSafe(
|
|
6451
6456
|
join12(dir, "config.json"),
|
|
6452
6457
|
JSON.stringify(cfg.body.config, null, 2)
|
|
6453
6458
|
);
|
|
@@ -6459,7 +6464,7 @@ async function cmdPull(argv) {
|
|
|
6459
6464
|
{ key }
|
|
6460
6465
|
);
|
|
6461
6466
|
if (doc.status === 200) {
|
|
6462
|
-
await
|
|
6467
|
+
await writeFileSafe(
|
|
6463
6468
|
join12(dir, "doc.json"),
|
|
6464
6469
|
JSON.stringify(doc.body, null, 2)
|
|
6465
6470
|
);
|
|
@@ -6991,7 +6996,7 @@ async function pushTakeClaimable(dir, flags, r) {
|
|
|
6991
6996
|
|
|
6992
6997
|
// src/plugin/program.ts
|
|
6993
6998
|
import { existsSync as existsSync13 } from "fs";
|
|
6994
|
-
import { mkdir as mkdir6, readFile as readFile11
|
|
6999
|
+
import { mkdir as mkdir6, readFile as readFile11 } from "fs/promises";
|
|
6995
7000
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
6996
7001
|
import { basename as basename3, dirname as dirname2, join as join14 } from "path";
|
|
6997
7002
|
import {
|
|
@@ -7209,9 +7214,9 @@ async function cmdFetch(argv) {
|
|
|
7209
7214
|
if (cfg.status !== 200)
|
|
7210
7215
|
throw new Error(apiError(`fetch config for ${vosId}`, cfg));
|
|
7211
7216
|
const slug = typeof vosMeta.slug === "string" && vosMeta.slug ? vosMeta.slug : vosId;
|
|
7212
|
-
const out = strFlag(flags, "out") ?? slug;
|
|
7217
|
+
const out = strFlag(flags, "out") ?? safePathName(slug, vosId);
|
|
7213
7218
|
await mkdir6(out, { recursive: true });
|
|
7214
|
-
await
|
|
7219
|
+
await writeFileSafe(
|
|
7215
7220
|
join14(out, "config.json"),
|
|
7216
7221
|
JSON.stringify(cfg.body.config, null, 2)
|
|
7217
7222
|
);
|
|
@@ -7237,12 +7242,18 @@ async function cmdFetch(argv) {
|
|
|
7237
7242
|
const hosted = migrateHostedDoc3(doc.body);
|
|
7238
7243
|
const { config: own } = await writeProgramDoc(out, hosted);
|
|
7239
7244
|
if (own) {
|
|
7240
|
-
await
|
|
7245
|
+
await writeFileSafe(
|
|
7246
|
+
join14(out, "config.json"),
|
|
7247
|
+
JSON.stringify(own, null, 2)
|
|
7248
|
+
);
|
|
7241
7249
|
}
|
|
7242
7250
|
} else if (doc.status === 200) {
|
|
7243
7251
|
take = true;
|
|
7244
7252
|
const hosted = migrateHostedDoc3(doc.body);
|
|
7245
|
-
await
|
|
7253
|
+
await writeFileSafe(
|
|
7254
|
+
join14(out, "doc.json"),
|
|
7255
|
+
JSON.stringify(hosted, null, 2)
|
|
7256
|
+
);
|
|
7246
7257
|
if (flags.media === true) {
|
|
7247
7258
|
const media = await pullMedia({ origin, key }, out, hosted, r.log);
|
|
7248
7259
|
await recordHostedMedia(out, vosId, media);
|
|
@@ -7263,7 +7274,7 @@ async function cmdFetch(argv) {
|
|
|
7263
7274
|
if (hostedCount && flags.media === true) {
|
|
7264
7275
|
const pulled = await pullManifest({ origin, key }, out, written, r.log);
|
|
7265
7276
|
if (pulled) {
|
|
7266
|
-
await
|
|
7277
|
+
await writeFileSafe(
|
|
7267
7278
|
configPath,
|
|
7268
7279
|
JSON.stringify({ ...written, assets: pulled.assets }, null, 2)
|
|
7269
7280
|
);
|
|
@@ -7737,7 +7748,10 @@ async function cmdPullProgram(argv) {
|
|
|
7737
7748
|
const configPath = join14(dir, "config.json");
|
|
7738
7749
|
let backedUp = false;
|
|
7739
7750
|
if (existsSync13(configPath)) {
|
|
7740
|
-
await
|
|
7751
|
+
await writeFileSafe(
|
|
7752
|
+
join14(dir, "config.backup.json"),
|
|
7753
|
+
await readFile11(configPath)
|
|
7754
|
+
);
|
|
7741
7755
|
backedUp = true;
|
|
7742
7756
|
}
|
|
7743
7757
|
let headConfig = cfg.body.config;
|
|
@@ -7756,7 +7770,7 @@ async function cmdPullProgram(argv) {
|
|
|
7756
7770
|
if (own) headConfig = own;
|
|
7757
7771
|
}
|
|
7758
7772
|
}
|
|
7759
|
-
await
|
|
7773
|
+
await writeFileSafe(configPath, JSON.stringify(headConfig, null, 2));
|
|
7760
7774
|
writeSyncState(dir, {
|
|
7761
7775
|
vosId,
|
|
7762
7776
|
versionId: typeof head.id === "string" ? head.id : since
|
|
@@ -7898,13 +7912,16 @@ async function setProgramStill(dir, t) {
|
|
|
7898
7912
|
);
|
|
7899
7913
|
doc = parsed;
|
|
7900
7914
|
}
|
|
7901
|
-
await
|
|
7915
|
+
await writeFileSafe(
|
|
7916
|
+
docPath,
|
|
7917
|
+
JSON.stringify({ ...doc, still: t }, null, 2) + "\n"
|
|
7918
|
+
);
|
|
7902
7919
|
}
|
|
7903
7920
|
async function writeProgramDoc(dir, hosted) {
|
|
7904
7921
|
const program = hosted.program && typeof hosted.program === "object" ? hosted.program : {};
|
|
7905
7922
|
const { config, ...rest } = program;
|
|
7906
7923
|
const onDisk = { ...hosted, program: rest };
|
|
7907
|
-
await
|
|
7924
|
+
await writeFileSafe(join14(dir, "doc.json"), JSON.stringify(onDisk, null, 2));
|
|
7908
7925
|
return {
|
|
7909
7926
|
config: config && typeof config === "object" ? config : null
|
|
7910
7927
|
};
|
|
@@ -8013,6 +8030,130 @@ function nameFromUrl(url) {
|
|
|
8013
8030
|
}
|
|
8014
8031
|
}
|
|
8015
8032
|
|
|
8033
|
+
// src/plugin/netAddress.ts
|
|
8034
|
+
function privateHostReason(hostname2) {
|
|
8035
|
+
const host = hostname2.replace(/^\[|\]$/g, "").toLowerCase();
|
|
8036
|
+
if (host === "localhost" || host.endsWith(".localhost"))
|
|
8037
|
+
return "is this machine";
|
|
8038
|
+
const v4 = parseIPv4(host);
|
|
8039
|
+
if (v4) return privateIPv4Reason(v4);
|
|
8040
|
+
const v6 = expandIPv6(host);
|
|
8041
|
+
if (!v6) return null;
|
|
8042
|
+
const carried = carriedIPv4(v6);
|
|
8043
|
+
if (carried) return privateIPv4Reason(carried);
|
|
8044
|
+
if (v6.every((w) => w === 0)) return "is an unspecified address";
|
|
8045
|
+
if (v6.slice(0, 7).every((w) => w === 0) && v6[7] === 1)
|
|
8046
|
+
return "is this machine";
|
|
8047
|
+
if ((v6[0] & 65024) === 64512) return "is a private network address";
|
|
8048
|
+
if ((v6[0] & 65472) === 65152) return "is a link-local address";
|
|
8049
|
+
return null;
|
|
8050
|
+
}
|
|
8051
|
+
function privateIPv4Reason([a, b]) {
|
|
8052
|
+
if (a === 0) return "is an unspecified address";
|
|
8053
|
+
if (a === 127) return "is this machine";
|
|
8054
|
+
if (a === 10) return "is a private network address";
|
|
8055
|
+
if (a === 172 && b >= 16 && b <= 31) return "is a private network address";
|
|
8056
|
+
if (a === 192 && b === 168) return "is a private network address";
|
|
8057
|
+
if (a === 100 && b >= 64 && b <= 127) return "is a private network address";
|
|
8058
|
+
if (a === 169 && b === 254) return "is a link-local address";
|
|
8059
|
+
return null;
|
|
8060
|
+
}
|
|
8061
|
+
function parseIPv4(host) {
|
|
8062
|
+
if (!/^[0-9a-fx.]+$/i.test(host)) return null;
|
|
8063
|
+
const parts = host.split(".");
|
|
8064
|
+
if (parts.length > 4 || parts.some((p) => p === "")) return null;
|
|
8065
|
+
const nums = [];
|
|
8066
|
+
for (const p of parts) {
|
|
8067
|
+
let n;
|
|
8068
|
+
if (/^0x[0-9a-f]+$/i.test(p)) n = parseInt(p.slice(2), 16);
|
|
8069
|
+
else if (/^0[0-7]+$/.test(p)) n = parseInt(p, 8);
|
|
8070
|
+
else if (/^[0-9]+$/.test(p)) n = parseInt(p, 10);
|
|
8071
|
+
else return null;
|
|
8072
|
+
nums.push(n);
|
|
8073
|
+
}
|
|
8074
|
+
const last = nums[nums.length - 1];
|
|
8075
|
+
const lead = nums.slice(0, -1);
|
|
8076
|
+
if (lead.some((n) => n > 255)) return null;
|
|
8077
|
+
const fill = 4 - lead.length;
|
|
8078
|
+
if (last >= 256 ** fill) return null;
|
|
8079
|
+
const tail = [];
|
|
8080
|
+
let rest = last;
|
|
8081
|
+
for (let i = 0; i < fill; i++) {
|
|
8082
|
+
tail.unshift(rest % 256);
|
|
8083
|
+
rest = Math.floor(rest / 256);
|
|
8084
|
+
}
|
|
8085
|
+
return [...lead, ...tail];
|
|
8086
|
+
}
|
|
8087
|
+
function expandIPv6(host) {
|
|
8088
|
+
if (!host.includes(":")) return null;
|
|
8089
|
+
const zone = host.indexOf("%");
|
|
8090
|
+
const addr = zone >= 0 ? host.slice(0, zone) : host;
|
|
8091
|
+
if (!/^[0-9a-f:.]+$/i.test(addr)) return null;
|
|
8092
|
+
const halves = addr.split("::");
|
|
8093
|
+
if (halves.length > 2) return null;
|
|
8094
|
+
const words2 = (part) => {
|
|
8095
|
+
if (part === "") return [];
|
|
8096
|
+
const out = [];
|
|
8097
|
+
const groups = part.split(":");
|
|
8098
|
+
for (let i = 0; i < groups.length; i++) {
|
|
8099
|
+
const g = groups[i];
|
|
8100
|
+
if (g.includes(".")) {
|
|
8101
|
+
if (i !== groups.length - 1) return null;
|
|
8102
|
+
const v4 = parseIPv4(g);
|
|
8103
|
+
if (!v4) return null;
|
|
8104
|
+
out.push(v4[0] << 8 | v4[1], v4[2] << 8 | v4[3]);
|
|
8105
|
+
continue;
|
|
8106
|
+
}
|
|
8107
|
+
if (!/^[0-9a-f]{1,4}$/i.test(g)) return null;
|
|
8108
|
+
out.push(parseInt(g, 16));
|
|
8109
|
+
}
|
|
8110
|
+
return out;
|
|
8111
|
+
};
|
|
8112
|
+
const head = words2(halves[0]);
|
|
8113
|
+
const tail = halves.length === 2 ? words2(halves[1]) : [];
|
|
8114
|
+
if (!head || !tail) return null;
|
|
8115
|
+
if (halves.length === 1) return head.length === 8 ? head : null;
|
|
8116
|
+
const gap = 8 - head.length - tail.length;
|
|
8117
|
+
if (gap < 1) return null;
|
|
8118
|
+
return [...head, ...new Array(gap).fill(0), ...tail];
|
|
8119
|
+
}
|
|
8120
|
+
function carriedIPv4(v6) {
|
|
8121
|
+
const zeroLead = v6.slice(0, 5).every((w) => w === 0);
|
|
8122
|
+
const mapped = zeroLead && v6[5] === 65535;
|
|
8123
|
+
const compatible = zeroLead && v6[5] === 0 && (v6[6] !== 0 || v6[7] > 1);
|
|
8124
|
+
const nat64 = v6[0] === 100 && v6[1] === 65435;
|
|
8125
|
+
if (!mapped && !compatible && !nat64) return null;
|
|
8126
|
+
return [v6[6] >> 8, v6[6] & 255, v6[7] >> 8, v6[7] & 255];
|
|
8127
|
+
}
|
|
8128
|
+
function fetchRefusal(url) {
|
|
8129
|
+
let u;
|
|
8130
|
+
try {
|
|
8131
|
+
u = new URL(url);
|
|
8132
|
+
} catch {
|
|
8133
|
+
return `${url} is not a URL`;
|
|
8134
|
+
}
|
|
8135
|
+
if (u.protocol !== "http:" && u.protocol !== "https:")
|
|
8136
|
+
return `${url} is not an http(s) address, and the CLI fetches nothing else`;
|
|
8137
|
+
const reason = privateHostReason(u.hostname);
|
|
8138
|
+
if (reason)
|
|
8139
|
+
return `${u.hostname} ${reason}, and the CLI fetches only from the public internet`;
|
|
8140
|
+
return null;
|
|
8141
|
+
}
|
|
8142
|
+
var MAX_HOPS = 5;
|
|
8143
|
+
async function fetchPublic(url, init = {}, fetchImpl = fetch) {
|
|
8144
|
+
let at2 = url;
|
|
8145
|
+
for (let hop = 0; ; hop++) {
|
|
8146
|
+
const refused = fetchRefusal(at2);
|
|
8147
|
+
if (refused) throw new Error(refused);
|
|
8148
|
+
const res = await fetchImpl(at2, { ...init, redirect: "manual" });
|
|
8149
|
+
const location = res.headers.get("location");
|
|
8150
|
+
if (res.status < 300 || res.status > 399 || !location) return res;
|
|
8151
|
+
if (hop >= MAX_HOPS)
|
|
8152
|
+
throw new Error(`${url} redirected more than ${MAX_HOPS} times`);
|
|
8153
|
+
at2 = new URL(location, at2).href;
|
|
8154
|
+
}
|
|
8155
|
+
}
|
|
8156
|
+
|
|
8016
8157
|
// src/plugin/asset.ts
|
|
8017
8158
|
var BOOLEAN_FLAGS3 = /* @__PURE__ */ new Set(["json", "help"]);
|
|
8018
8159
|
async function cmdRename(argv) {
|
|
@@ -8133,8 +8274,10 @@ async function cmdImport(argv) {
|
|
|
8133
8274
|
const key = requireCredential(strFlag(flags, "key"));
|
|
8134
8275
|
const folderRef = strFlag(flags, "folder");
|
|
8135
8276
|
const folder = folderRef ? resolveFolder(await listFolders(origin, key), folderRef) : null;
|
|
8277
|
+
const refused = fetchRefusal(url);
|
|
8278
|
+
if (refused) throw new UsageError(`import: ${refused}`);
|
|
8136
8279
|
r.log(`fetching ${url}`);
|
|
8137
|
-
const res = await
|
|
8280
|
+
const res = await fetchPublic(url);
|
|
8138
8281
|
if (!res.ok)
|
|
8139
8282
|
throw new Error(`import ${url}: the address answered ${res.status}`);
|
|
8140
8283
|
const declared = Number(res.headers.get("content-length") ?? 0);
|
|
@@ -10608,7 +10751,7 @@ async function cmdRecipe(argv) {
|
|
|
10608
10751
|
}
|
|
10609
10752
|
|
|
10610
10753
|
// src/plugin/brand.ts
|
|
10611
|
-
import { writeFile as
|
|
10754
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
10612
10755
|
import { resolve as resolve11 } from "path";
|
|
10613
10756
|
import { parseFrontmatter as parseFrontmatter2 } from "@vosjs/shared/frontmatter";
|
|
10614
10757
|
import { lookKindForGround } from "@vosjs/studio-core";
|
|
@@ -10907,7 +11050,7 @@ function renderBrandMd(c, claim) {
|
|
|
10907
11050
|
}
|
|
10908
11051
|
async function fetchText(url) {
|
|
10909
11052
|
try {
|
|
10910
|
-
const res = await
|
|
11053
|
+
const res = await fetchPublic(url);
|
|
10911
11054
|
if (!res.ok) return null;
|
|
10912
11055
|
const type = res.headers.get("content-type") ?? "";
|
|
10913
11056
|
if (/text\/html/i.test(type)) return null;
|
|
@@ -10927,6 +11070,8 @@ async function cmdBrand(argv) {
|
|
|
10927
11070
|
} catch {
|
|
10928
11071
|
throw new UsageError(`not a URL: ${raw}`);
|
|
10929
11072
|
}
|
|
11073
|
+
const refused = fetchRefusal(url);
|
|
11074
|
+
if (refused) throw new UsageError(refused);
|
|
10930
11075
|
const r = createReporter(flags.json === true);
|
|
10931
11076
|
const out = resolve11(strFlag(flags, "out") ?? "BRAND.md");
|
|
10932
11077
|
r.log(`reading ${origin}/design.md and /llms.txt\u2026`);
|
|
@@ -10962,7 +11107,7 @@ async function cmdBrand(argv) {
|
|
|
10962
11107
|
composition,
|
|
10963
11108
|
llms?.claim ?? design?.description ?? null
|
|
10964
11109
|
);
|
|
10965
|
-
await
|
|
11110
|
+
await writeFile8(out, md);
|
|
10966
11111
|
const k = composition.kit;
|
|
10967
11112
|
r.done(
|
|
10968
11113
|
{
|
|
@@ -10993,6 +11138,20 @@ function hostedEnv(actions, shell) {
|
|
|
10993
11138
|
}
|
|
10994
11139
|
return { env, missing };
|
|
10995
11140
|
}
|
|
11141
|
+
function envNamesNotice(actions) {
|
|
11142
|
+
const names = setupEnvNames2(actions.setup);
|
|
11143
|
+
if (names.length === 0) return null;
|
|
11144
|
+
return {
|
|
11145
|
+
names,
|
|
11146
|
+
line: `the setup reads ${names.length === 1 ? "this environment variable" : "these environment variables"} from this shell: ${names.join(", ")} (names only; a value is never printed or stored)`
|
|
11147
|
+
};
|
|
11148
|
+
}
|
|
11149
|
+
function announceEnvNames(actions, r) {
|
|
11150
|
+
const notice = envNamesNotice(actions);
|
|
11151
|
+
if (!notice) return;
|
|
11152
|
+
r.log(notice.line);
|
|
11153
|
+
r.event({ event: "env", names: notice.names });
|
|
11154
|
+
}
|
|
10996
11155
|
function isWallError(error) {
|
|
10997
11156
|
return !!error && /^(\[\w+\] )?The page is behind a sign-in/.test(error);
|
|
10998
11157
|
}
|
|
@@ -11076,8 +11235,11 @@ async function recordHosted(input) {
|
|
|
11076
11235
|
};
|
|
11077
11236
|
}
|
|
11078
11237
|
|
|
11238
|
+
// src/plugin/run.ts
|
|
11239
|
+
import { urlSchemeProblem } from "@vosjs/render-core/record";
|
|
11240
|
+
|
|
11079
11241
|
// src/plugin/agentBrowser.ts
|
|
11080
|
-
import { writeFile as
|
|
11242
|
+
import { writeFile as writeFile9 } from "fs/promises";
|
|
11081
11243
|
import { resolve as resolve12 } from "path";
|
|
11082
11244
|
function parseAgentBrowserLog(text) {
|
|
11083
11245
|
const records = [];
|
|
@@ -11575,7 +11737,7 @@ async function cmdActions(argv) {
|
|
|
11575
11737
|
);
|
|
11576
11738
|
return EXIT_ERROR;
|
|
11577
11739
|
}
|
|
11578
|
-
await
|
|
11740
|
+
await writeFile9(out, `${JSON.stringify(result.actions, null, 2)}
|
|
11579
11741
|
`);
|
|
11580
11742
|
r.done(
|
|
11581
11743
|
{ ok: true, out, url: result.actions.url ?? null, ...summary2(result) },
|
|
@@ -11610,7 +11772,43 @@ async function cmdActionsScript(input, flags) {
|
|
|
11610
11772
|
import { existsSync as existsSync20 } from "fs";
|
|
11611
11773
|
import { copyFile, mkdir as mkdir7, readFile as readFile12, stat as stat2 } from "fs/promises";
|
|
11612
11774
|
import { basename as basename9, join as join22, resolve as resolve13 } from "path";
|
|
11775
|
+
|
|
11776
|
+
// src/plugin/traceInflate.ts
|
|
11613
11777
|
import { inflateRawSync } from "zlib";
|
|
11778
|
+
var TRACE_ENTRY_MAX_BYTES = 64 * 1024 * 1024;
|
|
11779
|
+
var TRACE_TOTAL_MAX_BYTES = 256 * 1024 * 1024;
|
|
11780
|
+
function traceBudget(caps = {}) {
|
|
11781
|
+
return {
|
|
11782
|
+
entry: caps.entry ?? TRACE_ENTRY_MAX_BYTES,
|
|
11783
|
+
total: caps.total ?? TRACE_TOTAL_MAX_BYTES,
|
|
11784
|
+
used: 0
|
|
11785
|
+
};
|
|
11786
|
+
}
|
|
11787
|
+
var mib = (n) => `${(n / (1024 * 1024)).toFixed(n < 10 * 1024 * 1024 ? 1 : 0)} MiB`;
|
|
11788
|
+
function inflateEntry(raw, entry, budget) {
|
|
11789
|
+
const room = Math.min(budget.entry, budget.total - budget.used);
|
|
11790
|
+
const over = (bytes) => new Error(
|
|
11791
|
+
`${entry.name} inflates to ${bytes}, past the ${mib(budget.entry)} an entry may take (${mib(budget.total)} for the whole trace); this is not a trace the recorder reads`
|
|
11792
|
+
);
|
|
11793
|
+
if (entry.size > room) throw over(mib(entry.size));
|
|
11794
|
+
let out;
|
|
11795
|
+
if (entry.method === 8) {
|
|
11796
|
+
try {
|
|
11797
|
+
out = new Uint8Array(inflateRawSync(raw, { maxOutputLength: room + 1 }));
|
|
11798
|
+
} catch (e) {
|
|
11799
|
+
if (e.code === "ERR_BUFFER_TOO_LARGE")
|
|
11800
|
+
throw over(`more than ${mib(room)}`);
|
|
11801
|
+
throw e;
|
|
11802
|
+
}
|
|
11803
|
+
} else {
|
|
11804
|
+
out = raw;
|
|
11805
|
+
}
|
|
11806
|
+
if (out.length > room) throw over(mib(out.length));
|
|
11807
|
+
budget.used += out.length;
|
|
11808
|
+
return out;
|
|
11809
|
+
}
|
|
11810
|
+
|
|
11811
|
+
// src/plugin/ingest.ts
|
|
11614
11812
|
import {
|
|
11615
11813
|
cursorFromPlaywrightTrace,
|
|
11616
11814
|
cursorFromTrace,
|
|
@@ -11706,7 +11904,7 @@ async function readTraceFile(path, offsetMs) {
|
|
|
11706
11904
|
}
|
|
11707
11905
|
const raw = zipEntryBytes(bytes, entry);
|
|
11708
11906
|
const text2 = new TextDecoder().decode(
|
|
11709
|
-
entry
|
|
11907
|
+
inflateEntry(raw, entry, traceBudget())
|
|
11710
11908
|
);
|
|
11711
11909
|
return cursorFromPlaywrightTrace(text2, { offsetMs });
|
|
11712
11910
|
}
|
|
@@ -12053,6 +12251,14 @@ function doctorReport(facts) {
|
|
|
12053
12251
|
next_step = "Record: npx vos record --actions actions.json --out take --strict (the product-video skill writes actions.json)";
|
|
12054
12252
|
return { ok: nodeOk && browserOk, lines, next_step, facts };
|
|
12055
12253
|
}
|
|
12254
|
+
function bundledSkillsVersion(dir) {
|
|
12255
|
+
try {
|
|
12256
|
+
const v = readFileSync10(join23(dir, "VERSION"), "utf8").trim();
|
|
12257
|
+
return /^\d+\.\d+\.\d+$/.test(v) ? v : null;
|
|
12258
|
+
} catch {
|
|
12259
|
+
return null;
|
|
12260
|
+
}
|
|
12261
|
+
}
|
|
12056
12262
|
function bundledSkillsDir(from) {
|
|
12057
12263
|
let dir = dirname8(from);
|
|
12058
12264
|
for (let i = 0; i < 6; i++) {
|
|
@@ -12080,10 +12286,15 @@ var BOOLEAN_FLAGS11 = /* @__PURE__ */ new Set([
|
|
|
12080
12286
|
"help",
|
|
12081
12287
|
"global",
|
|
12082
12288
|
"no-skills",
|
|
12289
|
+
"skills-from-catalog",
|
|
12083
12290
|
"no-rules",
|
|
12084
12291
|
"no-browser"
|
|
12085
12292
|
]);
|
|
12086
12293
|
var SKILLS_SOURCE = "vosjs/skills";
|
|
12294
|
+
var SKILLS_CLI_VERSION = "1.7.2";
|
|
12295
|
+
function skillsCatalogAt(version) {
|
|
12296
|
+
return `https://github.com/${SKILLS_SOURCE}/tree/v${version}`;
|
|
12297
|
+
}
|
|
12087
12298
|
function reporterFor(flags) {
|
|
12088
12299
|
return createReporter(flags.json === true || process.stdout.isTTY !== true);
|
|
12089
12300
|
}
|
|
@@ -12159,6 +12370,7 @@ async function cmdSetup(argv) {
|
|
|
12159
12370
|
const global = flags.global === true;
|
|
12160
12371
|
const url = strFlag(flags, "url");
|
|
12161
12372
|
const noSkills = flags["no-skills"] === true;
|
|
12373
|
+
const fromCatalog = flags["skills-from-catalog"] === true;
|
|
12162
12374
|
const noRules = flags["no-rules"] === true;
|
|
12163
12375
|
const noBrowser = flags["no-browser"] === true;
|
|
12164
12376
|
const wanted = strFlag(flags, "agent");
|
|
@@ -12178,48 +12390,61 @@ async function cmdSetup(argv) {
|
|
|
12178
12390
|
let skillsVia = "skipped";
|
|
12179
12391
|
let skillNames = [];
|
|
12180
12392
|
if (!noSkills) {
|
|
12181
|
-
const
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
"-y",
|
|
12186
|
-
...global ? ["-g"] : []
|
|
12187
|
-
];
|
|
12188
|
-
r.log(`installing the vos skills: npx ${args.join(" ")}`);
|
|
12189
|
-
const res = spawnSync4(npx(), args, {
|
|
12190
|
-
cwd: root,
|
|
12191
|
-
encoding: "utf8",
|
|
12192
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
12193
|
-
shell: process.platform === "win32",
|
|
12194
|
-
timeout: 12e4
|
|
12195
|
-
});
|
|
12196
|
-
if (res.status === 0) {
|
|
12197
|
-
skillsVia = "skills.sh";
|
|
12198
|
-
} else {
|
|
12199
|
-
const bundled = bundledSkillsDir(import.meta.url.replace("file://", ""));
|
|
12200
|
-
if (!bundled)
|
|
12201
|
-
throw new Error(
|
|
12202
|
-
`could not install the skills: npx skills add ${SKILLS_SOURCE} failed (${(res.stderr ?? "").trim().split("\n").at(-1) ?? res.error?.message ?? "no output"}) and this build carries no bundled copy`
|
|
12203
|
-
);
|
|
12204
|
-
const targets = homes.length ? homes : [fallbackSkillsHome(root)];
|
|
12393
|
+
const bundled = bundledSkillsDir(import.meta.url.replace("file://", ""));
|
|
12394
|
+
const version = bundled ? bundledSkillsVersion(bundled) : null;
|
|
12395
|
+
const targets = homes.length ? homes : [fallbackSkillsHome(root)];
|
|
12396
|
+
const copyBundled = (dir) => {
|
|
12205
12397
|
for (const home of targets) {
|
|
12206
12398
|
const dest = skillsDirFor(home);
|
|
12207
12399
|
mkdirSync6(dest, { recursive: true });
|
|
12208
|
-
for (const name of installedSkills(
|
|
12209
|
-
cpSync(join24(
|
|
12400
|
+
for (const name of installedSkills(dir)) {
|
|
12401
|
+
cpSync(join24(dir, name), join24(dest, name), { recursive: true });
|
|
12210
12402
|
}
|
|
12211
12403
|
}
|
|
12404
|
+
};
|
|
12405
|
+
if (fromCatalog) {
|
|
12406
|
+
const source = version ? skillsCatalogAt(version) : SKILLS_SOURCE;
|
|
12407
|
+
const args = [
|
|
12408
|
+
`skills@${SKILLS_CLI_VERSION}`,
|
|
12409
|
+
"add",
|
|
12410
|
+
source,
|
|
12411
|
+
"-y",
|
|
12412
|
+
...global ? ["-g"] : []
|
|
12413
|
+
];
|
|
12414
|
+
r.log(`installing the vos skills: npx ${args.join(" ")}`);
|
|
12415
|
+
const res = spawnSync4(npx(), args, {
|
|
12416
|
+
cwd: root,
|
|
12417
|
+
encoding: "utf8",
|
|
12418
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
12419
|
+
shell: process.platform === "win32",
|
|
12420
|
+
timeout: 12e4
|
|
12421
|
+
});
|
|
12422
|
+
if (res.status === 0) {
|
|
12423
|
+
skillsVia = "skills.sh";
|
|
12424
|
+
} else {
|
|
12425
|
+
if (!bundled)
|
|
12426
|
+
throw new Error(
|
|
12427
|
+
`could not install the skills: npx ${args.join(" ")} failed (${(res.stderr ?? "").trim().split("\n").at(-1) ?? res.error?.message ?? "no output"}) and this build carries no bundled copy`
|
|
12428
|
+
);
|
|
12429
|
+
copyBundled(bundled);
|
|
12430
|
+
skillsVia = "bundled";
|
|
12431
|
+
r.log(
|
|
12432
|
+
`skills.sh did not answer; copied the bundled skills into ${targets.map((t) => skillsDirFor(t)).join(", ")}`
|
|
12433
|
+
);
|
|
12434
|
+
}
|
|
12435
|
+
} else {
|
|
12436
|
+
if (!bundled)
|
|
12437
|
+
throw new Error(
|
|
12438
|
+
"this build carries no bundled skills; run with --skills-from-catalog"
|
|
12439
|
+
);
|
|
12440
|
+
copyBundled(bundled);
|
|
12212
12441
|
skillsVia = "bundled";
|
|
12213
12442
|
r.log(
|
|
12214
|
-
`skills
|
|
12443
|
+
`installed the bundled vos skills${version ? ` (catalog ${version})` : ""} into ${targets.map((t) => skillsDirFor(t)).join(", ")}`
|
|
12215
12444
|
);
|
|
12216
12445
|
}
|
|
12217
12446
|
skillNames = [
|
|
12218
|
-
...new Set(
|
|
12219
|
-
(homes.length ? homes : [fallbackSkillsHome(root)]).flatMap(
|
|
12220
|
-
(h) => installedSkills(skillsDirFor(h))
|
|
12221
|
-
)
|
|
12222
|
-
)
|
|
12447
|
+
...new Set(targets.flatMap((h) => installedSkills(skillsDirFor(h))))
|
|
12223
12448
|
].sort();
|
|
12224
12449
|
}
|
|
12225
12450
|
r.event({ event: "skills", via: skillsVia, names: skillNames });
|
|
@@ -12432,11 +12657,12 @@ Take pipeline
|
|
|
12432
12657
|
the flow as numbered beats in words, for a person recording it by hand
|
|
12433
12658
|
|
|
12434
12659
|
This machine (no account)
|
|
12435
|
-
vos setup [--agent claude,cursor,codex,copilot|all] [--global] [--no-skills] [--no-rules] [--no-browser] [--url <dev server>] [--json]
|
|
12660
|
+
vos setup [--agent claude,cursor,codex,copilot|all] [--global] [--no-skills] [--skills-from-catalog] [--no-rules] [--no-browser] [--url <dev server>] [--json]
|
|
12436
12661
|
ready this computer for the loop: the vos skills into your
|
|
12437
|
-
agent's directories (
|
|
12438
|
-
|
|
12439
|
-
idempotent block in AGENTS.md
|
|
12662
|
+
agent's directories (the copy bundled in this package, or with
|
|
12663
|
+
--skills-from-catalog the same tag through skills.sh), a
|
|
12664
|
+
browser found or installed, one idempotent block in AGENTS.md
|
|
12665
|
+
(or CLAUDE.md), then doctor.
|
|
12440
12666
|
NDJSON whenever stdout is not a TTY; done carries next_step
|
|
12441
12667
|
vos doctor [--url <dev server>] [--json]
|
|
12442
12668
|
what is ready, in words: node, browser, ffmpeg, the skills per
|
|
@@ -12839,6 +13065,9 @@ async function cmdRecord(argv) {
|
|
|
12839
13065
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
12840
13066
|
if (!url)
|
|
12841
13067
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
13068
|
+
const scheme = urlSchemeProblem(url);
|
|
13069
|
+
if (scheme) throw new UsageError(scheme);
|
|
13070
|
+
announceEnvNames(actions, r);
|
|
12842
13071
|
const outDir = resolve14(strFlag(flags, "out") ?? "take");
|
|
12843
13072
|
const storageState = takeStorageState(flags);
|
|
12844
13073
|
const sessionName = takeSessionName(flags, storageState);
|
|
@@ -13084,6 +13313,9 @@ async function cmdCreate2(argv) {
|
|
|
13084
13313
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
13085
13314
|
if (!url)
|
|
13086
13315
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
13316
|
+
const scheme = urlSchemeProblem(url);
|
|
13317
|
+
if (scheme) throw new UsageError(scheme);
|
|
13318
|
+
announceEnvNames(actions, r);
|
|
13087
13319
|
const outDir = resolve14(strFlag(flags, "out") ?? "take");
|
|
13088
13320
|
const format = videoFormat(strFlag(flags, "format"), positionals[0]);
|
|
13089
13321
|
const out = positionals[0] ?? join25(outDir, `out.${format}`);
|
|
@@ -14447,4 +14679,4 @@ export {
|
|
|
14447
14679
|
verbHelp,
|
|
14448
14680
|
run
|
|
14449
14681
|
};
|
|
14450
|
-
//# sourceMappingURL=chunk-
|
|
14682
|
+
//# sourceMappingURL=chunk-SB622PZM.js.map
|