replicas-engine 0.1.759 → 0.1.761

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.
@@ -5,11 +5,11 @@ import {
5
5
  getCodexAspHost,
6
6
  restartCodexAspHost,
7
7
  restartCodexAspHostIfRunning
8
- } from "./chunk-JQHGDJE4.js";
9
- import "./chunk-WTNFZX53.js";
10
- import "./chunk-52SXO2DU.js";
8
+ } from "./chunk-47DDGIVB.js";
9
+ import "./chunk-VI2PM3UG.js";
10
+ import "./chunk-PWF56YNB.js";
11
11
  import "./chunk-UZSNFLDQ.js";
12
- import "./chunk-24FE3TDH.js";
12
+ import "./chunk-BU5GP3VV.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
  export {
15
15
  getCodexAspHost,
@@ -5,18 +5,18 @@ import {
5
5
  ENGINE_ENV,
6
6
  monolithRequest,
7
7
  setAgentCredentialSnapshot
8
- } from "./chunk-WTNFZX53.js";
8
+ } from "./chunk-VI2PM3UG.js";
9
9
  import {
10
10
  AppServerProcess,
11
11
  buildCodexAgentEnv
12
- } from "./chunk-52SXO2DU.js";
12
+ } from "./chunk-PWF56YNB.js";
13
13
  import {
14
14
  CODEX_AUTH_ENV_KEYS,
15
15
  CODEX_AUTH_ENV_KEYS_BY_METHOD,
16
16
  codexAuthEnvFromResponse,
17
17
  createErrorResult,
18
18
  createSuccessResult
19
- } from "./chunk-24FE3TDH.js";
19
+ } from "./chunk-BU5GP3VV.js";
20
20
 
21
21
  // src/managers/codex-token-manager.ts
22
22
  import { promises as fs } from "fs";
@@ -232,7 +232,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
232
232
  const data = await response.json();
233
233
  await this.applyCredentialsResponse(data);
234
234
  if (restartOnChange && CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index])) {
235
- const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-XMTAWU7K.js");
235
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-5GPDKD3D.js");
236
236
  await restartCodexAspHostIfRunning2();
237
237
  }
238
238
  if (data.scope) {
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  findCodeHostPullRequestUrls,
6
6
  mayCreatePullRequest
7
- } from "./chunk-24FE3TDH.js";
7
+ } from "./chunk-BU5GP3VV.js";
8
8
 
9
9
  // src/services/post-tool-pr-notifier.ts
10
10
  async function notifyPostToolUse(toolName, toolInput, toolResult) {
@@ -161,6 +161,7 @@ var DEEPSEEK_V4_FLASH_MODEL = "deepseek/deepseek-v4-flash-0731";
161
161
  var DEFAULT_DEEPSEEK_MODEL = DEEPSEEK_V4_PRO_MODEL;
162
162
  var DEFAULT_FX_MODEL = "zai/glm-5.2";
163
163
  var DEFAULT_KIMI_MODEL = "moonshotai/kimi-k2.6";
164
+ var MUSE_SPARK_1_3_MODEL = "muse-spark-1.3";
164
165
  var DEFAULT_MUSE_MODEL = "muse-spark-1.2";
165
166
  var DEFAULT_PI_MODEL = DEFAULT_OPENCODE_MODEL;
166
167
  var OPENROUTER_MODELS = [
@@ -172,6 +173,7 @@ var OPENROUTER_MODELS = [
172
173
  "minimax/minimax-m3",
173
174
  "xiaomi/mimo-v2.5-pro",
174
175
  "moonshotai/kimi-k2.6",
176
+ "meta/muse-spark-1.3",
175
177
  "google/gemini-3.8-flash"
176
178
  ];
177
179
  function prioritizeDeepseekModels(models) {
@@ -284,7 +286,7 @@ var AGENT_MODELS = {
284
286
  deepseek: prioritizeDeepseekModels(OPENROUTER_MODELS),
285
287
  fx: [DEFAULT_FX_MODEL],
286
288
  kimi: [DEFAULT_KIMI_MODEL],
287
- muse: [DEFAULT_MUSE_MODEL],
289
+ muse: [MUSE_SPARK_1_3_MODEL, DEFAULT_MUSE_MODEL],
288
290
  opencode: [...OPENROUTER_MODELS, ...ASTER_MODELS],
289
291
  pi: [...OPENROUTER_MODELS, ...ASTER_MODELS],
290
292
  relay: [CLAUDE_FABLE_5_1_MODEL, CLAUDE_FABLE_5_MODEL, CLAUDE_OPUS_5_MODEL, CLAUDE_OPUS_4_8_MODEL, CLAUDE_SONNET_5_MODEL]
@@ -328,7 +330,9 @@ var MODEL_LABELS = {
328
330
  "minimax/minimax-m3": "MiniMax M3 via OpenRouter",
329
331
  "xiaomi/mimo-v2.5-pro": "MiMo V2.5 Pro via OpenRouter",
330
332
  "moonshotai/kimi-k2.6": "Kimi K2.6 via OpenRouter",
333
+ [MUSE_SPARK_1_3_MODEL]: "Muse Spark 1.3",
331
334
  [DEFAULT_MUSE_MODEL]: "Muse Spark 1.2",
335
+ "meta/muse-spark-1.3": "Muse Spark 1.3 via OpenRouter",
332
336
  "google/gemini-3.8-flash": "Gemini 3.8 Flash via OpenRouter",
333
337
  ...ASTER_MODEL_LABELS,
334
338
  "gpt-5.4": "GPT-5.4",
@@ -1050,6 +1054,13 @@ var SANDBOX_PATHS = {
1050
1054
  var WORKSPACE_SIZES = ["small", "large"];
1051
1055
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
1052
1056
 
1057
+ // ../shared/src/github/url.ts
1058
+ var GITHUB_HOST_RE = /(^|@|\/\/)github\.com[:/]/;
1059
+ function isGitHubUrl(url) {
1060
+ if (!url) return false;
1061
+ return GITHUB_HOST_RE.test(url);
1062
+ }
1063
+
1053
1064
  // ../shared/src/runtime-env.ts
1054
1065
  var REPLICAS_RUNTIME_ENV_ALIASES = {
1055
1066
  monolithUrl: ["REPLICAS_MONOLITH_URL", "MONOLITH_URL"],
@@ -1125,13 +1136,45 @@ function parsePosixEnvFile(content) {
1125
1136
  var GIT_CREDENTIAL_HELPER_FILENAME = ".git-credential-replicas";
1126
1137
  var GITHUB_CREDENTIAL_REFRESH_PATH = "/git-credentials/github/refresh";
1127
1138
  var GITLAB_CREDENTIAL_REFRESH_PATH = "/git-credentials/gitlab/refresh";
1139
+ function githubOwnerTokens(access) {
1140
+ const ownerTokens = /* @__PURE__ */ new Map();
1141
+ for (const [repository, token] of Object.entries(access)) {
1142
+ const owner = repository.split("/")[0];
1143
+ if (!owner) continue;
1144
+ const tokens = ownerTokens.get(owner) ?? /* @__PURE__ */ new Set();
1145
+ tokens.add(token);
1146
+ ownerTokens.set(owner, tokens);
1147
+ }
1148
+ return ownerTokens;
1149
+ }
1150
+ function githubCredentialLines(access) {
1151
+ if (typeof access === "string") return [`https://x-access-token:${access}@github.com`];
1152
+ const entries = Object.entries(access);
1153
+ const ownerTokens = githubOwnerTokens(access);
1154
+ return [...entries.flatMap(([repository, token]) => [
1155
+ `https://x-access-token:${token}@github.com/${repository}`,
1156
+ `https://x-access-token:${token}@github.com/${repository}.git`
1157
+ ]), ...[...ownerTokens].flatMap(([owner, tokens]) => tokens.size === 1 ? [`https://x-access-token:${[...tokens][0]}@github.com/${owner}`] : [])];
1158
+ }
1128
1159
  function buildGitCredentialHelperScript(credentialsPath) {
1129
1160
  return `#!/bin/sh
1130
1161
  request=$(cat)
1162
+ if printf '%s
1163
+ ' "$request" | grep -q '^host=github.com$'; then
1164
+ request=$(printf '%s
1165
+ ' "$request" | awk '/^path=/ { $0 = tolower($0) } { print }')
1166
+ fi
1131
1167
 
1132
1168
  get_credential() {
1169
+ credential=$(printf '%s
1170
+ ' "$request" | git credential-store --file=${shellQuotePosix(credentialsPath)} get)
1171
+ if [ -z "$credential" ] && printf '%s
1172
+ ' "$request" | grep -q '^host=github.com$'; then
1173
+ credential=$(printf '%s
1174
+ ' "$request" | sed 's|^path=\\([^/]*\\)/.*|path=\\1|' | git credential-store --file=${shellQuotePosix(credentialsPath)} get)
1175
+ fi
1133
1176
  printf '%s
1134
- ' "$request" | git credential-store --file=${shellQuotePosix(credentialsPath)} get
1177
+ ' "$credential"
1135
1178
  }
1136
1179
 
1137
1180
  refresh_credential() {
@@ -1659,13 +1702,6 @@ function skillNamesFromCommand(command) {
1659
1702
  })));
1660
1703
  }
1661
1704
 
1662
- // ../shared/src/github/url.ts
1663
- var GITHUB_HOST_RE = /(^|@|\/\/)github\.com[:/]/;
1664
- function isGitHubUrl(url) {
1665
- if (!url) return false;
1666
- return GITHUB_HOST_RE.test(url);
1667
- }
1668
-
1669
1705
  // ../shared/src/urls.ts
1670
1706
  var HOME_PATH = "/home";
1671
1707
  var DASHBOARD_PATH = "/dashboard";
@@ -2052,6 +2088,8 @@ If authenticated, you can immediately use \`gh\` for all GitHub operations. No a
2052
2088
 
2053
2089
  The GitHub CLI (\`gh\`) is the recommended way to interact with GitHub. It handles authentication, pagination, and API formatting automatically.
2054
2090
 
2091
+ In a workspace spanning GitHub owners, run \`gh\` inside the target checkout or pass \`--repo owner/repo\`. For \`gh api graphql\`, set \`GH_REPO=owner/repo\`; SDK GraphQL requests use the \`repository\` option to select the account. Each request uses one account.
2092
+
2055
2093
  ### Pull Requests
2056
2094
 
2057
2095
  \`\`\`bash
@@ -2133,6 +2171,7 @@ await replicas.github.request('/repos/owner/repo/issues/123/comments', {
2133
2171
  });
2134
2172
 
2135
2173
  const result = await replicas.github.request('/graphql', {
2174
+ repository: 'owner/repo',
2136
2175
  method: 'POST',
2137
2176
  body: { query: '{ viewer { login } }' },
2138
2177
  });
@@ -2242,7 +2281,7 @@ var REFERENCE5 = `# Linear Integration
2242
2281
 
2243
2282
  Use \`@replicas/sdk\`; never request or handle a Linear OAuth token. Replicas refreshes the organization credential behind the gateway.
2244
2283
 
2245
- In gateway-enabled workspaces, Linear credentials stay on the Replicas server and the workspace receives only connection metadata. Older workspaces can still carry a legacy token snapshot, but should use the gateway when the SDK is available. A missing Linear MCP server does not prevent SDK access.
2284
+ In all new workspaces, Linear credentials stay on the Replicas server and the workspace receives only connection metadata. Older workspaces can still carry a legacy token snapshot, but should use the gateway when the SDK is available. A missing Linear MCP server does not prevent SDK access.
2246
2285
 
2247
2286
  Download protected attachments with \`await replicas.linear.download(url)\`; this returns a \`Response\` without exposing the provider token.
2248
2287
 
@@ -2312,9 +2351,9 @@ Search with \`containsIgnoreCase: $query\` filters, for example on both \`title\
2312
2351
  If \`@replicas/sdk\` cannot be imported, use the same refresh-capable gateway with workspace authentication. Send the GraphQL JSON request on stdin:
2313
2352
 
2314
2353
  \`\`\`bash
2315
- curl -sS --fail-with-body -X POST "$REPLICAS_MONOLITH_URL/v1/engine/linear/graphql" \\
2354
+ curl -sS --fail-with-body -X POST "\${REPLICAS_MONOLITH_URL:-$MONOLITH_URL}/v1/engine/linear/graphql" \\
2316
2355
  -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
2317
- -H "X-Workspace-Id: $REPLICAS_WORKSPACE_ID" \\
2356
+ -H "X-Workspace-Id: \${REPLICAS_WORKSPACE_ID:-$WORKSPACE_ID}" \\
2318
2357
  -H "Content-Type: application/json" \\
2319
2358
  --data-binary @-
2320
2359
  \`\`\`
@@ -3341,11 +3380,23 @@ const [messages, users] = await Promise.all([
3341
3380
  \`\`\`
3342
3381
 
3343
3382
  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.
3383
+
3384
+ ## Older workspaces without the SDK
3385
+
3386
+ If \`@replicas/sdk\` cannot be imported, use the gateway with workspace authentication. Send JSON containing \`method\` and \`arguments\` on stdin, for example \`{"method":"conversations.list","arguments":{"limit":3,"types":"public_channel"}}\`:
3387
+
3388
+ \`\`\`bash
3389
+ curl -sS --fail-with-body -X POST "\${REPLICAS_MONOLITH_URL:-$MONOLITH_URL}/v1/engine/slack/api" \\
3390
+ -H "Authorization: Bearer $REPLICAS_ENGINE_SECRET" \\
3391
+ -H "X-Workspace-Id: \${REPLICAS_WORKSPACE_ID:-$WORKSPACE_ID}" \\
3392
+ -H "Content-Type: application/json" \\
3393
+ --data-binary @-
3394
+ \`\`\`
3344
3395
  `;
3345
3396
  var SLACK_ABILITY = {
3346
3397
  label: "Slack",
3347
3398
  description: "Send messages, read threads, search, and transfer files through @replicas/sdk.",
3348
- bullet: "- Interacting with Slack (sending messages, reading threads, etc.)",
3399
+ bullet: "- Interacting with Slack (listing channels, sending messages, reading threads, or searching): use replicas.slack.call from @replicas/sdk. Read references/SLACK.md; no Slack MCP server or provider token in the VM is required.",
3349
3400
  section: SECTION12,
3350
3401
  referenceFile: { name: "SLACK.md", content: REFERENCE12 }
3351
3402
  };
@@ -7530,6 +7581,7 @@ export {
7530
7581
  GIT_CREDENTIAL_HELPER_FILENAME,
7531
7582
  GITHUB_CREDENTIAL_REFRESH_PATH,
7532
7583
  GITLAB_CREDENTIAL_REFRESH_PATH,
7584
+ githubCredentialLines,
7533
7585
  buildGitCredentialHelperScript,
7534
7586
  parseGitRemote,
7535
7587
  gitIdentityConfigCommands,
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  HOOK_EXEC_MAX_BUFFER_BYTES,
6
6
  isVersionBelow
7
- } from "./chunk-24FE3TDH.js";
7
+ } from "./chunk-BU5GP3VV.js";
8
8
 
9
9
  // src/utils/codex-agent-env.ts
10
10
  function buildCodexAgentEnv(source = process.env) {
@@ -241,7 +241,7 @@ var DEFAULT_CODEX_ARGS = [
241
241
  var MIN_CODEX_CLI_VERSION = "0.153.3";
242
242
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
243
243
  var codexCliVersionEnsured = null;
244
- var ENGINE_PACKAGE_VERSION = "0.1.759";
244
+ var ENGINE_PACKAGE_VERSION = "0.1.761";
245
245
  var INITIALIZE_METHOD = "initialize";
246
246
  var INITIALIZED_NOTIFICATION = "initialized";
247
247
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -15,7 +15,7 @@ import {
15
15
  isValidRelayBaseProvider,
16
16
  parsePosixEnvFile,
17
17
  readReplicasRuntimeEnv
18
- } from "./chunk-24FE3TDH.js";
18
+ } from "./chunk-BU5GP3VV.js";
19
19
 
20
20
  // src/engine-env.ts
21
21
  import { readFileSync as readFileSync2 } from "fs";
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  monolithRequest
6
- } from "./chunk-WTNFZX53.js";
6
+ } from "./chunk-VI2PM3UG.js";
7
7
  import {
8
8
  extractCommandProtectionCommandText,
9
9
  findGitCommitSignals,
10
10
  findPrMergeSignals
11
- } from "./chunk-24FE3TDH.js";
11
+ } from "./chunk-BU5GP3VV.js";
12
12
 
13
13
  // src/services/command-protection-service.ts
14
14
  var DEFAULT_COMMAND_PROTECTION_BLOCK_MESSAGE = "Blocked by Replicas command protection.";
@@ -3,12 +3,12 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  evaluateCommandProtection
6
- } from "./chunk-2N4HGHFZ.js";
7
- import "./chunk-WTNFZX53.js";
6
+ } from "./chunk-VMTI7O6V.js";
7
+ import "./chunk-VI2PM3UG.js";
8
8
  import {
9
9
  isRecord
10
10
  } from "./chunk-UZSNFLDQ.js";
11
- import "./chunk-24FE3TDH.js";
11
+ import "./chunk-BU5GP3VV.js";
12
12
  import "./chunk-VEQXQN22.js";
13
13
 
14
14
  // src/command-protection-hook.ts
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  evaluateCommandProtection
6
- } from "./chunk-2N4HGHFZ.js";
6
+ } from "./chunk-VMTI7O6V.js";
7
7
  import {
8
8
  notifyPostToolUse
9
- } from "./chunk-FTXE5FES.js";
10
- import "./chunk-WTNFZX53.js";
9
+ } from "./chunk-6M2VM5RC.js";
10
+ import "./chunk-VI2PM3UG.js";
11
11
  import "./chunk-UZSNFLDQ.js";
12
- import "./chunk-24FE3TDH.js";
12
+ import "./chunk-BU5GP3VV.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/deepseek-command-protection-plugin.ts
@@ -8,12 +8,12 @@ import {
8
8
  import {
9
9
  AppServerProcess,
10
10
  buildCodexAgentEnv
11
- } from "./chunk-52SXO2DU.js";
11
+ } from "./chunk-PWF56YNB.js";
12
12
  import {
13
13
  AGENT,
14
14
  getMemoryOutputSafetyViolation,
15
15
  headlessAgentRequestSchema
16
- } from "./chunk-24FE3TDH.js";
16
+ } from "./chunk-BU5GP3VV.js";
17
17
  import "./chunk-VEQXQN22.js";
18
18
 
19
19
  // src/headless-agent.ts
package/dist/src/index.js CHANGED
@@ -91,7 +91,7 @@ import {
91
91
  evaluateCommandProtection,
92
92
  extractToolCommand,
93
93
  reportCommandProtectionBlock
94
- } from "./chunk-2N4HGHFZ.js";
94
+ } from "./chunk-VMTI7O6V.js";
95
95
  import {
96
96
  ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
97
97
  AGENT_MESSAGE_DELTA_METHOD,
@@ -124,20 +124,20 @@ import {
124
124
  recordCredentialFallback,
125
125
  recordExhaustedCredential,
126
126
  restartCodexAspHost
127
- } from "./chunk-JQHGDJE4.js";
127
+ } from "./chunk-47DDGIVB.js";
128
128
  import {
129
129
  ENGINE_ENV,
130
130
  IS_WARMING_MODE,
131
131
  monolithRequest,
132
132
  monolithService,
133
133
  setAgentCredentialSnapshot
134
- } from "./chunk-WTNFZX53.js";
134
+ } from "./chunk-VI2PM3UG.js";
135
135
  import {
136
136
  AspClient,
137
137
  SUBPROCESS_MAX_BUFFER,
138
138
  execAsync,
139
139
  execFileAsync
140
- } from "./chunk-52SXO2DU.js";
140
+ } from "./chunk-PWF56YNB.js";
141
141
  import {
142
142
  isRecord as isRecord2
143
143
  } from "./chunk-UZSNFLDQ.js";
@@ -271,6 +271,7 @@ import {
271
271
  getUserMessage,
272
272
  getUserMessageId,
273
273
  gitIdentityConfigCommands,
274
+ githubCredentialLines,
274
275
  hasChatStarted,
275
276
  imageContentToUserMessageImages,
276
277
  isAgentBackendEvent,
@@ -331,7 +332,7 @@ import {
331
332
  spawnRelaySubagentRequestSchema,
332
333
  stripAgentDiagnosticErrors,
333
334
  withTimeout
334
- } from "./chunk-24FE3TDH.js";
335
+ } from "./chunk-BU5GP3VV.js";
335
336
  import {
336
337
  __commonJS,
337
338
  __export,
@@ -8572,6 +8573,9 @@ async function configureManagedGitCredentialHelper(homeDir) {
8572
8573
  await execFileAsync("git", ["config", "--global", "credential.helper", helperPath], {
8573
8574
  env: { ...process.env, HOME: homeDir }
8574
8575
  });
8576
+ await execFileAsync("git", ["config", "--global", "credential.https://github.com.useHttpPath", "true"], {
8577
+ env: { ...process.env, HOME: homeDir }
8578
+ });
8575
8579
  }
8576
8580
  var credentialFileLock = new AsyncLock();
8577
8581
  function upsertCredentialFileLines(filePath, hosts, lines) {
@@ -8582,7 +8586,7 @@ function upsertCredentialFileLines(filePath, hosts, lines) {
8582
8586
  } catch {
8583
8587
  existing = [];
8584
8588
  }
8585
- const kept = existing.filter((line) => !hosts.some((host) => line.endsWith(`@${host}`)));
8589
+ const kept = existing.filter((line) => !hosts.some((host) => line.endsWith(`@${host}`) || line.includes(`@${host}/`)));
8586
8590
  await writeSecureCredentialFile(filePath, [...lines, ...kept, ""].join("\n"));
8587
8591
  });
8588
8592
  }
@@ -9296,7 +9300,7 @@ var GitHubTokenManager = class extends BaseRefreshManager {
9296
9300
  const data = await response.json();
9297
9301
  const ghToken = data.userToken?.token ?? data.token;
9298
9302
  const ghUsername = data.userToken?.username ?? "x-access-token";
9299
- await this.updateGitCredentials(ghToken);
9303
+ await this.updateGitCredentials(data.repositoryTokens ?? ghToken);
9300
9304
  await this.updateGhHostsFile(ghToken, ghUsername);
9301
9305
  if (data.gitIdentity) {
9302
9306
  await updateGitIdentity(data.gitIdentity, "GitHubTokenManager", ["github.com"]);
@@ -9310,9 +9314,7 @@ var GitHubTokenManager = class extends BaseRefreshManager {
9310
9314
  async updateGitCredentials(token) {
9311
9315
  const credentialsPath = path.join(ENGINE_ENV.HOME_DIR, ".git-credentials");
9312
9316
  try {
9313
- await upsertCredentialFileLines(credentialsPath, ["github.com"], [
9314
- `https://x-access-token:${token}@github.com`
9315
- ]);
9317
+ await upsertCredentialFileLines(credentialsPath, ["github.com"], githubCredentialLines(token));
9316
9318
  console.log(`[GitHubTokenManager] Updated ${credentialsPath}`);
9317
9319
  } catch (error) {
9318
9320
  console.error("[GitHubTokenManager] Failed to update git credentials:", error);
@@ -9320,11 +9322,11 @@ var GitHubTokenManager = class extends BaseRefreshManager {
9320
9322
  }
9321
9323
  async updateGhHostsFile(token, username) {
9322
9324
  const hostsPath = path.join(ENGINE_ENV.HOME_DIR, ".config", "gh", "hosts.yml");
9323
- const content = `github.com:
9325
+ const content = token ? `github.com:
9324
9326
  oauth_token: ${JSON.stringify(token)}
9325
9327
  user: ${JSON.stringify(username)}
9326
9328
  git_protocol: https
9327
- `;
9329
+ ` : "";
9328
9330
  try {
9329
9331
  await writeSecureCredentialFile(hostsPath, content, { ensureParentDir: true });
9330
9332
  console.log(`[GitHubTokenManager] Updated ${hostsPath}`);
@@ -9336,8 +9338,9 @@ var GitHubTokenManager = class extends BaseRefreshManager {
9336
9338
  const credentialsPath = path.join(ENGINE_ENV.HOME_DIR, ".git-credentials");
9337
9339
  await removeCredentialFileLines(
9338
9340
  credentialsPath,
9339
- (line) => line.endsWith("@github.com")
9341
+ (line) => /^https:\/\/[^/]+@github\.com(?:\/|$)/.test(line)
9340
9342
  );
9343
+ await this.updateGhHostsFile("", "x-access-token");
9341
9344
  }
9342
9345
  };
9343
9346
  var githubTokenManager = new GitHubTokenManager();
@@ -3,11 +3,11 @@ import { createRequire as __createRequire } from 'node:module';
3
3
  const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  notifyPostToolUse
6
- } from "./chunk-FTXE5FES.js";
6
+ } from "./chunk-6M2VM5RC.js";
7
7
  import {
8
8
  isRecord
9
9
  } from "./chunk-UZSNFLDQ.js";
10
- import "./chunk-24FE3TDH.js";
10
+ import "./chunk-BU5GP3VV.js";
11
11
  import "./chunk-VEQXQN22.js";
12
12
 
13
13
  // src/post-tool-pr-hook.ts
@@ -4,7 +4,7 @@ const require = __createRequire(import.meta.url);
4
4
  import {
5
5
  messageRelaySubagentRequestSchema,
6
6
  spawnRelaySubagentRequestSchema
7
- } from "./chunk-24FE3TDH.js";
7
+ } from "./chunk-BU5GP3VV.js";
8
8
  import "./chunk-VEQXQN22.js";
9
9
 
10
10
  // src/relay-mcp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.759",
3
+ "version": "0.1.761",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -19,7 +19,8 @@
19
19
  "scripts/opencode-command-protection-plugin.ts",
20
20
  "scripts/deepseek",
21
21
  "scripts/engine-watchdog.sh",
22
- "scripts/lockmem.c"
22
+ "scripts/lockmem.c",
23
+ "scripts/gh.cjs"
23
24
  ],
24
25
  "scripts": {
25
26
  "dev": "tsx watch --conditions=development src/index.ts",
package/scripts/gh.cjs ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ const { spawnSync } = require('node:child_process');
3
+
4
+ const args = process.argv.slice(2);
5
+ const env = { ...process.env };
6
+ const hostnameIndex = args.indexOf('--hostname');
7
+ const hostname =
8
+ hostnameIndex >= 0
9
+ ? args[hostnameIndex + 1]
10
+ : args.find((arg) => arg.startsWith('--hostname='))?.slice(11);
11
+ const needsCredentials =
12
+ !['version', 'help', 'completion'].includes(args[0]) &&
13
+ !args.some((arg) => ['--version', '--help', '-h'].includes(arg));
14
+ if (
15
+ needsCredentials &&
16
+ !env.GH_TOKEN &&
17
+ !env.GITHUB_TOKEN &&
18
+ (!hostname || hostname === 'github.com') &&
19
+ (!env.GH_HOST || env.GH_HOST === 'github.com')
20
+ ) {
21
+ let repository;
22
+ for (let i = 0; i < args.length; i++) {
23
+ if (args[i] === '-R' || args[i] === '--repo') repository = args[++i];
24
+ else if (args[i].startsWith('--repo=')) repository = args[i].slice(7);
25
+ else if (args[i].startsWith('-R')) repository = args[i].slice(2);
26
+ }
27
+ const endpointRepository =
28
+ args[0] === 'api'
29
+ ? args
30
+ .slice(1)
31
+ .map((arg) => arg.match(/^\/?repos\/([^/]+\/[^/?]+)(?:[/?]|$)/)?.[1])
32
+ .find(Boolean)
33
+ : args[2]?.match(/^https:\/\/github\.com\/([^/]+\/[^/?]+)(?:[/?]|$)/)?.[1];
34
+ const positionalRepository = args[0] === 'repo' && args[1] === 'clone' ? args[2] : undefined;
35
+ repository =
36
+ (endpointRepository?.includes('{') ? undefined : endpointRepository) ||
37
+ repository ||
38
+ positionalRepository ||
39
+ env.GH_REPO;
40
+ if (!repository) {
41
+ const remote = spawnSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8' });
42
+ if (remote.status === 0) repository = remote.stdout.trim();
43
+ }
44
+ const slug = repository
45
+ ?.replace(
46
+ /^(?:https:\/\/github\.com\/|ssh:\/\/git@github\.com\/|git@github\.com:|github\.com\/)/,
47
+ '',
48
+ )
49
+ .replace(/\/$/, '')
50
+ .replace(/\.git$/, '')
51
+ .toLowerCase();
52
+ if (slug) {
53
+ const credential = spawnSync('git', ['credential', 'fill'], {
54
+ encoding: 'utf8',
55
+ input: `protocol=https\nhost=github.com\npath=${slug}.git\n\n`,
56
+ });
57
+ if (credential.status === 0) env.GH_TOKEN = credential.stdout.match(/^password=(.*)$/m)?.[1];
58
+ }
59
+ if (!env.GH_TOKEN && !(args[0] === 'auth' && args[1] === 'status' && !repository)) {
60
+ process.stderr.write(
61
+ 'Select a repository in this workspace: run gh inside its checkout, use --repo OWNER/REPO, or set GH_REPO=OWNER/REPO.\n',
62
+ );
63
+ process.exit(1);
64
+ }
65
+ }
66
+ const child = spawnSync('/usr/bin/gh', args, { env, stdio: 'inherit' });
67
+ if (child.error) {
68
+ process.stderr.write(`${child.error.message}\n`);
69
+ process.exit(1);
70
+ }
71
+ if (child.signal) process.kill(process.pid, child.signal);
72
+ else process.exit(child.status ?? 1);
@@ -107,7 +107,7 @@ const slack = {
107
107
  }),
108
108
  };
109
109
 
110
- const github = providerClient('/v1/engine/github/api');
110
+ const github = providerClient('/v1/engine/github/api', (options) => ({ repository: options.repository }));
111
111
 
112
112
  const gitlab = providerClient('/v1/engine/gitlab/api', (options) => ({ host: options.host }));
113
113
 
@@ -107,6 +107,8 @@ describe('@replicas/sdk', () => {
107
107
  process.env.REPLICAS_ENGINE_SECRET = 'engine-secret';
108
108
  process.env.REPLICAS_WORKSPACE_ID = 'workspace-1';
109
109
  try {
110
+ await replicas.github.request('/graphql', { repository: 'frontend/web', method: 'POST', body: { query: '{ viewer { login } }' } });
111
+ expect(observed?.body).toEqual({ path: '/graphql', repository: 'frontend/web', method: 'POST', body: { query: '{ viewer { login } }' } });
110
112
  await replicas.github.request('/user');
111
113
  expect(observed).toEqual({
112
114
  path: '/v1/engine/github/api',
@@ -40,7 +40,9 @@ export interface ReplicasSdk {
40
40
  }>;
41
41
  };
42
42
  github: {
43
- request<T = unknown>(path: string, options?: ProviderRequestOptions): Promise<T>;
43
+ request<T = unknown>(path: string, options?: ProviderRequestOptions & {
44
+ repository?: string;
45
+ }): Promise<T>;
44
46
  };
45
47
  gitlab: {
46
48
  request<T = unknown>(path: string, options?: ProviderRequestOptions & {