replicas-engine 0.1.335 → 0.1.336
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/index.js +163 -23
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -291,7 +291,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
291
291
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
292
292
|
|
|
293
293
|
// ../shared/src/e2b.ts
|
|
294
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-22-
|
|
294
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-22-v2";
|
|
295
295
|
|
|
296
296
|
// ../shared/src/runtime-env.ts
|
|
297
297
|
function parsePosixEnvFile(content) {
|
|
@@ -377,6 +377,51 @@ var InFlightMap = class {
|
|
|
377
377
|
}
|
|
378
378
|
};
|
|
379
379
|
|
|
380
|
+
// ../shared/src/github/url.ts
|
|
381
|
+
var GITHUB_HOST_RE = /(^|@|\/\/)github\.com[:/]/;
|
|
382
|
+
function isGitHubUrl(url) {
|
|
383
|
+
if (!url) return false;
|
|
384
|
+
return GITHUB_HOST_RE.test(url);
|
|
385
|
+
}
|
|
386
|
+
function stripCredentialsFromUrl(url) {
|
|
387
|
+
try {
|
|
388
|
+
const parsed = new URL(url);
|
|
389
|
+
if (parsed.username || parsed.password) {
|
|
390
|
+
parsed.username = "";
|
|
391
|
+
parsed.password = "";
|
|
392
|
+
return parsed.toString();
|
|
393
|
+
}
|
|
394
|
+
} catch {
|
|
395
|
+
}
|
|
396
|
+
return url;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ../shared/src/urls.ts
|
|
400
|
+
function decodePathSegments(segments) {
|
|
401
|
+
return segments.map((segment) => {
|
|
402
|
+
try {
|
|
403
|
+
return decodeURIComponent(segment);
|
|
404
|
+
} catch {
|
|
405
|
+
return segment;
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function normalizeRepositoryUrl(url, options = {}) {
|
|
410
|
+
if (!url) return null;
|
|
411
|
+
const stripped = stripCredentialsFromUrl(url).trim().replace(/\/+$/, "").replace(/\.git$/, "");
|
|
412
|
+
if (!stripped) return null;
|
|
413
|
+
try {
|
|
414
|
+
const parsed = new URL(stripped);
|
|
415
|
+
parsed.hash = "";
|
|
416
|
+
parsed.search = "";
|
|
417
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "").replace(/\.git$/, "");
|
|
418
|
+
const normalized = `${parsed.origin}${parsed.pathname}`;
|
|
419
|
+
return options.lowercase ? normalized.toLowerCase() : normalized;
|
|
420
|
+
} catch {
|
|
421
|
+
return options.lowercase ? stripped.toLowerCase() : stripped;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
380
425
|
// ../shared/src/slash-commands.ts
|
|
381
426
|
var MAX_CODEX_GOAL_OBJECTIVE_CHARS = 4e3;
|
|
382
427
|
function parseGoalCommand(message) {
|
|
@@ -2734,13 +2779,6 @@ var MEDIA_KIND = {
|
|
|
2734
2779
|
};
|
|
2735
2780
|
var MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO];
|
|
2736
2781
|
|
|
2737
|
-
// ../shared/src/github/url.ts
|
|
2738
|
-
var GITHUB_HOST_RE = /(^|@|\/\/)github\.com[:/]/;
|
|
2739
|
-
function isGitHubUrl(url) {
|
|
2740
|
-
if (!url) return false;
|
|
2741
|
-
return GITHUB_HOST_RE.test(url);
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
2782
|
// ../shared/src/skill-registry.ts
|
|
2745
2783
|
var SKILL_REGISTRY_MANIFEST_VERSION = 1;
|
|
2746
2784
|
|
|
@@ -3562,8 +3600,8 @@ var GitService = class {
|
|
|
3562
3600
|
defaultBranchCache = /* @__PURE__ */ new Map();
|
|
3563
3601
|
cachedPrByRepo = /* @__PURE__ */ new Map();
|
|
3564
3602
|
// No invalidation on purpose — `git remote set-url` mid-session is rare and
|
|
3565
|
-
// the worst case is
|
|
3566
|
-
|
|
3603
|
+
// the worst case is PR/MR lookup stays skipped until the next engine restart.
|
|
3604
|
+
originInfoCache = /* @__PURE__ */ new Map();
|
|
3567
3605
|
// Broadcaster + UI /repos requests fan in here every ~2s; one shared run.
|
|
3568
3606
|
listReposInFlight = new InFlightMap();
|
|
3569
3607
|
diffStatsInFlight = new InFlightMap();
|
|
@@ -3926,7 +3964,8 @@ var GitService = class {
|
|
|
3926
3964
|
}
|
|
3927
3965
|
}
|
|
3928
3966
|
async lookupPrOnRemote(repoName, repoPath, branch) {
|
|
3929
|
-
|
|
3967
|
+
const origin = await this.getOriginInfo(repoPath);
|
|
3968
|
+
if (origin.provider === "unknown") {
|
|
3930
3969
|
return { status: "not_found" };
|
|
3931
3970
|
}
|
|
3932
3971
|
try {
|
|
@@ -3941,6 +3980,9 @@ var GitService = class {
|
|
|
3941
3980
|
} catch {
|
|
3942
3981
|
return { status: "error" };
|
|
3943
3982
|
}
|
|
3983
|
+
if (origin.provider === "gitlab") {
|
|
3984
|
+
return this.lookupGitLabMrOnRemote(repoName, origin.gitLab, branch);
|
|
3985
|
+
}
|
|
3944
3986
|
try {
|
|
3945
3987
|
const { stdout } = await execFileAsync("gh", ["pr", "view", branch, "--json", "url", "--jq", ".url"], {
|
|
3946
3988
|
cwd: repoPath,
|
|
@@ -3955,24 +3997,120 @@ var GitService = class {
|
|
|
3955
3997
|
return { status: "error" };
|
|
3956
3998
|
}
|
|
3957
3999
|
}
|
|
3958
|
-
async
|
|
3959
|
-
const
|
|
4000
|
+
async lookupGitLabMrOnRemote(repoName, remote, branch) {
|
|
4001
|
+
const token = await this.getGitLabAccessToken(remote.host);
|
|
4002
|
+
if (!token) {
|
|
4003
|
+
return { status: "not_found" };
|
|
4004
|
+
}
|
|
4005
|
+
const url = `${remote.instanceUrl}/api/v4/projects/${encodeURIComponent(remote.projectPath)}/merge_requests?state=opened&source_branch=${encodeURIComponent(branch)}`;
|
|
4006
|
+
try {
|
|
4007
|
+
const response = await fetch(url, {
|
|
4008
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
4009
|
+
signal: AbortSignal.timeout(1e4)
|
|
4010
|
+
});
|
|
4011
|
+
if (!response.ok) {
|
|
4012
|
+
console.warn(`[GitService] GitLab MR lookup failed for ${repoName}: ${response.status}`);
|
|
4013
|
+
return response.status === 404 ? { status: "not_found" } : { status: "error" };
|
|
4014
|
+
}
|
|
4015
|
+
const data = await response.json();
|
|
4016
|
+
if (!Array.isArray(data)) return { status: "not_found" };
|
|
4017
|
+
const mergeRequest = data.find((item) => isRecord4(item) && item.source_branch === branch) ?? data[0];
|
|
4018
|
+
if (!isRecord4(mergeRequest)) return { status: "not_found" };
|
|
4019
|
+
const webUrl = mergeRequest.web_url;
|
|
4020
|
+
if (typeof webUrl === "string" && webUrl.length > 0) return { status: "found", url: webUrl };
|
|
4021
|
+
const iid = mergeRequest.iid;
|
|
4022
|
+
return typeof iid === "number" ? { status: "found", url: `${remote.instanceUrl}/${remote.projectPath}/-/merge_requests/${iid}` } : { status: "not_found" };
|
|
4023
|
+
} catch (error) {
|
|
4024
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4025
|
+
console.warn(`[GitService] GitLab MR lookup failed for ${repoName}: ${message}`);
|
|
4026
|
+
return { status: "error" };
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
async getOriginInfo(repoPath) {
|
|
4030
|
+
const cached = this.originInfoCache.get(repoPath);
|
|
3960
4031
|
if (cached !== void 0) {
|
|
3961
4032
|
return cached;
|
|
3962
4033
|
}
|
|
3963
|
-
let
|
|
4034
|
+
let info = { provider: "unknown" };
|
|
3964
4035
|
try {
|
|
3965
4036
|
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
|
|
3966
4037
|
cwd: repoPath,
|
|
3967
4038
|
encoding: "utf-8",
|
|
3968
4039
|
maxBuffer: SUBPROCESS_MAX_BUFFER
|
|
3969
4040
|
});
|
|
3970
|
-
|
|
4041
|
+
const originUrl = stdout.trim();
|
|
4042
|
+
if (isGitHubUrl(originUrl)) {
|
|
4043
|
+
info = { provider: "github" };
|
|
4044
|
+
} else {
|
|
4045
|
+
const gitLabRemote = this.parseGitLabRemote(originUrl);
|
|
4046
|
+
if (gitLabRemote) info = { provider: "gitlab", gitLab: gitLabRemote };
|
|
4047
|
+
}
|
|
3971
4048
|
} catch {
|
|
3972
|
-
|
|
4049
|
+
info = { provider: "unknown" };
|
|
3973
4050
|
}
|
|
3974
|
-
this.
|
|
3975
|
-
return
|
|
4051
|
+
this.originInfoCache.set(repoPath, info);
|
|
4052
|
+
return info;
|
|
4053
|
+
}
|
|
4054
|
+
parseGitLabRemote(remoteUrl) {
|
|
4055
|
+
const sshUrl = remoteUrl.trim().replace(/\/+$/, "").replace(/\.git$/, "");
|
|
4056
|
+
try {
|
|
4057
|
+
const parsed = new URL(sshUrl);
|
|
4058
|
+
if (parsed.protocol === "ssh:") {
|
|
4059
|
+
const projectPath = decodePathSegments(parsed.pathname.split("/").filter(Boolean)).join("/");
|
|
4060
|
+
if (!parsed.hostname || !projectPath) return null;
|
|
4061
|
+
const host = parsed.hostname.toLowerCase();
|
|
4062
|
+
return {
|
|
4063
|
+
host,
|
|
4064
|
+
instanceUrl: `https://${host}`,
|
|
4065
|
+
projectPath
|
|
4066
|
+
};
|
|
4067
|
+
}
|
|
4068
|
+
} catch {
|
|
4069
|
+
}
|
|
4070
|
+
const scpLike = sshUrl.match(/^git@([^:/]+):(?:(?:\d+)\/)?(.+)$/);
|
|
4071
|
+
if (scpLike) {
|
|
4072
|
+
const [, host, projectPath] = scpLike;
|
|
4073
|
+
if (!host || !projectPath) return null;
|
|
4074
|
+
const decodedProjectPath = decodePathSegments(projectPath.split("/").filter(Boolean)).join("/");
|
|
4075
|
+
return {
|
|
4076
|
+
host: host.toLowerCase(),
|
|
4077
|
+
instanceUrl: `https://${host}`,
|
|
4078
|
+
projectPath: decodedProjectPath
|
|
4079
|
+
};
|
|
4080
|
+
}
|
|
4081
|
+
const normalized = normalizeRepositoryUrl(remoteUrl);
|
|
4082
|
+
if (!normalized) return null;
|
|
4083
|
+
try {
|
|
4084
|
+
const parsed = new URL(normalized);
|
|
4085
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
4086
|
+
const projectPath = decodePathSegments(parsed.pathname.split("/").filter(Boolean)).join("/");
|
|
4087
|
+
if (!projectPath) return null;
|
|
4088
|
+
return {
|
|
4089
|
+
host: parsed.host.toLowerCase(),
|
|
4090
|
+
instanceUrl: parsed.origin,
|
|
4091
|
+
projectPath
|
|
4092
|
+
};
|
|
4093
|
+
} catch {
|
|
4094
|
+
}
|
|
4095
|
+
return null;
|
|
4096
|
+
}
|
|
4097
|
+
async getGitLabAccessToken(host) {
|
|
4098
|
+
try {
|
|
4099
|
+
const credentials = await readFile3(join5(ENGINE_ENV.HOME_DIR, ".git-credentials"), "utf-8");
|
|
4100
|
+
for (const line of credentials.split("\n")) {
|
|
4101
|
+
const trimmed = line.trim();
|
|
4102
|
+
if (!trimmed) continue;
|
|
4103
|
+
try {
|
|
4104
|
+
const parsed = new URL(trimmed);
|
|
4105
|
+
if (parsed.protocol === "https:" && parsed.host.toLowerCase() === host && parsed.password) {
|
|
4106
|
+
return decodeURIComponent(parsed.password);
|
|
4107
|
+
}
|
|
4108
|
+
} catch {
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
} catch {
|
|
4112
|
+
}
|
|
4113
|
+
return null;
|
|
3976
4114
|
}
|
|
3977
4115
|
async resolveDefaultBranch(repoPath) {
|
|
3978
4116
|
const cached = this.defaultBranchCache.get(repoPath);
|
|
@@ -7359,7 +7497,7 @@ var AspClient = class {
|
|
|
7359
7497
|
// src/managers/codex-asp/app-server-process.ts
|
|
7360
7498
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
7361
7499
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
7362
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
7500
|
+
var ENGINE_PACKAGE_VERSION = "0.1.336";
|
|
7363
7501
|
var INITIALIZE_METHOD = "initialize";
|
|
7364
7502
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
7365
7503
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -10798,10 +10936,12 @@ var ChatService = class {
|
|
|
10798
10936
|
}
|
|
10799
10937
|
}
|
|
10800
10938
|
async publishAgentTurnCompleteWebhook(chat) {
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10939
|
+
await Promise.all([
|
|
10940
|
+
githubTokenManager.refreshOnce().catch(() => {
|
|
10941
|
+
}),
|
|
10942
|
+
gitlabTokenManager.refreshOnce().catch(() => {
|
|
10943
|
+
})
|
|
10944
|
+
]);
|
|
10805
10945
|
const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
|
|
10806
10946
|
const observedBranches = chat.observedBranchesByRepo;
|
|
10807
10947
|
chat.observedBranchesByRepo = /* @__PURE__ */ new Map();
|