vibeview 0.24.0 → 0.26.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 +2 -0
- package/dist/{chunk-MVNMGB6I.js → chunk-JK3T3AMW.js} +327 -184
- package/dist/{chunk-2WNJYNDW.js → chunk-RFFCCPGZ.js} +5 -0
- package/dist/cli.js +178 -126
- package/dist/{server-KIJCEN6T.js → server-KYDTXPRZ.js} +92 -8
- package/dist/{upload-app-BXXKH65S.js → upload-app-E32EZXYQ.js} +1 -1
- package/package.json +1 -1
- package/skills/vibeview-agent/SKILL.md +40 -14
package/dist/cli.js
CHANGED
|
@@ -12,14 +12,16 @@ import {
|
|
|
12
12
|
formatDevicesHuman,
|
|
13
13
|
formatDuration,
|
|
14
14
|
killOwnedMetro,
|
|
15
|
+
listBuilds,
|
|
15
16
|
loadDevConfig,
|
|
16
17
|
newTransitionState,
|
|
18
|
+
platformWithArticle,
|
|
17
19
|
printOutcomeLine,
|
|
18
20
|
printTransition,
|
|
19
21
|
readDevState,
|
|
20
22
|
readMetroState,
|
|
21
23
|
runAgentVerb
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-JK3T3AMW.js";
|
|
23
25
|
import {
|
|
24
26
|
ApiClient,
|
|
25
27
|
EXIT_INFRA_ERROR,
|
|
@@ -32,7 +34,7 @@ import {
|
|
|
32
34
|
resolveAuth,
|
|
33
35
|
saveConfig,
|
|
34
36
|
uploadApp
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-RFFCCPGZ.js";
|
|
36
38
|
|
|
37
39
|
// src/cli.ts
|
|
38
40
|
import { createRequire } from "module";
|
|
@@ -881,8 +883,52 @@ async function listApps(options) {
|
|
|
881
883
|
console.log();
|
|
882
884
|
}
|
|
883
885
|
|
|
884
|
-
// src/commands/
|
|
886
|
+
// src/commands/stop.ts
|
|
885
887
|
import chalk8 from "chalk";
|
|
888
|
+
async function stopCommand(sessionId, opts, deps) {
|
|
889
|
+
const id = sessionId?.trim();
|
|
890
|
+
if (!id) throw new UsageError("a session id is required: vibeview stop <session-id>");
|
|
891
|
+
const { token, baseUrl } = resolveAuth(opts);
|
|
892
|
+
const d = deps ?? { stopSession: (s) => new ApiClient(baseUrl, token).stopSession(s) };
|
|
893
|
+
try {
|
|
894
|
+
await d.stopSession(id);
|
|
895
|
+
} catch (err) {
|
|
896
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
897
|
+
if (opts.json) console.log(JSON.stringify({ stopped: false, session_id: id, message }));
|
|
898
|
+
console.error(chalk8.red(`error: ${message}`));
|
|
899
|
+
process.exitCode = 1;
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
const state = readDevState(process.cwd());
|
|
903
|
+
let devPid = null;
|
|
904
|
+
if (state && state.session_id === id) {
|
|
905
|
+
devPid = state.pid;
|
|
906
|
+
try {
|
|
907
|
+
process.kill(state.pid, "SIGTERM");
|
|
908
|
+
} catch (err) {
|
|
909
|
+
if (err.code !== "ESRCH") throw err;
|
|
910
|
+
}
|
|
911
|
+
clearDevState(process.cwd());
|
|
912
|
+
killOwnedMetro(process.cwd());
|
|
913
|
+
}
|
|
914
|
+
if (opts.json) {
|
|
915
|
+
console.log(
|
|
916
|
+
JSON.stringify({
|
|
917
|
+
stopped: true,
|
|
918
|
+
session_id: id,
|
|
919
|
+
...devPid !== null ? { pid: devPid } : {}
|
|
920
|
+
})
|
|
921
|
+
);
|
|
922
|
+
} else {
|
|
923
|
+
console.error(
|
|
924
|
+
`Stopped session ${id}${devPid !== null ? ` (and this project's dev process, pid ${devPid})` : ""}.`
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
process.exitCode = 0;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// src/commands/create-test.ts
|
|
931
|
+
import chalk9 from "chalk";
|
|
886
932
|
import { existsSync, readFileSync } from "fs";
|
|
887
933
|
async function readStdin() {
|
|
888
934
|
return new Promise((resolve, reject) => {
|
|
@@ -973,19 +1019,19 @@ async function createTest(options) {
|
|
|
973
1019
|
);
|
|
974
1020
|
} else {
|
|
975
1021
|
console.log(`
|
|
976
|
-
${
|
|
1022
|
+
${chalk9.cyan(result.public_id)} ${result.name}`);
|
|
977
1023
|
if (result.app_name) {
|
|
978
|
-
console.log(` ${
|
|
1024
|
+
console.log(` ${chalk9.dim(`App: ${result.app_name}`)}`);
|
|
979
1025
|
}
|
|
980
1026
|
if (result.platform) {
|
|
981
|
-
console.log(` ${
|
|
1027
|
+
console.log(` ${chalk9.dim(`Platform: ${result.platform}`)}`);
|
|
982
1028
|
}
|
|
983
|
-
console.log(` ${
|
|
984
|
-
console.log(
|
|
1029
|
+
console.log(` ${chalk9.dim(`Steps: ${steps.length}`)}`);
|
|
1030
|
+
console.log(chalk9.dim(` ${baseUrl}/tests?tab=standalone
|
|
985
1031
|
`));
|
|
986
1032
|
}
|
|
987
1033
|
} catch (err) {
|
|
988
|
-
console.error(
|
|
1034
|
+
console.error(chalk9.red(err instanceof Error ? err.message : "Failed to create test"));
|
|
989
1035
|
process.exit(EXIT_INFRA_ERROR);
|
|
990
1036
|
}
|
|
991
1037
|
}
|
|
@@ -1067,7 +1113,7 @@ async function logout() {
|
|
|
1067
1113
|
}
|
|
1068
1114
|
|
|
1069
1115
|
// src/commands/dev-status.ts
|
|
1070
|
-
import
|
|
1116
|
+
import chalk10 from "chalk";
|
|
1071
1117
|
async function devStatus(opts) {
|
|
1072
1118
|
const state = readDevState(process.cwd());
|
|
1073
1119
|
if (!state) {
|
|
@@ -1112,7 +1158,7 @@ async function devStatus(opts) {
|
|
|
1112
1158
|
console.error(` url: ${state.page_url}`);
|
|
1113
1159
|
console.error(` started: ${state.started_at}`);
|
|
1114
1160
|
}
|
|
1115
|
-
if (metro) console.error(
|
|
1161
|
+
if (metro) console.error(chalk10.dim(`Metro: pid ${metro.pid} on :${metro.port} (CLI-owned)`));
|
|
1116
1162
|
process.exit(0);
|
|
1117
1163
|
}
|
|
1118
1164
|
|
|
@@ -1148,12 +1194,12 @@ async function devStop(opts) {
|
|
|
1148
1194
|
}
|
|
1149
1195
|
|
|
1150
1196
|
// src/commands/dev-reload.ts
|
|
1151
|
-
import
|
|
1197
|
+
import chalk11 from "chalk";
|
|
1152
1198
|
function fail(opts, code, message, exit) {
|
|
1153
1199
|
if (opts.json) {
|
|
1154
1200
|
console.log(JSON.stringify({ reloaded: false, code, message }));
|
|
1155
1201
|
} else {
|
|
1156
|
-
console.error(
|
|
1202
|
+
console.error(chalk11.red(`error: ${message}`));
|
|
1157
1203
|
}
|
|
1158
1204
|
process.exit(exit);
|
|
1159
1205
|
}
|
|
@@ -1172,7 +1218,7 @@ async function devReload(opts) {
|
|
|
1172
1218
|
fail(
|
|
1173
1219
|
opts,
|
|
1174
1220
|
"not_roku",
|
|
1175
|
-
`dev-reload is for Roku channels;
|
|
1221
|
+
`dev-reload is for Roku channels; ${platformWithArticle(state.platform)} session hot-reloads through Metro on its own.`,
|
|
1176
1222
|
2
|
|
1177
1223
|
);
|
|
1178
1224
|
}
|
|
@@ -1206,7 +1252,7 @@ async function devReload(opts) {
|
|
|
1206
1252
|
api,
|
|
1207
1253
|
// Build output and the "reloaded in" line are human output: stderr, so
|
|
1208
1254
|
// stdout stays reserved for the --json result.
|
|
1209
|
-
log: (line) => console.error(
|
|
1255
|
+
log: (line) => console.error(chalk11.dim(line))
|
|
1210
1256
|
});
|
|
1211
1257
|
const started = Date.now();
|
|
1212
1258
|
try {
|
|
@@ -1227,22 +1273,22 @@ async function devReload(opts) {
|
|
|
1227
1273
|
}
|
|
1228
1274
|
|
|
1229
1275
|
// src/commands/builds.ts
|
|
1230
|
-
import
|
|
1276
|
+
import chalk13 from "chalk";
|
|
1231
1277
|
|
|
1232
1278
|
// src/lib/formatters/builds.ts
|
|
1233
|
-
import
|
|
1279
|
+
import chalk12 from "chalk";
|
|
1234
1280
|
var HEADERS = ["ID", "PLATFORM", "STATUS", "CREATED", "COST", "APP"];
|
|
1235
1281
|
function formatCostCell(costMicro) {
|
|
1236
1282
|
return costMicro > 0 ? `$${(costMicro / 1e6).toFixed(2)}` : "";
|
|
1237
1283
|
}
|
|
1238
1284
|
var STATUS_COLOR = {
|
|
1239
|
-
succeeded:
|
|
1240
|
-
failed:
|
|
1241
|
-
timed_out:
|
|
1242
|
-
infra_failed:
|
|
1243
|
-
canceled:
|
|
1244
|
-
running:
|
|
1245
|
-
queued:
|
|
1285
|
+
succeeded: chalk12.green,
|
|
1286
|
+
failed: chalk12.red,
|
|
1287
|
+
timed_out: chalk12.red,
|
|
1288
|
+
infra_failed: chalk12.red,
|
|
1289
|
+
canceled: chalk12.dim,
|
|
1290
|
+
running: chalk12.yellow,
|
|
1291
|
+
queued: chalk12.dim
|
|
1246
1292
|
};
|
|
1247
1293
|
function formatBuildsHuman(builds2) {
|
|
1248
1294
|
if (builds2.length === 0) {
|
|
@@ -1259,7 +1305,7 @@ function formatBuildsHuman(builds2) {
|
|
|
1259
1305
|
const widths = HEADERS.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1260
1306
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1261
1307
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1262
|
-
const lines = [
|
|
1308
|
+
const lines = [chalk12.bold(join3(padCells(HEADERS)))];
|
|
1263
1309
|
for (const row of rows) {
|
|
1264
1310
|
const padded = padCells(row);
|
|
1265
1311
|
const colorFn = STATUS_COLOR[row[2]] ?? ((s) => s);
|
|
@@ -1318,7 +1364,7 @@ async function buildsLogs(id, opts, deps) {
|
|
|
1318
1364
|
console.log(JSON.stringify(logs));
|
|
1319
1365
|
} else {
|
|
1320
1366
|
if (logs.content) process.stdout.write(logs.content);
|
|
1321
|
-
console.error(
|
|
1367
|
+
console.error(chalk13.dim(`status: ${logs.status}`));
|
|
1322
1368
|
}
|
|
1323
1369
|
process.exitCode = 0;
|
|
1324
1370
|
return;
|
|
@@ -1415,7 +1461,7 @@ async function buildsDownload(id, opts, deps) {
|
|
|
1415
1461
|
if (opts.json) {
|
|
1416
1462
|
console.log(JSON.stringify(result));
|
|
1417
1463
|
} else {
|
|
1418
|
-
console.log(
|
|
1464
|
+
console.log(chalk13.green(`\u2713 saved ${result.path}`));
|
|
1419
1465
|
}
|
|
1420
1466
|
process.exitCode = 0;
|
|
1421
1467
|
} catch (err) {
|
|
@@ -1432,7 +1478,7 @@ async function buildsCancel(id, opts, deps) {
|
|
|
1432
1478
|
if (opts.json) {
|
|
1433
1479
|
console.log(JSON.stringify(build));
|
|
1434
1480
|
} else {
|
|
1435
|
-
console.log(`${
|
|
1481
|
+
console.log(`${chalk13.cyan(build.id)} ${build.status}`);
|
|
1436
1482
|
}
|
|
1437
1483
|
process.exitCode = 0;
|
|
1438
1484
|
} catch (err) {
|
|
@@ -1449,7 +1495,7 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1449
1495
|
if (opts.json) {
|
|
1450
1496
|
console.log(JSON.stringify(result));
|
|
1451
1497
|
} else {
|
|
1452
|
-
console.log(
|
|
1498
|
+
console.log(chalk13.green(`\u2713 deleted artifact for ${id}`));
|
|
1453
1499
|
}
|
|
1454
1500
|
process.exitCode = 0;
|
|
1455
1501
|
} catch (err) {
|
|
@@ -1460,11 +1506,11 @@ async function buildsDeleteArtifact(id, opts, deps) {
|
|
|
1460
1506
|
function printError(opts, err) {
|
|
1461
1507
|
const message = err instanceof Error ? err.message : String(err);
|
|
1462
1508
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1463
|
-
console.error(
|
|
1509
|
+
console.error(chalk13.red(`error: ${message}`));
|
|
1464
1510
|
}
|
|
1465
1511
|
|
|
1466
1512
|
// src/commands/submit.ts
|
|
1467
|
-
import
|
|
1513
|
+
import chalk14 from "chalk";
|
|
1468
1514
|
function defaultDeps2(client) {
|
|
1469
1515
|
return {
|
|
1470
1516
|
createSubmission: client.createSubmission.bind(client),
|
|
@@ -1487,7 +1533,7 @@ function submitConfigFor(cwd, platform) {
|
|
|
1487
1533
|
cfg = loadDevConfig(cwd);
|
|
1488
1534
|
} catch (err) {
|
|
1489
1535
|
console.error(
|
|
1490
|
-
|
|
1536
|
+
chalk14.yellow(
|
|
1491
1537
|
`warning: vibeview.json could not be read \u2014 ignoring submit defaults (${err instanceof Error ? err.message : String(err)})`
|
|
1492
1538
|
)
|
|
1493
1539
|
);
|
|
@@ -1635,12 +1681,12 @@ async function submitCommand(opts, deps) {
|
|
|
1635
1681
|
return;
|
|
1636
1682
|
}
|
|
1637
1683
|
if (!opts.json) {
|
|
1638
|
-
console.error(` ${
|
|
1684
|
+
console.error(` ${chalk14.cyan(sub.id)} ${chalk14.dim(`[${sub.platform}]`)}`);
|
|
1639
1685
|
}
|
|
1640
1686
|
const final = await followSubmission(sub, opts, d);
|
|
1641
1687
|
if (!opts.json && final.status === "succeeded" && (final.release_status ?? releaseStatus) === "draft") {
|
|
1642
1688
|
console.error(
|
|
1643
|
-
|
|
1689
|
+
chalk14.dim("release status: draft \u2014 activate it from the Play Console when ready")
|
|
1644
1690
|
);
|
|
1645
1691
|
}
|
|
1646
1692
|
process.exitCode = final.status === "succeeded" ? 0 : 1;
|
|
@@ -1664,11 +1710,11 @@ async function checkStore(platform, androidFamily, ascKey2, opts, deps) {
|
|
|
1664
1710
|
});
|
|
1665
1711
|
emit(opts.json, { event: "preflight", ...result });
|
|
1666
1712
|
if (!opts.json) {
|
|
1667
|
-
const mark = result.ready ?
|
|
1713
|
+
const mark = result.ready ? chalk14.green("\u2713") : chalk14.red("\u2717");
|
|
1668
1714
|
console.error(`${mark} ${result.message}`);
|
|
1669
1715
|
if (result.ready) {
|
|
1670
1716
|
console.error(
|
|
1671
|
-
|
|
1717
|
+
chalk14.dim(
|
|
1672
1718
|
` next: vibeview build --cloud --production --platform ${platform}, then vibeview submit --platform ${platform} --latest`
|
|
1673
1719
|
)
|
|
1674
1720
|
);
|
|
@@ -1717,14 +1763,14 @@ async function followSubmission(created, opts, deps) {
|
|
|
1717
1763
|
if (opts.json) {
|
|
1718
1764
|
emit(opts.json, { event: "status", id: created.id, status: "queued" });
|
|
1719
1765
|
} else {
|
|
1720
|
-
console.error(
|
|
1766
|
+
console.error(chalk14.dim("\u23F3 queued \u2014 waiting for a submission slot"));
|
|
1721
1767
|
}
|
|
1722
1768
|
} else if (log.status === "running" && !printedRunning) {
|
|
1723
1769
|
printedRunning = true;
|
|
1724
1770
|
if (opts.json) {
|
|
1725
1771
|
emit(opts.json, { event: "status", id: created.id, status: "running" });
|
|
1726
1772
|
} else {
|
|
1727
|
-
console.error(`${
|
|
1773
|
+
console.error(`${chalk14.cyan("\u25B6")} submitting`);
|
|
1728
1774
|
}
|
|
1729
1775
|
}
|
|
1730
1776
|
if (log.content) {
|
|
@@ -1766,7 +1812,7 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1766
1812
|
});
|
|
1767
1813
|
if (!opts.json) {
|
|
1768
1814
|
const ok = final.status === "succeeded";
|
|
1769
|
-
const mark = ok ?
|
|
1815
|
+
const mark = ok ? chalk14.green("\u2713") : chalk14.red("\u2717");
|
|
1770
1816
|
const duration = formatDuration(final.started_at, final.finished_at);
|
|
1771
1817
|
let line = `${mark} ${final.status}`;
|
|
1772
1818
|
if (duration) line += ` (${duration})`;
|
|
@@ -1778,11 +1824,11 @@ The submission continues server-side \u2014 see its outcome on the Builds page i
|
|
|
1778
1824
|
function printError2(opts, err) {
|
|
1779
1825
|
const message = err instanceof Error ? err.message : String(err);
|
|
1780
1826
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1781
|
-
console.error(
|
|
1827
|
+
console.error(chalk14.red(`error: ${message}`));
|
|
1782
1828
|
}
|
|
1783
1829
|
|
|
1784
1830
|
// src/commands/versions.ts
|
|
1785
|
-
import
|
|
1831
|
+
import chalk15 from "chalk";
|
|
1786
1832
|
function defaultDeps3(client) {
|
|
1787
1833
|
return {
|
|
1788
1834
|
listAppVersions: client.listAppVersions.bind(client),
|
|
@@ -1832,7 +1878,7 @@ async function versionsSet(buildNumber, opts, deps) {
|
|
|
1832
1878
|
console.log(JSON.stringify(version));
|
|
1833
1879
|
} else {
|
|
1834
1880
|
console.log(
|
|
1835
|
-
|
|
1881
|
+
chalk15.green(`\u2713 ${version.platform} build number set to ${version.build_number}`) + chalk15.dim(
|
|
1836
1882
|
" \u2014 the next autoIncrement production build gets " + (version.build_number + 1)
|
|
1837
1883
|
)
|
|
1838
1884
|
);
|
|
@@ -1852,18 +1898,18 @@ function formatVersionsHuman(versions2) {
|
|
|
1852
1898
|
const widths = HEADERS2.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
1853
1899
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
1854
1900
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
1855
|
-
const lines = [
|
|
1901
|
+
const lines = [chalk15.bold(join3(padCells(HEADERS2)))];
|
|
1856
1902
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
1857
1903
|
return lines.join("\n") + "\n";
|
|
1858
1904
|
}
|
|
1859
1905
|
function printError3(opts, err) {
|
|
1860
1906
|
const message = err instanceof Error ? err.message : String(err);
|
|
1861
1907
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
1862
|
-
console.error(
|
|
1908
|
+
console.error(chalk15.red(`error: ${message}`));
|
|
1863
1909
|
}
|
|
1864
1910
|
|
|
1865
1911
|
// src/commands/whoami.ts
|
|
1866
|
-
import
|
|
1912
|
+
import chalk16 from "chalk";
|
|
1867
1913
|
function defaultDeps4(opts) {
|
|
1868
1914
|
const { token, baseUrl } = resolveAuth(opts);
|
|
1869
1915
|
const client = new ApiClient(baseUrl, token);
|
|
@@ -1885,27 +1931,27 @@ async function whoAmI(opts, deps) {
|
|
|
1885
1931
|
process.exitCode = 0;
|
|
1886
1932
|
return;
|
|
1887
1933
|
}
|
|
1888
|
-
console.log(`${
|
|
1934
|
+
console.log(`${chalk16.bold("Logged in as")} ${me.email}`);
|
|
1889
1935
|
if (me.memberships.length === 1) {
|
|
1890
|
-
console.log(`${
|
|
1936
|
+
console.log(`${chalk16.bold("Organization")} ${me.memberships[0].organization_name}`);
|
|
1891
1937
|
} else if (me.memberships.length > 1) {
|
|
1892
|
-
console.log(
|
|
1938
|
+
console.log(chalk16.bold("Organizations"));
|
|
1893
1939
|
for (const m of me.memberships) {
|
|
1894
1940
|
console.log(` ${m.organization_name} (${m.role})`);
|
|
1895
1941
|
}
|
|
1896
1942
|
}
|
|
1897
|
-
console.log(`${
|
|
1898
|
-
console.log(`${
|
|
1899
|
-
console.log(`${
|
|
1943
|
+
console.log(`${chalk16.bold("Member role")} ${me.role ?? "\u2014"}`);
|
|
1944
|
+
console.log(`${chalk16.bold("Token role")} ${me.token_role ?? "\u2014 (session auth)"}`);
|
|
1945
|
+
console.log(`${chalk16.bold("Effective role")} ${effective ?? "\u2014"}`);
|
|
1900
1946
|
if (me.is_superadmin) {
|
|
1901
|
-
console.log(
|
|
1947
|
+
console.log(chalk16.dim("Superadmin (platform-wide; does not raise the org role above)"));
|
|
1902
1948
|
}
|
|
1903
1949
|
if (me.role === "admin" && me.token_role && me.token_role !== "admin") {
|
|
1904
1950
|
console.log(
|
|
1905
|
-
|
|
1951
|
+
chalk16.yellow(
|
|
1906
1952
|
`
|
|
1907
|
-
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 ${
|
|
1908
|
-
Create an admin API token in the dashboard and use ${
|
|
1953
|
+
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 ${chalk16.bold("vibeview env set")}) will fail with a permissions error.
|
|
1954
|
+
Create an admin API token in the dashboard and use ${chalk16.bold("--token")} or ${chalk16.bold("VIBEVIEW_API_TOKEN")}.`
|
|
1909
1955
|
)
|
|
1910
1956
|
);
|
|
1911
1957
|
}
|
|
@@ -1915,7 +1961,7 @@ Create an admin API token in the dashboard and use ${chalk15.bold("--token")} or
|
|
|
1915
1961
|
if (opts.json) {
|
|
1916
1962
|
console.log(JSON.stringify({ event: "error", message }));
|
|
1917
1963
|
}
|
|
1918
|
-
console.error(
|
|
1964
|
+
console.error(chalk16.red(`error: ${message}`));
|
|
1919
1965
|
process.exitCode = 1;
|
|
1920
1966
|
}
|
|
1921
1967
|
}
|
|
@@ -1923,7 +1969,7 @@ Create an admin API token in the dashboard and use ${chalk15.bold("--token")} or
|
|
|
1923
1969
|
// src/commands/env.ts
|
|
1924
1970
|
import { chmod, open as open2, readFile as readFileAsync } from "fs/promises";
|
|
1925
1971
|
import { basename } from "path";
|
|
1926
|
-
import
|
|
1972
|
+
import chalk17 from "chalk";
|
|
1927
1973
|
import { password } from "@inquirer/prompts";
|
|
1928
1974
|
|
|
1929
1975
|
// src/lib/gitignore.ts
|
|
@@ -1979,7 +2025,7 @@ function defaultDeps5(client) {
|
|
|
1979
2025
|
isIgnored: (path) => isGitIgnored(path),
|
|
1980
2026
|
writeFile: writeSecureFile,
|
|
1981
2027
|
readFile: (path) => readFileAsync(path),
|
|
1982
|
-
warn: (message) => console.error(
|
|
2028
|
+
warn: (message) => console.error(chalk17.yellow(`warning: ${message}`))
|
|
1983
2029
|
};
|
|
1984
2030
|
}
|
|
1985
2031
|
async function envList(opts, deps) {
|
|
@@ -2011,7 +2057,7 @@ function formatEnvVarsHuman(variables) {
|
|
|
2011
2057
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2012
2058
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2013
2059
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2014
|
-
const lines = [
|
|
2060
|
+
const lines = [chalk17.bold(join3(padCells(HEADERS3)))];
|
|
2015
2061
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2016
2062
|
return lines.join("\n") + "\n";
|
|
2017
2063
|
}
|
|
@@ -2061,7 +2107,7 @@ function printSetResult(opts, result) {
|
|
|
2061
2107
|
if (opts.json) {
|
|
2062
2108
|
console.log(JSON.stringify(result));
|
|
2063
2109
|
} else {
|
|
2064
|
-
console.log(
|
|
2110
|
+
console.log(chalk17.green(`\u2713 set ${result.name} (${result.visibility})`));
|
|
2065
2111
|
}
|
|
2066
2112
|
}
|
|
2067
2113
|
async function envRm(name, opts, deps) {
|
|
@@ -2071,7 +2117,7 @@ async function envRm(name, opts, deps) {
|
|
|
2071
2117
|
if (opts.json) {
|
|
2072
2118
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2073
2119
|
} else {
|
|
2074
|
-
console.log(
|
|
2120
|
+
console.log(chalk17.green(`\u2713 removed ${name}`));
|
|
2075
2121
|
}
|
|
2076
2122
|
process.exitCode = 0;
|
|
2077
2123
|
} catch (err) {
|
|
@@ -2103,7 +2149,7 @@ async function envPull(opts, deps) {
|
|
|
2103
2149
|
if (opts.json) {
|
|
2104
2150
|
console.log(JSON.stringify({ event: "pulled", path: outPath, count: variables.length }));
|
|
2105
2151
|
} else {
|
|
2106
|
-
console.log(
|
|
2152
|
+
console.log(chalk17.green(`\u2713 wrote ${variables.length} variable(s) to ${outPath}`));
|
|
2107
2153
|
}
|
|
2108
2154
|
process.exitCode = 0;
|
|
2109
2155
|
} catch (err) {
|
|
@@ -2142,7 +2188,7 @@ function escapeEnvValue(value) {
|
|
|
2142
2188
|
function printError4(opts, err) {
|
|
2143
2189
|
const message = err instanceof Error ? err.message : String(err);
|
|
2144
2190
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2145
|
-
console.error(
|
|
2191
|
+
console.error(chalk17.red(`error: ${message}`));
|
|
2146
2192
|
}
|
|
2147
2193
|
|
|
2148
2194
|
// src/commands/credentials.ts
|
|
@@ -2154,7 +2200,7 @@ import {
|
|
|
2154
2200
|
} from "fs/promises";
|
|
2155
2201
|
import { mkdirSync } from "fs";
|
|
2156
2202
|
import { basename as basename2, extname, join } from "path";
|
|
2157
|
-
import
|
|
2203
|
+
import chalk18 from "chalk";
|
|
2158
2204
|
import { input, password as password2 } from "@inquirer/prompts";
|
|
2159
2205
|
function clientFor2(opts) {
|
|
2160
2206
|
const { token, baseUrl } = resolveAuth(opts);
|
|
@@ -2227,7 +2273,7 @@ function defaultDeps6(client) {
|
|
|
2227
2273
|
mkdir: (dir) => mkdirSync(dir, { recursive: true }),
|
|
2228
2274
|
writeFile: (path, data, mode) => writeFileAsync(path, data, mode !== void 0 ? { mode } : void 0),
|
|
2229
2275
|
chmod: (path, mode) => chmodAsync(path, mode),
|
|
2230
|
-
warn: (message) => console.error(
|
|
2276
|
+
warn: (message) => console.error(chalk18.yellow(`warning: ${message}`))
|
|
2231
2277
|
};
|
|
2232
2278
|
}
|
|
2233
2279
|
var ANDROID_KIND = "android_keystore";
|
|
@@ -2296,7 +2342,7 @@ async function credentialsAdd(opts, deps) {
|
|
|
2296
2342
|
if (opts.json) {
|
|
2297
2343
|
console.log(JSON.stringify(result));
|
|
2298
2344
|
} else {
|
|
2299
|
-
console.log(
|
|
2345
|
+
console.log(chalk18.green(`\u2713 added ${result.name} (${result.platform})`));
|
|
2300
2346
|
}
|
|
2301
2347
|
process.exitCode = 0;
|
|
2302
2348
|
} catch (err) {
|
|
@@ -2354,20 +2400,20 @@ async function credentialsGenerate(opts, deps) {
|
|
|
2354
2400
|
}
|
|
2355
2401
|
if (opts.json) {
|
|
2356
2402
|
} else {
|
|
2357
|
-
console.log(
|
|
2403
|
+
console.log(chalk18.green(`\u2713 generated ${result.name} (android)`));
|
|
2358
2404
|
console.log("");
|
|
2359
|
-
console.log(` Keystore saved to: ${
|
|
2360
|
-
console.log(` Key alias: ${
|
|
2361
|
-
console.log(` Store password: ${
|
|
2362
|
-
console.log(` Key password: ${
|
|
2405
|
+
console.log(` Keystore saved to: ${chalk18.bold(savedTo)}`);
|
|
2406
|
+
console.log(` Key alias: ${chalk18.bold(result.key_alias)}`);
|
|
2407
|
+
console.log(` Store password: ${chalk18.bold(result.store_password)}`);
|
|
2408
|
+
console.log(` Key password: ${chalk18.bold(result.key_password)}`);
|
|
2363
2409
|
console.log("");
|
|
2364
2410
|
console.log(
|
|
2365
|
-
|
|
2411
|
+
chalk18.yellow(
|
|
2366
2412
|
" These are shown ONCE \u2014 VibeView cannot recover the keystore file or its passwords. Back them up somewhere safe."
|
|
2367
2413
|
)
|
|
2368
2414
|
);
|
|
2369
2415
|
console.log(
|
|
2370
|
-
|
|
2416
|
+
chalk18.yellow(
|
|
2371
2417
|
" The credential is already uploaded and active for android and androidtv production builds."
|
|
2372
2418
|
)
|
|
2373
2419
|
);
|
|
@@ -2393,19 +2439,19 @@ async function generateAppleCredential(platform, opts, d) {
|
|
|
2393
2439
|
if (opts.json) {
|
|
2394
2440
|
console.log(JSON.stringify(result));
|
|
2395
2441
|
} else {
|
|
2396
|
-
console.log(
|
|
2442
|
+
console.log(chalk18.green(`\u2713 generated ${result.name} (${result.platform})`));
|
|
2397
2443
|
console.log("");
|
|
2398
|
-
console.log(` Scope: ${
|
|
2444
|
+
console.log(` Scope: ${chalk18.bold(result.app_public_id ?? "org-wide")}`);
|
|
2399
2445
|
const expires = formatExpires(result);
|
|
2400
2446
|
if (expires) {
|
|
2401
|
-
console.log(` Expires: ${
|
|
2447
|
+
console.log(` Expires: ${chalk18.bold(expires)}`);
|
|
2402
2448
|
}
|
|
2403
2449
|
console.log("");
|
|
2404
2450
|
console.log(
|
|
2405
2451
|
` The certificate and provisioning profile are stored with VibeView and already active for ${result.platform} production builds.`
|
|
2406
2452
|
);
|
|
2407
2453
|
console.log(
|
|
2408
|
-
` Run ${
|
|
2454
|
+
` Run ${chalk18.bold(`vibeview credentials download ${result.name}`)} if you need the files locally.`
|
|
2409
2455
|
);
|
|
2410
2456
|
}
|
|
2411
2457
|
process.exitCode = 0;
|
|
@@ -2471,17 +2517,17 @@ async function credentialsDownload(name, opts, deps) {
|
|
|
2471
2517
|
await d.chmod(path, 384);
|
|
2472
2518
|
}
|
|
2473
2519
|
if (!opts.json) {
|
|
2474
|
-
console.log(
|
|
2520
|
+
console.log(chalk18.green(`\u2713 downloaded ${material.name} (${material.platform})`));
|
|
2475
2521
|
console.log("");
|
|
2476
|
-
console.log(` Saved to: ${
|
|
2522
|
+
console.log(` Saved to: ${chalk18.bold(savedTo)}`);
|
|
2477
2523
|
if (profileSavedTo !== null) {
|
|
2478
|
-
console.log(` Profile: ${
|
|
2524
|
+
console.log(` Profile: ${chalk18.bold(profileSavedTo)}`);
|
|
2479
2525
|
}
|
|
2480
2526
|
for (const [key, value] of Object.entries(material.passwords)) {
|
|
2481
|
-
console.log(` ${key}: ${
|
|
2527
|
+
console.log(` ${key}: ${chalk18.bold(value)}`);
|
|
2482
2528
|
}
|
|
2483
2529
|
console.log("");
|
|
2484
|
-
console.log(
|
|
2530
|
+
console.log(chalk18.yellow(" This download is recorded in your organization's audit log."));
|
|
2485
2531
|
}
|
|
2486
2532
|
process.exitCode = 0;
|
|
2487
2533
|
} catch (err) {
|
|
@@ -2512,13 +2558,13 @@ async function ascKeyAdd(opts, deps) {
|
|
|
2512
2558
|
if (opts.json) {
|
|
2513
2559
|
console.log(JSON.stringify(result));
|
|
2514
2560
|
} else {
|
|
2515
|
-
console.log(
|
|
2561
|
+
console.log(chalk18.green(`\u2713 added App Store Connect key ${result.name}`));
|
|
2516
2562
|
console.log("");
|
|
2517
|
-
console.log(` Key ID: ${
|
|
2518
|
-
console.log(` Issuer ID: ${
|
|
2563
|
+
console.log(` Key ID: ${chalk18.bold(result.key_id)}`);
|
|
2564
|
+
console.log(` Issuer ID: ${chalk18.bold(result.issuer_id)}`);
|
|
2519
2565
|
console.log("");
|
|
2520
2566
|
console.log(
|
|
2521
|
-
|
|
2567
|
+
chalk18.yellow(
|
|
2522
2568
|
" The .p8 is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2523
2569
|
)
|
|
2524
2570
|
);
|
|
@@ -2553,7 +2599,7 @@ function formatAscKeysHuman(keys) {
|
|
|
2553
2599
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2554
2600
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2555
2601
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2556
|
-
const lines = [
|
|
2602
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2557
2603
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2558
2604
|
return lines.join("\n") + "\n";
|
|
2559
2605
|
}
|
|
@@ -2564,7 +2610,7 @@ async function ascKeyRm(name, opts, deps) {
|
|
|
2564
2610
|
if (opts.json) {
|
|
2565
2611
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2566
2612
|
} else {
|
|
2567
|
-
console.log(
|
|
2613
|
+
console.log(chalk18.green(`\u2713 removed App Store Connect key ${name}`));
|
|
2568
2614
|
}
|
|
2569
2615
|
process.exitCode = 0;
|
|
2570
2616
|
} catch (err) {
|
|
@@ -2589,12 +2635,12 @@ async function playKeyAdd(opts, deps) {
|
|
|
2589
2635
|
if (opts.json) {
|
|
2590
2636
|
console.log(JSON.stringify(result));
|
|
2591
2637
|
} else {
|
|
2592
|
-
console.log(
|
|
2638
|
+
console.log(chalk18.green(`\u2713 added Google Play key ${result.name}`));
|
|
2593
2639
|
console.log("");
|
|
2594
|
-
console.log(` Service account: ${
|
|
2640
|
+
console.log(` Service account: ${chalk18.bold(result.client_email)}`);
|
|
2595
2641
|
console.log("");
|
|
2596
2642
|
console.log(
|
|
2597
|
-
|
|
2643
|
+
chalk18.yellow(
|
|
2598
2644
|
" The JSON key is stored encrypted and will never be shown again \u2014 keep your own copy somewhere safe."
|
|
2599
2645
|
)
|
|
2600
2646
|
);
|
|
@@ -2629,7 +2675,7 @@ function formatPlayKeysHuman(keys) {
|
|
|
2629
2675
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2630
2676
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2631
2677
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2632
|
-
const lines = [
|
|
2678
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2633
2679
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2634
2680
|
return lines.join("\n") + "\n";
|
|
2635
2681
|
}
|
|
@@ -2640,7 +2686,7 @@ async function playKeyRm(name, opts, deps) {
|
|
|
2640
2686
|
if (opts.json) {
|
|
2641
2687
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2642
2688
|
} else {
|
|
2643
|
-
console.log(
|
|
2689
|
+
console.log(chalk18.green(`\u2713 removed Google Play key ${name}`));
|
|
2644
2690
|
}
|
|
2645
2691
|
process.exitCode = 0;
|
|
2646
2692
|
} catch (err) {
|
|
@@ -2709,7 +2755,7 @@ function formatCredentialsHuman(credentials2) {
|
|
|
2709
2755
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2710
2756
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2711
2757
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2712
|
-
const lines = [
|
|
2758
|
+
const lines = [chalk18.bold(join3(padCells(HEADERS3)))];
|
|
2713
2759
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2714
2760
|
return lines.join("\n") + "\n";
|
|
2715
2761
|
}
|
|
@@ -2720,7 +2766,7 @@ async function credentialsRm(name, opts, deps) {
|
|
|
2720
2766
|
if (opts.json) {
|
|
2721
2767
|
console.log(JSON.stringify({ event: "deleted", name }));
|
|
2722
2768
|
} else {
|
|
2723
|
-
console.log(
|
|
2769
|
+
console.log(chalk18.green(`\u2713 removed ${name}`));
|
|
2724
2770
|
}
|
|
2725
2771
|
process.exitCode = 0;
|
|
2726
2772
|
} catch (err) {
|
|
@@ -2732,16 +2778,16 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2732
2778
|
const message = err instanceof Error ? err.message : String(err);
|
|
2733
2779
|
if (opts.json) {
|
|
2734
2780
|
console.log(JSON.stringify({ event: "error", message }));
|
|
2735
|
-
console.error(
|
|
2781
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2736
2782
|
return;
|
|
2737
2783
|
}
|
|
2738
|
-
console.error(
|
|
2784
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2739
2785
|
console.error(
|
|
2740
|
-
|
|
2786
|
+
chalk18.red(
|
|
2741
2787
|
`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.`
|
|
2742
2788
|
)
|
|
2743
2789
|
);
|
|
2744
|
-
console.error(
|
|
2790
|
+
console.error(chalk18.red("Recover it NOW from the values below \u2014 they will not be shown again:"));
|
|
2745
2791
|
console.error("");
|
|
2746
2792
|
console.error(` Key alias: ${result.key_alias}`);
|
|
2747
2793
|
console.error(` Store password: ${result.store_password}`);
|
|
@@ -2755,11 +2801,11 @@ function printKeystoreWriteFailure(opts, err, result) {
|
|
|
2755
2801
|
function printError5(opts, err) {
|
|
2756
2802
|
const message = err instanceof Error ? err.message : String(err);
|
|
2757
2803
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2758
|
-
console.error(
|
|
2804
|
+
console.error(chalk18.red(`error: ${message}`));
|
|
2759
2805
|
}
|
|
2760
2806
|
|
|
2761
2807
|
// src/commands/webhooks.ts
|
|
2762
|
-
import
|
|
2808
|
+
import chalk19 from "chalk";
|
|
2763
2809
|
function clientFor3(opts) {
|
|
2764
2810
|
const { token, baseUrl } = resolveAuth(opts);
|
|
2765
2811
|
return new ApiClient(baseUrl, token);
|
|
@@ -2790,14 +2836,14 @@ async function webhooksAdd(opts, deps) {
|
|
|
2790
2836
|
if (opts.json) {
|
|
2791
2837
|
console.log(JSON.stringify(result));
|
|
2792
2838
|
} else {
|
|
2793
|
-
console.log(
|
|
2839
|
+
console.log(chalk19.green(`\u2713 added ${result.id} ${result.url}`));
|
|
2794
2840
|
console.log("");
|
|
2795
|
-
console.log(` Signing secret: ${
|
|
2841
|
+
console.log(` Signing secret: ${chalk19.bold(result.secret)}`);
|
|
2796
2842
|
if (opts.secret !== void 0) {
|
|
2797
|
-
console.log(
|
|
2843
|
+
console.log(chalk19.yellow(" (This is the secret you provided.)"));
|
|
2798
2844
|
}
|
|
2799
2845
|
console.log(
|
|
2800
|
-
|
|
2846
|
+
chalk19.yellow(" This secret is shown ONCE and cannot be retrieved again \u2014 store it now.")
|
|
2801
2847
|
);
|
|
2802
2848
|
}
|
|
2803
2849
|
process.exitCode = 0;
|
|
@@ -2828,7 +2874,7 @@ function formatWebhooksHuman(webhooks2) {
|
|
|
2828
2874
|
const widths = HEADERS3.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
2829
2875
|
const padCells = (cells) => cells.map((c, i) => c.padEnd(widths[i]));
|
|
2830
2876
|
const join3 = (cells) => cells.join(" ").trimEnd();
|
|
2831
|
-
const lines = [
|
|
2877
|
+
const lines = [chalk19.bold(join3(padCells(HEADERS3)))];
|
|
2832
2878
|
for (const row of rows) lines.push(join3(padCells(row)));
|
|
2833
2879
|
return lines.join("\n") + "\n";
|
|
2834
2880
|
}
|
|
@@ -2854,7 +2900,7 @@ async function webhooksRm(id, opts, deps) {
|
|
|
2854
2900
|
if (opts.json) {
|
|
2855
2901
|
console.log(JSON.stringify({ event: "deleted", id }));
|
|
2856
2902
|
} else {
|
|
2857
|
-
console.log(
|
|
2903
|
+
console.log(chalk19.green(`\u2713 removed ${id}`));
|
|
2858
2904
|
}
|
|
2859
2905
|
process.exitCode = 0;
|
|
2860
2906
|
} catch (err) {
|
|
@@ -2887,13 +2933,13 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2887
2933
|
if (opts.json) console.log(JSON.stringify(ld));
|
|
2888
2934
|
if (ld.status === "succeeded") {
|
|
2889
2935
|
if (!opts.json) {
|
|
2890
|
-
console.log(
|
|
2936
|
+
console.log(chalk19.green(`\u2713 Delivered (HTTP ${ld.response_code})`));
|
|
2891
2937
|
}
|
|
2892
2938
|
process.exitCode = 0;
|
|
2893
2939
|
} else {
|
|
2894
2940
|
if (!opts.json) {
|
|
2895
2941
|
const code = ld.response_code != null ? `HTTP ${ld.response_code}` : "no response";
|
|
2896
|
-
console.error(
|
|
2942
|
+
console.error(chalk19.red(`\u2717 Failed (${code}) at ${ld.at}`));
|
|
2897
2943
|
}
|
|
2898
2944
|
process.exitCode = 1;
|
|
2899
2945
|
}
|
|
@@ -2902,7 +2948,7 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2902
2948
|
}
|
|
2903
2949
|
if (opts.json) console.log(JSON.stringify({ status: "pending" }));
|
|
2904
2950
|
console.error(
|
|
2905
|
-
|
|
2951
|
+
chalk19.yellow(
|
|
2906
2952
|
`Delivery still pending after ${TEST_POLL_BUDGET_MS / 1e3}s \u2014 check \`vibeview webhooks list\` later for the result.`
|
|
2907
2953
|
)
|
|
2908
2954
|
);
|
|
@@ -2915,7 +2961,7 @@ async function webhooksTest(id, opts, deps) {
|
|
|
2915
2961
|
function printError6(opts, err) {
|
|
2916
2962
|
const message = err instanceof Error ? err.message : String(err);
|
|
2917
2963
|
if (opts.json) console.log(JSON.stringify({ event: "error", message }));
|
|
2918
|
-
console.error(
|
|
2964
|
+
console.error(chalk19.red(`error: ${message}`));
|
|
2919
2965
|
}
|
|
2920
2966
|
|
|
2921
2967
|
// src/commands/list-devices.ts
|
|
@@ -3015,7 +3061,7 @@ import { dirname, join as join2 } from "path";
|
|
|
3015
3061
|
import { fileURLToPath } from "url";
|
|
3016
3062
|
import { spawnSync } from "child_process";
|
|
3017
3063
|
import { confirm } from "@inquirer/prompts";
|
|
3018
|
-
import
|
|
3064
|
+
import chalk20 from "chalk";
|
|
3019
3065
|
function resolveShippedSkillPath(fromDir) {
|
|
3020
3066
|
for (const rel of ["..", join2("..", "..")]) {
|
|
3021
3067
|
const candidate = join2(fromDir, rel, "skills", "vibeview-agent", "SKILL.md");
|
|
@@ -3043,23 +3089,23 @@ function registerMcp() {
|
|
|
3043
3089
|
encoding: "utf8"
|
|
3044
3090
|
});
|
|
3045
3091
|
if (res.status === 0) {
|
|
3046
|
-
console.log(
|
|
3092
|
+
console.log(chalk20.green("\u2713 MCP server registered with Claude Code (claude mcp add vibeview)"));
|
|
3047
3093
|
return;
|
|
3048
3094
|
}
|
|
3049
3095
|
const out = `${res.stderr ?? ""}${res.stdout ?? ""}`;
|
|
3050
3096
|
if (out.includes("already exists")) {
|
|
3051
|
-
console.log(
|
|
3097
|
+
console.log(chalk20.dim("MCP server already registered with Claude Code \u2014 nothing to do"));
|
|
3052
3098
|
return;
|
|
3053
3099
|
}
|
|
3054
|
-
console.error(
|
|
3055
|
-
console.error(
|
|
3100
|
+
console.error(chalk20.yellow(`\u26A0 could not register the MCP server: ${out.trim() || res.error}`));
|
|
3101
|
+
console.error(chalk20.yellow(" register it manually: claude mcp add vibeview -- vibeview mcp"));
|
|
3056
3102
|
}
|
|
3057
3103
|
async function agentSetup(opts) {
|
|
3058
3104
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
3059
3105
|
const shipped = resolveShippedSkillPath(moduleDir);
|
|
3060
3106
|
if (!shipped) {
|
|
3061
3107
|
console.error(
|
|
3062
|
-
|
|
3108
|
+
chalk20.red(
|
|
3063
3109
|
"error: could not find the packaged skill (skills/vibeview-agent/SKILL.md) \u2014 is this a complete install of the vibeview package?"
|
|
3064
3110
|
)
|
|
3065
3111
|
);
|
|
@@ -3068,9 +3114,9 @@ async function agentSetup(opts) {
|
|
|
3068
3114
|
}
|
|
3069
3115
|
const targetDir = skillInstallDir(opts.project ?? false, process.cwd(), homedir());
|
|
3070
3116
|
const result = installSkill(shipped, targetDir);
|
|
3071
|
-
console.log(
|
|
3117
|
+
console.log(chalk20.green(`\u2713 vibeview-agent skill ${result}: ${join2(targetDir, "SKILL.md")}`));
|
|
3072
3118
|
console.log(
|
|
3073
|
-
|
|
3119
|
+
chalk20.dim(
|
|
3074
3120
|
opts.project ? " Claude Code discovers it automatically for anyone working in this project." : " Claude Code discovers it automatically in every project on this machine."
|
|
3075
3121
|
)
|
|
3076
3122
|
);
|
|
@@ -3078,7 +3124,7 @@ async function agentSetup(opts) {
|
|
|
3078
3124
|
if (!claudeCliAvailable()) {
|
|
3079
3125
|
if (opts.mcp === true) {
|
|
3080
3126
|
console.error(
|
|
3081
|
-
|
|
3127
|
+
chalk20.yellow(
|
|
3082
3128
|
"\u26A0 claude CLI not found \u2014 install Claude Code, then run: claude mcp add vibeview -- vibeview mcp"
|
|
3083
3129
|
)
|
|
3084
3130
|
);
|
|
@@ -3092,7 +3138,7 @@ async function agentSetup(opts) {
|
|
|
3092
3138
|
}
|
|
3093
3139
|
console.log(
|
|
3094
3140
|
`
|
|
3095
|
-
Suggested line for your project's ${
|
|
3141
|
+
Suggested line for your project's ${chalk20.bold("CLAUDE.md")} (or ${chalk20.bold(
|
|
3096
3142
|
"AGENTS.md"
|
|
3097
3143
|
)} for other agents):
|
|
3098
3144
|
`
|
|
@@ -3100,7 +3146,7 @@ Suggested line for your project's ${chalk19.bold("CLAUDE.md")} (or ${chalk19.bol
|
|
|
3100
3146
|
console.log(` ${CLAUDE_MD_SUGGESTION}
|
|
3101
3147
|
`);
|
|
3102
3148
|
console.log(
|
|
3103
|
-
|
|
3149
|
+
chalk20.dim(
|
|
3104
3150
|
"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"
|
|
3105
3151
|
)
|
|
3106
3152
|
);
|
|
@@ -3222,6 +3268,9 @@ program.command("list-suites").description("List available test suites").option(
|
|
|
3222
3268
|
[]
|
|
3223
3269
|
).option("--match <mode>", "When multiple --tag flags: any (default) or all", "any").action((opts) => listSuites(opts));
|
|
3224
3270
|
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));
|
|
3271
|
+
program.command("list-builds <app>").description(
|
|
3272
|
+
"List an app's uploaded builds, newest first: id, version, platform, debug/release, upload time and note (the ids `dev --build <id>` and `run-test --build` take)"
|
|
3273
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the builds as a JSON array", false).action((app, opts) => listBuilds(app, opts));
|
|
3225
3274
|
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").option(
|
|
3226
3275
|
"--models",
|
|
3227
3276
|
"List the device models you can start instead (the names `dev --model` takes)",
|
|
@@ -3244,14 +3293,14 @@ program.command("dev").description(
|
|
|
3244
3293
|
parseDeviceCategory
|
|
3245
3294
|
).option(
|
|
3246
3295
|
"--model <name>",
|
|
3247
|
-
'Run on this exact device model, e.g. "iPhone Duo" (see `vibeview list-devices --models`)'
|
|
3296
|
+
'Run on this exact device model, e.g. "iPhone Duo" or "Pixel 9 Pro Fold" (see `vibeview list-devices --models`)'
|
|
3248
3297
|
).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(
|
|
3249
3298
|
"--detach",
|
|
3250
3299
|
"Run the dev session in the background; prints session info and exits (see `dev-status`, `dev-stop`, and `dev-reload` for Roku)",
|
|
3251
3300
|
false
|
|
3252
3301
|
).option(
|
|
3253
|
-
"--build",
|
|
3254
|
-
"
|
|
3302
|
+
"--build [id]",
|
|
3303
|
+
"Bare: build and upload first (uses platforms.<platform>.build from vibeview.json). With an id: run that uploaded debug build instead of the newest one (see `vibeview list-builds <app>`)",
|
|
3255
3304
|
false
|
|
3256
3305
|
).option(
|
|
3257
3306
|
"--watch [seconds]",
|
|
@@ -3387,13 +3436,16 @@ webhooks.command("rm <id>").description("Remove a webhook endpoint (rotate the s
|
|
|
3387
3436
|
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));
|
|
3388
3437
|
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));
|
|
3389
3438
|
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));
|
|
3439
|
+
program.command("stop <session-id>").description(
|
|
3440
|
+
"Stop any session by id \u2014 e.g. one started from the API, the sandbox, or a collaboration link (`dev-stop` stops this project's detached dev session without an id)"
|
|
3441
|
+
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print the result as one JSON line", false).action((sessionId, opts) => stopCommand(sessionId, opts));
|
|
3390
3442
|
program.command("dev-reload").description(
|
|
3391
3443
|
"Roku only: re-package, upload and reload the channel into this project's `vibeview dev --detach` session (the `r` key of the foreground loop)"
|
|
3392
3444
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").option("--json", "Print as one JSON line", false).action((opts) => devReload(opts));
|
|
3393
3445
|
program.command("mcp").description(
|
|
3394
3446
|
"Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop/dev_reload as tools"
|
|
3395
3447
|
).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
|
|
3396
|
-
const { runMcpServer } = await import("./server-
|
|
3448
|
+
const { runMcpServer } = await import("./server-KYDTXPRZ.js");
|
|
3397
3449
|
await runMcpServer(opts);
|
|
3398
3450
|
});
|
|
3399
3451
|
program.command("agent-setup").description(
|