replicas-engine 0.1.1028 → 0.1.1029
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/{asp-host-A57BJZPM.js → asp-host-2QL3R5O5.js} +5 -5
- package/dist/src/{chunk-BFHGBJO2.js → chunk-BOAIMJKK.js} +33 -4
- package/dist/src/{chunk-DU4QTHOX.js → chunk-DWWWY7HA.js} +6 -6
- package/dist/src/{chunk-3OGTHVR4.js → chunk-E35XSXJE.js} +1 -1
- package/dist/src/{chunk-CFLUSFBP.js → chunk-HIRAX6GE.js} +1 -1
- package/dist/src/{chunk-OK37MIB6.js → chunk-IPOU7CXA.js} +1 -1
- package/dist/src/{chunk-LY4WTFXS.js → chunk-SMKDV5DS.js} +3 -3
- package/dist/src/{chunk-AWQZGS2I.js → chunk-UMI7BLA3.js} +3 -3
- package/dist/src/command-protection-hook.js +4 -4
- package/dist/src/headless-agent.js +3 -3
- package/dist/src/index.js +165 -64
- package/dist/src/post-tool-pr-hook.js +2 -2
- package/dist/src/subagent-mcp.js +1 -1
- package/package.json +1 -1
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
getCodexAspHost,
|
|
6
6
|
restartCodexAspHost,
|
|
7
7
|
restartCodexAspHostIfRunning
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-DWWWY7HA.js";
|
|
9
|
+
import "./chunk-IPOU7CXA.js";
|
|
10
|
+
import "./chunk-SMKDV5DS.js";
|
|
11
|
+
import "./chunk-HIRAX6GE.js";
|
|
12
12
|
import "./chunk-UZSNFLDQ.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-BOAIMJKK.js";
|
|
14
14
|
import "./chunk-VEQXQN22.js";
|
|
15
15
|
export {
|
|
16
16
|
getCodexAspHost,
|
|
@@ -1548,6 +1548,19 @@ var mcpWorkloadAuthSchema = z4.strictObject({
|
|
|
1548
1548
|
type: z4.literal("workspace_identity"),
|
|
1549
1549
|
audience: workspaceAudienceSchema
|
|
1550
1550
|
});
|
|
1551
|
+
var mcpAuthSchema = z4.discriminatedUnion("type", [
|
|
1552
|
+
mcpWorkloadAuthSchema,
|
|
1553
|
+
z4.strictObject({ type: z4.literal("oauth") })
|
|
1554
|
+
]);
|
|
1555
|
+
var engineMcpOAuthTokenRequestSchema = z4.object({
|
|
1556
|
+
environment_mcp_id: z4.string().uuid(),
|
|
1557
|
+
force_refresh: z4.boolean().optional()
|
|
1558
|
+
});
|
|
1559
|
+
var engineMcpOAuthTokenResponseSchema = z4.object({
|
|
1560
|
+
url: z4.string(),
|
|
1561
|
+
access_token: z4.string(),
|
|
1562
|
+
expires_at: z4.string().nullable()
|
|
1563
|
+
});
|
|
1551
1564
|
|
|
1552
1565
|
// ../shared/src/runtime-env.ts
|
|
1553
1566
|
var REPLICAS_RUNTIME_ENV_ALIASES = {
|
|
@@ -2748,15 +2761,30 @@ function createUuidFromHex(value) {
|
|
|
2748
2761
|
}
|
|
2749
2762
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2750
2763
|
|
|
2764
|
+
// ../shared/src/automations/github/index.ts
|
|
2765
|
+
var REVIEW_REQUESTED_EVENT = "pull_request.review_requested";
|
|
2766
|
+
|
|
2751
2767
|
// ../shared/src/automations/trigger-schemas.ts
|
|
2768
|
+
function getReviewerLoginsError(event, logins) {
|
|
2769
|
+
const isReviewRequested = event === REVIEW_REQUESTED_EVENT;
|
|
2770
|
+
if (isReviewRequested === !!logins?.some((login) => login.trim().replace(/^@+/, ""))) return null;
|
|
2771
|
+
return isReviewRequested ? "The PR review requested trigger needs at least one GitHub username" : "Requested reviewers only apply to the PR review requested trigger";
|
|
2772
|
+
}
|
|
2752
2773
|
var repositoryTriggerConfigSchema = z10.object({
|
|
2753
2774
|
event: z10.string(),
|
|
2754
2775
|
repository_ids: z10.array(z10.string().regex(UUID_RE, "must be a repository id")).optional(),
|
|
2755
2776
|
group_pr_events: z10.boolean().optional(),
|
|
2756
|
-
excluded_actors: z10.array(z10.string()).optional()
|
|
2777
|
+
excluded_actors: z10.array(z10.string()).optional(),
|
|
2778
|
+
reviewer_logins: z10.array(z10.string()).optional()
|
|
2757
2779
|
});
|
|
2758
2780
|
var cronTriggerSchema = z10.object({ type: z10.literal("cron"), config: z10.object({ schedule: z10.string(), timezone: z10.string().optional() }) });
|
|
2759
|
-
var githubTriggerSchema = z10.object({
|
|
2781
|
+
var githubTriggerSchema = z10.object({
|
|
2782
|
+
type: z10.literal("github"),
|
|
2783
|
+
config: repositoryTriggerConfigSchema.superRefine((config, ctx) => {
|
|
2784
|
+
const message2 = getReviewerLoginsError(config.event, config.reviewer_logins);
|
|
2785
|
+
if (message2) ctx.addIssue({ code: "custom", message: message2, path: ["reviewer_logins"] });
|
|
2786
|
+
})
|
|
2787
|
+
});
|
|
2760
2788
|
var gitlabTriggerSchema = z10.object({ type: z10.literal("gitlab"), config: repositoryTriggerConfigSchema });
|
|
2761
2789
|
var automationTriggerSchema = z10.discriminatedUnion("type", [
|
|
2762
2790
|
cronTriggerSchema,
|
|
@@ -2776,7 +2804,7 @@ var createEnvironmentMcpRequestSchema = z11.object({
|
|
|
2776
2804
|
transport: z11.enum(ENVIRONMENT_MCP_TRANSPORTS),
|
|
2777
2805
|
config: z11.union([
|
|
2778
2806
|
z11.object({ command: z11.string().min(1), args: z11.array(z11.string()).optional(), env: stringMap.optional() }),
|
|
2779
|
-
z11.object({ url: z11.url(), headers: stringMap.optional(), auth:
|
|
2807
|
+
z11.object({ url: z11.url(), headers: stringMap.optional(), auth: mcpAuthSchema.optional() })
|
|
2780
2808
|
]).describe("stdio: `{ command, args, env }`. http/sse: `{ url, headers }`.")
|
|
2781
2809
|
});
|
|
2782
2810
|
var updateEnvironmentMcpRequestSchema = createEnvironmentMcpRequestSchema.partial();
|
|
@@ -3377,7 +3405,7 @@ Trigger shapes:
|
|
|
3377
3405
|
{ "type": "cron", "config": { "schedule": "0 9 * * 1-5", "timezone": "UTC" } }
|
|
3378
3406
|
\`\`\`
|
|
3379
3407
|
|
|
3380
|
-
GitHub events: \`pull_request.opened\`, \`pull_request.synchronize\`, \`pull_request.merged\`, \`pull_request.closed\`. GitLab events: \`merge_request.opened\`, \`merge_request.updated\`, \`merge_request.merged\`, \`merge_request.closed\`. Use one trigger type family per automation and pick the code host the repositories actually live on.
|
|
3408
|
+
GitHub events: \`pull_request.opened\`, \`pull_request.synchronize\`, \`pull_request.review_requested\` (requires a \`reviewer_logins\` list of GitHub usernames), \`pull_request.merged\`, \`pull_request.closed\`. GitLab events: \`merge_request.opened\`, \`merge_request.updated\`, \`merge_request.merged\`, \`merge_request.closed\`. Use one trigger type family per automation and pick the code host the repositories actually live on.
|
|
3381
3409
|
|
|
3382
3410
|
Test the hooks before proposing them: run the drafted warm hook and start hook scripts in this workspace (from \`~/workspaces\`) and fix the earliest failure until both exit 0 on a second run.
|
|
3383
3411
|
|
|
@@ -9358,6 +9386,7 @@ export {
|
|
|
9358
9386
|
workspaceTokenRequestSchema,
|
|
9359
9387
|
workspaceTokenResponseSchema,
|
|
9360
9388
|
legacyWorkspaceTokenBundleSchema,
|
|
9389
|
+
engineMcpOAuthTokenResponseSchema,
|
|
9361
9390
|
SANDBOX_SKILL_DIRS,
|
|
9362
9391
|
HISTORY_ROOT,
|
|
9363
9392
|
HISTORY_INDEX_FILENAME,
|
|
@@ -5,15 +5,15 @@ import {
|
|
|
5
5
|
ENGINE_ENV,
|
|
6
6
|
monolithRequest,
|
|
7
7
|
setAgentCredentialSnapshot
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IPOU7CXA.js";
|
|
9
9
|
import {
|
|
10
10
|
AppServerProcess,
|
|
11
11
|
buildCodexAgentEnv
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-SMKDV5DS.js";
|
|
13
13
|
import {
|
|
14
14
|
SUBPROCESS_MAX_BUFFER,
|
|
15
15
|
execFileAsync
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-HIRAX6GE.js";
|
|
17
17
|
import {
|
|
18
18
|
isRecord
|
|
19
19
|
} from "./chunk-UZSNFLDQ.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
listOpenAICompatibleModels,
|
|
29
29
|
readOllamaAuthEnv,
|
|
30
30
|
resolveOpenAICompatibleModelsUrl
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-BOAIMJKK.js";
|
|
32
32
|
|
|
33
33
|
// src/managers/codex-token-manager.ts
|
|
34
34
|
import { promises as fs } from "fs";
|
|
@@ -264,7 +264,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
|
|
|
264
264
|
await this.applyCredentialUpdate(++this.credentialGeneration, async () => {
|
|
265
265
|
await this.applyCredentialsResponse(data);
|
|
266
266
|
setAgentCredentialSnapshot("codex", data);
|
|
267
|
-
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-
|
|
267
|
+
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-2QL3R5O5.js");
|
|
268
268
|
await restartCodexAspHostIfRunning2();
|
|
269
269
|
});
|
|
270
270
|
await this.start(true);
|
|
@@ -285,7 +285,7 @@ var CodexTokenManager = class extends BaseRefreshManager {
|
|
|
285
285
|
const accountChanged = ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS.codex?.credentialId !== data.credentialId;
|
|
286
286
|
await this.applyCredentialsResponse(data);
|
|
287
287
|
if (restartOnChange && (accountChanged || CODEX_AUTH_ENV_KEYS.some((key, index) => process.env[key] !== previousEnv[index]))) {
|
|
288
|
-
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-
|
|
288
|
+
const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-2QL3R5O5.js");
|
|
289
289
|
await restartCodexAspHostIfRunning2();
|
|
290
290
|
}
|
|
291
291
|
setAgentCredentialSnapshot("codex", data);
|
|
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
HOOK_EXEC_MAX_BUFFER_BYTES
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BOAIMJKK.js";
|
|
7
7
|
|
|
8
8
|
// src/utils/exec.ts
|
|
9
9
|
import { exec, execFile } from "child_process";
|
|
@@ -3,10 +3,10 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
execFileAsync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HIRAX6GE.js";
|
|
7
7
|
import {
|
|
8
8
|
isVersionBelow
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BOAIMJKK.js";
|
|
10
10
|
|
|
11
11
|
// src/utils/codex-agent-env.ts
|
|
12
12
|
function buildCodexAgentEnv(source = process.env) {
|
|
@@ -240,7 +240,7 @@ function getCodexModelProvider(method) {
|
|
|
240
240
|
if (method === "foundry") return "azure";
|
|
241
241
|
return method === "ollama" || method === "openai-compatible" ? "replicas_openai_compatible" : "openai";
|
|
242
242
|
}
|
|
243
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
243
|
+
var ENGINE_PACKAGE_VERSION = "0.1.1029";
|
|
244
244
|
var INITIALIZE_METHOD = "initialize";
|
|
245
245
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
246
246
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -3,18 +3,18 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
monolithRequest
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IPOU7CXA.js";
|
|
7
7
|
import {
|
|
8
8
|
SUBPROCESS_MAX_BUFFER,
|
|
9
9
|
execFileAsync
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HIRAX6GE.js";
|
|
11
11
|
import {
|
|
12
12
|
extractCommandProtectionCommandText,
|
|
13
13
|
findCommandProtectionGitLookups,
|
|
14
14
|
findGitCommitSignals,
|
|
15
15
|
findPrMergeSignals,
|
|
16
16
|
parseCommandProtectionRequest
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-BOAIMJKK.js";
|
|
18
18
|
|
|
19
19
|
// src/services/command-protection-service.ts
|
|
20
20
|
import { readFile, stat } from "fs/promises";
|
|
@@ -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-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-UMI7BLA3.js";
|
|
7
|
+
import "./chunk-IPOU7CXA.js";
|
|
8
|
+
import "./chunk-HIRAX6GE.js";
|
|
9
9
|
import {
|
|
10
10
|
isRecord
|
|
11
11
|
} from "./chunk-UZSNFLDQ.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-BOAIMJKK.js";
|
|
13
13
|
import "./chunk-VEQXQN22.js";
|
|
14
14
|
|
|
15
15
|
// src/command-protection-hook.ts
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
AppServerProcess,
|
|
9
9
|
buildCodexAgentEnv
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-SMKDV5DS.js";
|
|
11
|
+
import "./chunk-HIRAX6GE.js";
|
|
12
12
|
import {
|
|
13
13
|
AGENT,
|
|
14
14
|
headlessAgentRequestSchema
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-BOAIMJKK.js";
|
|
16
16
|
import "./chunk-VEQXQN22.js";
|
|
17
17
|
|
|
18
18
|
// src/headless-agent.ts
|
package/dist/src/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
reportCommandProtectionBlock,
|
|
33
33
|
resolveDiffBase,
|
|
34
34
|
runGitCommand
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-UMI7BLA3.js";
|
|
36
36
|
import {
|
|
37
37
|
ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
|
|
38
38
|
AGENT_MESSAGE_DELTA_METHOD,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
} from "./chunk-P73LGPQO.js";
|
|
58
58
|
import {
|
|
59
59
|
publishedPullRequestUrls
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-E35XSXJE.js";
|
|
61
61
|
import {
|
|
62
62
|
BaseRefreshManager,
|
|
63
63
|
CodexAspAuthMethodChangedError,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
refreshDelayMs,
|
|
72
72
|
restartCodexAspHost,
|
|
73
73
|
routineRefreshRequest
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-DWWWY7HA.js";
|
|
75
75
|
import {
|
|
76
76
|
ENGINE_ENV,
|
|
77
77
|
monolithRequest,
|
|
@@ -79,16 +79,16 @@ import {
|
|
|
79
79
|
readRuntimeEnvFile,
|
|
80
80
|
reloadEngineEnv,
|
|
81
81
|
setAgentCredentialSnapshot
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-IPOU7CXA.js";
|
|
83
83
|
import {
|
|
84
84
|
AspClient,
|
|
85
85
|
getCodexModelProvider
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-SMKDV5DS.js";
|
|
87
87
|
import {
|
|
88
88
|
SUBPROCESS_MAX_BUFFER,
|
|
89
89
|
execAsync,
|
|
90
90
|
execFileAsync
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-HIRAX6GE.js";
|
|
92
92
|
import {
|
|
93
93
|
isRecord as isRecord2
|
|
94
94
|
} from "./chunk-UZSNFLDQ.js";
|
|
@@ -218,6 +218,7 @@ import {
|
|
|
218
218
|
detectAgentQuotaLimit,
|
|
219
219
|
detectEnvironmentAuthMethod,
|
|
220
220
|
detectLanguageByPath,
|
|
221
|
+
engineMcpOAuthTokenResponseSchema,
|
|
221
222
|
excludeQueuedAcceptedEvents,
|
|
222
223
|
extractErrorText,
|
|
223
224
|
extractFinalResponse,
|
|
@@ -318,7 +319,7 @@ import {
|
|
|
318
319
|
workspaceTokenRequestSchema,
|
|
319
320
|
workspaceTokenResponseSchema,
|
|
320
321
|
wrapInTag
|
|
321
|
-
} from "./chunk-
|
|
322
|
+
} from "./chunk-BOAIMJKK.js";
|
|
322
323
|
import {
|
|
323
324
|
cloneMcpConfig,
|
|
324
325
|
ensureCompatibilityImports,
|
|
@@ -9636,6 +9637,41 @@ async function applyInfisicalCredentials(data, paths) {
|
|
|
9636
9637
|
}
|
|
9637
9638
|
var infisicalTokenManager = new InfisicalTokenManager();
|
|
9638
9639
|
|
|
9640
|
+
// src/token-cache.ts
|
|
9641
|
+
var TokenCache = class {
|
|
9642
|
+
constructor(maxEntries = Infinity) {
|
|
9643
|
+
this.maxEntries = maxEntries;
|
|
9644
|
+
}
|
|
9645
|
+
maxEntries;
|
|
9646
|
+
cache = /* @__PURE__ */ new Map();
|
|
9647
|
+
inflight = /* @__PURE__ */ new Map();
|
|
9648
|
+
get(key, load, force = false) {
|
|
9649
|
+
const cached = this.cache.get(key);
|
|
9650
|
+
if (!force && cached && cached.refreshAt > Date.now()) return Promise.resolve(createSuccessResult(cached.token));
|
|
9651
|
+
const inflightKey = force ? `${key}\0force` : key;
|
|
9652
|
+
let pending = this.inflight.get(inflightKey);
|
|
9653
|
+
if (!pending) {
|
|
9654
|
+
pending = load().then((result) => {
|
|
9655
|
+
this.cache.delete(key);
|
|
9656
|
+
if (!result.ok) return result;
|
|
9657
|
+
const oldest = this.cache.keys().next();
|
|
9658
|
+
if (this.cache.size >= this.maxEntries && !oldest.done) this.cache.delete(oldest.value);
|
|
9659
|
+
this.cache.set(key, result.data);
|
|
9660
|
+
return createSuccessResult(result.data.token);
|
|
9661
|
+
}).finally(() => this.inflight.delete(inflightKey));
|
|
9662
|
+
this.inflight.set(inflightKey, pending);
|
|
9663
|
+
}
|
|
9664
|
+
return pending;
|
|
9665
|
+
}
|
|
9666
|
+
};
|
|
9667
|
+
async function requestToken(request, path7, body, failureMessage) {
|
|
9668
|
+
try {
|
|
9669
|
+
return createSuccessResult(await request(path7, { body }));
|
|
9670
|
+
} catch (error) {
|
|
9671
|
+
return createErrorResult({ message: error instanceof Error ? error.message : failureMessage, code: 503 });
|
|
9672
|
+
}
|
|
9673
|
+
}
|
|
9674
|
+
|
|
9639
9675
|
// src/workspace-identity-tokens.ts
|
|
9640
9676
|
var MIN_REMAINING_MS = 5 * 60 * 1e3;
|
|
9641
9677
|
var MAX_CACHED_AUDIENCES = 32;
|
|
@@ -9644,30 +9680,19 @@ var WorkspaceIdentityTokens = class {
|
|
|
9644
9680
|
this.request = request;
|
|
9645
9681
|
}
|
|
9646
9682
|
request;
|
|
9647
|
-
|
|
9648
|
-
inflight = /* @__PURE__ */ new Map();
|
|
9683
|
+
tokens = new TokenCache(MAX_CACHED_AUDIENCES);
|
|
9649
9684
|
async get(audience = WORKSPACE_IDENTITY_AUDIENCE, awsSourceIdentity = false) {
|
|
9650
9685
|
const parsed = workspaceAudienceSchema.safeParse(audience);
|
|
9651
9686
|
if (!parsed.success) {
|
|
9652
9687
|
return createErrorResult({ message: parsed.error.issues[0]?.message ?? "Invalid audience", code: 400 });
|
|
9653
9688
|
}
|
|
9654
9689
|
const key = awsSourceIdentity ? `${audience} aws_source_identity` : audience;
|
|
9655
|
-
|
|
9656
|
-
if (cached && Date.parse(cached.expires_at) - Date.now() > MIN_REMAINING_MS) return createSuccessResult(cached);
|
|
9657
|
-
let pending = this.inflight.get(key);
|
|
9658
|
-
if (!pending) {
|
|
9659
|
-
pending = this.mint(audience, awsSourceIdentity, key).finally(() => this.inflight.delete(key));
|
|
9660
|
-
this.inflight.set(key, pending);
|
|
9661
|
-
}
|
|
9662
|
-
return pending;
|
|
9690
|
+
return this.tokens.get(key, () => this.mint(audience, awsSourceIdentity));
|
|
9663
9691
|
}
|
|
9664
|
-
async mint(audience, awsSourceIdentity
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
} catch (error) {
|
|
9669
|
-
return createErrorResult({ message: error instanceof Error ? error.message : "Workspace identity request failed", code: 503 });
|
|
9670
|
-
}
|
|
9692
|
+
async mint(audience, awsSourceIdentity) {
|
|
9693
|
+
const requested = await requestToken(this.request, "/v1/engine/workspace-identity/token", { audience, aws_source_identity: awsSourceIdentity }, "Workspace identity request failed");
|
|
9694
|
+
if (!requested.ok) return requested;
|
|
9695
|
+
const response = requested.data;
|
|
9671
9696
|
if (!response.ok) {
|
|
9672
9697
|
return createErrorResult({ message: `Workspace identity request failed: ${response.status} ${await response.text()}`, code: response.status === 400 ? 400 : 503 });
|
|
9673
9698
|
}
|
|
@@ -9687,11 +9712,7 @@ var WorkspaceIdentityTokens = class {
|
|
|
9687
9712
|
return createErrorResult({ message: "AWS source identity is unavailable from this Replicas version", code: 503 });
|
|
9688
9713
|
}
|
|
9689
9714
|
}
|
|
9690
|
-
|
|
9691
|
-
const oldest = this.cache.keys().next();
|
|
9692
|
-
if (this.cache.size >= MAX_CACHED_AUDIENCES && !oldest.done) this.cache.delete(oldest.value);
|
|
9693
|
-
this.cache.set(key, token);
|
|
9694
|
-
return createSuccessResult(token);
|
|
9715
|
+
return createSuccessResult({ token, refreshAt: Date.parse(token.expires_at) - MIN_REMAINING_MS });
|
|
9695
9716
|
}
|
|
9696
9717
|
};
|
|
9697
9718
|
var workspaceIdentityTokens = new WorkspaceIdentityTokens();
|
|
@@ -9729,27 +9750,85 @@ function resolveIdentityRoute(requestUrl) {
|
|
|
9729
9750
|
target.search = url3.search;
|
|
9730
9751
|
return { target, audience: decode(encodedAudience) };
|
|
9731
9752
|
}
|
|
9732
|
-
function
|
|
9753
|
+
function resolveMcpOAuthRoute(requestUrl) {
|
|
9754
|
+
const url3 = new URL(requestUrl, "http://127.0.0.1");
|
|
9755
|
+
const [, kind, environmentMcpId, ...rest] = url3.pathname.split("/");
|
|
9756
|
+
return kind === "mcp-oauth" && environmentMcpId ? { environmentMcpId, rest, search: url3.search } : null;
|
|
9757
|
+
}
|
|
9758
|
+
var MAX_MCP_OAUTH_BODY_BYTES = 10 * 1024 * 1024;
|
|
9759
|
+
function readBody(request, maxBytes) {
|
|
9733
9760
|
return new Promise((resolve7) => {
|
|
9734
9761
|
const chunks = [];
|
|
9735
9762
|
let size = 0;
|
|
9736
9763
|
request.on("data", (chunk) => {
|
|
9737
9764
|
size += chunk.length;
|
|
9738
|
-
if (size
|
|
9739
|
-
|
|
9740
|
-
request.on("end", () => {
|
|
9741
|
-
if (size > MAX_TOKEN_REQUEST_BYTES) return resolve7(null);
|
|
9742
|
-
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
9743
|
-
try {
|
|
9744
|
-
resolve7(text ? JSON.parse(text) : {});
|
|
9745
|
-
} catch {
|
|
9746
|
-
resolve7(null);
|
|
9747
|
-
}
|
|
9765
|
+
if (size > maxBytes) resolve7("too_large");
|
|
9766
|
+
else chunks.push(chunk);
|
|
9748
9767
|
});
|
|
9768
|
+
request.on("end", () => resolve7(Buffer.concat(chunks)));
|
|
9749
9769
|
request.on("error", () => resolve7(null));
|
|
9750
9770
|
});
|
|
9751
9771
|
}
|
|
9752
|
-
function
|
|
9772
|
+
function forward(request, response, target, token, onResponse = (incoming) => pipeResponse(incoming, response)) {
|
|
9773
|
+
const headers = { host: target.host };
|
|
9774
|
+
for (const [name, value] of Object.entries(request.headers)) {
|
|
9775
|
+
if (!STRIPPED_HEADERS.has(name) && !name.startsWith("x-replicas-") && value !== void 0) headers[name] = value;
|
|
9776
|
+
}
|
|
9777
|
+
headers.authorization = `Bearer ${token}`;
|
|
9778
|
+
const upstream = (target.protocol === "https:" ? https : http).request(target, { method: request.method, headers }, onResponse);
|
|
9779
|
+
upstream.on("error", () => {
|
|
9780
|
+
if (!response.headersSent) response.writeHead(502);
|
|
9781
|
+
response.end();
|
|
9782
|
+
});
|
|
9783
|
+
response.on("close", () => upstream.destroy());
|
|
9784
|
+
return upstream;
|
|
9785
|
+
}
|
|
9786
|
+
function pipeResponse(incoming, response) {
|
|
9787
|
+
response.writeHead(incoming.statusCode ?? 502, incoming.headers);
|
|
9788
|
+
incoming.pipe(response);
|
|
9789
|
+
response.on("close", () => incoming.destroy());
|
|
9790
|
+
}
|
|
9791
|
+
async function proxyMcpOAuth(request, response, tokens, route) {
|
|
9792
|
+
const body = await readBody(request, MAX_MCP_OAUTH_BODY_BYTES);
|
|
9793
|
+
if (body === "too_large") {
|
|
9794
|
+
response.writeHead(413, { connection: "close" }).end();
|
|
9795
|
+
return;
|
|
9796
|
+
}
|
|
9797
|
+
if (!body) {
|
|
9798
|
+
response.writeHead(400).end();
|
|
9799
|
+
return;
|
|
9800
|
+
}
|
|
9801
|
+
const send = async (forceRefresh) => {
|
|
9802
|
+
const token = await tokens.get(route.environmentMcpId, forceRefresh);
|
|
9803
|
+
if (!token.ok) {
|
|
9804
|
+
response.writeHead(token.error.code ?? 503).end(token.error.message);
|
|
9805
|
+
return;
|
|
9806
|
+
}
|
|
9807
|
+
const target = new URL(token.data.url);
|
|
9808
|
+
if (route.rest.length) target.pathname = [target.pathname.replace(/\/$/, ""), ...route.rest].join("/");
|
|
9809
|
+
target.search = route.search;
|
|
9810
|
+
forward(request, response, target, token.data.access_token, (incoming) => {
|
|
9811
|
+
if (incoming.statusCode === 401 && !forceRefresh) {
|
|
9812
|
+
incoming.resume();
|
|
9813
|
+
void send(true);
|
|
9814
|
+
return;
|
|
9815
|
+
}
|
|
9816
|
+
pipeResponse(incoming, response);
|
|
9817
|
+
}).end(body);
|
|
9818
|
+
};
|
|
9819
|
+
await send(false);
|
|
9820
|
+
}
|
|
9821
|
+
async function readJsonBody(request) {
|
|
9822
|
+
const body = await readBody(request, MAX_TOKEN_REQUEST_BYTES);
|
|
9823
|
+
if (!body || body === "too_large") return null;
|
|
9824
|
+
const text = body.toString("utf8").trim();
|
|
9825
|
+
try {
|
|
9826
|
+
return text ? JSON.parse(text) : {};
|
|
9827
|
+
} catch {
|
|
9828
|
+
return null;
|
|
9829
|
+
}
|
|
9830
|
+
}
|
|
9831
|
+
function createIdentityProxy(tokens, mcpOAuthTokens2) {
|
|
9753
9832
|
return http.createServer(async (request, response) => {
|
|
9754
9833
|
const url3 = new URL(request.url ?? "/", "http://127.0.0.1");
|
|
9755
9834
|
if (url3.pathname === IDENTITY_TOKEN_PATH) {
|
|
@@ -9767,6 +9846,11 @@ function createIdentityProxy(tokens) {
|
|
|
9767
9846
|
response.end(JSON.stringify(result.ok ? result.data : { error: result.error.message }));
|
|
9768
9847
|
return;
|
|
9769
9848
|
}
|
|
9849
|
+
const mcpOAuthRoute = resolveMcpOAuthRoute(request.url ?? "/");
|
|
9850
|
+
if (mcpOAuthRoute) {
|
|
9851
|
+
await proxyMcpOAuth(request, response, mcpOAuthTokens2, mcpOAuthRoute);
|
|
9852
|
+
return;
|
|
9853
|
+
}
|
|
9770
9854
|
const route = resolveIdentityRoute(request.url ?? "/");
|
|
9771
9855
|
if (!route) {
|
|
9772
9856
|
response.writeHead(404).end("Unknown identity route");
|
|
@@ -9777,29 +9861,46 @@ function createIdentityProxy(tokens) {
|
|
|
9777
9861
|
response.writeHead(token.error.code ?? 503).end(token.error.message);
|
|
9778
9862
|
return;
|
|
9779
9863
|
}
|
|
9780
|
-
|
|
9781
|
-
for (const [name, value] of Object.entries(request.headers)) {
|
|
9782
|
-
if (!STRIPPED_HEADERS.has(name) && !name.startsWith("x-replicas-") && value !== void 0) headers[name] = value;
|
|
9783
|
-
}
|
|
9784
|
-
headers.authorization = `Bearer ${token.data.token}`;
|
|
9785
|
-
const upstream = (route.target.protocol === "https:" ? https : http).request(
|
|
9786
|
-
route.target,
|
|
9787
|
-
{ method: request.method, headers },
|
|
9788
|
-
(incoming) => {
|
|
9789
|
-
response.writeHead(incoming.statusCode ?? 502, incoming.headers);
|
|
9790
|
-
incoming.pipe(response);
|
|
9791
|
-
response.on("close", () => incoming.destroy());
|
|
9792
|
-
}
|
|
9793
|
-
);
|
|
9794
|
-
upstream.on("error", () => {
|
|
9795
|
-
if (!response.headersSent) response.writeHead(502);
|
|
9796
|
-
response.end();
|
|
9797
|
-
});
|
|
9798
|
-
response.on("close", () => upstream.destroy());
|
|
9799
|
-
request.pipe(upstream);
|
|
9864
|
+
request.pipe(forward(request, response, route.target, token.data.token));
|
|
9800
9865
|
});
|
|
9801
9866
|
}
|
|
9802
9867
|
|
|
9868
|
+
// src/mcp-oauth-tokens.ts
|
|
9869
|
+
var MIN_REMAINING_MS2 = 60 * 1e3;
|
|
9870
|
+
var MAX_CACHE_MS = 5 * 60 * 1e3;
|
|
9871
|
+
var McpOAuthTokens = class {
|
|
9872
|
+
constructor(request = monolithRequest) {
|
|
9873
|
+
this.request = request;
|
|
9874
|
+
}
|
|
9875
|
+
request;
|
|
9876
|
+
tokens = new TokenCache();
|
|
9877
|
+
get(environmentMcpId, forceRefresh = false) {
|
|
9878
|
+
return this.tokens.get(environmentMcpId, () => this.fetch(environmentMcpId, forceRefresh), forceRefresh);
|
|
9879
|
+
}
|
|
9880
|
+
async fetch(environmentMcpId, forceRefresh) {
|
|
9881
|
+
const requested = await requestToken(
|
|
9882
|
+
this.request,
|
|
9883
|
+
"/v1/engine/mcp-oauth/token",
|
|
9884
|
+
{ environment_mcp_id: environmentMcpId, force_refresh: forceRefresh },
|
|
9885
|
+
"MCP OAuth token request failed"
|
|
9886
|
+
);
|
|
9887
|
+
if (!requested.ok) return requested;
|
|
9888
|
+
const response = requested.data;
|
|
9889
|
+
const data = await response.json().catch(() => null);
|
|
9890
|
+
const parsed = engineMcpOAuthTokenResponseSchema.safeParse(data);
|
|
9891
|
+
if (!response.ok || !parsed.success) {
|
|
9892
|
+
const message = isRecord(data) && typeof data.error === "string" ? data.error : `MCP OAuth token request failed: ${response.status}`;
|
|
9893
|
+
return createErrorResult({ message, code: response.ok ? 502 : response.status });
|
|
9894
|
+
}
|
|
9895
|
+
const remaining = parsed.data.expires_at ? Date.parse(parsed.data.expires_at) - Date.now() : Infinity;
|
|
9896
|
+
return createSuccessResult({
|
|
9897
|
+
token: parsed.data,
|
|
9898
|
+
refreshAt: Date.now() + Math.min(Math.max(remaining - MIN_REMAINING_MS2, remaining / 2), MAX_CACHE_MS)
|
|
9899
|
+
});
|
|
9900
|
+
}
|
|
9901
|
+
};
|
|
9902
|
+
var mcpOAuthTokens = new McpOAuthTokens();
|
|
9903
|
+
|
|
9803
9904
|
// src/lifecycle.ts
|
|
9804
9905
|
import { readFileSync, rmSync, writeFileSync } from "fs";
|
|
9805
9906
|
var CLAIM_FILE = "/tmp/replicas-engine.claim";
|
|
@@ -50655,7 +50756,7 @@ data: ${JSON.stringify(payload)}
|
|
|
50655
50756
|
}
|
|
50656
50757
|
async function parseBody(req, res) {
|
|
50657
50758
|
try {
|
|
50658
|
-
const body = await
|
|
50759
|
+
const body = await readBody2(req);
|
|
50659
50760
|
if (!body || typeof body !== "object") {
|
|
50660
50761
|
sendJson(res, 400, { ok: false, error: "Invalid request body" });
|
|
50661
50762
|
return null;
|
|
@@ -50666,7 +50767,7 @@ async function parseBody(req, res) {
|
|
|
50666
50767
|
return null;
|
|
50667
50768
|
}
|
|
50668
50769
|
}
|
|
50669
|
-
function
|
|
50770
|
+
function readBody2(req) {
|
|
50670
50771
|
return new Promise((resolve7, reject) => {
|
|
50671
50772
|
let size = 0;
|
|
50672
50773
|
const chunks = [];
|
|
@@ -64677,7 +64778,7 @@ async function startBackgroundServices(signal) {
|
|
|
64677
64778
|
heartbeatService.start(bootTimeMs);
|
|
64678
64779
|
if (!identityProxyStarted) {
|
|
64679
64780
|
identityProxyStarted = true;
|
|
64680
|
-
createIdentityProxy(workspaceIdentityTokens).on("error", (error) => console.error("[identity-proxy] failed to listen:", error)).listen(IDENTITY_PROXY_PORT, "127.0.0.1");
|
|
64781
|
+
createIdentityProxy(workspaceIdentityTokens, mcpOAuthTokens).on("error", (error) => console.error("[identity-proxy] failed to listen:", error)).listen(IDENTITY_PROXY_PORT, "127.0.0.1");
|
|
64681
64782
|
}
|
|
64682
64783
|
for (const manager of tokenManagers.slice(1)) {
|
|
64683
64784
|
if (signal.aborted) return;
|
|
@@ -3,13 +3,13 @@ import { createRequire as __createRequire } from 'node:module';
|
|
|
3
3
|
const require = __createRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
publishedPullRequestUrls
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-E35XSXJE.js";
|
|
7
7
|
import {
|
|
8
8
|
isRecord
|
|
9
9
|
} from "./chunk-UZSNFLDQ.js";
|
|
10
10
|
import {
|
|
11
11
|
shouldRefreshPullRequests
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BOAIMJKK.js";
|
|
13
13
|
import "./chunk-VEQXQN22.js";
|
|
14
14
|
|
|
15
15
|
// src/services/post-tool-pr-notifier.ts
|
package/dist/src/subagent-mcp.js
CHANGED