replicas-engine 0.1.252 → 0.1.253

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.
Files changed (2) hide show
  1. package/dist/src/index.js +179 -6
  2. 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-v2";
300
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-02-v3";
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 = [
@@ -6142,7 +6222,7 @@ var AspClient = class {
6142
6222
  // src/managers/codex-asp/app-server-process.ts
6143
6223
  var DEFAULT_CODEX_BINARY = "codex";
6144
6224
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6145
- var ENGINE_PACKAGE_VERSION = "0.1.252";
6225
+ var ENGINE_PACKAGE_VERSION = "0.1.253";
6146
6226
  var INITIALIZE_METHOD = "initialize";
6147
6227
  var INITIALIZED_NOTIFICATION = "initialized";
6148
6228
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -6965,6 +7045,7 @@ var CodexAspManager = class extends CodingAgentManager {
6965
7045
  threadAttached = false;
6966
7046
  historyEvents = [];
6967
7047
  codexAspTranscript = null;
7048
+ lastEmittedTranscripts = /* @__PURE__ */ new Map();
6968
7049
  codexAspSequence = 0;
6969
7050
  quotaStatus = new CodexQuotaStatusTracker();
6970
7051
  currentGoal = null;
@@ -7440,6 +7521,9 @@ var CodexAspManager = class extends CodingAgentManager {
7440
7521
  this.codexAspSequence = next;
7441
7522
  }
7442
7523
  mergeTranscriptSnapshot(snapshot) {
7524
+ if (snapshot?.threadId && this.codexAspTranscript?.threadId !== snapshot.threadId) {
7525
+ this.lastEmittedTranscripts.clear();
7526
+ }
7443
7527
  this.codexAspTranscript = mergeCodexAspTranscripts(this.codexAspTranscript, snapshot);
7444
7528
  this.syncTranscriptSequence(this.codexAspTranscript);
7445
7529
  return this.codexAspTranscript;
@@ -7448,6 +7532,7 @@ var CodexAspManager = class extends CodingAgentManager {
7448
7532
  if (this.codexAspTranscript?.threadId === threadId) {
7449
7533
  return this.codexAspTranscript;
7450
7534
  }
7535
+ this.lastEmittedTranscripts.clear();
7451
7536
  this.codexAspTranscript = {
7452
7537
  threadId,
7453
7538
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -7617,14 +7702,95 @@ var CodexAspManager = class extends CodingAgentManager {
7617
7702
  emitTranscriptUpdated(threadId, options = {}) {
7618
7703
  this.transcriptUpdateCoalescer.schedule(threadId, options);
7619
7704
  }
7705
+ buildTranscriptItemDelta(previous, current) {
7706
+ if (!previous || previous.type !== current.type) {
7707
+ return { id: current.id, item: structuredClone(current) };
7708
+ }
7709
+ if (current.type === "agentMessage" && previous.type === "agentMessage" && current.text.startsWith(previous.text) && current.text.length > previous.text.length) {
7710
+ return {
7711
+ id: current.id,
7712
+ appendText: current.text.slice(previous.text.length)
7713
+ };
7714
+ }
7715
+ if ((current.type === "commandExecution" || current.type === "fileChange") && previous.type === current.type && current.output && current.output.startsWith(previous.output ?? "") && current.output.length > (previous.output ?? "").length) {
7716
+ const { output: _output, ...itemWithoutOutput } = current;
7717
+ const item = {
7718
+ ...itemWithoutOutput,
7719
+ output: previous.output
7720
+ };
7721
+ return {
7722
+ id: current.id,
7723
+ item,
7724
+ appendOutput: current.output.slice((previous.output ?? "").length)
7725
+ };
7726
+ }
7727
+ if (JSON.stringify(previous) === JSON.stringify(current)) {
7728
+ return null;
7729
+ }
7730
+ return { id: current.id, item: structuredClone(current) };
7731
+ }
7732
+ buildTranscriptDelta(threadId, current) {
7733
+ const previous = this.lastEmittedTranscripts.get(threadId);
7734
+ const updatedAt = current?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
7735
+ if (!current || previous === void 0 || previous?.threadId !== current.threadId) {
7736
+ return {
7737
+ threadId,
7738
+ updatedAt,
7739
+ reset: current ? structuredClone(current) : null,
7740
+ turns: []
7741
+ };
7742
+ }
7743
+ const turnDeltas = [];
7744
+ for (const currentTurn of current.turns) {
7745
+ const previousTurn = previous.turns.find((turn) => turn.id === currentTurn.id);
7746
+ if (!previousTurn) {
7747
+ turnDeltas.push({
7748
+ id: currentTurn.id,
7749
+ status: currentTurn.status,
7750
+ startedAt: currentTurn.startedAt,
7751
+ completedAt: currentTurn.completedAt,
7752
+ items: currentTurn.items.map((item) => ({ id: item.id, item: structuredClone(item) }))
7753
+ });
7754
+ continue;
7755
+ }
7756
+ const itemDeltas = currentTurn.items.map((item) => this.buildTranscriptItemDelta(
7757
+ previousTurn.items.find((candidate) => candidate.id === item.id),
7758
+ item
7759
+ )).filter((item) => item !== null);
7760
+ if (itemDeltas.length > 0 || currentTurn.status !== previousTurn.status || currentTurn.startedAt !== previousTurn.startedAt || currentTurn.completedAt !== previousTurn.completedAt) {
7761
+ turnDeltas.push({
7762
+ id: currentTurn.id,
7763
+ status: currentTurn.status,
7764
+ startedAt: currentTurn.startedAt,
7765
+ completedAt: currentTurn.completedAt,
7766
+ items: itemDeltas
7767
+ });
7768
+ }
7769
+ }
7770
+ return {
7771
+ threadId: current.threadId,
7772
+ updatedAt,
7773
+ turns: turnDeltas
7774
+ };
7775
+ }
7620
7776
  flushTranscriptUpdated(threadId) {
7621
7777
  const updatedAt = this.codexAspTranscript?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
7622
- const transcript = this.codexAspTranscript ? structuredClone(this.codexAspTranscript) : null;
7778
+ const transcriptDelta = this.buildTranscriptDelta(threadId, this.codexAspTranscript);
7623
7779
  const updatePayload = {
7624
7780
  updatedAt,
7625
- transcript,
7626
- threadId
7781
+ threadId,
7782
+ transcript: transcriptDelta.reset ?? null,
7783
+ transcriptDelta
7627
7784
  };
7785
+ this.lastEmittedTranscripts.set(
7786
+ threadId,
7787
+ this.codexAspTranscript ? structuredClone(this.codexAspTranscript) : null
7788
+ );
7789
+ for (const emittedThreadId of this.lastEmittedTranscripts.keys()) {
7790
+ if (emittedThreadId !== threadId) {
7791
+ this.lastEmittedTranscripts.delete(emittedThreadId);
7792
+ }
7793
+ }
7628
7794
  this.onEvent({
7629
7795
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7630
7796
  type: CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE,
@@ -8714,7 +8880,14 @@ function getCodexTranscriptUserMessages(transcript) {
8714
8880
  function getCodexTranscriptFromEvent(event) {
8715
8881
  if (event.type !== CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE) return null;
8716
8882
  const transcript = event.payload.transcript;
8717
- return isCodexAspTranscript(transcript) ? transcript : null;
8883
+ if (isCodexAspTranscript(transcript)) {
8884
+ return transcript;
8885
+ }
8886
+ const transcriptDelta = event.payload.transcriptDelta;
8887
+ if (!isCodexAspTranscriptDelta(transcriptDelta)) {
8888
+ return null;
8889
+ }
8890
+ return applyCodexAspTranscriptDelta(null, transcriptDelta);
8718
8891
  }
8719
8892
  function acceptedEventInCodexTranscript(acceptedEvent, transcript) {
8720
8893
  const message = getUserMessage(acceptedEvent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.252",
3
+ "version": "0.1.253",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",