vibeview 0.45.0 → 0.47.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.
@@ -2,6 +2,8 @@
2
2
  import {
3
3
  AGENT_COMMANDS,
4
4
  DEV_PLATFORMS,
5
+ FEEDBACK_KINDS,
6
+ FEEDBACK_RULES,
5
7
  PLATFORM_DEVICE,
6
8
  PLATFORM_NEEDS_METRO,
7
9
  buildLines,
@@ -14,10 +16,12 @@ import {
14
16
  decodeScreenshotResult,
15
17
  describeDevBuild,
16
18
  effectiveDevConfig,
19
+ feedbackSentLine,
17
20
  filterDeviceModels,
18
21
  formatBuildRowsHuman,
19
22
  formatDeviceModelsHuman,
20
23
  isDevPlatform,
24
+ isFeedbackKind,
21
25
  loadDevConfig,
22
26
  loadLocalDevConfig,
23
27
  outcomeOf,
@@ -30,12 +34,12 @@ import {
30
34
  renderEnvelope,
31
35
  resolveMetro,
32
36
  startDevSession
33
- } from "./chunk-YF4L2WO2.js";
37
+ } from "./chunk-GA56B7WS.js";
34
38
  import {
35
39
  ApiClient,
36
40
  NotFoundError,
37
41
  resolveAuth
38
- } from "./chunk-GDTLLJFL.js";
42
+ } from "./chunk-3LXR2YCS.js";
39
43
 
40
44
  // src/mcp/server.ts
41
45
  import { writeFileSync } from "fs";
@@ -243,6 +247,29 @@ var LIST_APPS_DEF = {
243
247
  },
244
248
  required: []
245
249
  };
250
+ var SEND_FEEDBACK_DEF = {
251
+ name: "send_feedback",
252
+ description: `Send the VibeView team a bug report, a friction note or a feature idea about VibeView itself. ${FEEDBACK_RULES} The report includes the session's device and status when it names one.`,
253
+ mutating: true,
254
+ properties: {
255
+ kind: {
256
+ type: "string",
257
+ description: "bug, friction or idea.",
258
+ enum: [...FEEDBACK_KINDS]
259
+ },
260
+ summary: { type: "string", description: "One line; kept to 200 characters." },
261
+ details: {
262
+ type: "string",
263
+ description: "What you tried, what happened, what you expected; kept to 4000 characters."
264
+ },
265
+ session_id: SESSION_ID_PROPERTY,
266
+ user_quote: {
267
+ type: "string",
268
+ description: "The user's own words about the problem, verbatim (optional)."
269
+ }
270
+ },
271
+ required: ["kind", "summary"]
272
+ };
246
273
  var DEV_STOP_DEF = {
247
274
  name: "dev_stop",
248
275
  description: "Stop the dev-loop session started by dev_start.",
@@ -287,7 +314,8 @@ function buildToolDefinitions() {
287
314
  CREATE_TEST_DEF,
288
315
  RUN_TEST_DEF,
289
316
  RUN_GROUP_DEF,
290
- GET_RUN_DEF
317
+ GET_RUN_DEF,
318
+ SEND_FEEDBACK_DEF
291
319
  ];
292
320
  }
293
321
  var runClientOf = (deps) => deps.runClient ?? new ApiClient(deps.auth.baseUrl, deps.auth.token, { client: "mcp" });
@@ -551,6 +579,9 @@ async function dispatchToolCall(toolName, args, deps, extra = {}) {
551
579
  if (toolName === "list_apps") {
552
580
  return handleListApps(args, deps);
553
581
  }
582
+ if (toolName === "send_feedback") {
583
+ return handleSendFeedback(args, deps);
584
+ }
554
585
  if (toolName === "stop_session") {
555
586
  return handleStopSession(args, deps);
556
587
  }
@@ -839,6 +870,28 @@ async function handleListDeviceModels(args, deps) {
839
870
  }))
840
871
  });
841
872
  }
873
+ async function handleSendFeedback(args, deps) {
874
+ if (!isFeedbackKind(args.kind)) {
875
+ return errorResult(`send_feedback: \`kind\` must be one of ${FEEDBACK_KINDS.join(", ")}`);
876
+ }
877
+ const summary = typeof args.summary === "string" ? args.summary.trim() : "";
878
+ if (!summary) return errorResult("send_feedback: `summary` is required");
879
+ const sessionId = typeof args.session_id === "string" && args.session_id.trim() ? args.session_id.trim() : deps.resolveSessionId();
880
+ const body = { kind: args.kind, summary, client: "mcp" };
881
+ if (typeof args.details === "string" && args.details.trim()) body.details = args.details;
882
+ if (typeof args.user_quote === "string" && args.user_quote.trim()) {
883
+ body.user_quote = args.user_quote;
884
+ }
885
+ if (sessionId) body.session_id = sessionId;
886
+ if (deps.clientVersion) body.client_version = deps.clientVersion;
887
+ const send = deps.sendFeedback ?? ((b) => new ApiClient(deps.auth.baseUrl, deps.auth.token, { client: "mcp" }).sendFeedback(b));
888
+ try {
889
+ const result = await send(body);
890
+ return textResult(feedbackSentLine(result), result);
891
+ } catch (err) {
892
+ return errorResult(`error: ${err instanceof Error ? err.message : String(err)}`);
893
+ }
894
+ }
842
895
  async function handleListApps(args, deps) {
843
896
  const list = deps.listApps ?? (() => new ApiClient(deps.auth.baseUrl, deps.auth.token).listApps());
844
897
  const platform = typeof args.platform === "string" && args.platform ? args.platform : void 0;
@@ -945,7 +998,7 @@ async function handleUploadApp(args, deps) {
945
998
  }
946
999
  const name = typeof args.name === "string" && args.name ? args.name : void 0;
947
1000
  const upload = deps.uploadApp ?? (async (f, n) => {
948
- const { uploadAppBuild } = await import("./upload-app-ZEQMGZIT.js");
1001
+ const { uploadAppBuild } = await import("./upload-app-TDR6PIWD.js");
949
1002
  const { result: result2 } = await uploadAppBuild(f, { ...deps.auth, name: n });
950
1003
  return result2;
951
1004
  });
@@ -1339,7 +1392,8 @@ var MCP_INSTRUCTIONS = [
1339
1392
  "screenshot writes a PNG and returns its path; pass inline: true to see the image. logs reads the app output after a crash or blank screen.",
1340
1393
  "Tests: create_test, then run_test (or run_group) and get_run. With session_id a run uses the session you hold; without it, a run starts its own new device (never your dev_start session).",
1341
1394
  "A session stopped elsewhere is reported as ended; call dev_start again for a new one.",
1342
- 'A session nobody uses ends after the idle timeout. A result that ends with "Session \u2026 ends in N s for inactivity" means act (tap, type, swipe, press) to keep it, or dev_stop if you are done; ui_tree, screenshot, logs, find and wait do not count as use.'
1395
+ 'A session nobody uses ends after the idle timeout. A result that ends with "Session \u2026 ends in N s for inactivity" means act (tap, type, swipe, press) to keep it, or dev_stop if you are done; ui_tree, screenshot, logs, find and wait do not count as use.',
1396
+ "If VibeView itself gets in your way (an error you cannot explain, a missing capability, confusing output), offer the user to send it with send_feedback."
1343
1397
  ].join("\n");
1344
1398
  function toolInputSchema(def, z) {
1345
1399
  const shape = {};
@@ -1370,7 +1424,8 @@ async function createMcpServer(opts) {
1370
1424
  auth,
1371
1425
  resolveSessionId: makeSessionResolver(devSession),
1372
1426
  agentTool: client.agentTool.bind(client),
1373
- devSession
1427
+ devSession,
1428
+ clientVersion: opts.version
1374
1429
  };
1375
1430
  const server = new McpServer(
1376
1431
  { name: "vibeview", version: opts.version ?? "0.0.0" },
@@ -3,7 +3,7 @@ import {
3
3
  describeBuild,
4
4
  uploadApp,
5
5
  uploadAppBuild
6
- } from "./chunk-GDTLLJFL.js";
6
+ } from "./chunk-3LXR2YCS.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.45.0",
3
+ "version": "0.47.0",
4
4
  "description": "VibeView CLI -- run your app on cloud iOS simulators, Android emulators, Apple TV, Android TV and Roku 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",
@@ -252,6 +252,19 @@ hit one:
252
252
  the confirmation alone. If it's still there, say what you still see and
253
253
  ask again.
254
254
 
255
+ ### When VibeView itself gets in your way
256
+
257
+ If VibeView — not the user's app — gets in your way (an error you can't
258
+ explain, a missing capability, confusing output), offer to tell the VibeView
259
+ team. Show the user what you will send and send it only with their OK:
260
+
261
+ vibeview feedback bug "dev_start says build not found for a build I just uploaded" \
262
+ --details "upload-app returned build 123; dev --build 123 failed" --session <id>
263
+
264
+ `kind` is `bug`, `friction` (worked, but confusing, slow or awkward) or `idea`.
265
+ Never include passwords, tokens, test data values or personal data. Over MCP
266
+ the same tool is `send_feedback`.
267
+
255
268
  ## 5. Cleanup
256
269
 
257
270
  **Always** stop the session when done verifying — a running session bills
@@ -318,6 +331,7 @@ Dev-loop lifecycle commands (not registry verbs, but needed for every run):
318
331
  | `dev-stop` | End the current project's detached dev session. |
319
332
  | `vibeview stop <session-id>` | End any session by id — one created through the API, the sandbox, or a collaboration link. |
320
333
  | `dev-reload` | Roku only: re-package, upload and restart the channel in the detached session (the `r` key of the foreground loop). |
334
+ | `vibeview feedback <bug\|friction\|idea> "<summary>"` | Send the VibeView team a report about VibeView itself (not your app), only after the user OKs it: `--details`, `--session` (defaults to the detached session, if any), `--quote` (the user's own words). Works with no session. |
321
335
 
322
336
  ## 7. If you're calling VibeView over MCP
323
337