replicas-cli 0.2.224 → 0.2.226
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 +194 -27
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8364,7 +8364,7 @@ var LINEAR_ABILITY = {
|
|
|
8364
8364
|
|
|
8365
8365
|
// ../shared/src/default-skills/replicas-agent/abilities/media.ts
|
|
8366
8366
|
var SECTION6 = `### Media
|
|
8367
|
-
Share screenshots, screen recordings, generated diagrams, and audio clips inline in the Replicas chat
|
|
8367
|
+
Share screenshots, screen recordings, generated diagrams, and audio clips inline in the Replicas chat and natively embedded in external messages.
|
|
8368
8368
|
|
|
8369
8369
|
**Reference:** \`references/MEDIA.md\`
|
|
8370
8370
|
|
|
@@ -8374,7 +8374,7 @@ Use this when:
|
|
|
8374
8374
|
- You need to embed media in a Slack/Linear/GitHub message AND keep a referenceable copy in the Replicas dashboard`;
|
|
8375
8375
|
var REFERENCE6 = `# Media (Screenshots, Recordings, Audio)
|
|
8376
8376
|
|
|
8377
|
-
This guide covers how to share screenshots, screen recordings, generated diagrams, and audio clips
|
|
8377
|
+
This guide covers how to share screenshots, screen recordings, generated diagrams, and audio clips \u2014 both inline in the Replicas chat and natively embedded in external surfaces (Slack, Linear, GitHub).
|
|
8378
8378
|
|
|
8379
8379
|
## Prerequisites
|
|
8380
8380
|
|
|
@@ -8390,7 +8390,7 @@ Upload to Replicas in these cases \u2014 and **only** these cases:
|
|
|
8390
8390
|
|
|
8391
8391
|
If none of these apply, don't upload.
|
|
8392
8392
|
|
|
8393
|
-
## Uploading
|
|
8393
|
+
## Uploading to Replicas
|
|
8394
8394
|
|
|
8395
8395
|
\`\`\`bash
|
|
8396
8396
|
replicas media upload <path-to-file> [<path-to-file> ...]
|
|
@@ -8400,47 +8400,185 @@ Pass one or more file paths. Uploading several files in a single invocation is p
|
|
|
8400
8400
|
|
|
8401
8401
|
For each file, the CLI prints two lines:
|
|
8402
8402
|
|
|
8403
|
-
1. \`\` \u2014 the chat embed (renders inline in Replicas chat only
|
|
8403
|
+
1. \`\` \u2014 the chat embed (renders inline in Replicas chat **only** \u2014 see below).
|
|
8404
8404
|
2. \`View in Replicas: <deep-link>\` \u2014 a per-file dashboard URL of the form \`https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>\` that opens directly to that specific file.
|
|
8405
8405
|
|
|
8406
8406
|
Match each "View in Replicas" line to the embed line directly above it \u2014 that's the deep link for that file.
|
|
8407
8407
|
|
|
8408
|
-
##
|
|
8408
|
+
## The two URLs the CLI gives you \u2014 and where each one is allowed
|
|
8409
8409
|
|
|
8410
|
-
|
|
8410
|
+
| URL | What it is | Where it's allowed |
|
|
8411
|
+
|---|---|---|
|
|
8412
|
+
| \`https://api.tryreplicas.com/v1/media/<id>\` (inside \`\`) | Authenticated API redirect to a presigned blob \u2014 requires the Replicas chat session | **Only** in the Replicas chat reply. Nowhere else. |
|
|
8413
|
+
| \`https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>\` | Public dashboard deep link to the media tab, scrolled to that specific file | Everywhere external \u2014 Slack, GitHub, Linear, PR bodies, comments, emails. |
|
|
8411
8414
|
|
|
8412
|
-
|
|
8415
|
+
### NEVER link the API redirect URL outside the Replicas chat reply
|
|
8413
8416
|
|
|
8414
|
-
**
|
|
8417
|
+
The \`api.tryreplicas.com/v1/media/<id>\` URL is **not public**. It's an authenticated redirect that only resolves to a presigned download when the Replicas chat session token is present. Anywhere else (Slack, Linear, GitHub, a browser tab the user opens directly, a customer copy-pasting from chat) it returns \`{"error":"Missing authorization token"}\` and renders as a broken image.
|
|
8415
8418
|
|
|
8416
|
-
|
|
8419
|
+
This rule has no exceptions:
|
|
8420
|
+
- \u274C Never paste it in a Slack message \u2014 upload the actual bytes via the 3-step \`files.getUploadURLExternal\` \u2192 POST bytes \u2192 \`files.completeUploadExternal\` flow instead (see below).
|
|
8421
|
+
- \u274C Never paste it in a GitHub PR description, issue body, review comment, or commit message.
|
|
8422
|
+
- \u274C Never paste it in a Linear issue body or comment \u2014 upload via Linear's \`fileUpload\` mutation instead (see below).
|
|
8423
|
+
- \u274C Never link to it from any external doc, email, or external chat.
|
|
8424
|
+
- \u274C Never include it as a "backup link" in case the dashboard link breaks \u2014 it will always break externally.
|
|
8417
8425
|
|
|
8418
|
-
|
|
8426
|
+
### ALWAYS link the dashboard URL \u2014 never the API URL \u2014 when referencing media externally
|
|
8427
|
+
|
|
8428
|
+
When you reference an uploaded file from anywhere outside the Replicas chat reply, the link must be the dashboard form:
|
|
8419
8429
|
|
|
8420
|
-
\`\`\`
|
|
8421
|
-
|
|
8430
|
+
\`\`\`
|
|
8431
|
+
https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>
|
|
8422
8432
|
\`\`\`
|
|
8423
8433
|
|
|
8424
|
-
|
|
8434
|
+
Both query params are required:
|
|
8435
|
+
- \`mode=media\` opens the media tab in the dashboard.
|
|
8436
|
+
- \`media=<media-id>\` scrolls to and opens that specific file.
|
|
8425
8437
|
|
|
8426
|
-
|
|
8438
|
+
Never link \`tryreplicas.com/workspaces/<id>?mode=media\` without the \`media=<id>\` param when you have a specific file in mind \u2014 that lands on the gallery, not the file. Never link the bare workspace URL.
|
|
8427
8439
|
|
|
8428
|
-
|
|
8429
|
-
- **Media tab link** (no \`media=\` param): \`...?mode=media\` opens the workspace's media tab listing all files. Use this only when you're pointing at the collection, not a specific file (rare \u2014 you almost always have a specific file in mind).
|
|
8440
|
+
Always render as a markdown / mrkdwn hyperlink labeled **View in Replicas** \u2014 never paste a raw URL.
|
|
8430
8441
|
|
|
8431
|
-
|
|
8442
|
+
## In your Replicas chat reply
|
|
8432
8443
|
|
|
8433
8444
|
Include each markdown embed line **verbatim** where you want that file to render inline. The chat substitutes each one with an embedded image, video, or audio player. Multiple embeds can appear in a single reply.
|
|
8434
8445
|
|
|
8435
|
-
After (or alongside) the embeds, include a \`[View in Replicas](<deep-link>)\` hyperlink for each file using the per-file URL the CLI
|
|
8446
|
+
After (or alongside) the embeds, include a \`[View in Replicas](<deep-link>)\` hyperlink for each file using the per-file dashboard URL from the CLI. This lets the user jump to the specific item in the media tab.
|
|
8447
|
+
|
|
8448
|
+
## On external platforms \u2014 upload natively AND link the dashboard
|
|
8449
|
+
|
|
8450
|
+
Sharing media externally is a **two-step requirement** for every file:
|
|
8451
|
+
|
|
8452
|
+
1. **Upload the raw bytes natively to that platform** so the recipient sees the media embedded inline in the message itself.
|
|
8453
|
+
2. **Link the Replicas dashboard deep link** (\`?mode=media&media=<id>\` form) so the user can jump straight to the workspace.
|
|
8454
|
+
|
|
8455
|
+
A link alone is not enough. A native upload alone is not enough. Do both.
|
|
8456
|
+
|
|
8457
|
+
The one exception is GitHub, which has no public image upload API \u2014 there, the dashboard link is the only option (see below).
|
|
8458
|
+
|
|
8459
|
+
### Slack \u2014 embed natively via the 3-step external file upload flow
|
|
8460
|
+
|
|
8461
|
+
A Slack message that just contains a \`tryreplicas.com\` link is not acceptable when the message is supposed to show an image. The recipient should see the image inline in the thread.
|
|
8436
8462
|
|
|
8437
|
-
|
|
8463
|
+
Slack deprecated the single-shot \`files.upload\` endpoint. The raw HTTP replacement is a 3-step flow: reserve an upload URL with \`files.getUploadURLExternal\`, POST the bytes to it, then share into the channel/thread with \`files.completeUploadExternal\`. (\`files.uploadV2\` is **only** an SDK convenience wrapper \u2014 it is NOT a real Web API HTTP endpoint and \`POST https://slack.com/api/files.uploadV2\` will return \`unknown_method\`.)
|
|
8438
8464
|
|
|
8439
|
-
|
|
8465
|
+
\`\`\`bash
|
|
8466
|
+
FILE=/abs/path/to/screenshot.png
|
|
8467
|
+
FILENAME=$(basename "$FILE")
|
|
8468
|
+
LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
8469
|
+
|
|
8470
|
+
# 1. Reserve an upload URL + file ID.
|
|
8471
|
+
RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
|
|
8472
|
+
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
|
|
8473
|
+
--data-urlencode "filename=$FILENAME" \\
|
|
8474
|
+
--data-urlencode "length=$LENGTH")
|
|
8475
|
+
UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
|
|
8476
|
+
FILE_ID=$(echo "$RESERVE" | jq -r '.file_id')
|
|
8477
|
+
|
|
8478
|
+
# 2. POST the raw bytes to the reserved URL.
|
|
8479
|
+
# Do not use -F / multipart here \u2014 the presigned URL expects the bytes
|
|
8480
|
+
# directly in the request body.
|
|
8481
|
+
curl -s -X POST "$UPLOAD_URL" \\
|
|
8482
|
+
-H "Content-Type: application/octet-stream" \\
|
|
8483
|
+
--data-binary @"$FILE"
|
|
8484
|
+
|
|
8485
|
+
# 3. Complete the upload, sharing it into the channel/thread with the dashboard link.
|
|
8486
|
+
curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
|
|
8487
|
+
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
|
|
8488
|
+
-H "Content-Type: application/json; charset=utf-8" \\
|
|
8489
|
+
-d "{
|
|
8490
|
+
\\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"Screenshot\\"}],
|
|
8491
|
+
\\"channel_id\\": \\"CHANNEL_ID\\",
|
|
8492
|
+
\\"thread_ts\\": \\"THREAD_TS\\",
|
|
8493
|
+
\\"initial_comment\\": \\"<https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>|View in Replicas>\\"
|
|
8494
|
+
}"
|
|
8495
|
+
\`\`\`
|
|
8440
8496
|
|
|
8441
|
-
|
|
8497
|
+
Notes:
|
|
8498
|
+
- All three steps are required; do not try to POST to \`https://slack.com/api/files.uploadV2\` \u2014 that endpoint does not exist on the Web API.
|
|
8499
|
+
- \`initial_comment\` uses Slack mrkdwn (\`<url|label>\`), not GitHub-flavored markdown.
|
|
8500
|
+
- Omit \`thread_ts\` only when you genuinely want a top-level channel post.
|
|
8501
|
+
- For multiple files in the same message, run steps 1\u20132 per file and pass all \`{id, title}\` objects in the \`files\` array of a single \`files.completeUploadExternal\` call \u2014 they share into the thread together.
|
|
8502
|
+
- If you also need to post a separate text reply in the thread, send it with \`chat.postMessage\` after the upload \u2014 but the upload itself must carry the image.
|
|
8442
8503
|
|
|
8443
|
-
|
|
8504
|
+
Never paste the \`api.tryreplicas.com/v1/media/<id>\` URL into a Slack message body or \`initial_comment\` \u2014 it will render as a broken image attempt.
|
|
8505
|
+
|
|
8506
|
+
### Linear \u2014 embed natively via the GraphQL \`fileUpload\` mutation
|
|
8507
|
+
|
|
8508
|
+
Linear comments and issue bodies support markdown image embeds, but the image URL must be publicly accessible \u2014 so you upload the file to Linear's storage first, then reference the returned \`assetUrl\` in markdown. Three steps:
|
|
8509
|
+
|
|
8510
|
+
Use \`jq\` to build the JSON bodies \u2014 the GraphQL variables (\`size\`, \`filename\`, the comment body) need to be real JSON values, not unquoted placeholders, and \`jq -n --argjson / --arg\` is the safest way to interpolate shell values without quoting bugs.
|
|
8511
|
+
|
|
8512
|
+
\`\`\`bash
|
|
8513
|
+
FILE=/abs/path/to/screenshot.png
|
|
8514
|
+
FILENAME=$(basename "$FILE")
|
|
8515
|
+
SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
8516
|
+
CONTENT_TYPE=image/png
|
|
8517
|
+
ISSUE_UUID=... # the Linear issue's UUID
|
|
8518
|
+
WORKSPACE_ID=... # the Replicas workspace ID
|
|
8519
|
+
MEDIA_ID=... # the media ID printed by \`replicas media upload\`
|
|
8520
|
+
|
|
8521
|
+
# 1. Ask Linear for an upload URL + assetUrl.
|
|
8522
|
+
RESERVE=$(curl -s -X POST https://api.linear.app/graphql \\
|
|
8523
|
+
-H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
|
|
8524
|
+
-H "Content-Type: application/json" \\
|
|
8525
|
+
-d "$(jq -n \\
|
|
8526
|
+
--argjson size "$SIZE" \\
|
|
8527
|
+
--arg contentType "$CONTENT_TYPE" \\
|
|
8528
|
+
--arg filename "$FILENAME" \\
|
|
8529
|
+
'{
|
|
8530
|
+
query: "mutation($size: Int!, $contentType: String!, $filename: String!) { fileUpload(size: $size, contentType: $contentType, filename: $filename) { uploadFile { uploadUrl assetUrl headers { key value } } } }",
|
|
8531
|
+
variables: { size: $size, contentType: $contentType, filename: $filename }
|
|
8532
|
+
}')")
|
|
8533
|
+
UPLOAD_URL=$(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.uploadUrl')
|
|
8534
|
+
ASSET_URL=$(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.assetUrl')
|
|
8535
|
+
|
|
8536
|
+
# 2. PUT the bytes to uploadUrl, replaying every header Linear returned.
|
|
8537
|
+
# Linear's presigned URL requires the exact Content-Type / Cache-Control /
|
|
8538
|
+
# etc. it gave you back, so forward each {key, value} from the headers array.
|
|
8539
|
+
HEADER_ARGS=()
|
|
8540
|
+
while IFS=$'\\t' read -r k v; do
|
|
8541
|
+
HEADER_ARGS+=(-H "$k: $v")
|
|
8542
|
+
done < <(echo "$RESERVE" | jq -r '.data.fileUpload.uploadFile.headers[] | "\\(.key)\\t\\(.value)"')
|
|
8543
|
+
|
|
8544
|
+
curl -s -X PUT "$UPLOAD_URL" \\
|
|
8545
|
+
"\${HEADER_ARGS[@]}" \\
|
|
8546
|
+
--data-binary @"$FILE"
|
|
8547
|
+
|
|
8548
|
+
# 3. Reference assetUrl inline in the comment body, alongside the dashboard link.
|
|
8549
|
+
BODY=$(printf '\\n\\n[View in Replicas](https://tryreplicas.com/workspaces/%s?mode=media&media=%s)' \\
|
|
8550
|
+
"$ASSET_URL" "$WORKSPACE_ID" "$MEDIA_ID")
|
|
8551
|
+
|
|
8552
|
+
curl -s -X POST https://api.linear.app/graphql \\
|
|
8553
|
+
-H "Authorization: Bearer $LINEAR_ACCESS_TOKEN" \\
|
|
8554
|
+
-H "Content-Type: application/json" \\
|
|
8555
|
+
-d "$(jq -n \\
|
|
8556
|
+
--arg issueId "$ISSUE_UUID" \\
|
|
8557
|
+
--arg body "$BODY" \\
|
|
8558
|
+
'{
|
|
8559
|
+
query: "mutation($issueId: String!, $body: String!) { commentCreate(input: { issueId: $issueId, body: $body }) { success } }",
|
|
8560
|
+
variables: { issueId: $issueId, body: $body }
|
|
8561
|
+
}')"
|
|
8562
|
+
\`\`\`
|
|
8563
|
+
|
|
8564
|
+
The same flow works for issue bodies (use \`issueCreate\` / \`issueUpdate\` with the same markdown body).
|
|
8565
|
+
|
|
8566
|
+
Never paste the \`api.tryreplicas.com/v1/media/<id>\` URL into a Linear body or comment \u2014 it will render as a broken image to anyone outside your Replicas chat.
|
|
8567
|
+
|
|
8568
|
+
### GitHub \u2014 link the dashboard deep link (no public upload API exists)
|
|
8569
|
+
|
|
8570
|
+
GitHub has **no public API** for uploading images to PRs or issues. Their web UI uses an undocumented internal endpoint that's not available to API clients. So for GitHub specifically, the only correct way to share media is the dashboard deep link, rendered as a markdown hyperlink:
|
|
8571
|
+
|
|
8572
|
+
\`\`\`markdown
|
|
8573
|
+
[View in Replicas](https://tryreplicas.com/workspaces/<workspace-id>?mode=media&media=<media-id>)
|
|
8574
|
+
\`\`\`
|
|
8575
|
+
|
|
8576
|
+
Do **not**:
|
|
8577
|
+
- Commit screenshots as files to the repo as a workaround.
|
|
8578
|
+
- Use placeholder image URLs.
|
|
8579
|
+
- Embed the \`api.tryreplicas.com/v1/media/<id>\` URL in markdown \u2014 it renders as a broken image for every viewer.
|
|
8580
|
+
|
|
8581
|
+
This applies to PR descriptions, PR review comments, issue bodies, issue comments, and commit messages.
|
|
8444
8582
|
|
|
8445
8583
|
## Recording defaults
|
|
8446
8584
|
|
|
@@ -8861,14 +8999,42 @@ curl -s "https://slack.com/api/search.messages?query=YOUR_SEARCH_QUERY" \\
|
|
|
8861
8999
|
|
|
8862
9000
|
### Uploading Files
|
|
8863
9001
|
|
|
9002
|
+
Slack deprecated \`files.upload\`; the raw HTTP replacement is a 3-step flow. (\`files.uploadV2\` is **only** an SDK convenience wrapper and is NOT a real Web API HTTP endpoint \u2014 \`POST https://slack.com/api/files.uploadV2\` returns \`unknown_method\`.)
|
|
9003
|
+
|
|
8864
9004
|
\`\`\`bash
|
|
8865
|
-
|
|
9005
|
+
FILE=/path/to/file
|
|
9006
|
+
FILENAME=$(basename "$FILE")
|
|
9007
|
+
LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
|
|
9008
|
+
|
|
9009
|
+
# 1. Reserve an upload URL + file ID.
|
|
9010
|
+
RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
|
|
8866
9011
|
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
|
|
8867
|
-
-
|
|
8868
|
-
-
|
|
8869
|
-
|
|
9012
|
+
--data-urlencode "filename=$FILENAME" \\
|
|
9013
|
+
--data-urlencode "length=$LENGTH")
|
|
9014
|
+
UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
|
|
9015
|
+
FILE_ID=$(echo "$RESERVE" | jq -r '.file_id')
|
|
9016
|
+
|
|
9017
|
+
# 2. POST the raw bytes to the reserved URL.
|
|
9018
|
+
# Do not use -F / multipart here \u2014 the presigned URL expects the bytes
|
|
9019
|
+
# directly in the request body.
|
|
9020
|
+
curl -s -X POST "$UPLOAD_URL" \\
|
|
9021
|
+
-H "Content-Type: application/octet-stream" \\
|
|
9022
|
+
--data-binary @"$FILE"
|
|
9023
|
+
|
|
9024
|
+
# 3. Complete the upload and share into a channel (and optionally a thread).
|
|
9025
|
+
curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
|
|
9026
|
+
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \\
|
|
9027
|
+
-H "Content-Type: application/json; charset=utf-8" \\
|
|
9028
|
+
-d "{
|
|
9029
|
+
\\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"File title\\"}],
|
|
9030
|
+
\\"channel_id\\": \\"CHANNEL_ID\\",
|
|
9031
|
+
\\"thread_ts\\": \\"OPTIONAL_THREAD_TS\\",
|
|
9032
|
+
\\"initial_comment\\": \\"Optional message body\\"
|
|
9033
|
+
}"
|
|
8870
9034
|
\`\`\`
|
|
8871
9035
|
|
|
9036
|
+
Omit \`thread_ts\` and/or \`initial_comment\` if you don't need them.
|
|
9037
|
+
|
|
8872
9038
|
### Other Operations
|
|
8873
9039
|
|
|
8874
9040
|
You can list channels, read channel history, add reactions, and perform any other operation supported by the Slack Web API using the same authentication pattern.
|
|
@@ -8933,7 +9099,7 @@ var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
|
8933
9099
|
var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
|
|
8934
9100
|
|
|
8935
9101
|
// ../shared/src/cli-version.ts
|
|
8936
|
-
var CLI_VERSION = "0.2.
|
|
9102
|
+
var CLI_VERSION = "0.2.226";
|
|
8937
9103
|
|
|
8938
9104
|
// ../shared/src/engine/environment.ts
|
|
8939
9105
|
var DESKTOP_NOVNC_PORT = 6080;
|
|
@@ -9038,6 +9204,7 @@ function workspaceConfigWithPrFollowups(config2, prFollowups = config2?.capabili
|
|
|
9038
9204
|
var WORKSPACE_FILE_UPLOAD_MAX_SIZE_BYTES = 20 * 1024 * 1024;
|
|
9039
9205
|
var WORKSPACE_FILE_CONTENT_MAX_SIZE_BYTES = 1 * 1024 * 1024;
|
|
9040
9206
|
var WORKSPACE_SIDEBAR_VIEWS = ["owned", "shared", "team", "automation", "integrations", "api"];
|
|
9207
|
+
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
9041
9208
|
|
|
9042
9209
|
// ../shared/src/audit-log.ts
|
|
9043
9210
|
var AUDIT_LOG_ACTION = {
|