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.
- package/dist/index.mjs +47 -69
- 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 -
|
|
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 -
|
|
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
|
|
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.**
|
|
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)
|
|
8173
|
-
#
|
|
8174
|
-
#
|
|
8175
|
-
replicas computer
|
|
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
|
|
8204
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 \`\` 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) |
|
|
8312
|
-
| Dashboard \`Desktop\` tab |
|
|
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.)
|
|
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
|
|
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
|
|
12890
|
-
|
|
12891
|
-
|
|
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
|
|
12904
|
-
const
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
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
|
|
12917
|
-
if (
|
|
12918
|
-
|
|
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
|
|
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.
|
|
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("
|
|
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)));
|