@vosjs/cli 0.74.0 → 0.75.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assetManifest-3QYCLT2H.js → assetManifest-LOPDTP47.js} +2 -2
- package/dist/{chunk-Y5E672GT.js → chunk-M3QIN457.js} +21 -6
- package/dist/chunk-M3QIN457.js.map +1 -0
- package/dist/{chunk-EYF3WJIC.js → chunk-X6NQNBDF.js} +281 -196
- package/dist/chunk-X6NQNBDF.js.map +1 -0
- package/dist/cli.js +13 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{run-FK5HWX4X.js → run-XZ2UPHMO.js} +3 -3
- package/package.json +4 -4
- package/dist/chunk-EYF3WJIC.js.map +0 -1
- package/dist/chunk-Y5E672GT.js.map +0 -1
- /package/dist/{assetManifest-3QYCLT2H.js.map → assetManifest-LOPDTP47.js.map} +0 -0
- /package/dist/{run-FK5HWX4X.js.map → run-XZ2UPHMO.js.map} +0 -0
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
uploadDocRefs,
|
|
37
37
|
uploadManifest,
|
|
38
38
|
writeJson
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-M3QIN457.js";
|
|
40
40
|
import {
|
|
41
41
|
CREDENTIALS_PATH,
|
|
42
42
|
MEDIA_HEAD_BYTES,
|
|
@@ -133,7 +133,7 @@ function landedLines(l) {
|
|
|
133
133
|
// src/plugin/run.ts
|
|
134
134
|
import { mkdir as mkdir8, readFile as readFile13, rm as rm2 } from "fs/promises";
|
|
135
135
|
import { existsSync as existsSync23 } from "fs";
|
|
136
|
-
import { join as join25, resolve as
|
|
136
|
+
import { join as join25, resolve as resolve14 } from "path";
|
|
137
137
|
import {
|
|
138
138
|
END_CARD_FROM as END_CARD_FROM2,
|
|
139
139
|
docOutputDuration as docOutputDuration3,
|
|
@@ -2014,7 +2014,7 @@ function mediaProbeLints(results) {
|
|
|
2014
2014
|
// src/plugin/framesTake.ts
|
|
2015
2015
|
import { mkdir as mkdir2, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
|
|
2016
2016
|
import { existsSync as existsSync3 } from "fs";
|
|
2017
|
-
import { join as join3, resolve as
|
|
2017
|
+
import { join as join3, resolve as resolve3 } from "path";
|
|
2018
2018
|
import { compileVosConfig } from "@vosjs/core";
|
|
2019
2019
|
import {
|
|
2020
2020
|
docStillTime,
|
|
@@ -2028,9 +2028,10 @@ import {
|
|
|
2028
2028
|
|
|
2029
2029
|
// src/plugin/server.ts
|
|
2030
2030
|
import { createServer } from "http";
|
|
2031
|
-
import {
|
|
2031
|
+
import { randomBytes } from "crypto";
|
|
2032
|
+
import { existsSync, readFileSync, realpathSync, statSync } from "fs";
|
|
2032
2033
|
import { writeFile } from "fs/promises";
|
|
2033
|
-
import { extname, join } from "path";
|
|
2034
|
+
import { extname, join, resolve, sep } from "path";
|
|
2034
2035
|
var MIME = {
|
|
2035
2036
|
".html": "text/html",
|
|
2036
2037
|
".js": "text/javascript",
|
|
@@ -2052,9 +2053,46 @@ var MIME = {
|
|
|
2052
2053
|
".m4a": "audio/mp4",
|
|
2053
2054
|
".ogg": "audio/ogg"
|
|
2054
2055
|
};
|
|
2056
|
+
var SAVE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
2057
|
+
var SAVE_NEVER = /* @__PURE__ */ new Set([
|
|
2058
|
+
"doc.json",
|
|
2059
|
+
"actions.json",
|
|
2060
|
+
"vos.json",
|
|
2061
|
+
"meta.json",
|
|
2062
|
+
"cursor.json"
|
|
2063
|
+
]);
|
|
2064
|
+
function saveNameOk(name) {
|
|
2065
|
+
return SAVE_NAME.test(name) && !name.includes("..") && !SAVE_NEVER.has(name);
|
|
2066
|
+
}
|
|
2067
|
+
function fileInRoot(rootDir, pathname) {
|
|
2068
|
+
let decoded;
|
|
2069
|
+
try {
|
|
2070
|
+
decoded = decodeURIComponent(pathname);
|
|
2071
|
+
} catch {
|
|
2072
|
+
return null;
|
|
2073
|
+
}
|
|
2074
|
+
const file = resolve(rootDir, `.${decoded}`);
|
|
2075
|
+
if (!existsSync(file) || !statSync(file).isFile()) return null;
|
|
2076
|
+
const root = realpathSync(rootDir);
|
|
2077
|
+
const real = realpathSync(file);
|
|
2078
|
+
return real.startsWith(root + sep) ? real : null;
|
|
2079
|
+
}
|
|
2080
|
+
function ownReader(req) {
|
|
2081
|
+
const site = req.headers["sec-fetch-site"];
|
|
2082
|
+
return site === void 0 || site === "same-origin" || site === "none";
|
|
2083
|
+
}
|
|
2055
2084
|
function startTakeServer(rootDir, pages) {
|
|
2085
|
+
const token = randomBytes(16).toString("hex");
|
|
2086
|
+
const prefix = `/t/${token}`;
|
|
2056
2087
|
const server = createServer((req, res) => {
|
|
2057
|
-
const
|
|
2088
|
+
const raw = new URL(req.url ?? "/", "http://x");
|
|
2089
|
+
const tokened = raw.pathname === prefix || raw.pathname.startsWith(`${prefix}/`);
|
|
2090
|
+
if (!tokened && req.method !== "OPTIONS" && !ownReader(req)) {
|
|
2091
|
+
res.writeHead(404).end();
|
|
2092
|
+
return;
|
|
2093
|
+
}
|
|
2094
|
+
const url = tokened ? new URL(raw.pathname.slice(prefix.length) || "/", "http://x") : raw;
|
|
2095
|
+
url.search = raw.search;
|
|
2058
2096
|
res.setHeader("access-control-allow-origin", "*");
|
|
2059
2097
|
res.setHeader("access-control-allow-private-network", "true");
|
|
2060
2098
|
if (req.method === "OPTIONS") {
|
|
@@ -2067,10 +2105,11 @@ function startTakeServer(rootDir, pages) {
|
|
|
2067
2105
|
return;
|
|
2068
2106
|
}
|
|
2069
2107
|
if (req.method === "POST" && url.pathname === "/save") {
|
|
2070
|
-
const name =
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2108
|
+
const name = url.searchParams.get("name") ?? "out.bin";
|
|
2109
|
+
if (tokened || !ownReader(req) || !saveNameOk(name)) {
|
|
2110
|
+
res.writeHead(404).end();
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
2074
2113
|
const chunks = [];
|
|
2075
2114
|
req.on("data", (c) => chunks.push(c));
|
|
2076
2115
|
req.on("end", () => {
|
|
@@ -2086,8 +2125,8 @@ function startTakeServer(rootDir, pages) {
|
|
|
2086
2125
|
res.end(pages[url.pathname]);
|
|
2087
2126
|
return;
|
|
2088
2127
|
}
|
|
2089
|
-
const file =
|
|
2090
|
-
if (
|
|
2128
|
+
const file = fileInRoot(rootDir, url.pathname);
|
|
2129
|
+
if (file) {
|
|
2091
2130
|
const size = statSync(file).size;
|
|
2092
2131
|
const buf = readFileSync(file);
|
|
2093
2132
|
const type = sniffMediaType(buf.subarray(0, MEDIA_HEAD_BYTES)) ?? MIME[extname(file)] ?? "application/octet-stream";
|
|
@@ -2120,10 +2159,13 @@ function startTakeServer(rootDir, pages) {
|
|
|
2120
2159
|
res.writeHead(404).end();
|
|
2121
2160
|
});
|
|
2122
2161
|
return new Promise(
|
|
2123
|
-
(
|
|
2162
|
+
(done) => server.listen(0, "127.0.0.1", () => {
|
|
2124
2163
|
const addr = server.address();
|
|
2125
2164
|
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
2126
|
-
|
|
2165
|
+
done({
|
|
2166
|
+
base: `http://127.0.0.1:${port}${prefix}`,
|
|
2167
|
+
close: () => server.close()
|
|
2168
|
+
});
|
|
2127
2169
|
})
|
|
2128
2170
|
);
|
|
2129
2171
|
}
|
|
@@ -2708,7 +2750,7 @@ function applyAndValidate(doc, o) {
|
|
|
2708
2750
|
// src/plugin/digestTake.ts
|
|
2709
2751
|
import { mkdir, readFile as readFile2, rename, writeFile as writeFile2 } from "fs/promises";
|
|
2710
2752
|
import { existsSync as existsSync2 } from "fs";
|
|
2711
|
-
import { join as join2, resolve } from "path";
|
|
2753
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
2712
2754
|
import {
|
|
2713
2755
|
CHANGE_GRID,
|
|
2714
2756
|
CHANGE_LEAD,
|
|
@@ -2969,7 +3011,7 @@ async function digestTake(browser, dir, opts = {}) {
|
|
|
2969
3011
|
const meta = doc.source.meta;
|
|
2970
3012
|
let plan = planForDigest(doc);
|
|
2971
3013
|
const transcript = opts.transcript ?? await discoverTranscript(dir);
|
|
2972
|
-
const outDir =
|
|
3014
|
+
const outDir = resolve2(opts.outDir ?? join2(dir, DIGEST_DIR));
|
|
2973
3015
|
await mkdir(outDir, { recursive: true });
|
|
2974
3016
|
const fullMax = opts.full ?? DIGEST_FULL_MAX;
|
|
2975
3017
|
const cropMax = opts.crop ?? DIGEST_CROP_MAX;
|
|
@@ -3380,7 +3422,7 @@ async function framesTake(browser, dir, opts) {
|
|
|
3380
3422
|
throw new Error(
|
|
3381
3423
|
"no frame times \u2014 pass --times/--frame, --at-zooms, --at-moments or --at-still"
|
|
3382
3424
|
);
|
|
3383
|
-
const outDir =
|
|
3425
|
+
const outDir = resolve3(opts.outDir ?? join3(dir, "stills"));
|
|
3384
3426
|
await mkdir2(outDir, { recursive: true });
|
|
3385
3427
|
const named = shots.map((s, i) => ({
|
|
3386
3428
|
...s,
|
|
@@ -3484,7 +3526,7 @@ async function writeIndexJson(result) {
|
|
|
3484
3526
|
|
|
3485
3527
|
// src/plugin/deliver.ts
|
|
3486
3528
|
import { mkdir as mkdir3, writeFile as writeFile5 } from "fs/promises";
|
|
3487
|
-
import { join as join4, relative, resolve as
|
|
3529
|
+
import { join as join4, relative, resolve as resolve4 } from "path";
|
|
3488
3530
|
import { existsSync as existsSync4 } from "fs";
|
|
3489
3531
|
import { readFile as readFile4 } from "fs/promises";
|
|
3490
3532
|
import { parseFrontmatter } from "@vosjs/shared/frontmatter";
|
|
@@ -4062,7 +4104,7 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4062
4104
|
const doc = take.doc;
|
|
4063
4105
|
const duration = docOutputDuration2(doc);
|
|
4064
4106
|
const videoSeconds = opts.range ? Math.min(opts.range[1], duration) - Math.min(opts.range[0], duration) : duration;
|
|
4065
|
-
const outDir =
|
|
4107
|
+
const outDir = resolve4(opts.outDir ?? join4(dir, "kit"));
|
|
4066
4108
|
await mkdir3(outDir, { recursive: true });
|
|
4067
4109
|
const destinations = opts.channels.flatMap((c) => destinationsForChannel(c));
|
|
4068
4110
|
const assets = [];
|
|
@@ -4156,10 +4198,147 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4156
4198
|
return { kit, kitFile, outDir };
|
|
4157
4199
|
}
|
|
4158
4200
|
|
|
4201
|
+
// src/plugin/login.ts
|
|
4202
|
+
import { hostname } from "os";
|
|
4203
|
+
var LoginUnsupportedError = class extends Error {
|
|
4204
|
+
constructor() {
|
|
4205
|
+
super("this origin does not support browser login");
|
|
4206
|
+
}
|
|
4207
|
+
};
|
|
4208
|
+
var MAX_TRANSIENT_FAILURES = 5;
|
|
4209
|
+
var MAX_INTERVAL_MS = 3e4;
|
|
4210
|
+
async function launchDefaultBrowser(url) {
|
|
4211
|
+
const { spawn: spawn2 } = await import("child_process");
|
|
4212
|
+
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
4213
|
+
try {
|
|
4214
|
+
const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
|
|
4215
|
+
child.on("error", () => {
|
|
4216
|
+
});
|
|
4217
|
+
child.unref();
|
|
4218
|
+
} catch {
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
function verifyUrlOk(verifyUrl, origin) {
|
|
4222
|
+
try {
|
|
4223
|
+
return new URL(verifyUrl).origin === new URL(origin).origin;
|
|
4224
|
+
} catch {
|
|
4225
|
+
return false;
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
async function browserLogin(origin, r, opts) {
|
|
4229
|
+
const create = await apiJson(origin, "/api/cli/login", {
|
|
4230
|
+
method: "POST",
|
|
4231
|
+
body: {
|
|
4232
|
+
hostname: hostname().slice(0, 64),
|
|
4233
|
+
...opts.label ? { label: opts.label.slice(0, 64) } : {}
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
4236
|
+
if (create.status === 404) throw new LoginUnsupportedError();
|
|
4237
|
+
if (create.status !== 201) throw new Error(apiError("start login", create));
|
|
4238
|
+
const code = create.body.code;
|
|
4239
|
+
const secret = create.body.secret;
|
|
4240
|
+
const verifyUrl = create.body.verifyUrl;
|
|
4241
|
+
const expiresAt = Date.parse(String(create.body.expiresAt ?? ""));
|
|
4242
|
+
const baseIntervalMs = (typeof create.body.interval === "number" ? create.body.interval : 3) * 1e3;
|
|
4243
|
+
if (!code || !secret || !verifyUrl || Number.isNaN(expiresAt)) {
|
|
4244
|
+
throw new Error("start login \u2192 malformed response from the platform");
|
|
4245
|
+
}
|
|
4246
|
+
r.event({ event: "login_await", url: verifyUrl, code, expiresAt });
|
|
4247
|
+
r.log(`Confirm this code in the browser: ${code}`);
|
|
4248
|
+
r.log(`Sign in at ${verifyUrl}`);
|
|
4249
|
+
if (opts.openBrowser && verifyUrlOk(verifyUrl, origin))
|
|
4250
|
+
void launchDefaultBrowser(verifyUrl);
|
|
4251
|
+
r.log("Waiting for approval\u2026 (Ctrl-C to cancel)");
|
|
4252
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((res) => setTimeout(res, ms)));
|
|
4253
|
+
let intervalMs = baseIntervalMs;
|
|
4254
|
+
let failures = 0;
|
|
4255
|
+
let capNoted = false;
|
|
4256
|
+
while (Date.now() < expiresAt) {
|
|
4257
|
+
await sleep(intervalMs);
|
|
4258
|
+
let res;
|
|
4259
|
+
try {
|
|
4260
|
+
res = await apiJson(origin, "/api/cli/login/poll", {
|
|
4261
|
+
method: "POST",
|
|
4262
|
+
body: { secret }
|
|
4263
|
+
});
|
|
4264
|
+
failures = 0;
|
|
4265
|
+
} catch (e) {
|
|
4266
|
+
if (++failures >= MAX_TRANSIENT_FAILURES) {
|
|
4267
|
+
throw new Error(
|
|
4268
|
+
`lost the connection while waiting (${e instanceof Error ? e.message : String(e)}) \u2014 run \`vos login\` again`
|
|
4269
|
+
);
|
|
4270
|
+
}
|
|
4271
|
+
continue;
|
|
4272
|
+
}
|
|
4273
|
+
const status = res.body.status;
|
|
4274
|
+
if (res.status === 200 && status === "pending") {
|
|
4275
|
+
intervalMs = baseIntervalMs;
|
|
4276
|
+
continue;
|
|
4277
|
+
}
|
|
4278
|
+
if (res.status === 200 && status === "ok") {
|
|
4279
|
+
const path = (opts.store ?? writeCredential)(res.body.key);
|
|
4280
|
+
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4281
|
+
return { path, user };
|
|
4282
|
+
}
|
|
4283
|
+
if (res.status === 429) {
|
|
4284
|
+
if (status === "key_limit" && !capNoted) {
|
|
4285
|
+
capNoted = true;
|
|
4286
|
+
r.log(`${res.body.error} \u2014 ${res.body.hint}`);
|
|
4287
|
+
}
|
|
4288
|
+
intervalMs = Math.min(intervalMs * 2, MAX_INTERVAL_MS);
|
|
4289
|
+
continue;
|
|
4290
|
+
}
|
|
4291
|
+
if (res.status === 403 && status === "denied") {
|
|
4292
|
+
throw new Error("the sign-in was denied in the browser");
|
|
4293
|
+
}
|
|
4294
|
+
throw new Error(
|
|
4295
|
+
typeof res.body.error === "string" ? res.body.error : apiError("poll login", res)
|
|
4296
|
+
);
|
|
4297
|
+
}
|
|
4298
|
+
throw new Error(
|
|
4299
|
+
"no approval within 15 minutes \u2014 run `vos login` again, or mint a key at https://vos.so/app/api and pass --key"
|
|
4300
|
+
);
|
|
4301
|
+
}
|
|
4302
|
+
var HANDOFF_URL = /^(https?:\/\/[^/]+)\/h\/(vos_ho_[A-Za-z0-9_-]+)$/;
|
|
4303
|
+
function parseHandoffUrl(url) {
|
|
4304
|
+
const m = HANDOFF_URL.exec(url.trim());
|
|
4305
|
+
return m ? { origin: m[1], token: m[2] } : null;
|
|
4306
|
+
}
|
|
4307
|
+
async function handoffLogin(url, r, opts = {}) {
|
|
4308
|
+
const parsed = parseHandoffUrl(url);
|
|
4309
|
+
if (!parsed)
|
|
4310
|
+
throw new Error(
|
|
4311
|
+
"--handoff wants the link a person copied from vos.so, https://vos.so/h/vos_ho_\u2026"
|
|
4312
|
+
);
|
|
4313
|
+
r.log(`exchanging the setup link at ${parsed.origin}\u2026`);
|
|
4314
|
+
const res = await apiJson(parsed.origin, "/api/cli/login/exchange", {
|
|
4315
|
+
method: "POST",
|
|
4316
|
+
body: { token: parsed.token, hostname: hostname().slice(0, 64) }
|
|
4317
|
+
});
|
|
4318
|
+
if (res.status === 200 && res.body.status === "ok") {
|
|
4319
|
+
const path = (opts.store ?? writeCredential)(res.body.key);
|
|
4320
|
+
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4321
|
+
return {
|
|
4322
|
+
path,
|
|
4323
|
+
user,
|
|
4324
|
+
keyName: String(res.body.keyName ?? ""),
|
|
4325
|
+
origin: parsed.origin
|
|
4326
|
+
};
|
|
4327
|
+
}
|
|
4328
|
+
if (res.status === 404 && !res.body.status) {
|
|
4329
|
+
throw new Error(
|
|
4330
|
+
`${parsed.origin} does not support setup links yet \u2014 run \`vos login\` instead`
|
|
4331
|
+
);
|
|
4332
|
+
}
|
|
4333
|
+
const said = typeof res.body.error === "string" ? res.body.error : apiError("exchange", res);
|
|
4334
|
+
const hint = typeof res.body.hint === "string" ? ` ${res.body.hint}` : "";
|
|
4335
|
+
throw new Error(`${said}${hint}`);
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4159
4338
|
// src/plugin/markAsset.ts
|
|
4160
4339
|
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
4161
4340
|
import { existsSync as existsSync5 } from "fs";
|
|
4162
|
-
import { isAbsolute, join as join5, resolve as
|
|
4341
|
+
import { isAbsolute, join as join5, resolve as resolve5 } from "path";
|
|
4163
4342
|
function markExtension(url) {
|
|
4164
4343
|
const m = /\.(svg|png|webp|jpe?g)(?:[?#]|$)/i.exec(url);
|
|
4165
4344
|
if (!m) return null;
|
|
@@ -4240,7 +4419,7 @@ async function fetchBrandMarks(takeDir, roles) {
|
|
|
4240
4419
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4241
4420
|
bytes = new Uint8Array(await res.arrayBuffer());
|
|
4242
4421
|
} else {
|
|
4243
|
-
const file = isAbsolute(src) ? src :
|
|
4422
|
+
const file = isAbsolute(src) ? src : resolve5(takeDir, src);
|
|
4244
4423
|
if (!existsSync5(file)) throw new Error("no such file");
|
|
4245
4424
|
bytes = new Uint8Array(await readFile5(file));
|
|
4246
4425
|
}
|
|
@@ -5269,10 +5448,10 @@ async function openSession(name, url, opts = { log: () => {
|
|
|
5269
5448
|
opts.log(
|
|
5270
5449
|
`a Chrome window opened on session "${name}": sign in to ${new URL(url).host}, ${leave}`
|
|
5271
5450
|
);
|
|
5272
|
-
return new Promise((
|
|
5451
|
+
return new Promise((resolve15, reject) => {
|
|
5273
5452
|
const child = spawn(exe, args, { stdio: "ignore" });
|
|
5274
5453
|
child.on("error", reject);
|
|
5275
|
-
child.on("exit", (code) =>
|
|
5454
|
+
child.on("exit", (code) => resolve15({ code }));
|
|
5276
5455
|
});
|
|
5277
5456
|
}
|
|
5278
5457
|
async function withSession(name, fn, opts = {}) {
|
|
@@ -5989,11 +6168,33 @@ function scriptToWrite(doc, hasLocal) {
|
|
|
5989
6168
|
return `${JSON.stringify(script, null, 2)}
|
|
5990
6169
|
`;
|
|
5991
6170
|
}
|
|
6171
|
+
function publicScript(script) {
|
|
6172
|
+
const setup = script.setup;
|
|
6173
|
+
if (!Array.isArray(setup)) return script;
|
|
6174
|
+
return {
|
|
6175
|
+
...script,
|
|
6176
|
+
setup: setup.map((step) => {
|
|
6177
|
+
if (!step || typeof step !== "object") return step;
|
|
6178
|
+
const s = step;
|
|
6179
|
+
if (s.do === "type" && typeof s.text === "string")
|
|
6180
|
+
return { ...s, text: "[typed value not stored]" };
|
|
6181
|
+
if (s.do === "goto" && typeof s.url === "string") {
|
|
6182
|
+
try {
|
|
6183
|
+
const u = new URL(s.url);
|
|
6184
|
+
return { ...s, url: `${u.origin}${u.pathname}` };
|
|
6185
|
+
} catch {
|
|
6186
|
+
return s;
|
|
6187
|
+
}
|
|
6188
|
+
}
|
|
6189
|
+
return s;
|
|
6190
|
+
})
|
|
6191
|
+
};
|
|
6192
|
+
}
|
|
5992
6193
|
function embedScript(doc, dir) {
|
|
5993
6194
|
const path = join11(dir, "actions.json");
|
|
5994
6195
|
if (!existsSync10(path)) return;
|
|
5995
6196
|
const script = scriptFromText(readFileSync2(path, "utf8"));
|
|
5996
|
-
if (script) doc.source.script = script;
|
|
6197
|
+
if (script) doc.source.script = publicScript(script);
|
|
5997
6198
|
}
|
|
5998
6199
|
async function writeScriptBeside(dir, doc) {
|
|
5999
6200
|
const path = join11(dir, "actions.json");
|
|
@@ -6800,133 +7001,9 @@ import {
|
|
|
6800
7001
|
} from "@vosjs/core";
|
|
6801
7002
|
import { lowerProgramDoc, migrateHostedDoc as migrateHostedDoc3 } from "@vosjs/studio-core";
|
|
6802
7003
|
|
|
6803
|
-
// src/plugin/login.ts
|
|
6804
|
-
import { hostname } from "os";
|
|
6805
|
-
var LoginUnsupportedError = class extends Error {
|
|
6806
|
-
constructor() {
|
|
6807
|
-
super("this origin does not support browser login");
|
|
6808
|
-
}
|
|
6809
|
-
};
|
|
6810
|
-
var MAX_TRANSIENT_FAILURES = 5;
|
|
6811
|
-
var MAX_INTERVAL_MS = 3e4;
|
|
6812
|
-
async function launchDefaultBrowser(url) {
|
|
6813
|
-
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
6814
|
-
const { exec } = await import("child_process");
|
|
6815
|
-
exec(`${opener} ${JSON.stringify(url)}`, () => {
|
|
6816
|
-
});
|
|
6817
|
-
}
|
|
6818
|
-
async function browserLogin(origin, r, opts) {
|
|
6819
|
-
const create = await apiJson(origin, "/api/cli/login", {
|
|
6820
|
-
method: "POST",
|
|
6821
|
-
body: {
|
|
6822
|
-
hostname: hostname().slice(0, 64),
|
|
6823
|
-
...opts.label ? { label: opts.label.slice(0, 64) } : {}
|
|
6824
|
-
}
|
|
6825
|
-
});
|
|
6826
|
-
if (create.status === 404) throw new LoginUnsupportedError();
|
|
6827
|
-
if (create.status !== 201) throw new Error(apiError("start login", create));
|
|
6828
|
-
const code = create.body.code;
|
|
6829
|
-
const secret = create.body.secret;
|
|
6830
|
-
const verifyUrl = create.body.verifyUrl;
|
|
6831
|
-
const expiresAt = Date.parse(String(create.body.expiresAt ?? ""));
|
|
6832
|
-
const baseIntervalMs = (typeof create.body.interval === "number" ? create.body.interval : 3) * 1e3;
|
|
6833
|
-
if (!code || !secret || !verifyUrl || Number.isNaN(expiresAt)) {
|
|
6834
|
-
throw new Error("start login \u2192 malformed response from the platform");
|
|
6835
|
-
}
|
|
6836
|
-
r.event({ event: "login_await", url: verifyUrl, code, expiresAt });
|
|
6837
|
-
r.log(`Confirm this code in the browser: ${code}`);
|
|
6838
|
-
r.log(`Sign in at ${verifyUrl}`);
|
|
6839
|
-
if (opts.openBrowser) void launchDefaultBrowser(verifyUrl);
|
|
6840
|
-
r.log("Waiting for approval\u2026 (Ctrl-C to cancel)");
|
|
6841
|
-
const sleep = opts.sleep ?? ((ms) => new Promise((res) => setTimeout(res, ms)));
|
|
6842
|
-
let intervalMs = baseIntervalMs;
|
|
6843
|
-
let failures = 0;
|
|
6844
|
-
let capNoted = false;
|
|
6845
|
-
while (Date.now() < expiresAt) {
|
|
6846
|
-
await sleep(intervalMs);
|
|
6847
|
-
let res;
|
|
6848
|
-
try {
|
|
6849
|
-
res = await apiJson(origin, "/api/cli/login/poll", {
|
|
6850
|
-
method: "POST",
|
|
6851
|
-
body: { secret }
|
|
6852
|
-
});
|
|
6853
|
-
failures = 0;
|
|
6854
|
-
} catch (e) {
|
|
6855
|
-
if (++failures >= MAX_TRANSIENT_FAILURES) {
|
|
6856
|
-
throw new Error(
|
|
6857
|
-
`lost the connection while waiting (${e instanceof Error ? e.message : String(e)}) \u2014 run \`vos login\` again`
|
|
6858
|
-
);
|
|
6859
|
-
}
|
|
6860
|
-
continue;
|
|
6861
|
-
}
|
|
6862
|
-
const status = res.body.status;
|
|
6863
|
-
if (res.status === 200 && status === "pending") {
|
|
6864
|
-
intervalMs = baseIntervalMs;
|
|
6865
|
-
continue;
|
|
6866
|
-
}
|
|
6867
|
-
if (res.status === 200 && status === "ok") {
|
|
6868
|
-
const path = (opts.store ?? writeCredential)(res.body.key);
|
|
6869
|
-
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
6870
|
-
return { path, user };
|
|
6871
|
-
}
|
|
6872
|
-
if (res.status === 429) {
|
|
6873
|
-
if (status === "key_limit" && !capNoted) {
|
|
6874
|
-
capNoted = true;
|
|
6875
|
-
r.log(`${res.body.error} \u2014 ${res.body.hint}`);
|
|
6876
|
-
}
|
|
6877
|
-
intervalMs = Math.min(intervalMs * 2, MAX_INTERVAL_MS);
|
|
6878
|
-
continue;
|
|
6879
|
-
}
|
|
6880
|
-
if (res.status === 403 && status === "denied") {
|
|
6881
|
-
throw new Error("the sign-in was denied in the browser");
|
|
6882
|
-
}
|
|
6883
|
-
throw new Error(
|
|
6884
|
-
typeof res.body.error === "string" ? res.body.error : apiError("poll login", res)
|
|
6885
|
-
);
|
|
6886
|
-
}
|
|
6887
|
-
throw new Error(
|
|
6888
|
-
"no approval within 15 minutes \u2014 run `vos login` again, or mint a key at https://vos.so/app/api and pass --key"
|
|
6889
|
-
);
|
|
6890
|
-
}
|
|
6891
|
-
var HANDOFF_URL = /^(https?:\/\/[^/]+)\/h\/(vos_ho_[A-Za-z0-9_-]+)$/;
|
|
6892
|
-
function parseHandoffUrl(url) {
|
|
6893
|
-
const m = HANDOFF_URL.exec(url.trim());
|
|
6894
|
-
return m ? { origin: m[1], token: m[2] } : null;
|
|
6895
|
-
}
|
|
6896
|
-
async function handoffLogin(url, r, opts = {}) {
|
|
6897
|
-
const parsed = parseHandoffUrl(url);
|
|
6898
|
-
if (!parsed)
|
|
6899
|
-
throw new Error(
|
|
6900
|
-
"--handoff wants the link a person copied from vos.so, https://vos.so/h/vos_ho_\u2026"
|
|
6901
|
-
);
|
|
6902
|
-
r.log(`exchanging the setup link at ${parsed.origin}\u2026`);
|
|
6903
|
-
const res = await apiJson(parsed.origin, "/api/cli/login/exchange", {
|
|
6904
|
-
method: "POST",
|
|
6905
|
-
body: { token: parsed.token, hostname: hostname().slice(0, 64) }
|
|
6906
|
-
});
|
|
6907
|
-
if (res.status === 200 && res.body.status === "ok") {
|
|
6908
|
-
const path = (opts.store ?? writeCredential)(res.body.key);
|
|
6909
|
-
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
6910
|
-
return {
|
|
6911
|
-
path,
|
|
6912
|
-
user,
|
|
6913
|
-
keyName: String(res.body.keyName ?? ""),
|
|
6914
|
-
origin: parsed.origin
|
|
6915
|
-
};
|
|
6916
|
-
}
|
|
6917
|
-
if (res.status === 404 && !res.body.status) {
|
|
6918
|
-
throw new Error(
|
|
6919
|
-
`${parsed.origin} does not support setup links yet \u2014 run \`vos login\` instead`
|
|
6920
|
-
);
|
|
6921
|
-
}
|
|
6922
|
-
const said = typeof res.body.error === "string" ? res.body.error : apiError("exchange", res);
|
|
6923
|
-
const hint = typeof res.body.hint === "string" ? ` ${res.body.hint}` : "";
|
|
6924
|
-
throw new Error(`${said}${hint}`);
|
|
6925
|
-
}
|
|
6926
|
-
|
|
6927
7004
|
// src/plugin/programFiles.ts
|
|
6928
7005
|
import { basename as basename2, extname as extname2, relative as relative2 } from "path";
|
|
6929
|
-
import { existsSync as existsSync12, realpathSync } from "fs";
|
|
7006
|
+
import { existsSync as existsSync12, realpathSync as realpathSync2 } from "fs";
|
|
6930
7007
|
function isLocalName(value) {
|
|
6931
7008
|
if (/^(https?:|data:|blob:|asset:|media:)/.test(value)) return false;
|
|
6932
7009
|
if (value.startsWith("$")) return false;
|
|
@@ -6978,7 +7055,7 @@ function liftNamedFiles(config, dir) {
|
|
|
6978
7055
|
}
|
|
6979
7056
|
function localDataRefs(config, dir) {
|
|
6980
7057
|
const refs = [];
|
|
6981
|
-
const root =
|
|
7058
|
+
const root = realpathSync2(dir);
|
|
6982
7059
|
const walk = (value, where, set) => {
|
|
6983
7060
|
if (typeof value === "string") {
|
|
6984
7061
|
if (!isLocalName(value) || !FILE_EXT.test(value)) return;
|
|
@@ -8493,7 +8570,7 @@ function trackingCwd(vosId) {
|
|
|
8493
8570
|
|
|
8494
8571
|
// src/plugin/buildProgram.ts
|
|
8495
8572
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
8496
|
-
import { basename as basename5, dirname as dirname3, join as join16, resolve as
|
|
8573
|
+
import { basename as basename5, dirname as dirname3, join as join16, resolve as resolve6 } from "path";
|
|
8497
8574
|
import { pathToFileURL } from "url";
|
|
8498
8575
|
import { parse } from "acorn";
|
|
8499
8576
|
import { fullAncestor } from "acorn-walk";
|
|
@@ -8693,7 +8770,7 @@ async function cmdBuild(argv) {
|
|
|
8693
8770
|
if (!source)
|
|
8694
8771
|
throw new UsageError("vos build <program.mjs> [--out config.json] [--json]");
|
|
8695
8772
|
const r = createReporter(flags.json === true);
|
|
8696
|
-
const file =
|
|
8773
|
+
const file = resolve6(source);
|
|
8697
8774
|
const text = readFileSync5(file, "utf8");
|
|
8698
8775
|
const mod = await import(`${pathToFileURL(file).href}?t=${Date.now()}`);
|
|
8699
8776
|
const program = mod.default ?? mod.program;
|
|
@@ -8710,7 +8787,7 @@ async function cmdBuild(argv) {
|
|
|
8710
8787
|
);
|
|
8711
8788
|
return EXIT_ERROR;
|
|
8712
8789
|
}
|
|
8713
|
-
const out =
|
|
8790
|
+
const out = resolve6(
|
|
8714
8791
|
strFlag(flags, "out") ?? join16(dirname3(file), "config.json")
|
|
8715
8792
|
);
|
|
8716
8793
|
writeFileSync2(out, JSON.stringify(built.config, null, 2) + "\n");
|
|
@@ -8729,7 +8806,7 @@ async function cmdBuild(argv) {
|
|
|
8729
8806
|
// src/plugin/compare.ts
|
|
8730
8807
|
import { spawnSync } from "child_process";
|
|
8731
8808
|
import { existsSync as existsSync15, mkdirSync as mkdirSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
8732
|
-
import { dirname as dirname4, join as join17, resolve as
|
|
8809
|
+
import { dirname as dirname4, join as join17, resolve as resolve7 } from "path";
|
|
8733
8810
|
var BOOLEAN_FLAGS7 = /* @__PURE__ */ new Set(["json", "help"]);
|
|
8734
8811
|
function sampleTimes(duration, every) {
|
|
8735
8812
|
const step = every > 0 ? every : 1;
|
|
@@ -8790,7 +8867,7 @@ async function cmdCompare(argv) {
|
|
|
8790
8867
|
);
|
|
8791
8868
|
requireFfmpeg();
|
|
8792
8869
|
const r = createReporter(flags.json === true);
|
|
8793
|
-
const ref =
|
|
8870
|
+
const ref = resolve7(against);
|
|
8794
8871
|
const loaded = await loadVosConfig(source);
|
|
8795
8872
|
for (const w of loaded.warnings) r.log(`note: ${w}`);
|
|
8796
8873
|
const config = loaded.config;
|
|
@@ -8812,7 +8889,7 @@ async function cmdCompare(argv) {
|
|
|
8812
8889
|
const threshold = Number(strFlag(flags, "threshold") ?? 0.95);
|
|
8813
8890
|
const timesRaw = strFlag(flags, "times");
|
|
8814
8891
|
const times = timesRaw ? parseTimes(timesRaw, duration) : sampleTimes(duration, Number(strFlag(flags, "every") ?? 1));
|
|
8815
|
-
const outDir =
|
|
8892
|
+
const outDir = resolve7(strFlag(flags, "out") ?? "compare");
|
|
8816
8893
|
mkdirSync2(outDir, { recursive: true });
|
|
8817
8894
|
const browser = await launchBrowser();
|
|
8818
8895
|
const scores = [];
|
|
@@ -8916,7 +8993,7 @@ async function cmdCompare(argv) {
|
|
|
8916
8993
|
|
|
8917
8994
|
// src/plugin/port.ts
|
|
8918
8995
|
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
8919
|
-
import { dirname as dirname7, join as join21, resolve as
|
|
8996
|
+
import { dirname as dirname7, join as join21, resolve as resolve10 } from "path";
|
|
8920
8997
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
8921
8998
|
|
|
8922
8999
|
// src/plugin/portInventory.ts
|
|
@@ -8928,7 +9005,7 @@ import {
|
|
|
8928
9005
|
readdirSync as readdirSync4,
|
|
8929
9006
|
statSync as statSync6
|
|
8930
9007
|
} from "fs";
|
|
8931
|
-
import { dirname as dirname5, join as join19, relative as relative3, resolve as
|
|
9008
|
+
import { dirname as dirname5, join as join19, relative as relative3, resolve as resolve8 } from "path";
|
|
8932
9009
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
8933
9010
|
import { findFontFamily as findFontFamily3 } from "@vosjs/shared";
|
|
8934
9011
|
|
|
@@ -9551,7 +9628,7 @@ var SEEK_AND_READ = `((args) => {
|
|
|
9551
9628
|
return out
|
|
9552
9629
|
})`;
|
|
9553
9630
|
async function readInventory(source, opts) {
|
|
9554
|
-
const abs =
|
|
9631
|
+
const abs = resolve8(source);
|
|
9555
9632
|
const dir = existsSync17(abs) && statSync6(abs).isDirectory() ? abs : dirname5(abs);
|
|
9556
9633
|
const engine = detectEngine(dir);
|
|
9557
9634
|
const page = sourcePage(abs);
|
|
@@ -9719,7 +9796,7 @@ async function readInventory(source, opts) {
|
|
|
9719
9796
|
// src/plugin/portScaffold.ts
|
|
9720
9797
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
9721
9798
|
import { copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
9722
|
-
import { basename as basename7, dirname as dirname6, join as join20, resolve as
|
|
9799
|
+
import { basename as basename7, dirname as dirname6, join as join20, resolve as resolve9 } from "path";
|
|
9723
9800
|
import { findFontFamily as findFontFamily4, fontFaceUrl, nearestFontWeight } from "@vosjs/shared";
|
|
9724
9801
|
|
|
9725
9802
|
// src/plugin/painterLib.ts
|
|
@@ -10128,7 +10205,7 @@ function planScaffold(inv, opts) {
|
|
|
10128
10205
|
const audio = [];
|
|
10129
10206
|
const copies = [];
|
|
10130
10207
|
inv.media.filter((m) => m.kind === "audio" && m.src).forEach((m, i) => {
|
|
10131
|
-
const from =
|
|
10208
|
+
const from = resolve9(opts.sourceDir, m.src);
|
|
10132
10209
|
const name = basename7(from);
|
|
10133
10210
|
if (!existsSync18(from)) {
|
|
10134
10211
|
report.push(
|
|
@@ -10181,9 +10258,18 @@ function planScaffold(inv, opts) {
|
|
|
10181
10258
|
}
|
|
10182
10259
|
function programSource(p) {
|
|
10183
10260
|
const j = (v) => JSON.stringify(v, null, 2).replace(/\n/g, "\n ");
|
|
10184
|
-
const
|
|
10185
|
-
|
|
10186
|
-
|
|
10261
|
+
const word = (v) => JSON.stringify(
|
|
10262
|
+
Array.from(String(v), (ch) => {
|
|
10263
|
+
const code = ch.charCodeAt(0);
|
|
10264
|
+
return code < 32 || code === 8232 || code === 8233 ? " " : ch;
|
|
10265
|
+
}).join("")
|
|
10266
|
+
);
|
|
10267
|
+
const secs = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
10268
|
+
const sceneTodos = p.scenes.length ? p.scenes.map((s) => {
|
|
10269
|
+
const start = secs(s.start) ?? 0;
|
|
10270
|
+
const duration = secs(s.duration);
|
|
10271
|
+
return ` // TODO scene ${word(s.name)} (${start}s${duration ? ` to ${start + duration}s` : ""}): translate its motion onto ctx.elements.get(id).props / .segments here`;
|
|
10272
|
+
}).join("\n") : " // TODO: translate the source's motion here, one block per scene (tl.addLabel above names them)";
|
|
10187
10273
|
const springHint = p.uses.includes("spring") ? `
|
|
10188
10274
|
// The source springs. Put a spring ON THE TIMELINE with the spring ease:
|
|
10189
10275
|
// tl.to(p, { y: 0, ease: 'spring(200)', duration: content.refs.lib.springSeconds({ damping: 200 }) }, at)
|
|
@@ -10360,11 +10446,11 @@ async function inventory(argv) {
|
|
|
10360
10446
|
const { positionals, flags } = parseArgs(argv, BOOLEAN_FLAGS8);
|
|
10361
10447
|
const source = positionals[0] ?? ".";
|
|
10362
10448
|
const r = createReporter(flags.json === true);
|
|
10363
|
-
const outDir =
|
|
10449
|
+
const outDir = resolve10(strFlag(flags, "out") ?? "port");
|
|
10364
10450
|
mkdirSync5(outDir, { recursive: true });
|
|
10365
10451
|
const renderFlag = strFlag(flags, "render");
|
|
10366
10452
|
const inv = await readInventory(source, {
|
|
10367
|
-
render: renderFlag === void 0 ? void 0 :
|
|
10453
|
+
render: renderFlag === void 0 ? void 0 : resolve10(renderFlag),
|
|
10368
10454
|
outDir,
|
|
10369
10455
|
log: (l) => r.log(`note: ${l}`)
|
|
10370
10456
|
});
|
|
@@ -10400,13 +10486,13 @@ function summary(inv) {
|
|
|
10400
10486
|
async function scaffold(argv) {
|
|
10401
10487
|
const { flags } = parseArgs(argv, BOOLEAN_FLAGS8);
|
|
10402
10488
|
const r = createReporter(flags.json === true);
|
|
10403
|
-
const from =
|
|
10489
|
+
const from = resolve10(strFlag(flags, "from") ?? join21("port", "inventory.json"));
|
|
10404
10490
|
if (!existsSync19(from))
|
|
10405
10491
|
throw new UsageError(
|
|
10406
10492
|
`no inventory at ${from}: run npx vos port inventory <source> first`
|
|
10407
10493
|
);
|
|
10408
10494
|
const inv = JSON.parse(readFileSync8(from, "utf8"));
|
|
10409
|
-
const outDir =
|
|
10495
|
+
const outDir = resolve10(
|
|
10410
10496
|
strFlag(flags, "out") ?? join21(dirname7(from), "program")
|
|
10411
10497
|
);
|
|
10412
10498
|
const plan = planScaffold(inv, {
|
|
@@ -10431,7 +10517,7 @@ async function scaffold(argv) {
|
|
|
10431
10517
|
}
|
|
10432
10518
|
function scaffoldSourceDir(inv) {
|
|
10433
10519
|
if (inv.root) return inv.root;
|
|
10434
|
-
return inv.source.endsWith(".html") ? dirname7(
|
|
10520
|
+
return inv.source.endsWith(".html") ? dirname7(resolve10(inv.source)) : resolve10(inv.source);
|
|
10435
10521
|
}
|
|
10436
10522
|
|
|
10437
10523
|
// src/plugin/recipe.ts
|
|
@@ -10523,7 +10609,7 @@ async function cmdRecipe(argv) {
|
|
|
10523
10609
|
|
|
10524
10610
|
// src/plugin/brand.ts
|
|
10525
10611
|
import { writeFile as writeFile10 } from "fs/promises";
|
|
10526
|
-
import { resolve as
|
|
10612
|
+
import { resolve as resolve11 } from "path";
|
|
10527
10613
|
import { parseFrontmatter as parseFrontmatter2 } from "@vosjs/shared/frontmatter";
|
|
10528
10614
|
import { lookKindForGround } from "@vosjs/studio-core";
|
|
10529
10615
|
var HEX_RE = /#(?:[0-9a-f]{6}|[0-9a-f]{3})\b/gi;
|
|
@@ -10842,7 +10928,7 @@ async function cmdBrand(argv) {
|
|
|
10842
10928
|
throw new UsageError(`not a URL: ${raw}`);
|
|
10843
10929
|
}
|
|
10844
10930
|
const r = createReporter(flags.json === true);
|
|
10845
|
-
const out =
|
|
10931
|
+
const out = resolve11(strFlag(flags, "out") ?? "BRAND.md");
|
|
10846
10932
|
r.log(`reading ${origin}/design.md and /llms.txt\u2026`);
|
|
10847
10933
|
const [designText, llmsText] = await Promise.all([
|
|
10848
10934
|
fetchText(`${origin}/design.md`),
|
|
@@ -10992,7 +11078,7 @@ async function recordHosted(input) {
|
|
|
10992
11078
|
|
|
10993
11079
|
// src/plugin/agentBrowser.ts
|
|
10994
11080
|
import { writeFile as writeFile11 } from "fs/promises";
|
|
10995
|
-
import { resolve as
|
|
11081
|
+
import { resolve as resolve12 } from "path";
|
|
10996
11082
|
function parseAgentBrowserLog(text) {
|
|
10997
11083
|
const records = [];
|
|
10998
11084
|
const problems = [];
|
|
@@ -11463,7 +11549,7 @@ async function cmdActions(argv) {
|
|
|
11463
11549
|
);
|
|
11464
11550
|
}
|
|
11465
11551
|
const r = createReporter(flags.json === true);
|
|
11466
|
-
const out =
|
|
11552
|
+
const out = resolve12(strFlag(flags, "out") ?? "actions.json");
|
|
11467
11553
|
const viewportFlag = strFlag(flags, "viewport");
|
|
11468
11554
|
let viewport;
|
|
11469
11555
|
if (viewportFlag) {
|
|
@@ -11472,7 +11558,7 @@ async function cmdActions(argv) {
|
|
|
11472
11558
|
viewport = { width: Number(m[1]), height: Number(m[2]) };
|
|
11473
11559
|
}
|
|
11474
11560
|
const { readFile: readFile14 } = await import("fs/promises");
|
|
11475
|
-
const text = await readFile14(
|
|
11561
|
+
const text = await readFile14(resolve12(input), "utf8");
|
|
11476
11562
|
const { records, problems } = parseAgentBrowserLog(text);
|
|
11477
11563
|
for (const p of problems) r.log(` ${p}`);
|
|
11478
11564
|
const result = convertAgentBrowser(records, {
|
|
@@ -11511,7 +11597,7 @@ async function cmdActionsScript(input, flags) {
|
|
|
11511
11597
|
const r = createReporter(flags.json === true);
|
|
11512
11598
|
const { readFile: readFile14 } = await import("fs/promises");
|
|
11513
11599
|
const { shotList, formatShotList } = await import("./shotList-MAQVLZBY.js");
|
|
11514
|
-
const raw = JSON.parse(await readFile14(
|
|
11600
|
+
const raw = JSON.parse(await readFile14(resolve12(input), "utf8"));
|
|
11515
11601
|
const errors = validateActions(raw);
|
|
11516
11602
|
if (errors.length) throw new UsageError(`${input}:
|
|
11517
11603
|
${errors.join("\n ")}`);
|
|
@@ -11523,7 +11609,7 @@ async function cmdActionsScript(input, flags) {
|
|
|
11523
11609
|
// src/plugin/ingest.ts
|
|
11524
11610
|
import { existsSync as existsSync20 } from "fs";
|
|
11525
11611
|
import { copyFile, mkdir as mkdir7, readFile as readFile12, stat as stat2 } from "fs/promises";
|
|
11526
|
-
import { basename as basename9, join as join22, resolve as
|
|
11612
|
+
import { basename as basename9, join as join22, resolve as resolve13 } from "path";
|
|
11527
11613
|
import { inflateRawSync } from "zlib";
|
|
11528
11614
|
import {
|
|
11529
11615
|
cursorFromPlaywrightTrace,
|
|
@@ -11640,10 +11726,10 @@ async function cmdIngest(argv) {
|
|
|
11640
11726
|
throw new UsageError(
|
|
11641
11727
|
"vos ingest <video.webm|mp4> [--cursor <trace.zip|steps.jsonl|cursor.csv>] [--as footage|take] [--out take] [--offset <ms>] [--viewport WxH] [--background <slug|url|none>] [--json]"
|
|
11642
11728
|
);
|
|
11643
|
-
const videoPath =
|
|
11729
|
+
const videoPath = resolve13(source);
|
|
11644
11730
|
if (!existsSync20(videoPath)) throw new UsageError(`${source}: no such file`);
|
|
11645
11731
|
const r = createReporter(flags.json === true);
|
|
11646
|
-
const outDir =
|
|
11732
|
+
const outDir = resolve13(strFlag(flags, "out") ?? "take");
|
|
11647
11733
|
const offsetMs = numFlag(flags, "offset", 0);
|
|
11648
11734
|
const viewportFlag = parseViewport(strFlag(flags, "viewport"));
|
|
11649
11735
|
const cursorPath = strFlag(flags, "cursor");
|
|
@@ -11665,7 +11751,7 @@ async function cmdIngest(argv) {
|
|
|
11665
11751
|
}
|
|
11666
11752
|
let trace = null;
|
|
11667
11753
|
if (cursorPath) {
|
|
11668
|
-
trace = await readTraceFile(
|
|
11754
|
+
trace = await readTraceFile(resolve13(cursorPath), offsetMs);
|
|
11669
11755
|
for (const n of trace.notes) r.log(`note: ${n}`);
|
|
11670
11756
|
}
|
|
11671
11757
|
if (existsSync20(join22(outDir, "meta.json"))) {
|
|
@@ -12670,7 +12756,7 @@ function takeBrowserArgs(multi) {
|
|
|
12670
12756
|
function takeStorageState(flags) {
|
|
12671
12757
|
const raw = strFlag(flags, "storage-state");
|
|
12672
12758
|
if (!raw) return void 0;
|
|
12673
|
-
const path =
|
|
12759
|
+
const path = resolve14(raw);
|
|
12674
12760
|
if (!existsSync23(path))
|
|
12675
12761
|
throw new UsageError(`--storage-state: no such file: ${path}`);
|
|
12676
12762
|
return path;
|
|
@@ -12753,7 +12839,7 @@ async function cmdRecord(argv) {
|
|
|
12753
12839
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
12754
12840
|
if (!url)
|
|
12755
12841
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
12756
|
-
const outDir =
|
|
12842
|
+
const outDir = resolve14(strFlag(flags, "out") ?? "take");
|
|
12757
12843
|
const storageState = takeStorageState(flags);
|
|
12758
12844
|
const sessionName = takeSessionName(flags, storageState);
|
|
12759
12845
|
const browserArgs = takeBrowserArgs(multi);
|
|
@@ -12880,7 +12966,9 @@ async function cmdRecord(argv) {
|
|
|
12880
12966
|
const carried = [
|
|
12881
12967
|
...strFlag(flags, "storage-state") ? [`--storage-state ${strFlag(flags, "storage-state")}`] : [],
|
|
12882
12968
|
...browserArgs.map((a) => `--browser-arg=${a}`),
|
|
12883
|
-
|
|
12969
|
+
// A header value is a bypass token more often than not: named, never
|
|
12970
|
+
// printed.
|
|
12971
|
+
...Object.keys(headers).map((k) => `--header ${k}=\u2026`),
|
|
12884
12972
|
...sessionName ? [`--session ${sessionName}`] : [],
|
|
12885
12973
|
...flags["allow-wall"] === true ? ["--allow-wall"] : []
|
|
12886
12974
|
].join(" ");
|
|
@@ -12996,7 +13084,7 @@ async function cmdCreate2(argv) {
|
|
|
12996
13084
|
const url = strFlag(flags, "url") ?? actions.url;
|
|
12997
13085
|
if (!url)
|
|
12998
13086
|
throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
|
|
12999
|
-
const outDir =
|
|
13087
|
+
const outDir = resolve14(strFlag(flags, "out") ?? "take");
|
|
13000
13088
|
const format = videoFormat(strFlag(flags, "format"), positionals[0]);
|
|
13001
13089
|
const out = positionals[0] ?? join25(outDir, `out.${format}`);
|
|
13002
13090
|
const parallel = numFlag(flags, "parallel", 1);
|
|
@@ -13123,7 +13211,7 @@ async function cmdPlan(argv) {
|
|
|
13123
13211
|
}
|
|
13124
13212
|
let reuse;
|
|
13125
13213
|
if (flags.reuse === true) {
|
|
13126
|
-
const from =
|
|
13214
|
+
const from = resolve14(strFlag(flags, "from") ?? join25(dir, PREV_DOC_NAME));
|
|
13127
13215
|
if (!existsSync23(from)) {
|
|
13128
13216
|
throw new UsageError(
|
|
13129
13217
|
`--reuse: ${from} does not exist \u2014 a re-record into this take writes doc.prev.json, or pass --from <doc.json>`
|
|
@@ -13181,7 +13269,7 @@ async function cmdPlan(argv) {
|
|
|
13181
13269
|
${s.reuse.flagged.join("\n ")}` : "") : "";
|
|
13182
13270
|
r.done(
|
|
13183
13271
|
{
|
|
13184
|
-
take:
|
|
13272
|
+
take: resolve14(dir),
|
|
13185
13273
|
fresh: s.fresh,
|
|
13186
13274
|
cursorKept: s.cursorKept,
|
|
13187
13275
|
zoomAuto: s.zoomAuto,
|
|
@@ -13547,7 +13635,7 @@ async function resolveStyleRef(flags) {
|
|
|
13547
13635
|
}
|
|
13548
13636
|
async function resolveDocRef(ref, flags, what) {
|
|
13549
13637
|
const styleRef = ref;
|
|
13550
|
-
const file = existsSync23(styleRef) ?
|
|
13638
|
+
const file = existsSync23(styleRef) ? resolve14(
|
|
13551
13639
|
styleRef,
|
|
13552
13640
|
existsSync23(join25(styleRef, "doc.json")) ? "doc.json" : ""
|
|
13553
13641
|
) : null;
|
|
@@ -13673,7 +13761,7 @@ async function cmdOpen(argv) {
|
|
|
13673
13761
|
/\/+$/,
|
|
13674
13762
|
""
|
|
13675
13763
|
);
|
|
13676
|
-
const server = await startTakeServer(
|
|
13764
|
+
const server = await startTakeServer(resolve14(dir), {});
|
|
13677
13765
|
const url = `${studio}/studio?take=${encodeURIComponent(server.base)}`;
|
|
13678
13766
|
r.event({ event: "open", server: server.base, url });
|
|
13679
13767
|
r.log(`take served at ${server.base}`);
|
|
@@ -13681,10 +13769,7 @@ async function cmdOpen(argv) {
|
|
|
13681
13769
|
`);
|
|
13682
13770
|
if (flags.print !== true) {
|
|
13683
13771
|
r.log("opening the studio\u2026 (Ctrl-C to stop serving)");
|
|
13684
|
-
|
|
13685
|
-
const { exec } = await import("child_process");
|
|
13686
|
-
exec(`${opener} ${JSON.stringify(url)}`, () => {
|
|
13687
|
-
});
|
|
13772
|
+
await launchDefaultBrowser(url);
|
|
13688
13773
|
} else {
|
|
13689
13774
|
r.log("serving (\u2014 --print: not launching a browser; Ctrl-C to stop)");
|
|
13690
13775
|
}
|
|
@@ -13970,7 +14055,7 @@ async function cmdPush3(argv) {
|
|
|
13970
14055
|
);
|
|
13971
14056
|
const refusal = takePushRefusal({
|
|
13972
14057
|
vos: strFlag(flags, "vos"),
|
|
13973
|
-
trackedVosId: readSyncState(
|
|
14058
|
+
trackedVosId: readSyncState(resolve14(dir))?.vosId ?? null,
|
|
13974
14059
|
programOnly: ["slug", "desc", "tags", "base", "remix-of", "still"].filter(
|
|
13975
14060
|
(name) => hasFlag(flags, name)
|
|
13976
14061
|
)
|
|
@@ -13986,7 +14071,7 @@ async function cmdPush3(argv) {
|
|
|
13986
14071
|
`--claimable creates a NEW claimable vos; ${iterating.map((f) => `--${f}`).join(", ")} ${iterating.length > 1 ? "apply" : "applies"} to a keyed push`
|
|
13987
14072
|
);
|
|
13988
14073
|
const claim = await pushTakeClaimable(
|
|
13989
|
-
|
|
14074
|
+
resolve14(dir),
|
|
13990
14075
|
{
|
|
13991
14076
|
api: strFlag(flags, "api"),
|
|
13992
14077
|
origin: strFlag(flags, "origin"),
|
|
@@ -14008,7 +14093,7 @@ reference and the only credential.`
|
|
|
14008
14093
|
}
|
|
14009
14094
|
const overrides = multi.override;
|
|
14010
14095
|
const result = await pushTake(
|
|
14011
|
-
|
|
14096
|
+
resolve14(dir),
|
|
14012
14097
|
{
|
|
14013
14098
|
key: strFlag(flags, "key"),
|
|
14014
14099
|
api: strFlag(flags, "api"),
|
|
@@ -14062,7 +14147,7 @@ async function cmdPull2(argv) {
|
|
|
14062
14147
|
const dir = positionals[0] ?? ".";
|
|
14063
14148
|
const r = createReporter(flags.json === true);
|
|
14064
14149
|
const result = await pullTake(
|
|
14065
|
-
|
|
14150
|
+
resolve14(dir),
|
|
14066
14151
|
{
|
|
14067
14152
|
key: strFlag(flags, "key"),
|
|
14068
14153
|
api: strFlag(flags, "api"),
|
|
@@ -14362,4 +14447,4 @@ export {
|
|
|
14362
14447
|
verbHelp,
|
|
14363
14448
|
run
|
|
14364
14449
|
};
|
|
14365
|
-
//# sourceMappingURL=chunk-
|
|
14450
|
+
//# sourceMappingURL=chunk-X6NQNBDF.js.map
|