vibeview 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import {
5
5
  loadConfig,
6
6
  resolveAuth,
7
7
  uploadAppBuild
8
- } from "./chunk-J7V3GYOI.js";
8
+ } from "./chunk-2WTLJ66O.js";
9
9
 
10
10
  // src/lib/dev-state.ts
11
11
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
@@ -148,6 +148,20 @@ function loadDevConfig(cwd) {
148
148
  `vibeview.json: platforms.${key}.build.artifact must be a non-empty string`
149
149
  );
150
150
  }
151
+ if (entry.build.productionCommand !== void 0) {
152
+ if (typeof entry.build.productionCommand !== "string" || !entry.build.productionCommand) {
153
+ throw new Error(
154
+ `vibeview.json: platforms.${key}.build.productionCommand must be a non-empty string`
155
+ );
156
+ }
157
+ }
158
+ if (entry.build.productionArtifact !== void 0) {
159
+ if (typeof entry.build.productionArtifact !== "string" || !entry.build.productionArtifact) {
160
+ throw new Error(
161
+ `vibeview.json: platforms.${key}.build.productionArtifact must be a non-empty string`
162
+ );
163
+ }
164
+ }
151
165
  }
152
166
  if (entry.watchIgnore !== void 0) {
153
167
  if (!Array.isArray(entry.watchIgnore)) {
@@ -252,7 +266,7 @@ async function checkMetro(port, timeoutMs = 1500) {
252
266
  import { spawn as spawn2 } from "child_process";
253
267
  import { createInterface } from "readline";
254
268
  import { select as select2 } from "@inquirer/prompts";
255
- import chalk from "chalk";
269
+ import chalk2 from "chalk";
256
270
 
257
271
  // src/lib/artifact.ts
258
272
  import { existsSync as existsSync2, mkdtempSync, readdirSync, rmSync as rmSync2, statSync } from "fs";
@@ -312,6 +326,7 @@ function prepareUploadArtifact(path) {
312
326
  }
313
327
 
314
328
  // src/lib/dev-setup.ts
329
+ import chalk from "chalk";
315
330
  import { input, select } from "@inquirer/prompts";
316
331
 
317
332
  // src/lib/project-detect.ts
@@ -402,6 +417,26 @@ function defaultsFor(cwd, platform) {
402
417
  metroCommand
403
418
  };
404
419
  }
420
+ var ANDROID_PRODUCTION_ARTIFACT = "android/app/build/outputs/bundle/release/*.aab";
421
+ var ANDROID_PRODUCTION_COMMAND = "yarn install --immutable && cd android && ./gradlew bundleRelease";
422
+ var IOS_PRODUCTION_ARTIFACT = "ios/build/*.ipa";
423
+ function productionDefaultsFor(cwd, platform) {
424
+ if (platform === "android") {
425
+ return { buildCommand: ANDROID_PRODUCTION_COMMAND, artifact: ANDROID_PRODUCTION_ARTIFACT };
426
+ }
427
+ if (platform === "ios") {
428
+ const ws = iosWorkspaceName(cwd);
429
+ if (!ws) return { artifact: IOS_PRODUCTION_ARTIFACT };
430
+ const archivePath = `ios/build/${ws}.xcarchive`;
431
+ const archiveCmd = `xcodebuild archive -workspace ios/${ws}.xcworkspace -scheme ${ws} -configuration Release -archivePath ${archivePath} CODE_SIGN_STYLE=Manual \${VIBEVIEW_DEVELOPMENT_TEAM:+"DEVELOPMENT_TEAM=$VIBEVIEW_DEVELOPMENT_TEAM"} \${VIBEVIEW_PROVISIONING_PROFILE:+"PROVISIONING_PROFILE_SPECIFIER=$VIBEVIEW_PROVISIONING_PROFILE"} \${VIBEVIEW_CODE_SIGN_IDENTITY:+"CODE_SIGN_IDENTITY=$VIBEVIEW_CODE_SIGN_IDENTITY"}`;
432
+ const exportCmd = `xcodebuild -exportArchive -archivePath ${archivePath} -exportPath ios/build -exportOptionsPlist "$VIBEVIEW_EXPORT_OPTIONS_PLIST"`;
433
+ return {
434
+ buildCommand: `yarn install --immutable && ${archiveCmd} && ${exportCmd}`,
435
+ artifact: IOS_PRODUCTION_ARTIFACT
436
+ };
437
+ }
438
+ return {};
439
+ }
405
440
 
406
441
  // src/lib/dev-setup.ts
407
442
  function platformChoices(cwd) {
@@ -454,6 +489,11 @@ async function promptBuildConfig(cwd, platform) {
454
489
  if (choice === "default") {
455
490
  return { command: defaults.buildCommand, artifact: defaults.artifact };
456
491
  }
492
+ console.log(
493
+ chalk.dim(
494
+ " Tip: include your install step \u2014 dependencies are not uploaded.\n e.g. `yarn install --immutable && yarn build:android`"
495
+ )
496
+ );
457
497
  const command = await input({ message: `Build command for ${platform}`, required: true });
458
498
  const artifact = await input({
459
499
  message: platform === "roku" ? "Path to the channel zip it produces (* allowed)" : "Path to the built app it produces (.apk, or .app dir; * allowed)",
@@ -462,6 +502,35 @@ async function promptBuildConfig(cwd, platform) {
462
502
  });
463
503
  return { command, artifact };
464
504
  }
505
+ async function promptProductionBuildConfig(cwd, platform) {
506
+ const defaults = productionDefaultsFor(cwd, platform);
507
+ const choice = await commandSelect(
508
+ `Production build command for ${platform}`,
509
+ defaults.buildCommand
510
+ );
511
+ if (choice === "skip") return null;
512
+ if (choice === "default") {
513
+ return {
514
+ productionCommand: defaults.buildCommand,
515
+ productionArtifact: defaults.artifact
516
+ };
517
+ }
518
+ console.log(
519
+ chalk.dim(
520
+ " Tip: include your install step \u2014 dependencies are not uploaded.\n e.g. `yarn install --immutable && cd android && ./gradlew bundleRelease`"
521
+ )
522
+ );
523
+ const productionCommand = await input({
524
+ message: `Production build command for ${platform}`,
525
+ required: true
526
+ });
527
+ const productionArtifact = await input({
528
+ message: "Path to the signed production artifact it produces (.aab/.ipa; * allowed)",
529
+ default: defaults.artifact,
530
+ required: true
531
+ });
532
+ return { productionCommand, productionArtifact };
533
+ }
465
534
  async function promptMetroCommand(cwd, platform) {
466
535
  const defaults = defaultsFor(cwd, platform);
467
536
  const choice = await commandSelect("Command that starts Metro", defaults.metroCommand);
@@ -642,6 +711,7 @@ function runTar(args) {
642
711
 
643
712
  // src/commands/build.ts
644
713
  var CLOUD_PLATFORMS = ["ios", "android", "tvos", "androidtv"];
714
+ var PRODUCTION_SIGNING_PLATFORMS = ["ios", "android"];
645
715
  function isCloudPlatform(p) {
646
716
  return CLOUD_PLATFORMS.includes(p);
647
717
  }
@@ -692,7 +762,7 @@ function runShell(command, cwd, log) {
692
762
  }
693
763
  async function resolveBarePlatform(cwd, cfg, opts) {
694
764
  if (opts.platform && !isDevPlatform(opts.platform)) {
695
- console.error(chalk.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
765
+ console.error(chalk2.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
696
766
  process.exit(2);
697
767
  }
698
768
  let platform = opts.platform || cfg?.defaultPlatform;
@@ -753,6 +823,37 @@ async function resolveBuildConfig(cwd, cfgRef, platform, opts) {
753
823
  cfgRef.current = persistPromptedBuild(cwd, cfgRef.current, platform, answered);
754
824
  return answered;
755
825
  }
826
+ function persistPromptedProductionBuild(cwd, cfg, platform, production) {
827
+ const next = cfg ?? { defaultPlatform: platform, platforms: {} };
828
+ const existingBuild = next.platforms[platform]?.build;
829
+ if (!existingBuild?.command || !existingBuild?.artifact) {
830
+ throw new Error(
831
+ `internal: cannot persist a production build config for ${platform} before its debug command/artifact are resolved`
832
+ );
833
+ }
834
+ next.platforms[platform].build = { ...existingBuild, ...production };
835
+ saveDevConfig(cwd, next);
836
+ return next;
837
+ }
838
+ async function resolveProductionBuildConfig(cwd, cfgRef, platform, opts) {
839
+ const entry = cfgRef.current?.platforms?.[platform]?.build;
840
+ if (entry?.productionCommand && entry?.productionArtifact) {
841
+ return { command: entry.productionCommand, artifact: entry.productionArtifact };
842
+ }
843
+ if (opts.json || !process.stdin.isTTY) {
844
+ fail(
845
+ opts,
846
+ `no production build config for ${platform}: add platforms.${platform}.build.productionCommand/productionArtifact to vibeview.json`,
847
+ "config_required"
848
+ );
849
+ }
850
+ const answered = await promptProductionBuildConfig(cwd, platform);
851
+ if (!answered) {
852
+ fail(opts, "a production build config is required for --production", "config_required");
853
+ }
854
+ cfgRef.current = persistPromptedProductionBuild(cwd, cfgRef.current, platform, answered);
855
+ return { command: answered.productionCommand, artifact: answered.productionArtifact };
856
+ }
756
857
  async function buildCommand(opts, cloudDeps) {
757
858
  const cwd = process.cwd();
758
859
  const cfgRef = { current: loadDevConfig(cwd) };
@@ -761,6 +862,13 @@ async function buildCommand(opts, cloudDeps) {
761
862
  await runCloudBuildCommand(cwd, cfgRef, opts, cloudDeps);
762
863
  return;
763
864
  }
865
+ if (opts.production) {
866
+ fail(
867
+ opts,
868
+ "--production requires --cloud: signed release builds run in the cloud (vibeview build --cloud --production)",
869
+ "usage"
870
+ );
871
+ }
764
872
  const platform = await resolveBarePlatform(cwd, cfgRef.current, opts);
765
873
  const build = await resolveBuildConfig(cwd, cfgRef, platform, opts);
766
874
  const cfg = cfgRef.current;
@@ -769,9 +877,9 @@ async function buildCommand(opts, cloudDeps) {
769
877
  platform,
770
878
  build,
771
879
  opts,
772
- (l) => console.error(chalk.dim(l))
880
+ (l) => console.error(chalk2.dim(l))
773
881
  );
774
- for (const w of result.warnings ?? []) console.error(chalk.yellow(`\u26A0 ${w}`));
882
+ for (const w of result.warnings ?? []) console.error(chalk2.yellow(`\u26A0 ${w}`));
775
883
  persistUploadedAppId(cwd, cfg, platform, build, result.public_id);
776
884
  if (opts.json) {
777
885
  console.log(
@@ -779,8 +887,8 @@ async function buildCommand(opts, cloudDeps) {
779
887
  );
780
888
  } else {
781
889
  console.error(
782
- chalk.green(`\u2713 built and uploaded ${result.name}`) + `
783
- ${chalk.cyan(result.public_id)} ${chalk.dim(`[${result.platform}]`)}`
890
+ chalk2.green(`\u2713 built and uploaded ${result.name}`) + `
891
+ ${chalk2.cyan(result.public_id)} ${chalk2.dim(`[${result.platform}]`)}`
784
892
  );
785
893
  }
786
894
  } catch (err) {
@@ -792,7 +900,7 @@ async function buildCommand(opts, cloudDeps) {
792
900
  }
793
901
  function printFailure(opts, message, code) {
794
902
  if (opts.json) console.log(JSON.stringify({ event: "error", code, message }));
795
- console.error(chalk.red(`error: ${message}`));
903
+ console.error(chalk2.red(`error: ${message}`));
796
904
  }
797
905
  function fail(opts, message, code) {
798
906
  printFailure(opts, message, code);
@@ -805,7 +913,32 @@ async function resolveCloudPlatforms(cwd, cfgRef, opts) {
805
913
  if (opts.platform === "all") {
806
914
  const configured = Object.entries(cfgRef.current?.platforms ?? {});
807
915
  const withBuild = configured.filter(([p, entry]) => isCloudPlatform(p) && entry?.build);
808
- if (withBuild.length > 0) return withBuild.map(([p]) => p);
916
+ if (withBuild.length > 0) {
917
+ let chosenPlatforms = withBuild.map(([p]) => p);
918
+ if (opts.production) {
919
+ const unsupported = chosenPlatforms.filter(
920
+ (p) => !PRODUCTION_SIGNING_PLATFORMS.includes(p)
921
+ );
922
+ if (unsupported.length > 0) {
923
+ for (const p of unsupported) {
924
+ const reason = `--production doesn't support ${p} \u2014 production signing supports ${PRODUCTION_SIGNING_PLATFORMS.join(" and ")}`;
925
+ emitCloud(opts.json, { event: "skipped", platform: p, reason });
926
+ if (!opts.json) console.error(chalk2.yellow(`\u26A0 skipping ${p}: ${reason}`));
927
+ }
928
+ chosenPlatforms = chosenPlatforms.filter((p) => !unsupported.includes(p));
929
+ }
930
+ if (chosenPlatforms.length === 0) {
931
+ const exclusions = describeAllExclusions(configured);
932
+ const prefix = exclusions ? `${exclusions}; ` : "";
933
+ fail(
934
+ opts,
935
+ `--platform all --production: ${prefix}none of the configured platforms support production signing (${PRODUCTION_SIGNING_PLATFORMS.join(" and ")} only)`,
936
+ "config_required"
937
+ );
938
+ }
939
+ }
940
+ return chosenPlatforms;
941
+ }
809
942
  if (opts.json || !process.stdin.isTTY) {
810
943
  fail(
811
944
  opts,
@@ -818,18 +951,20 @@ async function resolveCloudPlatforms(cwd, cfgRef, opts) {
818
951
  platform: void 0
819
952
  });
820
953
  requireCloudCapable(opts, chosen);
954
+ requireProductionCapable(opts, chosen);
821
955
  await resolveBuildConfig(cwd, cfgRef, chosen, opts);
822
956
  return [chosen];
823
957
  }
824
958
  const platform = opts.platform ? validateExplicitPlatform(opts.platform) : await resolveBarePlatform(cwd, cfgRef.current, opts);
825
959
  requireCloudCapable(opts, platform);
960
+ requireProductionCapable(opts, platform);
826
961
  await resolveBuildConfig(cwd, cfgRef, platform, opts);
827
962
  return [platform];
828
963
  }
829
964
  function validateExplicitPlatform(raw) {
830
965
  if (!isDevPlatform(raw)) {
831
966
  console.error(
832
- chalk.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}, or "all"`)
967
+ chalk2.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}, or "all"`)
833
968
  );
834
969
  process.exit(2);
835
970
  }
@@ -843,6 +978,14 @@ function requireCloudCapable(opts, platform) {
843
978
  );
844
979
  }
845
980
  }
981
+ function requireProductionCapable(opts, platform) {
982
+ if (opts.production && !PRODUCTION_SIGNING_PLATFORMS.includes(platform)) {
983
+ fail(
984
+ opts,
985
+ `--production doesn't support ${platform} \u2014 production signing supports ${PRODUCTION_SIGNING_PLATFORMS.join(" and ")}`
986
+ );
987
+ }
988
+ }
846
989
  function persistPickedAppId(cwd, cfg, platform, appId) {
847
990
  const next = cfg ?? { defaultPlatform: platform, platforms: {} };
848
991
  const entry = next.platforms[platform];
@@ -878,7 +1021,7 @@ async function resolveCloudAppIds(cwd, cfgRef, platforms, opts, listApps) {
878
1021
  createFromArtifact.add(platform);
879
1022
  if (!opts.json) {
880
1023
  console.error(
881
- chalk.dim(`no ${platform} apps yet \u2014 this build will create one from the artifact`)
1024
+ chalk2.dim(`no ${platform} apps yet \u2014 this build will create one from the artifact`)
882
1025
  );
883
1026
  }
884
1027
  continue;
@@ -976,6 +1119,12 @@ async function runCloudBuildCommand(cwd, cfgRef, opts, deps) {
976
1119
  const client = new ApiClient(baseUrl, token);
977
1120
  const d = deps ?? defaultCloudBuildDeps(client);
978
1121
  const createFromArtifact = await resolveCloudAppIds(cwd, cfgRef, platforms, opts, d.listApps);
1122
+ const productionBuilds = /* @__PURE__ */ new Map();
1123
+ if (opts.production) {
1124
+ for (const p of platforms) {
1125
+ productionBuilds.set(p, await resolveProductionBuildConfig(cwd, cfgRef, p, opts));
1126
+ }
1127
+ }
979
1128
  const cfg = cfgRef.current;
980
1129
  for (const p of platforms) {
981
1130
  try {
@@ -1021,6 +1170,9 @@ ${offenders}`);
1021
1170
  const manifestEntries = platforms.map((p) => {
1022
1171
  const entry = cfg.platforms[p];
1023
1172
  const build = entry.build;
1173
+ const production = productionBuilds.get(p);
1174
+ const command = production ? production.command : build.command;
1175
+ const artifactPath = production ? production.artifact : build.artifact;
1024
1176
  return {
1025
1177
  platform: p,
1026
1178
  // OMITTED, never invented, for a platform whose app the artifact will
@@ -1029,8 +1181,9 @@ ${offenders}`);
1029
1181
  // it either persisted a picked appId onto the entry, marked the
1030
1182
  // platform create-from-artifact, or failed the whole command.
1031
1183
  ...createFromArtifact.has(p) ? {} : { app_public_id: entry.appId },
1032
- command: build.command,
1033
- artifact_path: build.artifact,
1184
+ command,
1185
+ artifact_path: artifactPath,
1186
+ distribution: production ? "production" : "simulator",
1034
1187
  ...build.env ? { env: build.env } : {}
1035
1188
  };
1036
1189
  });
@@ -1051,7 +1204,7 @@ ${offenders}`);
1051
1204
  }
1052
1205
  if (!opts.json) {
1053
1206
  for (const b of created) {
1054
- console.error(` ${chalk.cyan(b.id)} ${chalk.dim(`[${b.platform}]`)}`);
1207
+ console.error(` ${chalk2.cyan(b.id)} ${chalk2.dim(`[${b.platform}]`)}`);
1055
1208
  }
1056
1209
  }
1057
1210
  const shouldWait = opts.wait !== false || opts.download;
@@ -1074,7 +1227,7 @@ ${offenders}`);
1074
1227
  path: result.path
1075
1228
  });
1076
1229
  if (!opts.json) {
1077
- console.error(chalk.green(`\u2713 saved ${result.filename}`));
1230
+ console.error(chalk2.green(`\u2713 saved ${result.filename}`));
1078
1231
  }
1079
1232
  } catch (err) {
1080
1233
  downloadFailed = true;
@@ -1083,7 +1236,7 @@ ${offenders}`);
1083
1236
  event: "error",
1084
1237
  message: `error downloading ${b.id}: ${message}`
1085
1238
  });
1086
- if (!opts.json) console.error(chalk.red(`error downloading ${b.id}: ${message}`));
1239
+ if (!opts.json) console.error(chalk2.red(`error downloading ${b.id}: ${message}`));
1087
1240
  }
1088
1241
  }
1089
1242
  }
@@ -1140,7 +1293,7 @@ async function waitForCloudBuilds(builds, opts, deps) {
1140
1293
  const giveUpLocally = (id, message) => {
1141
1294
  abandoned.add(id);
1142
1295
  emitCloud(opts.json, { event: "error", message });
1143
- if (!opts.json) console.error(chalk.red(message));
1296
+ if (!opts.json) console.error(chalk2.red(message));
1144
1297
  };
1145
1298
  const pollAndProcess = async (build) => {
1146
1299
  const offset = offsets.get(build.id) ?? 0;
@@ -1301,21 +1454,21 @@ function printTransition(id, platform, status, state, json, printLine) {
1301
1454
  if (json) {
1302
1455
  emitCloud(json, { event: "status", id, status: "queued" });
1303
1456
  } else {
1304
- printLine(id, platform, chalk.dim("\u23F3 queued \u2014 waiting for a build slot"));
1457
+ printLine(id, platform, chalk2.dim("\u23F3 queued \u2014 waiting for a build slot"));
1305
1458
  }
1306
1459
  } else if (status === "running" && !state.printedRunning) {
1307
1460
  state.printedRunning = true;
1308
1461
  if (json) {
1309
1462
  emitCloud(json, { event: "status", id, status: "running" });
1310
1463
  } else {
1311
- printLine(id, platform, `${chalk.cyan("\u25B6")} building`);
1464
+ printLine(id, platform, `${chalk2.cyan("\u25B6")} building`);
1312
1465
  }
1313
1466
  }
1314
1467
  }
1315
1468
  function printOutcomeLine(build, multi) {
1316
1469
  const prefix = multi ? `[${build.platform}] ` : "";
1317
1470
  const ok = build.status === "succeeded";
1318
- const mark = ok ? chalk.green("\u2713") : chalk.red("\u2717");
1471
+ const mark = ok ? chalk2.green("\u2713") : chalk2.red("\u2717");
1319
1472
  const duration = formatDuration(build.started_at, build.finished_at);
1320
1473
  let line = `${prefix}${mark} ${build.status}`;
1321
1474
  if (duration) line += ` (${duration})`;
@@ -1330,7 +1483,7 @@ import { createWriteStream, mkdirSync as mkdirSync3 } from "fs";
1330
1483
  import { dirname as dirname5 } from "path";
1331
1484
  import { createInterface as createInterface3 } from "readline";
1332
1485
  import { select as select3 } from "@inquirer/prompts";
1333
- import chalk2 from "chalk";
1486
+ import chalk3 from "chalk";
1334
1487
  import openBrowser from "open";
1335
1488
 
1336
1489
  // src/lib/tunnel-client.ts
@@ -1964,7 +2117,7 @@ function requireNonInteractive(json) {
1964
2117
  async function ensureConfig(api, opts) {
1965
2118
  const existing = loadDevConfig(process.cwd());
1966
2119
  if (opts.platform && !isDevPlatform(opts.platform)) {
1967
- console.error(chalk2.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
2120
+ console.error(chalk3.red(`error: --platform must be one of ${DEV_PLATFORMS.join(", ")}`));
1968
2121
  process.exit(2);
1969
2122
  }
1970
2123
  if (!opts.platform && !existing?.defaultPlatform) {
@@ -1977,12 +2130,12 @@ async function ensureConfig(api, opts) {
1977
2130
  const isTv = PLATFORM_DEVICE[platform].tv;
1978
2131
  if (isTv && opts.deviceCategory) {
1979
2132
  console.error(
1980
- chalk2.red(`error: --device-category does not apply to ${platform} (always a tv device)`)
2133
+ chalk3.red(`error: --device-category does not apply to ${platform} (always a tv device)`)
1981
2134
  );
1982
2135
  process.exit(2);
1983
2136
  }
1984
2137
  if (!isTv && opts.deviceCategory === "tv") {
1985
- console.error(chalk2.red(`error: use --platform tvos or --platform androidtv for TV devices`));
2138
+ console.error(chalk3.red(`error: use --platform tvos or --platform androidtv for TV devices`));
1986
2139
  process.exit(2);
1987
2140
  }
1988
2141
  let firstRunBuild = null;
@@ -2005,7 +2158,7 @@ async function ensureConfig(api, opts) {
2005
2158
  allApps = await api.listApps();
2006
2159
  } catch (err) {
2007
2160
  const message = `could not fetch your app list \u2014 ${err instanceof Error ? err.message : String(err)}`;
2008
- console.error(chalk2.red(`error: ${message}`));
2161
+ console.error(chalk3.red(`error: ${message}`));
2009
2162
  emit(opts.json, { event: "error", message });
2010
2163
  process.exit(1);
2011
2164
  }
@@ -2014,7 +2167,7 @@ async function ensureConfig(api, opts) {
2014
2167
  if (choice.staleFlag) {
2015
2168
  const message = `app "${choice.staleFlag}" not found \u2014 it may have been deleted.`;
2016
2169
  console.error(
2017
- chalk2.red(`error: ${message}`) + `
2170
+ chalk3.red(`error: ${message}`) + `
2018
2171
  Run \`vibeview dev\` without --app to pick from the list.`
2019
2172
  );
2020
2173
  emit(opts.json, { event: "error", message });
@@ -2024,7 +2177,7 @@ Run \`vibeview dev\` without --app to pick from the list.`
2024
2177
  let builtThisRun = false;
2025
2178
  if (choice.staleCached) {
2026
2179
  console.error(
2027
- chalk2.yellow(`\u26A0 app "${choice.staleCached}" no longer exists \u2014 pick your debug build again`)
2180
+ chalk3.yellow(`\u26A0 app "${choice.staleCached}" no longer exists \u2014 pick your debug build again`)
2028
2181
  );
2029
2182
  }
2030
2183
  if (isFirstRun && !appId) {
@@ -2040,20 +2193,20 @@ Run \`vibeview dev\` without --app to pick from the list.`
2040
2193
  });
2041
2194
  }
2042
2195
  if (action === "build") {
2043
- console.error(chalk2.dim(`Building ${platform}...`));
2196
+ console.error(chalk3.dim(`Building ${platform}...`));
2044
2197
  try {
2045
2198
  const result = await runBuildForPlatform(
2046
2199
  process.cwd(),
2047
2200
  platform,
2048
2201
  firstRunBuild,
2049
2202
  opts,
2050
- (l) => console.error(chalk2.dim(l))
2203
+ (l) => console.error(chalk3.dim(l))
2051
2204
  );
2052
2205
  appId = result.public_id;
2053
2206
  builtThisRun = true;
2054
2207
  } catch (err) {
2055
2208
  const message = err.message;
2056
- console.error(chalk2.red(`error: ${message}`));
2209
+ console.error(chalk3.red(`error: ${message}`));
2057
2210
  process.exit(1);
2058
2211
  }
2059
2212
  }
@@ -2061,20 +2214,20 @@ Run \`vibeview dev\` without --app to pick from the list.`
2061
2214
  if (!appId) {
2062
2215
  if (apps.length === 0) {
2063
2216
  const message = noAppsMessage(platform, entry?.build !== void 0);
2064
- console.error(chalk2.red(message));
2217
+ console.error(chalk3.red(message));
2065
2218
  emit(opts.json, { event: "error", code: "no_apps", message });
2066
2219
  process.exit(1);
2067
2220
  }
2068
2221
  if (choice.staleCached) {
2069
2222
  const message = `app "${choice.staleCached}" for ${platform} no longer exists \u2014 pass --app <id> (see \`vibeview list-apps\`) or run interactively to pick one.`;
2070
- console.error(chalk2.red(`error: ${message}`));
2223
+ console.error(chalk3.red(`error: ${message}`));
2071
2224
  emit(opts.json, { event: "error", code: "app_deleted", message });
2072
2225
  process.exit(1);
2073
2226
  }
2074
2227
  requireNonInteractive(opts.json);
2075
2228
  if (!process.stdin.isTTY) {
2076
2229
  console.error(
2077
- chalk2.red(
2230
+ chalk3.red(
2078
2231
  `error: no valid app configured for ${platform} \u2014 run interactively to pick one, or pass --app <id>`
2079
2232
  )
2080
2233
  );
@@ -2110,7 +2263,7 @@ Run \`vibeview dev\` without --app to pick from the list.`
2110
2263
  { build: !firstRunBuild, metro: PLATFORM_NEEDS_METRO[platform] && !firstRunMetro },
2111
2264
  platform
2112
2265
  );
2113
- if (hint) console.error(chalk2.dim(hint));
2266
+ if (hint) console.error(chalk3.dim(hint));
2114
2267
  }
2115
2268
  const finalMetro = isFirstRun ? resolveMetro(cfg, platform, opts.metroPort ? parseInt(opts.metroPort, 10) : void 0) : metroResolved;
2116
2269
  return {
@@ -2129,7 +2282,7 @@ async function runDevInProcess(opts) {
2129
2282
  watchSeconds = parseWatchSeconds(opts.watch);
2130
2283
  } catch (err) {
2131
2284
  const message = err.message;
2132
- console.error(chalk2.red(`error: ${message}`));
2285
+ console.error(chalk3.red(`error: ${message}`));
2133
2286
  emit(opts.json, { event: "error", code: "invalid_flag", message });
2134
2287
  process.exit(2);
2135
2288
  }
@@ -2145,7 +2298,7 @@ async function runDevInProcess(opts) {
2145
2298
  }
2146
2299
  }
2147
2300
  const { token, baseUrl } = resolveAuth(opts);
2148
- console.error(chalk2.dim(`Using ${baseUrl}`));
2301
+ console.error(chalk3.dim(`Using ${baseUrl}`));
2149
2302
  const api = new ApiClient(baseUrl, token);
2150
2303
  const cfg = await ensureConfig(api, opts);
2151
2304
  if (opts.build && !cfg.builtThisRun) {
@@ -2153,18 +2306,18 @@ async function runDevInProcess(opts) {
2153
2306
  const build = reloaded?.platforms?.[cfg.platform]?.build;
2154
2307
  if (!build) {
2155
2308
  const message = `no build config for ${cfg.platform} \u2014 run vibeview build once to set it up`;
2156
- console.error(chalk2.red(`error: ${message}`));
2309
+ console.error(chalk3.red(`error: ${message}`));
2157
2310
  emit(opts.json, { event: "error", code: "config_required", message });
2158
2311
  process.exit(1);
2159
2312
  }
2160
- console.error(chalk2.dim(`Building ${cfg.platform}...`));
2313
+ console.error(chalk3.dim(`Building ${cfg.platform}...`));
2161
2314
  try {
2162
2315
  const result = await runBuildForPlatform(
2163
2316
  process.cwd(),
2164
2317
  cfg.platform,
2165
2318
  build,
2166
2319
  { token, baseUrl },
2167
- (l) => console.error(chalk2.dim(l))
2320
+ (l) => console.error(chalk3.dim(l))
2168
2321
  );
2169
2322
  cfg.appId = result.public_id;
2170
2323
  if (reloaded && reloaded.platforms[cfg.platform] && reloaded.platforms[cfg.platform].appId !== result.public_id) {
@@ -2173,7 +2326,7 @@ async function runDevInProcess(opts) {
2173
2326
  }
2174
2327
  } catch (err) {
2175
2328
  const message = err.message;
2176
- console.error(chalk2.red(`error: ${message}`));
2329
+ console.error(chalk3.red(`error: ${message}`));
2177
2330
  emit(opts.json, { event: "error", message });
2178
2331
  process.exit(1);
2179
2332
  }
@@ -2195,7 +2348,7 @@ async function runDevInProcess(opts) {
2195
2348
  metroLogStream.write(line.replace(/^\[metro\] /, "") + "\n");
2196
2349
  } catch {
2197
2350
  }
2198
- if (shouldEchoMetroLine(line, opts.debug === true)) console.error(chalk2.dim(line));
2351
+ if (shouldEchoMetroLine(line, opts.debug === true)) console.error(chalk3.dim(line));
2199
2352
  };
2200
2353
  metroResult = await ensureMetro(
2201
2354
  process.cwd(),
@@ -2208,15 +2361,15 @@ async function runDevInProcess(opts) {
2208
2361
  );
2209
2362
  } catch (err) {
2210
2363
  const message = err.message;
2211
- console.error(chalk2.red(`error: ${message}`));
2364
+ console.error(chalk3.red(`error: ${message}`));
2212
2365
  emit(opts.json, { event: "error", code: "metro_down", message });
2213
2366
  process.exit(1);
2214
2367
  }
2215
- for (const w of metroResult.warnings) console.error(chalk2.yellow(`\u26A0 ${w}`));
2368
+ for (const w of metroResult.warnings) console.error(chalk3.yellow(`\u26A0 ${w}`));
2216
2369
  if (metroResult.status === "spawned" || metroResult.status === "respawned") {
2217
- console.error(chalk2.green(`\u2713 started Metro (${cfg.metroCommand})`));
2370
+ console.error(chalk3.green(`\u2713 started Metro (${cfg.metroCommand})`));
2218
2371
  console.error(
2219
- chalk2.dim(` full Metro output: ${metroLogPath(process.cwd())} (--debug echoes it here)`)
2372
+ chalk3.dim(` full Metro output: ${metroLogPath(process.cwd())} (--debug echoes it here)`)
2220
2373
  );
2221
2374
  }
2222
2375
  metroOwnedThisRun = metroResult.status === "spawned" || metroResult.status === "respawned";
@@ -2226,19 +2379,19 @@ async function runDevInProcess(opts) {
2226
2379
  watchIgnore = rokuEntry?.watchIgnore ?? [];
2227
2380
  if (!rokuBuild) {
2228
2381
  const message = `no build config for ${cfg.platform} \u2014 run \`vibeview build --platform ${cfg.platform}\` once to set it up`;
2229
- console.error(chalk2.red(`error: ${message}`));
2382
+ console.error(chalk3.red(`error: ${message}`));
2230
2383
  emit(opts.json, { event: "error", code: "config_required", message });
2231
2384
  process.exit(1);
2232
2385
  }
2233
2386
  }
2234
- console.error(chalk2.dim(`Starting a ${cfg.platform} dev session for ${cfg.appId}...`));
2387
+ console.error(chalk3.dim(`Starting a ${cfg.platform} dev session for ${cfg.appId}...`));
2235
2388
  let stopping = false;
2236
2389
  let handle = null;
2237
2390
  let reloadLoop = null;
2238
2391
  const stopSession = async (code) => {
2239
2392
  if (stopping) return;
2240
2393
  stopping = true;
2241
- console.error(chalk2.dim("\nStopping session..."));
2394
+ console.error(chalk3.dim("\nStopping session..."));
2242
2395
  reloadLoop?.stop();
2243
2396
  await handle?.stop();
2244
2397
  if (metroOwnedThisRun) killOwnedMetro(process.cwd());
@@ -2271,15 +2424,15 @@ async function runDevInProcess(opts) {
2271
2424
  if (evt.event === "warning") {
2272
2425
  if (nextWarningIsMetroUnreachable) {
2273
2426
  nextWarningIsMetroUnreachable = false;
2274
- console.error(chalk2.red(`\u2717 ${evt.message}`));
2427
+ console.error(chalk3.red(`\u2717 ${evt.message}`));
2275
2428
  } else {
2276
- console.error(chalk2.yellow(`\u26A0 ${evt.message}`));
2429
+ console.error(chalk3.yellow(`\u26A0 ${evt.message}`));
2277
2430
  }
2278
2431
  } else if (evt.event === "tunnel_connected") {
2279
2432
  everConnected = true;
2280
- console.error(chalk2.green("\u2713 tunnel connected \u2014 edit away, Fast Refresh is live"));
2433
+ console.error(chalk3.green("\u2713 tunnel connected \u2014 edit away, Fast Refresh is live"));
2281
2434
  } else if (evt.event === "session_ended" && !stopping && handle) {
2282
- console.error(chalk2.red("tunnel closed by server \u2014 session ended"));
2435
+ console.error(chalk3.red("tunnel closed by server \u2014 session ended"));
2283
2436
  stopping = true;
2284
2437
  endedEmitted = true;
2285
2438
  emit(opts.json, evt);
@@ -2298,20 +2451,20 @@ async function runDevInProcess(opts) {
2298
2451
  if (!waitingPrinted) {
2299
2452
  waitingPrinted = true;
2300
2453
  console.error(
2301
- chalk2.dim("\u2026 waiting for the device to come up (tunnel not ready yet)")
2454
+ chalk3.dim("\u2026 waiting for the device to come up (tunnel not ready yet)")
2302
2455
  );
2303
2456
  }
2304
2457
  return;
2305
2458
  }
2306
- console.error(chalk2.yellow("\u2026 tunnel dropped, reconnecting"));
2459
+ console.error(chalk3.yellow("\u2026 tunnel dropped, reconnecting"));
2307
2460
  } else if (s === "metro-unreachable") {
2308
2461
  nextWarningIsMetroUnreachable = true;
2309
2462
  }
2310
2463
  }
2311
2464
  );
2312
- const keysLine = rokuBuild ? `Press ${chalk2.bold("r")} to reload the channel, ${chalk2.bold("q")} or Ctrl-C to end the session.` : "Ctrl-C to end the session.";
2465
+ const keysLine = rokuBuild ? `Press ${chalk3.bold("r")} to reload the channel, ${chalk3.bold("q")} or Ctrl-C to end the session.` : "Ctrl-C to end the session.";
2313
2466
  console.error(`
2314
- Watch and interact: ${chalk2.cyan(handle.pageUrl)}
2467
+ Watch and interact: ${chalk3.cyan(handle.pageUrl)}
2315
2468
  ${keysLine}
2316
2469
  `);
2317
2470
  writeDevState(process.cwd(), {
@@ -2343,13 +2496,13 @@ async function runDevInProcess(opts) {
2343
2496
  // Build output and loop notices are human output, so they go to
2344
2497
  // stderr like every other line this command prints — stdout stays
2345
2498
  // reserved for the `--json` event stream.
2346
- log: (line) => console.error(chalk2.dim(line))
2499
+ log: (line) => console.error(chalk3.dim(line))
2347
2500
  }),
2348
- log: (line) => console.error(chalk2.yellow(line)),
2501
+ log: (line) => console.error(chalk3.yellow(line)),
2349
2502
  // A failed reload is an error, not a notice — same red as every other
2350
2503
  // failure this command prints, so it doesn't read like the yellow
2351
2504
  // "already reloading" line.
2352
- logError: (line) => console.error(chalk2.red(`\u2717 ${line}`)),
2505
+ logError: (line) => console.error(chalk3.red(`\u2717 ${line}`)),
2353
2506
  ...watchSeconds !== void 0 ? {
2354
2507
  watchSeconds,
2355
2508
  watch: watchProjectFiles(process.cwd(), rokuBuild.artifact, watchIgnore)
@@ -2357,7 +2510,7 @@ async function runDevInProcess(opts) {
2357
2510
  });
2358
2511
  if (watchSeconds !== void 0) {
2359
2512
  console.error(
2360
- chalk2.dim(` Watching for changes \u2014 reloading after ${watchSeconds}s of quiet.`)
2513
+ chalk3.dim(` Watching for changes \u2014 reloading after ${watchSeconds}s of quiet.`)
2361
2514
  );
2362
2515
  }
2363
2516
  if (process.stdin.isTTY) {
@@ -2392,7 +2545,7 @@ async function runDevInProcess(opts) {
2392
2545
  }
2393
2546
  const verdict = sessionLivenessVerdict(info);
2394
2547
  if (verdict.end && !stopping) {
2395
- console.error(chalk2.red(verdict.message));
2548
+ console.error(chalk3.red(verdict.message));
2396
2549
  emit(opts.json, { event: "session_ended", session_id: sessionId, code: 1 });
2397
2550
  endedEmitted = true;
2398
2551
  await stopSession(1);
@@ -2401,7 +2554,7 @@ async function runDevInProcess(opts) {
2401
2554
  const warningVerdict = lateWarningVerdict(info, reportedWarnings);
2402
2555
  for (const w of warningVerdict.toReport) {
2403
2556
  reportedWarnings.add(w);
2404
- console.error(chalk2.yellow(`\u26A0 ${w}`));
2557
+ console.error(chalk3.yellow(`\u26A0 ${w}`));
2405
2558
  emit(opts.json, { event: "warning", message: w });
2406
2559
  }
2407
2560
  if (warningVerdict.blocking && !stopping) {
@@ -2419,7 +2572,7 @@ async function runDevInProcess(opts) {
2419
2572
  }
2420
2573
  } catch (err) {
2421
2574
  const message = err.message;
2422
- console.error(chalk2.red(`error: ${message}`));
2575
+ console.error(chalk3.red(`error: ${message}`));
2423
2576
  emit(opts.json, { event: "error", message });
2424
2577
  await stopSession(1);
2425
2578
  }
@@ -2449,12 +2602,12 @@ async function dev(opts) {
2449
2602
  if (opts.json) {
2450
2603
  console.log(JSON.stringify(parsed));
2451
2604
  } else {
2452
- console.error(chalk2.dim(`Using ${resolveAuth(opts).baseUrl}`));
2453
- console.error(chalk2.green(`\u2713 dev session started in the background (pid ${parsed.pid})`));
2605
+ console.error(chalk3.dim(`Using ${resolveAuth(opts).baseUrl}`));
2606
+ console.error(chalk3.green(`\u2713 dev session started in the background (pid ${parsed.pid})`));
2454
2607
  console.error(`
2455
- Watch and interact: ${chalk2.cyan(parsed.url)}`);
2456
- console.error(chalk2.dim(` vibeview dev-status \u2014 check on it`));
2457
- console.error(chalk2.dim(` vibeview dev-stop \u2014 end it
2608
+ Watch and interact: ${chalk3.cyan(parsed.url)}`);
2609
+ console.error(chalk3.dim(` vibeview dev-status \u2014 check on it`));
2610
+ console.error(chalk3.dim(` vibeview dev-stop \u2014 end it
2458
2611
  `));
2459
2612
  }
2460
2613
  child.unref();
@@ -2464,13 +2617,13 @@ async function dev(opts) {
2464
2617
  settled = true;
2465
2618
  rl.close();
2466
2619
  emit(opts.json, parsed);
2467
- if (!opts.json) console.error(chalk2.red(`error: ${parsed.message}`));
2620
+ if (!opts.json) console.error(chalk3.red(`error: ${parsed.message}`));
2468
2621
  reject(new Error(parsed.message));
2469
2622
  } else if (parsed.event === "warning") {
2470
2623
  if (opts.json) {
2471
2624
  console.log(JSON.stringify(parsed));
2472
2625
  } else {
2473
- console.error(chalk2.yellow(`\u26A0 ${parsed.message}`));
2626
+ console.error(chalk3.yellow(`\u26A0 ${parsed.message}`));
2474
2627
  }
2475
2628
  }
2476
2629
  });
@@ -2479,14 +2632,14 @@ async function dev(opts) {
2479
2632
  rl.close();
2480
2633
  const message = `dev session exited before starting (code ${code ?? "unknown"})`;
2481
2634
  emit(opts.json, { event: "error", message });
2482
- if (!opts.json) console.error(chalk2.red(`error: ${message}`));
2635
+ if (!opts.json) console.error(chalk3.red(`error: ${message}`));
2483
2636
  reject(new Error(message));
2484
2637
  });
2485
2638
  child.on("error", (err) => {
2486
2639
  if (settled) return;
2487
2640
  rl.close();
2488
2641
  emit(opts.json, { event: "error", message: err.message });
2489
- if (!opts.json) console.error(chalk2.red(`error: ${err.message}`));
2642
+ if (!opts.json) console.error(chalk3.red(`error: ${err.message}`));
2490
2643
  reject(err);
2491
2644
  });
2492
2645
  }).catch(() => {
@@ -2902,18 +3055,18 @@ var AGENT_COMMANDS = [
2902
3055
  ];
2903
3056
 
2904
3057
  // src/agent/render.ts
2905
- import chalk3 from "chalk";
3058
+ import chalk4 from "chalk";
2906
3059
  function renderEnvelope(env) {
2907
3060
  const lines = [];
2908
3061
  if (env.ok) {
2909
- lines.push(chalk3.green(`ok`) + chalk3.dim(` (${env.tool})`));
3062
+ lines.push(chalk4.green(`ok`) + chalk4.dim(` (${env.tool})`));
2910
3063
  } else {
2911
- lines.push(chalk3.red(`error`) + chalk3.dim(` (${env.tool})`));
3064
+ lines.push(chalk4.red(`error`) + chalk4.dim(` (${env.tool})`));
2912
3065
  }
2913
3066
  lines.push(...resultLines(env.result));
2914
3067
  if (env.observation) {
2915
3068
  if (env.observation.kind === "unavailable") {
2916
- lines.push(chalk3.yellow(`warning: ${env.observation.text}`));
3069
+ lines.push(chalk4.yellow(`warning: ${env.observation.text}`));
2917
3070
  } else {
2918
3071
  lines.push(env.observation.text);
2919
3072
  }
@@ -2926,17 +3079,17 @@ function resultLines(result) {
2926
3079
  const lines = [];
2927
3080
  if (Array.isArray(r.entries) && typeof r.cursor === "number") {
2928
3081
  if (r.entries.length === 0) {
2929
- lines.push(chalk3.dim("(no log lines)"));
3082
+ lines.push(chalk4.dim("(no log lines)"));
2930
3083
  }
2931
3084
  for (const e of r.entries) {
2932
3085
  if (!e || typeof e !== "object") continue;
2933
3086
  const entry = e;
2934
3087
  const ts = typeof entry.timestamp === "number" ? new Date(entry.timestamp).toISOString().slice(11, 23) : "??:??:??.???";
2935
3088
  const level = typeof entry.level === "string" ? entry.level : "info";
2936
- const levelTag = level === "error" ? chalk3.red(level) : level === "warn" ? chalk3.yellow(level) : chalk3.dim(level);
2937
- lines.push(`${chalk3.dim(ts)} ${levelTag} ${String(entry.message ?? "")}`);
3089
+ const levelTag = level === "error" ? chalk4.red(level) : level === "warn" ? chalk4.yellow(level) : chalk4.dim(level);
3090
+ lines.push(`${chalk4.dim(ts)} ${levelTag} ${String(entry.message ?? "")}`);
2938
3091
  }
2939
- lines.push(chalk3.dim(`cursor: ${r.cursor}`));
3092
+ lines.push(chalk4.dim(`cursor: ${r.cursor}`));
2940
3093
  }
2941
3094
  if (r.found === true && typeof r.ref === "string" && r.ref) {
2942
3095
  let found = `found: @${r.ref}`;
@@ -2948,10 +3101,10 @@ function resultLines(result) {
2948
3101
  const text = typeof a.text === "string" && a.text ? ` ${JSON.stringify(a.text)}` : "";
2949
3102
  return `${ref}${text}`;
2950
3103
  });
2951
- if (alts.length > 0) lines.push(chalk3.dim(`alternatives: ${alts.join(", ")}`));
3104
+ if (alts.length > 0) lines.push(chalk4.dim(`alternatives: ${alts.join(", ")}`));
2952
3105
  }
2953
3106
  }
2954
- if (typeof r.note === "string" && r.note) lines.push(chalk3.dim(r.note));
3107
+ if (typeof r.note === "string" && r.note) lines.push(chalk4.dim(r.note));
2955
3108
  if (typeof r.message === "string" && r.message) lines.push(r.message);
2956
3109
  if (typeof r.warning === "string" && r.warning) lines.push(r.warning);
2957
3110
  return lines;