replicas-engine 0.1.286 → 0.1.287

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.
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-08-v8";
289
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-09-v1";
290
290
 
291
291
  // ../shared/src/runtime-env.ts
292
292
  function parsePosixEnvFile(content) {
@@ -3738,28 +3738,91 @@ var GitService = class {
3738
3738
  var gitService = new GitService();
3739
3739
 
3740
3740
  // src/utils/logger.ts
3741
- import { appendFile, mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
3741
+ import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
3742
3742
  import { homedir as homedir4 } from "os";
3743
3743
  import { join as join6 } from "path";
3744
3744
  import { format } from "util";
3745
3745
  import { randomBytes } from "crypto";
3746
+
3747
+ // src/utils/stream-writer.ts
3748
+ import { createWriteStream } from "fs";
3749
+ var DEFAULT_HIGH_WATER = 8 * 1024 * 1024;
3750
+ var StreamWriter = class {
3751
+ stream = null;
3752
+ backpressured = false;
3753
+ droppedCount = 0;
3754
+ flushTimer = null;
3755
+ open(path4, highWaterMark = DEFAULT_HIGH_WATER) {
3756
+ this.stream = createWriteStream(path4, { flags: "a", highWaterMark });
3757
+ this.stream.on("error", () => {
3758
+ this.stream = null;
3759
+ });
3760
+ this.stream.on("drain", () => {
3761
+ this.backpressured = false;
3762
+ });
3763
+ }
3764
+ write(line) {
3765
+ if (!this.stream) return false;
3766
+ if (this.backpressured) {
3767
+ this.droppedCount++;
3768
+ this.scheduleDropWarning();
3769
+ return false;
3770
+ }
3771
+ const written = this.stream.write(line);
3772
+ if (!written) {
3773
+ this.backpressured = true;
3774
+ }
3775
+ return true;
3776
+ }
3777
+ flush() {
3778
+ return new Promise((resolve3) => {
3779
+ if (!this.stream) {
3780
+ resolve3();
3781
+ return;
3782
+ }
3783
+ if (this.flushTimer) {
3784
+ clearTimeout(this.flushTimer);
3785
+ this.flushTimer = null;
3786
+ }
3787
+ const s = this.stream;
3788
+ this.stream = null;
3789
+ s.end(() => resolve3());
3790
+ });
3791
+ }
3792
+ scheduleDropWarning() {
3793
+ if (this.flushTimer) return;
3794
+ this.flushTimer = setTimeout(() => {
3795
+ this.flushTimer = null;
3796
+ if (this.droppedCount > 0 && this.stream) {
3797
+ this.stream.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] [WARN] Dropped ${this.droppedCount} log lines due to IO backpressure
3798
+ `);
3799
+ this.droppedCount = 0;
3800
+ }
3801
+ }, 2e3);
3802
+ if (this.flushTimer && typeof this.flushTimer === "object" && "unref" in this.flushTimer) {
3803
+ this.flushTimer.unref();
3804
+ }
3805
+ }
3806
+ };
3807
+
3808
+ // src/utils/logger.ts
3746
3809
  var LOG_DIR = join6(homedir4(), ".replicas", "logs");
3747
3810
  var EngineLogger = class {
3748
3811
  _sessionId = null;
3749
- filePath = null;
3750
- writeChain = Promise.resolve();
3751
3812
  patched = false;
3813
+ writer = new StreamWriter();
3752
3814
  get sessionId() {
3753
3815
  return this._sessionId;
3754
3816
  }
3755
3817
  async initialize() {
3756
3818
  await mkdir3(LOG_DIR, { recursive: true });
3757
3819
  this._sessionId = this.createSessionId();
3758
- this.filePath = join6(LOG_DIR, `${this._sessionId}.log`);
3759
- await writeFile2(this.filePath, `=== Replicas Engine Session ${this._sessionId} ===
3820
+ const logPath = join6(LOG_DIR, `${this._sessionId}.log`);
3821
+ await writeFile2(logPath, `=== Replicas Engine Session ${this._sessionId} ===
3760
3822
  `, "utf-8");
3823
+ this.writer.open(logPath);
3761
3824
  this.patchConsole();
3762
- this.log("INFO", `Engine logging initialized at ${this.filePath}`);
3825
+ this.log("INFO", `Engine logging initialized at ${logPath}`);
3763
3826
  }
3764
3827
  patchConsole() {
3765
3828
  if (this.patched) return;
@@ -3781,21 +3844,11 @@ var EngineLogger = class {
3781
3844
  };
3782
3845
  }
3783
3846
  log(level, message) {
3784
- if (!this.filePath) return;
3785
- const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${message}
3786
- `;
3787
- this.writeChain = this.writeChain.then(() => appendFile(this.filePath, line, "utf-8")).catch((error) => {
3788
- try {
3789
- const err = error instanceof Error ? error.message : "Unknown error";
3790
- process.stderr.write(`[EngineLogger] Failed to append log line: ${err}
3847
+ this.writer.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] [${level}] ${message}
3791
3848
  `);
3792
- } catch {
3793
- }
3794
- });
3795
3849
  }
3796
- /** Wait for all queued log writes to complete. */
3797
3850
  flush() {
3798
- return this.writeChain;
3851
+ return this.writer.flush();
3799
3852
  }
3800
3853
  createSessionId() {
3801
3854
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-");
@@ -3806,7 +3859,7 @@ var EngineLogger = class {
3806
3859
  var engineLogger = new EngineLogger();
3807
3860
 
3808
3861
  // src/services/replicas-config-service.ts
3809
- import { readFile as readFile5, appendFile as appendFile2, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
3862
+ import { readFile as readFile5, appendFile, writeFile as writeFile4, mkdir as mkdir6 } from "fs/promises";
3810
3863
  import { existsSync as existsSync4 } from "fs";
3811
3864
  import { join as join9 } from "path";
3812
3865
  import { homedir as homedir7 } from "os";
@@ -4180,7 +4233,7 @@ var ReplicasConfigService = class {
4180
4233
  `;
4181
4234
  try {
4182
4235
  await mkdir6(join9(homedir7(), ".replicas"), { recursive: true });
4183
- await appendFile2(START_HOOKS_LOG, logLine, "utf-8");
4236
+ await appendFile(START_HOOKS_LOG, logLine, "utf-8");
4184
4237
  } catch (error) {
4185
4238
  console.error("Failed to write to start hooks log:", error);
4186
4239
  }
@@ -4508,7 +4561,7 @@ ${startHookConfig.commands.join("\n")}`;
4508
4561
  var replicasConfigService = new ReplicasConfigService();
4509
4562
 
4510
4563
  // src/services/event-service.ts
4511
- import { appendFile as appendFile3, mkdir as mkdir7 } from "fs/promises";
4564
+ import { mkdir as mkdir7 } from "fs/promises";
4512
4565
  import { homedir as homedir8 } from "os";
4513
4566
  import { join as join10 } from "path";
4514
4567
  import { randomUUID } from "crypto";
@@ -4516,9 +4569,10 @@ var ENGINE_DIR = join10(homedir8(), ".replicas", "engine");
4516
4569
  var EVENTS_FILE = join10(ENGINE_DIR, "events.jsonl");
4517
4570
  var EventService = class {
4518
4571
  subscribers = /* @__PURE__ */ new Map();
4519
- writeChain = Promise.resolve();
4572
+ writer = new StreamWriter();
4520
4573
  async initialize() {
4521
4574
  await mkdir7(ENGINE_DIR, { recursive: true });
4575
+ this.writer.open(EVENTS_FILE);
4522
4576
  }
4523
4577
  subscribe(subscriber) {
4524
4578
  const id = randomUUID();
@@ -4531,18 +4585,13 @@ var EventService = class {
4531
4585
  return this.subscribers.size;
4532
4586
  }
4533
4587
  async publish(event) {
4534
- this.writeChain = this.writeChain.catch((error) => {
4535
- const message = error instanceof Error ? error.message : "Unknown error";
4536
- process.stderr.write(`[EventService] Previous write failed, continuing: ${message}
4537
- `);
4538
- }).then(() => appendFile3(EVENTS_FILE, JSON.stringify(event) + "\n", "utf-8"));
4588
+ this.writer.write(JSON.stringify(event) + "\n");
4539
4589
  for (const subscriber of this.subscribers.values()) {
4540
4590
  try {
4541
4591
  subscriber(event);
4542
4592
  } catch {
4543
4593
  }
4544
4594
  }
4545
- await this.writeChain;
4546
4595
  }
4547
4596
  };
4548
4597
  var eventService = new EventService();
@@ -4664,7 +4713,7 @@ async function registerDesktopPreview() {
4664
4713
 
4665
4714
  // src/services/chat/chat-service.ts
4666
4715
  import { existsSync as existsSync7 } from "fs";
4667
- import { appendFile as appendFile5, copyFile, mkdir as mkdir11, readFile as readFile8, rename as rename2, rm } from "fs/promises";
4716
+ import { appendFile as appendFile3, copyFile, mkdir as mkdir11, readFile as readFile8, rename as rename2, rm } from "fs/promises";
4668
4717
  import { homedir as homedir12 } from "os";
4669
4718
  import { join as join14 } from "path";
4670
4719
  import { randomUUID as randomUUID5 } from "crypto";
@@ -4675,7 +4724,7 @@ import {
4675
4724
  } from "@anthropic-ai/claude-agent-sdk";
4676
4725
  import { randomUUID as randomUUID4 } from "crypto";
4677
4726
  import { join as join13 } from "path";
4678
- import { mkdir as mkdir10, appendFile as appendFile4 } from "fs/promises";
4727
+ import { mkdir as mkdir10, appendFile as appendFile2 } from "fs/promises";
4679
4728
  import { homedir as homedir11 } from "os";
4680
4729
 
4681
4730
  // src/utils/jsonl-reader.ts
@@ -5788,7 +5837,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5788
5837
  type,
5789
5838
  payload: { ...payload, parent_tool_use_id: null }
5790
5839
  };
5791
- await appendFile4(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
5840
+ await appendFile2(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
5792
5841
  this.onEvent(event);
5793
5842
  }
5794
5843
  buildCanUseTool() {
@@ -5924,7 +5973,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
5924
5973
  }
5925
5974
  };
5926
5975
  try {
5927
- await appendFile4(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
5976
+ await appendFile2(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
5928
5977
  } catch (writeError) {
5929
5978
  console.error("[ClaudeManager] Failed to record auth-retry-exhausted event:", writeError);
5930
5979
  }
@@ -6254,7 +6303,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
6254
6303
  try {
6255
6304
  const usage = await response.getContextUsage();
6256
6305
  const event = this.emitContextUsage(this.buildContextUsagePayload(usage));
6257
- await appendFile4(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
6306
+ await appendFile2(this.historyFile, JSON.stringify(event) + "\n", "utf-8");
6258
6307
  } catch (error) {
6259
6308
  console.warn("[ClaudeManager] Failed to record context usage:", error instanceof Error ? error.message : error);
6260
6309
  }
@@ -6330,7 +6379,7 @@ var ClaudeManager = class _ClaudeManager extends CodingAgentManager {
6330
6379
  type: `claude-${event.type}`,
6331
6380
  payload: event
6332
6381
  };
6333
- await appendFile4(this.historyFile, JSON.stringify(jsonEvent) + "\n", "utf-8");
6382
+ await appendFile2(this.historyFile, JSON.stringify(jsonEvent) + "\n", "utf-8");
6334
6383
  this.onEvent(jsonEvent);
6335
6384
  }
6336
6385
  };
@@ -6531,7 +6580,7 @@ var AspClient = class {
6531
6580
  // src/managers/codex-asp/app-server-process.ts
6532
6581
  var DEFAULT_CODEX_BINARY = "codex";
6533
6582
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6534
- var ENGINE_PACKAGE_VERSION = "0.1.286";
6583
+ var ENGINE_PACKAGE_VERSION = "0.1.287";
6535
6584
  var INITIALIZE_METHOD = "initialize";
6536
6585
  var INITIALIZED_NOTIFICATION = "initialized";
6537
6586
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -8911,7 +8960,8 @@ var ChatService = class {
8911
8960
  }
8912
8961
  workingDirectory;
8913
8962
  chats = /* @__PURE__ */ new Map();
8914
- writeChain = Promise.resolve();
8963
+ persistInFlight = false;
8964
+ persistQueued = false;
8915
8965
  async initialize() {
8916
8966
  await mkdir11(ENGINE_DIR2, { recursive: true });
8917
8967
  await mkdir11(CLAUDE_HISTORY_DIR, { recursive: true });
@@ -9018,7 +9068,7 @@ var ChatService = class {
9018
9068
  }
9019
9069
  async appendSender(chatId, sender) {
9020
9070
  try {
9021
- await appendFile5(this.senderFilePath(chatId), JSON.stringify(sender) + "\n", "utf-8");
9071
+ await appendFile3(this.senderFilePath(chatId), JSON.stringify(sender) + "\n", "utf-8");
9022
9072
  } catch (error) {
9023
9073
  console.error("[ChatService] Failed to append sender record:", error);
9024
9074
  }
@@ -9408,8 +9458,12 @@ var ChatService = class {
9408
9458
  }
9409
9459
  }
9410
9460
  async persistAllChats() {
9411
- this.writeChain = this.writeChain.catch(() => {
9412
- }).then(async () => {
9461
+ if (this.persistInFlight) {
9462
+ this.persistQueued = true;
9463
+ return;
9464
+ }
9465
+ this.persistInFlight = true;
9466
+ try {
9413
9467
  const payload = Array.from(this.chats.values()).map((chat) => chat.persisted);
9414
9468
  try {
9415
9469
  await copyFile(CHATS_FILE, CHATS_BACKUP_FILE);
@@ -9420,8 +9474,14 @@ var ChatService = class {
9420
9474
  }
9421
9475
  await atomicWriteFile(CHATS_FILE, `${JSON.stringify(payload, null, 2)}
9422
9476
  `);
9423
- });
9424
- await this.writeChain;
9477
+ } catch {
9478
+ } finally {
9479
+ this.persistInFlight = false;
9480
+ if (this.persistQueued) {
9481
+ this.persistQueued = false;
9482
+ void this.persistAllChats();
9483
+ }
9484
+ }
9425
9485
  }
9426
9486
  async publish(input) {
9427
9487
  const event = {
@@ -9829,7 +9889,7 @@ import { existsSync as existsSync8 } from "fs";
9829
9889
  import { join as join18 } from "path";
9830
9890
 
9831
9891
  // src/services/warm-hook-logs-service.ts
9832
- import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile6, readdir as readdir4, appendFile as appendFile6, unlink as unlink3 } from "fs/promises";
9892
+ import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile6, readdir as readdir4, appendFile as appendFile4, unlink as unlink3 } from "fs/promises";
9833
9893
  import { homedir as homedir14 } from "os";
9834
9894
  import { join as join17 } from "path";
9835
9895
  var LOGS_DIR2 = join17(homedir14(), ".replicas", "warm-hook-logs");
@@ -9914,7 +9974,7 @@ var WarmHookLogsService = class {
9914
9974
  }
9915
9975
  async appendCurrentRunLog(chunk) {
9916
9976
  if (!chunk) return;
9917
- await appendFile6(CURRENT_RUN_LOG, chunk, "utf-8");
9977
+ await appendFile4(CURRENT_RUN_LOG, chunk, "utf-8");
9918
9978
  }
9919
9979
  async getCurrentRunLog() {
9920
9980
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.286",
3
+ "version": "0.1.287",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -86,9 +86,9 @@ while true; do
86
86
 
87
87
  START_TIME=$(date +%s)
88
88
  if [ -n "$ENGINE_LD_PRELOAD" ]; then
89
- LD_PRELOAD="$ENGINE_LD_PRELOAD" "${ENGINE_CMD[@]}" >> "$BOOTSTRAP_LOG" 2>&1 &
89
+ LD_PRELOAD="$ENGINE_LD_PRELOAD" "${ENGINE_CMD[@]}" > >(cat >> "$BOOTSTRAP_LOG") 2>&1 &
90
90
  else
91
- "${ENGINE_CMD[@]}" >> "$BOOTSTRAP_LOG" 2>&1 &
91
+ "${ENGINE_CMD[@]}" > >(cat >> "$BOOTSTRAP_LOG") 2>&1 &
92
92
  fi
93
93
  ENGINE_PID=$!
94
94
  echo "$ENGINE_PID" > "$PIDFILE"