@vosjs/cli 0.85.0 → 0.87.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 +7 -6
- package/dist/{assetManifest-32VI7OK7.js → assetManifest-UUKFWTLO.js} +3 -3
- package/dist/{chunk-M5ZBQFPG.js → chunk-2UFNOKVY.js} +2 -2
- package/dist/{chunk-PF2NEZYU.js → chunk-7A3PZARL.js} +10 -3
- package/dist/{chunk-PF2NEZYU.js.map → chunk-7A3PZARL.js.map} +1 -1
- package/dist/{chunk-NJBUBXFE.js → chunk-ACWV3Y6Y.js} +349 -84
- package/dist/chunk-ACWV3Y6Y.js.map +1 -0
- package/dist/{chunk-Q47FUCYN.js → chunk-EXDMMAPT.js} +2 -2
- package/dist/{chunk-EPSYIF2S.js → chunk-PEW5GIZF.js} +361 -58
- package/dist/chunk-PEW5GIZF.js.map +1 -0
- package/dist/cli.js +7 -7
- package/dist/index.d.ts +42 -6
- package/dist/index.js +5 -5
- package/dist/manifest-OLVFUZTW.js +8 -0
- package/dist/{run-XFKADM6I.js → run-OT54QJ4T.js} +5 -5
- package/package.json +2 -2
- 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-EPSYIF2S.js.map +0 -1
- package/dist/chunk-NJBUBXFE.js.map +0 -1
- package/dist/manifest-GPE4CVDR.js +0 -8
- /package/dist/{assetManifest-32VI7OK7.js.map → assetManifest-UUKFWTLO.js.map} +0 -0
- /package/dist/{chunk-M5ZBQFPG.js.map → chunk-2UFNOKVY.js.map} +0 -0
- /package/dist/{chunk-Q47FUCYN.js.map → chunk-EXDMMAPT.js.map} +0 -0
- /package/dist/{manifest-GPE4CVDR.js.map → manifest-OLVFUZTW.js.map} +0 -0
- /package/dist/{run-XFKADM6I.js.map → run-OT54QJ4T.js.map} +0 -0
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
reencodeStill,
|
|
11
11
|
renderStill,
|
|
12
12
|
videoFormat
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EXDMMAPT.js";
|
|
14
14
|
import {
|
|
15
15
|
PREV_DOC_NAME,
|
|
16
16
|
PasteFileRefusal,
|
|
@@ -46,47 +46,64 @@ import {
|
|
|
46
46
|
uploadDocRefs,
|
|
47
47
|
uploadManifest,
|
|
48
48
|
writeJson
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-2UFNOKVY.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
|
+
credentialAccount,
|
|
66
|
+
credentialFlags,
|
|
60
67
|
deriveSlug,
|
|
61
68
|
detailLine,
|
|
69
|
+
findStored,
|
|
62
70
|
formatChanges,
|
|
63
71
|
hasFlag,
|
|
64
72
|
hostedAssetId,
|
|
73
|
+
isActive,
|
|
74
|
+
lastCredential,
|
|
75
|
+
listStored,
|
|
65
76
|
localFile,
|
|
66
77
|
manifestRefs,
|
|
67
78
|
mintAt,
|
|
68
79
|
nameForType,
|
|
69
80
|
numFlag2 as numFlag,
|
|
81
|
+
originOf,
|
|
70
82
|
parseArgs2 as parseArgs,
|
|
71
83
|
parseVosId,
|
|
72
84
|
platformOrigin,
|
|
73
85
|
prepareOutput,
|
|
74
86
|
programAssets,
|
|
75
87
|
promptHint,
|
|
88
|
+
readActive,
|
|
76
89
|
readSyncState,
|
|
77
90
|
refuseSymlink,
|
|
91
|
+
removeAll,
|
|
92
|
+
removeStored,
|
|
78
93
|
requireCredential,
|
|
79
94
|
resolveCredential,
|
|
80
95
|
resolveMediaType,
|
|
81
96
|
serverWarnings,
|
|
82
97
|
sniffMediaType,
|
|
83
98
|
strFlag,
|
|
99
|
+
switchTarget,
|
|
100
|
+
syncIdentity,
|
|
84
101
|
writeCredential,
|
|
85
102
|
writeFileSafe,
|
|
86
103
|
writeOutput,
|
|
87
104
|
writeOutputSync,
|
|
88
105
|
writeSyncState
|
|
89
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-PEW5GIZF.js";
|
|
90
107
|
import {
|
|
91
108
|
deadLine,
|
|
92
109
|
deadWarns
|
|
@@ -4856,6 +4873,7 @@ async function deliverTake(browser, dir, opts) {
|
|
|
4856
4873
|
|
|
4857
4874
|
// src/plugin/login.ts
|
|
4858
4875
|
import { hostname } from "os";
|
|
4876
|
+
var storeWith = (store) => store ?? ((key, origin, account) => writeCredential(key, origin, void 0, account));
|
|
4859
4877
|
var LoginUnsupportedError = class extends Error {
|
|
4860
4878
|
constructor() {
|
|
4861
4879
|
super("this origin does not support browser login");
|
|
@@ -4932,12 +4950,14 @@ async function browserLogin(origin, r, opts) {
|
|
|
4932
4950
|
continue;
|
|
4933
4951
|
}
|
|
4934
4952
|
if (res.status === 200 && status === "ok") {
|
|
4935
|
-
const
|
|
4953
|
+
const account = accountFrom(res.body.user);
|
|
4954
|
+
const path = storeWith(opts.store)(
|
|
4936
4955
|
res.body.key,
|
|
4937
|
-
origin
|
|
4956
|
+
origin,
|
|
4957
|
+
account
|
|
4938
4958
|
);
|
|
4939
4959
|
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4940
|
-
return { path, user };
|
|
4960
|
+
return { path, user, account };
|
|
4941
4961
|
}
|
|
4942
4962
|
if (res.status === 429) {
|
|
4943
4963
|
if (status === "key_limit" && !capNoted) {
|
|
@@ -4975,16 +4995,19 @@ async function handoffLogin(url, r, opts = {}) {
|
|
|
4975
4995
|
body: { token: parsed.token, hostname: hostname().slice(0, 64) }
|
|
4976
4996
|
});
|
|
4977
4997
|
if (res.status === 200 && res.body.status === "ok") {
|
|
4978
|
-
const
|
|
4998
|
+
const account = accountFrom(res.body.user);
|
|
4999
|
+
const path = storeWith(opts.store)(
|
|
4979
5000
|
res.body.key,
|
|
4980
|
-
parsed.origin
|
|
5001
|
+
parsed.origin,
|
|
5002
|
+
account
|
|
4981
5003
|
);
|
|
4982
5004
|
const user = typeof res.body.user === "object" && res.body.user !== null ? res.body.user.name ?? "" : "";
|
|
4983
5005
|
return {
|
|
4984
5006
|
path,
|
|
4985
5007
|
user,
|
|
4986
5008
|
keyName: String(res.body.keyName ?? ""),
|
|
4987
|
-
origin: parsed.origin
|
|
5009
|
+
origin: parsed.origin,
|
|
5010
|
+
account
|
|
4988
5011
|
};
|
|
4989
5012
|
}
|
|
4990
5013
|
if (res.status === 404 && !res.body.status) {
|
|
@@ -7445,7 +7468,7 @@ async function planTake(dir, opts = {}) {
|
|
|
7445
7468
|
import { createHash } from "crypto";
|
|
7446
7469
|
import { existsSync as existsSync13, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
7447
7470
|
import { readFile as readFile11 } from "fs/promises";
|
|
7448
|
-
import { createInterface as
|
|
7471
|
+
import { createInterface as createInterface3 } from "readline/promises";
|
|
7449
7472
|
import { basename as basename3, join as join14 } from "path";
|
|
7450
7473
|
import { lowerToComposition as lowerToComposition3, migrateHostedDoc as migrateHostedDoc2 } from "@vosjs/studio-core";
|
|
7451
7474
|
|
|
@@ -7526,6 +7549,7 @@ import { mkdir as mkdir6 } from "fs/promises";
|
|
|
7526
7549
|
import { join as join13 } from "path";
|
|
7527
7550
|
import { recipeHints } from "@vosjs/shared/frontmatter";
|
|
7528
7551
|
import { migrateHostedDoc } from "@vosjs/studio-core";
|
|
7552
|
+
import { createInterface as createInterface2 } from "readline/promises";
|
|
7529
7553
|
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["json", "help", "media"]);
|
|
7530
7554
|
async function listFolders(origin, key) {
|
|
7531
7555
|
const r = await apiJson(origin, "/api/folders", { key });
|
|
@@ -7546,7 +7570,18 @@ function projectAddress(ref) {
|
|
|
7546
7570
|
);
|
|
7547
7571
|
return m ? { handle: m[1], slug: m[2].toLowerCase() } : null;
|
|
7548
7572
|
}
|
|
7549
|
-
|
|
7573
|
+
function startFromVerdict(at2, mine) {
|
|
7574
|
+
const owner = at2.handle.toLowerCase();
|
|
7575
|
+
const asks = mine !== null && (!mine.handle || mine.handle.toLowerCase() !== owner);
|
|
7576
|
+
const who = mine ? accountLabel(mine) : "this credential";
|
|
7577
|
+
const address = `@${at2.handle}/${at2.slug}`;
|
|
7578
|
+
return {
|
|
7579
|
+
asks,
|
|
7580
|
+
question: `Pushing to ${address} as ${who} would START your own copy of it (its recipes copied in), not continue it. Continue?`,
|
|
7581
|
+
refusal: `vos push --folder ${address} as ${who} would start your own copy of it, not continue it: run it as @${at2.handle} (vos switch ${at2.handle}, or --account ${at2.handle}), or pass --yes to start the copy`
|
|
7582
|
+
};
|
|
7583
|
+
}
|
|
7584
|
+
async function resolvePushFolder(origin, key, ref, opts = {}) {
|
|
7550
7585
|
const at2 = projectAddress(ref);
|
|
7551
7586
|
if (!at2) {
|
|
7552
7587
|
return {
|
|
@@ -7554,6 +7589,15 @@ async function resolvePushFolder(origin, key, ref) {
|
|
|
7554
7589
|
note: null
|
|
7555
7590
|
};
|
|
7556
7591
|
}
|
|
7592
|
+
const mine = await credentialAccount(origin, key);
|
|
7593
|
+
const start = startFromVerdict(at2, mine);
|
|
7594
|
+
if (start.asks && !opts.yes) {
|
|
7595
|
+
if (!process.stdin.isTTY) throw new UsageError(start.refusal);
|
|
7596
|
+
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
7597
|
+
const answer = await rl.question(`${start.question} [y/N] `);
|
|
7598
|
+
rl.close();
|
|
7599
|
+
if (!/^y(es)?$/i.test(answer.trim())) throw new UsageError(start.refusal);
|
|
7600
|
+
}
|
|
7557
7601
|
const r = await apiJson(
|
|
7558
7602
|
origin,
|
|
7559
7603
|
`/api/folders/public/${encodeURIComponent(at2.handle)}/${encodeURIComponent(at2.slug)}/push-target`,
|
|
@@ -7603,7 +7647,7 @@ async function cmdList(argv) {
|
|
|
7603
7647
|
origin: strFlag(flags, "origin"),
|
|
7604
7648
|
api: strFlag(flags, "api")
|
|
7605
7649
|
});
|
|
7606
|
-
const key = requireCredential(
|
|
7650
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7607
7651
|
const rows = await listFolders(origin, key);
|
|
7608
7652
|
if (r.json) {
|
|
7609
7653
|
r.done({ folders: rows }, "");
|
|
@@ -7628,7 +7672,7 @@ async function cmdCreate(argv) {
|
|
|
7628
7672
|
origin: strFlag(flags, "origin"),
|
|
7629
7673
|
api: strFlag(flags, "api")
|
|
7630
7674
|
});
|
|
7631
|
-
const key = requireCredential(
|
|
7675
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7632
7676
|
const parentRef = strFlag(flags, "parent");
|
|
7633
7677
|
let parentId;
|
|
7634
7678
|
if (parentRef) {
|
|
@@ -7663,7 +7707,7 @@ async function cmdMove(argv) {
|
|
|
7663
7707
|
origin: strFlag(flags, "origin"),
|
|
7664
7708
|
api: strFlag(flags, "api")
|
|
7665
7709
|
});
|
|
7666
|
-
const key = requireCredential(
|
|
7710
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7667
7711
|
const folderId = toRef === "none" ? null : resolveFolder(await listFolders(origin, key), toRef).id;
|
|
7668
7712
|
let failed = 0;
|
|
7669
7713
|
const moved = [];
|
|
@@ -7723,7 +7767,7 @@ async function cmdPull(argv) {
|
|
|
7723
7767
|
origin: strFlag(flags, "origin"),
|
|
7724
7768
|
api: strFlag(flags, "api")
|
|
7725
7769
|
});
|
|
7726
|
-
const key = requireCredential(
|
|
7770
|
+
const key = requireCredential(credentialFlags(flags));
|
|
7727
7771
|
const folder = resolveFolder(await listFolders(origin, key), ref);
|
|
7728
7772
|
const res = await apiJson(origin, `/api/folders/${folder.id}`, { key });
|
|
7729
7773
|
if (res.status !== 200)
|
|
@@ -7791,7 +7835,8 @@ async function cmdPull(argv) {
|
|
|
7791
7835
|
vosId: v.id,
|
|
7792
7836
|
versionId: v.currentVersionId ?? null,
|
|
7793
7837
|
title: v.title,
|
|
7794
|
-
...v.slug ? { slug: v.slug } : {}
|
|
7838
|
+
...v.slug ? { slug: v.slug } : {},
|
|
7839
|
+
...await syncIdentity(origin, key)
|
|
7795
7840
|
});
|
|
7796
7841
|
members.push({ dir, id: v.id, title: v.title, take });
|
|
7797
7842
|
}
|
|
@@ -7931,10 +7976,16 @@ function hostOf(origin) {
|
|
|
7931
7976
|
}
|
|
7932
7977
|
|
|
7933
7978
|
// src/plugin/sync.ts
|
|
7934
|
-
function apiContext(flags) {
|
|
7979
|
+
function apiContext(flags, dir) {
|
|
7980
|
+
const origin = platformOrigin(flags);
|
|
7935
7981
|
return {
|
|
7936
|
-
origin
|
|
7937
|
-
key: requireCredential(
|
|
7982
|
+
origin,
|
|
7983
|
+
key: requireCredential({
|
|
7984
|
+
key: flags.key,
|
|
7985
|
+
account: flags.account,
|
|
7986
|
+
origin,
|
|
7987
|
+
dir
|
|
7988
|
+
})
|
|
7938
7989
|
};
|
|
7939
7990
|
}
|
|
7940
7991
|
async function api(ctx, path, init) {
|
|
@@ -8026,7 +8077,7 @@ async function pushTake(dir, flags, r) {
|
|
|
8026
8077
|
await readScript(dir) ?? take.doc.source.script,
|
|
8027
8078
|
dir
|
|
8028
8079
|
);
|
|
8029
|
-
const ctx = apiContext(flags);
|
|
8080
|
+
const ctx = apiContext(flags, dir);
|
|
8030
8081
|
const tracked = readSyncState(dir);
|
|
8031
8082
|
const firstPush = tracked === null;
|
|
8032
8083
|
if (firstPush && !flags.yes) {
|
|
@@ -8035,7 +8086,7 @@ async function pushTake(dir, flags, r) {
|
|
|
8035
8086
|
"first push of this take uploads its recording \u2014 pass --yes to consent headlessly"
|
|
8036
8087
|
);
|
|
8037
8088
|
}
|
|
8038
|
-
const rl =
|
|
8089
|
+
const rl = createInterface3({ input: process.stdin, output: process.stderr });
|
|
8039
8090
|
const answer = await rl.question(
|
|
8040
8091
|
`Push this take (recording + doc.json) to ${ctx.origin}? [y/N] `
|
|
8041
8092
|
);
|
|
@@ -8071,7 +8122,9 @@ async function pushTake(dir, flags, r) {
|
|
|
8071
8122
|
"--folder applies when CREATING a vos \u2014 this take is already pushed; file it with: vos folder move <vosId> --to <folder>"
|
|
8072
8123
|
);
|
|
8073
8124
|
}
|
|
8074
|
-
const target = await resolvePushFolder(ctx.origin, ctx.key, flags.folder
|
|
8125
|
+
const target = await resolvePushFolder(ctx.origin, ctx.key, flags.folder, {
|
|
8126
|
+
yes: flags.yes === true
|
|
8127
|
+
});
|
|
8075
8128
|
folderId = target.id;
|
|
8076
8129
|
if (target.note) r.log(target.note);
|
|
8077
8130
|
}
|
|
@@ -8164,7 +8217,8 @@ async function pushTake(dir, flags, r) {
|
|
|
8164
8217
|
versionId,
|
|
8165
8218
|
pushedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8166
8219
|
title,
|
|
8167
|
-
slug
|
|
8220
|
+
slug,
|
|
8221
|
+
...await syncIdentity(ctx.origin, ctx.key)
|
|
8168
8222
|
});
|
|
8169
8223
|
return { vosId: vos.id, versionId, versionNumber: 1 };
|
|
8170
8224
|
}
|
|
@@ -8214,7 +8268,8 @@ async function pushTake(dir, flags, r) {
|
|
|
8214
8268
|
writeSyncState(dir, {
|
|
8215
8269
|
vosId: state.vosId,
|
|
8216
8270
|
versionId: version.id,
|
|
8217
|
-
pushedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8271
|
+
pushedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8272
|
+
...await syncIdentity(ctx.origin, ctx.key)
|
|
8218
8273
|
});
|
|
8219
8274
|
return {
|
|
8220
8275
|
vosId: state.vosId,
|
|
@@ -8223,7 +8278,7 @@ async function pushTake(dir, flags, r) {
|
|
|
8223
8278
|
};
|
|
8224
8279
|
}
|
|
8225
8280
|
async function pullTake(dir, flags, r) {
|
|
8226
|
-
const ctx = apiContext(flags);
|
|
8281
|
+
const ctx = apiContext(flags, dir);
|
|
8227
8282
|
const state = readSyncState(dir);
|
|
8228
8283
|
const vosId = flags.vos ?? state?.vosId;
|
|
8229
8284
|
if (!vosId) {
|
|
@@ -8333,7 +8388,8 @@ async function pullTake(dir, flags, r) {
|
|
|
8333
8388
|
writeSyncState(dir, {
|
|
8334
8389
|
vosId,
|
|
8335
8390
|
versionId: head,
|
|
8336
|
-
pushedAt: state?.pushedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
8391
|
+
pushedAt: state?.pushedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
8392
|
+
...await syncIdentity(ctx.origin, ctx.key)
|
|
8337
8393
|
});
|
|
8338
8394
|
return {
|
|
8339
8395
|
vosId,
|
|
@@ -8448,7 +8504,7 @@ async function pushTakeClaimable(dir, flags, r) {
|
|
|
8448
8504
|
// src/plugin/program.ts
|
|
8449
8505
|
import { existsSync as existsSync15 } from "fs";
|
|
8450
8506
|
import { mkdir as mkdir7, readFile as readFile12 } from "fs/promises";
|
|
8451
|
-
import { createInterface as
|
|
8507
|
+
import { createInterface as createInterface4 } from "readline/promises";
|
|
8452
8508
|
import { basename as basename5, dirname as dirname2, join as join15 } from "path";
|
|
8453
8509
|
import {
|
|
8454
8510
|
CURRENT_CONFIG_VERSION,
|
|
@@ -8677,7 +8733,8 @@ async function cmdFetch(argv) {
|
|
|
8677
8733
|
vosId,
|
|
8678
8734
|
versionId: head,
|
|
8679
8735
|
...title ? { title } : {},
|
|
8680
|
-
slug
|
|
8736
|
+
slug,
|
|
8737
|
+
...await syncIdentity(origin, key)
|
|
8681
8738
|
});
|
|
8682
8739
|
let take = false;
|
|
8683
8740
|
let mediaLine = "";
|
|
@@ -8944,8 +9001,8 @@ with their key: vos push ${source} --vos ${String(created2.id ?? "<id>")}`
|
|
|
8944
9001
|
);
|
|
8945
9002
|
return EXIT_OK;
|
|
8946
9003
|
}
|
|
8947
|
-
const key = requireCredential(
|
|
8948
|
-
|
|
9004
|
+
const key = requireCredential({ ...credentialFlags(flags), dir });
|
|
9005
|
+
const yes = flags.yes === true;
|
|
8949
9006
|
const files = await collectFiles(config, programDoc, dir, r);
|
|
8950
9007
|
await files.upload({ origin, key });
|
|
8951
9008
|
const overrides = [
|
|
@@ -9029,7 +9086,11 @@ with their key: vos push ${source} --vos ${String(created2.id ?? "<id>")}`
|
|
|
9029
9086
|
}
|
|
9030
9087
|
const version = res.body.version ?? {};
|
|
9031
9088
|
if (typeof version.id === "string") {
|
|
9032
|
-
writeSyncState(dir, {
|
|
9089
|
+
writeSyncState(dir, {
|
|
9090
|
+
vosId,
|
|
9091
|
+
versionId: version.id,
|
|
9092
|
+
...await syncIdentity(origin, key)
|
|
9093
|
+
});
|
|
9033
9094
|
}
|
|
9034
9095
|
const watchUrl2 = `${origin}/vos/${vosId}`;
|
|
9035
9096
|
const studioUrl2 = `${origin}/studio?vos=${vosId}`;
|
|
@@ -9064,7 +9125,7 @@ ${landedLines(landed2)}` : "")
|
|
|
9064
9125
|
const remixOfId = pushTarget.kind === "create" ? pushTarget.remixOfId : void 0;
|
|
9065
9126
|
const fallbackTitle = state?.title ? `${state.title} remix` : basename5(source).replace(/\.json$/i, "") || "vos remix";
|
|
9066
9127
|
const title = (strFlag(flags, "title") ?? fallbackTitle).slice(0, 100);
|
|
9067
|
-
const pushFolder = folderRef ? await resolvePushFolder(origin, key, folderRef) : void 0;
|
|
9128
|
+
const pushFolder = folderRef ? await resolvePushFolder(origin, key, folderRef, { yes }) : void 0;
|
|
9068
9129
|
const folderId = pushFolder?.id;
|
|
9069
9130
|
if (pushFolder?.note) r.log(pushFolder.note);
|
|
9070
9131
|
const created = await createProgramVos({
|
|
@@ -9092,7 +9153,8 @@ ${landedLines(landed2)}` : "")
|
|
|
9092
9153
|
versionId: created.currentVersionId,
|
|
9093
9154
|
title,
|
|
9094
9155
|
slug: created.slug,
|
|
9095
|
-
...remixOfId ? { remixOfId } : {}
|
|
9156
|
+
...remixOfId ? { remixOfId } : {},
|
|
9157
|
+
...await syncIdentity(origin, key)
|
|
9096
9158
|
});
|
|
9097
9159
|
const watchUrl = `${origin}/vos/${created.id}`;
|
|
9098
9160
|
const studioUrl = `${origin}/studio?vos=${created.id}`;
|
|
@@ -9159,7 +9221,7 @@ async function cmdPullProgram(argv) {
|
|
|
9159
9221
|
`no base version in ${dir}/vos.json \u2014 pass --since <versionId>`
|
|
9160
9222
|
);
|
|
9161
9223
|
}
|
|
9162
|
-
const key = requireCredential(
|
|
9224
|
+
const key = requireCredential({ ...credentialFlags(flags), dir });
|
|
9163
9225
|
const res = await apiJson(
|
|
9164
9226
|
origin,
|
|
9165
9227
|
`/api/vos/${vosId}/changes?since=${encodeURIComponent(since)}`,
|
|
@@ -9231,7 +9293,8 @@ async function cmdPullProgram(argv) {
|
|
|
9231
9293
|
await writeFileSafe(configPath, JSON.stringify(headConfig, null, 2));
|
|
9232
9294
|
writeSyncState(dir, {
|
|
9233
9295
|
vosId,
|
|
9234
|
-
versionId: typeof head.id === "string" ? head.id : since
|
|
9296
|
+
versionId: typeof head.id === "string" ? head.id : since,
|
|
9297
|
+
...await syncIdentity(origin, key)
|
|
9235
9298
|
});
|
|
9236
9299
|
r.done(
|
|
9237
9300
|
{
|
|
@@ -9258,16 +9321,21 @@ async function cmdLogin(argv) {
|
|
|
9258
9321
|
});
|
|
9259
9322
|
const handoffUrl = strFlag(flags, "handoff");
|
|
9260
9323
|
if (handoffUrl) {
|
|
9324
|
+
const before = await nameActiveCredential(
|
|
9325
|
+
parseHandoffUrl(handoffUrl)?.origin ?? origin
|
|
9326
|
+
);
|
|
9261
9327
|
const done = await handoffLogin(handoffUrl, r);
|
|
9262
9328
|
r.done(
|
|
9263
9329
|
{
|
|
9264
9330
|
path: done.path,
|
|
9265
9331
|
origin: done.origin,
|
|
9266
9332
|
user: done.user,
|
|
9333
|
+
account: done.account,
|
|
9267
9334
|
keyName: done.keyName,
|
|
9335
|
+
...setAsideFacts(before, done.account),
|
|
9268
9336
|
next_step: "the link is spent; vos push when you want the work hosted"
|
|
9269
9337
|
},
|
|
9270
|
-
`Signed in${done.user
|
|
9338
|
+
`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)}`
|
|
9271
9339
|
);
|
|
9272
9340
|
return EXIT_OK;
|
|
9273
9341
|
}
|
|
@@ -9275,13 +9343,14 @@ async function cmdLogin(argv) {
|
|
|
9275
9343
|
if (explicit) return storeKey(explicit, origin, r);
|
|
9276
9344
|
try {
|
|
9277
9345
|
const openBrowser = process.stdout.isTTY === true && !process.env.SSH_CONNECTION && !process.env.SSH_TTY && flags.json !== true && flags["no-browser"] !== true;
|
|
9278
|
-
const
|
|
9346
|
+
const before = await nameActiveCredential(origin);
|
|
9347
|
+
const { path, user, account } = await browserLogin(origin, r, {
|
|
9279
9348
|
label: strFlag(flags, "label"),
|
|
9280
9349
|
openBrowser
|
|
9281
9350
|
});
|
|
9282
9351
|
r.done(
|
|
9283
|
-
{ path, origin, user },
|
|
9284
|
-
`Signed in${user
|
|
9352
|
+
{ path, origin, user, account, ...setAsideFacts(before, account) },
|
|
9353
|
+
`Signed in${signedAs(user, account)} \u2014 key stored at ${path} (used by every vos platform verb).${setAsideLine(before, account)}`
|
|
9285
9354
|
);
|
|
9286
9355
|
return EXIT_OK;
|
|
9287
9356
|
} catch (e) {
|
|
@@ -9292,24 +9361,64 @@ async function cmdLogin(argv) {
|
|
|
9292
9361
|
`vos login --key <vos_sk_\u2026> (headless), or run interactively \u2014 mint a key at ${mintAt(origin)}`
|
|
9293
9362
|
);
|
|
9294
9363
|
}
|
|
9295
|
-
const rl =
|
|
9364
|
+
const rl = createInterface4({ input: process.stdin, output: process.stderr });
|
|
9296
9365
|
const key = (await rl.question(`Paste a content key from ${origin}/app/api: `)).trim();
|
|
9297
9366
|
rl.close();
|
|
9298
9367
|
if (!key) throw new UsageError("no key given");
|
|
9299
9368
|
return storeKey(key, origin, r);
|
|
9300
9369
|
}
|
|
9301
9370
|
async function storeKey(key, origin, r) {
|
|
9302
|
-
const
|
|
9303
|
-
if (
|
|
9304
|
-
throw new Error(apiError("validate key",
|
|
9371
|
+
const who = await apiJson(origin, "/api/user/whoami", { key });
|
|
9372
|
+
if (who.status === 401 || who.status === 403) {
|
|
9373
|
+
throw new Error(apiError("validate key", who));
|
|
9305
9374
|
}
|
|
9306
|
-
|
|
9375
|
+
let account = null;
|
|
9376
|
+
if (who.status === 200) account = accountFrom(who.body.user);
|
|
9377
|
+
else {
|
|
9378
|
+
const probe3 = await apiJson(origin, "/api/folders", { key });
|
|
9379
|
+
if (probe3.status === 401 || probe3.status === 403) {
|
|
9380
|
+
throw new Error(apiError("validate key", probe3));
|
|
9381
|
+
}
|
|
9382
|
+
}
|
|
9383
|
+
const before = await nameActiveCredential(origin);
|
|
9384
|
+
const path = writeCredential(key, origin, void 0, account);
|
|
9307
9385
|
r.done(
|
|
9308
|
-
{ path, origin },
|
|
9309
|
-
`Signed in \u2014 key stored at ${path} (used by every vos platform verb)`
|
|
9386
|
+
{ path, origin, account, ...setAsideFacts(before, account) },
|
|
9387
|
+
`Signed in${signedAs("", account)} \u2014 key stored at ${path} (used by every vos platform verb).${setAsideLine(before, account)}`
|
|
9310
9388
|
);
|
|
9311
9389
|
return EXIT_OK;
|
|
9312
9390
|
}
|
|
9391
|
+
function signedAs(user, account) {
|
|
9392
|
+
if (account) return ` as ${accountLabel(account)}`;
|
|
9393
|
+
return user ? ` as ${user}` : "";
|
|
9394
|
+
}
|
|
9395
|
+
async function nameActiveCredential(origin) {
|
|
9396
|
+
const active = readActive(DEFAULT_STORE);
|
|
9397
|
+
if (!active || active.origin !== originOf(origin)) return active;
|
|
9398
|
+
if (active.account) return active;
|
|
9399
|
+
try {
|
|
9400
|
+
const who = await apiJson(origin, "/api/user/whoami", { key: active.key });
|
|
9401
|
+
const account = who.status === 200 ? accountFrom(who.body.user) : null;
|
|
9402
|
+
if (!account) return active;
|
|
9403
|
+
const named = { ...active, account };
|
|
9404
|
+
activate(DEFAULT_STORE, named);
|
|
9405
|
+
return named;
|
|
9406
|
+
} catch {
|
|
9407
|
+
return active;
|
|
9408
|
+
}
|
|
9409
|
+
}
|
|
9410
|
+
function setAsideFacts(before, account) {
|
|
9411
|
+
if (!before || account && before.account?.id === account.id) return {};
|
|
9412
|
+
return before.account ? { setAside: before.account } : { replaced: true };
|
|
9413
|
+
}
|
|
9414
|
+
function setAsideLine(before, account) {
|
|
9415
|
+
const facts = setAsideFacts(before, account);
|
|
9416
|
+
if (facts.setAside)
|
|
9417
|
+
return ` ${accountLabel(facts.setAside)} stays stored; vos switch ${facts.setAside.handle ?? facts.setAside.id} when you need it.`;
|
|
9418
|
+
if (facts.replaced)
|
|
9419
|
+
return " The credential stored before had no name on file and was replaced.";
|
|
9420
|
+
return "";
|
|
9421
|
+
}
|
|
9313
9422
|
function isTakeDir(target) {
|
|
9314
9423
|
return directoryKind(target) === "take";
|
|
9315
9424
|
}
|
|
@@ -9625,7 +9734,7 @@ async function cmdRename(argv) {
|
|
|
9625
9734
|
origin: strFlag(flags, "origin"),
|
|
9626
9735
|
api: strFlag(flags, "api")
|
|
9627
9736
|
});
|
|
9628
|
-
const key = requireCredential(
|
|
9737
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9629
9738
|
const res = await apiJson(origin, `/api/assets/${assetId}`, {
|
|
9630
9739
|
method: "PATCH",
|
|
9631
9740
|
key,
|
|
@@ -9648,7 +9757,7 @@ async function cmdPush(argv) {
|
|
|
9648
9757
|
origin: strFlag(flags, "origin"),
|
|
9649
9758
|
api: strFlag(flags, "api")
|
|
9650
9759
|
});
|
|
9651
|
-
const key = requireCredential(
|
|
9760
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9652
9761
|
const folderRef = strFlag(flags, "folder");
|
|
9653
9762
|
const folder = folderRef ? resolveFolder(await listFolders(origin, key), folderRef) : null;
|
|
9654
9763
|
const uploaded = [];
|
|
@@ -9729,7 +9838,7 @@ async function cmdImport(argv) {
|
|
|
9729
9838
|
origin: strFlag(flags, "origin"),
|
|
9730
9839
|
api: strFlag(flags, "api")
|
|
9731
9840
|
});
|
|
9732
|
-
const key = requireCredential(
|
|
9841
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9733
9842
|
const folderRef = strFlag(flags, "folder");
|
|
9734
9843
|
const folder = folderRef ? resolveFolder(await listFolders(origin, key), folderRef) : null;
|
|
9735
9844
|
const refused = fetchRefusal(url);
|
|
@@ -9813,7 +9922,7 @@ async function cmdList2(argv) {
|
|
|
9813
9922
|
origin: strFlag(flags, "origin"),
|
|
9814
9923
|
api: strFlag(flags, "api")
|
|
9815
9924
|
});
|
|
9816
|
-
const key = requireCredential(
|
|
9925
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9817
9926
|
const params = new URLSearchParams({
|
|
9818
9927
|
limit: String(Math.min(200, Math.max(1, numFlag(flags, "limit", 50))))
|
|
9819
9928
|
});
|
|
@@ -9846,7 +9955,7 @@ async function cmdUsage(argv) {
|
|
|
9846
9955
|
origin: strFlag(flags, "origin"),
|
|
9847
9956
|
api: strFlag(flags, "api")
|
|
9848
9957
|
});
|
|
9849
|
-
const key = requireCredential(
|
|
9958
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9850
9959
|
const res = await apiJson(origin, "/api/user/usage", { key });
|
|
9851
9960
|
if (res.status !== 200) throw new Error(apiError("read usage", res));
|
|
9852
9961
|
const usage = res.body.usage ?? {};
|
|
@@ -9873,7 +9982,7 @@ async function cmdWhy(argv) {
|
|
|
9873
9982
|
origin: strFlag(flags, "origin"),
|
|
9874
9983
|
api: strFlag(flags, "api")
|
|
9875
9984
|
});
|
|
9876
|
-
const key = requireCredential(
|
|
9985
|
+
const key = requireCredential(credentialFlags(flags));
|
|
9877
9986
|
const res = await apiJson(origin, `/api/assets/${assetId}`, { key });
|
|
9878
9987
|
if (res.status !== 200) throw new Error(apiError(`read ${assetId}`, res));
|
|
9879
9988
|
const asset = hostedFile(res.body.asset);
|
|
@@ -9919,7 +10028,7 @@ async function cmdAsset(argv) {
|
|
|
9919
10028
|
// src/plugin/remove.ts
|
|
9920
10029
|
import { existsSync as existsSync16, rmSync as rmSync2, statSync as statSync3 } from "fs";
|
|
9921
10030
|
import { join as join16 } from "path";
|
|
9922
|
-
import { createInterface as
|
|
10031
|
+
import { createInterface as createInterface5 } from "readline/promises";
|
|
9923
10032
|
|
|
9924
10033
|
// src/plugin/trash.ts
|
|
9925
10034
|
var BOOLEAN_FLAGS4 = /* @__PURE__ */ new Set(["json", "help"]);
|
|
@@ -9968,7 +10077,7 @@ function context(flags) {
|
|
|
9968
10077
|
origin: strFlag(flags, "origin"),
|
|
9969
10078
|
api: strFlag(flags, "api")
|
|
9970
10079
|
}).replace(/\/+$/, "");
|
|
9971
|
-
return { origin, key: requireCredential(
|
|
10080
|
+
return { origin, key: requireCredential(credentialFlags(flags)) };
|
|
9972
10081
|
}
|
|
9973
10082
|
async function readTrash(ctx) {
|
|
9974
10083
|
const res = await apiJson(ctx.origin, "/api/trash", { key: ctx.key });
|
|
@@ -10096,7 +10205,7 @@ async function cmdDelete(argv) {
|
|
|
10096
10205
|
origin: strFlag(flags, "origin"),
|
|
10097
10206
|
api: strFlag(flags, "api")
|
|
10098
10207
|
}).replace(/\/+$/, "");
|
|
10099
|
-
const key = requireCredential(
|
|
10208
|
+
const key = requireCredential(credentialFlags(flags));
|
|
10100
10209
|
const dir = existsSync16(target) && statSync3(target).isDirectory() ? target : null;
|
|
10101
10210
|
const vosId = dir ? readSyncState(dir)?.vosId : parseVosId(target);
|
|
10102
10211
|
if (!vosId)
|
|
@@ -10119,7 +10228,7 @@ async function cmdDelete(argv) {
|
|
|
10119
10228
|
throw new UsageError(
|
|
10120
10229
|
`"${title}" (${vosId}) would move to Trash: re-run with --yes to confirm, or --dry-run to only look`
|
|
10121
10230
|
);
|
|
10122
|
-
const rl =
|
|
10231
|
+
const rl = createInterface5({ input: process.stdin, output: process.stderr });
|
|
10123
10232
|
const answer = await rl.question(
|
|
10124
10233
|
`Move "${title}" (${vosId}) to Trash? It stays restorable there for a while (vos restore ${vosId}). [y/N] `
|
|
10125
10234
|
);
|
|
@@ -12149,7 +12258,7 @@ async function cmdPush2(argv) {
|
|
|
12149
12258
|
origin: strFlag(flags, "origin"),
|
|
12150
12259
|
api: strFlag(flags, "api")
|
|
12151
12260
|
});
|
|
12152
|
-
const key = requireCredential(
|
|
12261
|
+
const key = requireCredential(credentialFlags(flags));
|
|
12153
12262
|
if (assetId) {
|
|
12154
12263
|
const res = await apiJson(origin, `/api/assets/${assetId}/file`, {
|
|
12155
12264
|
method: "PUT",
|
|
@@ -18021,7 +18130,6 @@ import {
|
|
|
18021
18130
|
existsSync as existsSync30,
|
|
18022
18131
|
mkdirSync as mkdirSync6,
|
|
18023
18132
|
readFileSync as readFileSync12,
|
|
18024
|
-
rmSync as rmSync3,
|
|
18025
18133
|
writeFileSync as writeFileSync6
|
|
18026
18134
|
} from "fs";
|
|
18027
18135
|
import { homedir as homedir2 } from "os";
|
|
@@ -18115,7 +18223,7 @@ var RULES_BODY = `## Product videos (vosso)
|
|
|
18115
18223
|
- Hand back: vos open take serves the take into the studio at vos.so, doc.json intact
|
|
18116
18224
|
- Local by default: vos push only when asked for a link, the shelf or a cloud render
|
|
18117
18225
|
- 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
|
|
18118
|
-
- Credentials: VOS_API_KEY, then ~/.config/vos/credentials, then vos login; never print one
|
|
18226
|
+
- 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
|
|
18119
18227
|
- Reference: https://vos.so/llms-full.txt`;
|
|
18120
18228
|
var RULES_BLOCK = `${RULES_BEGIN}
|
|
18121
18229
|
${RULES_BODY}
|
|
@@ -18195,6 +18303,18 @@ var NODE_MIN_MAJOR = 18;
|
|
|
18195
18303
|
function major(version) {
|
|
18196
18304
|
return parseInt(version.split(".")[0] ?? "0", 10);
|
|
18197
18305
|
}
|
|
18306
|
+
function credentialLine(facts) {
|
|
18307
|
+
const accounts = facts.accounts ?? [];
|
|
18308
|
+
const active = accounts.find((a) => a.active);
|
|
18309
|
+
const others = accounts.filter((a) => !a.active).map((a) => a.label);
|
|
18310
|
+
if (active) {
|
|
18311
|
+
return `${active.label} \u2713${others.length ? ` (also ${others.join(", ")})` : ""}`;
|
|
18312
|
+
}
|
|
18313
|
+
if (facts.credential) {
|
|
18314
|
+
return `present \u2713${others.length ? ` (stored: ${others.join(", ")}; vos switch to use one)` : ""}`;
|
|
18315
|
+
}
|
|
18316
|
+
return `absent (vos login when you need hosting)${others.length ? `; stored: ${others.join(", ")}, vos switch to use one` : ""}`;
|
|
18317
|
+
}
|
|
18198
18318
|
function doctorReport(facts) {
|
|
18199
18319
|
const lines = [];
|
|
18200
18320
|
const nodeOk = major(facts.node) >= NODE_MIN_MAJOR;
|
|
@@ -18220,9 +18340,7 @@ function doctorReport(facts) {
|
|
|
18220
18340
|
} else {
|
|
18221
18341
|
lines.push("skills none \u2717 run: npx vos setup");
|
|
18222
18342
|
}
|
|
18223
|
-
lines.push(
|
|
18224
|
-
`credential ${facts.credential ? "present \u2713" : "absent (vos login when you need hosting)"}`
|
|
18225
|
-
);
|
|
18343
|
+
lines.push(`credential ${credentialLine(facts)}`);
|
|
18226
18344
|
if (facts.devServer) {
|
|
18227
18345
|
const d = facts.devServer;
|
|
18228
18346
|
lines.push(
|
|
@@ -18280,6 +18398,7 @@ var BOOLEAN_FLAGS15 = /* @__PURE__ */ new Set([
|
|
|
18280
18398
|
"no-rules",
|
|
18281
18399
|
"no-browser"
|
|
18282
18400
|
]);
|
|
18401
|
+
var LOGOUT_FLAGS = /* @__PURE__ */ new Set([...BOOLEAN_FLAGS15, "all"]);
|
|
18283
18402
|
var SKILLS_SOURCE = "vosjs/skills";
|
|
18284
18403
|
var SKILLS_CLI_VERSION = "1.7.2";
|
|
18285
18404
|
function skillsCatalogAt(version) {
|
|
@@ -18349,10 +18468,24 @@ async function doctorFacts(opts) {
|
|
|
18349
18468
|
browser: probe2(),
|
|
18350
18469
|
ffmpeg: ffmpegVersion(),
|
|
18351
18470
|
skills: skillsFacts(opts.homes),
|
|
18352
|
-
credential:
|
|
18471
|
+
credential: safeResolve() !== null,
|
|
18472
|
+
accounts: storedAccounts(platformOrigin()),
|
|
18353
18473
|
...opts.url ? { devServer: await devServerFact(opts.url) } : {}
|
|
18354
18474
|
};
|
|
18355
18475
|
}
|
|
18476
|
+
function safeResolve() {
|
|
18477
|
+
try {
|
|
18478
|
+
return resolveCredential();
|
|
18479
|
+
} catch {
|
|
18480
|
+
return null;
|
|
18481
|
+
}
|
|
18482
|
+
}
|
|
18483
|
+
function storedAccounts(origin, store = DEFAULT_STORE) {
|
|
18484
|
+
return listStored(store, origin).map((c) => ({
|
|
18485
|
+
label: accountLabel(c.account),
|
|
18486
|
+
active: isActive(c, store)
|
|
18487
|
+
}));
|
|
18488
|
+
}
|
|
18356
18489
|
async function cmdSetup(argv) {
|
|
18357
18490
|
const { flags } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18358
18491
|
const r = reporterFor(flags);
|
|
@@ -18512,29 +18645,42 @@ async function cmdWhoami(argv) {
|
|
|
18512
18645
|
origin: strFlag(flags, "origin"),
|
|
18513
18646
|
api: strFlag(flags, "api")
|
|
18514
18647
|
});
|
|
18515
|
-
const
|
|
18648
|
+
const stored = storedAccounts(origin);
|
|
18649
|
+
const others = stored.filter((a) => !a.active).map((a) => a.label);
|
|
18650
|
+
const alsoStored = others.length ? ` Also stored: ${others.join(", ")}; vos switch <name> to use one.` : "";
|
|
18651
|
+
const key = resolveCredential({
|
|
18652
|
+
key: strFlag(flags, "key"),
|
|
18653
|
+
account: strFlag(flags, "account"),
|
|
18654
|
+
origin
|
|
18655
|
+
});
|
|
18516
18656
|
if (!key) {
|
|
18517
18657
|
r.done(
|
|
18518
18658
|
{
|
|
18519
18659
|
signedIn: false,
|
|
18520
18660
|
origin,
|
|
18661
|
+
accounts: stored,
|
|
18521
18662
|
next_step: "vos login (only needed for hosting, sharing or cloud rendering)"
|
|
18522
18663
|
},
|
|
18523
|
-
`Not signed in to ${origin}. Recording and rendering need no account; vos login when you want a link
|
|
18664
|
+
`Not signed in to ${origin}. Recording and rendering need no account; vos login when you want a link.${alsoStored}`
|
|
18524
18665
|
);
|
|
18525
18666
|
return EXIT_ERROR;
|
|
18526
18667
|
}
|
|
18668
|
+
const resolved = lastCredential();
|
|
18669
|
+
const via = resolved?.via ?? "stored";
|
|
18670
|
+
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})` : "";
|
|
18527
18671
|
const res = await apiJson(origin, "/api/user/whoami", { key });
|
|
18528
18672
|
if (res.status === 404) {
|
|
18529
18673
|
r.done(
|
|
18530
18674
|
{
|
|
18531
18675
|
signedIn: true,
|
|
18532
18676
|
origin,
|
|
18677
|
+
via,
|
|
18533
18678
|
user: null,
|
|
18534
18679
|
key: null,
|
|
18680
|
+
accounts: stored,
|
|
18535
18681
|
next_step: "vos push when you want the work hosted"
|
|
18536
18682
|
},
|
|
18537
|
-
`A credential is present for ${origin} (this origin cannot say whose)
|
|
18683
|
+
`A credential is present for ${origin}${viaLine} (this origin cannot say whose).${alsoStored}`
|
|
18538
18684
|
);
|
|
18539
18685
|
return EXIT_OK;
|
|
18540
18686
|
}
|
|
@@ -18543,44 +18689,150 @@ async function cmdWhoami(argv) {
|
|
|
18543
18689
|
{
|
|
18544
18690
|
signedIn: false,
|
|
18545
18691
|
origin,
|
|
18692
|
+
via,
|
|
18546
18693
|
error: apiError("whoami", res),
|
|
18694
|
+
accounts: stored,
|
|
18547
18695
|
next_step: "vos login"
|
|
18548
18696
|
},
|
|
18549
|
-
`The stored credential is refused by ${origin}: ${apiError("whoami", res)}. Run vos login
|
|
18697
|
+
`The stored credential is refused by ${origin}${viaLine}: ${apiError("whoami", res)}. Run vos login.${alsoStored}`
|
|
18550
18698
|
);
|
|
18551
18699
|
return EXIT_ERROR;
|
|
18552
18700
|
}
|
|
18553
18701
|
if (res.status !== 200) throw new Error(apiError("whoami", res));
|
|
18554
18702
|
const user = res.body.user;
|
|
18703
|
+
const actor = res.body.actor;
|
|
18555
18704
|
const k = res.body.key;
|
|
18556
18705
|
const who = user?.username ? `@${user.username}` : user?.name ?? "an account";
|
|
18706
|
+
const orgLine = user?.kind === "org" ? ` (an organization${actor ? `, ${actor.username ? `@${actor.username}` : actor.name ?? "you"} recorded as the person behind it` : ""})` : "";
|
|
18557
18707
|
const keyLine = k ? `key "${k.name ?? ""}" (${k.prefix ?? "\u2026"}, ${(k.scopes ?? []).join(", ") || "no scopes"})` : "a session, not a key";
|
|
18708
|
+
if (via === "stored" && resolved && !resolved.account && user?.id) {
|
|
18709
|
+
const active = readActive(DEFAULT_STORE);
|
|
18710
|
+
if (active && active.key === key) {
|
|
18711
|
+
activate(DEFAULT_STORE, {
|
|
18712
|
+
...active,
|
|
18713
|
+
account: {
|
|
18714
|
+
id: user.id,
|
|
18715
|
+
kind: user.kind === "org" ? "org" : "person",
|
|
18716
|
+
handle: user.username ?? null
|
|
18717
|
+
}
|
|
18718
|
+
});
|
|
18719
|
+
}
|
|
18720
|
+
}
|
|
18558
18721
|
r.done(
|
|
18559
18722
|
{
|
|
18560
18723
|
signedIn: true,
|
|
18561
18724
|
origin,
|
|
18725
|
+
via,
|
|
18562
18726
|
user,
|
|
18727
|
+
actor: actor ?? null,
|
|
18563
18728
|
key: k,
|
|
18729
|
+
accounts: storedAccounts(origin),
|
|
18564
18730
|
next_step: "vos push when you want the work hosted"
|
|
18565
18731
|
},
|
|
18566
|
-
`Signed in to ${origin} as ${who}, with ${keyLine}
|
|
18732
|
+
`Signed in to ${origin} as ${who}${orgLine}, with ${keyLine}${viaLine}.${alsoStored}`
|
|
18733
|
+
);
|
|
18734
|
+
return EXIT_OK;
|
|
18735
|
+
}
|
|
18736
|
+
function cmdSwitch(argv) {
|
|
18737
|
+
const { flags, positionals } = parseArgs(argv, BOOLEAN_FLAGS15);
|
|
18738
|
+
const r = reporterFor(flags);
|
|
18739
|
+
const origin = platformOrigin({
|
|
18740
|
+
origin: strFlag(flags, "origin"),
|
|
18741
|
+
api: strFlag(flags, "api")
|
|
18742
|
+
});
|
|
18743
|
+
const store = DEFAULT_STORE;
|
|
18744
|
+
const stored = listStored(store, origin);
|
|
18745
|
+
const active = readActive(store);
|
|
18746
|
+
const target = switchTarget(
|
|
18747
|
+
stored,
|
|
18748
|
+
active?.key ?? null,
|
|
18749
|
+
positionals[0],
|
|
18750
|
+
origin
|
|
18751
|
+
);
|
|
18752
|
+
if (!target.ok) throw new UsageError(target.error);
|
|
18753
|
+
const to = target.to;
|
|
18754
|
+
if (active && active.key === to.key) {
|
|
18755
|
+
r.done(
|
|
18756
|
+
{
|
|
18757
|
+
origin,
|
|
18758
|
+
account: to.account,
|
|
18759
|
+
changed: false,
|
|
18760
|
+
accounts: storedAccounts(origin, store),
|
|
18761
|
+
next_step: "vos push when you want the work hosted"
|
|
18762
|
+
},
|
|
18763
|
+
`${accountLabel(to.account)} is already the account in use on ${origin}.`
|
|
18764
|
+
);
|
|
18765
|
+
return EXIT_OK;
|
|
18766
|
+
}
|
|
18767
|
+
activate(store, to);
|
|
18768
|
+
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
18769
|
+
r.done(
|
|
18770
|
+
{
|
|
18771
|
+
origin,
|
|
18772
|
+
account: to.account,
|
|
18773
|
+
changed: true,
|
|
18774
|
+
accounts: storedAccounts(origin, store),
|
|
18775
|
+
next_step: envKey ? "unset VOS_API_KEY; it outranks the stored credential" : "vos push when you want the work hosted"
|
|
18776
|
+
},
|
|
18777
|
+
`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." : ""}`
|
|
18567
18778
|
);
|
|
18568
18779
|
return EXIT_OK;
|
|
18569
18780
|
}
|
|
18570
18781
|
function cmdLogout(argv) {
|
|
18571
|
-
const { flags } = parseArgs(argv,
|
|
18782
|
+
const { flags, positionals } = parseArgs(argv, LOGOUT_FLAGS);
|
|
18572
18783
|
const r = reporterFor(flags);
|
|
18573
|
-
const
|
|
18574
|
-
|
|
18784
|
+
const origin = platformOrigin({
|
|
18785
|
+
origin: strFlag(flags, "origin"),
|
|
18786
|
+
api: strFlag(flags, "api")
|
|
18787
|
+
});
|
|
18788
|
+
const store = DEFAULT_STORE;
|
|
18575
18789
|
const envKey = Boolean(process.env.VOS_API_KEY?.trim());
|
|
18790
|
+
const envNote = envKey ? " VOS_API_KEY is still set in this shell and still resolves." : "";
|
|
18791
|
+
const envStep = envKey ? "unset VOS_API_KEY as well; it still resolves" : "vos login when you next need hosting";
|
|
18792
|
+
if (flags.all === true) {
|
|
18793
|
+
const { had } = removeAll(store);
|
|
18794
|
+
r.done(
|
|
18795
|
+
{
|
|
18796
|
+
path: CREDENTIALS_PATH,
|
|
18797
|
+
removed: had,
|
|
18798
|
+
all: true,
|
|
18799
|
+
envCredential: envKey,
|
|
18800
|
+
next_step: envStep
|
|
18801
|
+
},
|
|
18802
|
+
(had ? "Removed every stored credential." : "Nothing was stored.") + envNote
|
|
18803
|
+
);
|
|
18804
|
+
return EXIT_OK;
|
|
18805
|
+
}
|
|
18806
|
+
const ref = positionals[0];
|
|
18807
|
+
const target = ref ? findStored(store, origin, ref) : readActive(store);
|
|
18808
|
+
if (!target) {
|
|
18809
|
+
const have = storedAccounts(origin, store);
|
|
18810
|
+
r.done(
|
|
18811
|
+
{
|
|
18812
|
+
path: CREDENTIALS_PATH,
|
|
18813
|
+
removed: false,
|
|
18814
|
+
envCredential: envKey,
|
|
18815
|
+
accounts: have,
|
|
18816
|
+
next_step: envStep
|
|
18817
|
+
},
|
|
18818
|
+
(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
|
|
18819
|
+
);
|
|
18820
|
+
return EXIT_OK;
|
|
18821
|
+
}
|
|
18822
|
+
const { wasActive } = removeStored(store, target);
|
|
18823
|
+
const left = storedAccounts(origin, store);
|
|
18824
|
+
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.` : "";
|
|
18576
18825
|
r.done(
|
|
18577
18826
|
{
|
|
18578
18827
|
path: CREDENTIALS_PATH,
|
|
18579
|
-
removed:
|
|
18828
|
+
removed: true,
|
|
18829
|
+
account: target.account,
|
|
18830
|
+
wasActive,
|
|
18580
18831
|
envCredential: envKey,
|
|
18581
|
-
|
|
18832
|
+
accounts: left,
|
|
18833
|
+
next_step: left.length && wasActive ? "vos switch <name>" : envStep
|
|
18582
18834
|
},
|
|
18583
|
-
|
|
18835
|
+
`Removed ${accountLabel(target.account)} (${target.origin}).${leftLine}${envNote}`
|
|
18584
18836
|
);
|
|
18585
18837
|
return EXIT_OK;
|
|
18586
18838
|
}
|
|
@@ -18689,15 +18941,22 @@ This machine (no account)
|
|
|
18689
18941
|
agent, a credential (present or absent, never printed), and the
|
|
18690
18942
|
dev server when --url names one. Exit 3 when no browser
|
|
18691
18943
|
vos whoami [--json]
|
|
18692
|
-
the key's name
|
|
18693
|
-
|
|
18694
|
-
|
|
18944
|
+
the account in use (its key's name, which rung resolved it) and
|
|
18945
|
+
every other account stored for the origin, never a key
|
|
18946
|
+
vos switch [<handle>] [--json]
|
|
18947
|
+
use another stored account (with two stored, the other one);
|
|
18948
|
+
vos login once per account, approving as it, stores them all
|
|
18949
|
+
vos logout [<handle>] [--all] [--json]
|
|
18950
|
+
forget the account in use, a named one, or every stored
|
|
18951
|
+
credential (VOS_API_KEY still resolves)
|
|
18695
18952
|
|
|
18696
18953
|
Platform (vos.so) \u2014 fetch, edit, push, pull, repeat
|
|
18697
18954
|
vos login [--key <vos_sk_\u2026>] [--handoff <url>] [--label <name>] [--no-browser]
|
|
18698
18955
|
sign in via the browser (approve at vos.so/cli/auth; works
|
|
18699
18956
|
headless \u2014 print the URL, a human approves, the key stores
|
|
18700
18957
|
itself). --key skips the browser (mint at vos.so/app/api).
|
|
18958
|
+
Additive: the person picks the account on the approval page,
|
|
18959
|
+
and every account signed in stays stored (vos switch).
|
|
18701
18960
|
--handoff https://vos.so/h/\u2026 exchanges the setup link a
|
|
18702
18961
|
signed-in person's line carries for a key, once, no click
|
|
18703
18962
|
vos fetch <vosId|watch-url> [--out dir] [--media] [--json]
|
|
@@ -18761,7 +19020,8 @@ Platform (vos.so) \u2014 fetch, edit, push, pull, repeat
|
|
|
18761
19020
|
kept) or the take's doc.json. ALWAYS pull before editing pushed work.
|
|
18762
19021
|
--media also downloads the recording (+ mic/cam sidecars) beside
|
|
18763
19022
|
the doc and re-anchors it, so digest/frames/render run locally
|
|
18764
|
-
auth: --key, VOS_API_KEY, or
|
|
19023
|
+
auth: --key, --account <handle>, VOS_API_KEY, VOS_ACCOUNT, or the
|
|
19024
|
+
stored account in use (~/.config/vos/credentials); keys can
|
|
18765
19025
|
never publish (visibility stays private; humans publish on vos.so)
|
|
18766
19026
|
vos folder list
|
|
18767
19027
|
vos folder create <name> [--parent <folderId|slug>] [--desc <text>]
|
|
@@ -18962,13 +19222,16 @@ doc.json edits arrive intact; a human can drag every zoom span. Keeps
|
|
|
18962
19222
|
serving until Ctrl-C. The studio is https://vos.so by default (VOS_ORIGIN
|
|
18963
19223
|
moves it; --studio http://localhost:6060 for a dev server).
|
|
18964
19224
|
|
|
18965
|
-
push/pull \u2014 the hosted iteration loop (credentials: --key,
|
|
18966
|
-
|
|
18967
|
-
|
|
19225
|
+
push/pull \u2014 the hosted iteration loop (credentials: --key, --account <handle>,
|
|
19226
|
+
VOS_API_KEY, VOS_ACCOUNT, or the account in use at ~/.config/vos/credentials
|
|
19227
|
+
via vos login, one sign-in per account and vos switch between them; origin
|
|
19228
|
+
via VOS_ORIGIN, default https://vos.so). A take push uploads the recording ONCE (content-addressed),
|
|
18968
19229
|
lowers doc.json, and creates a private vos (first push asks; --yes for
|
|
18969
19230
|
headless) or a new version against the base in vos.json \u2014 a stale base
|
|
18970
19231
|
prints the human's typed changelog and exits 1 (run pull, re-apply, push
|
|
18971
|
-
again).
|
|
19232
|
+
again). vos.json also names the ACCOUNT the directory belongs to, and a
|
|
19233
|
+
verb on it uses the stored credential for that account before the active
|
|
19234
|
+
one, so a take fetched as an organization pushes as it with no switch. A protected conflict means the human touched those nodes in the
|
|
18972
19235
|
studio: keep their values, or --override <id> ONLY when the user asked for
|
|
18973
19236
|
that exact change. ALWAYS pass --label (what you did, one line) and --note
|
|
18974
19237
|
(why: the user's ask) \u2014 the version history reads as a conversation, and an
|
|
@@ -20794,7 +21057,7 @@ reference and the only credential.`
|
|
|
20794
21057
|
}).replace(/\/+$/, "");
|
|
20795
21058
|
const landed = flags.wait === true ? await waitForLanded({
|
|
20796
21059
|
origin: pushedTo,
|
|
20797
|
-
key: requireCredential(
|
|
21060
|
+
key: requireCredential(credentialFlags(flags)),
|
|
20798
21061
|
vosId: result.vosId,
|
|
20799
21062
|
versionId: result.versionId ?? null,
|
|
20800
21063
|
log: (l) => r.log(l)
|
|
@@ -20915,6 +21178,8 @@ async function run(argv) {
|
|
|
20915
21178
|
return await cmdWhoami(rest);
|
|
20916
21179
|
case "logout":
|
|
20917
21180
|
return cmdLogout(rest);
|
|
21181
|
+
case "switch":
|
|
21182
|
+
return cmdSwitch(rest);
|
|
20918
21183
|
case "push": {
|
|
20919
21184
|
const target = rest.find((a) => !a.startsWith("-"));
|
|
20920
21185
|
if (target && isTakeDir(target)) return await cmdPush3(rest);
|
|
@@ -21177,4 +21442,4 @@ export {
|
|
|
21177
21442
|
verbHelp,
|
|
21178
21443
|
run
|
|
21179
21444
|
};
|
|
21180
|
-
//# sourceMappingURL=chunk-
|
|
21445
|
+
//# sourceMappingURL=chunk-ACWV3Y6Y.js.map
|