replicas-cli 0.2.200 → 0.2.202

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 (2) hide show
  1. package/dist/index.mjs +47 -69
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8131,18 +8131,18 @@ function extractPrNumber(url) {
8131
8131
 
8132
8132
  // ../shared/src/default-skills/replicas-agent/abilities/computer.ts
8133
8133
  var SECTION = `### Computer use (Linux desktop control)
8134
- Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - and surface a live noVNC viewer to the user via the \`replicas computer\` CLI. Every Replicas workspace boots with Xvfb / openbox / x11vnc / noVNC pre-installed.
8134
+ Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - via the \`replicas computer\` CLI. Every Replicas workspace boots with Xvfb / openbox / x11vnc / noVNC pre-installed and the live noVNC viewer is automatically published as an authenticated preview, so a \`Desktop\` tab is always available in the dashboard. Use \`replicas computer info\` to get the viewer URL when you want to share it (e.g. point a user on Slack at the live stream).
8135
8135
 
8136
8136
  **Reference:** \`references/COMPUTER-USE.md\`
8137
8137
 
8138
8138
  Use this when:
8139
8139
  - A task requires interacting with a website, web app, or desktop application that has no usable API
8140
- - You want the user to watch the agent work - \`replicas computer start\` exposes a \`Desktop\` tab in the dashboard
8140
+ - You want the user to watch the agent work - they can open the \`Desktop\` tab, or you can share the URL from \`replicas computer info\`
8141
8141
  - You're testing UI changes in a browser before reporting them as done
8142
8142
  - You want to record a screen capture of a task as proof to share back`;
8143
8143
  var REFERENCE = `# Computer use (Linux desktop control)
8144
8144
 
8145
- Every Replicas workspace boots with a full Linux desktop stack - Xvfb (1920\xD71080), openbox, tint2, x11vnc, noVNC, ffmpeg, and Google Chrome. You drive it through the \`replicas computer\` CLI.
8145
+ Every Replicas workspace boots with a full Linux desktop stack - Xvfb (1920\xD71080), openbox, tint2, x11vnc, noVNC, ffmpeg, and Google Chrome. The engine also auto-registers the noVNC viewer (port 6080) as an authenticated preview at startup, so the dashboard \`Desktop\` tab is live the moment the workspace is up. You drive the desktop through the \`replicas computer\` CLI.
8146
8146
 
8147
8147
  Use this for anything the user can't reasonably do via an API - clicking around web apps, filling forms, testing UI changes, dragging files between desktop apps, recording a walkthrough.
8148
8148
 
@@ -8150,7 +8150,7 @@ Use this for anything the user can't reasonably do via an API - clicking around
8150
8150
 
8151
8151
  - **Prefer real APIs first.** If a task has a CLI or HTTP API (GitHub, Linear, Slack, Replicas itself), use that. Driving a UI is slower, flakier, and less auditable.
8152
8152
  - **Use it when there's no API**: testing a frontend you just changed, navigating a vendor portal, demonstrating a flow on video.
8153
- - **Use it when the user wants to watch.** \`replicas computer start\` exposes a live \`Desktop\` tab in the dashboard - they can watch you work in real time.
8153
+ - **Use it when the user wants to watch.** The dashboard already shows a \`Desktop\` tab. If you're talking to the user somewhere else (e.g. Slack), call \`replicas computer info\` to get the viewer URL and paste it in.
8154
8154
 
8155
8155
  ## Never use raw \`xdotool\` / \`scrot\` / \`ffmpeg\` directly
8156
8156
 
@@ -8169,10 +8169,10 @@ scrot /tmp/state.png
8169
8169
  ## Quickstart
8170
8170
 
8171
8171
  \`\`\`bash
8172
- # 1) Make the desktop visible to the user (creates an authenticated noVNC
8173
- # preview on port 6080, prints the viewer URL, adds a "Desktop" tab to the
8174
- # dashboard).
8175
- replicas computer start
8172
+ # 1) (Optional) Get the live viewer URL so you can share it with the user.
8173
+ # The desktop is already running and the preview is already registered -
8174
+ # this just looks up the URL.
8175
+ replicas computer info
8176
8176
 
8177
8177
  # 2) Launch a browser on the workspace display.
8178
8178
  replicas computer launch chrome
@@ -8193,20 +8193,14 @@ replicas computer record start /tmp/demo.mp4 --fps 60
8193
8193
  # ... do stuff ...
8194
8194
  replicas computer record stop
8195
8195
  replicas media upload /tmp/demo.mp4
8196
-
8197
- # 6) Tear down the live preview when done (services keep running for next time).
8198
- replicas computer stop
8199
8196
  \`\`\`
8200
8197
 
8201
8198
  ## Command reference
8202
8199
 
8203
- ### \`replicas computer start [--port N] [--display :N] [--size WxH]\`
8204
- Ensures all desktop services are running and creates an authenticated noVNC preview. Prints the viewer URL (\`https://<port>-<hash>.tryreplicas.com/\`). The Replicas dashboard automatically shows a \`Desktop\` tab while this preview is live - point the user at it instead of pasting the URL.
8205
-
8206
- Idempotent - safe to call repeatedly. Use it as the first computer-use command in any session.
8200
+ ### \`replicas computer info\`
8201
+ Prints the live noVNC viewer URL (\`https://6080-<hash>.tryreplicas.com/\`) for the workspace desktop. The engine auto-registers this authenticated preview on startup; \`info\` just looks it up. Use it when you want to share the live stream URL with the user out-of-band (e.g. in a Slack reply) - the dashboard \`Desktop\` tab already points at the same URL automatically.
8207
8202
 
8208
- ### \`replicas computer stop [--port N]\`
8209
- Tears down the noVNC preview (the \`Desktop\` tab disappears). The underlying Xvfb / openbox / x11vnc / browser keep running so the next \`start\` is instant.
8203
+ If invoked very early in the workspace lifecycle, \`info\` will poll briefly while the engine finishes registering the preview, then error if it's still not available.
8210
8204
 
8211
8205
  ### \`replicas computer status\`
8212
8206
  Prints which desktop services are running and the active preview URL (if any). Useful for debugging when a tool call seems to be doing nothing.
@@ -8279,12 +8273,11 @@ replicas computer screenshot /tmp/loaded.png
8279
8273
  The display is 1920\xD71080. Screenshot pixels map 1:1 to click coordinates - if your Read tool shows a button at pixel (520, 700), click \`replicas computer click 520 700\`. **No translation needed.** Modern image-reading models often imagine the screenshot is at a different resolution; trust the \`xdpyinfo\` value (\`replicas computer status\` shows the real size).
8280
8274
 
8281
8275
  ### Letting the user watch
8282
- Always start the desktop session with \`replicas computer start\` *before* doing anything visual, even if you don't need the URL yourself. The Desktop tab appears in their dashboard. They get to watch and intervene if needed.
8276
+ The Desktop tab is already live in the dashboard - the user can open it any time. If you're communicating with the user somewhere else (Slack, PR comment, etc.), grab the URL with \`replicas computer info\` and share it inline so they can watch you work.
8283
8277
 
8284
8278
  ### Recording a deliverable
8285
8279
  For tasks the user wants proof of:
8286
8280
  \`\`\`bash
8287
- replicas computer start # makes it visible live too
8288
8281
  replicas computer record start /tmp/walkthrough.mp4
8289
8282
  # ... your work ...
8290
8283
  replicas computer record stop
@@ -8292,15 +8285,13 @@ replicas media upload /tmp/walkthrough.mp4
8292
8285
  \`\`\`
8293
8286
  Then embed the printed \`![\u2026](\u2026)\` line in your chat reply. See \`MEDIA.md\`.
8294
8287
 
8295
- ### Cleaning up
8296
- Call \`replicas computer stop\` when you're done with the visual demo so the live preview URL goes away. The services keep running so the next \`start\` is instant.
8297
-
8298
8288
  ## Failure modes
8299
8289
 
8300
8290
  - **"Desktop services script missing"**: workspace image is older than this skill. Tell the user - nothing you can do from the CLI side.
8301
8291
  - **\`xdotool ... failed: Can't open display\`**: Xvfb didn't come up. \`replicas computer status\` will show which service is dead. Re-running any CLI command auto-attempts to start it.
8302
8292
  - **Browser doesn't appear after \`launch chrome\`**: give it 1-2s, then screenshot. Chrome cold-start on the virtual display takes ~500ms but bigger pages take longer.
8303
8293
  - **Live preview shows static / black screen**: the browser may have crashed. \`replicas computer status\` should show no Chrome process - re-launch.
8294
+ - **\`replicas computer info\` errors with "not registered"**: engine couldn't register the preview at startup (transient monolith error, or warming mode). Re-running the engine usually fixes it. Until it's registered, the Desktop tab will show a placeholder.
8304
8295
 
8305
8296
  ## What gets baked in vs. lazy
8306
8297
 
@@ -8308,10 +8299,10 @@ Call \`replicas computer stop\` when you're done with the visual demo so the liv
8308
8299
  |---|---|
8309
8300
  | \`xvfb\`, \`openbox\`, \`tint2\`, \`x11vnc\`, \`websockify\`, \`xdotool\`, \`scrot\`, \`ffmpeg\`, \`google-chrome\` | Baked into the workspace image |
8310
8301
  | Xvfb / openbox / tint2 / x11vnc / websockify processes | Started at workspace boot (\`replicas-start-desktop-services\`) |
8311
- | noVNC preview URL (port 6080) | **Lazy** - created by \`replicas computer start\` |
8312
- | Dashboard \`Desktop\` tab | Appears when the preview URL is live, disappears on \`stop\` |
8302
+ | noVNC preview URL (port 6080) | Registered by the engine on startup (authenticated) |
8303
+ | Dashboard \`Desktop\` tab | Always available once the engine has registered the preview |
8313
8304
 
8314
- You can call any of the input tools (\`click\`, \`type\`, \`screenshot\`, etc.) without first calling \`start\` - they'll work since the daemons are running. \`start\` is only needed when you want the user to see the live stream.
8305
+ You can call any of the input tools (\`click\`, \`type\`, \`screenshot\`, etc.) immediately - the daemons are already running.
8315
8306
  `;
8316
8307
  var COMPUTER_ABILITY = {
8317
8308
  label: "Computer use",
@@ -12835,6 +12826,8 @@ var STATE_DIR = process.env.REPLICAS_DESKTOP_STATE_DIR || "/tmp/replicas-compute
12835
12826
  var DEFAULT_DISPLAY = process.env.REPLICAS_DESKTOP_DISPLAY || ":99";
12836
12827
  var NOVNC_PORT = process.env.REPLICAS_DESKTOP_NOVNC_PORT ? parseInt(process.env.REPLICAS_DESKTOP_NOVNC_PORT, 10) : DESKTOP_NOVNC_PORT;
12837
12828
  var SERVICES_SCRIPT = "/usr/local/bin/replicas-start-desktop-services";
12829
+ var INFO_WAIT_TIMEOUT_MS = 1e4;
12830
+ var INFO_WAIT_INTERVAL_MS = 500;
12838
12831
  function fail(msg) {
12839
12832
  throw new Error(msg);
12840
12833
  }
@@ -12868,43 +12861,33 @@ function parseCoord(value, label) {
12868
12861
  function resolvePath(p) {
12869
12862
  return isAbsolute(p) ? p : resolve(process.cwd(), p);
12870
12863
  }
12871
- async function computerStartCommand(options) {
12872
- if (options.display) process.env.REPLICAS_DESKTOP_DISPLAY = options.display;
12873
- if (options.size) {
12874
- const m = /^(\d+)x(\d+)$/.exec(options.size);
12875
- if (!m) fail(`--size must be WIDTHxHEIGHT (got "${options.size}")`);
12876
- process.env.REPLICAS_DESKTOP_WIDTH = m[1];
12877
- process.env.REPLICAS_DESKTOP_HEIGHT = m[2];
12878
- }
12879
- ensureServicesRunning();
12880
- const port = options.port ? parsePreviewPort(options.port) : NOVNC_PORT;
12881
- let publicUrl;
12864
+ async function lookupDesktopViewerUrl() {
12882
12865
  try {
12883
- const result = await createAgentPreview(port, true);
12884
- publicUrl = result.preview.publicUrl;
12885
- } catch (err) {
12886
- const msg = err instanceof Error ? err.message : String(err);
12887
- if (!/409/.test(msg)) throw err;
12888
12866
  const list = await listAgentPreviews();
12889
- const existing = list.previews.find((p) => p.port === port);
12890
- if (!existing) throw err;
12891
- publicUrl = existing.publicUrl;
12867
+ const preview2 = list.previews.find((p) => p.port === NOVNC_PORT);
12868
+ return preview2 ? getDesktopViewerUrl(preview2.publicUrl) : null;
12869
+ } catch {
12870
+ return null;
12892
12871
  }
12893
- const viewerUrl = getDesktopViewerUrl(publicUrl);
12894
- mkdirSync(STATE_DIR, { recursive: true });
12895
- writeFileSync(
12896
- `${STATE_DIR}/preview.json`,
12897
- JSON.stringify({ port, publicUrl, viewerUrl }, null, 2)
12898
- );
12899
- console.log(viewerUrl);
12900
- console.error(chalk19.dim(`Desktop preview ready (port ${port}, authenticated).`));
12901
- console.error(chalk19.dim(`The Replicas dashboard will show a "Desktop" tab while this preview is live.`));
12902
12872
  }
12903
- async function computerStopCommand(options) {
12904
- const port = options.port ? parsePreviewPort(options.port) : NOVNC_PORT;
12905
- await deleteAgentPreview(port);
12906
- rmSync(`${STATE_DIR}/preview.json`, { force: true });
12907
- console.log(`Desktop preview stopped on port ${port}`);
12873
+ async function waitForDesktopViewerUrl(timeoutMs) {
12874
+ const deadline = Date.now() + timeoutMs;
12875
+ while (Date.now() < deadline) {
12876
+ const url = await lookupDesktopViewerUrl();
12877
+ if (url) return url;
12878
+ await new Promise((resolve2) => setTimeout(resolve2, INFO_WAIT_INTERVAL_MS));
12879
+ }
12880
+ return await lookupDesktopViewerUrl();
12881
+ }
12882
+ async function computerInfoCommand() {
12883
+ const viewerUrl = await waitForDesktopViewerUrl(INFO_WAIT_TIMEOUT_MS);
12884
+ if (!viewerUrl) {
12885
+ fail(
12886
+ `Desktop preview for port ${NOVNC_PORT} is not registered. The engine registers it at startup \u2014 check /tmp/replicas-desktop-stack.log and engine logs for errors.`
12887
+ );
12888
+ }
12889
+ console.log(viewerUrl);
12890
+ console.error(chalk19.dim(`Share this URL with the user to let them watch the desktop live.`));
12908
12891
  }
12909
12892
  async function computerStatusCommand() {
12910
12893
  const procs = ["Xvfb", "openbox", "tint2", "x11vnc", "websockify"];
@@ -12913,15 +12896,11 @@ async function computerStatusCommand() {
12913
12896
  const running = r.status === 0 && !!r.stdout?.toString().trim();
12914
12897
  console.log(` ${running ? chalk19.green("\u25CF") : chalk19.red("\u25CB")} ${p}`);
12915
12898
  }
12916
- const previewFile = `${STATE_DIR}/preview.json`;
12917
- if (existsSync(previewFile)) {
12918
- try {
12919
- const meta = JSON.parse(readFileSync(previewFile, "utf8"));
12920
- console.log(` ${chalk19.cyan("preview")}: ${meta.viewerUrl}`);
12921
- } catch {
12922
- }
12899
+ const viewerUrl = await lookupDesktopViewerUrl();
12900
+ if (viewerUrl) {
12901
+ console.log(` ${chalk19.cyan("preview")}: ${viewerUrl}`);
12923
12902
  } else {
12924
- console.log(` ${chalk19.dim("preview: not started (run `replicas computer start`)")}`);
12903
+ console.log(` ${chalk19.dim("preview: not yet registered (engine registers it at startup)")}`);
12925
12904
  }
12926
12905
  }
12927
12906
  async function computerScreenshotCommand(path6) {
@@ -16602,7 +16581,7 @@ Deleted file ${pathOrId}.
16602
16581
  }
16603
16582
 
16604
16583
  // src/index.ts
16605
- var CLI_VERSION = "0.2.200";
16584
+ var CLI_VERSION = "0.2.202";
16606
16585
  function parseBooleanOption(value) {
16607
16586
  if (value === "true") return true;
16608
16587
  if (value === "false") return false;
@@ -17227,8 +17206,7 @@ if (isAgentMode()) {
17227
17206
  process.exit(1);
17228
17207
  }
17229
17208
  };
17230
- computer.command("start").description("Ensure the desktop stack is running and create an authenticated noVNC preview URL. Prints the viewer URL.").option("--port <port>", "noVNC port to expose (default: 6080)").option("--display <id>", "X display to use (default: :99)").option("--size <WxH>", "Display size, e.g. 1920x1080 (default: 1920x1080)").action(wrap((options) => computerStartCommand(options)));
17231
- computer.command("stop").description("Tear down the noVNC preview. Desktop services stay running for the next start.").option("--port <port>", "noVNC port to unregister (default: 6080)").action(wrap((options) => computerStopCommand(options)));
17209
+ computer.command("info").description("Print the live noVNC viewer URL for the workspace desktop. The preview is registered automatically at engine startup, so this just looks it up \u2014 share the URL with the user to let them watch the desktop.").action(wrap(() => computerInfoCommand()));
17232
17210
  computer.command("status").description("Show which desktop services are running and the active preview URL").action(wrap(() => computerStatusCommand()));
17233
17211
  computer.command("screenshot <path>").description("Capture the current desktop to a PNG file. Use the path with `replicas media upload` to share it.").action(wrap((path6) => computerScreenshotCommand(path6)));
17234
17212
  computer.command("click <x> <y>").description("Move to (x, y) and click. Coordinates are in pixels on the workspace display.").option("-b, --button <n>", "Mouse button (1=left, 2=middle, 3=right). Default 1.").option("--double", "Double-click instead of single-click").option("--modifiers <mods>", "Hold modifier keys during the click, e.g. ctrl or ctrl+shift").action(wrap((x, y, options) => computerClickCommand(x, y, options)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.200",
3
+ "version": "0.2.202",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.mjs",
6
6
  "bin": {