replicas-engine 0.1.580 → 0.1.581

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 +141 -37
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -3311,14 +3311,23 @@ function chatHistoryPageParamsFromQuery(query2) {
3311
3311
  beforeTurn: parse(query2.beforeTurn)
3312
3312
  };
3313
3313
  }
3314
+ function getChatHistoryPageWindow(totalItems, limit, before) {
3315
+ const endIndex = Math.min(before ?? totalItems, totalItems);
3316
+ return { startIndex: Math.max(0, endIndex - Math.max(1, limit)), endIndex };
3317
+ }
3314
3318
  function paginateChatHistory(full, params) {
3315
3319
  if (params.limit === void 0) return { ...full, totalEvents: full.events.length };
3316
- const limit = Math.max(1, params.limit);
3317
- const eventsEnd = Math.min(params.beforeEvent ?? full.events.length, full.events.length);
3318
- const eventsStartIndex = Math.max(0, eventsEnd - limit);
3320
+ const { startIndex: eventsStartIndex, endIndex: eventsEnd } = getChatHistoryPageWindow(
3321
+ full.events.length,
3322
+ params.limit,
3323
+ params.beforeEvent
3324
+ );
3319
3325
  const turns = full.codexAspTranscript?.turns;
3320
- const turnsEnd = turns ? Math.min(params.beforeTurn ?? turns.length, turns.length) : 0;
3321
- const turnsStartIndex = Math.max(0, turnsEnd - limit);
3326
+ const { startIndex: turnsStartIndex, endIndex: turnsEnd } = getChatHistoryPageWindow(
3327
+ turns?.length ?? 0,
3328
+ params.limit,
3329
+ params.beforeTurn
3330
+ );
3322
3331
  const codexAspTranscript = full.codexAspTranscript && turns && (turnsStartIndex > 0 || turnsEnd < turns.length) ? { ...full.codexAspTranscript, turns: turns.slice(turnsStartIndex, turnsEnd) } : full.codexAspTranscript;
3323
3332
  return {
3324
3333
  ...full,
@@ -9406,13 +9415,14 @@ function isNotFoundError(error) {
9406
9415
  }
9407
9416
 
9408
9417
  // src/managers/codex-asp/codex-history-file.ts
9409
- import { appendFile as appendFile2, readFile as readFile9 } from "fs/promises";
9418
+ import { appendFile as appendFile2, open, readFile as readFile9 } from "fs/promises";
9410
9419
  var CodexHistoryFile = class {
9411
9420
  constructor(filePath) {
9412
9421
  this.filePath = filePath;
9413
9422
  }
9414
9423
  filePath;
9415
9424
  writeLock = new AsyncLock();
9425
+ eventLineIndex = null;
9416
9426
  /** Best-effort ordered append; failures must not disrupt the turn. */
9417
9427
  append(event) {
9418
9428
  void this.writeLock.run(
@@ -9435,6 +9445,88 @@ var CodexHistoryFile = class {
9435
9445
  return { events: [], transcript: null, transcriptsByThreadId: /* @__PURE__ */ new Map() };
9436
9446
  }
9437
9447
  }
9448
+ async loadEventsPage(page) {
9449
+ if (page.limit === void 0) {
9450
+ const history2 = await this.load();
9451
+ return { events: history2.events, eventsStartIndex: 0, totalEvents: history2.events.length };
9452
+ }
9453
+ let file;
9454
+ try {
9455
+ file = await open(this.filePath, "r");
9456
+ } catch (error) {
9457
+ if (!(error && typeof error === "object" && "code" in error && error.code === "ENOENT")) {
9458
+ console.error("[CodexHistoryFile] Failed to open history file:", error);
9459
+ }
9460
+ return { events: [], eventsStartIndex: 0, totalEvents: 0 };
9461
+ }
9462
+ try {
9463
+ const stats = await file.stat();
9464
+ let index = this.eventLineIndex;
9465
+ if (!index || index.size !== stats.size || index.mtimeMs !== stats.mtimeMs) {
9466
+ const starts = stats.size > 0 ? [0] : [];
9467
+ const buffer = Buffer.allocUnsafe(64 * 1024);
9468
+ let position = 0;
9469
+ while (position < stats.size) {
9470
+ const { bytesRead: bytesRead2 } = await file.read(
9471
+ buffer,
9472
+ 0,
9473
+ Math.min(buffer.length, stats.size - position),
9474
+ position
9475
+ );
9476
+ if (bytesRead2 === 0) break;
9477
+ for (let offset = 0; offset < bytesRead2; offset += 1) {
9478
+ const next = position + offset + 1;
9479
+ if (buffer[offset] === 10 && next < stats.size) starts.push(next);
9480
+ }
9481
+ position += bytesRead2;
9482
+ }
9483
+ index = { size: stats.size, mtimeMs: stats.mtimeMs, starts };
9484
+ this.eventLineIndex = index;
9485
+ }
9486
+ const totalEvents2 = index.starts.length;
9487
+ const { startIndex: eventsStartIndex2, endIndex: eventsEnd2 } = getChatHistoryPageWindow(
9488
+ totalEvents2,
9489
+ page.limit,
9490
+ page.beforeEvent
9491
+ );
9492
+ const startByte = index.starts[eventsStartIndex2] ?? index.size;
9493
+ const endByte = index.starts[eventsEnd2] ?? index.size;
9494
+ const content = Buffer.allocUnsafe(endByte - startByte);
9495
+ let bytesRead = 0;
9496
+ while (bytesRead < content.length) {
9497
+ const result = await file.read(
9498
+ content,
9499
+ bytesRead,
9500
+ content.length - bytesRead,
9501
+ startByte + bytesRead
9502
+ );
9503
+ if (result.bytesRead === 0) break;
9504
+ bytesRead += result.bytesRead;
9505
+ }
9506
+ if (bytesRead === content.length) {
9507
+ const parsed = parseAgentEventJsonlWithCodexAspTranscript(content.toString("utf-8"));
9508
+ if (!parsed.transcript && parsed.events.length === eventsEnd2 - eventsStartIndex2) {
9509
+ return { events: parsed.events, eventsStartIndex: eventsStartIndex2, totalEvents: totalEvents2 };
9510
+ }
9511
+ }
9512
+ } catch (error) {
9513
+ console.error("[CodexHistoryFile] Failed to load history page:", error);
9514
+ } finally {
9515
+ await file.close();
9516
+ }
9517
+ const history = await this.load();
9518
+ const totalEvents = history.events.length;
9519
+ const { startIndex: eventsStartIndex, endIndex: eventsEnd } = getChatHistoryPageWindow(
9520
+ totalEvents,
9521
+ page.limit,
9522
+ page.beforeEvent
9523
+ );
9524
+ return {
9525
+ events: history.events.slice(eventsStartIndex, eventsEnd),
9526
+ eventsStartIndex,
9527
+ totalEvents
9528
+ };
9529
+ }
9438
9530
  };
9439
9531
 
9440
9532
  // src/managers/claude-activity.ts
@@ -10563,13 +10655,13 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
10563
10655
  }
10564
10656
  return null;
10565
10657
  }
10566
- async getHistory() {
10658
+ async getHistory(page = {}) {
10567
10659
  await this.initialized;
10568
10660
  await this.historyFile.flush();
10569
- const history = await this.historyFile.load();
10661
+ const history = await this.historyFile.loadEventsPage(page);
10570
10662
  return {
10571
10663
  thread_id: this.sessionId,
10572
- events: history.events
10664
+ ...history
10573
10665
  };
10574
10666
  }
10575
10667
  partialMessageStreamKey(message) {
@@ -10896,7 +10988,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
10896
10988
  var MIN_CODEX_CLI_VERSION = "0.144.6";
10897
10989
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
10898
10990
  var codexCliVersionEnsured = null;
10899
- var ENGINE_PACKAGE_VERSION = "0.1.580";
10991
+ var ENGINE_PACKAGE_VERSION = "0.1.581";
10900
10992
  var INITIALIZE_METHOD = "initialize";
10901
10993
  var INITIALIZED_NOTIFICATION = "initialized";
10902
10994
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -12009,22 +12101,24 @@ var CodexAspManager = class extends CodingAgentManager {
12009
12101
  this.recordUserMessageEvent(request);
12010
12102
  return true;
12011
12103
  }
12012
- async getHistory() {
12104
+ async getHistory(page = {}) {
12013
12105
  if (!this.currentThreadId) {
12014
- return { thread_id: null, events: [], goal: null };
12106
+ return paginateChatHistory({ thread_id: null, events: [], goal: null }, page);
12015
12107
  }
12016
- if (this.activeTurnId && this.codexAspTranscript?.threadId === this.currentThreadId) {
12017
- try {
12018
- const host = await getCodexAspHost();
12019
- await this.refreshThreadGoal(host, this.currentThreadId);
12020
- } catch {
12108
+ if (this.codexAspTranscript?.threadId === this.currentThreadId) {
12109
+ if (page.beforeEvent === void 0 && page.beforeTurn === void 0) {
12110
+ try {
12111
+ const host = await getCodexAspHost();
12112
+ await this.refreshThreadGoal(host, this.currentThreadId);
12113
+ } catch {
12114
+ }
12021
12115
  }
12022
- return {
12116
+ return paginateChatHistory({
12023
12117
  thread_id: this.currentThreadId,
12024
12118
  events: [...this.historyEvents],
12025
12119
  codexAspTranscript: this.codexAspTranscript,
12026
12120
  goal: this.currentGoal
12027
- };
12121
+ }, page);
12028
12122
  }
12029
12123
  try {
12030
12124
  const host = await getCodexAspHost();
@@ -12039,20 +12133,20 @@ var CodexAspManager = class extends CodingAgentManager {
12039
12133
  if (transcript) {
12040
12134
  transcript.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
12041
12135
  }
12042
- return {
12136
+ return paginateChatHistory({
12043
12137
  thread_id: this.currentThreadId,
12044
12138
  events: [...this.historyEvents],
12045
12139
  codexAspTranscript: transcript,
12046
12140
  goal: this.currentGoal
12047
- };
12141
+ }, page);
12048
12142
  } catch {
12049
12143
  }
12050
- return {
12144
+ return paginateChatHistory({
12051
12145
  thread_id: this.currentThreadId,
12052
12146
  events: [...this.historyEvents],
12053
12147
  codexAspTranscript: this.codexAspTranscript,
12054
12148
  goal: this.currentGoal
12055
- };
12149
+ }, page);
12056
12150
  }
12057
12151
  getGoal() {
12058
12152
  return this.currentGoal;
@@ -13260,12 +13354,12 @@ var CursorManager = class extends CodingAgentManager {
13260
13354
  }
13261
13355
  this.agent = null;
13262
13356
  }
13263
- async getHistory() {
13357
+ async getHistory(page = {}) {
13264
13358
  await this.historyFile.flush();
13265
- const history = await this.historyFile.load();
13359
+ const history = await this.historyFile.loadEventsPage(page);
13266
13360
  return {
13267
13361
  thread_id: this.agent?.agentId ?? this.initialSessionId,
13268
- events: history.events,
13362
+ ...history,
13269
13363
  goal: null
13270
13364
  };
13271
13365
  }
@@ -13859,12 +13953,12 @@ var OpencodeManager = class extends CodingAgentManager {
13859
13953
  { throwOnError: true }
13860
13954
  );
13861
13955
  }
13862
- async getHistory() {
13956
+ async getHistory(page = {}) {
13863
13957
  await this.historyFile.flush();
13864
- const history = await this.historyFile.load();
13958
+ const history = await this.historyFile.loadEventsPage(page);
13865
13959
  return {
13866
13960
  thread_id: this.sessionId ?? this.initialSessionId,
13867
- events: history.events,
13961
+ ...history,
13868
13962
  goal: null
13869
13963
  };
13870
13964
  }
@@ -14435,10 +14529,10 @@ var PiManager = class extends CodingAgentManager {
14435
14529
  this.recordUserMessage(session, request.message);
14436
14530
  return true;
14437
14531
  }
14438
- async getHistory() {
14532
+ async getHistory(page = {}) {
14439
14533
  await this.historyFile.flush();
14440
- const history = await this.historyFile.load();
14441
- return { thread_id: this.activeSessionFile ?? this.initialSessionId, events: history.events, goal: null };
14534
+ const history = await this.historyFile.loadEventsPage(page);
14535
+ return { thread_id: this.activeSessionFile ?? this.initialSessionId, ...history, goal: null };
14442
14536
  }
14443
14537
  async listSlashCommands() {
14444
14538
  await this.initialized;
@@ -15155,8 +15249,8 @@ var RelayManager = class {
15155
15249
  async interrupt() {
15156
15250
  return this.inner.interrupt();
15157
15251
  }
15158
- async getHistory() {
15159
- return this.inner.getHistory();
15252
+ async getHistory(page = {}) {
15253
+ return this.inner.getHistory(page);
15160
15254
  }
15161
15255
  async listSlashCommands() {
15162
15256
  return this.inner.listSlashCommands?.() ?? [];
@@ -16419,17 +16513,27 @@ var ChatService = class {
16419
16513
  async getChatHistory(chatId, page = {}) {
16420
16514
  const chat = this.requireChat(chatId);
16421
16515
  const [history, senders] = await Promise.all([
16422
- chat.provider.getHistory(),
16516
+ chat.provider.getHistory(page),
16423
16517
  this.readSenders(chatId)
16424
16518
  ]);
16425
16519
  for (const [messageId, acceptedEvent] of chat.acceptedUserEvents) {
16426
- if (acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript)) {
16520
+ if (acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) || history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent))) {
16427
16521
  chat.acceptedUserEvents.delete(messageId);
16428
16522
  }
16429
16523
  }
16524
+ const isLatestPage = page.beforeEvent === void 0 && page.beforeTurn === void 0;
16430
16525
  const queuedMessageIds = new Set(chat.provider.getQueue().map((message) => message.id));
16431
- const acceptedEvents = [...chat.acceptedUserEvents.entries()].filter(([messageId]) => messageId === chat.activeMessageId || !chat.hasActiveTurn && chat.pendingMessageIds[0] === messageId && !queuedMessageIds.has(messageId)).map(([, acceptedEvent]) => acceptedEvent).filter((acceptedEvent) => !acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) && !history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent)));
16526
+ const acceptedEvents = (isLatestPage ? [...chat.acceptedUserEvents.entries()] : []).filter(([messageId]) => messageId === chat.activeMessageId || !chat.hasActiveTurn && chat.pendingMessageIds[0] === messageId && !queuedMessageIds.has(messageId)).map(([, acceptedEvent]) => acceptedEvent).filter((acceptedEvent) => !acceptedEventInCodexTranscript(acceptedEvent, history.codexAspTranscript) && !history.events.some((event) => isSameAcceptedUserEvent(event, acceptedEvent)));
16432
16527
  const events = [...history.events, ...acceptedEvents].sort((a, b) => getEventTimestampMs(a) - getEventTimestampMs(b));
16528
+ if (history.eventsStartIndex !== void 0) {
16529
+ return {
16530
+ ...history,
16531
+ events,
16532
+ totalEvents: (history.totalEvents ?? history.eventsStartIndex + history.events.length) + acceptedEvents.length,
16533
+ goal: history.goal ?? chat.provider.getGoal?.() ?? null,
16534
+ senders
16535
+ };
16536
+ }
16433
16537
  return paginateChatHistory({
16434
16538
  thread_id: history.thread_id,
16435
16539
  events,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.580",
3
+ "version": "0.1.581",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",