replicas-engine 0.1.287 → 0.1.288

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 +139 -68
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -116,9 +116,9 @@ var EXT_TO_LANGUAGE = {
116
116
  function detectLanguageByPath(filePath) {
117
117
  const dot = filePath.lastIndexOf(".");
118
118
  if (dot === -1) {
119
- const basename2 = filePath.split("/").pop() ?? "";
120
- if (basename2 === "Dockerfile") return "dockerfile";
121
- if (basename2 === "Makefile") return "makefile";
119
+ const basename3 = filePath.split("/").pop() ?? "";
120
+ if (basename3 === "Dockerfile") return "dockerfile";
121
+ if (basename3 === "Makefile") return "makefile";
122
122
  return null;
123
123
  }
124
124
  const ext = filePath.slice(dot).toLowerCase();
@@ -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-v1";
289
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-09-v2";
290
290
 
291
291
  // ../shared/src/runtime-env.ts
292
292
  function parsePosixEnvFile(content) {
@@ -2502,10 +2502,35 @@ function areSameUserMessageEvents(a, b) {
2502
2502
  if (aItemId || bItemId) return aItemId === bItemId;
2503
2503
  return Math.abs(getEventTimestampMs(a) - getEventTimestampMs(b)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
2504
2504
  }
2505
+ function parseAgentEventJsonl(content, options = {}) {
2506
+ const events = [];
2507
+ for (const line of content.split("\n")) {
2508
+ const trimmed = line.trim();
2509
+ if (!trimmed) continue;
2510
+ try {
2511
+ const parsed = JSON.parse(trimmed);
2512
+ if (isAgentBackendEvent(parsed)) {
2513
+ events.push(parsed);
2514
+ } else {
2515
+ options.onInvalidLine?.({ line: trimmed });
2516
+ }
2517
+ } catch (error) {
2518
+ options.onInvalidLine?.({ line: trimmed, error });
2519
+ }
2520
+ }
2521
+ return events;
2522
+ }
2505
2523
 
2506
2524
  // ../shared/src/display-message/parsers/codex-asp-parser.ts
2507
2525
  var DUPLICATE_WINDOW_MS = 5 * 60 * 1e3;
2508
2526
 
2527
+ // ../shared/src/display-message/parsers/index.ts
2528
+ function isAgentBackendEvent(value) {
2529
+ if (!value || typeof value !== "object") return false;
2530
+ const candidate = value;
2531
+ return typeof candidate.timestamp === "string" && typeof candidate.type === "string" && typeof candidate.payload === "object" && candidate.payload !== null;
2532
+ }
2533
+
2509
2534
  // ../shared/src/object-store/types.ts
2510
2535
  var MEDIA_KIND = {
2511
2536
  IMAGE: "image",
@@ -2739,14 +2764,16 @@ async function monolithRequest(path4, init = {}) {
2739
2764
  if (!ENGINE_ENV.WORKSPACE_ID) {
2740
2765
  throw new Error("WORKSPACE_ID is not set; cannot call monolith");
2741
2766
  }
2767
+ const isFormData = init.body instanceof FormData;
2768
+ const headers = {
2769
+ Authorization: `Bearer ${ENGINE_ENV.REPLICAS_ENGINE_SECRET}`,
2770
+ "X-Workspace-Id": ENGINE_ENV.WORKSPACE_ID
2771
+ };
2772
+ if (!isFormData) headers["Content-Type"] = "application/json";
2742
2773
  return fetch(`${ENGINE_ENV.MONOLITH_URL}${path4}`, {
2743
2774
  method: init.method ?? "POST",
2744
- headers: {
2745
- Authorization: `Bearer ${ENGINE_ENV.REPLICAS_ENGINE_SECRET}`,
2746
- "X-Workspace-Id": ENGINE_ENV.WORKSPACE_ID,
2747
- "Content-Type": "application/json"
2748
- },
2749
- body: init.body === void 0 ? void 0 : JSON.stringify(init.body),
2775
+ headers,
2776
+ body: init.body === void 0 ? void 0 : isFormData ? init.body : JSON.stringify(init.body),
2750
2777
  signal: init.signal
2751
2778
  });
2752
2779
  }
@@ -4729,30 +4756,10 @@ import { homedir as homedir11 } from "os";
4729
4756
 
4730
4757
  // src/utils/jsonl-reader.ts
4731
4758
  import { readFile as readFile7 } from "fs/promises";
4732
- function isJsonlEvent(value) {
4733
- if (!isRecord4(value)) {
4734
- return false;
4735
- }
4736
- return typeof value.timestamp === "string" && typeof value.type === "string" && isRecord4(value.payload);
4737
- }
4738
- function parseJsonlEvents(lines) {
4739
- const events = [];
4740
- for (const line of lines) {
4741
- try {
4742
- const parsed = JSON.parse(line);
4743
- if (isJsonlEvent(parsed)) {
4744
- events.push(parsed);
4745
- }
4746
- } catch {
4747
- }
4748
- }
4749
- return events;
4750
- }
4751
4759
  async function readJSONL(filePath) {
4752
4760
  try {
4753
4761
  const content = await readFile7(filePath, "utf-8");
4754
- const lines = content.split("\n").filter((line) => line.trim());
4755
- return parseJsonlEvents(lines);
4762
+ return parseAgentEventJsonl(content);
4756
4763
  } catch (error) {
4757
4764
  return [];
4758
4765
  }
@@ -6580,7 +6587,7 @@ var AspClient = class {
6580
6587
  // src/managers/codex-asp/app-server-process.ts
6581
6588
  var DEFAULT_CODEX_BINARY = "codex";
6582
6589
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6583
- var ENGINE_PACKAGE_VERSION = "0.1.287";
6590
+ var ENGINE_PACKAGE_VERSION = "0.1.288";
6584
6591
  var INITIALIZE_METHOD = "initialize";
6585
6592
  var INITIALIZED_NOTIFICATION = "initialized";
6586
6593
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -9592,11 +9599,11 @@ function scoreMatch(query2, filePath) {
9592
9599
  const lowerQuery = query2.toLowerCase();
9593
9600
  const lowerPath = filePath.toLowerCase();
9594
9601
  const segments = lowerPath.split("/");
9595
- const basename2 = segments[segments.length - 1] ?? "";
9596
- if (basename2 === lowerQuery) return 100;
9597
- if (basename2.startsWith(lowerQuery)) return 90;
9602
+ const basename3 = segments[segments.length - 1] ?? "";
9603
+ if (basename3 === lowerQuery) return 100;
9604
+ if (basename3.startsWith(lowerQuery)) return 90;
9598
9605
  if (segments.some((seg) => seg === lowerQuery)) return 80;
9599
- if (basename2.includes(lowerQuery)) return 70;
9606
+ if (basename3.includes(lowerQuery)) return 70;
9600
9607
  if (segments.some((seg) => seg.includes(lowerQuery))) return 60;
9601
9608
  if (lowerPath.includes(lowerQuery)) return 50;
9602
9609
  return 0;
@@ -9799,23 +9806,76 @@ var RepoFileService = class {
9799
9806
  // src/v1-routes.ts
9800
9807
  import { Hono } from "hono";
9801
9808
  import { z as z2 } from "zod";
9802
- import { readdir as readdir5, stat as stat4, readFile as readFile13 } from "fs/promises";
9803
- import { join as join19, resolve as resolve2 } from "path";
9809
+ import { readdir as readdir6, stat as stat4, readFile as readFile14 } from "fs/promises";
9810
+ import { join as join20, resolve as resolve2 } from "path";
9804
9811
 
9805
- // src/services/canvas-service.ts
9806
- import { readdir as readdir3, readFile as readFile10, stat as stat3 } from "fs/promises";
9807
- import { homedir as homedir13 } from "os";
9812
+ // src/services/upload-chat-transcripts.ts
9813
+ import { readdir as readdir3, readFile as readFile10 } from "fs/promises";
9808
9814
  import { basename, join as join16 } from "path";
9815
+ import { homedir as homedir13 } from "os";
9816
+ var ENGINE_DIR3 = join16(homedir13(), ".replicas", "engine");
9817
+ var HISTORY_DIRS = [
9818
+ join16(ENGINE_DIR3, "claude-histories"),
9819
+ join16(ENGINE_DIR3, "relay-histories")
9820
+ ];
9821
+ async function flushAllChatTranscripts() {
9822
+ let flushed = 0;
9823
+ let failed = 0;
9824
+ const tasks = [];
9825
+ for (const dir of HISTORY_DIRS) {
9826
+ let entries;
9827
+ try {
9828
+ entries = await readdir3(dir);
9829
+ } catch {
9830
+ continue;
9831
+ }
9832
+ for (const entry of entries) {
9833
+ if (!entry.endsWith(".jsonl")) continue;
9834
+ const chatId = basename(entry, ".jsonl");
9835
+ tasks.push(
9836
+ uploadOne(chatId, join16(dir, entry)).then(() => {
9837
+ flushed++;
9838
+ }).catch((err) => {
9839
+ failed++;
9840
+ console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
9841
+ })
9842
+ );
9843
+ }
9844
+ }
9845
+ await Promise.all(tasks);
9846
+ return { flushed, failed };
9847
+ }
9848
+ async function uploadOne(chatId, filePath) {
9849
+ const bytes = await readFile10(filePath);
9850
+ if (bytes.byteLength === 0) return;
9851
+ const form = new FormData();
9852
+ form.append("chat_id", chatId);
9853
+ form.append(
9854
+ "file",
9855
+ new Blob([new Uint8Array(bytes)], { type: "application/x-ndjson" }),
9856
+ "transcript.jsonl"
9857
+ );
9858
+ const response = await monolithRequest("/v1/engine/chat-transcripts", { body: form });
9859
+ if (!response.ok) {
9860
+ const errorText = await response.text();
9861
+ throw new Error(`upload failed: ${response.status} ${errorText}`);
9862
+ }
9863
+ }
9864
+
9865
+ // src/services/canvas-service.ts
9866
+ import { readdir as readdir4, readFile as readFile11, stat as stat3 } from "fs/promises";
9867
+ import { homedir as homedir14 } from "os";
9868
+ import { basename as basename2, join as join17 } from "path";
9809
9869
  var CANVAS_DIRECTORIES = [
9810
- join16(homedir13(), ".claude", "plans"),
9811
- join16(homedir13(), ".replicas", "canvas")
9870
+ join17(homedir14(), ".claude", "plans"),
9871
+ join17(homedir14(), ".replicas", "canvas")
9812
9872
  ];
9813
9873
  var MAX_CANVAS_FILE_BYTES = 5 * 1024 * 1024;
9814
9874
  function isTextKind(kind) {
9815
9875
  return kind === "markdown" || kind === "html";
9816
9876
  }
9817
9877
  function sanitizeFilename(filename) {
9818
- return basename(filename);
9878
+ return basename2(filename);
9819
9879
  }
9820
9880
  var CanvasService = class {
9821
9881
  async listItems() {
@@ -9823,7 +9883,7 @@ var CanvasService = class {
9823
9883
  for (const directory of CANVAS_DIRECTORIES) {
9824
9884
  let entries;
9825
9885
  try {
9826
- entries = await readdir3(directory, { withFileTypes: true });
9886
+ entries = await readdir4(directory, { withFileTypes: true });
9827
9887
  } catch {
9828
9888
  continue;
9829
9889
  }
@@ -9834,7 +9894,7 @@ var CanvasService = class {
9834
9894
  const { kind } = classifyCanvasFilename(entry.name);
9835
9895
  let sizeBytes = 0;
9836
9896
  try {
9837
- const s = await stat3(join16(directory, entry.name));
9897
+ const s = await stat3(join17(directory, entry.name));
9838
9898
  sizeBytes = s.size;
9839
9899
  } catch {
9840
9900
  continue;
@@ -9849,7 +9909,7 @@ var CanvasService = class {
9849
9909
  if (!safe || safe !== filename || safe.startsWith(".")) return null;
9850
9910
  const { kind, mimeType } = classifyCanvasFilename(safe);
9851
9911
  for (const directory of CANVAS_DIRECTORIES) {
9852
- const filePath = join16(directory, safe);
9912
+ const filePath = join17(directory, safe);
9853
9913
  let sizeBytes = 0;
9854
9914
  try {
9855
9915
  const s = await stat3(filePath);
@@ -9868,10 +9928,10 @@ var CanvasService = class {
9868
9928
  }
9869
9929
  try {
9870
9930
  if (isTextKind(kind)) {
9871
- const content = await readFile10(filePath, "utf-8");
9931
+ const content = await readFile11(filePath, "utf-8");
9872
9932
  return { filename: safe, kind, sizeBytes, mimeType, content };
9873
9933
  }
9874
- const buf = await readFile10(filePath);
9934
+ const buf = await readFile11(filePath);
9875
9935
  return { filename: safe, kind, sizeBytes, mimeType, base64: buf.toString("base64") };
9876
9936
  } catch {
9877
9937
  continue;
@@ -9884,16 +9944,16 @@ var canvasService = new CanvasService();
9884
9944
 
9885
9945
  // src/services/warm-hooks-service.ts
9886
9946
  import { spawn as spawn4 } from "child_process";
9887
- import { readFile as readFile12 } from "fs/promises";
9947
+ import { readFile as readFile13 } from "fs/promises";
9888
9948
  import { existsSync as existsSync8 } from "fs";
9889
- import { join as join18 } from "path";
9949
+ import { join as join19 } from "path";
9890
9950
 
9891
9951
  // src/services/warm-hook-logs-service.ts
9892
- import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile6, readdir as readdir4, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
9893
- import { homedir as homedir14 } from "os";
9894
- import { join as join17 } from "path";
9895
- var LOGS_DIR2 = join17(homedir14(), ".replicas", "warm-hook-logs");
9896
- var CURRENT_RUN_LOG = join17(LOGS_DIR2, "current-run.log");
9952
+ import { mkdir as mkdir12, readFile as readFile12, writeFile as writeFile6, readdir as readdir5, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
9953
+ import { homedir as homedir15 } from "os";
9954
+ import { join as join18 } from "path";
9955
+ var LOGS_DIR2 = join18(homedir15(), ".replicas", "warm-hook-logs");
9956
+ var CURRENT_RUN_LOG = join18(LOGS_DIR2, "current-run.log");
9897
9957
  var GLOBAL_FILENAME = "global.json";
9898
9958
  function withPreview2(stored) {
9899
9959
  const preview = buildHookOutputPreview(stored.output);
@@ -9910,7 +9970,7 @@ var WarmHookLogsService = class {
9910
9970
  hookName: "organization",
9911
9971
  ...entry
9912
9972
  };
9913
- await writeFile6(join17(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
9973
+ await writeFile6(join18(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
9914
9974
  `, "utf-8");
9915
9975
  }
9916
9976
  async saveEnvironmentHookLog(entry) {
@@ -9920,7 +9980,7 @@ var WarmHookLogsService = class {
9920
9980
  hookName: "environment",
9921
9981
  ...entry
9922
9982
  };
9923
- await writeFile6(join17(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
9983
+ await writeFile6(join18(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
9924
9984
  `, "utf-8");
9925
9985
  }
9926
9986
  async saveRepoHookLog(repoName, entry) {
@@ -9930,13 +9990,13 @@ var WarmHookLogsService = class {
9930
9990
  hookName: repoName,
9931
9991
  ...entry
9932
9992
  };
9933
- await writeFile6(join17(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
9993
+ await writeFile6(join18(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
9934
9994
  `, "utf-8");
9935
9995
  }
9936
9996
  async getAllLogs() {
9937
9997
  let files;
9938
9998
  try {
9939
- files = await readdir4(LOGS_DIR2);
9999
+ files = await readdir5(LOGS_DIR2);
9940
10000
  } catch (err) {
9941
10001
  if (err.code === "ENOENT") {
9942
10002
  return [];
@@ -9949,7 +10009,7 @@ var WarmHookLogsService = class {
9949
10009
  continue;
9950
10010
  }
9951
10011
  try {
9952
- const raw = await readFile11(join17(LOGS_DIR2, file), "utf-8");
10012
+ const raw = await readFile12(join18(LOGS_DIR2, file), "utf-8");
9953
10013
  const stored = JSON.parse(raw);
9954
10014
  logs.push(withPreview2(stored));
9955
10015
  } catch {
@@ -9978,7 +10038,7 @@ var WarmHookLogsService = class {
9978
10038
  }
9979
10039
  async getCurrentRunLog() {
9980
10040
  try {
9981
- return await readFile11(CURRENT_RUN_LOG, "utf-8");
10041
+ return await readFile12(CURRENT_RUN_LOG, "utf-8");
9982
10042
  } catch (err) {
9983
10043
  if (err.code === "ENOENT") return null;
9984
10044
  throw err;
@@ -9987,7 +10047,7 @@ var WarmHookLogsService = class {
9987
10047
  async getFullOutput(hookType, hookName) {
9988
10048
  const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
9989
10049
  try {
9990
- const raw = await readFile11(join17(LOGS_DIR2, filename), "utf-8");
10050
+ const raw = await readFile12(join18(LOGS_DIR2, filename), "utf-8");
9991
10051
  const stored = JSON.parse(raw);
9992
10052
  if (stored.hookType !== hookType || stored.hookName !== hookName) {
9993
10053
  return null;
@@ -10006,12 +10066,12 @@ var warmHookLogsService = new WarmHookLogsService();
10006
10066
  // src/services/warm-hooks-service.ts
10007
10067
  async function readRepoWarmHook(repoPath) {
10008
10068
  for (const filename of REPLICAS_CONFIG_FILENAMES) {
10009
- const configPath = join18(repoPath, filename);
10069
+ const configPath = join19(repoPath, filename);
10010
10070
  if (!existsSync8(configPath)) {
10011
10071
  continue;
10012
10072
  }
10013
10073
  try {
10014
- const raw = await readFile12(configPath, "utf-8");
10074
+ const raw = await readFile13(configPath, "utf-8");
10015
10075
  const config = parseReplicasConfigString(raw, filename);
10016
10076
  if (!config.warmHook) {
10017
10077
  return null;
@@ -10487,6 +10547,17 @@ function createV1Routes(deps) {
10487
10547
  return c.json(jsonError("Failed to clear goal", error instanceof Error ? error.message : "Unknown error"), 404);
10488
10548
  }
10489
10549
  });
10550
+ app2.post("/chat-transcripts/flush-all", async (c) => {
10551
+ try {
10552
+ const result = await flushAllChatTranscripts();
10553
+ return c.json(result);
10554
+ } catch (error) {
10555
+ return c.json(
10556
+ jsonError("Failed to flush transcripts", error instanceof Error ? error.message : "Unknown error"),
10557
+ 500
10558
+ );
10559
+ }
10560
+ });
10490
10561
  app2.get("/chats/:chatId/queue", (c) => {
10491
10562
  try {
10492
10563
  const result = deps.chatService.getChatQueue(c.req.param("chatId"));
@@ -10922,11 +10993,11 @@ function createV1Routes(deps) {
10922
10993
  });
10923
10994
  app2.get("/logs", async (c) => {
10924
10995
  try {
10925
- const files = await readdir5(LOG_DIR).catch(() => []);
10996
+ const files = await readdir6(LOG_DIR).catch(() => []);
10926
10997
  const logFiles = files.filter((f) => f.endsWith(".log"));
10927
10998
  const sessions = await Promise.all(
10928
10999
  logFiles.map(async (filename) => {
10929
- const filePath = join19(LOG_DIR, filename);
11000
+ const filePath = join20(LOG_DIR, filename);
10930
11001
  const fileStat = await stat4(filePath);
10931
11002
  const sessionId = filename.replace(/\.log$/, "");
10932
11003
  return {
@@ -10963,7 +11034,7 @@ function createV1Routes(deps) {
10963
11034
  const limit = Math.min(parseInt(c.req.query("limit") || "500", 10), 5e3);
10964
11035
  let content;
10965
11036
  try {
10966
- content = await readFile13(filePath, "utf-8");
11037
+ content = await readFile14(filePath, "utf-8");
10967
11038
  } catch {
10968
11039
  return c.json(jsonError("Log session not found"), 404);
10969
11040
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.287",
3
+ "version": "0.1.288",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",