vibeview 0.28.0 → 0.28.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.
@@ -13,7 +13,7 @@ import {
13
13
  resolveArtifact,
14
14
  resolveAuth,
15
15
  uploadAppBuild
16
- } from "./chunk-2JLTC67A.js";
16
+ } from "./chunk-PBMB6TG4.js";
17
17
 
18
18
  // src/lib/dev-config.ts
19
19
  import { readFileSync, writeFileSync } from "fs";
@@ -344,18 +344,31 @@ function isPidAlive(pid) {
344
344
  return err.code === "EPERM";
345
345
  }
346
346
  }
347
+ var WHOLE_DIR_LINE = /^(\/?)\.vibeview\/?$/;
347
348
  function ensureGitignored(cwd) {
348
349
  try {
349
350
  const gitignore = join2(cwd, ".gitignore");
350
351
  if (!existsSync(gitignore)) return;
351
352
  const content = readFileSync2(gitignore, "utf-8");
352
- const covered = content.split("\n").map((l) => l.trim()).some((l) => l === ".vibeview" || l === ".vibeview/" || l === "/.vibeview");
353
- if (covered) return;
353
+ const lines = content.split("\n");
354
+ const trimmed = lines.map((l) => l.trim());
355
+ if (trimmed.some((l) => /^\/?\.vibeview\/\*$/.test(l))) return;
356
+ const i = trimmed.findIndex((l) => WHOLE_DIR_LINE.test(l));
357
+ if (i !== -1) {
358
+ const anchor = WHOLE_DIR_LINE.exec(trimmed[i])[1];
359
+ lines.splice(i, 1, `${anchor}.vibeview/*`, `!${anchor}.vibeview/test-spec.json`);
360
+ writeFileSync2(gitignore, lines.join("\n"));
361
+ return;
362
+ }
354
363
  const prefix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
355
- writeFileSync2(gitignore, `${content}${prefix}
356
- # VibeView local session state
357
- .vibeview/
358
- `);
364
+ writeFileSync2(
365
+ gitignore,
366
+ `${content}${prefix}
367
+ # VibeView local session state (test-spec.json is committed for CI)
368
+ .vibeview/*
369
+ !.vibeview/test-spec.json
370
+ `
371
+ );
359
372
  } catch {
360
373
  }
361
374
  }
@@ -191,9 +191,10 @@ var ApiClient = class {
191
191
  model: options?.model,
192
192
  provider: options?.provider,
193
193
  mode: options?.mode,
194
- // When pinning a specific device, omit device_category — the backend
195
- // rejects the combo.
196
- device_category: options?.device ? void 0 : options?.deviceCategory ?? "phone",
194
+ // Omitted unless asked for: the backend picks tv for a TV suite and
195
+ // phone otherwise. Never sent with a pinned device (the backend
196
+ // rejects the combo).
197
+ device_category: options?.device ? void 0 : options?.deviceCategory,
197
198
  device_id: options?.device,
198
199
  build_id: options?.build,
199
200
  metadata: options?.metadata
@@ -206,7 +207,7 @@ var ApiClient = class {
206
207
  model: options?.model,
207
208
  provider: options?.provider,
208
209
  mode: options?.mode,
209
- device_category: options?.device ? void 0 : options?.deviceCategory ?? "phone",
210
+ device_category: options?.device ? void 0 : options?.deviceCategory,
210
211
  device_id: options?.device,
211
212
  build_id: options?.build,
212
213
  metadata: options?.metadata
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  readDevState,
23
23
  readMetroState,
24
24
  runAgentVerb
25
- } from "./chunk-OKOAWGWV.js";
25
+ } from "./chunk-3DKY443B.js";
26
26
  import {
27
27
  ApiClient,
28
28
  ApiStatusError,
@@ -38,11 +38,12 @@ import {
38
38
  formatUtcTimestamp,
39
39
  loadConfig,
40
40
  printJsonError,
41
+ queueReasonCopy,
41
42
  reportCommandError,
42
43
  resolveAuth,
43
44
  saveConfig,
44
45
  uploadApp
45
- } from "./chunk-2JLTC67A.js";
46
+ } from "./chunk-PBMB6TG4.js";
46
47
 
47
48
  // src/cli.ts
48
49
  import { createRequire } from "module";
@@ -338,6 +339,7 @@ async function pollUntilComplete(client, runId, timeoutMs, spinner, onQueueObser
338
339
  let currentStepLabel = "";
339
340
  const printedSteps = /* @__PURE__ */ new Set();
340
341
  let cachedDeviceLabel = null;
342
+ let lastQueueReason = null;
341
343
  const caseStateBefore = /* @__PURE__ */ new Map();
342
344
  const caseStartedPrinted = /* @__PURE__ */ new Set();
343
345
  while (Date.now() < deadline) {
@@ -415,6 +417,11 @@ async function pollUntilComplete(client, runId, timeoutMs, spinner, onQueueObser
415
417
  label = "the device pool";
416
418
  }
417
419
  spinner.text = `Queued \u2014 position ${q.position} in line for ${label}`;
420
+ const why = queueReasonCopy(q.reason);
421
+ if (why && why !== lastQueueReason) {
422
+ printBelowSpinner(spinner, `${chalk2.yellow("\u23F3")} Waiting for a device: ${why}`);
423
+ }
424
+ lastQueueReason = why;
418
425
  }
419
426
  if (progress.length === 0) {
420
427
  if (result.status === "pending") {
@@ -434,7 +441,8 @@ async function pollUntilComplete(client, runId, timeoutMs, spinner, onQueueObser
434
441
  }
435
442
  }
436
443
  if (keepAlive && Date.now() - lastLogTime >= 3e4) {
437
- const where = result.status === "queued" && result.queue ? ` (position ${result.queue.position} in line for a device)` : "";
444
+ const why = result.status === "queued" ? queueReasonCopy(result.queue?.reason) : null;
445
+ const where = result.status === "queued" && result.queue ? ` (position ${result.queue.position} in line for a device${why ? `: ${why}` : ""})` : "";
438
446
  process.stderr.write(`Status: ${result.status}${where}...
439
447
  `);
440
448
  lastLogTime = Date.now();
@@ -742,7 +750,8 @@ ${signal} received.
742
750
  model: opts.model,
743
751
  provider: opts.provider,
744
752
  mode: opts.mode,
745
- device_category: opts.device ? void 0 : opts.deviceCategory ?? "phone",
753
+ // Omitted unless asked for: the backend picks tv for each TV suite.
754
+ device_category: opts.device ? void 0 : opts.deviceCategory,
746
755
  device_id: opts.device,
747
756
  build_id: opts.build,
748
757
  metadata: opts.metadata
@@ -792,6 +801,7 @@ ${chalk4.dim("Matched:")} ${totalMatched} suite(s)${matchedNames.length ? " \u20
792
801
  const deadline = Date.now() + totalTimeout * 1e3;
793
802
  const suiteStateBefore = /* @__PURE__ */ new Map();
794
803
  const suiteStartedPrinted = /* @__PURE__ */ new Set();
804
+ let lastQueueReason = null;
795
805
  const print = (line) => {
796
806
  spinner.stop();
797
807
  process.stderr.write(line + "\n");
@@ -870,8 +880,16 @@ ${chalk4.dim("Matched:")} ${totalMatched} suite(s)${matchedNames.length ? " \u20
870
880
  if (queuedChild && queuedChild.queue) {
871
881
  const q = queuedChild.queue;
872
882
  const target = q.specific_device_id ?? "the device pool";
883
+ const why = queueReasonCopy(q.reason);
884
+ if (why && why !== lastQueueReason) {
885
+ print(
886
+ `${chalk4.yellow("\u23F3")} ${chalk4.bold(queuedChild.suite_name)} is waiting for a device: ${why}`
887
+ );
888
+ }
889
+ lastQueueReason = why;
873
890
  spinner.text = `Queued \u2014 ${chalk4.bold(queuedChild.suite_name)} position ${q.position} for ${target} (${doneCount}/${totalMatched} suite(s) complete)`;
874
891
  } else {
892
+ lastQueueReason = null;
875
893
  spinner.text = `Running suites \u2014 ${doneCount}/${totalMatched} complete...`;
876
894
  }
877
895
  if (TERMINAL.has(last.status)) break;
@@ -3511,7 +3529,7 @@ program.name("vibeview").description(
3511
3529
  ).version(pkg.version);
3512
3530
  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(
3513
3531
  "--device-category <category>",
3514
- "Device category: phone, tablet, tv (default: phone when --device is not set)",
3532
+ "Device category: phone, tablet, tv (default: tv for a TV platform, else phone)",
3515
3533
  parseDeviceCategory
3516
3534
  ).option(
3517
3535
  "--device <device_id>",
@@ -3539,7 +3557,7 @@ program.command("run-suites").description("Run all suites matching a tag filter"
3539
3557
  "Filter matched suites to one platform: ios, android, tvos, androidtv (default: no filter)"
3540
3558
  ).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(
3541
3559
  "--device-category <category>",
3542
- "Device category: phone, tablet, tv (default: phone when --device is not set)",
3560
+ "Device category: phone, tablet, tv (default: tv for a TV platform, else phone)",
3543
3561
  parseDeviceCategory
3544
3562
  ).option(
3545
3563
  "--device <device_id>",
@@ -3559,7 +3577,7 @@ program.command("run-suites").description("Run all suites matching a tag filter"
3559
3577
  });
3560
3578
  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(
3561
3579
  "--device-category <category>",
3562
- "Device category: phone, tablet, tv (default: phone when --device is not set)",
3580
+ "Device category: phone, tablet, tv (default: tv for a TV platform, else phone)",
3563
3581
  parseDeviceCategory
3564
3582
  ).option(
3565
3583
  "--device <device_id>",
@@ -3775,7 +3793,7 @@ program.command("dev-reload").description(
3775
3793
  program.command("mcp").description(
3776
3794
  "Run an MCP stdio server exposing the agent verbs (tap, swipe, type, ...) plus dev_start/dev_stop/dev_reload as tools"
3777
3795
  ).option("--token <token>", "API token (or set VIBEVIEW_API_TOKEN)").action(async (opts) => {
3778
- const { runMcpServer } = await import("./server-6SRFOQ6B.js");
3796
+ const { runMcpServer } = await import("./server-BGQJOVSN.js");
3779
3797
  await runMcpServer({ ...opts, version: pkg.version });
3780
3798
  });
3781
3799
  program.command("agent-setup").description(
@@ -21,12 +21,12 @@ import {
21
21
  readDevState,
22
22
  renderEnvelope,
23
23
  startDevSession
24
- } from "./chunk-OKOAWGWV.js";
24
+ } from "./chunk-3DKY443B.js";
25
25
  import {
26
26
  ApiClient,
27
27
  NotFoundError,
28
28
  resolveAuth
29
- } from "./chunk-2JLTC67A.js";
29
+ } from "./chunk-PBMB6TG4.js";
30
30
 
31
31
  // src/mcp/server.ts
32
32
  import { writeFileSync } from "fs";
@@ -539,7 +539,7 @@ async function handleUploadApp(args, deps) {
539
539
  }
540
540
  const name = typeof args.name === "string" && args.name ? args.name : void 0;
541
541
  const upload = deps.uploadApp ?? (async (f, n) => {
542
- const { uploadAppBuild } = await import("./upload-app-WROTRZCA.js");
542
+ const { uploadAppBuild } = await import("./upload-app-FEZG23NU.js");
543
543
  const { result: result2 } = await uploadAppBuild(f, { ...deps.auth, name: n });
544
544
  return result2;
545
545
  });
@@ -3,7 +3,7 @@ import {
3
3
  describeBuild,
4
4
  uploadApp,
5
5
  uploadAppBuild
6
- } from "./chunk-2JLTC67A.js";
6
+ } from "./chunk-PBMB6TG4.js";
7
7
  export {
8
8
  describeBuild,
9
9
  uploadApp,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeview",
3
- "version": "0.28.0",
3
+ "version": "0.28.1",
4
4
  "description": "VibeView CLI -- run your app on cloud iOS simulators, Android emulators, Apple TV, Android TV and Roku (beta) devices: a React Native dev loop, device control for you or your coding agent (CLI or MCP), and tests from CI",
5
5
  "mcpName": "io.github.vibeview/vibeview",
6
6
  "type": "module",