vibeview 0.20.4 → 0.22.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/dist/{chunk-BBGXBKJQ.js → chunk-SHS5PCSS.js} +112 -47
- package/dist/{chunk-KON2FOEC.js → chunk-UGCGJ6IN.js} +7 -0
- package/dist/cli.js +205 -120
- package/dist/{server-WOIB6CDQ.js → server-6IJ44HAX.js} +126 -11
- package/dist/{upload-app-W6NOSJPA.js → upload-app-LJH3PETS.js} +1 -1
- package/package.json +1 -1
- package/skills/vibeview-agent/SKILL.md +20 -4
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
BUILD_TERMINAL_STATUSES,
|
|
5
5
|
buildCommand,
|
|
6
6
|
clearDevState,
|
|
7
|
+
createRokuPush,
|
|
7
8
|
dev,
|
|
8
9
|
fetchFinalSummary,
|
|
9
10
|
formatDuration,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
readDevState,
|
|
16
17
|
readMetroState,
|
|
17
18
|
runAgentVerb
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-SHS5PCSS.js";
|
|
19
20
|
import {
|
|
20
21
|
ApiClient,
|
|
21
22
|
EXIT_INFRA_ERROR,
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
resolveAuth,
|
|
29
30
|
saveConfig,
|
|
30
31
|
uploadApp
|
|
31
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-UGCGJ6IN.js";
|
|
32
33
|
|
|
33
34
|
// src/cli.ts
|
|
34
35
|
import { createRequire } from "module";
|
|
@@ -1143,23 +1144,102 @@ async function devStop(opts) {
|
|
|
1143
1144
|
process.exit(0);
|
|
1144
1145
|
}
|
|
1145
1146
|
|
|
1147
|
+
// src/commands/dev-reload.ts
|
|
1148
|
+
import chalk10 from "chalk";
|
|
1149
|
+
function fail(opts, code, message, exit) {
|
|
1150
|
+
if (opts.json) {
|
|
1151
|
+
console.log(JSON.stringify({ reloaded: false, code, message }));
|
|
1152
|
+
} else {
|
|
1153
|
+
console.error(chalk10.red(`error: ${message}`));
|
|
1154
|
+
}
|
|
1155
|
+
process.exit(exit);
|
|
1156
|
+
}
|
|
1157
|
+
async function devReload(opts) {
|
|
1158
|
+
const cwd = process.cwd();
|
|
1159
|
+
const state = readDevState(cwd);
|
|
1160
|
+
if (!state) {
|
|
1161
|
+
fail(
|
|
1162
|
+
opts,
|
|
1163
|
+
"no_dev_session",
|
|
1164
|
+
"No dev session running (or it was not started with --detach).",
|
|
1165
|
+
1
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
if (state.platform !== "roku") {
|
|
1169
|
+
fail(
|
|
1170
|
+
opts,
|
|
1171
|
+
"not_roku",
|
|
1172
|
+
`dev-reload is for Roku channels; a ${state.platform} session hot-reloads through Metro on its own.`,
|
|
1173
|
+
2
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
let build;
|
|
1177
|
+
try {
|
|
1178
|
+
build = loadDevConfig(cwd)?.platforms?.roku?.build;
|
|
1179
|
+
} catch (err) {
|
|
1180
|
+
fail(
|
|
1181
|
+
opts,
|
|
1182
|
+
"config_required",
|
|
1183
|
+
`vibeview.json could not be read: ${err instanceof Error ? err.message : String(err)}`,
|
|
1184
|
+
1
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
if (!build) {
|
|
1188
|
+
fail(
|
|
1189
|
+
opts,
|
|
1190
|
+
"config_required",
|
|
1191
|
+
"no build config for roku \u2014 run `vibeview build --platform roku` once to set it up",
|
|
1192
|
+
1
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
const { token, baseUrl } = resolveAuth(opts);
|
|
1196
|
+
const api = new ApiClient(baseUrl, token);
|
|
1197
|
+
const push = createRokuPush({
|
|
1198
|
+
cwd,
|
|
1199
|
+
sessionId: state.session_id,
|
|
1200
|
+
build,
|
|
1201
|
+
token,
|
|
1202
|
+
baseUrl,
|
|
1203
|
+
api,
|
|
1204
|
+
// Build output and the "reloaded in" line are human output: stderr, so
|
|
1205
|
+
// stdout stays reserved for the --json result.
|
|
1206
|
+
log: (line) => console.error(chalk10.dim(line))
|
|
1207
|
+
});
|
|
1208
|
+
const started = Date.now();
|
|
1209
|
+
try {
|
|
1210
|
+
await push();
|
|
1211
|
+
} catch (err) {
|
|
1212
|
+
fail(opts, "reload_failed", err instanceof Error ? err.message : String(err), 1);
|
|
1213
|
+
}
|
|
1214
|
+
if (opts.json) {
|
|
1215
|
+
console.log(
|
|
1216
|
+
JSON.stringify({
|
|
1217
|
+
reloaded: true,
|
|
1218
|
+
session_id: state.session_id,
|
|
1219
|
+
seconds: (Date.now() - started) / 1e3
|
|
1220
|
+
})
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
process.exit(0);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1146
1226
|
// src/commands/builds.ts
|
|
1147
|
-
import
|
|
1227
|
+
import chalk12 from "chalk";
|
|
1148
1228
|
|
|
1149
1229
|
// src/lib/formatters/builds.ts
|
|
1150
|
-
import
|
|
1230
|
+
import chalk11 from "chalk";
|
|
1151
1231
|
var HEADERS = ["ID", "PLATFORM", "STATUS", "CREATED", "COST", "APP"];
|
|
1152
1232
|
function formatCostCell(costMicro) {
|
|
1153
1233
|
return costMicro > 0 ? `$${(costMicro / 1e6).toFixed(2)}` : "";
|
|
1154
1234
|
}
|
|
1155
1235
|
var STATUS_COLOR = {
|
|
1156
|
-
succeeded:
|
|
1157
|
-
failed:
|
|
1158
|
-
timed_out:
|
|
1159
|
-
infra_failed:
|
|
1160
|
-
canceled:
|
|
1161
|
-
running:
|
|
1162
|
-
queued:
|
|
1236
|
+
succeeded: chalk11.green,
|
|
1237
|
+
failed: chalk11.red,
|
|
1238
|
+
timed_out: chalk11.red,
|
|
1239
|
+
infra_failed: chalk11.red,
|
|
1240
|
+
canceled: chalk11.dim,
|
|
1241
|
+
running: chalk11.yellow,
|
|
1242
|
+
queued: chalk11.dim
|
|
1163
1243
|
};
|
|
1164
1244
|
function formatBuildsHuman(builds2) {
|
|
1165
1245
|
if (builds2.length === 0) {
|
|
@@ -1176,7 +1256,7 @@ function formatBuildsHuman(builds2) {
|
|
|
1176
1256
|
const widths = HEADERS.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1177
1257
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1178
1258
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1179
|
-
const lines = [
|
|
1259
|
+
const lines = [chalk11.bold(join3(padCells(HEADERS)))];
|
|
1180
1260
|
for (const row of rows) {
|
|
1181
1261
|
const padded = padCells(row);
|
|
1182
1262
|
const colorFn = STATUS_COLOR[row[2]] ?? ((s) => s);
|
|
@@ -1235,7 +1315,7 @@ async function buildsLogs(id, opts, deps) {
|
|
|
1235
1315
|
console.log(JSON.stringify(logs));
|
|
1236
1316
|
} else {
|
|
1237
1317
|
if (logs.content) process.stdout.write(logs.content);
|
|
1238
|
-
console.error(
|
|
1318
|
+
console.error(chalk12.dim(`status: ${logs.status}`));
|
|
1239
1319
|
}
|
|
1240
1320
|
process.exitCode = 0;
|
|
1241
1321
|
return;
|
|
@@ -1332,7 +1412,7 @@ async function buildsDownload(id, opts, deps) {
|
|
|
1332
1412
|
if (opts.json) {
|
|
1333
1413
|
console.log(JSON.stringify(result));
|
|
1334
1414
|
} else {
|
|
1335
|
-
console.log(
|
|
1415
|
+
console.log(chalk12.green(`\u2713 saved ${result.path}`));
|
|
1336
1416
|
}
|
|
1337
1417
|
process.exitCode = 0;
|
|
1338
1418
|
} catch (err) {
|
|
@@ -1349,7 +1429,7 @@ async function buildsCancel(id, opts, deps) {
|
|
|
1349
1429
|
if (opts.json) {
|
|
1350
1430
|
console.log(JSON.stringify(build));
|
|
1351
1431
|
} else {
|
|
1352
|
-
console.log(`${
|
|
1432
|
+
console.log(`${chalk12.cyan(build.id)} ${build.status}`);
|
|
1353
1433
|
}
|
|
1354
1434
|
process.exitCode = 0;
|
|
1355
1435
|
} catch (err) {
|
|
@@ -1366,7 +1446,7 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1366
1446
|
if (opts.json) {
|
|
1367
1447
|
console.log(JSON.stringify(result));
|
|
1368
1448
|
} else {
|
|
1369
|
-
console.log(
|
|
1449
|
+
console.log(chalk12.green(`\u2713 deleted artifact for ${id}`));
|
|
1370
1450
|
}
|
|
1371
1451
|
process.exitCode = 0;
|
|
1372
1452
|
} catch (err) {
|
|
@@ -1377,11 +1457,11 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1377
1457
|
function printError(opts, err) {
|
|
1378
1458
|
const message = err instanceof Error ? err.message : String(err);
|
|
1379
1459
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1380
|
-
console.error(
|
|
1460
|
+
console.error(chalk12.red(`error: ${message}`));
|
|
1381
1461
|
}
|
|
1382
1462
|
|
|
1383
1463
|
// src/commands/submit.ts
|
|
1384
|
-
import
|
|
1464
|
+
import chalk13 from "chalk";
|
|
1385
1465
|
function defaultDeps2(client) {
|
|
1386
1466
|
return {
|
|
1387
1467
|
createSubmission: client.createSubmission.bind(client),
|
|
@@ -1404,7 +1484,7 @@ function submitConfigFor(cwd, platform) {
|
|
|
1404
1484
|
cfg = loadDevConfig(cwd);
|
|
1405
1485
|
} catch (err) {
|
|
1406
1486
|
console.error(
|
|
1407
|
-
|
|
1487
|
+
chalk13.yellow(
|
|
1408
1488
|
`warning: vibeview.json could not be read \u2014 ignoring submit defaults (${err instanceof Error ? err.message : String(err)})`
|
|
1409
1489
|
)
|
|
1410
1490
|
);
|
|
@@ -1552,12 +1632,12 @@ async function submitCommand(opts, deps) {
|
|
|
1552
1632
|
return;
|
|
1553
1633
|
}
|
|
1554
1634
|
if (!opts.json) {
|
|
1555
|
-
console.error(` ${
|
|
1635
|
+
console.error(` ${chalk13.cyan(sub.id)} ${chalk13.dim(`[${sub.platform}]`)}`);
|
|
1556
1636
|
}
|
|
1557
1637
|
const final = await followSubmission(sub, opts, d);
|
|
1558
1638
|
if (!opts.json && final.status === "succeeded" && (final.release_status ?? releaseStatus) === "draft") {
|
|
1559
1639
|
console.error(
|
|
1560
|
-
|
|
1640
|
+
chalk13.dim("release status: draft \u2014 activate it from the Play Console when ready")
|
|
1561
1641
|
);
|
|
1562
1642
|
}
|
|
1563
1643
|
process.exitCode = final.status === "succeeded" ? 0 : 1;
|
|
@@ -1581,11 +1661,11 @@ async function checkStore(platform, androidFamily, ascKey2, opts, deps) {
|
|
|
1581
1661
|
});
|
|
1582
1662
|
emit(opts.json, { event: "preflight", ...result });
|
|
1583
1663
|
if (!opts.json) {
|
|
1584
|
-
const mark = result.ready ?
|
|
1664
|
+
const mark = result.ready ? chalk13.green("\u2713") : chalk13.red("\u2717");
|
|
1585
1665
|
console.error(`${mark} ${result.message}`);
|
|
1586
1666
|
if (result.ready) {
|
|
1587
1667
|
console.error(
|
|
1588
|
-
|
|
1668
|
+
chalk13.dim(
|
|
1589
1669
|
` next: vibeview build --cloud --production --platform ${platform}, then vibeview submit --platform ${platform} --latest`
|
|
1590
1670
|
)
|
|
1591
1671
|
);
|
|
@@ -1634,14 +1714,14 @@ async function followSubmission(created, opts, deps) {
|
|
|
1634
1714
|
if (opts.json) {
|
|
1635
1715
|
emit(opts.json, { event: "status", id: created.id, status: "queued" });
|
|
1636
1716
|
} else {
|
|
1637
|
-
console.error(
|
|
1717
|
+
console.error(chalk13.dim("\u23F3 queued \u2014 waiting for a submission slot"));
|
|
1638
1718
|
}
|
|
1639
1719
|
} else if (log.status === "running" && !printedRunning) {
|
|
1640
1720
|
printedRunning = true;
|
|
1641
1721
|
if (opts.json) {
|
|
1642
1722
|
emit(opts.json, { event: "status", id: created.id, status: "running" });
|
|
1643
1723
|
} else {
|
|
1644
|
-
console.error(`${
|
|
1724
|
+
console.error(`${chalk13.cyan("\u25B6")} submitting`);
|
|
1645
1725
|
}
|
|
1646
1726
|
}
|
|
1647
1727
|
if (log.content) {
|
|
@@ -1683,7 +1763,7 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1683
1763
|
});
|
|
1684
1764
|
if (!opts.json) {
|
|
1685
1765
|
const ok = final.status === "succeeded";
|
|
1686
|
-
const mark = ok ?
|
|
1766
|
+
const mark = ok ? chalk13.green("\u2713") : chalk13.red("\u2717");
|
|
1687
1767
|
const duration = formatDuration(final.started_at, final.finished_at);
|
|
1688
1768
|
let line = `${mark} ${final.status}`;
|
|
1689
1769
|
if (duration) line += ` (${duration})`;
|
|
@@ -1695,11 +1775,11 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1695
1775
|
function printError2(opts, err) {
|
|
1696
1776
|
const message = err instanceof Error ? err.message : String(err);
|
|
1697
1777
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1698
|
-
console.error(
|
|
1778
|
+
console.error(chalk13.red(`error: ${message}`));
|
|
1699
1779
|
}
|
|
1700
1780
|
|
|
1701
1781
|
// src/commands/versions.ts
|
|
1702
|
-
import
|
|
1782
|
+
import chalk14 from "chalk";
|
|
1703
1783
|
function defaultDeps3(client) {
|
|
1704
1784
|
return {
|
|
1705
1785
|
listAppVersions: client.listAppVersions.bind(client),
|
|
@@ -1749,7 +1829,7 @@ async function versionsSet(buildNumber, opts, deps) {
|
|
|
1749
1829
|
console.log(JSON.stringify(version));
|
|
1750
1830
|
} else {
|
|
1751
1831
|
console.log(
|
|
1752
|
-
|
|
1832
|
+
chalk14.green(`\u2713 ${version.platform} build number set to ${version.build_number}`) + chalk14.dim(
|
|
1753
1833
|
" \u2014 the next autoIncrement production build gets " + (version.build_number + 1)
|
|
1754
1834
|
)
|
|
1755
1835
|
);
|
|
@@ -1769,18 +1849,18 @@ function formatVersionsHuman(versions2) {
|
|
|
1769
1849
|
const widths = HEADERS2.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1770
1850
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1771
1851
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1772
|
-
const lines = [
|
|
1852
|
+
const lines = [chalk14.bold(join3(padCells(HEADERS2)))];
|
|
1773
1853
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
1774
1854
|
return lines.join("\n") + "\n";
|
|
1775
1855
|
}
|
|
1776
1856
|
function printError3(opts, err) {
|
|
1777
1857
|
const message = err instanceof Error ? err.message : String(err);
|
|
1778
1858
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1779
|
-
console.error(
|
|
1859
|
+
console.error(chalk14.red(`error: ${message}`));
|
|
1780
1860
|
}
|
|
1781
1861
|
|
|
1782
1862
|
// src/commands/whoami.ts
|
|
1783
|
-
import
|
|
1863
|
+
import chalk15 from "chalk";
|
|
1784
1864
|
function defaultDeps4(opts) {
|
|
1785
1865
|
const { token, baseUrl } = resolveAuth(opts);
|
|
1786
1866
|
const client = new ApiClient(baseUrl, token);
|
|
@@ -1802,27 +1882,27 @@ async function whoAmI(opts, deps) {
|
|
|
1802
1882
|
process.exitCode = 0;
|
|
1803
1883
|
return;
|
|
1804
1884
|
}
|
|
1805
|
-
console.log(`${
|
|
1885
|
+
console.log(`${chalk15.bold("Logged in as")} ${me.email}`);
|
|
1806
1886
|
if (me.memberships.length === 1) {
|
|
1807
|
-
console.log(`${
|
|
1887
|
+
console.log(`${chalk15.bold("Organization")} ${me.memberships[0].organization_name}`);
|
|
1808
1888
|
} else if (me.memberships.length > 1) {
|
|
1809
|
-
console.log(
|
|
1889
|
+
console.log(chalk15.bold("Organizations"));
|
|
1810
1890
|
for (const m of me.memberships) {
|
|
1811
1891
|
console.log(` ${m.organization_name} (${m.role})`);
|
|
1812
1892
|
}
|
|
1813
1893
|
}
|
|
1814
|
-
console.log(`${
|
|
1815
|
-
console.log(`${
|
|
1816
|
-
console.log(`${
|
|
1894
|
+
console.log(`${chalk15.bold("Member role")} ${me.role ?? "\u2014"}`);
|
|
1895
|
+
console.log(`${chalk15.bold("Token role")} ${me.token_role ?? "\u2014 (session auth)"}`);
|
|
1896
|
+
console.log(`${chalk15.bold("Effective role")} ${effective ?? "\u2014"}`);
|
|
1817
1897
|
if (me.is_superadmin) {
|
|
1818
|
-
console.log(
|
|
1898
|
+
console.log(chalk15.dim("Superadmin (platform-wide; does not raise the org role above)"));
|
|
1819
1899
|
}
|
|
1820
1900
|
if (me.role === "admin" && me.token_role && me.token_role !== "admin") {
|
|
1821
1901
|
console.log(
|
|
1822
|
-
|
|
1902
|
+
chalk15.yellow(
|
|
1823
1903
|
`
|
|
1824
|
-
Your account is admin, but this CLI token is ${me.token_role}. The effective role is the lower of the two, so admin-only commands (such as ${
|
|
1825
|
-
Create an admin API token in the dashboard and use ${
|
|
1904
|
+
Your account is admin, but this CLI token is ${me.token_role}. The effective role is the lower of the two, so admin-only commands (such as ${chalk15.bold("vibeview env set")}) will fail with a permissions error.
|
|
1905
|
+
Create an admin API token in the dashboard and use ${chalk15.bold("--token")} or ${chalk15.bold("VIBEVIEW_API_TOKEN")}.`
|
|
1826
1906
|
)
|
|
1827
1907
|
);
|
|
1828
1908
|
}
|
|
@@ -1832,7 +1912,7 @@ Create an admin API token in the dashboard and use ${chalk14.bold("--token")} or
|
|
|
1832
1912
|
if (opts.json) {
|
|
1833
1913
|
console.log(JSON.stringify({ event: "error", message }));
|
|
1834
1914
|
}
|
|
1835
|
-
console.error(
|
|
1915
|
+
console.error(chalk15.red(`error: ${message}`));
|
|
1836
1916
|
process.exitCode = 1;
|
|
1837
1917
|
}
|
|
1838
1918
|
}
|
|
@@ -1840,7 +1920,7 @@ Create an admin API token in the dashboard and use ${chalk14.bold("--token")} or
|
|
|
1840
1920
|
// src/commands/env.ts
|
|
1841
1921
|
import { chmod, open as open2, readFile as readFileAsync } from "fs/promises";
|
|
1842
1922
|
import { basename } from "path";
|
|
1843
|
-
import
|
|
1923
|
+
import chalk16 from "chalk";
|
|
1844
1924
|
import { password } from "@inquirer/prompts";
|
|
1845
1925
|
|
|
1846
1926
|
// src/lib/gitignore.ts
|
|
@@ -1896,7 +1976,7 @@ function defaultDeps5(client) {
|
|
|
1896
1976
|
isIgnored: (path) => isGitIgnored(path),
|
|
1897
1977
|
writeFile: writeSecureFile,
|
|
1898
1978
|
readFile: (path) => readFileAsync(path),
|
|
1899
|
-
warn: (message) => console.error(
|
|
1979
|
+
warn: (message) => console.error(chalk16.yellow(`warning: ${message}`))
|
|
1900
1980
|
};
|
|
1901
1981
|
}
|
|
1902
1982
|
async function envList(opts, deps) {
|
|
@@ -1928,7 +2008,7 @@ function formatEnvVarsHuman(variables) {
|
|
|
1928
2008
|
const widths = HEADERS4.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1929
2009
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1930
2010
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1931
|
-
const lines = [
|
|
2011
|
+
const lines = [chalk16.bold(join3(padCells(HEADERS4)))];
|
|
1932
2012
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
1933
2013
|
return lines.join("\n") + "\n";
|
|
1934
2014
|
}
|
|
@@ -1978,7 +2058,7 @@ function printSetResult(opts, result) {
|
|
|
1978
2058
|
if (opts.json) {
|
|
1979
2059
|
console.log(JSON.stringify(result));
|
|
1980
2060
|
} else {
|
|
1981
|
-
console.log(
|
|
2061
|
+
console.log(chalk16.green(`\u2713 set ${result.name} (${result.visibility})`));
|
|
1982
2062
|
}
|
|
1983
2063
|
}
|
|
1984
2064
|
async function envRm(name, opts, deps) {
|
|
@@ -1988,7 +2068,7 @@ async function envRm(name, opts, deps) {
|
|
|
1988
2068
|
if (opts.json) {
|
|
1989
2069
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
1990
2070
|
} else {
|
|
1991
|
-
console.log(
|
|
2071
|
+
console.log(chalk16.green(`\u2713 removed ${name}`));
|
|
1992
2072
|
}
|
|
1993
2073
|
process.exitCode = 0;
|
|
1994
2074
|
} catch (err) {
|
|
@@ -2020,7 +2100,7 @@ async function envPull(opts, deps) {
|
|
|
2020
2100
|
if (opts.json) {
|
|
2021
2101
|
console.log(JSON.stringify({ event: "pulled", path: outPath, count: variables.length }));
|
|
2022
2102
|
} else {
|
|
2023
|
-
console.log(
|
|
2103
|
+
console.log(chalk16.green(`\u2713 wrote ${variables.length} variable(s) to ${outPath}`));
|
|
2024
2104
|
}
|
|
2025
2105
|
process.exitCode = 0;
|
|
2026
2106
|
} catch (err) {
|
|
@@ -2059,7 +2139,7 @@ function escapeEnvValue(value) {
|
|
|
2059
2139
|
function printError4(opts, err) {
|
|
2060
2140
|
const message = err instanceof Error ? err.message : String(err);
|
|
2061
2141
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2062
|
-
console.error(
|
|
2142
|
+
console.error(chalk16.red(`error: ${message}`));
|
|
2063
2143
|
}
|
|
2064
2144
|
|
|
2065
2145
|
// src/commands/credentials.ts
|
|
@@ -2071,7 +2151,7 @@ import {
|
|
|
2071
2151
|
} from "fs/promises";
|
|
2072
2152
|
import { mkdirSync } from "fs";
|
|
2073
2153
|
import { basename as basename2, extname, join } from "path";
|
|
2074
|
-
import
|
|
2154
|
+
import chalk17 from "chalk";
|
|
2075
2155
|
import { input, password as password2 } from "@inquirer/prompts";
|
|
2076
2156
|
function clientFor2(opts) {
|
|
2077
2157
|
const { token, baseUrl } = resolveAuth(opts);
|
|
@@ -2144,7 +2224,7 @@ function defaultDeps6(client) {
|
|
|
2144
2224
|
mkdir: (dir) => mkdirSync(dir, { recursive: true }),
|
|
2145
2225
|
writeFile: (path, data, mode) => writeFileAsync(path, data, mode !== void 0 ? { mode } : void 0),
|
|
2146
2226
|
chmod: (path, mode) => chmodAsync(path, mode),
|
|
2147
|
-
warn: (message) => console.error(
|
|
2227
|
+
warn: (message) => console.error(chalk17.yellow(`warning: ${message}`))
|
|
2148
2228
|
};
|
|
2149
2229
|
}
|
|
2150
2230
|
var ANDROID_KIND = "android_keystore";
|
|
@@ -2213,7 +2293,7 @@ async function credentialsAdd(opts, deps) {
|
|
|
2213
2293
|
if (opts.json) {
|
|
2214
2294
|
console.log(JSON.stringify(result));
|
|
2215
2295
|
} else {
|
|
2216
|
-
console.log(
|
|
2296
|
+
console.log(chalk17.green(`\u2713 added ${result.name} (${result.platform})`));
|
|
2217
2297
|
}
|
|
2218
2298
|
process.exitCode = 0;
|
|
2219
2299
|
} catch (err) {
|
|
@@ -2271,20 +2351,20 @@ async function credentialsGenerate(opts, deps) {
|
|
|
2271
2351
|
}
|
|
2272
2352
|
if (opts.json) {
|
|
2273
2353
|
} else {
|
|
2274
|
-
console.log(
|
|
2354
|
+
console.log(chalk17.green(`\u2713 generated ${result.name} (android)`));
|
|
2275
2355
|
console.log("");
|
|
2276
|
-
console.log(` Keystore saved to: ${
|
|
2277
|
-
console.log(` Key alias: ${
|
|
2278
|
-
console.log(` Store password: ${
|
|
2279
|
-
console.log(` Key password: ${
|
|
2356
|
+
console.log(` Keystore saved to: ${chalk17.bold(savedTo)}`);
|
|
2357
|
+
console.log(` Key alias: ${chalk17.bold(result.key_alias)}`);
|
|
2358
|
+
console.log(` Store password: ${chalk17.bold(result.store_password)}`);
|
|
2359
|
+
console.log(` Key password: ${chalk17.bold(result.key_password)}`);
|
|
2280
2360
|
console.log("");
|
|
2281
2361
|
console.log(
|
|
2282
|
-
|
|
2362
|
+
chalk17.yellow(
|
|
2283
2363
|
" These are shown ONCE \u2014 VibeView cannot recover the keystore file or its passwords. Back them up somewhere safe."
|
|
2284
2364
|
)
|
|
2285
2365
|
);
|
|
2286
2366
|
console.log(
|
|
2287
|
-
|
|
2367
|
+
chalk17.yellow(
|
|
2288
2368
|
" The credential is already uploaded and active for android and androidtv production builds."
|
|
2289
2369
|
)
|
|
2290
2370
|
);
|
|
@@ -2310,19 +2390,19 @@ async function generateAppleCredential(platform, opts, d) {
|
|
|
2310
2390
|
if (opts.json) {
|
|
2311
2391
|
console.log(JSON.stringify(result));
|
|
2312
2392
|
} else {
|
|
2313
|
-
console.log(
|
|
2393
|
+
console.log(chalk17.green(`\u2713 generated ${result.name} (${result.platform})`));
|
|
2314
2394
|
console.log("");
|
|
2315
|
-
console.log(` Scope: ${
|
|
2395
|
+
console.log(` Scope: ${chalk17.bold(result.app_public_id ?? "org-wide")}`);
|
|
2316
2396
|
const expires = formatExpires(result);
|
|
2317
2397
|
if (expires) {
|
|
2318
|
-
console.log(` Expires: ${
|
|
2398
|
+
console.log(` Expires: ${chalk17.bold(expires)}`);
|
|
2319
2399
|
}
|
|
2320
2400
|
console.log("");
|
|
2321
2401
|
console.log(
|
|
2322
2402
|
` The certificate and provisioning profile are stored with VibeView and already active for ${result.platform} production builds.`
|
|
2323
2403
|
);
|
|
2324
2404
|
console.log(
|
|
2325
|
-
` Run ${
|
|
2405
|
+
` Run ${chalk17.bold(`vibeview credentials download ${result.name}`)} if you need the files locally.`
|
|
2326
2406
|
);
|
|
2327
2407
|
}
|
|
2328
2408
|
process.exitCode = 0;
|
|
@@ -2388,17 +2468,17 @@ async function credentialsDownload(name, opts, deps) {
|
|
|
2388
2468
|
await d.chmod(path, 384);
|
|
2389
2469
|
}
|
|
2390
2470
|
if (!opts.json) {
|
|
2391
|
-
console.log(
|
|
2471
|
+
console.log(chalk17.green(`\u2713 downloaded ${material.name} (${material.platform})`));
|
|
2392
2472
|
console.log("");
|
|
2393
|
-
console.log(` Saved to: ${
|
|
2473
|
+
console.log(` Saved to: ${chalk17.bold(savedTo)}`);
|
|
2394
2474
|
if (profileSavedTo !== null) {
|
|
2395
|
-
console.log(` Profile: ${
|
|
2475
|
+
console.log(` Profile: ${chalk17.bold(profileSavedTo)}`);
|
|
2396
2476
|
}
|
|
2397
2477
|
for (const [key, value] of Object.entries(material.passwords)) {
|
|
2398
|
-
console.log(` ${key}: ${
|
|
2478
|
+
console.log(` ${key}: ${chalk17.bold(value)}`);
|
|
2399
2479
|
}
|
|
2400
2480
|
console.log("");
|
|
2401
|
-
console.log(
|
|
2481
|
+
console.log(chalk17.yellow(" This download is recorded in your organization's audit log."));
|
|
2402
2482
|
}
|
|
2403
2483
|
process.exitCode = 0;
|
|
2404
2484
|
} catch (err) {
|
|
@@ -2429,13 +2509,13 @@ async function ascKeyAdd(opts, deps) {
|
|
|
2429
2509
|
if (opts.json) {
|
|
2430
2510
|
console.log(JSON.stringify(result));
|
|
2431
2511
|
} else {
|
|
2432
|
-
console.log(
|
|
2512
|
+
console.log(chalk17.green(`\u2713 added App Store Connect key ${result.name}`));
|
|
2433
2513
|
console.log("");
|
|
2434
|
-
console.log(` Key ID: ${
|
|
2435
|
-
console.log(` Issuer ID: ${
|
|
2514
|
+
console.log(` Key ID: ${chalk17.bold(result.key_id)}`);
|
|
2515
|
+
console.log(` Issuer ID: ${chalk17.bold(result.issuer_id)}`);
|
|
2436
2516
|
console.log("");
|
|
2437
2517
|
console.log(
|
|
2438
|
-
|
|
2518
|
+
chalk17.yellow(
|
|
2439
2519
|
" The .p8 is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2440
2520
|
)
|
|
2441
2521
|
);
|
|
@@ -2470,7 +2550,7 @@ function formatAscKeysHuman(keys) {
|
|
|
2470
2550
|
const widths = HEADERS4.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2471
2551
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2472
2552
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2473
|
-
const lines = [
|
|
2553
|
+
const lines = [chalk17.bold(join3(padCells(HEADERS4)))];
|
|
2474
2554
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2475
2555
|
return lines.join("\n") + "\n";
|
|
2476
2556
|
}
|
|
@@ -2481,7 +2561,7 @@ async function ascKeyRm(name, opts, deps) {
|
|
|
2481
2561
|
if (opts.json) {
|
|
2482
2562
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2483
2563
|
} else {
|
|
2484
|
-
console.log(
|
|
2564
|
+
console.log(chalk17.green(`\u2713 removed App Store Connect key ${name}`));
|
|
2485
2565
|
}
|
|
2486
2566
|
process.exitCode = 0;
|
|
2487
2567
|
} catch (err) {
|
|
@@ -2506,12 +2586,12 @@ async function playKeyAdd(opts, deps) {
|
|
|
2506
2586
|
if (opts.json) {
|
|
2507
2587
|
console.log(JSON.stringify(result));
|
|
2508
2588
|
} else {
|
|
2509
|
-
console.log(
|
|
2589
|
+
console.log(chalk17.green(`\u2713 added Google Play key ${result.name}`));
|
|
2510
2590
|
console.log("");
|
|
2511
|
-
console.log(` Service account: ${
|
|
2591
|
+
console.log(` Service account: ${chalk17.bold(result.client_email)}`);
|
|
2512
2592
|
console.log("");
|
|
2513
2593
|
console.log(
|
|
2514
|
-
|
|
2594
|
+
chalk17.yellow(
|
|
2515
2595
|
" The JSON key is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2516
2596
|
)
|
|
2517
2597
|
);
|
|
@@ -2546,7 +2626,7 @@ function formatPlayKeysHuman(keys) {
|
|
|
2546
2626
|
const widths = HEADERS4.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2547
2627
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2548
2628
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2549
|
-
const lines = [
|
|
2629
|
+
const lines = [chalk17.bold(join3(padCells(HEADERS4)))];
|
|
2550
2630
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2551
2631
|
return lines.join("\n") + "\n";
|
|
2552
2632
|
}
|
|
@@ -2557,7 +2637,7 @@ async function playKeyRm(name, opts, deps) {
|
|
|
2557
2637
|
if (opts.json) {
|
|
2558
2638
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2559
2639
|
} else {
|
|
2560
|
-
console.log(
|
|
2640
|
+
console.log(chalk17.green(`\u2713 removed Google Play key ${name}`));
|
|
2561
2641
|
}
|
|
2562
2642
|
process.exitCode = 0;
|
|
2563
2643
|
} catch (err) {
|
|
@@ -2626,7 +2706,7 @@ function formatCredentialsHuman(credentials2) {
|
|
|
2626
2706
|
const widths = HEADERS4.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2627
2707
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2628
2708
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2629
|
-
const lines = [
|
|
2709
|
+
const lines = [chalk17.bold(join3(padCells(HEADERS4)))];
|
|
2630
2710
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2631
2711
|
return lines.join("\n") + "\n";
|
|
2632
2712
|
}
|
|
@@ -2637,7 +2717,7 @@ async function credentialsRm(name, opts, deps) {
|
|
|
2637
2717
|
if (opts.json) {
|
|
2638
2718
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2639
2719
|
} else {
|
|
2640
|
-
console.log(
|
|
2720
|
+
console.log(chalk17.green(`\u2713 removed ${name}`));
|
|
2641
2721
|
}
|
|
2642
2722
|
process.exitCode = 0;
|
|
2643
2723
|
} catch (err) {
|
|
@@ -2649,16 +2729,16 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2649
2729
|
const message = err instanceof Error ? err.message : String(err);
|
|
2650
2730
|
if (opts.json) {
|
|
2651
2731
|
console.log(JSON.stringify({ event: "error", message }));
|
|
2652
|
-
console.error(
|
|
2732
|
+
console.error(chalk17.red(`error: ${message}`));
|
|
2653
2733
|
return;
|
|
2654
2734
|
}
|
|
2655
|
-
console.error(
|
|
2735
|
+
console.error(chalk17.red(`error: ${message}`));
|
|
2656
2736
|
console.error(
|
|
2657
|
-
|
|
2737
|
+
chalk17.red(
|
|
2658
2738
|
`The keystore could NOT be saved locally, but the credential "${result.name}" WAS created server-side and its key material can never be re-fetched.`
|
|
2659
2739
|
)
|
|
2660
2740
|
);
|
|
2661
|
-
console.error(
|
|
2741
|
+
console.error(chalk17.red("Recover it NOW from the values below \u2014 they will not be shown again:"));
|
|
2662
2742
|
console.error("");
|
|
2663
2743
|
console.error(` Key alias: ${result.key_alias}`);
|
|
2664
2744
|
console.error(` Store password: ${result.store_password}`);
|
|
@@ -2672,11 +2752,11 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2672
2752
|
function printError5(opts, err) {
|
|
2673
2753
|
const message = err instanceof Error ? err.message : String(err);
|
|
2674
2754
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2675
|
-
console.error(
|
|
2755
|
+
console.error(chalk17.red(`error: ${message}`));
|
|
2676
2756
|
}
|
|
2677
2757
|
|
|
2678
2758
|
// src/commands/webhooks.ts
|
|
2679
|
-
import
|
|
2759
|
+
import chalk18 from "chalk";
|
|
2680
2760
|
function clientFor3(opts) {
|
|
2681
2761
|
const { token, baseUrl } = resolveAuth(opts);
|
|
2682
2762
|
return new ApiClient(baseUrl, token);
|
|
@@ -2707,14 +2787,14 @@ async function webhooksAdd(opts, deps) {
|
|
|
2707
2787
|
if (opts.json) {
|
|
2708
2788
|
console.log(JSON.stringify(result));
|
|
2709
2789
|
} else {
|
|
2710
|
-
console.log(
|
|
2790
|
+
console.log(chalk18.green(`\u2713 added ${result.id} ${result.url}`));
|
|
2711
2791
|
console.log("");
|
|
2712
|
-
console.log(` Signing secret: ${
|
|
2792
|
+
console.log(` Signing secret: ${chalk18.bold(result.secret)}`);
|
|
2713
2793
|
if (opts.secret !== void 0) {
|
|
2714
|
-
console.log(
|
|
2794
|
+
console.log(chalk18.yellow(" (This is the secret you provided.)"));
|
|
2715
2795
|
}
|
|
2716
2796
|
console.log(
|
|
2717
|
-
|
|
2797
|
+
chalk18.yellow(" This secret is shown ONCE and cannot be retrieved again \u2014 store it now.")
|
|
2718
2798
|
);
|
|
2719
2799
|
}
|
|
2720
2800
|
process.exitCode = 0;
|
|
@@ -2745,7 +2825,7 @@ function formatWebhooksHuman(webhooks2) {
|
|
|
2745
2825
|
const widths = HEADERS4.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2746
2826
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2747
2827
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2748
|
-
const lines = [
|
|
2828
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS4)))];
|
|
2749
2829
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2750
2830
|
return lines.join("\n") + "\n";
|
|
2751
2831
|
}
|
|
@@ -2771,7 +2851,7 @@ async function webhooksRm(id, opts, deps) {
|
|
|
2771
2851
|
if (opts.json) {
|
|
2772
2852
|
console.log(JSON.stringify({ event: "deleted", id }));
|
|
2773
2853
|
} else {
|
|
2774
|
-
console.log(
|
|
2854
|
+
console.log(chalk18.green(`\u2713 removed ${id}`));
|
|
2775
2855
|
}
|
|
2776
2856
|
process.exitCode = 0;
|
|
2777
2857
|
} catch (err) {
|
|
@@ -2804,13 +2884,13 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2804
2884
|
if (opts.json) console.log(JSON.stringify(ld));
|
|
2805
2885
|
if (ld.status === "succeeded") {
|
|
2806
2886
|
if (!opts.json) {
|
|
2807
|
-
console.log(
|
|
2887
|
+
console.log(chalk18.green(`\u2713 Delivered (HTTP ${ld.response_code})`));
|
|
2808
2888
|
}
|
|
2809
2889
|
process.exitCode = 0;
|
|
2810
2890
|
} else {
|
|
2811
2891
|
if (!opts.json) {
|
|
2812
2892
|
const code = ld.response_code != null ? `HTTP ${ld.response_code}` : "no response";
|
|
2813
|
-
console.error(
|
|
2893
|
+
console.error(chalk18.red(`\u2717 Failed (${code}) at ${ld.at}`));
|
|
2814
2894
|
}
|
|
2815
2895
|
process.exitCode = 1;
|
|
2816
2896
|
}
|
|
@@ -2819,7 +2899,7 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2819
2899
|
}
|
|
2820
2900
|
if (opts.json) console.log(JSON.stringify({ status: "pending" }));
|
|
2821
2901
|
console.error(
|
|
2822
|
-
|
|
2902
|
+
chalk18.yellow(
|
|
2823
2903
|
`Delivery still pending after ${TEST_POLL_BUDGET_MS / 1e3}s \u2014 check \`vibeview webhooks list\` later for the result.`
|
|
2824
2904
|
)
|
|
2825
2905
|
);
|
|
@@ -2832,11 +2912,11 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2832
2912
|
function printError6(opts, err) {
|
|
2833
2913
|
const message = err instanceof Error ? err.message : String(err);
|
|
2834
2914
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2835
|
-
console.error(
|
|
2915
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2836
2916
|
}
|
|
2837
2917
|
|
|
2838
2918
|
// src/lib/formatters/devices.ts
|
|
2839
|
-
import
|
|
2919
|
+
import chalk19 from "chalk";
|
|
2840
2920
|
var HEADERS3 = ["DEVICE_ID", "NAME", "TYPE", "CATEGORY", "OS", "STATUS"];
|
|
2841
2921
|
function formatDevicesHuman(devices) {
|
|
2842
2922
|
if (devices.length === 0) {
|
|
@@ -2852,9 +2932,9 @@ function formatDevicesHuman(devices) {
|
|
|
2852
2932
|
]);
|
|
2853
2933
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2854
2934
|
const fmt = (cells) => cells.map((c, i) => c.padEnd(widths[i])).join(" ").trimEnd();
|
|
2855
|
-
const lines = [
|
|
2935
|
+
const lines = [chalk19.bold(fmt(HEADERS3))];
|
|
2856
2936
|
for (const row of rows.sort(rowSort)) {
|
|
2857
|
-
const statusColored = row[5] === "available" ?
|
|
2937
|
+
const statusColored = row[5] === "available" ? chalk19.green(row[5]) : row[5] === "busy" ? chalk19.yellow(row[5]) : chalk19.dim(row[5]);
|
|
2858
2938
|
lines.push(fmt([row[0], row[1], row[2], row[3], row[4], statusColored]));
|
|
2859
2939
|
}
|
|
2860
2940
|
return lines.join("\n") + "\n";
|
|
@@ -2944,7 +3024,7 @@ import { dirname, join as join2 } from "path";
|
|
|
2944
3024
|
import { fileURLToPath } from "url";
|
|
2945
3025
|
import { spawnSync } from "child_process";
|
|
2946
3026
|
import { confirm } from "@inquirer/prompts";
|
|
2947
|
-
import
|
|
3027
|
+
import chalk20 from "chalk";
|
|
2948
3028
|
function resolveShippedSkillPath(fromDir) {
|
|
2949
3029
|
for (const rel of ["..", join2("..", "..")]) {
|
|
2950
3030
|
const candidate = join2(fromDir, rel, "skills", "vibeview-agent", "SKILL.md");
|
|
@@ -2972,23 +3052,23 @@ function registerMcp() {
|
|
|
2972
3052
|
encoding: "utf8"
|
|
2973
3053
|
});
|
|
2974
3054
|
if (res.status === 0) {
|
|
2975
|
-
console.log(
|
|
3055
|
+
console.log(chalk20.green("\u2713 MCP server registered with Claude Code (claude mcp add vibeview)"));
|
|
2976
3056
|
return;
|
|
2977
3057
|
}
|
|
2978
3058
|
const out = `${res.stderr ?? ""}${res.stdout ?? ""}`;
|
|
2979
3059
|
if (out.includes("already exists")) {
|
|
2980
|
-
console.log(
|
|
3060
|
+
console.log(chalk20.dim("MCP server already registered with Claude Code \u2014 nothing to do"));
|
|
2981
3061
|
return;
|
|
2982
3062
|
}
|
|
2983
|
-
console.error(
|
|
2984
|
-
console.error(
|
|
3063
|
+
console.error(chalk20.yellow(`\u26A0 could not register the MCP server: ${out.trim() || res.error}`));
|
|
3064
|
+
console.error(chalk20.yellow(" register it manually: claude mcp add vibeview -- vibeview mcp"));
|
|
2985
3065
|
}
|
|
2986
3066
|
async function agentSetup(opts) {
|
|
2987
3067
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
2988
3068
|
const shipped = resolveShippedSkillPath(moduleDir);
|
|
2989
3069
|
if (!shipped) {
|
|
2990
3070
|
console.error(
|
|
2991
|
-
|
|
3071
|
+
chalk20.red(
|
|
2992
3072
|
"error: could not find the packaged skill (skills/vibeview-agent/SKILL.md) \u2014 is this a complete install of the vibeview package?"
|
|
2993
3073
|
)
|
|
2994
3074
|
);
|
|
@@ -2997,9 +3077,9 @@ async function agentSetup(opts) {
|
|
|
2997
3077
|
}
|
|
2998
3078
|
const targetDir = skillInstallDir(opts.project ?? false, process.cwd(), homedir());
|
|
2999
3079
|
const result = installSkill(shipped, targetDir);
|
|
3000
|
-
console.log(
|
|
3080
|
+
console.log(chalk20.green(`\u2713 vibeview-agent skill ${result}: ${join2(targetDir, "SKILL.md")}`));
|
|
3001
3081
|
console.log(
|
|
3002
|
-
|
|
3082
|
+
chalk20.dim(
|
|
3003
3083
|
opts.project ? " Claude Code discovers it automatically for anyone working in this project." : " Claude Code discovers it automatically in every project on this machine."
|
|
3004
3084
|
)
|
|
3005
3085
|
);
|
|
@@ -3007,7 +3087,7 @@ async function agentSetup(opts) {
|
|
|
3007
3087
|
if (!claudeCliAvailable()) {
|
|
3008
3088
|
if (opts.mcp === true) {
|
|
3009
3089
|
console.error(
|
|
3010
|
-
|
|
3090
|
+
chalk20.yellow(
|
|
3011
3091
|
"\u26A0 claude CLI not found \u2014 install Claude Code, then run: claude mcp add vibeview -- vibeview mcp"
|
|
3012
3092
|
)
|
|
3013
3093
|
);
|
|
@@ -3021,7 +3101,7 @@ async function agentSetup(opts) {
|
|
|
3021
3101
|
}
|
|
3022
3102
|
console.log(
|
|
3023
3103
|
`
|
|
3024
|
-
Suggested line for your project's ${
|
|
3104
|
+
Suggested line for your project's ${chalk20.bold("CLAUDE.md")} (or ${chalk20.bold(
|
|
3025
3105
|
"AGENTS.md"
|
|
3026
3106
|
)} for other agents):
|
|
3027
3107
|
`
|
|
@@ -3029,7 +3109,7 @@ Suggested line for your project's ${chalk19.bold("CLAUDE.md")} (or ${chalk19.bol
|
|
|
3029
3109
|
console.log(` ${CLAUDE_MD_SUGGESTION}
|
|
3030
3110
|
`);
|
|
3031
3111
|
console.log(
|
|
3032
|
-
|
|
3112
|
+
chalk20.dim(
|
|
3033
3113
|
"Other agents (Cursor, Copilot, Codex, ...): install the same skill from GitHub with\n npx skills add vibeview/skills\nor point them at the skill file above, or add the MCP server per client \u2014\nsee https://vibeview.io/docs/agent-control"
|
|
3034
3114
|
)
|
|
3035
3115
|
);
|
|
@@ -3076,7 +3156,7 @@ function resolveMetadata(opts) {
|
|
|
3076
3156
|
}
|
|
3077
3157
|
var program = new Command();
|
|
3078
3158
|
program.name("vibeview").description("VibeView CLI -- run mobile tests from CI/CD pipelines").version(pkg.version);
|
|
3079
|
-
program.command("run-suite <suite-id>").description("Run all test cases in a suite").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show per-case breakdown", false).option("--timeout <seconds>", "Max wait time in seconds", "
|
|
3159
|
+
program.command("run-suite <suite-id>").description("Run all test cases in a suite").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show per-case breakdown", false).option("--timeout <seconds>", "Max wait time in seconds (queue wait plus execution)", "1800").option("--commit-sha <sha>", "Git commit SHA for GitHub status checks").option("--model <model>", "AI model to use").option("--provider <provider>", "AI provider").option("--mode <mode>", "Execution mode: hybrid, ai, replay").option(
|
|
3080
3160
|
"--device-category <category>",
|
|
3081
3161
|
"Device category: phone, tablet, tv (default: phone when --device is not set)",
|
|
3082
3162
|
parseDeviceCategory
|
|
@@ -3104,7 +3184,7 @@ program.command("run-suites").description("Run all suites matching a tag filter"
|
|
|
3104
3184
|
).option("--match <mode>", "any (default) or all", "any").option(
|
|
3105
3185
|
"--platform <platform>",
|
|
3106
3186
|
"Filter matched suites to one platform: ios, android, tvos, androidtv (default: no filter)"
|
|
3107
|
-
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show per-suite progress", false).option("--timeout <seconds>", "Per-suite timeout, capped at 2 hours total", "
|
|
3187
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show per-suite progress", false).option("--timeout <seconds>", "Per-suite timeout, capped at 2 hours total", "1800").option("--commit-sha <sha>", "Git commit SHA propagated to every SuiteRun").option("--model <model>", "AI model").option("--provider <provider>", "AI provider").option("--mode <mode>", "Execution mode: hybrid, ai, replay").option(
|
|
3108
3188
|
"--device-category <category>",
|
|
3109
3189
|
"Device category: phone, tablet, tv (default: phone when --device is not set)",
|
|
3110
3190
|
parseDeviceCategory
|
|
@@ -3124,7 +3204,7 @@ program.command("run-suites").description("Run all suites matching a tag filter"
|
|
|
3124
3204
|
build: opts.build ? parseInt(opts.build, 10) : void 0
|
|
3125
3205
|
});
|
|
3126
3206
|
});
|
|
3127
|
-
program.command("run-test <test-id>").description("Run a single test case").option("--token <token>", "API token").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show step details", false).option("--timeout <seconds>", "Max wait time in seconds", "
|
|
3207
|
+
program.command("run-test <test-id>").description("Run a single test case").option("--token <token>", "API token").option("--output <format>", "Output format: human, json, junit", "human").option("--verbose", "Show step details", false).option("--timeout <seconds>", "Max wait time in seconds (queue wait plus execution)", "1800").option("--commit-sha <sha>", "Git commit SHA for GitHub status checks").option("--model <model>", "AI model to use").option("--provider <provider>", "AI provider").option("--mode <mode>", "Execution mode: hybrid, ai, replay").option(
|
|
3128
3208
|
"--device-category <category>",
|
|
3129
3209
|
"Device category: phone, tablet, tv (default: phone when --device is not set)",
|
|
3130
3210
|
parseDeviceCategory
|
|
@@ -3151,8 +3231,10 @@ program.command("list-suites").description("List available test suites").option(
|
|
|
3151
3231
|
[]
|
|
3152
3232
|
).option("--match <mode>", "When multiple --tag flags: any (default) or all", "any").action((opts) => listSuites(opts));
|
|
3153
3233
|
program.command("list-apps").description("List apps in your organization").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").action((opts) => listApps(opts));
|
|
3154
|
-
program.command("list-devices").description("List devices registered with the platform (filterable by type and category)").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").option("--type <type>", "Filter by device type: ios, android").option("--category <category>", "Filter by category: phone, tablet, tv").option("--status <status>", "Filter by status: available, busy, offline").action((opts) => listDevicesCommand(opts));
|
|
3155
|
-
program.command("upload-app <file>").description(
|
|
3234
|
+
program.command("list-devices").description("List devices registered with the platform (filterable by type and category)").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").option("--type <type>", "Filter by device type: ios, android, roku").option("--category <category>", "Filter by category: phone, tablet, tv").option("--status <status>", "Filter by status: available, busy, offline").action((opts) => listDevicesCommand(opts));
|
|
3235
|
+
program.command("upload-app <file>").description(
|
|
3236
|
+
"Upload an app build (zipped simulator .app for iOS/tvOS, .apk for Android/Android TV, or a Roku channel .zip)"
|
|
3237
|
+
).option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").option("--name <name>", "App name (auto-detected if not provided)").action((file, opts) => uploadApp(file, opts));
|
|
3156
3238
|
program.command("create-test [name]").description("Create a standalone AI test case").option("--token <token>", "API token").option("--output <format>", "Output format: human, json", "human").option("--app <app>", "App ID (public_id) or package name (requires --platform)").option("--platform <platform>", "Platform (ios, android) when using package name for --app").option("--steps <json>", "Test steps as inline JSON array").option("--steps-file <path>", "Path to JSON file containing test steps").option("--context <text>", "Additional context for AI test execution").option("--test-name <name>", "Test case name (alternative to positional arg)").action((name, opts) => createTest({ ...opts, testName: name || opts.testName || "CLI Test" }));
|
|
3157
3239
|
program.command("login").description("Log in to VibeView (interactive)").option("--base-url <url>", "VibeView server URL (defaults to https://vibeview.io)").action((opts) => login(opts));
|
|
3158
3240
|
program.command("logout").description("Revoke the saved login token and remove it from ~/.vibeview/config.json").action(() => logout());
|
|
@@ -3167,7 +3249,7 @@ program.command("dev").description(
|
|
|
3167
3249
|
parseDeviceCategory
|
|
3168
3250
|
).option("--no-open", "Do not open the browser automatically").option("--debug", "Log raw tunnel lifecycle events (close codes, reconnects) for diagnostics").option("--json", "Emit line-delimited JSON events on stdout instead of human output", false).option(
|
|
3169
3251
|
"--detach",
|
|
3170
|
-
"Run the dev session in the background; prints session info and exits (see `dev-status`, `dev-stop`)",
|
|
3252
|
+
"Run the dev session in the background; prints session info and exits (see `dev-status`, `dev-stop`, and `dev-reload` for Roku)",
|
|
3171
3253
|
false
|
|
3172
3254
|
).option(
|
|
3173
3255
|
"--build",
|
|
@@ -3307,10 +3389,13 @@ webhooks.command("rm <id>").description("Remove a webhook endpoint (rotate the s
|
|
|
3307
3389
|
webhooks.command("test <id>").description("Send a ping delivery and wait up to 60s for the result").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the final delivery result as one JSON line", false).action((id, opts) => webhooksTest(id, opts));
|
|
3308
3390
|
program.command("dev-status").description("Show the status of a `vibeview dev --detach` session in this project").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devStatus(opts));
|
|
3309
3391
|
program.command("dev-stop").description("Stop a `vibeview dev --detach` session in this project").option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devStop(opts));
|
|
3392
|
+
program.command("dev-reload").description(
|
|
3393
|
+
"Roku only: re-package, upload and reload the channel into this project's `vibeview dev --detach` session (the `r` key of the foreground loop)"
|
|
3394
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devReload(opts));
|
|
3310
3395
|
program.command("mcp").description(
|
|
3311
|
-
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop as tools"
|
|
3396
|
+
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop/dev_reload as tools"
|
|
3312
3397
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
|
|
3313
|
-
const { runMcpServer } = await import("./server-
|
|
3398
|
+
const { runMcpServer } = await import("./server-6IJ44HAX.js");
|
|
3314
3399
|
await runMcpServer(opts);
|
|
3315
3400
|
});
|
|
3316
3401
|
program.command("agent-setup").description(
|