replicas-engine 0.1.1034 → 0.1.1036

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.
@@ -5,12 +5,12 @@ import {
5
5
  getCodexAspHost,
6
6
  restartCodexAspHost,
7
7
  restartCodexAspHostIfRunning
8
- } from "./chunk-RBHMZBDO.js";
9
- import "./chunk-WRAVQEOB.js";
10
- import "./chunk-ZY5TH3KK.js";
11
- import "./chunk-SEYXPQY7.js";
8
+ } from "./chunk-EDNMHUVD.js";
9
+ import "./chunk-2RHUTB67.js";
10
+ import "./chunk-AP442WDC.js";
11
+ import "./chunk-KVJYQOUT.js";
12
12
  import "./chunk-UZSNFLDQ.js";
13
- import "./chunk-MD2DJUY2.js";
13
+ import "./chunk-OPJ5KAGY.js";
14
14
  import "./chunk-VEQXQN22.js";
15
15
  export {
16
16
  getCodexAspHost,
@@ -14,7 +14,7 @@ import {
14
14
  isValidAgentProvider,
15
15
  parsePosixEnvFile,
16
16
  readReplicasRuntimeEnv
17
- } from "./chunk-MD2DJUY2.js";
17
+ } from "./chunk-OPJ5KAGY.js";
18
18
 
19
19
  // src/runtime-env-loader.ts
20
20
  import { readFileSync } from "fs";
@@ -5,7 +5,7 @@ import {
5
5
  extractCommandProtectionCommandText,
6
6
  isRecord,
7
7
  parseCodeHostPrUrl
8
- } from "./chunk-MD2DJUY2.js";
8
+ } from "./chunk-OPJ5KAGY.js";
9
9
 
10
10
  // src/services/published-pull-request-urls.ts
11
11
  function publishedPullRequestUrls(result) {
@@ -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-SEYXPQY7.js";
6
+ } from "./chunk-KVJYQOUT.js";
7
7
  import {
8
8
  isVersionBelow
9
- } from "./chunk-MD2DJUY2.js";
9
+ } from "./chunk-OPJ5KAGY.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.1034";
243
+ var ENGINE_PACKAGE_VERSION = "0.1.1036";
244
244
  var INITIALIZE_METHOD = "initialize";
245
245
  var INITIALIZED_NOTIFICATION = "initialized";
246
246
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -5,15 +5,15 @@ import {
5
5
  ENGINE_ENV,
6
6
  monolithRequest,
7
7
  setAgentCredentialSnapshot
8
- } from "./chunk-WRAVQEOB.js";
8
+ } from "./chunk-2RHUTB67.js";
9
9
  import {
10
10
  AppServerProcess,
11
11
  buildCodexAgentEnv
12
- } from "./chunk-ZY5TH3KK.js";
12
+ } from "./chunk-AP442WDC.js";
13
13
  import {
14
14
  SUBPROCESS_MAX_BUFFER,
15
15
  execFileAsync
16
- } from "./chunk-SEYXPQY7.js";
16
+ } from "./chunk-KVJYQOUT.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-MD2DJUY2.js";
31
+ } from "./chunk-OPJ5KAGY.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-I5GX3B77.js");
267
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-4JQWKA47.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-I5GX3B77.js");
288
+ const { restartCodexAspHostIfRunning: restartCodexAspHostIfRunning2 } = await import("./asp-host-4JQWKA47.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-MD2DJUY2.js";
6
+ } from "./chunk-OPJ5KAGY.js";
7
7
 
8
8
  // src/utils/exec.ts
9
9
  import { exec, execFile } from "child_process";
@@ -9476,36 +9476,46 @@ async function readJsonlPage(args) {
9476
9476
  throw new RangeError("Invalid JSONL page");
9477
9477
  }
9478
9478
  let startByte = endByte;
9479
- let bytes = new Uint8Array();
9480
- let items = [];
9481
- while (startByte > 0 && items.length < args.limit && (endByte - startByte < MAX_SOURCE_PAGE_BYTES || !bytes.subarray(0, -1).includes(10))) {
9482
- const nextStartByte = Math.max(0, startByte - SOURCE_RANGE_BYTES);
9479
+ let head = new Uint8Array();
9480
+ let headTerminated = false;
9481
+ let lineBreaks = 0;
9482
+ let endsWithLineBreak = false;
9483
+ const pages = [];
9484
+ let itemCount = 0;
9485
+ while (startByte > 0 && itemCount < args.limit && (endByte - startByte < MAX_SOURCE_PAGE_BYTES || lineBreaks - (endsWithLineBreak ? 1 : 0) === 0)) {
9486
+ const read = endByte - startByte;
9487
+ const nextStartByte = Math.max(0, startByte - (read < MAX_SOURCE_PAGE_BYTES ? Math.min(Math.max(SOURCE_RANGE_BYTES, read), MAX_SOURCE_PAGE_BYTES - read) : SOURCE_RANGE_BYTES));
9483
9488
  const chunk = await readExactRange(
9484
9489
  args.readRange,
9485
9490
  nextStartByte,
9486
9491
  startByte,
9487
9492
  "Incomplete JSONL page read"
9488
9493
  );
9489
- const combined = new Uint8Array(chunk.length + bytes.length);
9490
- combined.set(chunk);
9491
- combined.set(bytes, chunk.length);
9492
- bytes = combined;
9494
+ if (startByte === endByte) endsWithLineBreak = chunk[chunk.length - 1] === 10;
9495
+ for (let index = chunk.indexOf(10); index !== -1; index = chunk.indexOf(10, index + 1)) lineBreaks++;
9496
+ const bytes = new Uint8Array(chunk.length + head.length + (headTerminated ? 1 : 0));
9497
+ bytes.set(chunk);
9498
+ bytes.set(head, chunk.length);
9499
+ if (headTerminated) bytes[bytes.length - 1] = 10;
9493
9500
  startByte = nextStartByte;
9494
- items = [];
9495
- let lineStart = 0;
9496
- for (let lineEnd = bytes.indexOf(10); lineEnd !== -1; lineEnd = bytes.indexOf(10, lineStart)) {
9497
- if (!(startByte > 0 && lineStart === 0)) {
9498
- try {
9499
- const item = args.parse(JSON.parse(decoder.decode(bytes.subarray(lineStart, lineEnd))));
9500
- if (item !== void 0) items.push({ item, startByte: startByte + lineStart });
9501
- } catch {
9502
- }
9501
+ const firstLineEnd = bytes.indexOf(10);
9502
+ const page = [];
9503
+ let lineStart = startByte > 0 ? firstLineEnd + 1 : 0;
9504
+ for (let lineEnd = bytes.indexOf(10, lineStart); lineEnd !== -1; lineEnd = bytes.indexOf(10, lineStart)) {
9505
+ try {
9506
+ const item = args.parse(JSON.parse(decoder.decode(bytes.subarray(lineStart, lineEnd))));
9507
+ if (item !== void 0) page.push({ item, startByte: startByte + lineStart });
9508
+ } catch {
9503
9509
  }
9504
9510
  lineStart = lineEnd + 1;
9505
9511
  }
9512
+ head = firstLineEnd === -1 ? bytes : bytes.subarray(0, startByte > 0 ? firstLineEnd : 0);
9513
+ headTerminated = firstLineEnd !== -1;
9514
+ pages.push(page);
9515
+ itemCount += page.length;
9506
9516
  }
9507
- const selected = items.slice(-args.limit);
9508
- const firstCompleteLine = bytes.indexOf(10) + 1;
9517
+ const selected = pages.reverse().flat().slice(-args.limit);
9518
+ const firstCompleteLine = headTerminated ? head.length + 1 : 0;
9509
9519
  let before = 0;
9510
9520
  if (selected.length === args.limit) before = selected[0].startByte;
9511
9521
  else if (startByte > 0) {
@@ -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-WRAVQEOB.js";
6
+ } from "./chunk-2RHUTB67.js";
7
7
  import {
8
8
  SUBPROCESS_MAX_BUFFER,
9
9
  execFileAsync
10
- } from "./chunk-SEYXPQY7.js";
10
+ } from "./chunk-KVJYQOUT.js";
11
11
  import {
12
12
  extractCommandProtectionCommandText,
13
13
  findCommandProtectionGitLookups,
14
14
  findGitCommitSignals,
15
15
  findPrMergeSignals,
16
16
  parseCommandProtectionRequest
17
- } from "./chunk-MD2DJUY2.js";
17
+ } from "./chunk-OPJ5KAGY.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-SXWQC3OB.js";
7
- import "./chunk-WRAVQEOB.js";
8
- import "./chunk-SEYXPQY7.js";
6
+ } from "./chunk-W6NY5P76.js";
7
+ import "./chunk-2RHUTB67.js";
8
+ import "./chunk-KVJYQOUT.js";
9
9
  import {
10
10
  isRecord
11
11
  } from "./chunk-UZSNFLDQ.js";
12
- import "./chunk-MD2DJUY2.js";
12
+ import "./chunk-OPJ5KAGY.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-ZY5TH3KK.js";
11
- import "./chunk-SEYXPQY7.js";
10
+ } from "./chunk-AP442WDC.js";
11
+ import "./chunk-KVJYQOUT.js";
12
12
  import {
13
13
  AGENT,
14
14
  headlessAgentRequestSchema
15
- } from "./chunk-MD2DJUY2.js";
15
+ } from "./chunk-OPJ5KAGY.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-SXWQC3OB.js";
35
+ } from "./chunk-W6NY5P76.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-X6SC3YRN.js";
60
+ } from "./chunk-3OBN7KPB.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-RBHMZBDO.js";
74
+ } from "./chunk-EDNMHUVD.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-WRAVQEOB.js";
82
+ } from "./chunk-2RHUTB67.js";
83
83
  import {
84
84
  AspClient,
85
85
  getCodexModelProvider
86
- } from "./chunk-ZY5TH3KK.js";
86
+ } from "./chunk-AP442WDC.js";
87
87
  import {
88
88
  SUBPROCESS_MAX_BUFFER,
89
89
  execAsync,
90
90
  execFileAsync
91
- } from "./chunk-SEYXPQY7.js";
91
+ } from "./chunk-KVJYQOUT.js";
92
92
  import {
93
93
  isRecord as isRecord2
94
94
  } from "./chunk-UZSNFLDQ.js";
@@ -322,7 +322,7 @@ import {
322
322
  workspaceTokenRequestSchema,
323
323
  workspaceTokenResponseSchema,
324
324
  wrapInTag
325
- } from "./chunk-MD2DJUY2.js";
325
+ } from "./chunk-OPJ5KAGY.js";
326
326
  import {
327
327
  cloneMcpConfig,
328
328
  ensureCompatibilityImports,
@@ -11074,7 +11074,7 @@ async function registerDesktopPreview(signal) {
11074
11074
  }
11075
11075
 
11076
11076
  // src/services/chat/chat-service.ts
11077
- import { appendFile as appendFile5, copyFile as copyFile2, mkdir as mkdir20, readFile as readFile19, rename as rename4, rm as rm4 } from "fs/promises";
11077
+ import { appendFile as appendFile5, copyFile as copyFile2, mkdir as mkdir20, readFile as readFile19, rename as rename4, rm as rm4, stat as stat7 } from "fs/promises";
11078
11078
  import { join as join35 } from "path";
11079
11079
  import { randomUUID as randomUUID11 } from "crypto";
11080
11080
 
@@ -60325,7 +60325,7 @@ function shouldFlushChatTranscript(historyDir, chat, chatsById, sessionHistoryCa
60325
60325
  if (!chat) return false;
60326
60326
  return chat.parentChatId ? chatsById.has(chat.parentChatId) : sessionHistoryCapture;
60327
60327
  }
60328
- async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), capture) {
60328
+ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), capture, onUploaded) {
60329
60329
  let flushed = 0;
60330
60330
  let failed = 0;
60331
60331
  const revisions = [];
@@ -60343,9 +60343,12 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), ca
60343
60343
  const chat = chatsById.get(chatId);
60344
60344
  if (!shouldFlushChatTranscript(dir, chat, chatsById, Boolean(capture))) continue;
60345
60345
  tasks.push(
60346
- uploadChatTranscript(chatId, join32(dir, entry), chat, capture).then((artifact) => {
60346
+ uploadChatTranscript(chatId, join32(dir, entry), chat, capture).then(async (artifact) => {
60347
60347
  flushed++;
60348
60348
  if (artifact && capture) revisions.push(artifact);
60349
+ await onUploaded?.(chatId, artifact).catch((err) => {
60350
+ console.error("[ChatTranscriptUploader] recording the uploaded history version failed:", { chatId, err });
60351
+ });
60349
60352
  }).catch((err) => {
60350
60353
  failed++;
60351
60354
  console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
@@ -60368,8 +60371,10 @@ function uploadChatTranscript(chatId, filePath, chat, capture) {
60368
60371
  return upload;
60369
60372
  }
60370
60373
  async function uploadChatTranscriptNow(chatId, filePath, chat, capture) {
60374
+ const versionBeforeStat = chat?.currentHistoryVersion?.();
60371
60375
  const { size } = await stat5(filePath);
60372
60376
  if (size === 0) return null;
60377
+ const historyVersion = versionBeforeStat === chat?.currentHistoryVersion?.() ? versionBeforeStat : void 0;
60373
60378
  const metadata = chat ? {
60374
60379
  provider: chat.provider,
60375
60380
  // Chats with no turn since this engine version fall back to the auth live at upload.
@@ -60381,7 +60386,8 @@ async function uploadChatTranscriptNow(chatId, filePath, chat, capture) {
60381
60386
  updatedAt: chat.updatedAt,
60382
60387
  parentChatId: chat.parentChatId,
60383
60388
  deletedAt: chat.deletedAt ?? null,
60384
- fork: chat.fork ?? null
60389
+ fork: chat.fork ?? null,
60390
+ ...historyVersion ? { historyVersion } : {}
60385
60391
  } : {};
60386
60392
  if (capture) {
60387
60393
  const hash = createHash7("sha256");
@@ -60638,6 +60644,7 @@ async function buildForkHandoff(input) {
60638
60644
  // src/services/chat/slack-activity-stream.ts
60639
60645
  var FLUSH_INTERVAL_MS = 3e3;
60640
60646
  var MAX_ACTIVITY_LENGTH = 100;
60647
+ var MAX_THOUGHT_LENGTH = 500;
60641
60648
  var MAX_CODE_LENGTH = 40;
60642
60649
  var MAX_DONE_ATTEMPTS = 3;
60643
60650
  var GENERIC_STEPS = {
@@ -60659,11 +60666,11 @@ var code = (text) => {
60659
60666
  };
60660
60667
  var basename4 = (path7) => path7.split("/").pop() || path7;
60661
60668
  function describeActivity(message, idle) {
60669
+ if (planItemsFromMessage(message) || message.type === "tool_call" && message.inputRequest) return null;
60662
60670
  if (message.type === "agent" || message.type === "reasoning" && !isCompaction(message)) {
60663
- const heading = message.type === "reasoning" ? [...message.content.matchAll(/^\*\*(.+?)\*\*$/gm)].at(-1)?.[1] : void 0;
60664
- return { thought: clean(heading ?? "") || "Thinking" };
60671
+ const thought = message.content.replace(/\*\*/g, "").replace(/\s+/g, " ").trim();
60672
+ return thought ? { thought: thought.length > MAX_THOUGHT_LENGTH ? `\u2026${thought.slice(1 - MAX_THOUGHT_LENGTH)}` : thought } : null;
60665
60673
  }
60666
- if (planItemsFromMessage(message) || message.type === "tool_call" && message.inputRequest) return null;
60667
60674
  const steps = describeMessageSteps(message);
60668
60675
  const step = steps.at(-1);
60669
60676
  if (!step) return null;
@@ -60693,9 +60700,6 @@ var SlackActivityStream = class {
60693
60700
  stopped = false;
60694
60701
  queued = false;
60695
60702
  noteEvent(event) {
60696
- if (event.type === CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE) return;
60697
- const partialType = event.type === CODEX_ITEM_PARTIAL_EVENT_TYPE ? codexItemFromEvent(event)?.item.type : void 0;
60698
- if (partialType === "agentMessage" || partialType === "reasoning") return;
60699
60703
  const streamId = getEventStreamId(event);
60700
60704
  const index = streamId ? this.events.findLastIndex((previous) => getEventStreamId(previous) === streamId) : -1;
60701
60705
  if (index >= 0) this.events[index] = event;
@@ -60728,7 +60732,9 @@ var SlackActivityStream = class {
60728
60732
  if (idle && this.settled) return true;
60729
60733
  this.settled = idle;
60730
60734
  this.dirty = false;
60731
- activity = parseDisplayMessages(this.events, this.provider).map((message) => describeActivity(message, idle)).findLast(Boolean) ?? null;
60735
+ const latestReasoning = this.provider === "codex" ? this.events.findLast((event2) => codexItemFromEvent(event2)?.item.type === "reasoning") : void 0;
60736
+ const events = latestReasoning ? this.events.filter((event2) => event2 === latestReasoning || codexItemFromEvent(event2)?.item.type !== "reasoning") : this.events;
60737
+ activity = parseDisplayMessages(events, this.provider).map((message) => describeActivity(message, idle)).findLast(Boolean) ?? null;
60732
60738
  if (!activity || JSON.stringify(activity) === this.sent) return true;
60733
60739
  }
60734
60740
  this.attempted = true;
@@ -60855,6 +60861,7 @@ function normalizePersistedChat(chat) {
60855
60861
  ...chat.chatCredential === "workspace" || agentCredentialSnapshotSchema.safeParse(chat.chatCredential).success ? { chatCredential: chat.chatCredential } : {},
60856
60862
  transcriptAuth: normalizeTranscriptAuth(chat.transcriptAuth),
60857
60863
  ...typeof chat.lastSenderKey === "string" ? { lastSenderKey: chat.lastSenderKey } : {},
60864
+ ...isRecord2(chat.uploadedHistory) && typeof chat.uploadedHistory.version === "string" && typeof chat.uploadedHistory.size === "number" ? { uploadedHistory: { version: chat.uploadedHistory.version, size: chat.uploadedHistory.size } } : {},
60858
60865
  removedMessageIds: Array.isArray(chat.removedMessageIds) ? chat.removedMessageIds.filter((id) => typeof id === "string").slice(-MAX_REMOVED_MESSAGE_IDS) : [],
60859
60866
  acceptedSendResponses: isRecord2(chat.acceptedSendResponses) ? Object.fromEntries(Object.entries(chat.acceptedSendResponses).filter((entry) => {
60860
60867
  const response = entry[1];
@@ -60898,6 +60905,10 @@ var ChatService = class {
60898
60905
  const persisted = await this.loadChats();
60899
60906
  for (const chat of persisted) {
60900
60907
  const runtime = this.createRuntimeChat(chat);
60908
+ if (chat.uploadedHistory) {
60909
+ const size = await stat7(this.historyPath(chat)).then(({ size: size2 }) => size2, () => null);
60910
+ if (size === chat.uploadedHistory.size) runtime.historyVersion = chat.uploadedHistory.version;
60911
+ }
60901
60912
  this.chats.set(chat.id, runtime);
60902
60913
  }
60903
60914
  }
@@ -61515,7 +61526,7 @@ var ChatService = class {
61515
61526
  return descendants;
61516
61527
  }
61517
61528
  async deleteHistoryFile(persisted) {
61518
- const historyPath = join35(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`);
61529
+ const historyPath = this.historyPath(persisted);
61519
61530
  await Promise.all([
61520
61531
  historyPath,
61521
61532
  `${historyPath}.pages.jsonl`,
@@ -61712,15 +61723,30 @@ var ChatService = class {
61712
61723
  return count;
61713
61724
  }
61714
61725
  toTranscriptSource(chat) {
61715
- return { ...this.toSummary(chat), removedMessageIds: chat.persisted.removedMessageIds, transcriptAuth: chat.persisted.transcriptAuth };
61726
+ return {
61727
+ ...this.toSummary(chat),
61728
+ removedMessageIds: chat.persisted.removedMessageIds,
61729
+ transcriptAuth: chat.persisted.transcriptAuth,
61730
+ currentHistoryVersion: () => this.toSummary(chat).historyVersion
61731
+ };
61732
+ }
61733
+ historyPath(persisted) {
61734
+ return join35(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`);
61735
+ }
61736
+ async recordUploadedHistory(chatId, artifact) {
61737
+ const chat = this.getRuntimeChat(chatId);
61738
+ const version = artifact?.metadata.historyVersion;
61739
+ if (!chat || !artifact || !version || version !== this.toSummary(chat).historyVersion) return;
61740
+ chat.persisted.uploadedHistory = { version, size: artifact.size };
61741
+ await this.persistAllChats();
61716
61742
  }
61717
61743
  uploadChatTranscript(chat) {
61718
61744
  const chatId = chat.persisted.id;
61719
61745
  uploadChatTranscript(
61720
61746
  chatId,
61721
- join35(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
61747
+ this.historyPath(chat.persisted),
61722
61748
  this.toTranscriptSource(chat)
61723
- ).catch((err) => {
61749
+ ).then((artifact) => this.recordUploadedHistory(chatId, artifact)).catch((err) => {
61724
61750
  console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
61725
61751
  });
61726
61752
  }
@@ -61735,14 +61761,14 @@ var ChatService = class {
61735
61761
  async flushAllChatTranscripts() {
61736
61762
  return flushAllChatTranscripts(new Map(
61737
61763
  [...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toTranscriptSource(chat)])
61738
- ));
61764
+ ), void 0, (chatId, artifact) => this.recordUploadedHistory(chatId, artifact));
61739
61765
  }
61740
61766
  async flushAllWorkspaceArtifacts(capture) {
61741
61767
  const chatsById = new Map(
61742
61768
  [...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toTranscriptSource(chat)])
61743
61769
  );
61744
61770
  const [chatTranscripts, canvas, repoState, engineLogs, [chatActivity]] = await Promise.all([
61745
- flushAllChatTranscripts(chatsById, capture),
61771
+ flushAllChatTranscripts(chatsById, capture, (chatId, artifact) => this.recordUploadedHistory(chatId, artifact)),
61746
61772
  flushAllCanvasItems(),
61747
61773
  flushRepoState(),
61748
61774
  flushAllEngineLogs(),
@@ -62761,7 +62787,7 @@ var RepoFileService = class {
62761
62787
  // src/v1-routes.ts
62762
62788
  import { Hono } from "hono";
62763
62789
  import { z as z5 } from "zod";
62764
- import { readdir as readdir11, stat as stat7, readFile as readFile23 } from "fs/promises";
62790
+ import { readdir as readdir11, stat as stat8, readFile as readFile23 } from "fs/promises";
62765
62791
  import { join as join40, resolve as resolve5 } from "path";
62766
62792
 
62767
62793
  // src/services/warm-hooks-service.ts
@@ -64271,7 +64297,7 @@ data: ${JSON.stringify("Terminal session not found")}
64271
64297
  const sessions = await Promise.all(
64272
64298
  logFiles.map(async (filename) => {
64273
64299
  const filePath = join40(LOG_DIR, filename);
64274
- const fileStat = await stat7(filePath);
64300
+ const fileStat = await stat8(filePath);
64275
64301
  const sessionId = filename.replace(/\.log$/, "");
64276
64302
  return {
64277
64303
  sessionId,
@@ -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-X6SC3YRN.js";
6
+ } from "./chunk-3OBN7KPB.js";
7
7
  import {
8
8
  isRecord
9
9
  } from "./chunk-UZSNFLDQ.js";
10
10
  import {
11
11
  shouldRefreshPullRequests
12
- } from "./chunk-MD2DJUY2.js";
12
+ } from "./chunk-OPJ5KAGY.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/services/post-tool-pr-notifier.ts
@@ -9,7 +9,7 @@ import {
9
9
  spawnSubagentRequestSchema,
10
10
  subagentResponseSchema,
11
11
  waitSubagentRequestSchema
12
- } from "./chunk-MD2DJUY2.js";
12
+ } from "./chunk-OPJ5KAGY.js";
13
13
  import "./chunk-VEQXQN22.js";
14
14
 
15
15
  // src/subagent-mcp.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.1034",
3
+ "version": "0.1.1036",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",