replicas-cli 0.2.492 → 0.2.493

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 +258 -590
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8527,7 +8527,7 @@ var DOCKER_ABILITY = {
8527
8527
 
8528
8528
  // ../shared/src/default-skills/replicas-agent/abilities/github.ts
8529
8529
  var SECTION3 = `### GitHub
8530
- Use the pre-authenticated \`gh\` CLI for pull requests, issues, actions, and API calls.
8530
+ Use the pre-authenticated \`gh\` CLI for repository workflows and the workspace-scoped TypeScript SDK for GitHub API calls.
8531
8531
 
8532
8532
  **Reference:** \`references/GITHUB.md\`
8533
8533
 
@@ -8538,7 +8538,7 @@ Use this when:
8538
8538
  - You need to include images in PR descriptions`;
8539
8539
  var REFERENCE3 = `# GitHub Integration
8540
8540
 
8541
- This guide covers how to interact with GitHub from within your Replicas workspace.
8541
+ This guide covers how to interact with GitHub from within your Replicas workspace. Prefer \`@replicas/sdk\` for API calls so batching and data processing stay in one TypeScript program. The \`gh\` CLI remains useful for ergonomic pull request and git-adjacent workflows.
8542
8542
 
8543
8543
  ## Prerequisites
8544
8544
 
@@ -8623,17 +8623,21 @@ gh run rerun RUN_ID --failed
8623
8623
 
8624
8624
  ### GitHub API (Advanced)
8625
8625
 
8626
- For operations not covered by \`gh\` subcommands, use the API directly:
8626
+ For operations not covered by \`gh\` subcommands, use the scoped SDK. Pass only a relative GitHub API path:
8627
8627
 
8628
- \`\`\`bash
8629
- # GET request
8630
- gh api repos/owner/repo/pulls/123/comments
8628
+ \`\`\`ts
8629
+ import { replicas } from '@replicas/sdk';
8631
8630
 
8632
- # POST request
8633
- gh api repos/owner/repo/issues/123/comments -f body="Comment text"
8631
+ const comments = await replicas.github.request('/repos/owner/repo/pulls/123/comments');
8632
+ await replicas.github.request('/repos/owner/repo/issues/123/comments', {
8633
+ method: 'POST',
8634
+ body: { body: 'Comment text' },
8635
+ });
8634
8636
 
8635
- # GraphQL query
8636
- gh api graphql -f query='{ repository(owner: "owner", name: "repo") { issues(first: 10) { nodes { title number } } } }'
8637
+ const result = await replicas.github.request('/graphql', {
8638
+ method: 'POST',
8639
+ body: { query: '{ viewer { login } }' },
8640
+ });
8637
8641
  \`\`\`
8638
8642
 
8639
8643
  ### Working with PR Reviews
@@ -8663,7 +8667,7 @@ GitHub does NOT have a public API for uploading images to PRs/issues. When you n
8663
8667
  `;
8664
8668
  var GITHUB_ABILITY = {
8665
8669
  label: "GitHub",
8666
- description: "Pre-authenticated `gh` CLI for PRs, issues, releases, and GraphQL.",
8670
+ description: "GitHub workflows through gh and API calls through @replicas/sdk.",
8667
8671
  bullet: "- Interacting with GitHub (creating PRs, managing issues, using the API, etc.)",
8668
8672
  section: SECTION3,
8669
8673
  referenceFile: { name: "GITHUB.md", content: REFERENCE3 }
@@ -8671,124 +8675,61 @@ var GITHUB_ABILITY = {
8671
8675
 
8672
8676
  // ../shared/src/default-skills/replicas-agent/abilities/gitlab.ts
8673
8677
  var SECTION4 = `### GitLab
8674
- Workspace repos hosted on GitLab use pre-configured git credentials \u2014 push, pull, and open merge requests with plain \`git\`.
8678
+ Use plain git for repository traffic and the workspace-scoped TypeScript SDK for GitLab API operations.
8675
8679
 
8676
8680
  **Reference:** \`references/GITLAB.md\`
8677
8681
 
8678
8682
  Use this when:
8679
- - A repo's remote is on gitlab.com or a self-managed GitLab instance
8680
- - You need to open or update a merge request`;
8683
+ - A repository remote is on gitlab.com or a self-managed GitLab instance
8684
+ - You need to open or update a merge request
8685
+ - You need GitLab issues, pipelines, comments, or other API data`;
8681
8686
  var REFERENCE4 = `# GitLab Integration
8682
8687
 
8683
- This guide covers how to work with GitLab-hosted repositories from within your Replicas workspace.
8684
-
8685
- ## Prerequisites
8686
-
8687
- Git credentials for the workspace's GitLab hosts are pre-configured in \`~/.git-credentials\` and refreshed automatically. Plain \`git fetch\` / \`git pull\` / \`git push\` over HTTPS work with no additional setup.
8688
-
8689
- - Never ask the user for a GitLab token or PAT \u2014 credentials are already wired. If a push fails with an authentication error, report it to the user instead of working around it.
8690
- - A workspace can hold credentials for several GitLab hosts, and \`origin\` is whatever the repo says it is. Always select the token by the host you are about to call, as the snippets below do. Grabbing the first entry in \`~/.git-credentials\` can send one host's token to another.
8691
- - There is no \`glab\` CLI in the workspace, and \`gh\` only works for GitHub remotes. Check a repo's host with \`git remote get-url origin\` before choosing the GitHub or GitLab workflow.
8692
-
8693
- ### Reading the credential for a repo
8688
+ Git credentials are preconfigured for fetch, pull, and push. Use \`@replicas/sdk\` for API traffic; never inspect \`~/.git-credentials\`, request a token, or send a credential with curl.
8694
8689
 
8695
- A workspace can hold tokens for several GitLab hosts, so always ask git for the
8696
- credential belonging to the host you are about to call. Never grep
8697
- \`~/.git-credentials\` yourself: taking the first line sends one instance's token to
8698
- another, and interpolating a host into a grep pattern makes it a regular
8699
- expression. \`git credential fill\` matches the host exactly and returns nothing
8700
- when there is no credential for it:
8690
+ ## Merge requests
8701
8691
 
8702
- \`\`\`bash
8703
- HOST=$(git remote get-url origin | sed -E 's#^[a-z]+://##; s#^[^@/]*@##; s#/.*##; s#:[^0-9].*##')
8704
- TOKEN=$(printf 'protocol=https\\nhost=%s\\n\\n' "$HOST" | GIT_TERMINAL_PROMPT=0 git credential fill | sed -n 's/^password=//p')
8705
- [ -n "$TOKEN" ] || { echo "no credential for $HOST"; exit 1; }
8706
- \`\`\`
8707
-
8708
- Every recipe below repeats these two lines so each block runs on its own, and
8709
- every one calls \`https://$HOST\`, so the token only ever reaches the host it
8710
- belongs to. Run them inside the repo whose API you are calling. An empty
8711
- \`$TOKEN\` means the workspace has no credential for that host. Report that rather
8712
- than reaching for another one.
8713
-
8714
- ## Merge Requests
8715
-
8716
- Create a merge request directly from a push using push options:
8692
+ Create a merge request directly from a push:
8717
8693
 
8718
8694
  \`\`\`bash
8719
8695
  git push -o merge_request.create -o merge_request.target=<default-branch> -o merge_request.title="Title" origin HEAD
8720
8696
  \`\`\`
8721
8697
 
8722
- Useful options:
8698
+ Useful options are \`-o merge_request.draft\` and \`-o merge_request.remove_source_branch\`. GitLab prints the merge request URL.
8723
8699
 
8724
- \`\`\`bash
8725
- -o merge_request.draft # open as draft
8726
- -o merge_request.remove_source_branch # delete branch on merge
8727
- \`\`\`
8700
+ ## API requests
8728
8701
 
8729
- GitLab prints the MR URL in the push output \u2014 include it in your reply to the user.
8702
+ Pass a relative path below \`/api/v4\`. Replicas selects the credential only from GitLab hosts attached to the workspace repositories.
8730
8703
 
8731
- ### Setting the description
8704
+ \`\`\`ts
8705
+ import { replicas } from '@replicas/sdk';
8732
8706
 
8733
- Do **not** pass the description as a push option. Push option values are shell
8734
- arguments on one line, so a real description \u2014 headings, lists, the Replicas
8735
- footer HTML \u2014 gets mangled or truncated. Write the body to a file and PUT it as
8736
- JSON instead, which preserves it exactly:
8707
+ const project = encodeURIComponent('group/project');
8708
+ const mergeRequests = await replicas.gitlab.request(
8709
+ \`/projects/\${project}/merge_requests?state=opened\`,
8710
+ );
8737
8711
 
8738
- \`\`\`bash
8739
- HOST=$(git remote get-url origin | sed -E 's#^[a-z]+://##; s#^[^@/]*@##; s#/.*##; s#:[^0-9].*##')
8740
- TOKEN=$(printf 'protocol=https\\nhost=%s\\n\\n' "$HOST" | GIT_TERMINAL_PROMPT=0 git credential fill | sed -n 's/^password=//p')
8741
- PROJECT=$(python3 -c 'import urllib.parse; print(urllib.parse.quote("group/project", safe=""))')
8742
- cat > /tmp/mr-body.md <<'EOF'
8743
- ## Summary
8744
- ...your full description, ending with the Replicas footer...
8745
- EOF
8746
- jq -Rs '{description: .}' /tmp/mr-body.md > /tmp/mr-body.json
8747
- curl -sS --request PUT \\
8748
- --header "Authorization: Bearer $TOKEN" \\
8749
- --header "Content-Type: application/json" \\
8750
- --data @/tmp/mr-body.json \\
8751
- "https://$HOST/api/v4/projects/$PROJECT/merge_requests/<iid>"
8712
+ await replicas.gitlab.request(\`/projects/\${project}/issues/42/notes\`, {
8713
+ method: 'POST',
8714
+ body: { body: 'Update from Replicas' },
8715
+ });
8752
8716
  \`\`\`
8753
8717
 
8754
- Use the same command to edit a description later. Editing replaces the whole
8755
- body, so re-include the Replicas footer every time \u2014 it is how merge requests
8756
- opened through Replicas are counted.
8757
-
8758
- ## GitLab API (advanced)
8759
-
8760
- For operations with no git equivalent (commenting on MRs, reading pipelines), call the REST API with the workspace credential:
8718
+ When a workspace contains repositories from more than one GitLab host, pass the exact repository host:
8761
8719
 
8762
- \`\`\`bash
8763
- HOST=$(git remote get-url origin | sed -E 's#^[a-z]+://##; s#^[^@/]*@##; s#/.*##; s#:[^0-9].*##')
8764
- TOKEN=$(printf 'protocol=https\\nhost=%s\\n\\n' "$HOST" | GIT_TERMINAL_PROMPT=0 git credential fill | sed -n 's/^password=//p')
8765
- curl -s -H "Authorization: Bearer $TOKEN" "https://$HOST/api/v4/projects/<url-encoded-path>/merge_requests"
8720
+ \`\`\`ts
8721
+ await replicas.gitlab.request('/projects/group%2Frepo/pipelines', {
8722
+ host: 'gitlab.example.com',
8723
+ });
8766
8724
  \`\`\`
8767
8725
 
8768
- This works for gitlab.com and self-managed instances alike, because the base URL
8769
- and the token both come from the repo's own host.
8770
-
8771
- ## Inline media in merge requests
8772
-
8773
- GitLab provides a supported project Markdown uploads API. Upload media to Replicas first, then upload the same bytes natively so repository permissions protect the asset:
8726
+ ## Descriptions and media
8774
8727
 
8775
- \`\`\`bash
8776
- FILE=/abs/path/to/screenshot.png
8777
- HOST=$(git remote get-url origin | sed -E 's#^[a-z]+://##; s#^[^@/]*@##; s#/.*##; s#:[^0-9].*##')
8778
- PROJECT=$(python3 -c 'import urllib.parse; print(urllib.parse.quote("group/project", safe=""))')
8779
- TOKEN=$(printf 'protocol=https\\nhost=%s\\n\\n' "$HOST" | GIT_TERMINAL_PROMPT=0 git credential fill | sed -n 's/^password=//p')
8780
- UPLOAD=$(curl -sS --request POST \\
8781
- --header "Authorization: Bearer $TOKEN" \\
8782
- --form "file=@$FILE" \\
8783
- "https://$HOST/api/v4/projects/$PROJECT/uploads")
8784
- echo "$UPLOAD" | jq -r .markdown
8785
- \`\`\`
8786
-
8787
- Insert the returned \`markdown\` into the merge request description or comment and add the media's **View in Replicas** dashboard link. Images render inline; MP4, MOV, and WebM render as inline video players. Do not create a public Replicas forge share when this native upload succeeds.
8728
+ API updates replace the entire merge request description, so always preserve the required Replicas footer and co-author trailers. For media, first run \`replicas media upload\` as documented in \`MEDIA.md\`; use GitLab's project uploads endpoint only when a native repository-protected embed is required.
8788
8729
  `;
8789
8730
  var GITLAB_ABILITY = {
8790
8731
  label: "GitLab",
8791
- description: "Pre-configured git credentials for GitLab repos; merge requests via push options.",
8732
+ description: "Git for repository traffic and @replicas/sdk for the GitLab API.",
8792
8733
  bullet: "- Interacting with GitLab (pushing to GitLab repos, opening merge requests)",
8793
8734
  section: SECTION4,
8794
8735
  referenceFile: { name: "GITLAB.md", content: REFERENCE4 }
@@ -8796,332 +8737,67 @@ var GITLAB_ABILITY = {
8796
8737
 
8797
8738
  // ../shared/src/default-skills/replicas-agent/abilities/google.ts
8798
8739
  var SECTION5 = `### Google Workspace and Search Console
8799
- Create and edit Google Docs, Sheets, and Forms, and read Google Search Console data via the Replicas gateway. Drive access is limited to files created by Replicas.
8740
+ Create and edit Docs, Sheets, and Forms, manage Replicas-created Drive files, and read Search Console through the workspace-scoped TypeScript SDK.
8800
8741
 
8801
8742
  **Reference:** \`references/GOOGLE.md\`
8802
8743
 
8803
8744
  Use this when:
8804
8745
  - You need to create or edit a Google Doc, Sheet, or Form
8805
- - You need to share, rename, move, or delete a Replicas-created Google file
8806
- - You need to read responses from a Replicas-created Google Form
8807
- - You need to list Search Console properties, query search performance, read sitemaps, or inspect an indexed URL`;
8746
+ - You need to manage a file Replicas created
8747
+ - You need Google Search Console data`;
8808
8748
  var REFERENCE5 = `# Google Workspace and Search Console
8809
8749
 
8810
- This guide covers how to create and edit Google Docs, Sheets, and Forms, perform basic Drive file operations, and read Google Search Console data from inside a Replicas workspace using the monolith as a gateway to Google's APIs.
8811
-
8812
- ## Prerequisites
8813
-
8814
- The integration is configured at the org or user level by the Replicas admin. From inside a workspace you don't have a Google access token directly; instead you call the monolith's \`/v1/gdrive/*\` endpoints, authenticated with your workspace's engine secret. The monolith refreshes the org's (or user's) Google access token and proxies the call.
8815
-
8816
- Quick check that the integration is connected:
8817
-
8818
- \`\`\`bash
8819
- curl -s -X GET "$REPLICAS_MONOLITH_URL/v1/gdrive/credentials" \\
8820
- -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
8821
- -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID"
8822
- \`\`\`
8823
-
8824
- - If \`hasCredentials\` is \`true\`: you're good to go.
8825
- - If \`hasCredentials\` is \`false\`: Google has not been connected for this org. Ask the user to go to **Settings \u2192 Integrations \u2192 Google** in the [Replicas dashboard](https://replicas.dev) and connect a Google account. Do not attempt Google operations until it's connected.
8826
-
8827
- Standard auth headers used by every call below:
8828
-
8829
- \`\`\`
8830
- Authorization: Bearer $REPLICAS_ENGINE_SECRET
8831
- X-Workspace-Id: $REPLICAS_WORKSPACE_ID
8832
- \`\`\`
8833
-
8834
- For brevity the examples below use a shell variable:
8835
-
8836
- \`\`\`bash
8837
- GDRIVE_AUTH=(-H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID")
8838
- \`\`\`
8839
-
8840
- ## Important constraint: drive.file scope
8841
-
8842
- The integration uses the **sensitive-tier \`drive.file\` scope**. That means Replicas can only read and edit Google files **it created itself**. It **cannot**:
8843
-
8844
- - Read or edit a user's pre-existing Google Docs, Sheets, or Forms \u2014 even ones that were shared with the connected Google account.
8845
- - List or search the user's broader Drive.
8846
- - Touch any file that was not created via these gateway endpoints.
8847
-
8848
- If the user asks you to edit an existing doc that Replicas didn't create, tell them this constraint and offer to create a new doc that mirrors what they want.
8849
-
8850
- ## Google Docs
8851
-
8852
- ### Create a new doc
8853
-
8854
- \`\`\`bash
8855
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/docs" "\${GDRIVE_AUTH[@]}" \\
8856
- -H "Content-Type: application/json" \\
8857
- -d '{"title":"Meeting notes 2026-05-14"}'
8858
- \`\`\`
8859
-
8860
- Returns the full Doc object; grab \`.documentId\` for follow-up calls.
8861
-
8862
- ### Read a doc
8863
-
8864
- \`\`\`bash
8865
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/docs/$DOC_ID" "\${GDRIVE_AUTH[@]}"
8866
- \`\`\`
8867
-
8868
- Returns the full document structure \u2014 \`body.content\` is an ordered list of structural elements (paragraphs, tables, etc.) with character indexes you can target for edits.
8869
-
8870
- ### Edit a doc (batchUpdate)
8871
-
8872
- The Docs API edits use a list of [structural requests](https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request). Insert text, then style it; or insert tables, images, page breaks, etc.
8873
-
8874
- \`\`\`bash
8875
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/docs/$DOC_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
8876
- -H "Content-Type: application/json" \\
8877
- -d '{
8878
- "requests": [
8879
- { "insertText": { "location": { "index": 1 }, "text": "Hello, world!\\n" } }
8880
- ]
8881
- }'
8882
- \`\`\`
8883
-
8884
- Common request types:
8885
-
8886
- - \`insertText\` \u2014 insert plain text at a given index
8887
- - \`deleteContentRange\` \u2014 delete a range
8888
- - \`replaceAllText\` \u2014 find-and-replace
8889
- - \`updateTextStyle\` \u2014 bold/italic/colors/fonts/sizes for a range
8890
- - \`updateParagraphStyle\` \u2014 headings (\`HEADING_1\`..\`HEADING_6\`), alignment, spacing
8891
- - \`createParagraphBullets\` \u2014 turn paragraphs into bulleted/numbered lists
8892
- - \`insertTable\` \u2014 insert a table
8893
- - \`insertInlineImage\` \u2014 insert an image from a URL
8894
-
8895
- Edits are verbose but powerful. Prefer batching many requests into a single \`batchUpdate\` call rather than making many round trips \u2014 it's faster and keeps the doc state consistent.
8896
-
8897
- ## Google Sheets
8898
-
8899
- ### Create a new spreadsheet
8900
-
8901
- \`\`\`bash
8902
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets" "\${GDRIVE_AUTH[@]}" \\
8903
- -H "Content-Type: application/json" \\
8904
- -d '{"title":"Q2 metrics"}'
8905
- \`\`\`
8906
-
8907
- Returns the full Spreadsheet object; grab \`.spreadsheetId\`.
8908
-
8909
- ### Read a range of cells
8910
-
8911
- \`\`\`bash
8912
- # Range is in A1 notation, e.g. "Sheet1!A1:C10"
8913
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:C10' | jq -sRr @uri)" \\
8914
- "\${GDRIVE_AUTH[@]}"
8915
- \`\`\`
8916
-
8917
- ### Write a range of cells
8918
-
8919
- \`\`\`bash
8920
- curl -s -X PUT \\
8921
- "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:B2' | jq -sRr @uri)?valueInputOption=USER_ENTERED" \\
8922
- "\${GDRIVE_AUTH[@]}" \\
8923
- -H "Content-Type: application/json" \\
8924
- -d '{
8925
- "range": "Sheet1!A1:B2",
8926
- "majorDimension": "ROWS",
8927
- "values": [
8928
- ["Name", "Revenue"],
8929
- ["Q1", "=SUM(B3:B100)"]
8930
- ]
8931
- }'
8932
- \`\`\`
8933
-
8934
- \`valueInputOption=USER_ENTERED\` makes formulas evaluate as if a human typed them. Use \`RAW\` to write literal strings.
8935
-
8936
- ### Bulk operations (formatting, charts, new tabs, etc.)
8937
-
8938
- \`\`\`bash
8939
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
8940
- -H "Content-Type: application/json" \\
8941
- -d '{ "requests": [ { "addSheet": { "properties": { "title": "Raw data" } } } ] }'
8942
- \`\`\`
8943
-
8944
- \`batchUpdate\` accepts an array of [Sheets API requests](https://developers.google.com/workspace/sheets/api/reference/rest/v4/spreadsheets/request) \u2014 addSheet, updateSheetProperties, repeatCell, addChart, autoResizeDimensions, etc.
8945
-
8946
- ## Google Forms
8947
-
8948
- ### Create a new form
8949
-
8950
- \`\`\`bash
8951
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/forms" "\${GDRIVE_AUTH[@]}" \\
8952
- -H "Content-Type: application/json" \\
8953
- -d '{"title":"Customer feedback"}'
8954
- \`\`\`
8955
-
8956
- Returns the form. Grab \`.formId\`.
8957
-
8958
- ### Add questions / edit form structure
8959
-
8960
- The Forms API uses its own \`batchUpdate\`:
8961
-
8962
- \`\`\`bash
8963
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/forms/$FORM_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
8964
- -H "Content-Type: application/json" \\
8965
- -d '{
8966
- "requests": [
8967
- {
8968
- "createItem": {
8969
- "item": {
8970
- "title": "How likely are you to recommend us?",
8971
- "questionItem": {
8972
- "question": {
8973
- "required": true,
8974
- "scaleQuestion": { "low": 0, "high": 10, "lowLabel": "Not at all", "highLabel": "Very likely" }
8975
- }
8976
- }
8977
- },
8978
- "location": { "index": 0 }
8979
- }
8980
- }
8981
- ]
8982
- }'
8983
- \`\`\`
8984
-
8985
- See the [Forms API Request reference](https://developers.google.com/workspace/forms/api/reference/rest/v1/forms/request) for all supported request types \u2014 text questions, multiple choice, checkboxes, scale, grid, date, time, file upload, section breaks, branching logic, quiz settings, etc.
8986
-
8987
- ### Read responses
8988
-
8989
- \`\`\`bash
8990
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/forms/$FORM_ID/responses" "\${GDRIVE_AUTH[@]}"
8991
- \`\`\`
8750
+ Use \`@replicas/sdk\`; the workspace never receives Google OAuth credentials. Personal credentials are preferred for the workspace owner, then Replicas falls back to the organization connection.
8992
8751
 
8993
- Pagination: pass \`?pageToken=...&pageSize=...\` to walk through responses.
8994
-
8995
- ## Drive operations (only on Replicas-created files)
8996
-
8997
- ### Share a file with a person
8998
-
8999
- \`\`\`bash
9000
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
9001
- -H "Content-Type: application/json" \\
9002
- -d '{
9003
- "type": "user",
9004
- "role": "writer",
9005
- "emailAddress": "alice@example.com",
9006
- "sendNotificationEmail": true
9007
- }'
9008
- \`\`\`
9009
-
9010
- Roles: \`reader\`, \`commenter\`, \`writer\`. Types: \`user\`, \`group\`, \`domain\`, \`anyone\`.
9011
-
9012
- ### Make a file viewable by anyone with the link
9013
-
9014
- \`\`\`bash
9015
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
9016
- -H "Content-Type: application/json" \\
9017
- -d '{ "type": "anyone", "role": "reader" }'
9018
- \`\`\`
9019
-
9020
- ### List existing permissions
9021
-
9022
- \`\`\`bash
9023
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}"
9024
- \`\`\`
9025
-
9026
- ### Rename / move a file
9027
-
9028
- \`\`\`bash
9029
- curl -s -X PATCH "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}" \\
9030
- -H "Content-Type: application/json" \\
9031
- -d '{"name":"Final report.docx"}'
9032
- \`\`\`
9033
-
9034
- To move into a folder, also pass \`addParents\` and \`removeParents\` as query parameters per [Drive API docs](https://developers.google.com/workspace/drive/api/reference/rest/v3/files/update).
9035
-
9036
- ### Get file metadata
9037
-
9038
- \`\`\`bash
9039
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID?fields=id,name,mimeType,webViewLink,parents,modifiedTime" \\
9040
- "\${GDRIVE_AUTH[@]}"
9041
- \`\`\`
9042
-
9043
- \`webViewLink\` is the human-shareable URL that opens in Google Docs/Sheets/Forms.
9044
-
9045
- ### Delete a file
9046
-
9047
- \`\`\`bash
9048
- curl -s -X DELETE "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}"
9049
- \`\`\`
9050
-
9051
- ### List Replicas-created files
8752
+ \`\`\`ts
8753
+ import { replicas } from '@replicas/sdk';
9052
8754
 
9053
- \`\`\`bash
9054
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files?pageSize=50" "\${GDRIVE_AUTH[@]}"
8755
+ const { native } = await replicas.integrations.list();
8756
+ if (!native.google) throw new Error('Connect Google in Replicas integrations first.');
9055
8757
  \`\`\`
9056
8758
 
9057
- Pass \`?q=...\` to filter using [Drive API search syntax](https://developers.google.com/workspace/drive/api/guides/search-files). Only files the app created or was granted access to will appear.
9058
-
9059
- ## Google Search Console (read-only)
9060
-
9061
- Search Console access uses the \`webmasters.readonly\` scope. The connected Google account must have access to the requested property. If the account was connected before this scope was added, reconnect it in **Settings \u2192 Integrations \u2192 Google** first.
9062
-
9063
- Property identifiers must be URL-encoded as query parameters. URL-prefix properties include the trailing slash (for example, \`https://example.com/\`); Domain properties use \`sc-domain:example.com\`.
9064
-
9065
- ### List accessible properties
9066
-
9067
- \`\`\`bash
9068
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/sites" "\${GDRIVE_AUTH[@]}"
9069
- \`\`\`
8759
+ Google Drive uses \`drive.file\`: Replicas can access only files it created, not pre-existing files in the account.
9070
8760
 
9071
- ### Get a property
8761
+ ## Docs
9072
8762
 
9073
- \`\`\`bash
9074
- SITE_URL=$(printf %s 'sc-domain:example.com' | jq -sRr @uri)
9075
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/site?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
9076
- \`\`\`
9077
-
9078
- ### Query search performance
9079
-
9080
- \`\`\`bash
9081
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/search-analytics/query?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}" \\
9082
- -H "Content-Type: application/json" \\
9083
- -d '{
9084
- "startDate": "2026-06-01",
9085
- "endDate": "2026-06-30",
9086
- "dimensions": ["query", "page"],
9087
- "rowLimit": 1000
9088
- }'
8763
+ \`\`\`ts
8764
+ const doc = await replicas.google.request<{ documentId: string }>('docs', {
8765
+ method: 'POST',
8766
+ body: { title: 'Meeting notes' },
8767
+ });
8768
+ await replicas.google.request(\`docs/\${doc.documentId}/batchUpdate\`, {
8769
+ method: 'POST',
8770
+ body: { requests: [{ insertText: { location: { index: 1 }, text: 'Hello\\n' } }] },
8771
+ });
9089
8772
  \`\`\`
9090
8773
 
9091
- Results contain clicks, impressions, CTR, and average position. Use \`startRow\` with \`rowLimit\` to paginate; Google returns at most 25,000 rows per request.
8774
+ ## Sheets
9092
8775
 
9093
- ### List sitemaps
9094
-
9095
- \`\`\`bash
9096
- curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/sitemaps?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
8776
+ \`\`\`ts
8777
+ const sheet = await replicas.google.request<{ spreadsheetId: string }>('sheets', {
8778
+ method: 'POST',
8779
+ body: { title: 'Q2 metrics' },
8780
+ });
8781
+ await replicas.google.request(
8782
+ \`sheets/\${sheet.spreadsheetId}/values/\${encodeURIComponent('Sheet1!A1:B2')}?valueInputOption=USER_ENTERED\`,
8783
+ { method: 'PUT', body: { values: [['Name', 'Revenue'], ['Q1', 100]] } },
8784
+ );
9097
8785
  \`\`\`
9098
8786
 
9099
- Pass a URL-encoded \`sitemapIndex\` query parameter to list sitemaps referenced by a sitemap index. To fetch one sitemap, call \`/v1/gdrive/search-console/sitemap\` with URL-encoded \`siteUrl\` and \`feedpath\` query parameters.
9100
-
9101
- ### Inspect an indexed URL
9102
-
9103
- \`\`\`bash
9104
- curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/url-inspection" "\${GDRIVE_AUTH[@]}" \\
9105
- -H "Content-Type: application/json" \\
9106
- -d '{
9107
- "inspectionUrl": "https://example.com/page",
9108
- "siteUrl": "sc-domain:example.com",
9109
- "languageCode": "en-US"
9110
- }'
9111
- \`\`\`
8787
+ ## Forms, Drive, and Search Console
9112
8788
 
9113
- URL Inspection reports the version currently in Google's index; it does not run a live URL test.
8789
+ The same method maps directly to the guarded \`/v1/gdrive/*\` routes:
9114
8790
 
9115
- ## Tips
8791
+ - \`forms\`, \`forms/:id\`, \`forms/:id/batchUpdate\`, \`forms/:id/responses\`
8792
+ - \`files\`, \`files/:id\`, \`files/:id/permissions\`
8793
+ - \`search-console/sites\`, \`search-console/search-analytics/query\`, \`search-console/sitemaps\`, \`search-console/url-inspection\`
9116
8794
 
9117
- - **Always return the \`webViewLink\`** to the user when you create or edit a file so they can open it. Get it from \`/v1/gdrive/files/$FILE_ID?fields=webViewLink\` or from \`documents.documentId\` \u2192 \`https://docs.google.com/document/d/$ID/edit\`.
9118
- - **Batch your edits.** A single \`batchUpdate\` with 20 requests beats 20 round-trips.
9119
- - **Watch error responses.** A 412 from the gateway means the org has no Google credentials connected \u2014 tell the user to connect Google in the dashboard. Other 4xx responses come straight from Google and usually explain the issue clearly.
8795
+ Batch independent reads with \`Promise.all\`; use each API's batch-update endpoint for dependent writes.
9120
8796
  `;
9121
8797
  var GOOGLE_ABILITY = {
9122
- label: "Google",
9123
- description: "Use Google Workspace and read Search Console data via the Replicas gateway.",
9124
- bullet: "- Interacting with Google Workspace or Search Console (Docs, Sheets, Forms, Drive files, search performance, sitemaps, and URL inspection)",
8798
+ label: "Google Workspace",
8799
+ description: "Use Docs, Sheets, Forms, Drive, and Search Console through @replicas/sdk.",
8800
+ bullet: "- Interacting with Google Workspace or Search Console",
9125
8801
  section: SECTION5,
9126
8802
  referenceFile: { name: "GOOGLE.md", content: REFERENCE5 }
9127
8803
  };
@@ -9155,102 +8831,63 @@ var LEARNINGS_ABILITY = {
9155
8831
 
9156
8832
  // ../shared/src/default-skills/replicas-agent/abilities/linear.ts
9157
8833
  var SECTION7 = `### Linear
9158
- Fetch issues, update state, add comments, and search via the Linear GraphQL API.
8834
+ Fetch issues, update state, add comments, and search through the workspace-scoped TypeScript SDK.
9159
8835
 
9160
8836
  **Reference:** \`references/LINEAR.md\`
9161
8837
 
9162
8838
  Use this when:
9163
8839
  - You encounter a Linear issue link and need to understand the task
9164
- - You need to update an issue's state (e.g. mark as done)
9165
- - You need to comment on or search for Linear issues`;
8840
+ - You need to update an issue's state or add a comment
8841
+ - You need to search Linear issues`;
9166
8842
  var REFERENCE7 = `# Linear Integration
9167
8843
 
9168
- This guide covers how to interact with Linear from within your Replicas workspace.
8844
+ Use \`@replicas/sdk\`; never request or handle a Linear OAuth token. Replicas refreshes the organization credential behind the gateway.
9169
8845
 
9170
- ## Prerequisites
8846
+ ## Check access
9171
8847
 
9172
- Check that the workspace has the Replicas engine credentials needed to proxy Linear requests:
9173
-
9174
- \`\`\`bash
9175
- test -n "$REPLICAS_MONOLITH_URL" && test -n "$REPLICAS_ENGINE_SECRET" && test -n "$REPLICAS_WORKSPACE_ID" && echo set
9176
- \`\`\`
9177
-
9178
- - If **set**: Use the Replicas Linear proxy below. It refreshes Linear OAuth tokens for you.
9179
- - If **not set**: The workspace cannot authenticate to Replicas. Let the user know and do not attempt Linear operations.
9180
-
9181
- Then verify Linear is connected:
9182
-
9183
- \`\`\`bash
9184
- curl -fsS -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/refresh-token" \\
9185
- -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
9186
- -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
9187
- -H "Content-Type: application/json" \\
9188
- -d '{}' >/dev/null
9189
- \`\`\`
9190
-
9191
- If this fails because no Linear credential is connected, the user needs to connect Linear in the [Replicas dashboard](https://replicas.dev) under their organization's integration settings.
9192
-
9193
- ## Using the Linear API
9194
-
9195
- Linear uses a GraphQL API. Always call it through Replicas so the access token stays fresh:
9196
-
9197
- \`\`\`bash
9198
- linear_graphql() {
9199
- curl -sS -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/graphql" \\
9200
- -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
9201
- -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
9202
- -H "Content-Type: application/json" \\
9203
- --data-binary @-
9204
- }
9205
- \`\`\`
9206
-
9207
- ### Fetching an Issue
9208
-
9209
- If you encounter a Linear issue link (e.g. \`https://linear.app/team/issue/ENG-123\`), the identifier is the last path segment (\`ENG-123\`).
9210
-
9211
- \`\`\`bash
9212
- jq -n --arg identifier "ENG-123" '{
9213
- query: "query($identifier: String!) { issue(id: $identifier) { id identifier title description state { name } assignee { name } parent { identifier title description } } }",
9214
- variables: { identifier: $identifier }
9215
- }' | linear_graphql
9216
- \`\`\`
9217
-
9218
- ### Updating Issue State
8848
+ \`\`\`ts
8849
+ import { replicas } from '@replicas/sdk';
9219
8850
 
9220
- \`\`\`bash
9221
- jq -n --arg issueId "ISSUE_UUID" --arg stateId "STATE_UUID" '{
9222
- query: "mutation($issueId: String!, $stateId: String!) { issueUpdate(id: $issueId, input: { stateId: $stateId }) { success issue { identifier state { name } } } }",
9223
- variables: { issueId: $issueId, stateId: $stateId }
9224
- }' | linear_graphql
8851
+ const { native } = await replicas.integrations.list();
8852
+ if (!native.linear) throw new Error('Connect Linear in Replicas organization integrations first.');
9225
8853
  \`\`\`
9226
8854
 
9227
- To find available states, query: \`query { workflowStates { nodes { id name } } }\`
8855
+ ## Fetch an issue
9228
8856
 
9229
- ### Adding a Comment
9230
-
9231
- \`\`\`bash
9232
- jq -n --arg issueId "ISSUE_UUID" --arg body "Your comment here" '{
9233
- query: "mutation($issueId: String!, $body: String!) { commentCreate(input: { issueId: $issueId, body: $body }) { success comment { id } } }",
9234
- variables: { issueId: $issueId, body: $body }
9235
- }' | linear_graphql
8857
+ \`\`\`ts
8858
+ const issue = await replicas.linear.graphql({
8859
+ query: \`query($identifier: String!) {
8860
+ issue(id: $identifier) {
8861
+ id identifier title description state { id name } assignee { name }
8862
+ parent { identifier title description }
8863
+ }
8864
+ }\`,
8865
+ variables: { identifier: 'ENG-123' },
8866
+ });
9236
8867
  \`\`\`
9237
8868
 
9238
- ### Searching Issues
8869
+ ## Update and comment in one script
9239
8870
 
9240
- \`\`\`bash
9241
- jq -n --arg query "search terms" '{
9242
- query: "query($query: String!) { issues(filter: { or: [{ title: { containsIgnoreCase: $query } }, { description: { containsIgnoreCase: $query } }] }, first: 10) { nodes { identifier title state { name } } } }",
9243
- variables: { query: $query }
9244
- }' | linear_graphql
8871
+ \`\`\`ts
8872
+ await replicas.linear.graphql({
8873
+ query: \`mutation($issueId: String!, $stateId: String!) {
8874
+ issueUpdate(id: $issueId, input: { stateId: $stateId }) { success }
8875
+ }\`,
8876
+ variables: { issueId, stateId },
8877
+ });
8878
+ await replicas.linear.graphql({
8879
+ query: \`mutation($issueId: String!, $body: String!) {
8880
+ commentCreate(input: { issueId: $issueId, body: $body }) { success comment { id } }
8881
+ }\`,
8882
+ variables: { issueId, body: 'Implemented in PR #123.' },
8883
+ });
9245
8884
  \`\`\`
9246
8885
 
9247
- ### Other Operations
9248
-
9249
- The Linear GraphQL API supports creating issues, managing projects, labels, cycles, and more. For the full schema and documentation, see: https://developers.linear.app/docs/graphql/working-with-the-graphql-api
8886
+ Search with \`containsIgnoreCase: $query\` filters, for example on both \`title\` and \`description\`. Batch independent queries with \`Promise.all\` to save round trips.
9250
8887
  `;
9251
8888
  var LINEAR_ABILITY = {
9252
8889
  label: "Linear",
9253
- description: "Fetch issues, post comments, update states via the Linear GraphQL API.",
8890
+ description: "Fetch issues, comment, and update state through @replicas/sdk.",
9254
8891
  bullet: "- Interacting with Linear (fetching issues, updating state, commenting, etc.)",
9255
8892
  section: SECTION7,
9256
8893
  referenceFile: { name: "LINEAR.md", content: REFERENCE7 }
@@ -9667,8 +9304,79 @@ var PREVIEWS_ABILITY = {
9667
9304
  referenceFile: { name: "PREVIEWS.md", content: REFERENCE9 }
9668
9305
  };
9669
9306
 
9307
+ // ../shared/src/default-skills/replicas-agent/abilities/plugins.ts
9308
+ var SECTION10 = `### Plugins
9309
+ Discover and execute installed Attio, Google Ads, and Stripe tools through the workspace-scoped TypeScript SDK.
9310
+
9311
+ **Reference:** \`references/PLUGINS.md\`
9312
+
9313
+ Use this when:
9314
+ - The user asks for CRM data from Attio
9315
+ - The user asks for Google Ads campaigns or reporting
9316
+ - The user asks for Stripe customers, payments, invoices, subscriptions, or balances`;
9317
+ var REFERENCE10 = `# Plugins
9318
+
9319
+ Plugins are TypeScript libraries, not MCP servers. Import \`@replicas/sdk\`; Replicas authenticates the workspace and selects only the owner\u2019s personal connection or the organization fallback. Composio credentials, sessions, and project keys are never exposed.
9320
+
9321
+ The initial plugin library is read-only. Tool discovery and execution both reject tools that are not tagged read-only.
9322
+
9323
+ ## Discover installed plugins
9324
+
9325
+ \`\`\`ts
9326
+ import { replicas } from '@replicas/sdk';
9327
+
9328
+ const plugins = await replicas.plugins.list();
9329
+ const installed = plugins.filter((plugin) => plugin.connected);
9330
+ \`\`\`
9331
+
9332
+ If a plugin is not connected, ask the user to install it under personal or organization Integrations in the Replicas dashboard.
9333
+
9334
+ ## Search, inspect, execute
9335
+
9336
+ \`\`\`ts
9337
+ const search = await replicas.plugins.search({
9338
+ plugin: 'stripe',
9339
+ query: 'list recent successful payments with customer details',
9340
+ });
9341
+
9342
+ const [tool] = search.tools;
9343
+ if (!tool) throw new Error('No matching read-only tool found');
9344
+
9345
+ const { data } = await replicas.plugins.execute({
9346
+ plugin: 'stripe',
9347
+ tool: tool.slug,
9348
+ arguments: { limit: 25 },
9349
+ });
9350
+ \`\`\`
9351
+
9352
+ Use \`replicas.plugins.describe({ plugin, tools: [slug] })\` when search returned a partial schema or before constructing unfamiliar arguments.
9353
+
9354
+ ## Batch work
9355
+
9356
+ Keep dependent operations in one TypeScript file and batch independent calls:
9357
+
9358
+ \`\`\`ts
9359
+ const results = await Promise.all(customerIds.map((customer) =>
9360
+ replicas.plugins.execute({
9361
+ plugin: 'stripe',
9362
+ tool: 'STRIPE_RETRIEVE_CUSTOMER',
9363
+ arguments: { customer },
9364
+ }),
9365
+ ));
9366
+ \`\`\`
9367
+
9368
+ Never attempt to import Composio, create a session, manage a connection, or call a provider with raw credentials. Those operations are intentionally unavailable inside the workspace.
9369
+ `;
9370
+ var PLUGINS_ABILITY = {
9371
+ label: "Plugins",
9372
+ description: "Use installed Attio, Google Ads, and Stripe tools through @replicas/sdk.",
9373
+ bullet: "- Interacting with installed plugins such as Attio, Google Ads, or Stripe",
9374
+ section: SECTION10,
9375
+ referenceFile: { name: "PLUGINS.md", content: REFERENCE10 }
9376
+ };
9377
+
9670
9378
  // ../shared/src/default-skills/replicas-agent/abilities/replicas.ts
9671
- var SECTION10 = `### Replicas (in-workspace CLI)
9379
+ var SECTION11 = `### Replicas (in-workspace CLI)
9672
9380
  Take action *with* Replicas itself \u2014 manage automations, environments (variables, files), repos, and \`replicas.json\` config \u2014 using the pre-installed, pre-authenticated \`replicas\` CLI.
9673
9381
 
9674
9382
  **Reference:** \`references/REPLICAS.md\`
@@ -9679,7 +9387,7 @@ Use this when:
9679
9387
  - The user asks "what envs / repos / automations do I have?"
9680
9388
  - The user asks you to scaffold a \`replicas.json\` / \`replicas.yaml\` in a repo
9681
9389
  - You need to run a long-lived service (dev server, daemon) \u2014 always use \`replicas service start\` so it survives workspace sleep/wake`;
9682
- var REFERENCE10 = `# Replicas (in-workspace CLI)
9390
+ var REFERENCE11 = `# Replicas (in-workspace CLI)
9683
9391
 
9684
9392
  This guide covers how to take action *with* Replicas itself from inside a Replicas workspace \u2014 managing automations, environments (and their variables/files), repos, previews, and the user's \`replicas.json\` config \u2014 using the pre-installed \`replicas\` CLI.
9685
9393
 
@@ -9906,149 +9614,107 @@ var REPLICAS_ABILITY = {
9906
9614
  description: "Teach the agent about Replicas itself \u2014 automations, environments, the in-workspace CLI.",
9907
9615
  // No bullet — help_instructions covers the `replicas` CLI surface in detail.
9908
9616
  bullet: "",
9909
- section: SECTION10,
9910
- referenceFile: { name: "REPLICAS.md", content: REFERENCE10 },
9617
+ section: SECTION11,
9618
+ referenceFile: { name: "REPLICAS.md", content: REFERENCE11 },
9911
9619
  locked: true
9912
9620
  };
9913
9621
 
9914
- // ../shared/src/default-skills/replicas-agent/abilities/slack.ts
9915
- var SECTION11 = `### Slack
9916
- Send messages, read threads, search conversations, and upload files via the Slack Web API.
9622
+ // ../shared/src/default-skills/replicas-agent/abilities/sentry.ts
9623
+ var SECTION12 = `### Sentry
9624
+ Read issues and project data through the workspace-scoped TypeScript SDK.
9917
9625
 
9918
- **Reference:** \`references/SLACK.md\`
9626
+ **Reference:** \`references/SENTRY.md\`
9919
9627
 
9920
9628
  Use this when:
9921
- - You need to send a message to a Slack channel or thread
9922
- - You need to read or fetch a Slack conversation
9923
- - You encounter a Slack message link and need to retrieve its content
9924
- - The task asks you to notify, update, or communicate via Slack`;
9925
- var REFERENCE11 = `# Slack Integration
9629
+ - You need to inspect Sentry projects or issues
9630
+ - A user asks for error-monitoring context outside a webhook-triggered task`;
9631
+ var REFERENCE12 = `# Sentry Integration
9926
9632
 
9927
- This guide covers how to interact with Slack from within your Replicas workspace.
9633
+ Use \`@replicas/sdk\`; never request or read a Sentry token. Sentry access is organization-scoped and read-only.
9928
9634
 
9929
- ## Prerequisites
9635
+ \`\`\`ts
9636
+ import { replicas } from '@replicas/sdk';
9930
9637
 
9931
- Check if the namespaced or legacy Slack token environment variable is set:
9638
+ const { native } = await replicas.integrations.list();
9639
+ if (!native.sentry) throw new Error('Connect Sentry in Replicas organization integrations first.');
9932
9640
 
9933
- \`\`\`bash
9934
- if [ -n "\${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" ]; then echo set; fi
9641
+ const issues = await replicas.sentry.request('/organizations/acme/issues/?query=is:unresolved');
9935
9642
  \`\`\`
9936
9643
 
9937
- - If **set**: Your workspace has Slack access. You can use the Slack Web API as described below.
9938
- - If **not set**: Slack has not been configured for this workspace. The user needs to connect Slack in the [Replicas dashboard](https://replicas.dev) under their organization's integration settings. Let the user know and do not attempt Slack operations.
9939
-
9940
- ## Using the Slack API
9941
-
9942
- All requests prefer \`$REPLICAS_SLACK_BOT_TOKEN\` and fall back to \`$SLACK_BOT_TOKEN\` for compatibility with older workspaces.
9943
-
9944
- ### Fetching a Thread from a Slack Link
9945
-
9946
- If you encounter a Slack message link (e.g. \`https://team.slack.com/archives/C0123ABC/p1234567890123456\`), extract the channel ID and thread timestamp:
9947
-
9948
- - **Channel ID**: The segment after \`/archives/\` (e.g. \`C0123ABC\`)
9949
- - **Thread TS**: The \`p\` value with a dot inserted before the last 6 digits (e.g. \`p1234567890123456\` -> \`1234567890.123456\`)
9644
+ Pass only a relative Sentry API path. The Replicas gateway selects the connected organization credential and rejects writes, absolute URLs, oversized responses, and long-running requests.
9645
+ `;
9646
+ var SENTRY_ABILITY = {
9647
+ label: "Sentry",
9648
+ description: "Read Sentry projects and issues through @replicas/sdk.",
9649
+ bullet: "- Interacting with Sentry (reading projects, issues, and error context)",
9650
+ section: SECTION12,
9651
+ referenceFile: { name: "SENTRY.md", content: REFERENCE12 }
9652
+ };
9950
9653
 
9951
- \`\`\`bash
9952
- curl -s "https://slack.com/api/conversations.replies?channel=CHANNEL_ID&ts=THREAD_TS" \\
9953
- -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}"
9954
- \`\`\`
9654
+ // ../shared/src/default-skills/replicas-agent/abilities/slack.ts
9655
+ var SECTION13 = `### Slack
9656
+ Send messages, read threads, search conversations, and upload files through the workspace-scoped TypeScript SDK.
9955
9657
 
9956
- ### Sending a Message
9658
+ **Reference:** \`references/SLACK.md\`
9957
9659
 
9958
- \`\`\`bash
9959
- curl -s -X POST "https://slack.com/api/chat.postMessage" \\
9960
- -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
9961
- -H "Content-Type: application/json" \\
9962
- -d '{
9963
- "channel": "CHANNEL_ID",
9964
- "text": "Your message here",
9965
- "thread_ts": "OPTIONAL_THREAD_TS"
9966
- }'
9967
- \`\`\`
9660
+ Use this when:
9661
+ - You need to send a message to a Slack channel or thread
9662
+ - You need to read or search Slack conversations
9663
+ - You encounter a Slack message link and need its full thread`;
9664
+ var REFERENCE13 = `# Slack Integration
9968
9665
 
9969
- Omit \`thread_ts\` to post a new message to the channel. Include it to reply in a thread.
9666
+ Use \`@replicas/sdk\`; never read or send a Slack token directly. The SDK calls Replicas, which selects only this workspace's organization connection.
9970
9667
 
9971
- #### Attach every new conversation
9668
+ ## Check access
9972
9669
 
9973
- Whenever you send a Slack message outside the thread that already routes to the current workspace, immediately attach the destination thread so future replies are delivered to this workspace:
9670
+ \`\`\`ts
9671
+ import { replicas } from '@replicas/sdk';
9974
9672
 
9975
- \`\`\`bash
9976
- replicas slack thread attach --channel <channel-id> --thread-ts <thread-root-ts>
9673
+ const { native } = await replicas.integrations.list();
9674
+ if (!native.slack) throw new Error('Connect Slack in Replicas organization integrations first.');
9977
9675
  \`\`\`
9978
9676
 
9979
- - For a new top-level message or DM, use the \`channel\` and \`ts\` from the successful \`chat.postMessage\` response. That message's \`ts\` is the new thread root.
9980
- - For a reply in another existing thread, use its root \`thread_ts\`, not the reply's \`ts\`.
9981
- - Do not attach the originating thread again when it already routes to the current workspace.
9982
- - Treat sending and attaching as one operation: check that both API calls succeed, and report an attachment failure instead of implying future replies will reach you.
9983
-
9984
- #### Switch a thread to an existing workspace
9677
+ ## Read a thread
9985
9678
 
9986
- When the user wants a Slack thread to continue in a particular existing workspace, resolve the target and switch the thread:
9679
+ For a link such as \`https://team.slack.com/archives/C0123ABC/p1234567890123456\`, the channel is \`C0123ABC\` and the timestamp is \`1234567890.123456\`.
9987
9680
 
9988
- \`\`\`bash
9989
- replicas list
9990
- replicas slack thread switch <workspace-id-or-name> --channel <channel-id> --thread-ts <thread-root-ts>
9681
+ \`\`\`ts
9682
+ const thread = await replicas.slack.call('conversations.replies', {
9683
+ channel: 'C0123ABC',
9684
+ ts: '1234567890.123456',
9685
+ limit: 200,
9686
+ });
9991
9687
  \`\`\`
9992
9688
 
9993
- The channel and thread flags default to \`REPLICAS_SLACK_CHANNEL_ID\` and \`REPLICAS_SLACK_THREAD_TS\` for a Slack-triggered workspace. Workspace-authenticated agents may target only their current workspace; switching to a different workspace requires running the command with user authentication outside agent mode. If that restriction applies, give the user the exact command to run rather than claiming the switch succeeded.
9689
+ ## Send and attach a message
9994
9690
 
9995
- ### Searching Messages
9996
-
9997
- \`\`\`bash
9998
- curl -s "https://slack.com/api/search.messages?query=YOUR_SEARCH_QUERY" \\
9999
- -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}"
9691
+ \`\`\`ts
9692
+ const message = await replicas.slack.call<{ channel: string; ts: string }>('chat.postMessage', {
9693
+ channel: 'C0123ABC',
9694
+ text: 'Update from Replicas',
9695
+ });
9696
+ await replicas.slack.attachThread({ channel: message.channel, threadTs: message.ts });
10000
9697
  \`\`\`
10001
9698
 
10002
- ### Uploading Files
10003
-
10004
- 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\`.)
10005
-
10006
- \`\`\`bash
10007
- FILE=/path/to/file
10008
- FILENAME=$(basename "$FILE")
10009
- LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
10010
-
10011
- # 1. Reserve an upload URL + file ID.
10012
- RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
10013
- -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
10014
- --data-urlencode "filename=$FILENAME" \\
10015
- --data-urlencode "length=$LENGTH")
10016
- UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
10017
- FILE_ID=$(echo "$RESERVE" | jq -r '.file_id')
9699
+ Attach every new top-level conversation so future replies route to this workspace. For a reply in another thread, attach its root \`thread_ts\`, not the reply timestamp. Do not attach the originating thread again.
10018
9700
 
10019
- # 2. POST the raw bytes to the reserved URL.
10020
- # Do not use -F / multipart here \u2014 the presigned URL expects the bytes
10021
- # directly in the request body.
10022
- curl -s -X POST "$UPLOAD_URL" \\
10023
- -H "Content-Type: application/octet-stream" \\
10024
- --data-binary @"$FILE"
9701
+ ## Search and batch
10025
9702
 
10026
- # 3. Complete the upload and share into a channel (and optionally a thread).
10027
- curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
10028
- -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
10029
- -H "Content-Type: application/json; charset=utf-8" \\
10030
- -d "{
10031
- \\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"File title\\"}],
10032
- \\"channel_id\\": \\"CHANNEL_ID\\",
10033
- \\"thread_ts\\": \\"OPTIONAL_THREAD_TS\\",
10034
- \\"initial_comment\\": \\"Optional message body\\"
10035
- }"
9703
+ \`\`\`ts
9704
+ const [messages, users] = await Promise.all([
9705
+ replicas.slack.call('search.messages', { query: 'launch status' }),
9706
+ replicas.slack.call('users.list', { limit: 200 }),
9707
+ ]);
10036
9708
  \`\`\`
10037
9709
 
10038
- Omit \`thread_ts\` and/or \`initial_comment\` if you don't need them.
10039
-
10040
- ### Other Operations
10041
-
10042
- 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.
10043
-
10044
- For full API documentation, see: https://docs.slack.dev/apis/web-api/
9710
+ Supported methods cover conversations, messages, search, users, reactions, and Slack's external file-upload flow. An unsupported method is rejected by Replicas before Slack is called.
10045
9711
  `;
10046
9712
  var SLACK_ABILITY = {
10047
9713
  label: "Slack",
10048
- description: "Send messages, read threads, search conversations, upload files.",
9714
+ description: "Send messages, read threads, and search through @replicas/sdk.",
10049
9715
  bullet: "- Interacting with Slack (sending messages, reading threads, etc.)",
10050
- section: SECTION11,
10051
- referenceFile: { name: "SLACK.md", content: REFERENCE11 }
9716
+ section: SECTION13,
9717
+ referenceFile: { name: "SLACK.md", content: REFERENCE13 }
10052
9718
  };
10053
9719
 
10054
9720
  // ../shared/src/default-skills/replicas-agent/registry.ts
@@ -10062,7 +9728,9 @@ var REPLICAS_AGENT_ABILITY_REGISTRY = {
10062
9728
  learnings: LEARNINGS_ABILITY,
10063
9729
  linear: LINEAR_ABILITY,
10064
9730
  media: MEDIA_ABILITY,
9731
+ plugins: PLUGINS_ABILITY,
10065
9732
  previews: PREVIEWS_ABILITY,
9733
+ sentry: SENTRY_ABILITY,
10066
9734
  slack: SLACK_ABILITY
10067
9735
  };
10068
9736
  var REPLICAS_AGENT_ABILITIES = Object.keys(
@@ -10161,7 +9829,7 @@ function formatTurnElapsed(ms) {
10161
9829
  }
10162
9830
 
10163
9831
  // ../shared/src/cli-version.ts
10164
- var CLI_VERSION = "0.2.492";
9832
+ var CLI_VERSION = "0.2.493";
10165
9833
 
10166
9834
  // ../shared/src/version.ts
10167
9835
  function compareVersions(v1, v2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.492",
3
+ "version": "0.2.493",
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": {