replicas-cli 0.2.407 → 0.2.408
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 +51 -16
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -22655,7 +22655,7 @@ replicas computer browser-state /tmp/after-click.png
|
|
|
22655
22655
|
replicas computer record start /tmp/demo.mp4 --fps 60
|
|
22656
22656
|
# ... do stuff ...
|
|
22657
22657
|
replicas computer record stop
|
|
22658
|
-
replicas media upload /tmp/demo.mp4
|
|
22658
|
+
replicas media upload /tmp/demo.mp4 --name "Demo recording"
|
|
22659
22659
|
\`\`\`
|
|
22660
22660
|
|
|
22661
22661
|
## Command reference
|
|
@@ -22745,7 +22745,7 @@ Starts an ffmpeg screen recorder and returns only after ffmpeg has written the f
|
|
|
22745
22745
|
Only one recording at a time. Re-running \`start\` while one is active fails - call \`stop\` first.
|
|
22746
22746
|
|
|
22747
22747
|
### \`replicas computer record stop\`
|
|
22748
|
-
SIGINTs ffmpeg, verifies that the process has finalized the MP4, then prints the output path. A finalization timeout preserves the recording state so \`stop\` can be retried safely. Upload it with \`replicas media upload <path
|
|
22748
|
+
SIGINTs ffmpeg, verifies that the process has finalized the MP4, then prints the output path. A finalization timeout preserves the recording state so \`stop\` can be retried safely. Upload it with \`replicas media upload <path> --name "<name>"\` to share it.
|
|
22749
22749
|
|
|
22750
22750
|
## Patterns
|
|
22751
22751
|
|
|
@@ -22790,7 +22790,7 @@ For tasks the user wants proof of:
|
|
|
22790
22790
|
replicas computer record start /tmp/walkthrough.mp4
|
|
22791
22791
|
# ... your work ...
|
|
22792
22792
|
replicas computer record stop
|
|
22793
|
-
replicas media upload /tmp/walkthrough.mp4
|
|
22793
|
+
replicas media upload /tmp/walkthrough.mp4 --name "Walkthrough recording"
|
|
22794
22794
|
\`\`\`
|
|
22795
22795
|
Then embed the printed \`\` line in your chat reply. See \`MEDIA.md\`.
|
|
22796
22796
|
|
|
@@ -22991,7 +22991,7 @@ gh pr review 123 --request-changes --body "Changes needed"
|
|
|
22991
22991
|
GitHub does NOT have a public API for uploading images to PRs/issues. When you need to include images:
|
|
22992
22992
|
- Do NOT use placeholder image URLs
|
|
22993
22993
|
- Do NOT commit screenshots as files to the repository
|
|
22994
|
-
- Run \`replicas media upload <image> --share\` and put the printed \`Forge embed\` Markdown in the PR body or comment
|
|
22994
|
+
- Run \`replicas media upload <image> --name "<display name>" --share\` and put the printed \`Forge embed\` Markdown in the PR body or comment
|
|
22995
22995
|
- For video, embed a shared poster image linked to the recording's **View in Replicas** URL; GitHub does not reliably render externally hosted video inline
|
|
22996
22996
|
- Treat the public URL as an opt-in bearer capability; revoke it with \`replicas media revoke <media-id>\` only when the user asks or the media should stop rendering \u2014 revoking breaks embeds already posted on the PR
|
|
22997
22997
|
- If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
|
|
@@ -23572,10 +23572,26 @@ If none of these apply, don't upload.
|
|
|
23572
23572
|
## Uploading to Replicas
|
|
23573
23573
|
|
|
23574
23574
|
\`\`\`bash
|
|
23575
|
-
replicas media upload <path-to-file> [<path-to-file> ...]
|
|
23575
|
+
replicas media upload <path-to-file> --name "<display name>" [<path-to-file> --name "<display name>" ...]
|
|
23576
23576
|
\`\`\`
|
|
23577
23577
|
|
|
23578
|
-
Pass one or more file paths. Uploading several files in a single invocation is preferred over running the command repeatedly
|
|
23578
|
+
Pass one or more file paths, each with a required \`--name\` (see below). Uploading several files in a single invocation is preferred over running the command repeatedly: it's faster and keeps the output grouped.
|
|
23579
|
+
|
|
23580
|
+
### Name each upload
|
|
23581
|
+
|
|
23582
|
+
\`--name\` is **required** and sets the short, human-readable display name shown in the Replicas dashboard (the backend still tracks the asset by UUID). Make it descriptive of the content, e.g. \`login-page\`, \`checkout-error\`, or \`db-latency-chart\`. Never use a generic value like \`screenshot\` or \`image\`.
|
|
23583
|
+
|
|
23584
|
+
\`\`\`bash
|
|
23585
|
+
replicas media upload /tmp/shot.png --name "Login page after fix"
|
|
23586
|
+
\`\`\`
|
|
23587
|
+
|
|
23588
|
+
Pass one \`--name\` per file, in the same order as the file paths:
|
|
23589
|
+
|
|
23590
|
+
\`\`\`bash
|
|
23591
|
+
replicas media upload /tmp/before.png /tmp/after.png --name "Before fix" --name "After fix"
|
|
23592
|
+
\`\`\`
|
|
23593
|
+
|
|
23594
|
+
Names are normalized to hyphen-case (spaces become hyphens, e.g. \`Login page\` is stored as \`login-page\`). Give every asset a **distinct** name \u2014 duplicates are not rejected, but Replicas keeps the first as-is and adds a \`-1\`, \`-2\` suffix to later collisions, which produces confusing lists, so pick unique names yourself.
|
|
23579
23595
|
|
|
23580
23596
|
For each file, the CLI prints two lines:
|
|
23581
23597
|
|
|
@@ -23587,7 +23603,7 @@ Match each "View in Replicas" line to the embed line directly above it \u2014 th
|
|
|
23587
23603
|
Pass \`--share\` only when the media must render on an external forge:
|
|
23588
23604
|
|
|
23589
23605
|
\`\`\`bash
|
|
23590
|
-
replicas media upload screenshot.png --share
|
|
23606
|
+
replicas media upload screenshot.png --name "Login page" --share
|
|
23591
23607
|
\`\`\`
|
|
23592
23608
|
|
|
23593
23609
|
This prints an additional \`Forge embed\` Markdown line backed by an opt-in public bearer URL. Anyone with that unguessable URL can view the asset until it is rotated or revoked. Use \`replicas media share <media-id>\` to rotate it and \`replicas media revoke <media-id>\` to revoke it.
|
|
@@ -23757,7 +23773,7 @@ Never paste the \`api.tryreplicas.com/v1/media/<id>\` URL into a Linear body or
|
|
|
23757
23773
|
GitHub has **no public API** for uploading attachments to PRs or issues. Its web UI uses an undocumented internal endpoint that API clients must not emulate. For screenshots, explicitly create a forge share and put the printed \`Forge embed\` Markdown directly in the PR body or comment, followed by the dashboard link:
|
|
23758
23774
|
|
|
23759
23775
|
\`\`\`bash
|
|
23760
|
-
replicas media upload /tmp/screenshot.png --share
|
|
23776
|
+
replicas media upload /tmp/screenshot.png --name "PR screenshot" --share
|
|
23761
23777
|
\`\`\`
|
|
23762
23778
|
|
|
23763
23779
|
GitHub does not reliably render arbitrary external videos as inline players. For a recording:
|
|
@@ -23811,13 +23827,14 @@ Auto-detected from the filename extension:
|
|
|
23811
23827
|
For other extensions, pass \`--kind image|video|audio\` explicitly. The kind applies to every file in that invocation, so group files of the same kind together:
|
|
23812
23828
|
|
|
23813
23829
|
\`\`\`bash
|
|
23814
|
-
replicas media upload diagram.svg --kind image
|
|
23815
|
-
replicas media upload chart-a.svg chart-b.svg --kind image
|
|
23830
|
+
replicas media upload diagram.svg --name "Architecture diagram" --kind image
|
|
23831
|
+
replicas media upload chart-a.svg chart-b.svg --name "Latency chart" --name "Error rate chart" --kind image
|
|
23816
23832
|
\`\`\`
|
|
23817
23833
|
|
|
23818
23834
|
## Options
|
|
23819
23835
|
|
|
23820
23836
|
- \`--kind <image|video|audio>\` \u2014 override auto-detection
|
|
23837
|
+
- \`--name <name>\`: required display name shown in the dashboard, one per file in order
|
|
23821
23838
|
- \`--session-id <id>\` \u2014 associate the upload with a specific session
|
|
23822
23839
|
- \`--share\`: create a revocable public bearer URL for a forge image embed
|
|
23823
23840
|
`;
|
|
@@ -24401,7 +24418,7 @@ function formatTurnElapsed(ms) {
|
|
|
24401
24418
|
}
|
|
24402
24419
|
|
|
24403
24420
|
// ../shared/src/cli-version.ts
|
|
24404
|
-
var CLI_VERSION = "0.2.
|
|
24421
|
+
var CLI_VERSION = "0.2.408";
|
|
24405
24422
|
|
|
24406
24423
|
// ../shared/src/version.ts
|
|
24407
24424
|
function compareVersions(v1, v2) {
|
|
@@ -29690,9 +29707,12 @@ function mediaInfo(ext) {
|
|
|
29690
29707
|
if (kind !== "image" && kind !== "video" && kind !== "audio") return void 0;
|
|
29691
29708
|
return { kind, contentType: mimeType };
|
|
29692
29709
|
}
|
|
29710
|
+
function isMediaKind(value) {
|
|
29711
|
+
return MEDIA_KINDS.some((kind) => kind === value);
|
|
29712
|
+
}
|
|
29693
29713
|
function resolveKind(ext, override) {
|
|
29694
29714
|
if (override) {
|
|
29695
|
-
if (!
|
|
29715
|
+
if (!isMediaKind(override)) {
|
|
29696
29716
|
throw new Error(`Invalid kind '${override}'. Must be one of: ${MEDIA_KINDS.join(", ")}`);
|
|
29697
29717
|
}
|
|
29698
29718
|
return override;
|
|
@@ -29703,7 +29723,7 @@ function resolveKind(ext, override) {
|
|
|
29703
29723
|
}
|
|
29704
29724
|
return inferred;
|
|
29705
29725
|
}
|
|
29706
|
-
async function uploadOne(filePath, options) {
|
|
29726
|
+
async function uploadOne(filePath, displayName, options) {
|
|
29707
29727
|
const absPath = path5.resolve(filePath);
|
|
29708
29728
|
if (!fs4.existsSync(absPath)) {
|
|
29709
29729
|
throw new Error(`File not found: ${absPath}`);
|
|
@@ -29723,6 +29743,7 @@ async function uploadOne(filePath, options) {
|
|
|
29723
29743
|
form.append("file", new Blob([fs4.readFileSync(absPath)], { type: contentType }), fileName);
|
|
29724
29744
|
form.append("kind", kind);
|
|
29725
29745
|
if (options.sessionId) form.append("session_id", options.sessionId);
|
|
29746
|
+
form.append("display_name", displayName);
|
|
29726
29747
|
const { media } = await agentFetch("/v1/engine/media", {
|
|
29727
29748
|
method: "POST",
|
|
29728
29749
|
body: form
|
|
@@ -29733,10 +29754,19 @@ async function mediaUploadCommand(filePaths, options) {
|
|
|
29733
29754
|
if (filePaths.length === 0) {
|
|
29734
29755
|
throw new Error("No files specified");
|
|
29735
29756
|
}
|
|
29736
|
-
if (options.kind && !
|
|
29757
|
+
if (options.kind && !isMediaKind(options.kind)) {
|
|
29737
29758
|
throw new Error(`Invalid kind '${options.kind}'. Must be one of: ${MEDIA_KINDS.join(", ")}`);
|
|
29738
29759
|
}
|
|
29739
|
-
const
|
|
29760
|
+
const names = options.name ?? [];
|
|
29761
|
+
if (names.length !== filePaths.length) {
|
|
29762
|
+
throw new Error(
|
|
29763
|
+
`Each file needs a --name. Got ${filePaths.length} file(s) and ${names.length} --name value(s); pass one --name per file, in order.`
|
|
29764
|
+
);
|
|
29765
|
+
}
|
|
29766
|
+
if (names.some((name) => !name.trim())) {
|
|
29767
|
+
throw new Error("--name must not be empty.");
|
|
29768
|
+
}
|
|
29769
|
+
const results = await Promise.allSettled(filePaths.map((p, i) => uploadOne(p, names[i], options)));
|
|
29740
29770
|
const config3 = readAgentConfig();
|
|
29741
29771
|
const failures = [];
|
|
29742
29772
|
for (let i = 0; i < results.length; i++) {
|
|
@@ -37267,7 +37297,12 @@ if (isAgentMode()) {
|
|
|
37267
37297
|
}
|
|
37268
37298
|
});
|
|
37269
37299
|
const media = program.command("media").description("Share workspace media (screenshots, videos, audio) inline in chat");
|
|
37270
|
-
media.command("upload <files...>").description("Upload one or more screenshot, video, or audio files. Multiple files are uploaded concurrently. Prints a markdown embed per file for the assistant reply.").option("-k, --kind <kind>", "Media kind: image, video, or audio (inferred from extension if omitted)").option("-s, --session-id <id>", "Session ID to associate the asset with").option(
|
|
37300
|
+
media.command("upload <files...>").description("Upload one or more screenshot, video, or audio files. Multiple files are uploaded concurrently. Prints a markdown embed per file for the assistant reply.").option("-k, --kind <kind>", "Media kind: image, video, or audio (inferred from extension if omitted)").option("-s, --session-id <id>", "Session ID to associate the asset with").option(
|
|
37301
|
+
"-n, --name <name>",
|
|
37302
|
+
"Required human-facing display name shown in the dashboard. Pass one --name per file, in order.",
|
|
37303
|
+
(value, previous) => [...previous, value],
|
|
37304
|
+
[]
|
|
37305
|
+
).option("--share", "Create an opt-in public forge embed URL for each asset").action(async (files, options) => {
|
|
37271
37306
|
try {
|
|
37272
37307
|
await mediaUploadCommand(files, options);
|
|
37273
37308
|
} catch (error51) {
|