replicas-engine 0.1.291 → 0.1.293

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 +114 -81
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -286,7 +286,7 @@ var WORKSPACE_SIZES = ["small", "large"];
286
286
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
287
287
 
288
288
  // ../shared/src/e2b.ts
289
- var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-09-v5";
289
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-10-v2";
290
290
 
291
291
  // ../shared/src/runtime-env.ts
292
292
  function parsePosixEnvFile(content) {
@@ -2384,6 +2384,12 @@ function extractToolResultText(content, separator = "\n") {
2384
2384
  }
2385
2385
  return texts.join(separator);
2386
2386
  }
2387
+ function normalizeContentBlocks(content) {
2388
+ if (typeof content === "string") {
2389
+ return content ? [{ type: "text", text: content }] : [];
2390
+ }
2391
+ return content ?? [];
2392
+ }
2387
2393
  function parseStringField(value) {
2388
2394
  if (typeof value !== "string") return null;
2389
2395
  const trimmed = value.trim();
@@ -4747,9 +4753,9 @@ async function registerDesktopPreview() {
4747
4753
 
4748
4754
  // src/services/chat/chat-service.ts
4749
4755
  import { existsSync as existsSync7 } from "fs";
4750
- import { appendFile as appendFile4, copyFile, mkdir as mkdir11, readFile as readFile9, rename as rename2, rm } from "fs/promises";
4751
- import { homedir as homedir12 } from "os";
4752
- import { join as join14 } from "path";
4756
+ import { appendFile as appendFile4, copyFile, mkdir as mkdir11, readFile as readFile10, rename as rename2, rm } from "fs/promises";
4757
+ import { homedir as homedir13 } from "os";
4758
+ import { join as join15 } from "path";
4753
4759
  import { randomUUID as randomUUID5 } from "crypto";
4754
4760
 
4755
4761
  // src/managers/claude-manager.ts
@@ -4805,7 +4811,7 @@ function summarizeInput(input) {
4805
4811
  function convertClaudeEvent(event, linearSessionId) {
4806
4812
  if (event.type === "assistant") {
4807
4813
  const message = event;
4808
- const contentBlocks = message.message?.content || [];
4814
+ const contentBlocks = normalizeContentBlocks(message.message?.content);
4809
4815
  for (const block of contentBlocks) {
4810
4816
  if (block.type === "text" && block.text) {
4811
4817
  return {
@@ -4877,7 +4883,7 @@ function convertClaudeEvent(event, linearSessionId) {
4877
4883
  }
4878
4884
  if (event.type === "user") {
4879
4885
  const message = event;
4880
- const contentBlocks = message.message?.content || [];
4886
+ const contentBlocks = normalizeContentBlocks(message.message?.content);
4881
4887
  for (const block of contentBlocks) {
4882
4888
  if (block.type === "tool_result") {
4883
4889
  const resultText = extractToolResultText(block.content);
@@ -6594,7 +6600,7 @@ var AspClient = class {
6594
6600
  // src/managers/codex-asp/app-server-process.ts
6595
6601
  var DEFAULT_CODEX_BINARY = "codex";
6596
6602
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6597
- var ENGINE_PACKAGE_VERSION = "0.1.291";
6603
+ var ENGINE_PACKAGE_VERSION = "0.1.293";
6598
6604
  var INITIALIZE_METHOD = "initialize";
6599
6605
  var INITIALIZED_NOTIFICATION = "initialized";
6600
6606
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -8907,6 +8913,74 @@ var KeepAliveService = class _KeepAliveService {
8907
8913
  };
8908
8914
  var keepAliveService = new KeepAliveService();
8909
8915
 
8916
+ // src/services/upload-chat-transcripts.ts
8917
+ import { readdir as readdir3, readFile as readFile9 } from "fs/promises";
8918
+ import { basename, join as join14 } from "path";
8919
+ import { homedir as homedir12 } from "os";
8920
+ var ENGINE_DIR2 = join14(homedir12(), ".replicas", "engine");
8921
+ var HISTORY_DIRS = [
8922
+ join14(ENGINE_DIR2, "claude-histories"),
8923
+ join14(ENGINE_DIR2, "relay-histories"),
8924
+ join14(ENGINE_DIR2, "codex-histories")
8925
+ ];
8926
+ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
8927
+ let flushed = 0;
8928
+ let failed = 0;
8929
+ const tasks = [];
8930
+ for (const dir of HISTORY_DIRS) {
8931
+ let entries;
8932
+ try {
8933
+ entries = await readdir3(dir);
8934
+ } catch {
8935
+ continue;
8936
+ }
8937
+ for (const entry of entries) {
8938
+ if (!entry.endsWith(".jsonl")) continue;
8939
+ const chatId = basename(entry, ".jsonl");
8940
+ tasks.push(
8941
+ uploadChatTranscript(chatId, join14(dir, entry), chatsById.get(chatId)).then(() => {
8942
+ flushed++;
8943
+ }).catch((err) => {
8944
+ failed++;
8945
+ console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
8946
+ })
8947
+ );
8948
+ }
8949
+ }
8950
+ await Promise.all(tasks);
8951
+ return { flushed, failed };
8952
+ }
8953
+ async function uploadChatTranscript(chatId, filePath, chat) {
8954
+ const bytes = await readFile9(filePath);
8955
+ if (bytes.byteLength === 0) return;
8956
+ const form = new FormData();
8957
+ form.append("chat_id", chatId);
8958
+ if (chat) {
8959
+ const metadata = {
8960
+ provider: chat.provider,
8961
+ title: chat.title,
8962
+ createdAt: chat.createdAt,
8963
+ updatedAt: chat.updatedAt,
8964
+ parentChatId: chat.parentChatId
8965
+ };
8966
+ form.append("provider", metadata.provider);
8967
+ form.append("title", metadata.title);
8968
+ form.append("created_at", metadata.createdAt);
8969
+ form.append("updated_at", metadata.updatedAt);
8970
+ if (metadata.parentChatId) form.append("parent_chat_id", metadata.parentChatId);
8971
+ }
8972
+ form.append(
8973
+ "file",
8974
+ new Blob([new Uint8Array(bytes)], { type: "application/x-ndjson" }),
8975
+ "transcript.jsonl"
8976
+ );
8977
+ const response = await monolithRequest("/v1/engine/chat-transcripts", { body: form });
8978
+ if (!response.ok) {
8979
+ const errorText = await response.text();
8980
+ throw new Error(`upload failed: ${response.status} ${errorText}`);
8981
+ }
8982
+ }
8983
+
8910
8984
  // src/services/chat/errors.ts
8911
8985
  var ChatNotFoundError = class extends Error {
8912
8986
  constructor(chatId) {
@@ -8934,18 +9008,18 @@ var DuplicateDefaultChatError = class extends Error {
8934
9008
  };
8935
9009
 
8936
9010
  // src/services/chat/chat-service.ts
8937
- var ENGINE_DIR2 = join14(homedir12(), ".replicas", "engine");
8938
- var CHATS_FILE = join14(ENGINE_DIR2, "chats.json");
8939
- var CLAUDE_HISTORY_DIR = join14(ENGINE_DIR2, "claude-histories");
8940
- var RELAY_HISTORY_DIR = join14(ENGINE_DIR2, "relay-histories");
8941
- var CODEX_HISTORY_DIR = join14(ENGINE_DIR2, "codex-histories");
9011
+ var ENGINE_DIR3 = join15(homedir13(), ".replicas", "engine");
9012
+ var CHATS_FILE = join15(ENGINE_DIR3, "chats.json");
9013
+ var CLAUDE_HISTORY_DIR = join15(ENGINE_DIR3, "claude-histories");
9014
+ var RELAY_HISTORY_DIR = join15(ENGINE_DIR3, "relay-histories");
9015
+ var CODEX_HISTORY_DIR = join15(ENGINE_DIR3, "codex-histories");
8942
9016
  var HISTORY_DIR_BY_PROVIDER = {
8943
9017
  claude: CLAUDE_HISTORY_DIR,
8944
9018
  relay: RELAY_HISTORY_DIR,
8945
9019
  codex: CODEX_HISTORY_DIR
8946
9020
  };
8947
- var CHAT_SENDERS_DIR = join14(ENGINE_DIR2, "chat-senders");
8948
- var CODEX_AUTH_PATH2 = join14(homedir12(), ".codex", "auth.json");
9021
+ var CHAT_SENDERS_DIR = join15(ENGINE_DIR3, "chat-senders");
9022
+ var CODEX_AUTH_PATH2 = join15(homedir13(), ".codex", "auth.json");
8949
9023
  var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
8950
9024
  function isChatMessageSender(value) {
8951
9025
  if (!isRecord4(value)) return false;
@@ -9041,7 +9115,7 @@ var ChatService = class {
9041
9115
  persistInFlight = false;
9042
9116
  persistQueued = false;
9043
9117
  async initialize() {
9044
- await mkdir11(ENGINE_DIR2, { recursive: true });
9118
+ await mkdir11(ENGINE_DIR3, { recursive: true });
9045
9119
  await mkdir11(CLAUDE_HISTORY_DIR, { recursive: true });
9046
9120
  await mkdir11(RELAY_HISTORY_DIR, { recursive: true });
9047
9121
  await mkdir11(CODEX_HISTORY_DIR, { recursive: true });
@@ -9143,7 +9217,7 @@ var ChatService = class {
9143
9217
  };
9144
9218
  }
9145
9219
  senderFilePath(chatId) {
9146
- return join14(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
9220
+ return join15(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
9147
9221
  }
9148
9222
  async appendSender(chatId, sender) {
9149
9223
  try {
@@ -9154,7 +9228,7 @@ var ChatService = class {
9154
9228
  }
9155
9229
  async readSenders(chatId) {
9156
9230
  try {
9157
- const content = await readFile9(this.senderFilePath(chatId), "utf-8");
9231
+ const content = await readFile10(this.senderFilePath(chatId), "utf-8");
9158
9232
  const lines = content.split("\n").filter((line) => line.trim().length > 0);
9159
9233
  const senders = [];
9160
9234
  for (const line of lines) {
@@ -9291,7 +9365,7 @@ var ChatService = class {
9291
9365
  return descendants;
9292
9366
  }
9293
9367
  async deleteHistoryFile(persisted) {
9294
- await rm(join14(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
9368
+ await rm(join15(HISTORY_DIR_BY_PROVIDER[persisted.provider], `${persisted.id}.jsonl`), { force: true });
9295
9369
  await rm(this.senderFilePath(persisted.id), { force: true });
9296
9370
  }
9297
9371
  async getChatHistory(chatId) {
@@ -9324,6 +9398,11 @@ var ChatService = class {
9324
9398
  }
9325
9399
  return count;
9326
9400
  }
9401
+ async flushAllChatTranscripts() {
9402
+ return flushAllChatTranscripts(new Map(
9403
+ [...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toSummary(chat)])
9404
+ ));
9405
+ }
9327
9406
  createRuntimeChat(persisted) {
9328
9407
  const saveSession = async (sessionId) => {
9329
9408
  persisted.providerSessionId = sessionId;
@@ -9347,7 +9426,7 @@ var ChatService = class {
9347
9426
  if (persisted.provider === "claude") {
9348
9427
  provider = new ClaudeManager({
9349
9428
  workingDirectory: this.workingDirectory,
9350
- historyFilePath: join14(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
9429
+ historyFilePath: join15(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
9351
9430
  initialSessionId: persisted.providerSessionId,
9352
9431
  onSaveSessionId: saveSession,
9353
9432
  onTurnComplete: onProviderTurnComplete,
@@ -9356,7 +9435,7 @@ var ChatService = class {
9356
9435
  } else if (persisted.provider === "relay") {
9357
9436
  provider = new RelayManager({
9358
9437
  workingDirectory: this.workingDirectory,
9359
- historyFilePath: join14(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
9438
+ historyFilePath: join15(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
9360
9439
  initialSessionId: persisted.providerSessionId,
9361
9440
  onSaveSessionId: saveSession,
9362
9441
  onTurnComplete: onProviderTurnComplete,
@@ -9367,7 +9446,7 @@ var ChatService = class {
9367
9446
  } else {
9368
9447
  provider = new CodexAspManager({
9369
9448
  workingDirectory: this.workingDirectory,
9370
- historyFilePath: join14(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
9449
+ historyFilePath: join15(CODEX_HISTORY_DIR, `${persisted.id}.jsonl`),
9371
9450
  initialSessionId: persisted.providerSessionId,
9372
9451
  onSaveSessionId: saveSession,
9373
9452
  onTurnComplete: onProviderTurnComplete,
@@ -9501,6 +9580,13 @@ var ChatService = class {
9501
9580
  });
9502
9581
  monolithService.sendEvent({ type: "agent_response_complete", payload: {} }).catch(() => {
9503
9582
  });
9583
+ uploadChatTranscript(
9584
+ chatId,
9585
+ join15(HISTORY_DIR_BY_PROVIDER[chat.persisted.provider], `${chatId}.jsonl`),
9586
+ this.toSummary(chat)
9587
+ ).catch((err) => {
9588
+ console.error("[ChatService] Failed to upload chat transcript:", { chatId, err });
9589
+ });
9504
9590
  await this.publishAgentTurnCompleteWebhook(chat);
9505
9591
  }
9506
9592
  getRuntimeChat(chatId) {
@@ -9508,7 +9594,7 @@ var ChatService = class {
9508
9594
  }
9509
9595
  async loadChats() {
9510
9596
  try {
9511
- const content = await readFile9(CHATS_FILE, "utf-8");
9597
+ const content = await readFile10(CHATS_FILE, "utf-8");
9512
9598
  return parsePersistedChatsContent(content);
9513
9599
  } catch (error) {
9514
9600
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
@@ -9523,7 +9609,7 @@ var ChatService = class {
9523
9609
  console.error("[ChatService] Failed to quarantine corrupt chats file:", renameError);
9524
9610
  }
9525
9611
  try {
9526
- const backupContent = await readFile9(CHATS_BACKUP_FILE, "utf-8");
9612
+ const backupContent = await readFile10(CHATS_BACKUP_FILE, "utf-8");
9527
9613
  return parsePersistedChatsContent(backupContent);
9528
9614
  } catch (backupError) {
9529
9615
  if (backupError && typeof backupError === "object" && "code" in backupError && backupError.code === "ENOENT") {
@@ -9608,8 +9694,8 @@ var ChatService = class {
9608
9694
 
9609
9695
  // src/services/repo-file-service.ts
9610
9696
  import { execFile as execFile2 } from "child_process";
9611
- import { readFile as readFile10, realpath, stat as stat2 } from "fs/promises";
9612
- import { join as join15, resolve, extname } from "path";
9697
+ import { readFile as readFile11, realpath, stat as stat2 } from "fs/promises";
9698
+ import { join as join16, resolve, extname } from "path";
9613
9699
  var CACHE_TTL_MS = 3e4;
9614
9700
  var SEARCH_TIMEOUT_MS = 15e3;
9615
9701
  var MAX_CONTENT_BYTES = 256 * 1024;
@@ -9769,7 +9855,7 @@ var RepoFileService = class {
9769
9855
  const repo = repos.find((r) => r.name === repoName);
9770
9856
  if (!repo) return null;
9771
9857
  try {
9772
- const fullPath = await realpath(resolve(join15(repo.path, filePath)));
9858
+ const fullPath = await realpath(resolve(join16(repo.path, filePath)));
9773
9859
  const repoRoot = await realpath(repo.path);
9774
9860
  const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
9775
9861
  if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
@@ -9798,7 +9884,7 @@ var RepoFileService = class {
9798
9884
  tooLarge: true
9799
9885
  };
9800
9886
  }
9801
- const content = await readFile10(fullPath, "utf-8");
9887
+ const content = await readFile11(fullPath, "utf-8");
9802
9888
  return {
9803
9889
  repoName,
9804
9890
  path: filePath,
@@ -9879,59 +9965,6 @@ import { z as z2 } from "zod";
9879
9965
  import { readdir as readdir6, stat as stat4, readFile as readFile15 } from "fs/promises";
9880
9966
  import { join as join20, resolve as resolve2 } from "path";
9881
9967
 
9882
- // src/services/upload-chat-transcripts.ts
9883
- import { readdir as readdir3, readFile as readFile11 } from "fs/promises";
9884
- import { basename, join as join16 } from "path";
9885
- import { homedir as homedir13 } from "os";
9886
- var ENGINE_DIR3 = join16(homedir13(), ".replicas", "engine");
9887
- var HISTORY_DIRS = [
9888
- join16(ENGINE_DIR3, "claude-histories"),
9889
- join16(ENGINE_DIR3, "relay-histories")
9890
- ];
9891
- async function flushAllChatTranscripts() {
9892
- let flushed = 0;
9893
- let failed = 0;
9894
- const tasks = [];
9895
- for (const dir of HISTORY_DIRS) {
9896
- let entries;
9897
- try {
9898
- entries = await readdir3(dir);
9899
- } catch {
9900
- continue;
9901
- }
9902
- for (const entry of entries) {
9903
- if (!entry.endsWith(".jsonl")) continue;
9904
- const chatId = basename(entry, ".jsonl");
9905
- tasks.push(
9906
- uploadOne(chatId, join16(dir, entry)).then(() => {
9907
- flushed++;
9908
- }).catch((err) => {
9909
- failed++;
9910
- console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
9911
- })
9912
- );
9913
- }
9914
- }
9915
- await Promise.all(tasks);
9916
- return { flushed, failed };
9917
- }
9918
- async function uploadOne(chatId, filePath) {
9919
- const bytes = await readFile11(filePath);
9920
- if (bytes.byteLength === 0) return;
9921
- const form = new FormData();
9922
- form.append("chat_id", chatId);
9923
- form.append(
9924
- "file",
9925
- new Blob([new Uint8Array(bytes)], { type: "application/x-ndjson" }),
9926
- "transcript.jsonl"
9927
- );
9928
- const response = await monolithRequest("/v1/engine/chat-transcripts", { body: form });
9929
- if (!response.ok) {
9930
- const errorText = await response.text();
9931
- throw new Error(`upload failed: ${response.status} ${errorText}`);
9932
- }
9933
- }
9934
-
9935
9968
  // src/services/canvas-service.ts
9936
9969
  import { readdir as readdir4, readFile as readFile12, stat as stat3 } from "fs/promises";
9937
9970
  import { homedir as homedir14 } from "os";
@@ -10619,7 +10652,7 @@ function createV1Routes(deps) {
10619
10652
  });
10620
10653
  app2.post("/chat-transcripts/flush-all", async (c) => {
10621
10654
  try {
10622
- const result = await flushAllChatTranscripts();
10655
+ const result = await deps.chatService.flushAllChatTranscripts();
10623
10656
  return c.json(result);
10624
10657
  } catch (error) {
10625
10658
  return c.json(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.291",
3
+ "version": "0.1.293",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",