@runalabs/rill-cli 0.1.2 → 0.1.3

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.
Files changed (3) hide show
  1. package/README.md +3 -2
  2. package/dist/cli.js +26 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  Record, inspect, and share agent-controlled browser runs with Rill.
4
4
 
5
+ After `rill record stop`, compatible agent hosts may receive `feedbackRequested: true`. They can submit a short Rill product review with `rill feedback submit <recording-id>`. Use `rill record stop <recording-id> --no-feedback` to opt out for one run.
6
+
5
7
  ## Install
6
8
 
7
9
  ```sh
8
- npm install --global @runalabs/rill-cli@0.1.2
10
+ npm install --global @runalabs/rill-cli@0.1.3
9
11
  rill doctor
10
12
  ```
11
13
 
12
14
  Rill requires Node.js 22 or newer, Google Chrome or Chromium, and `ffmpeg`.
13
- The CLI connects to `https://userill.dev` by default.
14
15
 
15
16
  ## Record
16
17
 
package/dist/cli.js CHANGED
@@ -621,6 +621,12 @@ var ControlPlaneClient = class {
621
621
  body: JSON.stringify(input)
622
622
  });
623
623
  }
624
+ submitRecordingFeedback(recordingId, input) {
625
+ return this.request(`/api/recordings/${recordingId}/feedback`, {
626
+ method: "POST",
627
+ body: JSON.stringify(input)
628
+ });
629
+ }
624
630
  provisionVideo(recordingId, input) {
625
631
  return this.request(`/api/recordings/${recordingId}/video-upload`, { method: "POST", body: JSON.stringify(input) });
626
632
  }
@@ -992,27 +998,42 @@ record.command("start").option("--url <url>").option("--title <title>").option("
992
998
  }).catch(() => void 0);
993
999
  emit({ schemaVersion: 1, recordingId: remote.recordingId, status: local.status, cdpUrl: local.cdpUrl, bodyCaptureEnabled: remote.bodyCaptureEnabled, maxDurationSeconds: Number(commandOptions.maxDuration) }, options.pretty);
994
1000
  });
995
- record.command("stop").argument("<recording-id>").option("--no-wait").action(async (recordingId, commandOptions) => {
1001
+ record.command("stop").argument("<recording-id>").option("--no-wait").option("--no-feedback").action(async (recordingId, commandOptions) => {
996
1002
  const options = program.opts();
997
1003
  await ensureDaemon(process.argv[1]);
998
1004
  const local = await stopRecording(recordingId);
999
1005
  if (!local.result) throw new Error(local.error ?? "The recorder did not produce an artifact.");
1000
1006
  const token = await loadCredential(options.apiUrl);
1001
1007
  const client = new ControlPlaneClient(options.apiUrl, token);
1002
- await client.markRecordingStopped(recordingId, {
1008
+ const stopped = await client.markRecordingStopped(recordingId, {
1003
1009
  durationSeconds: local.result.durationSeconds,
1004
1010
  stoppedReason: local.result.stoppedReason,
1005
- diagnosticsAvailable: true
1006
- }).catch(() => void 0);
1011
+ diagnosticsAvailable: true,
1012
+ requestFeedback: commandOptions.feedback
1013
+ }).catch(() => null);
1007
1014
  const video = await stat2(local.result.videoPath);
1008
1015
  const provisioned = await client.provisionVideo(recordingId, { sizeBytes: video.size, filename: basename(local.result.videoPath), uploadKind: "recorded_browser" });
1009
1016
  await Promise.all([client.uploadVideo(provisioned.uploadUrl, local.result.videoPath), client.uploadDiagnostics(recordingId, local.result.diagnosticsPath, local.result.diagnostics)]);
1010
1017
  const remote = commandOptions.wait === false ? null : await client.waitUntilPlayable(recordingId);
1011
1018
  if (remote) process.stderr.write("\n");
1012
- const result = { schemaVersion: 1, recordingId, status: remote ? "ready" : "processing", shareUrl: remote?.shareUrl ?? null, durationSeconds: local.result.durationSeconds, stoppedReason: local.result.stoppedReason, diagnostics: local.result.diagnostics };
1019
+ const result = { schemaVersion: 1, recordingId, status: remote ? "ready" : "processing", shareUrl: remote?.shareUrl ?? null, durationSeconds: local.result.durationSeconds, stoppedReason: local.result.stoppedReason, diagnostics: local.result.diagnostics, feedbackRequested: stopped?.feedbackRequested ?? false };
1013
1020
  emit(result, options.pretty);
1014
1021
  if (remote) await rm2(dirname2(local.result.videoPath), { recursive: true, force: true });
1015
1022
  });
1023
+ var feedback = program.command("feedback").description("Submit a short Rill product review for a recorded run.");
1024
+ feedback.command("submit").argument("<recording-id>").requiredOption("--outcome <outcome>", "succeeded, failed, or abandoned").option("--helped <text>", "What helped during the run", "").option("--friction <text>", "What created friction during the run", "").option("--improvement <text>", "The single most useful Rill improvement", "").action(async (recordingId, commandOptions) => {
1025
+ if (!["succeeded", "failed", "abandoned"].includes(commandOptions.outcome)) throw new Error("validation_failed: Feedback outcome must be succeeded, failed, or abandoned.");
1026
+ if (![commandOptions.helped, commandOptions.friction, commandOptions.improvement].some((value) => value.trim())) throw new Error("validation_failed: Include at least one short feedback answer.");
1027
+ const options = program.opts();
1028
+ const token = await loadCredential(options.apiUrl);
1029
+ const client = new ControlPlaneClient(options.apiUrl, token);
1030
+ await client.submitRecordingFeedback(recordingId, {
1031
+ outcome: commandOptions.outcome,
1032
+ whatHelped: commandOptions.helped,
1033
+ friction: commandOptions.friction,
1034
+ improvement: commandOptions.improvement
1035
+ });
1036
+ });
1016
1037
  record.command("status").argument("<recording-id>").action(async (recordingId) => {
1017
1038
  const options = program.opts();
1018
1039
  const token = await loadCredential(options.apiUrl);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runalabs/rill-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Record, inspect, and share agent-controlled browser runs with Rill.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {