replicas-engine 0.1.252 → 0.1.254
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 +206 -24
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -297,7 +297,7 @@ var WORKSPACE_SIZES = ["small", "large"];
|
|
|
297
297
|
var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
|
|
298
298
|
|
|
299
299
|
// ../shared/src/e2b.ts
|
|
300
|
-
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-02-
|
|
300
|
+
var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-02-v4";
|
|
301
301
|
|
|
302
302
|
// ../shared/src/runtime-env.ts
|
|
303
303
|
function parsePosixEnvFile(content) {
|
|
@@ -1847,6 +1847,86 @@ function isCodexAspTranscript(value) {
|
|
|
1847
1847
|
if (!isRecord(value)) return false;
|
|
1848
1848
|
return typeof value.threadId === "string" && typeof value.updatedAt === "string" && Array.isArray(value.turns);
|
|
1849
1849
|
}
|
|
1850
|
+
function isCodexAspTranscriptDelta(value) {
|
|
1851
|
+
if (!isRecord(value)) return false;
|
|
1852
|
+
if (typeof value.threadId !== "string" || typeof value.updatedAt !== "string" || !Array.isArray(value.turns) || value.reset !== void 0 && value.reset !== null && !isCodexAspTranscript(value.reset)) {
|
|
1853
|
+
return false;
|
|
1854
|
+
}
|
|
1855
|
+
return value.turns.every((turn) => isRecord(turn) && typeof turn.id === "string" && typeof turn.status === "string" && typeof turn.startedAt === "string" && (turn.completedAt === null || typeof turn.completedAt === "string") && Array.isArray(turn.items) && turn.items.every((item) => isRecord(item) && typeof item.id === "string" && (item.item === void 0 || isRecord(item.item) && typeof item.item.type === "string" && typeof item.item.id === "string" && typeof item.item.timestamp === "string") && (item.appendText === void 0 || typeof item.appendText === "string") && (item.appendOutput === void 0 || typeof item.appendOutput === "string")));
|
|
1856
|
+
}
|
|
1857
|
+
function appendCodexAspTranscriptField(current, append) {
|
|
1858
|
+
return append === void 0 ? current : `${current ?? ""}${append}`;
|
|
1859
|
+
}
|
|
1860
|
+
function patchCodexAspTranscriptItem(current, delta) {
|
|
1861
|
+
const base = delta.item ?? current;
|
|
1862
|
+
if (!base) {
|
|
1863
|
+
return null;
|
|
1864
|
+
}
|
|
1865
|
+
if (base.type === "agentMessage" && delta.appendText !== void 0) {
|
|
1866
|
+
return {
|
|
1867
|
+
...base,
|
|
1868
|
+
text: appendCodexAspTranscriptField(base.text, delta.appendText) ?? ""
|
|
1869
|
+
};
|
|
1870
|
+
}
|
|
1871
|
+
if ((base.type === "commandExecution" || base.type === "fileChange") && delta.appendOutput !== void 0) {
|
|
1872
|
+
return {
|
|
1873
|
+
...base,
|
|
1874
|
+
output: appendCodexAspTranscriptField(base.output, delta.appendOutput)
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1877
|
+
return base;
|
|
1878
|
+
}
|
|
1879
|
+
function applyCodexAspTranscriptDelta(current, delta) {
|
|
1880
|
+
if (!delta) return current ?? null;
|
|
1881
|
+
if (delta.reset === null) {
|
|
1882
|
+
return null;
|
|
1883
|
+
}
|
|
1884
|
+
const base = delta.reset ?? (current?.threadId === delta.threadId ? current : {
|
|
1885
|
+
threadId: delta.threadId,
|
|
1886
|
+
updatedAt: delta.updatedAt,
|
|
1887
|
+
turns: []
|
|
1888
|
+
});
|
|
1889
|
+
const turns = base.turns.map((turn) => ({
|
|
1890
|
+
...turn,
|
|
1891
|
+
items: [...turn.items]
|
|
1892
|
+
}));
|
|
1893
|
+
for (const turnDelta of delta.turns) {
|
|
1894
|
+
let turn = turns.find((candidate) => candidate.id === turnDelta.id);
|
|
1895
|
+
if (!turn) {
|
|
1896
|
+
turn = {
|
|
1897
|
+
id: turnDelta.id,
|
|
1898
|
+
status: turnDelta.status,
|
|
1899
|
+
startedAt: turnDelta.startedAt,
|
|
1900
|
+
completedAt: turnDelta.completedAt,
|
|
1901
|
+
items: []
|
|
1902
|
+
};
|
|
1903
|
+
turns.push(turn);
|
|
1904
|
+
} else {
|
|
1905
|
+
turn.status = turnDelta.status;
|
|
1906
|
+
turn.startedAt = turnDelta.startedAt;
|
|
1907
|
+
turn.completedAt = turnDelta.completedAt;
|
|
1908
|
+
}
|
|
1909
|
+
for (const itemDelta of turnDelta.items) {
|
|
1910
|
+
const itemIndex = turn.items.findIndex((item) => item.id === itemDelta.id);
|
|
1911
|
+
const patched = patchCodexAspTranscriptItem(turn.items[itemIndex], itemDelta);
|
|
1912
|
+
if (!patched) continue;
|
|
1913
|
+
if (itemIndex === -1) {
|
|
1914
|
+
turn.items.push(patched);
|
|
1915
|
+
} else {
|
|
1916
|
+
turn.items[itemIndex] = patched;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
turns.sort((a, b) => Date.parse(a.startedAt) - Date.parse(b.startedAt));
|
|
1921
|
+
for (const turn of turns) {
|
|
1922
|
+
turn.items.sort((a, b) => (a.sequence ?? Number.MAX_SAFE_INTEGER) - (b.sequence ?? Number.MAX_SAFE_INTEGER) || Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
1923
|
+
}
|
|
1924
|
+
return {
|
|
1925
|
+
threadId: delta.threadId,
|
|
1926
|
+
updatedAt: delta.updatedAt,
|
|
1927
|
+
turns
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1850
1930
|
|
|
1851
1931
|
// ../shared/src/routes/codex.ts
|
|
1852
1932
|
var CODEX_AUTH_ENV_KEYS = [
|
|
@@ -2648,7 +2728,7 @@ var codexTokenManager = new CodexTokenManager();
|
|
|
2648
2728
|
|
|
2649
2729
|
// src/git/service.ts
|
|
2650
2730
|
import { readdir, stat } from "fs/promises";
|
|
2651
|
-
import { existsSync as existsSync2, unlinkSync } from "fs";
|
|
2731
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3, unlinkSync } from "fs";
|
|
2652
2732
|
import { execFileSync as execFileSync2, spawnSync } from "child_process";
|
|
2653
2733
|
import { join as join5 } from "path";
|
|
2654
2734
|
|
|
@@ -2857,27 +2937,21 @@ var GitService = class {
|
|
|
2857
2937
|
}
|
|
2858
2938
|
async listRepos(options) {
|
|
2859
2939
|
const includeDiffs = options?.includeDiffs === true;
|
|
2860
|
-
if (includeDiffs) {
|
|
2861
|
-
const repos2 = await this.refreshRepos();
|
|
2862
|
-
return repos2.map((repo) => ({
|
|
2863
|
-
...repo,
|
|
2864
|
-
gitDiff: repo.gitDiff ? { ...repo.gitDiff, fullDiff: this.getFullGitDiff(repo.path, repo.defaultBranch) } : null
|
|
2865
|
-
}));
|
|
2866
|
-
}
|
|
2867
2940
|
const repos = await this.listRepositories();
|
|
2868
2941
|
const states = [];
|
|
2869
2942
|
for (const repo of repos) {
|
|
2870
2943
|
try {
|
|
2871
2944
|
const persistedState = await loadRepoState(repo.name);
|
|
2872
2945
|
const currentBranch = getCurrentBranch(repo.path) ?? repo.defaultBranch;
|
|
2873
|
-
const
|
|
2946
|
+
const gitDiff = this.getGitDiffStats(repo.path, repo.defaultBranch);
|
|
2874
2947
|
states.push({
|
|
2875
2948
|
name: repo.name,
|
|
2876
2949
|
path: repo.path,
|
|
2877
2950
|
defaultBranch: repo.defaultBranch,
|
|
2878
2951
|
currentBranch,
|
|
2879
2952
|
prUrls: persistedState?.prUrls ?? [],
|
|
2880
|
-
|
|
2953
|
+
// fullDiff may be empty if the diff subprocess fails.
|
|
2954
|
+
gitDiff: includeDiffs && gitDiff ? { ...gitDiff, fullDiff: this.getFullGitDiff(repo.path, repo.defaultBranch) } : gitDiff,
|
|
2881
2955
|
startHooksCompleted: persistedState?.startHooksCompleted ?? false
|
|
2882
2956
|
});
|
|
2883
2957
|
} catch {
|
|
@@ -3040,17 +3114,20 @@ var GitService = class {
|
|
|
3040
3114
|
return null;
|
|
3041
3115
|
}
|
|
3042
3116
|
}
|
|
3043
|
-
|
|
3117
|
+
listUntrackedPaths(repoPath) {
|
|
3044
3118
|
const listing = execFileSync2("git", ["ls-files", "--others", "--exclude-standard", "-z"], {
|
|
3045
3119
|
cwd: repoPath,
|
|
3046
3120
|
encoding: "utf-8",
|
|
3047
3121
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3048
3122
|
});
|
|
3049
|
-
|
|
3123
|
+
return listing.split("\0").filter(Boolean);
|
|
3124
|
+
}
|
|
3125
|
+
getUntrackedDiff(repoPath) {
|
|
3126
|
+
const paths = this.listUntrackedPaths(repoPath);
|
|
3050
3127
|
if (paths.length === 0) return "";
|
|
3051
3128
|
try {
|
|
3052
3129
|
execFileSync2("git", ["add", "--intent-to-add", "--", ...paths], { cwd: repoPath, stdio: ["pipe", "pipe", "pipe"] });
|
|
3053
|
-
const result = spawnSync("git", ["diff",
|
|
3130
|
+
const result = spawnSync("git", ["diff", "--", ...paths], {
|
|
3054
3131
|
cwd: repoPath,
|
|
3055
3132
|
encoding: "utf-8",
|
|
3056
3133
|
maxBuffer: 50 * 1024 * 1024
|
|
@@ -3065,9 +3142,21 @@ var GitService = class {
|
|
|
3065
3142
|
}
|
|
3066
3143
|
countUntrackedAddedLines(repoPath) {
|
|
3067
3144
|
try {
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3145
|
+
return this.listUntrackedPaths(repoPath).reduce((total, path4) => {
|
|
3146
|
+
try {
|
|
3147
|
+
const contents = readFileSync3(join5(repoPath, path4));
|
|
3148
|
+
if (contents.length === 0 || contents.includes(0)) {
|
|
3149
|
+
return total;
|
|
3150
|
+
}
|
|
3151
|
+
let lines = 0;
|
|
3152
|
+
for (const byte of contents) {
|
|
3153
|
+
if (byte === 10) lines += 1;
|
|
3154
|
+
}
|
|
3155
|
+
return total + lines + (contents[contents.length - 1] === 10 ? 0 : 1);
|
|
3156
|
+
} catch {
|
|
3157
|
+
return total;
|
|
3158
|
+
}
|
|
3159
|
+
}, 0);
|
|
3071
3160
|
} catch (error) {
|
|
3072
3161
|
console.error("Error counting untracked added lines:", error);
|
|
3073
3162
|
return 0;
|
|
@@ -6142,7 +6231,7 @@ var AspClient = class {
|
|
|
6142
6231
|
// src/managers/codex-asp/app-server-process.ts
|
|
6143
6232
|
var DEFAULT_CODEX_BINARY = "codex";
|
|
6144
6233
|
var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
|
|
6145
|
-
var ENGINE_PACKAGE_VERSION = "0.1.
|
|
6234
|
+
var ENGINE_PACKAGE_VERSION = "0.1.254";
|
|
6146
6235
|
var INITIALIZE_METHOD = "initialize";
|
|
6147
6236
|
var INITIALIZED_NOTIFICATION = "initialized";
|
|
6148
6237
|
var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
|
|
@@ -6409,7 +6498,7 @@ function isCodexAuthError(error) {
|
|
|
6409
6498
|
}
|
|
6410
6499
|
|
|
6411
6500
|
// src/managers/codex-asp/mappers.ts
|
|
6412
|
-
import { existsSync as existsSync6, readFileSync as
|
|
6501
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
6413
6502
|
var localImageCache = /* @__PURE__ */ new Map();
|
|
6414
6503
|
var DEFAULT_MODEL = DEFAULT_CODEX_MODEL;
|
|
6415
6504
|
var THREAD_START_METHOD = "thread/start";
|
|
@@ -6490,7 +6579,7 @@ function userImageForLocalPath(path4) {
|
|
|
6490
6579
|
const image = {
|
|
6491
6580
|
type: "image",
|
|
6492
6581
|
mediaType: inferMediaType(path4),
|
|
6493
|
-
data:
|
|
6582
|
+
data: readFileSync4(path4).toString("base64")
|
|
6494
6583
|
};
|
|
6495
6584
|
if (image.data.length > 0) localImageCache.set(path4, image);
|
|
6496
6585
|
return image;
|
|
@@ -6965,6 +7054,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
6965
7054
|
threadAttached = false;
|
|
6966
7055
|
historyEvents = [];
|
|
6967
7056
|
codexAspTranscript = null;
|
|
7057
|
+
lastEmittedTranscripts = /* @__PURE__ */ new Map();
|
|
6968
7058
|
codexAspSequence = 0;
|
|
6969
7059
|
quotaStatus = new CodexQuotaStatusTracker();
|
|
6970
7060
|
currentGoal = null;
|
|
@@ -7440,6 +7530,9 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
7440
7530
|
this.codexAspSequence = next;
|
|
7441
7531
|
}
|
|
7442
7532
|
mergeTranscriptSnapshot(snapshot) {
|
|
7533
|
+
if (snapshot?.threadId && this.codexAspTranscript?.threadId !== snapshot.threadId) {
|
|
7534
|
+
this.lastEmittedTranscripts.clear();
|
|
7535
|
+
}
|
|
7443
7536
|
this.codexAspTranscript = mergeCodexAspTranscripts(this.codexAspTranscript, snapshot);
|
|
7444
7537
|
this.syncTranscriptSequence(this.codexAspTranscript);
|
|
7445
7538
|
return this.codexAspTranscript;
|
|
@@ -7448,6 +7541,7 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
7448
7541
|
if (this.codexAspTranscript?.threadId === threadId) {
|
|
7449
7542
|
return this.codexAspTranscript;
|
|
7450
7543
|
}
|
|
7544
|
+
this.lastEmittedTranscripts.clear();
|
|
7451
7545
|
this.codexAspTranscript = {
|
|
7452
7546
|
threadId,
|
|
7453
7547
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -7617,14 +7711,95 @@ var CodexAspManager = class extends CodingAgentManager {
|
|
|
7617
7711
|
emitTranscriptUpdated(threadId, options = {}) {
|
|
7618
7712
|
this.transcriptUpdateCoalescer.schedule(threadId, options);
|
|
7619
7713
|
}
|
|
7714
|
+
buildTranscriptItemDelta(previous, current) {
|
|
7715
|
+
if (!previous || previous.type !== current.type) {
|
|
7716
|
+
return { id: current.id, item: structuredClone(current) };
|
|
7717
|
+
}
|
|
7718
|
+
if (current.type === "agentMessage" && previous.type === "agentMessage" && current.text.startsWith(previous.text) && current.text.length > previous.text.length) {
|
|
7719
|
+
return {
|
|
7720
|
+
id: current.id,
|
|
7721
|
+
appendText: current.text.slice(previous.text.length)
|
|
7722
|
+
};
|
|
7723
|
+
}
|
|
7724
|
+
if ((current.type === "commandExecution" || current.type === "fileChange") && previous.type === current.type && current.output && current.output.startsWith(previous.output ?? "") && current.output.length > (previous.output ?? "").length) {
|
|
7725
|
+
const { output: _output, ...itemWithoutOutput } = current;
|
|
7726
|
+
const item = {
|
|
7727
|
+
...itemWithoutOutput,
|
|
7728
|
+
output: previous.output
|
|
7729
|
+
};
|
|
7730
|
+
return {
|
|
7731
|
+
id: current.id,
|
|
7732
|
+
item,
|
|
7733
|
+
appendOutput: current.output.slice((previous.output ?? "").length)
|
|
7734
|
+
};
|
|
7735
|
+
}
|
|
7736
|
+
if (JSON.stringify(previous) === JSON.stringify(current)) {
|
|
7737
|
+
return null;
|
|
7738
|
+
}
|
|
7739
|
+
return { id: current.id, item: structuredClone(current) };
|
|
7740
|
+
}
|
|
7741
|
+
buildTranscriptDelta(threadId, current) {
|
|
7742
|
+
const previous = this.lastEmittedTranscripts.get(threadId);
|
|
7743
|
+
const updatedAt = current?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
7744
|
+
if (!current || previous === void 0 || previous?.threadId !== current.threadId) {
|
|
7745
|
+
return {
|
|
7746
|
+
threadId,
|
|
7747
|
+
updatedAt,
|
|
7748
|
+
reset: current ? structuredClone(current) : null,
|
|
7749
|
+
turns: []
|
|
7750
|
+
};
|
|
7751
|
+
}
|
|
7752
|
+
const turnDeltas = [];
|
|
7753
|
+
for (const currentTurn of current.turns) {
|
|
7754
|
+
const previousTurn = previous.turns.find((turn) => turn.id === currentTurn.id);
|
|
7755
|
+
if (!previousTurn) {
|
|
7756
|
+
turnDeltas.push({
|
|
7757
|
+
id: currentTurn.id,
|
|
7758
|
+
status: currentTurn.status,
|
|
7759
|
+
startedAt: currentTurn.startedAt,
|
|
7760
|
+
completedAt: currentTurn.completedAt,
|
|
7761
|
+
items: currentTurn.items.map((item) => ({ id: item.id, item: structuredClone(item) }))
|
|
7762
|
+
});
|
|
7763
|
+
continue;
|
|
7764
|
+
}
|
|
7765
|
+
const itemDeltas = currentTurn.items.map((item) => this.buildTranscriptItemDelta(
|
|
7766
|
+
previousTurn.items.find((candidate) => candidate.id === item.id),
|
|
7767
|
+
item
|
|
7768
|
+
)).filter((item) => item !== null);
|
|
7769
|
+
if (itemDeltas.length > 0 || currentTurn.status !== previousTurn.status || currentTurn.startedAt !== previousTurn.startedAt || currentTurn.completedAt !== previousTurn.completedAt) {
|
|
7770
|
+
turnDeltas.push({
|
|
7771
|
+
id: currentTurn.id,
|
|
7772
|
+
status: currentTurn.status,
|
|
7773
|
+
startedAt: currentTurn.startedAt,
|
|
7774
|
+
completedAt: currentTurn.completedAt,
|
|
7775
|
+
items: itemDeltas
|
|
7776
|
+
});
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7779
|
+
return {
|
|
7780
|
+
threadId: current.threadId,
|
|
7781
|
+
updatedAt,
|
|
7782
|
+
turns: turnDeltas
|
|
7783
|
+
};
|
|
7784
|
+
}
|
|
7620
7785
|
flushTranscriptUpdated(threadId) {
|
|
7621
7786
|
const updatedAt = this.codexAspTranscript?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
7622
|
-
const
|
|
7787
|
+
const transcriptDelta = this.buildTranscriptDelta(threadId, this.codexAspTranscript);
|
|
7623
7788
|
const updatePayload = {
|
|
7624
7789
|
updatedAt,
|
|
7625
|
-
|
|
7626
|
-
|
|
7790
|
+
threadId,
|
|
7791
|
+
transcript: transcriptDelta.reset ?? null,
|
|
7792
|
+
transcriptDelta
|
|
7627
7793
|
};
|
|
7794
|
+
this.lastEmittedTranscripts.set(
|
|
7795
|
+
threadId,
|
|
7796
|
+
this.codexAspTranscript ? structuredClone(this.codexAspTranscript) : null
|
|
7797
|
+
);
|
|
7798
|
+
for (const emittedThreadId of this.lastEmittedTranscripts.keys()) {
|
|
7799
|
+
if (emittedThreadId !== threadId) {
|
|
7800
|
+
this.lastEmittedTranscripts.delete(emittedThreadId);
|
|
7801
|
+
}
|
|
7802
|
+
}
|
|
7628
7803
|
this.onEvent({
|
|
7629
7804
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7630
7805
|
type: CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE,
|
|
@@ -8714,7 +8889,14 @@ function getCodexTranscriptUserMessages(transcript) {
|
|
|
8714
8889
|
function getCodexTranscriptFromEvent(event) {
|
|
8715
8890
|
if (event.type !== CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE) return null;
|
|
8716
8891
|
const transcript = event.payload.transcript;
|
|
8717
|
-
|
|
8892
|
+
if (isCodexAspTranscript(transcript)) {
|
|
8893
|
+
return transcript;
|
|
8894
|
+
}
|
|
8895
|
+
const transcriptDelta = event.payload.transcriptDelta;
|
|
8896
|
+
if (!isCodexAspTranscriptDelta(transcriptDelta)) {
|
|
8897
|
+
return null;
|
|
8898
|
+
}
|
|
8899
|
+
return applyCodexAspTranscriptDelta(null, transcriptDelta);
|
|
8718
8900
|
}
|
|
8719
8901
|
function acceptedEventInCodexTranscript(acceptedEvent, transcript) {
|
|
8720
8902
|
const message = getUserMessage(acceptedEvent);
|