@runalabs/rill-cli 0.1.7 → 0.1.9

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 +7 -0
  2. package/dist/cli.js +36 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -262,3 +262,10 @@ secret-tool clear service rill api-url https://userill.dev
262
262
  ```
263
263
 
264
264
  Substitute your API URL if you configured another environment. These commands clear the local credential; server-side revocation is managed in Settings.
265
+
266
+ ### Cloud run output
267
+
268
+ `rill record <url> -p "<prompt>"` prints the outcome, summary, and recording URL.
269
+ Use `--json` for a machine-readable result (`--pretty` also enables JSON formatting).
270
+ Provider token usage is retained internally and omitted from customer output.
271
+ `rill run status <run-id>` and `rill run cancel <run-id>` support the same output options.
package/dist/cli.js CHANGED
@@ -15448,6 +15448,9 @@ var ControlPlaneClient = class {
15448
15448
  // src/analytics.ts
15449
15449
  var commandCategories = /* @__PURE__ */ new Map([
15450
15450
  ["doctor", "doctor"],
15451
+ ["record", "cloud_record"],
15452
+ ["run status", "cloud_run_status"],
15453
+ ["run cancel", "cloud_run_cancel"],
15451
15454
  ["record start", "record_start"],
15452
15455
  ["record stop", "record_stop"],
15453
15456
  ["record status", "record_status"],
@@ -15702,6 +15705,25 @@ function errorMessage(error51) {
15702
15705
  return error51 instanceof Error ? error51.message : String(error51);
15703
15706
  }
15704
15707
 
15708
+ // src/cloud-output.ts
15709
+ function customerRun(run2) {
15710
+ if (!run2.result) return run2;
15711
+ const { usage: _usage, ...result } = run2.result;
15712
+ return { ...run2, result };
15713
+ }
15714
+ function formatCloudRun(run2) {
15715
+ const result = run2.result;
15716
+ const outcome = typeof result?.outcome === "string" ? result.outcome : void 0;
15717
+ const summary = typeof result?.summary === "string" ? result.summary : void 0;
15718
+ const publication = result?.publication;
15719
+ const lines = [`Run ${run2.status}${outcome ? ` \xB7 ${outcome}` : ""}`, `Run ID: ${run2.id}`];
15720
+ if (summary) lines.push("", summary);
15721
+ if (publication?.playbackUrl) lines.push("", `Recording: ${publication.playbackUrl}`);
15722
+ if (run2.status === "failed" && !summary) lines.push("", "The run could not finish.");
15723
+ if (!["completed", "failed", "cancelled"].includes(run2.status)) lines.push("", `Check progress: rill run status ${run2.id}`);
15724
+ return lines.join("\n") + "\n";
15725
+ }
15726
+
15705
15727
  // src/recording-lifecycle.ts
15706
15728
  async function startRecordingWithCompensation(remote, dependencies) {
15707
15729
  try {
@@ -15739,7 +15761,7 @@ function controlPlaneUrl(environmentUrl) {
15739
15761
 
15740
15762
  // src/cli.ts
15741
15763
  var program = new Command();
15742
- program.name("rill").description("Record, inspect, and share agent browser runs.").version(CLI_VERSION).option("--api-url <url>", "Rill control plane", controlPlaneUrl(process.env.RILL_API_URL)).option("--pretty", "Pretty-print JSON output", false);
15764
+ program.name("rill").description("Record, inspect, and share agent browser runs.").version(CLI_VERSION).option("--api-url <url>", "Rill control plane", controlPlaneUrl(process.env.RILL_API_URL)).option("--pretty", "Pretty-print JSON output", false).option("--json", "Output cloud run results as JSON", false);
15743
15765
  var activeTelemetry = null;
15744
15766
  program.command("daemon", { hidden: true }).action(() => runDaemon());
15745
15767
  program.command("doctor").description("Validate Rill prerequisites before recording.").action(async () => {
@@ -15748,7 +15770,7 @@ program.command("doctor").description("Validate Rill prerequisites before record
15748
15770
  emit(result, options.pretty);
15749
15771
  if (result.status === "error") process.exitCode = 1;
15750
15772
  });
15751
- async function authorize() {
15773
+ async function authorize(quiet = false) {
15752
15774
  const options = program.opts();
15753
15775
  const client = new ControlPlaneClient(options.apiUrl, null);
15754
15776
  const authorization = await client.createDeviceAuthorization({ deviceName: `${hostname3()} \xB7 ${process.platform}` });
@@ -15765,7 +15787,7 @@ async function authorize() {
15765
15787
  if (result.status === "pending") continue;
15766
15788
  if (result.status !== "approved" || !result.token) throw new Error(`Device authorization ${result.status}.`);
15767
15789
  await saveCredential(options.apiUrl, result.token);
15768
- emit({ schemaVersion: 1, status: "authenticated", expiresAt: result.expiresAt, apiUrl: options.apiUrl }, options.pretty);
15790
+ if (!quiet) emit({ schemaVersion: 1, status: "authenticated", expiresAt: result.expiresAt, apiUrl: options.apiUrl }, options.pretty);
15769
15791
  return result.token;
15770
15792
  }
15771
15793
  throw new Error("Device authorization expired.");
@@ -15776,8 +15798,9 @@ program.command("login").description("Authorize Rill once.").action(async () =>
15776
15798
  var record2 = program.command("record").description("Run a cloud browser from a URL and prompt, or manage a local recording.").argument("[url]").option("-p, --prompt <prompt>").option("--expectation <text>").option("--account <name>", "Saved website test account").option("--id <uuid>", "Retry a submission with the same run ID").option("--no-wait").action(async (url2, commandOptions) => {
15777
15799
  if (!url2 || !commandOptions.prompt) throw new Error("Use rill record <url> -p <prompt>.");
15778
15800
  const options = program.opts();
15779
- const token = await loadCredential(options.apiUrl) ?? await authorize();
15801
+ const token = await loadCredential(options.apiUrl) ?? await authorize(true);
15780
15802
  const client = new ControlPlaneClient(options.apiUrl, token);
15803
+ if (!activeTelemetry) await startCliTelemetry(client, "cloud_record");
15781
15804
  const id = commandOptions.id ?? crypto.randomUUID();
15782
15805
  process.stderr.write(`Run ID: ${id}
15783
15806
  `);
@@ -15792,14 +15815,17 @@ var record2 = program.command("record").description("Run a cloud browser from a
15792
15815
  await new Promise((resolve) => setTimeout(resolve, 2e3));
15793
15816
  run2 = await client.cloudRun(id);
15794
15817
  }
15795
- emit(run2, options.pretty);
15818
+ if (options.json || options.pretty) emit(customerRun(run2), options.pretty);
15819
+ else process.stdout.write(formatCloudRun(run2));
15796
15820
  if (run2.status === "failed") process.exitCode = 1;
15797
15821
  });
15798
15822
  var cloudRun = program.command("run").description("Retrieve or cancel a cloud run.");
15799
15823
  for (const action of ["status", "cancel"]) cloudRun.command(action).argument("<run-id>").action(async (id) => {
15800
15824
  const options = program.opts();
15801
15825
  const client = new ControlPlaneClient(options.apiUrl, await loadCredential(options.apiUrl));
15802
- emit(await (action === "status" ? client.cloudRun(id) : client.cancelCloudRun(id)), options.pretty);
15826
+ const run2 = await (action === "status" ? client.cloudRun(id) : client.cancelCloudRun(id));
15827
+ if (options.json || options.pretty) emit(customerRun(run2), options.pretty);
15828
+ else process.stdout.write(formatCloudRun(run2));
15803
15829
  });
15804
15830
  record2.command("start").option("--url <url>").option("--title <title>").option("--description <description>", "").option("--headed").option("--cdp-url <url>").option("--width <pixels>", "", "1280").option("--height <pixels>", "", "720").option("--max-duration <seconds>", "", "600").action(async (commandOptions) => {
15805
15831
  const options = program.opts();
@@ -15939,11 +15965,14 @@ program.hook("preAction", async (_command, actionCommand) => {
15939
15965
  const token = await loadCredential(options.apiUrl).catch(() => null);
15940
15966
  if (!token) return;
15941
15967
  const client = new ControlPlaneClient(options.apiUrl, token);
15968
+ await startCliTelemetry(client, command);
15969
+ });
15970
+ async function startCliTelemetry(client, command) {
15942
15971
  const session = await client.agentSession().catch(() => null);
15943
15972
  if (!session?.analyticsEnabled) return;
15944
15973
  activeTelemetry = { client, command, startedAt: Date.now() };
15945
15974
  await client.reportCliCommand({ phase: "started", command, cliVersion: CLI_VERSION, os: process.platform, arch: process.arch }).catch(() => void 0);
15946
- });
15975
+ }
15947
15976
  program.hook("postAction", async () => {
15948
15977
  await finishCliTelemetry(process.exitCode ? new Error("command_reported_failure: Command returned a failure status.") : null);
15949
15978
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runalabs/rill-cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Record, inspect, and share agent-controlled browser runs with Rill.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {