@osmo.inc/cli 0.1.22 → 0.1.23
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 +5 -1
- package/dist/osmo.js +147 -52
- package/package.json +4 -4
- package/release.json +9 -9
package/README.md
CHANGED
|
@@ -36,7 +36,11 @@ not required. Other CLI commands remain available on platforms without Studio.
|
|
|
36
36
|
When you want a review link for this project, run `osmo login`, then
|
|
37
37
|
`osmo studio deploy`. This uploads the source and video to one project review
|
|
38
38
|
page. Use `osmo studio clone PROJECT` to copy an accessible project for local
|
|
39
|
-
editing.
|
|
39
|
+
editing. Old web-editor projects download into `legacy-<id>/` with `README.md`,
|
|
40
|
+
`project.json`, `animations/`, and `assets.json`. These are conversion materials,
|
|
41
|
+
not runnable local projects: media remains as URLs, and no Git history or cloud
|
|
42
|
+
sync connection is created. Pass a folder argument to override the destination.
|
|
43
|
+
Cloud operations require login and retain existing source permissions.
|
|
40
44
|
|
|
41
45
|
## Share a video and collect feedback
|
|
42
46
|
|
package/dist/osmo.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/commands.ts
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import
|
|
4
|
+
import path7 from "node:path";
|
|
5
5
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
|
|
@@ -500,8 +500,8 @@ async function revoke(origin, state, save3) {
|
|
|
500
500
|
await save3();
|
|
501
501
|
return signedIn;
|
|
502
502
|
}
|
|
503
|
-
async function authCommand(args, flags = {}) {
|
|
504
|
-
const origin = authOrigin();
|
|
503
|
+
async function authCommand(args, flags = {}, requestedOrigin = authOrigin()) {
|
|
504
|
+
const origin = authOrigin({ OSMO_BASE_URL: requestedOrigin });
|
|
505
505
|
const scope = [
|
|
506
506
|
...IDENTITY_SCOPES,
|
|
507
507
|
...PERMISSIONS.filter(
|
|
@@ -1259,13 +1259,43 @@ function formatResources(result) {
|
|
|
1259
1259
|
}
|
|
1260
1260
|
|
|
1261
1261
|
// src/run.ts
|
|
1262
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1262
1263
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
1263
|
-
import { createWriteStream, openAsBlob, rmSync } from "node:fs";
|
|
1264
|
-
import { mkdir as mkdir3, readFile as readFile3, rename as rename3, rm as rm3, stat as stat2 } from "node:fs/promises";
|
|
1265
|
-
import
|
|
1264
|
+
import { createWriteStream, existsSync as existsSync2, openAsBlob, rmSync as rmSync2 } from "node:fs";
|
|
1265
|
+
import { mkdir as mkdir3, readFile as readFile3, rename as rename3, rm as rm3, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
|
|
1266
|
+
import path5 from "node:path";
|
|
1266
1267
|
import { Readable } from "node:stream";
|
|
1267
1268
|
import { pipeline } from "node:stream/promises";
|
|
1268
1269
|
|
|
1270
|
+
// src/cloud-pointer.ts
|
|
1271
|
+
import { spawnSync } from "node:child_process";
|
|
1272
|
+
|
|
1273
|
+
// src/git.ts
|
|
1274
|
+
import {
|
|
1275
|
+
existsSync,
|
|
1276
|
+
mkdirSync,
|
|
1277
|
+
readFileSync,
|
|
1278
|
+
renameSync,
|
|
1279
|
+
rmSync,
|
|
1280
|
+
writeFileSync
|
|
1281
|
+
} from "node:fs";
|
|
1282
|
+
import path4 from "node:path";
|
|
1283
|
+
var hasRepo = (root) => existsSync(path4.join(root, ".git"));
|
|
1284
|
+
|
|
1285
|
+
// src/cloud-pointer.ts
|
|
1286
|
+
var PROJECT_ID = /^[a-z0-9]{10,40}$/;
|
|
1287
|
+
function pointerFromGit(root) {
|
|
1288
|
+
const read = (key) => {
|
|
1289
|
+
const r = spawnSync("git", ["-C", root, "config", "--get", key], {
|
|
1290
|
+
encoding: "utf8"
|
|
1291
|
+
});
|
|
1292
|
+
return r.status === 0 ? r.stdout.trim() : "";
|
|
1293
|
+
};
|
|
1294
|
+
const origin = read("osmo.cloud.origin"), id = read("osmo.cloud.id");
|
|
1295
|
+
return origin && id ? { origin, id } : null;
|
|
1296
|
+
}
|
|
1297
|
+
var cloudPointer = (root) => hasRepo(root) ? pointerFromGit(root) : null;
|
|
1298
|
+
|
|
1269
1299
|
// src/cloud-request.ts
|
|
1270
1300
|
var PERMISSION_DOES = {
|
|
1271
1301
|
"projects:write": "change projects",
|
|
@@ -1318,12 +1348,17 @@ var UPLOAD_MAX_BYTES = 100 * 1024 * 1024;
|
|
|
1318
1348
|
var TRANSFER_MS = 15 * 6e4;
|
|
1319
1349
|
var EXTENSIONS = {
|
|
1320
1350
|
"video/mp4": "mp4",
|
|
1351
|
+
"video/quicktime": "mov",
|
|
1352
|
+
"video/webm": "webm",
|
|
1321
1353
|
"image/png": "png",
|
|
1322
1354
|
"image/jpeg": "jpg",
|
|
1323
1355
|
"image/webp": "webp",
|
|
1356
|
+
"image/gif": "gif",
|
|
1324
1357
|
"image/svg+xml": "svg",
|
|
1325
1358
|
"audio/mpeg": "mp3",
|
|
1326
|
-
"audio/wav": "wav"
|
|
1359
|
+
"audio/wav": "wav",
|
|
1360
|
+
"audio/mp4": "m4a",
|
|
1361
|
+
"audio/ogg": "ogg"
|
|
1327
1362
|
};
|
|
1328
1363
|
var jobPattern = /^run_[a-z0-9]{8,40}$/;
|
|
1329
1364
|
var invalidInput = (detail, issues) => new OsmoError(
|
|
@@ -1569,7 +1604,7 @@ function fileSource(value) {
|
|
|
1569
1604
|
return { kind: "local", file: value };
|
|
1570
1605
|
}
|
|
1571
1606
|
function uploadType(name) {
|
|
1572
|
-
return UPLOAD_TYPES[
|
|
1607
|
+
return UPLOAD_TYPES[path5.extname(name).slice(1).toLowerCase()];
|
|
1573
1608
|
}
|
|
1574
1609
|
var megabytes = (n) => n < 1048576 ? `${Math.max(1, Math.round(n / 1024))} KB` : `${(n / 1048576).toFixed(1)} MB`;
|
|
1575
1610
|
async function resolveFiles(schema, input, issues, io) {
|
|
@@ -1605,12 +1640,12 @@ async function resolveFiles(schema, input, issues, io) {
|
|
|
1605
1640
|
else if (!uploadType(job.source.file))
|
|
1606
1641
|
issues.push({
|
|
1607
1642
|
path: job.path,
|
|
1608
|
-
message: `${
|
|
1643
|
+
message: `${path5.basename(job.source.file)} isn't a type runs take (${Object.keys(UPLOAD_TYPES).join(", ")})`
|
|
1609
1644
|
});
|
|
1610
1645
|
else if (info.size > UPLOAD_MAX_BYTES || info.size === 0)
|
|
1611
1646
|
issues.push({
|
|
1612
1647
|
path: job.path,
|
|
1613
|
-
message: `${
|
|
1648
|
+
message: `${path5.basename(job.source.file)} must be 1 byte to ${megabytes(UPLOAD_MAX_BYTES)}`
|
|
1614
1649
|
});
|
|
1615
1650
|
}
|
|
1616
1651
|
return async () => {
|
|
@@ -1619,7 +1654,7 @@ async function resolveFiles(schema, input, issues, io) {
|
|
|
1619
1654
|
const { file } = job.source;
|
|
1620
1655
|
const type = uploadType(file);
|
|
1621
1656
|
const blob = await openAsBlob(file, { type });
|
|
1622
|
-
io.log(`uploading ${
|
|
1657
|
+
io.log(`uploading ${path5.basename(file)} (${megabytes(blob.size)})`);
|
|
1623
1658
|
job.set(await upload(blob, type));
|
|
1624
1659
|
} else if (job.source.kind === "web") {
|
|
1625
1660
|
io.log(`fetching ${job.source.url}`);
|
|
@@ -1807,34 +1842,71 @@ Next: ${next}`
|
|
|
1807
1842
|
stop();
|
|
1808
1843
|
}
|
|
1809
1844
|
}
|
|
1845
|
+
function projectFolder(start = process.cwd()) {
|
|
1846
|
+
for (let dir = path5.resolve(start); ; dir = path5.dirname(dir)) {
|
|
1847
|
+
if (existsSync2(path5.join(dir, ".osmo/project.json"))) return dir;
|
|
1848
|
+
if (path5.dirname(dir) === dir) return null;
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
function here() {
|
|
1852
|
+
const root = projectFolder();
|
|
1853
|
+
if (!root) return null;
|
|
1854
|
+
const pointer = cloudPointer(root);
|
|
1855
|
+
let same = false;
|
|
1856
|
+
try {
|
|
1857
|
+
same = !!pointer && PROJECT_ID.test(pointer.id) && new URL(pointer.origin).origin === new URL(authOrigin()).origin;
|
|
1858
|
+
} catch {
|
|
1859
|
+
}
|
|
1860
|
+
return same && pointer ? { root, project: pointer.id } : { root };
|
|
1861
|
+
}
|
|
1862
|
+
async function generationsFolder(root) {
|
|
1863
|
+
const ours = path5.join(root, "generations");
|
|
1864
|
+
const listed = hasRepo(root) ? spawnSync2("git", ["-C", root, "ls-files", "--", "generations"], {
|
|
1865
|
+
encoding: "utf8"
|
|
1866
|
+
}) : null;
|
|
1867
|
+
const tracked = listed?.status === 0 && listed.stdout.trim() !== "";
|
|
1868
|
+
const theirs = tracked || existsSync2(ours) && !existsSync2(path5.join(ours, ".gitignore"));
|
|
1869
|
+
const folder = theirs ? path5.join(root, "osmo-generations") : ours;
|
|
1870
|
+
await mkdir3(folder, { recursive: true });
|
|
1871
|
+
const ignore = path5.join(folder, ".gitignore");
|
|
1872
|
+
if (!existsSync2(ignore)) await writeFile3(ignore, "*\n");
|
|
1873
|
+
return folder;
|
|
1874
|
+
}
|
|
1810
1875
|
async function targets(run, out2) {
|
|
1811
1876
|
const model = (run.model.split("/").pop() ?? "").replace(/[^A-Za-z0-9.-]/g, "-").replace(/^[.-]+/, "") || "output";
|
|
1812
1877
|
const name = `${model}-${run.job.slice(4, 12)}`;
|
|
1813
1878
|
const extension = (o) => {
|
|
1814
|
-
const fromUrl =
|
|
1879
|
+
const fromUrl = path5.extname(new URL(o.url).pathname).slice(1);
|
|
1815
1880
|
return EXTENSIONS[o.mime] ?? (/^[A-Za-z0-9]{1,5}$/.test(fromUrl) ? fromUrl : "bin");
|
|
1816
1881
|
};
|
|
1817
1882
|
const several = run.outputs.length > 1;
|
|
1818
1883
|
const named = run.outputs.map(
|
|
1819
1884
|
(o, i) => `${name}${several ? `-${i + 1}` : ""}.${extension(o)}`
|
|
1820
1885
|
);
|
|
1821
|
-
if (out2 === void 0)
|
|
1822
|
-
|
|
1886
|
+
if (out2 === void 0) {
|
|
1887
|
+
const project = here();
|
|
1888
|
+
if (!project) return named;
|
|
1889
|
+
const folder2 = await generationsFolder(project.root);
|
|
1890
|
+
return named.map(
|
|
1891
|
+
(n) => path5.relative(process.cwd(), path5.join(folder2, n)) || n
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
const folder = /[/\\]$/.test(out2) || (await stat2(out2).catch(() => null))?.isDirectory() || several && !path5.extname(out2);
|
|
1823
1895
|
if (!folder) {
|
|
1824
1896
|
if (!several)
|
|
1825
1897
|
return run.outputs.map(
|
|
1826
|
-
(o) =>
|
|
1898
|
+
(o) => path5.extname(out2) ? out2 : `${out2}.${extension(o)}`
|
|
1827
1899
|
);
|
|
1828
|
-
const stem = out2.slice(0, -
|
|
1900
|
+
const stem = out2.slice(0, -path5.extname(out2).length);
|
|
1829
1901
|
return run.outputs.map((o, i) => `${stem}-${i + 1}.${extension(o)}`);
|
|
1830
1902
|
}
|
|
1831
1903
|
await mkdir3(out2, { recursive: true });
|
|
1832
|
-
return named.map((file) =>
|
|
1904
|
+
return named.map((file) => path5.join(out2, file));
|
|
1833
1905
|
}
|
|
1834
1906
|
async function save2(run, out2, io) {
|
|
1835
1907
|
let partial;
|
|
1836
1908
|
const stop = onInterrupt(() => {
|
|
1837
|
-
if (partial)
|
|
1909
|
+
if (partial) rmSync2(partial, { force: true });
|
|
1838
1910
|
writeNow(
|
|
1839
1911
|
io.json ? 1 : 2,
|
|
1840
1912
|
io.json ? JSON.stringify({
|
|
@@ -1863,7 +1935,7 @@ Next: ${pickUp(run.job, out2)}`
|
|
|
1863
1935
|
gone ? `${run.job}'s outputs are no longer kept. Outputs last 30 days.` : `Couldn't download ${run.job}'s output${response ? ` (${response.status})` : ""}.`,
|
|
1864
1936
|
gone ? void 0 : pickUp(run.job, out2)
|
|
1865
1937
|
);
|
|
1866
|
-
await mkdir3(
|
|
1938
|
+
await mkdir3(path5.dirname(path5.resolve(file)), { recursive: true });
|
|
1867
1939
|
partial = `${file}.part-${process.pid}`;
|
|
1868
1940
|
try {
|
|
1869
1941
|
await pipeline(
|
|
@@ -1880,7 +1952,7 @@ Next: ${pickUp(run.job, out2)}`
|
|
|
1880
1952
|
partial = void 0;
|
|
1881
1953
|
}
|
|
1882
1954
|
const bytes2 = (await stat2(file)).size;
|
|
1883
|
-
const said =
|
|
1955
|
+
const said = path5.extname(file).slice(1).toLowerCase();
|
|
1884
1956
|
const made = EXTENSIONS[output.mime];
|
|
1885
1957
|
if (out2 !== void 0 && said && made && (said === "jpeg" ? "jpg" : said) !== made)
|
|
1886
1958
|
io.log(`${file} holds ${output.mime}, which its name doesn't say.`);
|
|
@@ -1969,7 +2041,7 @@ async function runCommand(id, flags, io) {
|
|
|
1969
2041
|
const schema = detail.run.inputSchema;
|
|
1970
2042
|
const base = flags.inputs ? await readInputsFile(flags.inputs) : {};
|
|
1971
2043
|
const { input, issues } = buildInputs(schema, flags.input ?? [], base);
|
|
1972
|
-
const wanted =
|
|
2044
|
+
const wanted = path5.extname(flags.out ?? "").slice(1).toLowerCase();
|
|
1973
2045
|
const formats = schema.properties?.format?.enum;
|
|
1974
2046
|
if (wanted && formats && input.format === void 0 && !issues.length) {
|
|
1975
2047
|
const format = wanted === "jpeg" ? "jpg" : wanted;
|
|
@@ -2003,6 +2075,7 @@ Next: ${error.next}`
|
|
|
2003
2075
|
);
|
|
2004
2076
|
});
|
|
2005
2077
|
const key = randomUUID2();
|
|
2078
|
+
const linked = here()?.project;
|
|
2006
2079
|
const refusedFirst = (code) => ["runs_disabled", "model_unavailable"].includes(code ?? "");
|
|
2007
2080
|
let started;
|
|
2008
2081
|
try {
|
|
@@ -2014,7 +2087,9 @@ Next: ${error.next}`
|
|
|
2014
2087
|
body: {
|
|
2015
2088
|
model: detail.id,
|
|
2016
2089
|
inputs: input,
|
|
2017
|
-
...flags.workspace ? { workspace: flags.workspace } : {}
|
|
2090
|
+
...flags.workspace ? { workspace: flags.workspace } : {},
|
|
2091
|
+
// The linked project this runs in: the run is listed with it.
|
|
2092
|
+
...linked ? { project: linked } : {}
|
|
2018
2093
|
},
|
|
2019
2094
|
wait: 0,
|
|
2020
2095
|
headers: { "Idempotency-Key": key }
|
|
@@ -2074,6 +2149,8 @@ async function jobsCommand(job, flags, io) {
|
|
|
2074
2149
|
if (job === void 0) {
|
|
2075
2150
|
const params = new URLSearchParams({ limit: flags.limit ?? "20" });
|
|
2076
2151
|
if (flags.cursor) params.set("cursor", flags.cursor);
|
|
2152
|
+
const project = flags.all ? void 0 : here()?.project;
|
|
2153
|
+
if (project) params.set("project", project);
|
|
2077
2154
|
const page = await api(`/api/runs?${params}`);
|
|
2078
2155
|
if (page.status === 400 && page.data.error === "invalid_cursor")
|
|
2079
2156
|
throw new UsageError(
|
|
@@ -2091,7 +2168,9 @@ async function jobsCommand(job, flags, io) {
|
|
|
2091
2168
|
status: "ok",
|
|
2092
2169
|
runs: page.data.runs,
|
|
2093
2170
|
nextCursor: page.data.nextCursor ?? null,
|
|
2094
|
-
|
|
2171
|
+
...project ? { inProject: true } : {},
|
|
2172
|
+
...flags.all ? { all: true } : {},
|
|
2173
|
+
next: page.data.runs.length ? "osmo jobs JOB" : project ? "osmo jobs --all" : "osmo resources list --type model"
|
|
2095
2174
|
};
|
|
2096
2175
|
}
|
|
2097
2176
|
if (!jobPattern.test(job))
|
|
@@ -2175,7 +2254,9 @@ Next: ${r.next}`;
|
|
|
2175
2254
|
}
|
|
2176
2255
|
function formatJobs(result) {
|
|
2177
2256
|
const r = result;
|
|
2178
|
-
if (!r.runs.length)
|
|
2257
|
+
if (!r.runs.length)
|
|
2258
|
+
return r.inProject ? `No runs in this project yet. osmo jobs --all lists all of yours.
|
|
2259
|
+
Next: ${r.next}` : `No runs yet.
|
|
2179
2260
|
Next: ${r.next}`;
|
|
2180
2261
|
const when = (iso) => {
|
|
2181
2262
|
const d = new Date(iso);
|
|
@@ -2194,7 +2275,9 @@ Next: ${r.next}`;
|
|
|
2194
2275
|
...rows.map(
|
|
2195
2276
|
(row) => row.map((cell, i) => i < 3 ? cell.padEnd(widths[i]) : cell).join(" ")
|
|
2196
2277
|
),
|
|
2197
|
-
...r.nextCursor ? [
|
|
2278
|
+
...r.nextCursor ? [
|
|
2279
|
+
`\u2026 and older runs. Continue with: osmo jobs --cursor ${r.nextCursor}${r.all ? " --all" : ""}`
|
|
2280
|
+
] : [],
|
|
2198
2281
|
"",
|
|
2199
2282
|
`Next: ${r.next}`
|
|
2200
2283
|
].join("\n");
|
|
@@ -2344,24 +2427,27 @@ async function deleteShare(value, yes = false) {
|
|
|
2344
2427
|
async function unshare(value) {
|
|
2345
2428
|
const share = await resolveShare(value);
|
|
2346
2429
|
const origin = authOrigin();
|
|
2430
|
+
await unshareProject(share.id, origin);
|
|
2431
|
+
const restore = newVersion(share);
|
|
2432
|
+
return {
|
|
2433
|
+
status: "unshared",
|
|
2434
|
+
share: share.id,
|
|
2435
|
+
...restore ? { restore } : {}
|
|
2436
|
+
};
|
|
2437
|
+
}
|
|
2438
|
+
async function unshareProject(projectId, origin) {
|
|
2347
2439
|
const done = await call(
|
|
2348
2440
|
origin,
|
|
2349
|
-
`/api/projects/${
|
|
2441
|
+
`/api/projects/${projectId}/share`,
|
|
2350
2442
|
{ method: "DELETE", allow: [403] }
|
|
2351
2443
|
);
|
|
2352
2444
|
if (done.error === "scope_required") throw scopeRequired(origin, done.scope);
|
|
2353
2445
|
if (done.error)
|
|
2354
2446
|
throw new OsmoError(
|
|
2355
2447
|
"forbidden",
|
|
2356
|
-
`Only an owner of share ${
|
|
2448
|
+
`Only an owner of share ${projectId} can unshare it.`,
|
|
2357
2449
|
"osmo shares"
|
|
2358
2450
|
);
|
|
2359
|
-
const restore = newVersion(share);
|
|
2360
|
-
return {
|
|
2361
|
-
status: "unshared",
|
|
2362
|
-
share: share.id,
|
|
2363
|
-
...restore ? { restore } : {}
|
|
2364
|
-
};
|
|
2365
2451
|
}
|
|
2366
2452
|
async function shareComments(value, {
|
|
2367
2453
|
open = false,
|
|
@@ -2597,7 +2683,7 @@ function formatUsage(result, now = Date.now()) {
|
|
|
2597
2683
|
// src/video-deploy.ts
|
|
2598
2684
|
import { execFile } from "node:child_process";
|
|
2599
2685
|
import { stat as stat3 } from "node:fs/promises";
|
|
2600
|
-
import
|
|
2686
|
+
import path6 from "node:path";
|
|
2601
2687
|
import { promisify } from "node:util";
|
|
2602
2688
|
|
|
2603
2689
|
// src/upload-render.ts
|
|
@@ -2766,9 +2852,9 @@ async function shareVideo(file, {
|
|
|
2766
2852
|
if (to !== void 0) parseShare(to, origin);
|
|
2767
2853
|
if (name !== void 0 && (!name.trim() || name.trim().length > 200))
|
|
2768
2854
|
throw new Error("--name takes 1 to 200 characters.");
|
|
2769
|
-
const source =
|
|
2855
|
+
const source = path6.resolve(file), metadata = await probeVideo(source);
|
|
2770
2856
|
await currentAccount(origin);
|
|
2771
|
-
const title = name?.trim() ??
|
|
2857
|
+
const title = name?.trim() ?? path6.basename(source).slice(0, 200);
|
|
2772
2858
|
const target = to === void 0 ? void 0 : await resolveShare(to);
|
|
2773
2859
|
if (target?.kind === "repo")
|
|
2774
2860
|
throw new OsmoError(
|
|
@@ -2811,14 +2897,14 @@ Retry with --to ${share} to add it to the same share.`,
|
|
|
2811
2897
|
}
|
|
2812
2898
|
|
|
2813
2899
|
// src/commands.ts
|
|
2814
|
-
var auth = (
|
|
2815
|
-
path:
|
|
2900
|
+
var auth = (path8, usage, about, args, flags) => ({
|
|
2901
|
+
path: path8,
|
|
2816
2902
|
group: "Account",
|
|
2817
2903
|
usage,
|
|
2818
2904
|
about,
|
|
2819
2905
|
args,
|
|
2820
2906
|
flags,
|
|
2821
|
-
run: (rest, flags2) => authCommand([...
|
|
2907
|
+
run: (rest, flags2) => authCommand([...path8, ...rest], flags2),
|
|
2822
2908
|
text: (result) => formatAuth(result),
|
|
2823
2909
|
failed: (result) => ["denied", "expired"].includes(result.status)
|
|
2824
2910
|
});
|
|
@@ -3044,7 +3130,7 @@ var COMMANDS = [
|
|
|
3044
3130
|
},
|
|
3045
3131
|
out: out(
|
|
3046
3132
|
"PATH",
|
|
3047
|
-
"A file for one output, replacing one of that name, or a folder. A file name with no extension gets the output's. Default: MODEL-JOB.EXT here."
|
|
3133
|
+
"A file for one output, replacing one of that name, or a folder. A file name with no extension gets the output's. Default: MODEL-JOB.EXT in the project's generations/ (kept out of its versions), or here outside a project."
|
|
3048
3134
|
),
|
|
3049
3135
|
"no-wait": {
|
|
3050
3136
|
type: "boolean",
|
|
@@ -3065,13 +3151,13 @@ var COMMANDS = [
|
|
|
3065
3151
|
{
|
|
3066
3152
|
path: ["jobs"],
|
|
3067
3153
|
group: "Resources and models",
|
|
3068
|
-
usage: "jobs [JOB] [--out PATH] [--limit N]",
|
|
3069
|
-
about: "Lists your recent runs, newest first. With a JOB, waits for it and saves its outputs, which are kept for 30 days.",
|
|
3154
|
+
usage: "jobs [JOB] [--out PATH] [--limit N] [--all]",
|
|
3155
|
+
about: "Lists your recent runs, newest first: in a project linked to the cloud, that project's. With a JOB, waits for it and saves its outputs, which are kept for 30 days.",
|
|
3070
3156
|
args: [0, 1],
|
|
3071
3157
|
flags: {
|
|
3072
3158
|
out: out(
|
|
3073
3159
|
"PATH",
|
|
3074
|
-
"A file for one output, replacing one of that name, or a folder. A file name with no extension gets the output's. Default: MODEL-JOB.EXT here."
|
|
3160
|
+
"A file for one output, replacing one of that name, or a folder. A file name with no extension gets the output's. Default: MODEL-JOB.EXT in the project's generations/ (kept out of its versions), or here outside a project."
|
|
3075
3161
|
),
|
|
3076
3162
|
limit: {
|
|
3077
3163
|
type: "string",
|
|
@@ -3082,6 +3168,10 @@ var COMMANDS = [
|
|
|
3082
3168
|
type: "string",
|
|
3083
3169
|
value: "CURSOR",
|
|
3084
3170
|
help: "Continue a cut-off list from its nextCursor."
|
|
3171
|
+
},
|
|
3172
|
+
all: {
|
|
3173
|
+
type: "boolean",
|
|
3174
|
+
help: "List all your runs, not only this project's."
|
|
3085
3175
|
}
|
|
3086
3176
|
},
|
|
3087
3177
|
example: "osmo jobs run_abc12345",
|
|
@@ -3096,6 +3186,11 @@ var COMMANDS = [
|
|
|
3096
3186
|
"--out needs a job: osmo jobs JOB --out PATH.",
|
|
3097
3187
|
"osmo jobs --help"
|
|
3098
3188
|
);
|
|
3189
|
+
if (args.length && flags.all)
|
|
3190
|
+
throw new UsageError(
|
|
3191
|
+
"--all widens the list, which osmo jobs prints without a JOB.",
|
|
3192
|
+
"osmo jobs --help"
|
|
3193
|
+
);
|
|
3099
3194
|
if (args.length && (flags.limit !== void 0 || flags.cursor !== void 0))
|
|
3100
3195
|
throw new UsageError(
|
|
3101
3196
|
"--limit and --cursor page the list, which osmo jobs prints without a JOB.",
|
|
@@ -3289,7 +3384,7 @@ Version: ${r.versionLink}`;
|
|
|
3289
3384
|
studio(
|
|
3290
3385
|
"clone",
|
|
3291
3386
|
"PROJECT [FOLDER]",
|
|
3292
|
-
"Copies a project
|
|
3387
|
+
"Copies a cloud project and its history into a new folder. Legacy web-editor projects download as text exports with asset URLs and require conversion before local editing. PROJECT is an ID or project/review link. FOLDER defaults to the project name, or legacy-<id> for legacy exports. Needs osmo login and source access.",
|
|
3293
3388
|
[1, 2],
|
|
3294
3389
|
{ example: "osmo studio clone https://studio.osmo.inc/app/projects/ID" }
|
|
3295
3390
|
),
|
|
@@ -3490,9 +3585,9 @@ var GLOBAL_FLAGS = {
|
|
|
3490
3585
|
function findCommand(words2) {
|
|
3491
3586
|
let found;
|
|
3492
3587
|
for (const command of COMMANDS)
|
|
3493
|
-
for (const
|
|
3494
|
-
if (
|
|
3495
|
-
found = { command, length:
|
|
3588
|
+
for (const path8 of [command.path, ...command.aliases ?? []])
|
|
3589
|
+
if (path8.length <= words2.length && path8.every((word, i) => words2[i] === word) && path8.length > (found?.length ?? 0))
|
|
3590
|
+
found = { command, length: path8.length };
|
|
3496
3591
|
return found && { command: found.command, rest: words2.slice(found.length) };
|
|
3497
3592
|
}
|
|
3498
3593
|
function commandHelp(command) {
|
|
@@ -3504,7 +3599,7 @@ function commandHelp(command) {
|
|
|
3504
3599
|
);
|
|
3505
3600
|
const width = Math.max(...names.map((name) => name.length));
|
|
3506
3601
|
const aliases = (command.aliases ?? []).map(
|
|
3507
|
-
(
|
|
3602
|
+
(path8) => `osmo ${path8.join(" ")}`
|
|
3508
3603
|
);
|
|
3509
3604
|
return [
|
|
3510
3605
|
`osmo ${command.usage}`,
|
|
@@ -3684,17 +3779,17 @@ async function loadStudio() {
|
|
|
3684
3779
|
manifest2 = createRequire(import.meta.url).resolve(
|
|
3685
3780
|
`@osmo.inc/cli-${platform}/package.json`
|
|
3686
3781
|
);
|
|
3687
|
-
entry =
|
|
3782
|
+
entry = path7.join(path7.dirname(manifest2), "dist/studio.js");
|
|
3688
3783
|
} catch {
|
|
3689
3784
|
}
|
|
3690
|
-
if (!
|
|
3785
|
+
if (!existsSync3(entry))
|
|
3691
3786
|
throw new OsmoError(
|
|
3692
3787
|
"studio_unavailable",
|
|
3693
3788
|
PLATFORMS.includes(platform) ? `Osmo Studio and its renderer aren't installed: @osmo.inc/cli-${platform} is missing. Reinstall @osmo.inc/cli with optional dependencies; if that doesn't add it, this release has no package for ${platform}.` : `Osmo Studio's renderer isn't available for ${platform} yet. It runs on ${PLATFORMS.join(", ")}.`,
|
|
3694
3789
|
PLATFORMS.includes(platform) ? "npm install -g @osmo.inc/cli" : void 0
|
|
3695
3790
|
);
|
|
3696
3791
|
if (manifest2) {
|
|
3697
|
-
const installed = JSON.parse(
|
|
3792
|
+
const installed = JSON.parse(readFileSync2(manifest2, "utf8")).version;
|
|
3698
3793
|
if (installed !== version)
|
|
3699
3794
|
throw new OsmoError(
|
|
3700
3795
|
"studio_mismatch",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osmo.inc/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"fflate"
|
|
34
34
|
],
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@osmo.inc/cli-darwin-arm64": "0.1.
|
|
37
|
-
"@osmo.inc/cli-linux-x64": "0.1.
|
|
38
|
-
"@osmo.inc/cli-linux-arm64": "0.1.
|
|
36
|
+
"@osmo.inc/cli-darwin-arm64": "0.1.23",
|
|
37
|
+
"@osmo.inc/cli-linux-x64": "0.1.23",
|
|
38
|
+
"@osmo.inc/cli-linux-arm64": "0.1.23"
|
|
39
39
|
}
|
|
40
40
|
}
|
package/release.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.23",
|
|
3
3
|
"package": "@osmo.inc/cli",
|
|
4
4
|
"platform": "any",
|
|
5
5
|
"channel": "latest",
|
|
6
6
|
"defaultCloudOrigin": "https://studio.osmo.inc",
|
|
7
|
-
"sourceCommit": "
|
|
7
|
+
"sourceCommit": "e865c900aafb496ce6520ab1308f911087337ccf",
|
|
8
8
|
"sourceDirty": false,
|
|
9
9
|
"licenseFileIncluded": false,
|
|
10
10
|
"dependencyCount": 1,
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"contents": {
|
|
22
|
-
"totalBytes":
|
|
22
|
+
"totalBytes": 258185,
|
|
23
23
|
"fileCount": 13,
|
|
24
24
|
"groups": {
|
|
25
|
-
"dist":
|
|
25
|
+
"dist": 141437,
|
|
26
26
|
"node_modules/fflate": 96377,
|
|
27
27
|
"DEPLOY.md": 6514,
|
|
28
28
|
"third-party": 4850,
|
|
29
|
-
"README.md":
|
|
29
|
+
"README.md": 3970,
|
|
30
30
|
"SETUP.md": 2893,
|
|
31
31
|
"bin": 1001,
|
|
32
32
|
"package.json": 788,
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"largestFiles": [
|
|
36
36
|
{
|
|
37
37
|
"path": "dist/osmo.js",
|
|
38
|
-
"bytes":
|
|
38
|
+
"bytes": 141437
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"path": "node_modules/fflate/esm/index.mjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"path": "README.md",
|
|
50
|
-
"bytes":
|
|
50
|
+
"bytes": 3970
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"path": "third-party/npm/fflate@0.8.3/package.json",
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
]
|
|
89
89
|
},
|
|
90
90
|
"hashes": {
|
|
91
|
-
"dist/osmo.js": "
|
|
91
|
+
"dist/osmo.js": "049c78e40164dbf2c1f0b6edbb42f3367ee53f30349b2256e7745472278bf985",
|
|
92
92
|
"third-party/inventory.json": "3927f7452a7e60b86aa376f17c549311f4d55327a33f5ac2a82d337a14b38f0b"
|
|
93
93
|
},
|
|
94
94
|
"lockfiles": {
|
|
95
|
-
"package-lock.json": "
|
|
95
|
+
"package-lock.json": "2d0f9f1a32d5196c97f3a6cc4116390870c667686cf562ba17f5addb83ed6a01",
|
|
96
96
|
"apps/native/Cargo.lock": "cf31d67cf167c5f32438abfeb42159eb50da61d36e4e482bae50ed3d71241373",
|
|
97
97
|
"packages/render-engine/Cargo.lock": "a1a68051e1eea30ef0fa46bf17cd0685bb2c6a327defed0405e0d63dd61017a7"
|
|
98
98
|
}
|