replicas-engine 0.1.484 → 0.1.485

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 +69 -59
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -583,7 +583,7 @@ var WORKSPACE_SIZES = ["small", "large"];
583
583
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
584
584
 
585
585
  // ../shared/src/e2b.ts
586
- var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-23-v4";
586
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-23-v5";
587
587
 
588
588
  // ../shared/src/runtime-env.ts
589
589
  function shellQuotePosix(value) {
@@ -2840,6 +2840,9 @@ var sendChatMessageRequestSchema = z2.object({
2840
2840
  z2.object({ type: z2.literal("automation"), executionId: z2.string() })
2841
2841
  ]).optional()
2842
2842
  }).passthrough();
2843
+ function isChatMessageSender(value) {
2844
+ return isRecord(value) && typeof value.senderUserId === "string" && typeof value.senderEmail === "string" && typeof value.recordedAt === "string";
2845
+ }
2843
2846
  function normalizeCodexAspTranscriptStatus(status, failed = false) {
2844
2847
  if (failed || status === "failed" || status === "declined") return "failed";
2845
2848
  if (status === "completed") return "completed";
@@ -7109,8 +7112,8 @@ async function registerDesktopPreview() {
7109
7112
  // src/services/chat/chat-service.ts
7110
7113
  import { existsSync as existsSync7 } from "fs";
7111
7114
  import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
7112
- import { homedir as homedir15 } from "os";
7113
- import { join as join22 } from "path";
7115
+ import { homedir as homedir14 } from "os";
7116
+ import { join as join23 } from "path";
7114
7117
  import { randomUUID as randomUUID5 } from "crypto";
7115
7118
 
7116
7119
  // src/managers/claude-manager.ts
@@ -9848,7 +9851,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
9848
9851
  var MIN_CODEX_CLI_VERSION = "0.144.6";
9849
9852
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
9850
9853
  var codexCliVersionEnsured = null;
9851
- var ENGINE_PACKAGE_VERSION = "0.1.484";
9854
+ var ENGINE_PACKAGE_VERSION = "0.1.485";
9852
9855
  var INITIALIZE_METHOD = "initialize";
9853
9856
  var INITIALIZED_NOTIFICATION = "initialized";
9854
9857
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -14124,13 +14127,31 @@ async function reconcileCanvasItems(filenames) {
14124
14127
 
14125
14128
  // src/services/upload-chat-transcripts.ts
14126
14129
  import { readdir as readdir7, readFile as readFile13 } from "fs/promises";
14127
- import { basename as basename2, join as join21 } from "path";
14128
- import { homedir as homedir14 } from "os";
14129
- var ENGINE_DIR3 = join21(homedir14(), ".replicas", "engine");
14130
+ import { basename as basename2, join as join22 } from "path";
14131
+
14132
+ // src/services/chat/chat-senders.ts
14133
+ import { join as join21 } from "path";
14134
+ var CHAT_SENDERS_DIR = join21(ENGINE_DIR2, "chat-senders");
14135
+ function chatMessageSendersFilePath(chatId) {
14136
+ return join21(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
14137
+ }
14138
+ function parseChatMessageSendersJsonl(content) {
14139
+ return content.split("\n").flatMap((line) => {
14140
+ if (!line.trim()) return [];
14141
+ try {
14142
+ const parsed = JSON.parse(line);
14143
+ return isChatMessageSender(parsed) ? [parsed] : [];
14144
+ } catch {
14145
+ return [];
14146
+ }
14147
+ });
14148
+ }
14149
+
14150
+ // src/services/upload-chat-transcripts.ts
14130
14151
  var HISTORY_DIRS = [
14131
- join21(ENGINE_DIR3, "claude-histories"),
14132
- join21(ENGINE_DIR3, "relay-histories"),
14133
- join21(ENGINE_DIR3, "codex-histories")
14152
+ join22(ENGINE_DIR2, "claude-histories"),
14153
+ join22(ENGINE_DIR2, "relay-histories"),
14154
+ join22(ENGINE_DIR2, "codex-histories")
14134
14155
  ];
14135
14156
  async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
14136
14157
  let flushed = 0;
@@ -14147,7 +14168,7 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
14147
14168
  if (!entry.endsWith(".jsonl")) continue;
14148
14169
  const chatId = basename2(entry, ".jsonl");
14149
14170
  tasks.push(
14150
- uploadChatTranscript(chatId, join21(dir, entry), chatsById.get(chatId)).then(() => {
14171
+ uploadChatTranscript(chatId, join22(dir, entry), chatsById.get(chatId)).then(() => {
14151
14172
  flushed++;
14152
14173
  }).catch((err) => {
14153
14174
  failed++;
@@ -14162,6 +14183,12 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
14162
14183
  async function uploadChatTranscript(chatId, filePath, chat) {
14163
14184
  const bytes = await readFile13(filePath);
14164
14185
  if (bytes.byteLength === 0) return;
14186
+ let senders;
14187
+ try {
14188
+ senders = parseChatMessageSendersJsonl(await readFile13(chatMessageSendersFilePath(chatId), "utf-8"));
14189
+ } catch (error) {
14190
+ if (!(error && typeof error === "object" && "code" in error && error.code === "ENOENT")) throw error;
14191
+ }
14165
14192
  const form = new FormData();
14166
14193
  form.append("chat_id", chatId);
14167
14194
  if (chat) {
@@ -14180,6 +14207,9 @@ async function uploadChatTranscript(chatId, filePath, chat) {
14180
14207
  if (metadata.parentChatId) form.append("parent_chat_id", metadata.parentChatId);
14181
14208
  form.append("deleted_at", metadata.deletedAt ?? "");
14182
14209
  }
14210
+ if (senders !== void 0) {
14211
+ form.append("senders", JSON.stringify(senders));
14212
+ }
14183
14213
  form.append(
14184
14214
  "file",
14185
14215
  new Blob([new Uint8Array(bytes)], { type: "application/x-ndjson" }),
@@ -14226,14 +14256,9 @@ async function flushRepoState() {
14226
14256
  }
14227
14257
 
14228
14258
  // src/services/chat/chat-service.ts
14229
- var CHAT_SENDERS_DIR = join22(ENGINE_DIR2, "chat-senders");
14230
- var CODEX_AUTH_PATH2 = join22(homedir15(), ".codex", "auth.json");
14231
- var OPENCODE_AUTH_PATH3 = join22(homedir15(), ".local", "share", "opencode", "auth.json");
14259
+ var CODEX_AUTH_PATH2 = join23(homedir14(), ".codex", "auth.json");
14260
+ var OPENCODE_AUTH_PATH3 = join23(homedir14(), ".local", "share", "opencode", "auth.json");
14232
14261
  var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
14233
- function isChatMessageSender(value) {
14234
- if (!isRecord4(value)) return false;
14235
- return typeof value.senderUserId === "string" && typeof value.senderEmail === "string" && typeof value.recordedAt === "string";
14236
- }
14237
14262
  function isCodexAvailable() {
14238
14263
  return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
14239
14264
  }
@@ -14506,31 +14531,16 @@ var ChatService = class {
14506
14531
  position: result.position
14507
14532
  };
14508
14533
  }
14509
- senderFilePath(chatId) {
14510
- return join22(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
14511
- }
14512
14534
  async appendSender(chatId, sender) {
14513
14535
  try {
14514
- await appendFile3(this.senderFilePath(chatId), JSON.stringify(sender) + "\n", "utf-8");
14536
+ await appendFile3(chatMessageSendersFilePath(chatId), JSON.stringify(sender) + "\n", "utf-8");
14515
14537
  } catch (error) {
14516
14538
  console.error("[ChatService] Failed to append sender record:", error);
14517
14539
  }
14518
14540
  }
14519
14541
  async readSenders(chatId) {
14520
14542
  try {
14521
- const content = await readFile14(this.senderFilePath(chatId), "utf-8");
14522
- const lines = content.split("\n").filter((line) => line.trim().length > 0);
14523
- const senders = [];
14524
- for (const line of lines) {
14525
- try {
14526
- const parsed = JSON.parse(line);
14527
- if (isChatMessageSender(parsed)) {
14528
- senders.push(parsed);
14529
- }
14530
- } catch {
14531
- }
14532
- }
14533
- return senders;
14543
+ return parseChatMessageSendersJsonl(await readFile14(chatMessageSendersFilePath(chatId), "utf-8"));
14534
14544
  } catch (error) {
14535
14545
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
14536
14546
  return [];
@@ -14709,8 +14719,8 @@ var ChatService = class {
14709
14719
  return descendants;
14710
14720
  }
14711
14721
  async deleteHistoryFile(persisted) {
14712
- await rm2(join22(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
14713
- await rm2(this.senderFilePath(persisted.id), { force: true });
14722
+ await rm2(join23(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
14723
+ await rm2(chatMessageSendersFilePath(persisted.id), { force: true });
14714
14724
  }
14715
14725
  async getChatHistory(chatId, page = {}) {
14716
14726
  const chat = this.requireChat(chatId);
@@ -14784,7 +14794,7 @@ var ChatService = class {
14784
14794
  if (persisted.provider === "claude") {
14785
14795
  provider = new ClaudeManager({
14786
14796
  workingDirectory: this.workingDirectory,
14787
- historyFilePath: join22(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
14797
+ historyFilePath: join23(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
14788
14798
  initialSessionId: persisted.providerSessionId,
14789
14799
  onSaveSessionId: saveSession,
14790
14800
  onTurnComplete: onProviderTurnComplete,
@@ -14793,7 +14803,7 @@ var ChatService = class {
14793
14803
  } else if (persisted.provider === "relay") {
14794
14804
  provider = new RelayManager({
14795
14805
  workingDirectory: this.workingDirectory,
14796
- historyFilePath: join22(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
14806
+ historyFilePath: join23(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
14797
14807
  initialSessionId: persisted.providerSessionId,
14798
14808
  onSaveSessionId: saveSession,
14799
14809
  onTurnComplete: onProviderTurnComplete,
@@ -14807,7 +14817,7 @@ var ChatService = class {
14807
14817
  } else if (persisted.provider === "cursor") {
14808
14818
  provider = new CursorManager({
14809
14819
  workingDirectory: this.workingDirectory,
14810
- historyFilePath: join22(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
14820
+ historyFilePath: join23(CURSOR_HISTORY_DIR, `${persisted.id}.jsonl`),
14811
14821
  initialSessionId: persisted.providerSessionId,
14812
14822
  onSaveSessionId: saveSession,
14813
14823
  onTurnComplete: onProviderTurnComplete,
@@ -14816,7 +14826,7 @@ var ChatService = class {
14816
14826
  } else if (persisted.provider === "opencode") {
14817
14827
  provider = new OpencodeManager({
14818
14828
  workingDirectory: this.workingDirectory,
14819
- historyFilePath: join22(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
14829
+ historyFilePath: join23(OPENCODE_HISTORY_DIR, `${persisted.id}.jsonl`),
14820
14830
  initialSessionId: persisted.providerSessionId,
14821
14831
  onSaveSessionId: saveSession,
14822
14832
  onTurnComplete: onProviderTurnComplete,
@@ -14825,7 +14835,7 @@ var ChatService = class {
14825
14835
  } else if (persisted.provider === "pi") {
14826
14836
  provider = new PiManager({
14827
14837
  workingDirectory: this.workingDirectory,
14828
- historyFilePath: join22(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
14838
+ historyFilePath: join23(PI_HISTORY_DIR, `${persisted.id}.jsonl`),
14829
14839
  initialSessionId: persisted.providerSessionId,
14830
14840
  onSaveSessionId: saveSession,
14831
14841
  onTurnComplete: onProviderTurnComplete,
@@ -14834,7 +14844,7 @@ var ChatService = class {
14834
14844
  } else {
14835
14845
  provider = new CodexAspManager({
14836
14846
  workingDirectory: this.workingDirectory,
14837
- historyFilePath: join22(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
14847
+ historyFilePath: join23(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
14838
14848
  initialSessionId: persisted.providerSessionId,
14839
14849
  onSaveSessionId: saveSession,
14840
14850
  onTurnComplete: onProviderTurnComplete,
@@ -14983,7 +14993,7 @@ var ChatService = class {
14983
14993
  });
14984
14994
  uploadChatTranscript(
14985
14995
  chatId,
14986
- join22(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
14996
+ join23(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
14987
14997
  this.toSummary(chat)
14988
14998
  ).catch((err) => {
14989
14999
  console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
@@ -15119,7 +15129,7 @@ var ChatService = class {
15119
15129
  // src/services/repo-file-service.ts
15120
15130
  import { execFile as execFile2 } from "child_process";
15121
15131
  import { readFile as readFile15, realpath, stat as stat4 } from "fs/promises";
15122
- import { join as join23, resolve as resolve2, extname as extname2 } from "path";
15132
+ import { join as join24, resolve as resolve2, extname as extname2 } from "path";
15123
15133
  var CACHE_TTL_MS = 3e4;
15124
15134
  var SEARCH_TIMEOUT_MS = 15e3;
15125
15135
  var MAX_CONTENT_BYTES = 256 * 1024;
@@ -15279,7 +15289,7 @@ var RepoFileService = class {
15279
15289
  const repo = repos.find((r) => r.name === repoName);
15280
15290
  if (!repo) return null;
15281
15291
  try {
15282
- const fullPath = await realpath(resolve2(join23(repo.path, filePath)));
15292
+ const fullPath = await realpath(resolve2(join24(repo.path, filePath)));
15283
15293
  const repoRoot = await realpath(repo.path);
15284
15294
  const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
15285
15295
  if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
@@ -15387,20 +15397,20 @@ var RepoFileService = class {
15387
15397
  import { Hono } from "hono";
15388
15398
  import { z as z7 } from "zod";
15389
15399
  import { readdir as readdir9, stat as stat5, readFile as readFile18 } from "fs/promises";
15390
- import { join as join26, resolve as resolve3 } from "path";
15400
+ import { join as join27, resolve as resolve3 } from "path";
15391
15401
 
15392
15402
  // src/services/warm-hooks-service.ts
15393
15403
  import { spawn as spawn4 } from "child_process";
15394
15404
  import { readFile as readFile17 } from "fs/promises";
15395
15405
  import { existsSync as existsSync8 } from "fs";
15396
- import { join as join25 } from "path";
15406
+ import { join as join26 } from "path";
15397
15407
 
15398
15408
  // src/services/warm-hook-logs-service.ts
15399
15409
  import { mkdir as mkdir15, readFile as readFile16, writeFile as writeFile6, readdir as readdir8, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
15400
- import { homedir as homedir16 } from "os";
15401
- import { join as join24 } from "path";
15402
- var LOGS_DIR2 = join24(homedir16(), ".replicas", "warm-hook-logs");
15403
- var CURRENT_RUN_LOG = join24(LOGS_DIR2, "current-run.log");
15410
+ import { homedir as homedir15 } from "os";
15411
+ import { join as join25 } from "path";
15412
+ var LOGS_DIR2 = join25(homedir15(), ".replicas", "warm-hook-logs");
15413
+ var CURRENT_RUN_LOG = join25(LOGS_DIR2, "current-run.log");
15404
15414
  var GLOBAL_FILENAME = "global.json";
15405
15415
  function withPreview2(stored) {
15406
15416
  const preview = buildHookOutputPreview(stored.output);
@@ -15417,7 +15427,7 @@ var WarmHookLogsService = class {
15417
15427
  hookName: "organization",
15418
15428
  ...entry
15419
15429
  };
15420
- await writeFile6(join24(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
15430
+ await writeFile6(join25(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
15421
15431
  `, "utf-8");
15422
15432
  }
15423
15433
  async saveEnvironmentHookLog(entry) {
@@ -15427,7 +15437,7 @@ var WarmHookLogsService = class {
15427
15437
  hookName: "environment",
15428
15438
  ...entry
15429
15439
  };
15430
- await writeFile6(join24(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
15440
+ await writeFile6(join25(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
15431
15441
  `, "utf-8");
15432
15442
  }
15433
15443
  async saveRepoHookLog(repoName, entry) {
@@ -15437,7 +15447,7 @@ var WarmHookLogsService = class {
15437
15447
  hookName: repoName,
15438
15448
  ...entry
15439
15449
  };
15440
- await writeFile6(join24(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
15450
+ await writeFile6(join25(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
15441
15451
  `, "utf-8");
15442
15452
  }
15443
15453
  async getAllLogs() {
@@ -15456,7 +15466,7 @@ var WarmHookLogsService = class {
15456
15466
  continue;
15457
15467
  }
15458
15468
  try {
15459
- const raw = await readFile16(join24(LOGS_DIR2, file), "utf-8");
15469
+ const raw = await readFile16(join25(LOGS_DIR2, file), "utf-8");
15460
15470
  const stored = JSON.parse(raw);
15461
15471
  logs.push(withPreview2(stored));
15462
15472
  } catch {
@@ -15494,7 +15504,7 @@ var WarmHookLogsService = class {
15494
15504
  async getFullOutput(hookType, hookName) {
15495
15505
  const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
15496
15506
  try {
15497
- const raw = await readFile16(join24(LOGS_DIR2, filename), "utf-8");
15507
+ const raw = await readFile16(join25(LOGS_DIR2, filename), "utf-8");
15498
15508
  const stored = JSON.parse(raw);
15499
15509
  if (stored.hookType !== hookType || stored.hookName !== hookName) {
15500
15510
  return null;
@@ -15513,7 +15523,7 @@ var warmHookLogsService = new WarmHookLogsService();
15513
15523
  // src/services/warm-hooks-service.ts
15514
15524
  async function readRepoWarmHook(repoPath) {
15515
15525
  for (const filename of REPLICAS_CONFIG_FILENAMES) {
15516
- const configPath = join25(repoPath, filename);
15526
+ const configPath = join26(repoPath, filename);
15517
15527
  if (!existsSync8(configPath)) {
15518
15528
  continue;
15519
15529
  }
@@ -16746,7 +16756,7 @@ data: ${JSON.stringify("Terminal session not found")}
16746
16756
  const logFiles = files.filter((f) => f.endsWith(".log"));
16747
16757
  const sessions = await Promise.all(
16748
16758
  logFiles.map(async (filename) => {
16749
- const filePath = join26(LOG_DIR, filename);
16759
+ const filePath = join27(LOG_DIR, filename);
16750
16760
  const fileStat = await stat5(filePath);
16751
16761
  const sessionId = filename.replace(/\.log$/, "");
16752
16762
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.484",
3
+ "version": "0.1.485",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",