replicas-engine 0.1.251 → 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 +182 -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-v1";
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 = [
@@ -1920,6 +2000,9 @@ var AUDIT_LOG_ACTION = {
1920
2000
  };
1921
2001
  var AUDIT_LOG_ACTIONS = Object.values(AUDIT_LOG_ACTION);
1922
2002
 
2003
+ // ../shared/src/automations/types.ts
2004
+ var AUTOMATION_DEBOUNCE_MAX_SECONDS = 24 * 60 * 60;
2005
+
1923
2006
  // ../shared/src/display-message/types.ts
1924
2007
  var BACKGROUND_TASK_SUBTYPES = /* @__PURE__ */ new Set([
1925
2008
  "task_started",
@@ -6139,7 +6222,7 @@ var AspClient = class {
6139
6222
  // src/managers/codex-asp/app-server-process.ts
6140
6223
  var DEFAULT_CODEX_BINARY = "codex";
6141
6224
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6142
- var ENGINE_PACKAGE_VERSION = "0.1.251";
6225
+ var ENGINE_PACKAGE_VERSION = "0.1.253";
6143
6226
  var INITIALIZE_METHOD = "initialize";
6144
6227
  var INITIALIZED_NOTIFICATION = "initialized";
6145
6228
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -6962,6 +7045,7 @@ var CodexAspManager = class extends CodingAgentManager {
6962
7045
  threadAttached = false;
6963
7046
  historyEvents = [];
6964
7047
  codexAspTranscript = null;
7048
+ lastEmittedTranscripts = /* @__PURE__ */ new Map();
6965
7049
  codexAspSequence = 0;
6966
7050
  quotaStatus = new CodexQuotaStatusTracker();
6967
7051
  currentGoal = null;
@@ -7437,6 +7521,9 @@ var CodexAspManager = class extends CodingAgentManager {
7437
7521
  this.codexAspSequence = next;
7438
7522
  }
7439
7523
  mergeTranscriptSnapshot(snapshot) {
7524
+ if (snapshot?.threadId && this.codexAspTranscript?.threadId !== snapshot.threadId) {
7525
+ this.lastEmittedTranscripts.clear();
7526
+ }
7440
7527
  this.codexAspTranscript = mergeCodexAspTranscripts(this.codexAspTranscript, snapshot);
7441
7528
  this.syncTranscriptSequence(this.codexAspTranscript);
7442
7529
  return this.codexAspTranscript;
@@ -7445,6 +7532,7 @@ var CodexAspManager = class extends CodingAgentManager {
7445
7532
  if (this.codexAspTranscript?.threadId === threadId) {
7446
7533
  return this.codexAspTranscript;
7447
7534
  }
7535
+ this.lastEmittedTranscripts.clear();
7448
7536
  this.codexAspTranscript = {
7449
7537
  threadId,
7450
7538
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -7614,14 +7702,95 @@ var CodexAspManager = class extends CodingAgentManager {
7614
7702
  emitTranscriptUpdated(threadId, options = {}) {
7615
7703
  this.transcriptUpdateCoalescer.schedule(threadId, options);
7616
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
+ }
7617
7776
  flushTranscriptUpdated(threadId) {
7618
7777
  const updatedAt = this.codexAspTranscript?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
7619
- const transcript = this.codexAspTranscript ? structuredClone(this.codexAspTranscript) : null;
7778
+ const transcriptDelta = this.buildTranscriptDelta(threadId, this.codexAspTranscript);
7620
7779
  const updatePayload = {
7621
7780
  updatedAt,
7622
- transcript,
7623
- threadId
7781
+ threadId,
7782
+ transcript: transcriptDelta.reset ?? null,
7783
+ transcriptDelta
7624
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
+ }
7625
7794
  this.onEvent({
7626
7795
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7627
7796
  type: CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE,
@@ -8711,7 +8880,14 @@ function getCodexTranscriptUserMessages(transcript) {
8711
8880
  function getCodexTranscriptFromEvent(event) {
8712
8881
  if (event.type !== CODEX_ASP_TRANSCRIPT_UPDATED_EVENT_TYPE) return null;
8713
8882
  const transcript = event.payload.transcript;
8714
- 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);
8715
8891
  }
8716
8892
  function acceptedEventInCodexTranscript(acceptedEvent, transcript) {
8717
8893
  const message = getUserMessage(acceptedEvent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.251",
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",