replicas-engine 0.1.576 → 0.1.578

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/README.md CHANGED
@@ -125,7 +125,7 @@ Credential files expected/used by provider CLIs:
125
125
  The engine calls monolith with:
126
126
 
127
127
  - `Authorization: Bearer <REPLICAS_ENGINE_SECRET>`
128
- - `X-Workspace-Id: <WORKSPACE_ID>`
128
+ - `X-Workspace-Id: <REPLICAS_WORKSPACE_ID>`
129
129
 
130
130
  Outgoing endpoints:
131
131
 
package/dist/src/index.js CHANGED
@@ -725,6 +725,18 @@ var WORKSPACE_SIZES = ["small", "large"];
725
725
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
726
726
 
727
727
  // ../shared/src/runtime-env.ts
728
+ var REPLICAS_RUNTIME_ENV_ALIASES = {
729
+ monolithUrl: ["REPLICAS_MONOLITH_URL", "MONOLITH_URL"],
730
+ workspaceId: ["REPLICAS_WORKSPACE_ID", "WORKSPACE_ID"],
731
+ linearSessionId: ["REPLICAS_LINEAR_SESSION_ID", "LINEAR_SESSION_ID"],
732
+ linearAccessToken: ["REPLICAS_LINEAR_ACCESS_TOKEN", "LINEAR_ACCESS_TOKEN"],
733
+ slackBotToken: ["REPLICAS_SLACK_BOT_TOKEN", "SLACK_BOT_TOKEN"],
734
+ slackChannelId: ["REPLICAS_SLACK_CHANNEL_ID", "SLACK_CHANNEL_ID"],
735
+ slackThreadTs: ["REPLICAS_SLACK_THREAD_TS", "SLACK_THREAD_TS"]
736
+ };
737
+ function readReplicasRuntimeEnv(readEnv2, [namespacedKey, legacyKey]) {
738
+ return readEnv2(namespacedKey) ?? readEnv2(legacyKey);
739
+ }
728
740
  function shellQuotePosix(value) {
729
741
  return `'${value.split("'").join("'\\''")}'`;
730
742
  }
@@ -785,6 +797,7 @@ function parsePosixEnvFile(content) {
785
797
 
786
798
  // ../shared/src/git.ts
787
799
  var GIT_CREDENTIAL_HELPER_FILENAME = ".git-credential-replicas";
800
+ var GITHUB_CREDENTIAL_REFRESH_PATH = "/git-credentials/github/refresh";
788
801
  var GITLAB_CREDENTIAL_REFRESH_PATH = "/git-credentials/gitlab/refresh";
789
802
  function buildGitCredentialHelperScript(credentialsPath) {
790
803
  return `#!/bin/sh
@@ -795,18 +808,24 @@ get_credential() {
795
808
  ' "$request" | git credential-store --file=${shellQuotePosix(credentialsPath)} get
796
809
  }
797
810
 
798
- refresh_gitlab_credential() {
811
+ refresh_credential() {
812
+ case "$1" in
813
+ x-access-token) refresh_path=${GITHUB_CREDENTIAL_REFRESH_PATH} ;;
814
+ oauth2) refresh_path=${GITLAB_CREDENTIAL_REFRESH_PATH} ;;
815
+ *) return 1 ;;
816
+ esac
799
817
  [ -n "\${REPLICAS_ENGINE_SECRET:-}" ] || return 1
800
818
  command -v curl >/dev/null 2>&1 || return 1
801
- curl --silent --fail --connect-timeout 1 --max-time 5 -X POST -H "X-Replicas-Engine-Secret: $REPLICAS_ENGINE_SECRET" "http://127.0.0.1:\${REPLICAS_ENGINE_PORT:-3737}${GITLAB_CREDENTIAL_REFRESH_PATH}" >/dev/null 2>&1
819
+ curl --silent --fail --connect-timeout 1 --max-time 5 -X POST -H "X-Replicas-Engine-Secret: $REPLICAS_ENGINE_SECRET" "http://127.0.0.1:\${REPLICAS_ENGINE_PORT:-3737}$refresh_path" >/dev/null 2>&1
802
820
  }
803
821
 
804
822
  if [ "$1" = "get" ]; then
805
823
  credential=$(get_credential)
806
- if printf '%s
824
+ username=$(printf '%s
807
825
  %s
808
- ' "$request" "$credential" | grep -q '^username=oauth2$'; then
809
- if refresh_gitlab_credential; then
826
+ ' "$request" "$credential" | sed -n 's/^username=//p' | head -n 1)
827
+ if [ -n "$username" ]; then
828
+ if refresh_credential "$username"; then
810
829
  refreshed_credential=$(get_credential)
811
830
  if [ -n "$refreshed_credential" ]; then
812
831
  credential=$refreshed_credential
@@ -815,9 +834,10 @@ if [ "$1" = "get" ]; then
815
834
  fi
816
835
  printf '%s
817
836
  ' "$credential"
818
- elif [ "$1" = "erase" ] && printf '%s
819
- ' "$request" | grep -q '^username=oauth2$'; then
820
- refresh_gitlab_credential || true
837
+ elif [ "$1" = "erase" ]; then
838
+ username=$(printf '%s
839
+ ' "$request" | sed -n 's/^username=//p' | head -n 1)
840
+ refresh_credential "$username" || true
821
841
  fi
822
842
  exit 0
823
843
  `;
@@ -1573,9 +1593,9 @@ The integration is configured at the org or user level by the Replicas admin. Fr
1573
1593
  Quick check that the integration is connected:
1574
1594
 
1575
1595
  \`\`\`bash
1576
- curl -s -X GET "$MONOLITH_URL/v1/gdrive/credentials" \\
1596
+ curl -s -X GET "$REPLICAS_MONOLITH_URL/v1/gdrive/credentials" \\
1577
1597
  -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
1578
- -H "X-Workspace-Id: $WORKSPACE_ID"
1598
+ -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID"
1579
1599
  \`\`\`
1580
1600
 
1581
1601
  - If \`hasCredentials\` is \`true\`: you're good to go.
@@ -1585,13 +1605,13 @@ Standard auth headers used by every call below:
1585
1605
 
1586
1606
  \`\`\`
1587
1607
  Authorization: Bearer $REPLICAS_ENGINE_SECRET
1588
- X-Workspace-Id: $WORKSPACE_ID
1608
+ X-Workspace-Id: $REPLICAS_WORKSPACE_ID
1589
1609
  \`\`\`
1590
1610
 
1591
1611
  For brevity the examples below use a shell variable:
1592
1612
 
1593
1613
  \`\`\`bash
1594
- GDRIVE_AUTH=(-H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" -H "X-Workspace-Id: $WORKSPACE_ID")
1614
+ GDRIVE_AUTH=(-H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID")
1595
1615
  \`\`\`
1596
1616
 
1597
1617
  ## Important constraint: drive.file scope
@@ -1609,7 +1629,7 @@ If the user asks you to edit an existing doc that Replicas didn't create, tell t
1609
1629
  ### Create a new doc
1610
1630
 
1611
1631
  \`\`\`bash
1612
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/docs" "\${GDRIVE_AUTH[@]}" \\
1632
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/docs" "\${GDRIVE_AUTH[@]}" \\
1613
1633
  -H "Content-Type: application/json" \\
1614
1634
  -d '{"title":"Meeting notes 2026-05-14"}'
1615
1635
  \`\`\`
@@ -1619,7 +1639,7 @@ Returns the full Doc object; grab \`.documentId\` for follow-up calls.
1619
1639
  ### Read a doc
1620
1640
 
1621
1641
  \`\`\`bash
1622
- curl -s "$MONOLITH_URL/v1/gdrive/docs/$DOC_ID" "\${GDRIVE_AUTH[@]}"
1642
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/docs/$DOC_ID" "\${GDRIVE_AUTH[@]}"
1623
1643
  \`\`\`
1624
1644
 
1625
1645
  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.
@@ -1629,7 +1649,7 @@ Returns the full document structure \u2014 \`body.content\` is an ordered list o
1629
1649
  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.
1630
1650
 
1631
1651
  \`\`\`bash
1632
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/docs/$DOC_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1652
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/docs/$DOC_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1633
1653
  -H "Content-Type: application/json" \\
1634
1654
  -d '{
1635
1655
  "requests": [
@@ -1656,7 +1676,7 @@ Edits are verbose but powerful. Prefer batching many requests into a single \`ba
1656
1676
  ### Create a new spreadsheet
1657
1677
 
1658
1678
  \`\`\`bash
1659
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/sheets" "\${GDRIVE_AUTH[@]}" \\
1679
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets" "\${GDRIVE_AUTH[@]}" \\
1660
1680
  -H "Content-Type: application/json" \\
1661
1681
  -d '{"title":"Q2 metrics"}'
1662
1682
  \`\`\`
@@ -1667,7 +1687,7 @@ Returns the full Spreadsheet object; grab \`.spreadsheetId\`.
1667
1687
 
1668
1688
  \`\`\`bash
1669
1689
  # Range is in A1 notation, e.g. "Sheet1!A1:C10"
1670
- curl -s "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:C10' | jq -sRr @uri)" \\
1690
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:C10' | jq -sRr @uri)" \\
1671
1691
  "\${GDRIVE_AUTH[@]}"
1672
1692
  \`\`\`
1673
1693
 
@@ -1675,7 +1695,7 @@ curl -s "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:
1675
1695
 
1676
1696
  \`\`\`bash
1677
1697
  curl -s -X PUT \\
1678
- "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:B2' | jq -sRr @uri)?valueInputOption=USER_ENTERED" \\
1698
+ "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/values/$(printf %s 'Sheet1!A1:B2' | jq -sRr @uri)?valueInputOption=USER_ENTERED" \\
1679
1699
  "\${GDRIVE_AUTH[@]}" \\
1680
1700
  -H "Content-Type: application/json" \\
1681
1701
  -d '{
@@ -1693,7 +1713,7 @@ curl -s -X PUT \\
1693
1713
  ### Bulk operations (formatting, charts, new tabs, etc.)
1694
1714
 
1695
1715
  \`\`\`bash
1696
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1716
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1697
1717
  -H "Content-Type: application/json" \\
1698
1718
  -d '{ "requests": [ { "addSheet": { "properties": { "title": "Raw data" } } } ] }'
1699
1719
  \`\`\`
@@ -1705,7 +1725,7 @@ curl -s -X POST "$MONOLITH_URL/v1/gdrive/sheets/$SHEET_ID/batchUpdate" "\${GDRIV
1705
1725
  ### Create a new form
1706
1726
 
1707
1727
  \`\`\`bash
1708
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/forms" "\${GDRIVE_AUTH[@]}" \\
1728
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/forms" "\${GDRIVE_AUTH[@]}" \\
1709
1729
  -H "Content-Type: application/json" \\
1710
1730
  -d '{"title":"Customer feedback"}'
1711
1731
  \`\`\`
@@ -1717,7 +1737,7 @@ Returns the form. Grab \`.formId\`.
1717
1737
  The Forms API uses its own \`batchUpdate\`:
1718
1738
 
1719
1739
  \`\`\`bash
1720
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/forms/$FORM_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1740
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/forms/$FORM_ID/batchUpdate" "\${GDRIVE_AUTH[@]}" \\
1721
1741
  -H "Content-Type: application/json" \\
1722
1742
  -d '{
1723
1743
  "requests": [
@@ -1744,7 +1764,7 @@ See the [Forms API Request reference](https://developers.google.com/workspace/fo
1744
1764
  ### Read responses
1745
1765
 
1746
1766
  \`\`\`bash
1747
- curl -s "$MONOLITH_URL/v1/gdrive/forms/$FORM_ID/responses" "\${GDRIVE_AUTH[@]}"
1767
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/forms/$FORM_ID/responses" "\${GDRIVE_AUTH[@]}"
1748
1768
  \`\`\`
1749
1769
 
1750
1770
  Pagination: pass \`?pageToken=...&pageSize=...\` to walk through responses.
@@ -1754,7 +1774,7 @@ Pagination: pass \`?pageToken=...&pageSize=...\` to walk through responses.
1754
1774
  ### Share a file with a person
1755
1775
 
1756
1776
  \`\`\`bash
1757
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
1777
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
1758
1778
  -H "Content-Type: application/json" \\
1759
1779
  -d '{
1760
1780
  "type": "user",
@@ -1769,7 +1789,7 @@ Roles: \`reader\`, \`commenter\`, \`writer\`. Types: \`user\`, \`group\`, \`doma
1769
1789
  ### Make a file viewable by anyone with the link
1770
1790
 
1771
1791
  \`\`\`bash
1772
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
1792
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}" \\
1773
1793
  -H "Content-Type: application/json" \\
1774
1794
  -d '{ "type": "anyone", "role": "reader" }'
1775
1795
  \`\`\`
@@ -1777,13 +1797,13 @@ curl -s -X POST "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_
1777
1797
  ### List existing permissions
1778
1798
 
1779
1799
  \`\`\`bash
1780
- curl -s "$MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}"
1800
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID/permissions" "\${GDRIVE_AUTH[@]}"
1781
1801
  \`\`\`
1782
1802
 
1783
1803
  ### Rename / move a file
1784
1804
 
1785
1805
  \`\`\`bash
1786
- curl -s -X PATCH "$MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}" \\
1806
+ curl -s -X PATCH "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}" \\
1787
1807
  -H "Content-Type: application/json" \\
1788
1808
  -d '{"name":"Final report.docx"}'
1789
1809
  \`\`\`
@@ -1793,7 +1813,7 @@ To move into a folder, also pass \`addParents\` and \`removeParents\` as query p
1793
1813
  ### Get file metadata
1794
1814
 
1795
1815
  \`\`\`bash
1796
- curl -s "$MONOLITH_URL/v1/gdrive/files/$FILE_ID?fields=id,name,mimeType,webViewLink,parents,modifiedTime" \\
1816
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID?fields=id,name,mimeType,webViewLink,parents,modifiedTime" \\
1797
1817
  "\${GDRIVE_AUTH[@]}"
1798
1818
  \`\`\`
1799
1819
 
@@ -1802,13 +1822,13 @@ curl -s "$MONOLITH_URL/v1/gdrive/files/$FILE_ID?fields=id,name,mimeType,webViewL
1802
1822
  ### Delete a file
1803
1823
 
1804
1824
  \`\`\`bash
1805
- curl -s -X DELETE "$MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}"
1825
+ curl -s -X DELETE "$REPLICAS_MONOLITH_URL/v1/gdrive/files/$FILE_ID" "\${GDRIVE_AUTH[@]}"
1806
1826
  \`\`\`
1807
1827
 
1808
1828
  ### List Replicas-created files
1809
1829
 
1810
1830
  \`\`\`bash
1811
- curl -s "$MONOLITH_URL/v1/gdrive/files?pageSize=50" "\${GDRIVE_AUTH[@]}"
1831
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/files?pageSize=50" "\${GDRIVE_AUTH[@]}"
1812
1832
  \`\`\`
1813
1833
 
1814
1834
  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.
@@ -1822,20 +1842,20 @@ Property identifiers must be URL-encoded as query parameters. URL-prefix propert
1822
1842
  ### List accessible properties
1823
1843
 
1824
1844
  \`\`\`bash
1825
- curl -s "$MONOLITH_URL/v1/gdrive/search-console/sites" "\${GDRIVE_AUTH[@]}"
1845
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/sites" "\${GDRIVE_AUTH[@]}"
1826
1846
  \`\`\`
1827
1847
 
1828
1848
  ### Get a property
1829
1849
 
1830
1850
  \`\`\`bash
1831
1851
  SITE_URL=$(printf %s 'sc-domain:example.com' | jq -sRr @uri)
1832
- curl -s "$MONOLITH_URL/v1/gdrive/search-console/site?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
1852
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/site?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
1833
1853
  \`\`\`
1834
1854
 
1835
1855
  ### Query search performance
1836
1856
 
1837
1857
  \`\`\`bash
1838
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/search-console/search-analytics/query?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}" \\
1858
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/search-analytics/query?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}" \\
1839
1859
  -H "Content-Type: application/json" \\
1840
1860
  -d '{
1841
1861
  "startDate": "2026-06-01",
@@ -1850,7 +1870,7 @@ Results contain clicks, impressions, CTR, and average position. Use \`startRow\`
1850
1870
  ### List sitemaps
1851
1871
 
1852
1872
  \`\`\`bash
1853
- curl -s "$MONOLITH_URL/v1/gdrive/search-console/sitemaps?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
1873
+ curl -s "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/sitemaps?siteUrl=$SITE_URL" "\${GDRIVE_AUTH[@]}"
1854
1874
  \`\`\`
1855
1875
 
1856
1876
  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.
@@ -1858,7 +1878,7 @@ Pass a URL-encoded \`sitemapIndex\` query parameter to list sitemaps referenced
1858
1878
  ### Inspect an indexed URL
1859
1879
 
1860
1880
  \`\`\`bash
1861
- curl -s -X POST "$MONOLITH_URL/v1/gdrive/search-console/url-inspection" "\${GDRIVE_AUTH[@]}" \\
1881
+ curl -s -X POST "$REPLICAS_MONOLITH_URL/v1/gdrive/search-console/url-inspection" "\${GDRIVE_AUTH[@]}" \\
1862
1882
  -H "Content-Type: application/json" \\
1863
1883
  -d '{
1864
1884
  "inspectionUrl": "https://example.com/page",
@@ -1929,7 +1949,7 @@ This guide covers how to interact with Linear from within your Replicas workspac
1929
1949
  Check that the workspace has the Replicas engine credentials needed to proxy Linear requests:
1930
1950
 
1931
1951
  \`\`\`bash
1932
- test -n "$MONOLITH_URL" && test -n "$REPLICAS_ENGINE_SECRET" && test -n "$WORKSPACE_ID" && echo set
1952
+ test -n "$REPLICAS_MONOLITH_URL" && test -n "$REPLICAS_ENGINE_SECRET" && test -n "$REPLICAS_WORKSPACE_ID" && echo set
1933
1953
  \`\`\`
1934
1954
 
1935
1955
  - If **set**: Use the Replicas Linear proxy below. It refreshes Linear OAuth tokens for you.
@@ -1938,9 +1958,9 @@ test -n "$MONOLITH_URL" && test -n "$REPLICAS_ENGINE_SECRET" && test -n "$WORKSP
1938
1958
  Then verify Linear is connected:
1939
1959
 
1940
1960
  \`\`\`bash
1941
- curl -fsS -X POST "$MONOLITH_URL/v1/engine/linear/refresh-token" \\
1961
+ curl -fsS -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/refresh-token" \\
1942
1962
  -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
1943
- -H "X-Workspace-Id: $WORKSPACE_ID" \\
1963
+ -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
1944
1964
  -H "Content-Type: application/json" \\
1945
1965
  -d '{}' >/dev/null
1946
1966
  \`\`\`
@@ -1953,9 +1973,9 @@ Linear uses a GraphQL API. Always call it through Replicas so the access token s
1953
1973
 
1954
1974
  \`\`\`bash
1955
1975
  linear_graphql() {
1956
- curl -sS -X POST "$MONOLITH_URL/v1/engine/linear/graphql" \\
1976
+ curl -sS -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/graphql" \\
1957
1977
  -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
1958
- -H "X-Workspace-Id: $WORKSPACE_ID" \\
1978
+ -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
1959
1979
  -H "Content-Type: application/json" \\
1960
1980
  --data-binary @-
1961
1981
  }
@@ -2143,7 +2163,7 @@ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
2143
2163
 
2144
2164
  # 1. Reserve an upload URL + file ID.
2145
2165
  RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
2146
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
2166
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
2147
2167
  --data-urlencode "filename=$FILENAME" \\
2148
2168
  --data-urlencode "length=$LENGTH")
2149
2169
  UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
@@ -2158,7 +2178,7 @@ curl -s -X POST "$UPLOAD_URL" \\
2158
2178
 
2159
2179
  # 3. Complete the upload, sharing it into the channel/thread with the dashboard link.
2160
2180
  curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
2161
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
2181
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
2162
2182
  -H "Content-Type: application/json; charset=utf-8" \\
2163
2183
  -d "{
2164
2184
  \\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"Screenshot\\"}],
@@ -2192,9 +2212,9 @@ ISSUE_UUID=... # the Linear issue's UUID
2192
2212
  MEDIA_ID=... # the media ID printed by \`replicas media upload\`
2193
2213
 
2194
2214
  linear_graphql() {
2195
- curl -sS -X POST "$MONOLITH_URL/v1/engine/linear/graphql" \\
2215
+ curl -sS -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/graphql" \\
2196
2216
  -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
2197
- -H "X-Workspace-Id: $WORKSPACE_ID" \\
2217
+ -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
2198
2218
  -H "Content-Type: application/json" \\
2199
2219
  --data-binary @-
2200
2220
  }
@@ -2225,7 +2245,7 @@ curl -s -X PUT "$UPLOAD_URL" \\
2225
2245
 
2226
2246
  # 3. Reference assetUrl inline in the comment body, alongside the dashboard link.
2227
2247
  BODY=$(printf '![screenshot](%s)\\n\\n[View in Replicas](https://tryreplicas.com/workspaces/%s?media=%s)' \\
2228
- "$ASSET_URL" "$WORKSPACE_ID" "$MEDIA_ID")
2248
+ "$ASSET_URL" "$REPLICAS_WORKSPACE_ID" "$MEDIA_ID")
2229
2249
 
2230
2250
  jq -n \\
2231
2251
  --arg issueId "$ISSUE_UUID" \\
@@ -2669,10 +2689,10 @@ This guide covers how to interact with Slack from within your Replicas workspace
2669
2689
 
2670
2690
  ## Prerequisites
2671
2691
 
2672
- Check if the \`REPLICAS_SLACK_BOT_TOKEN\` environment variable is set:
2692
+ Check if the namespaced or legacy Slack token environment variable is set:
2673
2693
 
2674
2694
  \`\`\`bash
2675
- echo "\${REPLICAS_SLACK_BOT_TOKEN:+set}"
2695
+ if [ -n "\${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" ]; then echo set; fi
2676
2696
  \`\`\`
2677
2697
 
2678
2698
  - If **set**: Your workspace has Slack access. You can use the Slack Web API as described below.
@@ -2680,7 +2700,7 @@ echo "\${REPLICAS_SLACK_BOT_TOKEN:+set}"
2680
2700
 
2681
2701
  ## Using the Slack API
2682
2702
 
2683
- All requests use the \`$REPLICAS_SLACK_BOT_TOKEN\` for authentication via the Slack Web API.
2703
+ All requests prefer \`$REPLICAS_SLACK_BOT_TOKEN\` and fall back to \`$SLACK_BOT_TOKEN\` for compatibility with older workspaces.
2684
2704
 
2685
2705
  ### Fetching a Thread from a Slack Link
2686
2706
 
@@ -2691,14 +2711,14 @@ If you encounter a Slack message link (e.g. \`https://team.slack.com/archives/C0
2691
2711
 
2692
2712
  \`\`\`bash
2693
2713
  curl -s "https://slack.com/api/conversations.replies?channel=CHANNEL_ID&ts=THREAD_TS" \\
2694
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN"
2714
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}"
2695
2715
  \`\`\`
2696
2716
 
2697
2717
  ### Sending a Message
2698
2718
 
2699
2719
  \`\`\`bash
2700
2720
  curl -s -X POST "https://slack.com/api/chat.postMessage" \\
2701
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
2721
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
2702
2722
  -H "Content-Type: application/json" \\
2703
2723
  -d '{
2704
2724
  "channel": "CHANNEL_ID",
@@ -2731,13 +2751,13 @@ replicas list
2731
2751
  replicas slack thread switch <workspace-id-or-name> --channel <channel-id> --thread-ts <thread-root-ts>
2732
2752
  \`\`\`
2733
2753
 
2734
- The channel and thread flags default to \`SLACK_CHANNEL_ID\` and \`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.
2754
+ 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.
2735
2755
 
2736
2756
  ### Searching Messages
2737
2757
 
2738
2758
  \`\`\`bash
2739
2759
  curl -s "https://slack.com/api/search.messages?query=YOUR_SEARCH_QUERY" \\
2740
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN"
2760
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}"
2741
2761
  \`\`\`
2742
2762
 
2743
2763
  ### Uploading Files
@@ -2751,7 +2771,7 @@ LENGTH=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
2751
2771
 
2752
2772
  # 1. Reserve an upload URL + file ID.
2753
2773
  RESERVE=$(curl -s -G "https://slack.com/api/files.getUploadURLExternal" \\
2754
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
2774
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
2755
2775
  --data-urlencode "filename=$FILENAME" \\
2756
2776
  --data-urlencode "length=$LENGTH")
2757
2777
  UPLOAD_URL=$(echo "$RESERVE" | jq -r '.upload_url')
@@ -2766,7 +2786,7 @@ curl -s -X POST "$UPLOAD_URL" \\
2766
2786
 
2767
2787
  # 3. Complete the upload and share into a channel (and optionally a thread).
2768
2788
  curl -s -X POST "https://slack.com/api/files.completeUploadExternal" \\
2769
- -H "Authorization: Bearer $REPLICAS_SLACK_BOT_TOKEN" \\
2789
+ -H "Authorization: Bearer \${REPLICAS_SLACK_BOT_TOKEN:-$SLACK_BOT_TOKEN}" \\
2770
2790
  -H "Content-Type: application/json; charset=utf-8" \\
2771
2791
  -d "{
2772
2792
  \\"files\\": [{\\"id\\": \\"$FILE_ID\\", \\"title\\": \\"File title\\"}],
@@ -5659,17 +5679,20 @@ function loadEngineEnv() {
5659
5679
  // Defined: always available
5660
5680
  REPLICAS_ENGINE_SECRET: requireDefined(readEnv("REPLICAS_ENGINE_SECRET"), "REPLICAS_ENGINE_SECRET"),
5661
5681
  REPLICAS_ENGINE_PORT: parsePort(readEnv("REPLICAS_ENGINE_PORT")),
5662
- MONOLITH_URL: requireValidURL(requireDefined(readEnv("MONOLITH_URL"), "MONOLITH_URL"), "MONOLITH_URL"),
5682
+ REPLICAS_MONOLITH_URL: requireValidURL(
5683
+ requireDefined(readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.monolithUrl), "REPLICAS_MONOLITH_URL"),
5684
+ "REPLICAS_MONOLITH_URL"
5685
+ ),
5663
5686
  HOME_DIR,
5664
5687
  WORKSPACE_ROOT: join2(HOME_DIR, "workspaces"),
5665
5688
  REPLICAS_SANDBOX_IMAGE_VERSION: readEnv("REPLICAS_SANDBOX_IMAGE_VERSION") ?? "development",
5666
5689
  // Runtime: may not be set during warming
5667
- WORKSPACE_ID: readEnv("WORKSPACE_ID"),
5668
- LINEAR_SESSION_ID: readEnv("LINEAR_SESSION_ID"),
5669
- LINEAR_ACCESS_TOKEN: readEnv("LINEAR_ACCESS_TOKEN"),
5670
- REPLICAS_SLACK_BOT_TOKEN: readEnv("REPLICAS_SLACK_BOT_TOKEN"),
5671
- SLACK_CHANNEL_ID: readEnv("SLACK_CHANNEL_ID"),
5672
- SLACK_THREAD_TS: readEnv("SLACK_THREAD_TS"),
5690
+ REPLICAS_WORKSPACE_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.workspaceId),
5691
+ REPLICAS_LINEAR_SESSION_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearSessionId),
5692
+ REPLICAS_LINEAR_ACCESS_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearAccessToken),
5693
+ REPLICAS_SLACK_BOT_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackBotToken),
5694
+ REPLICAS_SLACK_CHANNEL_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackChannelId),
5695
+ REPLICAS_SLACK_THREAD_TS: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackThreadTs),
5673
5696
  ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
5674
5697
  OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
5675
5698
  CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
@@ -5686,8 +5709,8 @@ function loadEngineEnv() {
5686
5709
  REPLICAS_DISABLE_AUTO_START_HOOKS: readEnv("REPLICAS_DISABLE_AUTO_START_HOOKS")?.toLowerCase() === "true",
5687
5710
  REPLICAS_ENGINE_DEFER_INITIALIZATION: readEnv("REPLICAS_ENGINE_DEFER_INITIALIZATION")?.toLowerCase() === "true"
5688
5711
  };
5689
- if (!IS_WARMING_MODE && !env.WORKSPACE_ID) {
5690
- console.error("WORKSPACE_ID is not set \u2014 this is required in normal (non-warming) mode");
5712
+ if (!IS_WARMING_MODE && !env.REPLICAS_WORKSPACE_ID) {
5713
+ console.error("REPLICAS_WORKSPACE_ID is not set \u2014 this is required in normal (non-warming) mode");
5691
5714
  }
5692
5715
  return env;
5693
5716
  }
@@ -5773,12 +5796,12 @@ var BaseRefreshManager = class {
5773
5796
  return this.intervalMs;
5774
5797
  }
5775
5798
  getRuntimeConfig() {
5776
- if (!ENGINE_ENV.WORKSPACE_ID) {
5799
+ if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
5777
5800
  return null;
5778
5801
  }
5779
5802
  return {
5780
- monolithUrl: ENGINE_ENV.MONOLITH_URL,
5781
- workspaceId: ENGINE_ENV.WORKSPACE_ID,
5803
+ monolithUrl: ENGINE_ENV.REPLICAS_MONOLITH_URL,
5804
+ workspaceId: ENGINE_ENV.REPLICAS_WORKSPACE_ID,
5782
5805
  engineSecret: ENGINE_ENV.REPLICAS_ENGINE_SECRET
5783
5806
  };
5784
5807
  }
@@ -5816,16 +5839,16 @@ var BaseRefreshManager = class {
5816
5839
 
5817
5840
  // src/services/monolith-service.ts
5818
5841
  async function monolithRequest(path6, init = {}) {
5819
- if (!ENGINE_ENV.WORKSPACE_ID) {
5820
- throw new Error("WORKSPACE_ID is not set; cannot call monolith");
5842
+ if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
5843
+ throw new Error("REPLICAS_WORKSPACE_ID is not set; cannot call monolith");
5821
5844
  }
5822
5845
  const isFormData = init.body instanceof FormData;
5823
5846
  const headers = {
5824
5847
  Authorization: `Bearer ${ENGINE_ENV.REPLICAS_ENGINE_SECRET}`,
5825
- "X-Workspace-Id": ENGINE_ENV.WORKSPACE_ID
5848
+ "X-Workspace-Id": ENGINE_ENV.REPLICAS_WORKSPACE_ID
5826
5849
  };
5827
5850
  if (!isFormData) headers["Content-Type"] = "application/json";
5828
- return fetch(`${ENGINE_ENV.MONOLITH_URL}${path6}`, {
5851
+ return fetch(`${ENGINE_ENV.REPLICAS_MONOLITH_URL}${path6}`, {
5829
5852
  method: init.method ?? "POST",
5830
5853
  headers,
5831
5854
  body: init.body === void 0 ? void 0 : isFormData ? init.body : JSON.stringify(init.body),
@@ -5858,7 +5881,7 @@ var MonolithService = class {
5858
5881
  }
5859
5882
  }
5860
5883
  async sendEvent(event) {
5861
- if (!ENGINE_ENV.WORKSPACE_ID) {
5884
+ if (!ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
5862
5885
  return;
5863
5886
  }
5864
5887
  try {
@@ -7303,7 +7326,9 @@ var EnvironmentDetailsService = class {
7303
7326
  details.githubCredentialsConfigured = ghConfigured;
7304
7327
  details.gitlabAccessConfigured = gitlabAccessConfigured;
7305
7328
  details.gitlabCredentialsConfigured = gitlabAccessConfigured;
7306
- details.linearAccessConfigured = Boolean(ENGINE_ENV.LINEAR_SESSION_ID || ENGINE_ENV.LINEAR_ACCESS_TOKEN);
7329
+ details.linearAccessConfigured = Boolean(
7330
+ ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID || ENGINE_ENV.REPLICAS_LINEAR_ACCESS_TOKEN
7331
+ );
7307
7332
  details.slackAccessConfigured = Boolean(ENGINE_ENV.REPLICAS_SLACK_BOT_TOKEN);
7308
7333
  const freshRepos = repositories.map((repo) => ({
7309
7334
  repositoryName: repo.name,
@@ -8030,7 +8055,7 @@ async function attemptRegistration() {
8030
8055
  }
8031
8056
  }
8032
8057
  async function registerDesktopPreview() {
8033
- if (IS_WARMING_MODE || !ENGINE_ENV.WORKSPACE_ID) {
8058
+ if (IS_WARMING_MODE || !ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
8034
8059
  return;
8035
8060
  }
8036
8061
  const deadline = Date.now() + REGISTRATION_TIMEOUT_MS;
@@ -8472,13 +8497,13 @@ async function getLinearAccessToken() {
8472
8497
  const response = await monolithRequest("/v1/engine/linear/refresh-token");
8473
8498
  if (!response.ok) {
8474
8499
  console.warn(`[ImageUtils] Failed to refresh Linear token: ${response.status} ${await response.text()}`);
8475
- return ENGINE_ENV.LINEAR_ACCESS_TOKEN;
8500
+ return ENGINE_ENV.REPLICAS_LINEAR_ACCESS_TOKEN;
8476
8501
  }
8477
8502
  const data = await response.json();
8478
8503
  return data.token;
8479
8504
  } catch (error) {
8480
8505
  console.warn("[ImageUtils] Failed to refresh Linear token:", error);
8481
- return ENGINE_ENV.LINEAR_ACCESS_TOKEN;
8506
+ return ENGINE_ENV.REPLICAS_LINEAR_ACCESS_TOKEN;
8482
8507
  }
8483
8508
  }
8484
8509
  function isLinearUploadUrl(url) {
@@ -8905,7 +8930,7 @@ var CodingAgentManager = class {
8905
8930
  };
8906
8931
  }
8907
8932
  emitInterruptedQueueEvent(queue) {
8908
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
8933
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
8909
8934
  if (!linearSessionId || queue.length === 0) {
8910
8935
  return;
8911
8936
  }
@@ -10247,7 +10272,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
10247
10272
  this.activeSessionSignature = signature;
10248
10273
  this.activeSessionModel = claudeCodeModel;
10249
10274
  this.activeSessionPermissionMode = resolvedPermissionMode;
10250
- this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.LINEAR_SESSION_ID);
10275
+ this.sessionLinearForwarder = new LinearEventForwarder(ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID);
10251
10276
  this.activeBackgroundTasks.clear();
10252
10277
  this.clearBackgroundContinuationTimer();
10253
10278
  resetClaudeSessionActivity(this.sessionActivity);
@@ -10261,7 +10286,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
10261
10286
  });
10262
10287
  }
10263
10288
  async runSessionLoop(response) {
10264
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
10289
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
10265
10290
  const iterator = response[Symbol.asyncIterator]();
10266
10291
  let loopError = null;
10267
10292
  let suppressLinearResponseFlush = false;
@@ -10854,7 +10879,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
10854
10879
  var MIN_CODEX_CLI_VERSION = "0.144.6";
10855
10880
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
10856
10881
  var codexCliVersionEnsured = null;
10857
- var ENGINE_PACKAGE_VERSION = "0.1.576";
10882
+ var ENGINE_PACKAGE_VERSION = "0.1.578";
10858
10883
  var INITIALIZE_METHOD = "initialize";
10859
10884
  var INITIALIZED_NOTIFICATION = "initialized";
10860
10885
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -12321,7 +12346,7 @@ var CodexAspManager = class extends CodingAgentManager {
12321
12346
  let goalContinuationTimer = null;
12322
12347
  const completedItems = [];
12323
12348
  const agentMessageDeltas = /* @__PURE__ */ new Map();
12324
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
12349
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
12325
12350
  const model = request.model ?? DEFAULT_MODEL;
12326
12351
  let tempImagePaths = [];
12327
12352
  const linearForwarder = new LinearEventForwarder(linearSessionId);
@@ -13274,7 +13299,7 @@ var CursorManager = class extends CodingAgentManager {
13274
13299
  const aborted = new Promise((resolve4) => {
13275
13300
  this.abortActiveTurn = () => resolve4(TURN_ABORTED);
13276
13301
  });
13277
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
13302
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
13278
13303
  const linearForwarder = new LinearEventForwarder(linearSessionId);
13279
13304
  try {
13280
13305
  const includeInstructions = !this.initialSessionId && !this.instructionsDelivered;
@@ -13973,7 +13998,7 @@ var OpencodeManager = class extends CodingAgentManager {
13973
13998
  async processMessageInternal(request) {
13974
13999
  const provider = await getOpencodeProvider();
13975
14000
  const controller = new AbortController();
13976
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
14001
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
13977
14002
  const linearForwarder = new LinearEventForwarder(linearSessionId);
13978
14003
  this.activeAbortController = controller;
13979
14004
  this.activeLinearForwarder = linearForwarder;
@@ -14272,7 +14297,7 @@ var OpencodeManager = class extends CodingAgentManager {
14272
14297
  return false;
14273
14298
  }
14274
14299
  forwardOpencodePartToLinear(part) {
14275
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
14300
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
14276
14301
  if (!linearSessionId || !this.activeLinearForwarder) return;
14277
14302
  const event = convertOpencodePart(part, linearSessionId);
14278
14303
  if (!event) return;
@@ -15406,7 +15431,7 @@ var KeepAliveService = class _KeepAliveService {
15406
15431
  await this.ping();
15407
15432
  }
15408
15433
  async ping() {
15409
- if (!ENGINE_ENV.MONOLITH_URL || !ENGINE_ENV.REPLICAS_ENGINE_SECRET || !ENGINE_ENV.WORKSPACE_ID) {
15434
+ if (!ENGINE_ENV.REPLICAS_MONOLITH_URL || !ENGINE_ENV.REPLICAS_ENGINE_SECRET || !ENGINE_ENV.REPLICAS_WORKSPACE_ID) {
15410
15435
  return;
15411
15436
  }
15412
15437
  try {
@@ -16741,7 +16766,7 @@ var ChatService = class {
16741
16766
  gitlabTokenManager.refreshOnce().catch(() => {
16742
16767
  })
16743
16768
  ]);
16744
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
16769
+ const linearSessionId = ENGINE_ENV.REPLICAS_LINEAR_SESSION_ID;
16745
16770
  const observedBranches = chat.observedBranchesByRepo;
16746
16771
  chat.observedBranchesByRepo = /* @__PURE__ */ new Map();
16747
16772
  const errors = chat.persisted.parentChatId === null ? chat.lastTurnErrors : null;
@@ -18505,7 +18530,7 @@ var HeartbeatService = class _HeartbeatService {
18505
18530
  static HEARTBEAT_INTERVAL_MS = 15e3;
18506
18531
  static REQUEST_TIMEOUT_MS = 5e3;
18507
18532
  start(bootTimeMs2) {
18508
- if (IS_WARMING_MODE || !ENGINE_ENV.WORKSPACE_ID || this.interval) return;
18533
+ if (IS_WARMING_MODE || !ENGINE_ENV.REPLICAS_WORKSPACE_ID || this.interval) return;
18509
18534
  this.bootTimeMs = bootTimeMs2;
18510
18535
  void this.ping();
18511
18536
  this.interval = setInterval(() => {
@@ -18689,6 +18714,16 @@ app.get("/token-refresh/health", async (c) => {
18689
18714
  infisical: infisicalTokenManager.getHealthStatus()
18690
18715
  });
18691
18716
  });
18717
+ app.post(GITHUB_CREDENTIAL_REFRESH_PATH, async (c) => {
18718
+ const result = await githubTokenManager.refreshOnce();
18719
+ if (!result.ok) {
18720
+ return c.json({
18721
+ error: "Failed to refresh GitHub credentials",
18722
+ details: result.error.message
18723
+ }, 502);
18724
+ }
18725
+ return c.body(null, 204);
18726
+ });
18692
18727
  app.post(GITLAB_CREDENTIAL_REFRESH_PATH, async (c) => {
18693
18728
  const result = await gitlabTokenManager.refreshOnce();
18694
18729
  if (!result.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.576",
3
+ "version": "0.1.578",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",