replicas-engine 0.1.277 → 0.1.279

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 +76 -713
  2. package/package.json +1 -2
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-07-v2";
289
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-06-07-v4";
290
290
 
291
291
  // ../shared/src/runtime-env.ts
292
292
  function parsePosixEnvFile(content) {
@@ -4664,10 +4664,10 @@ async function registerDesktopPreview() {
4664
4664
  }
4665
4665
 
4666
4666
  // src/services/chat/chat-service.ts
4667
- import { existsSync as existsSync8 } from "fs";
4668
- import { appendFile as appendFile5, copyFile, mkdir as mkdir12, readFile as readFile9, rename as rename2, rm } from "fs/promises";
4669
- import { homedir as homedir13 } from "os";
4670
- import { join as join15 } from "path";
4667
+ import { existsSync as existsSync7 } from "fs";
4668
+ import { appendFile as appendFile5, copyFile, mkdir as mkdir11, readFile as readFile8, rename as rename2, rm } from "fs/promises";
4669
+ import { homedir as homedir12 } from "os";
4670
+ import { join as join14 } from "path";
4671
4671
  import { randomUUID as randomUUID5 } from "crypto";
4672
4672
 
4673
4673
  // src/managers/claude-manager.ts
@@ -4847,212 +4847,6 @@ function mapTodoStatus(status) {
4847
4847
  }
4848
4848
  return "pending";
4849
4849
  }
4850
- function convertCodexEvent(event, linearSessionId) {
4851
- if (event.type === "turn.started") {
4852
- return {
4853
- linearSessionId,
4854
- content: {
4855
- type: "thought",
4856
- body: "Processing..."
4857
- }
4858
- };
4859
- }
4860
- if (event.type === "item.started") {
4861
- const item = event.item;
4862
- if (!item) return null;
4863
- if (item.type === "agent_message") {
4864
- const text = "text" in item ? String(item.text || "") : "";
4865
- if (text) {
4866
- return {
4867
- linearSessionId,
4868
- content: {
4869
- type: "thought",
4870
- body: text
4871
- }
4872
- };
4873
- }
4874
- }
4875
- if (item.type === "reasoning") {
4876
- const text = "text" in item ? String(item.text || "") : "";
4877
- if (text) {
4878
- return {
4879
- linearSessionId,
4880
- content: {
4881
- type: "thought",
4882
- body: text
4883
- }
4884
- };
4885
- }
4886
- }
4887
- if (item.type === "command_execution") {
4888
- const command = "command" in item ? String(item.command || "") : "";
4889
- return {
4890
- linearSessionId,
4891
- content: {
4892
- type: "action",
4893
- action: "Running command",
4894
- parameter: command
4895
- }
4896
- };
4897
- }
4898
- if (item.type === "file_change") {
4899
- const changes = "changes" in item && Array.isArray(item.changes) ? item.changes : [];
4900
- const paths = changes.map((c) => c.path || "").filter(Boolean);
4901
- return {
4902
- linearSessionId,
4903
- content: {
4904
- type: "action",
4905
- action: "File change",
4906
- parameter: paths.join(", ") || ""
4907
- }
4908
- };
4909
- }
4910
- if (item.type === "mcp_tool_call") {
4911
- const tool2 = "tool" in item ? String(item.tool || "") : "";
4912
- return {
4913
- linearSessionId,
4914
- content: {
4915
- type: "action",
4916
- action: tool2 || "MCP tool call",
4917
- parameter: ""
4918
- }
4919
- };
4920
- }
4921
- if (item.type === "web_search") {
4922
- const query2 = "query" in item ? String(item.query || "") : "";
4923
- return {
4924
- linearSessionId,
4925
- content: {
4926
- type: "action",
4927
- action: "Web search",
4928
- parameter: query2
4929
- }
4930
- };
4931
- }
4932
- if (item.type === "todo_list") {
4933
- const items = "items" in item && Array.isArray(item.items) ? item.items : [];
4934
- const completed = items.filter((t) => t.completed).length;
4935
- const total = items.length;
4936
- const currentTask = items.find((t) => !t.completed);
4937
- const summary = `${completed}/${total}`;
4938
- const parameter = currentTask?.text ? `${summary}: ${currentTask.text}` : summary;
4939
- return {
4940
- linearSessionId,
4941
- content: {
4942
- type: "action",
4943
- action: "Updating plan",
4944
- parameter
4945
- }
4946
- };
4947
- }
4948
- }
4949
- if (event.type === "item.completed") {
4950
- const item = event.item;
4951
- if (!item) return null;
4952
- if (item.type === "command_execution") {
4953
- const command = "command" in item ? String(item.command || "") : "";
4954
- const output = "aggregated_output" in item ? String(item.aggregated_output || "") : "";
4955
- const exitCode = "exit_code" in item ? item.exit_code : void 0;
4956
- const result = exitCode !== void 0 ? `Exit code: ${exitCode}` : output || "Done";
4957
- return {
4958
- linearSessionId,
4959
- content: {
4960
- type: "action",
4961
- action: "Running command",
4962
- parameter: command,
4963
- result
4964
- }
4965
- };
4966
- }
4967
- if (item.type === "file_change") {
4968
- const changes = "changes" in item && Array.isArray(item.changes) ? item.changes : [];
4969
- const paths = changes.map((c) => c.path || "").filter(Boolean);
4970
- const status = "status" in item ? String(item.status || "") : "";
4971
- return {
4972
- linearSessionId,
4973
- content: {
4974
- type: "action",
4975
- action: "File change",
4976
- parameter: paths.join(", ") || "",
4977
- result: status === "completed" ? "Done" : status || "Done"
4978
- }
4979
- };
4980
- }
4981
- if (item.type === "mcp_tool_call") {
4982
- const tool2 = "tool" in item ? String(item.tool || "") : "";
4983
- const status = "status" in item ? String(item.status || "") : "";
4984
- return {
4985
- linearSessionId,
4986
- content: {
4987
- type: "action",
4988
- action: tool2 || "MCP tool call",
4989
- parameter: "",
4990
- result: status === "completed" ? "Done" : status || "Done"
4991
- }
4992
- };
4993
- }
4994
- if (item.type === "web_search") {
4995
- const query2 = "query" in item ? String(item.query || "") : "";
4996
- return {
4997
- linearSessionId,
4998
- content: {
4999
- type: "action",
5000
- action: "Web search",
5001
- parameter: query2,
5002
- result: "Done"
5003
- }
5004
- };
5005
- }
5006
- if (item.type === "todo_list") {
5007
- const items = "items" in item && Array.isArray(item.items) ? item.items : [];
5008
- const completed = items.filter((t) => t.completed).length;
5009
- const total = items.length;
5010
- const currentTask = items.find((t) => !t.completed);
5011
- const summary = `${completed}/${total}`;
5012
- const parameter = currentTask?.text ? `${summary}: ${currentTask.text}` : summary;
5013
- return {
5014
- linearSessionId,
5015
- content: {
5016
- type: "action",
5017
- action: "Updating plan",
5018
- parameter,
5019
- result: "Done"
5020
- }
5021
- };
5022
- }
5023
- if (item.type === "agent_message") {
5024
- const text = "text" in item ? String(item.text || "") : "";
5025
- if (text) {
5026
- return {
5027
- linearSessionId,
5028
- content: {
5029
- type: "thought",
5030
- body: text
5031
- }
5032
- };
5033
- }
5034
- }
5035
- }
5036
- return null;
5037
- }
5038
- function extractPlanFromCodexEvent(event) {
5039
- if (event.type !== "item.started" && event.type !== "item.completed") {
5040
- return null;
5041
- }
5042
- const item = event.item;
5043
- if (!item || item.type !== "todo_list") {
5044
- return null;
5045
- }
5046
- const items = "items" in item && Array.isArray(item.items) ? item.items : [];
5047
- if (items.length === 0) {
5048
- return null;
5049
- }
5050
- const hasIncomplete = items.some((entry) => !entry.completed);
5051
- return items.filter((entry) => Boolean(entry.text && entry.text.trim().length > 0)).map((entry) => ({
5052
- content: entry.text.trim(),
5053
- status: entry.completed ? "completed" : hasIncomplete ? "inProgress" : "pending"
5054
- }));
5055
- }
5056
4850
  function codexAspReasoningText(item) {
5057
4851
  return [...item.summary, ...item.content].filter(Boolean).join("\n").trim();
5058
4852
  }
@@ -5616,12 +5410,6 @@ function buildCodexAgentEnv() {
5616
5410
  delete env.GH_CONFIG_DIR;
5617
5411
  return env;
5618
5412
  }
5619
- function resolveCodexApiKey() {
5620
- if (shouldStripOpenAIApiKey()) {
5621
- return void 0;
5622
- }
5623
- return ENGINE_ENV.OPENAI_API_KEY;
5624
- }
5625
5413
  function shouldStripAnthropicApiKey() {
5626
5414
  const method = ENGINE_ENV.REPLICAS_CLAUDE_AUTH_METHOD;
5627
5415
  return method === "oauth" || method === "bedrock";
@@ -6744,7 +6532,7 @@ var AspClient = class {
6744
6532
  // src/managers/codex-asp/app-server-process.ts
6745
6533
  var DEFAULT_CODEX_BINARY = "codex";
6746
6534
  var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
6747
- var ENGINE_PACKAGE_VERSION = "0.1.277";
6535
+ var ENGINE_PACKAGE_VERSION = "0.1.279";
6748
6536
  var INITIALIZE_METHOD = "initialize";
6749
6537
  var INITIALIZED_NOTIFICATION = "initialized";
6750
6538
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -6947,25 +6735,6 @@ function buildCodexRateLimitsSnapshot(fields) {
6947
6735
  planType: fields.planType
6948
6736
  };
6949
6737
  }
6950
- function extractCodexRateLimitsSnapshotFromJsonl(parsed) {
6951
- if (!isRecord4(parsed)) return null;
6952
- const payload = isRecord4(parsed.payload) ? parsed.payload : parsed;
6953
- const rateLimits = isRecord4(payload.rate_limits) ? payload.rate_limits : null;
6954
- if (!rateLimits) return null;
6955
- const credits = isRecord4(rateLimits.credits) ? rateLimits.credits : null;
6956
- const hasCredits = credits && typeof credits.has_credits === "boolean" ? credits.has_credits : null;
6957
- const unlimited = credits && typeof credits.unlimited === "boolean" ? credits.unlimited : null;
6958
- const balance = credits && typeof credits.balance === "string" ? credits.balance : null;
6959
- const rateLimitResetType = typeof rateLimits.rate_limit_reached_type === "string" && rateLimits.rate_limit_reached_type.length > 0 ? rateLimits.rate_limit_reached_type : null;
6960
- const planType = typeof rateLimits.plan_type === "string" ? rateLimits.plan_type : null;
6961
- return buildCodexRateLimitsSnapshot({
6962
- unlimited,
6963
- hasCredits,
6964
- balance,
6965
- rateLimitResetType,
6966
- planType
6967
- });
6968
- }
6969
6738
  var CodexQuotaStatusTracker = class {
6970
6739
  lastEmittedQuotaState = "ok";
6971
6740
  latestQuotaSnapshot = null;
@@ -8444,410 +8213,6 @@ var CodexAspManager = class extends CodingAgentManager {
8444
8213
  }
8445
8214
  };
8446
8215
 
8447
- // src/managers/codex-manager.ts
8448
- import { Codex } from "@openai/codex-sdk";
8449
- import { readdir as readdir3, stat as stat2, writeFile as writeFile6, mkdir as mkdir11, readFile as readFile8 } from "fs/promises";
8450
- import { existsSync as existsSync7 } from "fs";
8451
- import { join as join14 } from "path";
8452
- import { homedir as homedir12 } from "os";
8453
- import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
8454
- var CODEX_CONFIG_PATH = join14(homedir12(), ".codex", "config.toml");
8455
- function isJsonlEvent2(value) {
8456
- if (!isRecord4(value)) {
8457
- return false;
8458
- }
8459
- return typeof value.timestamp === "string" && typeof value.type === "string" && isRecord4(value.payload);
8460
- }
8461
- function sleep(ms) {
8462
- return new Promise((resolve3) => setTimeout(resolve3, ms));
8463
- }
8464
- var CodexManager = class extends CodingAgentManager {
8465
- codex;
8466
- currentThreadId = null;
8467
- currentThread = null;
8468
- activeAbortController = null;
8469
- quotaStatus = new CodexQuotaStatusTracker();
8470
- constructor(options) {
8471
- super(options);
8472
- this.codex = this.createCodexClient();
8473
- this.initializeManager(this.processMessageInternal.bind(this));
8474
- }
8475
- createCodexClient() {
8476
- const codexApiKey = resolveCodexApiKey();
8477
- return new Codex({
8478
- env: buildCodexAgentEnv(),
8479
- ...codexApiKey ? { apiKey: codexApiKey } : {}
8480
- });
8481
- }
8482
- resetCodexClient() {
8483
- this.codex = this.createCodexClient();
8484
- this.currentThread = null;
8485
- }
8486
- async initialize() {
8487
- if (this.initialSessionId) {
8488
- this.currentThreadId = this.initialSessionId;
8489
- console.log(`[CodexManager] Restored thread ID from persisted state: ${this.currentThreadId}`);
8490
- }
8491
- }
8492
- async flushQuotaSnapshotFromCurrentSession() {
8493
- if (!this.currentThreadId) return;
8494
- try {
8495
- const sessionFile = await this.findSessionFile(this.currentThreadId);
8496
- if (!sessionFile) return;
8497
- const content = await readFile8(sessionFile, "utf-8");
8498
- const lines = content.split("\n").map((line) => line.trim()).filter(Boolean);
8499
- let latest = null;
8500
- for (const line of lines) {
8501
- try {
8502
- const parsed = JSON.parse(line);
8503
- const snapshot = extractCodexRateLimitsSnapshotFromJsonl(parsed);
8504
- if (snapshot) {
8505
- latest = snapshot;
8506
- }
8507
- } catch {
8508
- }
8509
- }
8510
- if (latest) {
8511
- this.emitQuotaStatus(latest);
8512
- }
8513
- } catch (error) {
8514
- console.warn("[CodexManager] Failed to flush quota snapshot from session:", error);
8515
- }
8516
- }
8517
- emitQuotaStatus(snapshot, force = false) {
8518
- const event = this.quotaStatus.apply(snapshot, force);
8519
- if (event) this.onEvent(event);
8520
- }
8521
- async interruptActiveTurn() {
8522
- if (this.activeAbortController) {
8523
- this.activeAbortController.abort();
8524
- }
8525
- }
8526
- /**
8527
- * Update the developer_instructions in ~/.codex/config.toml
8528
- * This sets the system prompt that Codex will use for this turn
8529
- */
8530
- async updateCodexConfig(developerInstructions) {
8531
- try {
8532
- const codexDir = join14(homedir12(), ".codex");
8533
- await mkdir11(codexDir, { recursive: true });
8534
- let config = {};
8535
- if (existsSync7(CODEX_CONFIG_PATH)) {
8536
- try {
8537
- const existingContent = await readFile8(CODEX_CONFIG_PATH, "utf-8");
8538
- const parsed = parseToml(existingContent);
8539
- if (isRecord4(parsed)) {
8540
- config = parsed;
8541
- }
8542
- } catch (parseError) {
8543
- console.warn("[CodexManager] Failed to parse existing config.toml, starting fresh:", parseError);
8544
- }
8545
- }
8546
- if (developerInstructions) {
8547
- config.developer_instructions = developerInstructions;
8548
- } else {
8549
- delete config.developer_instructions;
8550
- }
8551
- const tomlContent = stringifyToml(config);
8552
- await writeFile6(CODEX_CONFIG_PATH, tomlContent, "utf-8");
8553
- console.log("[CodexManager] Updated config.toml with developer_instructions");
8554
- } catch (error) {
8555
- console.error("[CodexManager] Failed to update config.toml:", error);
8556
- }
8557
- }
8558
- async processMessageInternal(request) {
8559
- try {
8560
- await this.executeCodexTurn(request);
8561
- } catch (error) {
8562
- if (isCodexAuthError(error)) {
8563
- const refreshed = await codexTokenManager.fetchFreshCredentials(error instanceof Error ? error.message : String(error));
8564
- if (refreshed) {
8565
- this.resetCodexClient();
8566
- await this.executeCodexTurn(request);
8567
- return;
8568
- }
8569
- }
8570
- throw error;
8571
- }
8572
- }
8573
- async executeCodexTurn(request) {
8574
- if (this.quotaStatus.blocked && this.quotaStatus.latestSnapshot) {
8575
- await this.flushQuotaSnapshotFromCurrentSession();
8576
- if (this.quotaStatus.blocked && this.quotaStatus.latestSnapshot) {
8577
- this.emitQuotaStatus(this.quotaStatus.latestSnapshot, true);
8578
- try {
8579
- await this.onTurnComplete();
8580
- } catch (error) {
8581
- console.error("[CodexManager] onTurnComplete failed during quota-blocked turn:", error);
8582
- }
8583
- return;
8584
- }
8585
- }
8586
- const {
8587
- message,
8588
- model,
8589
- customInstructions,
8590
- images,
8591
- permissionMode,
8592
- thinkingLevel
8593
- } = request;
8594
- const linearSessionId = ENGINE_ENV.LINEAR_SESSION_ID;
8595
- let tempImagePaths = [];
8596
- let stopTail = null;
8597
- let abortController = null;
8598
- try {
8599
- if (images && images.length > 0) {
8600
- const normalizedImages = await normalizeImages(images);
8601
- tempImagePaths = await saveNormalizedImagesToTempFiles(normalizedImages);
8602
- }
8603
- const developerInstructions = this.buildCombinedInstructions(customInstructions);
8604
- await this.updateCodexConfig(developerInstructions);
8605
- const sandboxMode = "danger-full-access";
8606
- const webSearchMode = "live";
8607
- const codexReasoningEffort = codexReasoningEffortForThinkingLevel(thinkingLevel);
8608
- const additionalDirectories = await getAgentAdditionalDirectories();
8609
- const threadOptions = {
8610
- workingDirectory: this.workingDirectory,
8611
- skipGitRepoCheck: true,
8612
- sandboxMode,
8613
- model: model || DEFAULT_CODEX_MODEL,
8614
- webSearchMode,
8615
- additionalDirectories,
8616
- ...codexReasoningEffort ? { modelReasoningEffort: codexReasoningEffort } : {}
8617
- };
8618
- abortController = new AbortController();
8619
- this.activeAbortController = abortController;
8620
- if (this.currentThreadId) {
8621
- this.currentThread = this.codex.resumeThread(this.currentThreadId, threadOptions);
8622
- } else {
8623
- this.currentThread = this.codex.startThread(threadOptions);
8624
- const { events } = await this.currentThread.runStreamed("Hello", { signal: abortController.signal });
8625
- for await (const event of events) {
8626
- if (event.type === "thread.started") {
8627
- this.currentThreadId = event.thread_id;
8628
- await this.onSaveSessionId(this.currentThreadId);
8629
- console.log(`[CodexManager] Captured and persisted thread ID: ${this.currentThreadId}`);
8630
- }
8631
- }
8632
- if (!this.currentThreadId && this.currentThread.id) {
8633
- this.currentThreadId = this.currentThread.id;
8634
- await this.onSaveSessionId(this.currentThreadId);
8635
- console.log(`[CodexManager] Captured and persisted thread ID from thread.id: ${this.currentThreadId}`);
8636
- }
8637
- }
8638
- stopTail = this.currentThreadId ? await this.startSessionTail(this.currentThreadId) : null;
8639
- let input;
8640
- if (tempImagePaths.length > 0) {
8641
- const inputItems = [
8642
- { type: "text", text: message },
8643
- ...tempImagePaths.map((path4) => ({ type: "local_image", path: path4 }))
8644
- ];
8645
- input = inputItems;
8646
- } else {
8647
- input = message;
8648
- }
8649
- try {
8650
- const { events } = await this.currentThread.runStreamed(input, { signal: abortController.signal });
8651
- const linearForwarder = new LinearEventForwarder(linearSessionId);
8652
- for await (const event of events) {
8653
- if (linearSessionId) {
8654
- linearForwarder.sendPlan(extractPlanFromCodexEvent(event));
8655
- linearForwarder.sendEvent(convertCodexEvent(event, linearSessionId));
8656
- }
8657
- }
8658
- linearForwarder.flushThoughtAsResponse();
8659
- } catch (error) {
8660
- await this.flushQuotaSnapshotFromCurrentSession();
8661
- if (this.quotaStatus.blocked) {
8662
- return;
8663
- }
8664
- throw error;
8665
- }
8666
- } finally {
8667
- if (stopTail) {
8668
- await stopTail();
8669
- }
8670
- await removeTempImageFiles(tempImagePaths);
8671
- try {
8672
- await this.onTurnComplete();
8673
- } catch (error) {
8674
- console.error("[CodexManager] onTurnComplete failed:", error);
8675
- }
8676
- this.activeAbortController = null;
8677
- }
8678
- }
8679
- async getHistory() {
8680
- if (!this.currentThreadId) {
8681
- return {
8682
- thread_id: null,
8683
- events: []
8684
- };
8685
- }
8686
- const sessionFile = await this.findSessionFile(this.currentThreadId);
8687
- if (!sessionFile) {
8688
- return {
8689
- thread_id: this.currentThreadId,
8690
- events: []
8691
- };
8692
- }
8693
- const events = await readJSONL(sessionFile);
8694
- return {
8695
- thread_id: this.currentThreadId,
8696
- events
8697
- };
8698
- }
8699
- // Helper methods for finding session files
8700
- async findSessionFile(threadId) {
8701
- const sessionsDir = join14(homedir12(), ".codex", "sessions");
8702
- try {
8703
- const now = /* @__PURE__ */ new Date();
8704
- const year = now.getFullYear();
8705
- const month = String(now.getMonth() + 1).padStart(2, "0");
8706
- const day = String(now.getDate()).padStart(2, "0");
8707
- const todayDir = join14(sessionsDir, String(year), month, day);
8708
- const file = await this.findFileInDirectory(todayDir, threadId);
8709
- if (file) return file;
8710
- for (let daysAgo = 1; daysAgo <= 7; daysAgo++) {
8711
- const date = new Date(now);
8712
- date.setDate(date.getDate() - daysAgo);
8713
- const searchYear = date.getFullYear();
8714
- const searchMonth = String(date.getMonth() + 1).padStart(2, "0");
8715
- const searchDay = String(date.getDate()).padStart(2, "0");
8716
- const searchDir = join14(sessionsDir, String(searchYear), searchMonth, searchDay);
8717
- const file2 = await this.findFileInDirectory(searchDir, threadId);
8718
- if (file2) return file2;
8719
- }
8720
- return null;
8721
- } catch (error) {
8722
- return null;
8723
- }
8724
- }
8725
- async findFileInDirectory(directory, threadId) {
8726
- try {
8727
- const files = await readdir3(directory);
8728
- for (const file of files) {
8729
- if (file.endsWith(".jsonl") && file.includes(threadId)) {
8730
- const fullPath = join14(directory, file);
8731
- const stats = await stat2(fullPath);
8732
- if (stats.isFile()) {
8733
- return fullPath;
8734
- }
8735
- }
8736
- }
8737
- return null;
8738
- } catch (error) {
8739
- return null;
8740
- }
8741
- }
8742
- async waitForSessionFile(threadId, timeoutMs = 5e3) {
8743
- const start = Date.now();
8744
- while (Date.now() - start < timeoutMs) {
8745
- const sessionFile = await this.findSessionFile(threadId);
8746
- if (sessionFile) {
8747
- return sessionFile;
8748
- }
8749
- await sleep(100);
8750
- }
8751
- return null;
8752
- }
8753
- // @openai/codex-sdk doesn't expose manual /compact (TUI-only); we only mirror the auto-compaction rollout entries to the UI.
8754
- trackNativeCompaction(event) {
8755
- if (event.type === "compacted") {
8756
- this.setCompacting(false);
8757
- return;
8758
- }
8759
- if (event.type !== "event_msg") return;
8760
- const msg = event.payload.msg;
8761
- if (!msg) return;
8762
- const itemType = msg.payload?.item?.type;
8763
- if (itemType !== "context_compaction") return;
8764
- if (msg.type === "item_started") {
8765
- this.setCompacting(true);
8766
- } else if (msg.type === "item_completed") {
8767
- this.setCompacting(false);
8768
- }
8769
- }
8770
- async startSessionTail(threadId) {
8771
- const sessionFile = await this.waitForSessionFile(threadId);
8772
- if (!sessionFile) {
8773
- return async () => {
8774
- };
8775
- }
8776
- let active = true;
8777
- const seenLines = /* @__PURE__ */ new Set();
8778
- const seedSeenLines = async () => {
8779
- try {
8780
- const content = await readFile8(sessionFile, "utf-8");
8781
- const lines = content.split("\n").map((line) => line.trim()).filter(Boolean);
8782
- let latest = null;
8783
- for (const line of lines) {
8784
- seenLines.add(line);
8785
- try {
8786
- const parsed = JSON.parse(line);
8787
- const snapshot = extractCodexRateLimitsSnapshotFromJsonl(parsed);
8788
- if (snapshot) latest = snapshot;
8789
- } catch {
8790
- }
8791
- }
8792
- if (latest) {
8793
- this.quotaStatus.prime(latest);
8794
- }
8795
- } catch {
8796
- }
8797
- };
8798
- await seedSeenLines();
8799
- const pump = async () => {
8800
- let emitted = 0;
8801
- try {
8802
- const content = await readFile8(sessionFile, "utf-8");
8803
- const lines = content.split("\n");
8804
- const completeLines = content.endsWith("\n") ? lines : lines.slice(0, -1);
8805
- for (const line of completeLines) {
8806
- const trimmed = line.trim();
8807
- if (!trimmed || seenLines.has(trimmed)) {
8808
- continue;
8809
- }
8810
- seenLines.add(trimmed);
8811
- try {
8812
- const parsed = JSON.parse(trimmed);
8813
- const snapshot = extractCodexRateLimitsSnapshotFromJsonl(parsed);
8814
- if (snapshot) {
8815
- this.emitQuotaStatus(snapshot);
8816
- }
8817
- if (isJsonlEvent2(parsed)) {
8818
- this.trackNativeCompaction(parsed);
8819
- this.onEvent(parsed);
8820
- emitted += 1;
8821
- }
8822
- } catch {
8823
- }
8824
- }
8825
- } catch {
8826
- }
8827
- return emitted;
8828
- };
8829
- const loop = (async () => {
8830
- while (active) {
8831
- await pump();
8832
- await sleep(100);
8833
- }
8834
- await pump();
8835
- })();
8836
- return async () => {
8837
- active = false;
8838
- await loop;
8839
- const deadline = Date.now() + 1500;
8840
- while (Date.now() < deadline) {
8841
- const emitted = await pump();
8842
- if (emitted > 0) {
8843
- continue;
8844
- }
8845
- await sleep(100);
8846
- }
8847
- };
8848
- }
8849
- };
8850
-
8851
8216
  // src/managers/relay-tools.ts
8852
8217
  import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
8853
8218
  import { z } from "zod";
@@ -9449,19 +8814,19 @@ var DuplicateDefaultChatError = class extends Error {
9449
8814
  };
9450
8815
 
9451
8816
  // src/services/chat/chat-service.ts
9452
- var ENGINE_DIR2 = join15(homedir13(), ".replicas", "engine");
9453
- var CHATS_FILE = join15(ENGINE_DIR2, "chats.json");
9454
- var CLAUDE_HISTORY_DIR = join15(ENGINE_DIR2, "claude-histories");
9455
- var RELAY_HISTORY_DIR = join15(ENGINE_DIR2, "relay-histories");
9456
- var CHAT_SENDERS_DIR = join15(ENGINE_DIR2, "chat-senders");
9457
- var CODEX_AUTH_PATH2 = join15(homedir13(), ".codex", "auth.json");
8817
+ var ENGINE_DIR2 = join14(homedir12(), ".replicas", "engine");
8818
+ var CHATS_FILE = join14(ENGINE_DIR2, "chats.json");
8819
+ var CLAUDE_HISTORY_DIR = join14(ENGINE_DIR2, "claude-histories");
8820
+ var RELAY_HISTORY_DIR = join14(ENGINE_DIR2, "relay-histories");
8821
+ var CHAT_SENDERS_DIR = join14(ENGINE_DIR2, "chat-senders");
8822
+ var CODEX_AUTH_PATH2 = join14(homedir12(), ".codex", "auth.json");
9458
8823
  var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
9459
8824
  function isChatMessageSender(value) {
9460
8825
  if (!isRecord4(value)) return false;
9461
8826
  return typeof value.senderUserId === "string" && typeof value.senderEmail === "string" && typeof value.recordedAt === "string";
9462
8827
  }
9463
8828
  function isCodexAvailable() {
9464
- return existsSync8(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
8829
+ return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
9465
8830
  }
9466
8831
  function isSameAcceptedUserEvent(event, acceptedEvent) {
9467
8832
  if (areSameUserMessageEvents(event, acceptedEvent)) return true;
@@ -9503,18 +8868,18 @@ function isPersistedChat(value) {
9503
8868
  return false;
9504
8869
  }
9505
8870
  const candidate = value;
9506
- return typeof candidate.id === "string" && (candidate.provider === "claude" || candidate.provider === "codex" || candidate.provider === "relay") && typeof candidate.title === "string" && typeof candidate.createdAt === "string" && typeof candidate.updatedAt === "string" && (candidate.providerSessionId === null || typeof candidate.providerSessionId === "string") && (candidate.parentChatId === void 0 || candidate.parentChatId === null || typeof candidate.parentChatId === "string") && (candidate.codexBackend === void 0 || candidate.codexBackend === "sdk" || candidate.codexBackend === "asp");
9507
- }
9508
- function codexBackendForChat(chat) {
9509
- if (chat.provider !== "codex") return "asp";
9510
- if (chat.codexBackend) return chat.codexBackend;
9511
- return chat.providerSessionId ? "sdk" : "asp";
8871
+ return typeof candidate.id === "string" && (candidate.provider === "claude" || candidate.provider === "codex" || candidate.provider === "relay") && typeof candidate.title === "string" && typeof candidate.createdAt === "string" && typeof candidate.updatedAt === "string" && (candidate.providerSessionId === null || typeof candidate.providerSessionId === "string") && (candidate.parentChatId === void 0 || candidate.parentChatId === null || typeof candidate.parentChatId === "string");
9512
8872
  }
9513
8873
  function normalizePersistedChat(chat) {
8874
+ const isLegacyCodexSdkChat = chat.provider === "codex" && (chat.codexBackend === "sdk" || chat.codexBackend === void 0 && chat.providerSessionId !== null);
9514
8875
  return {
9515
- ...chat,
9516
- parentChatId: chat.parentChatId ?? null,
9517
- ...chat.provider === "codex" ? { codexBackend: codexBackendForChat(chat) } : {}
8876
+ id: chat.id,
8877
+ provider: chat.provider,
8878
+ title: chat.title,
8879
+ createdAt: chat.createdAt,
8880
+ updatedAt: chat.updatedAt,
8881
+ providerSessionId: isLegacyCodexSdkChat ? null : chat.providerSessionId,
8882
+ parentChatId: chat.parentChatId ?? null
9518
8883
  };
9519
8884
  }
9520
8885
  function parsePersistedChatsContent(content) {
@@ -9549,10 +8914,10 @@ var ChatService = class {
9549
8914
  chats = /* @__PURE__ */ new Map();
9550
8915
  writeChain = Promise.resolve();
9551
8916
  async initialize() {
9552
- await mkdir12(ENGINE_DIR2, { recursive: true });
9553
- await mkdir12(CLAUDE_HISTORY_DIR, { recursive: true });
9554
- await mkdir12(RELAY_HISTORY_DIR, { recursive: true });
9555
- await mkdir12(CHAT_SENDERS_DIR, { recursive: true });
8917
+ await mkdir11(ENGINE_DIR2, { recursive: true });
8918
+ await mkdir11(CLAUDE_HISTORY_DIR, { recursive: true });
8919
+ await mkdir11(RELAY_HISTORY_DIR, { recursive: true });
8920
+ await mkdir11(CHAT_SENDERS_DIR, { recursive: true });
9556
8921
  const persisted = await this.loadChats();
9557
8922
  for (const chat of persisted) {
9558
8923
  const runtime = this.createRuntimeChat(chat);
@@ -9604,8 +8969,7 @@ var ChatService = class {
9604
8969
  createdAt: now,
9605
8970
  updatedAt: now,
9606
8971
  providerSessionId: null,
9607
- parentChatId,
9608
- ...request.provider === "codex" ? { codexBackend: "asp" } : {}
8972
+ parentChatId
9609
8973
  };
9610
8974
  const runtime = this.createRuntimeChat(persisted);
9611
8975
  this.chats.set(persisted.id, runtime);
@@ -9651,7 +9015,7 @@ var ChatService = class {
9651
9015
  };
9652
9016
  }
9653
9017
  senderFilePath(chatId) {
9654
- return join15(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
9018
+ return join14(CHAT_SENDERS_DIR, `${chatId}.jsonl`);
9655
9019
  }
9656
9020
  async appendSender(chatId, sender) {
9657
9021
  try {
@@ -9662,7 +9026,7 @@ var ChatService = class {
9662
9026
  }
9663
9027
  async readSenders(chatId) {
9664
9028
  try {
9665
- const content = await readFile9(this.senderFilePath(chatId), "utf-8");
9029
+ const content = await readFile8(this.senderFilePath(chatId), "utf-8");
9666
9030
  const lines = content.split("\n").filter((line) => line.trim().length > 0);
9667
9031
  const senders = [];
9668
9032
  for (const line of lines) {
@@ -9801,7 +9165,7 @@ var ChatService = class {
9801
9165
  async deleteHistoryFile(persisted) {
9802
9166
  if (persisted.provider === "claude" || persisted.provider === "relay") {
9803
9167
  const dir = persisted.provider === "claude" ? CLAUDE_HISTORY_DIR : RELAY_HISTORY_DIR;
9804
- await rm(join15(dir, `${persisted.id}.jsonl`), { force: true });
9168
+ await rm(join14(dir, `${persisted.id}.jsonl`), { force: true });
9805
9169
  }
9806
9170
  await rm(this.senderFilePath(persisted.id), { force: true });
9807
9171
  }
@@ -9858,7 +9222,7 @@ var ChatService = class {
9858
9222
  if (persisted.provider === "claude") {
9859
9223
  provider = new ClaudeManager({
9860
9224
  workingDirectory: this.workingDirectory,
9861
- historyFilePath: join15(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
9225
+ historyFilePath: join14(CLAUDE_HISTORY_DIR, `${persisted.id}.jsonl`),
9862
9226
  initialSessionId: persisted.providerSessionId,
9863
9227
  onSaveSessionId: saveSession,
9864
9228
  onTurnComplete: onProviderTurnComplete,
@@ -9867,7 +9231,7 @@ var ChatService = class {
9867
9231
  } else if (persisted.provider === "relay") {
9868
9232
  provider = new RelayManager({
9869
9233
  workingDirectory: this.workingDirectory,
9870
- historyFilePath: join15(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
9234
+ historyFilePath: join14(RELAY_HISTORY_DIR, `${persisted.id}.jsonl`),
9871
9235
  initialSessionId: persisted.providerSessionId,
9872
9236
  onSaveSessionId: saveSession,
9873
9237
  onTurnComplete: onProviderTurnComplete,
@@ -9876,8 +9240,7 @@ var ChatService = class {
9876
9240
  codexAvailable: isCodexAvailable()
9877
9241
  });
9878
9242
  } else {
9879
- const CodexProviderCtor = codexBackendForChat(persisted) === "sdk" ? CodexManager : CodexAspManager;
9880
- provider = new CodexProviderCtor({
9243
+ provider = new CodexAspManager({
9881
9244
  workingDirectory: this.workingDirectory,
9882
9245
  initialSessionId: persisted.providerSessionId,
9883
9246
  onSaveSessionId: saveSession,
@@ -10019,7 +9382,7 @@ var ChatService = class {
10019
9382
  }
10020
9383
  async loadChats() {
10021
9384
  try {
10022
- const content = await readFile9(CHATS_FILE, "utf-8");
9385
+ const content = await readFile8(CHATS_FILE, "utf-8");
10023
9386
  return parsePersistedChatsContent(content);
10024
9387
  } catch (error) {
10025
9388
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
@@ -10034,7 +9397,7 @@ var ChatService = class {
10034
9397
  console.error("[ChatService] Failed to quarantine corrupt chats file:", renameError);
10035
9398
  }
10036
9399
  try {
10037
- const backupContent = await readFile9(CHATS_BACKUP_FILE, "utf-8");
9400
+ const backupContent = await readFile8(CHATS_BACKUP_FILE, "utf-8");
10038
9401
  return parsePersistedChatsContent(backupContent);
10039
9402
  } catch (backupError) {
10040
9403
  if (backupError && typeof backupError === "object" && "code" in backupError && backupError.code === "ENOENT") {
@@ -10109,8 +9472,8 @@ var ChatService = class {
10109
9472
 
10110
9473
  // src/services/repo-file-service.ts
10111
9474
  import { execFile as execFile2 } from "child_process";
10112
- import { readFile as readFile10, realpath, stat as stat3 } from "fs/promises";
10113
- import { join as join16, resolve, extname } from "path";
9475
+ import { readFile as readFile9, realpath, stat as stat2 } from "fs/promises";
9476
+ import { join as join15, resolve, extname } from "path";
10114
9477
  var CACHE_TTL_MS = 3e4;
10115
9478
  var SEARCH_TIMEOUT_MS = 15e3;
10116
9479
  var MAX_CONTENT_BYTES = 256 * 1024;
@@ -10270,11 +9633,11 @@ var RepoFileService = class {
10270
9633
  const repo = repos.find((r) => r.name === repoName);
10271
9634
  if (!repo) return null;
10272
9635
  try {
10273
- const fullPath = await realpath(resolve(join16(repo.path, filePath)));
9636
+ const fullPath = await realpath(resolve(join15(repo.path, filePath)));
10274
9637
  const repoRoot = await realpath(repo.path);
10275
9638
  const repoPrefix = repoRoot.endsWith("/") ? repoRoot : repoRoot + "/";
10276
9639
  if (!fullPath.startsWith(repoPrefix) && fullPath !== repoRoot) return null;
10277
- const fileStat = await stat3(fullPath);
9640
+ const fileStat = await stat2(fullPath);
10278
9641
  if (!fileStat.isFile()) return null;
10279
9642
  const sizeBytes = fileStat.size;
10280
9643
  if (isBinaryExtension(filePath)) {
@@ -10299,7 +9662,7 @@ var RepoFileService = class {
10299
9662
  tooLarge: true
10300
9663
  };
10301
9664
  }
10302
- const content = await readFile10(fullPath, "utf-8");
9665
+ const content = await readFile9(fullPath, "utf-8");
10303
9666
  return {
10304
9667
  repoName,
10305
9668
  path: filePath,
@@ -10377,16 +9740,16 @@ var RepoFileService = class {
10377
9740
  // src/v1-routes.ts
10378
9741
  import { Hono } from "hono";
10379
9742
  import { z as z2 } from "zod";
10380
- import { readdir as readdir6, stat as stat5, readFile as readFile14 } from "fs/promises";
10381
- import { join as join20, resolve as resolve2 } from "path";
9743
+ import { readdir as readdir5, stat as stat4, readFile as readFile13 } from "fs/promises";
9744
+ import { join as join19, resolve as resolve2 } from "path";
10382
9745
 
10383
9746
  // src/services/canvas-service.ts
10384
- import { readdir as readdir4, readFile as readFile11, stat as stat4 } from "fs/promises";
10385
- import { homedir as homedir14 } from "os";
10386
- import { basename, join as join17 } from "path";
9747
+ import { readdir as readdir3, readFile as readFile10, stat as stat3 } from "fs/promises";
9748
+ import { homedir as homedir13 } from "os";
9749
+ import { basename, join as join16 } from "path";
10387
9750
  var CANVAS_DIRECTORIES = [
10388
- join17(homedir14(), ".claude", "plans"),
10389
- join17(homedir14(), ".replicas", "canvas")
9751
+ join16(homedir13(), ".claude", "plans"),
9752
+ join16(homedir13(), ".replicas", "canvas")
10390
9753
  ];
10391
9754
  var MAX_CANVAS_FILE_BYTES = 5 * 1024 * 1024;
10392
9755
  function isTextKind(kind) {
@@ -10401,7 +9764,7 @@ var CanvasService = class {
10401
9764
  for (const directory of CANVAS_DIRECTORIES) {
10402
9765
  let entries;
10403
9766
  try {
10404
- entries = await readdir4(directory, { withFileTypes: true });
9767
+ entries = await readdir3(directory, { withFileTypes: true });
10405
9768
  } catch {
10406
9769
  continue;
10407
9770
  }
@@ -10412,7 +9775,7 @@ var CanvasService = class {
10412
9775
  const { kind } = classifyCanvasFilename(entry.name);
10413
9776
  let sizeBytes = 0;
10414
9777
  try {
10415
- const s = await stat4(join17(directory, entry.name));
9778
+ const s = await stat3(join16(directory, entry.name));
10416
9779
  sizeBytes = s.size;
10417
9780
  } catch {
10418
9781
  continue;
@@ -10427,10 +9790,10 @@ var CanvasService = class {
10427
9790
  if (!safe || safe !== filename || safe.startsWith(".")) return null;
10428
9791
  const { kind, mimeType } = classifyCanvasFilename(safe);
10429
9792
  for (const directory of CANVAS_DIRECTORIES) {
10430
- const filePath = join17(directory, safe);
9793
+ const filePath = join16(directory, safe);
10431
9794
  let sizeBytes = 0;
10432
9795
  try {
10433
- const s = await stat4(filePath);
9796
+ const s = await stat3(filePath);
10434
9797
  sizeBytes = s.size;
10435
9798
  } catch {
10436
9799
  continue;
@@ -10446,10 +9809,10 @@ var CanvasService = class {
10446
9809
  }
10447
9810
  try {
10448
9811
  if (isTextKind(kind)) {
10449
- const content = await readFile11(filePath, "utf-8");
9812
+ const content = await readFile10(filePath, "utf-8");
10450
9813
  return { filename: safe, kind, sizeBytes, mimeType, content };
10451
9814
  }
10452
- const buf = await readFile11(filePath);
9815
+ const buf = await readFile10(filePath);
10453
9816
  return { filename: safe, kind, sizeBytes, mimeType, base64: buf.toString("base64") };
10454
9817
  } catch {
10455
9818
  continue;
@@ -10462,16 +9825,16 @@ var canvasService = new CanvasService();
10462
9825
 
10463
9826
  // src/services/warm-hooks-service.ts
10464
9827
  import { spawn as spawn4 } from "child_process";
10465
- import { readFile as readFile13 } from "fs/promises";
10466
- import { existsSync as existsSync9 } from "fs";
10467
- import { join as join19 } from "path";
9828
+ import { readFile as readFile12 } from "fs/promises";
9829
+ import { existsSync as existsSync8 } from "fs";
9830
+ import { join as join18 } from "path";
10468
9831
 
10469
9832
  // src/services/warm-hook-logs-service.ts
10470
- import { mkdir as mkdir13, readFile as readFile12, writeFile as writeFile7, readdir as readdir5, appendFile as appendFile6, unlink as unlink3 } from "fs/promises";
10471
- import { homedir as homedir15 } from "os";
10472
- import { join as join18 } from "path";
10473
- var LOGS_DIR2 = join18(homedir15(), ".replicas", "warm-hook-logs");
10474
- var CURRENT_RUN_LOG = join18(LOGS_DIR2, "current-run.log");
9833
+ import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile6, readdir as readdir4, appendFile as appendFile6, unlink as unlink3 } from "fs/promises";
9834
+ import { homedir as homedir14 } from "os";
9835
+ import { join as join17 } from "path";
9836
+ var LOGS_DIR2 = join17(homedir14(), ".replicas", "warm-hook-logs");
9837
+ var CURRENT_RUN_LOG = join17(LOGS_DIR2, "current-run.log");
10475
9838
  var GLOBAL_FILENAME = "global.json";
10476
9839
  function withPreview2(stored) {
10477
9840
  const preview = buildHookOutputPreview(stored.output);
@@ -10479,7 +9842,7 @@ function withPreview2(stored) {
10479
9842
  }
10480
9843
  var WarmHookLogsService = class {
10481
9844
  async ensureDir() {
10482
- await mkdir13(LOGS_DIR2, { recursive: true });
9845
+ await mkdir12(LOGS_DIR2, { recursive: true });
10483
9846
  }
10484
9847
  async saveGlobalHookLog(entry) {
10485
9848
  await this.ensureDir();
@@ -10488,7 +9851,7 @@ var WarmHookLogsService = class {
10488
9851
  hookName: "organization",
10489
9852
  ...entry
10490
9853
  };
10491
- await writeFile7(join18(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
9854
+ await writeFile6(join17(LOGS_DIR2, GLOBAL_FILENAME), `${JSON.stringify(log, null, 2)}
10492
9855
  `, "utf-8");
10493
9856
  }
10494
9857
  async saveEnvironmentHookLog(entry) {
@@ -10498,7 +9861,7 @@ var WarmHookLogsService = class {
10498
9861
  hookName: "environment",
10499
9862
  ...entry
10500
9863
  };
10501
- await writeFile7(join18(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
9864
+ await writeFile6(join17(LOGS_DIR2, ENVIRONMENT_HOOK_LOG_FILENAME), `${JSON.stringify(log, null, 2)}
10502
9865
  `, "utf-8");
10503
9866
  }
10504
9867
  async saveRepoHookLog(repoName, entry) {
@@ -10508,13 +9871,13 @@ var WarmHookLogsService = class {
10508
9871
  hookName: repoName,
10509
9872
  ...entry
10510
9873
  };
10511
- await writeFile7(join18(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
9874
+ await writeFile6(join17(LOGS_DIR2, repoHookLogFilename(repoName)), `${JSON.stringify(log, null, 2)}
10512
9875
  `, "utf-8");
10513
9876
  }
10514
9877
  async getAllLogs() {
10515
9878
  let files;
10516
9879
  try {
10517
- files = await readdir5(LOGS_DIR2);
9880
+ files = await readdir4(LOGS_DIR2);
10518
9881
  } catch (err) {
10519
9882
  if (err.code === "ENOENT") {
10520
9883
  return [];
@@ -10527,7 +9890,7 @@ var WarmHookLogsService = class {
10527
9890
  continue;
10528
9891
  }
10529
9892
  try {
10530
- const raw = await readFile12(join18(LOGS_DIR2, file), "utf-8");
9893
+ const raw = await readFile11(join17(LOGS_DIR2, file), "utf-8");
10531
9894
  const stored = JSON.parse(raw);
10532
9895
  logs.push(withPreview2(stored));
10533
9896
  } catch {
@@ -10556,7 +9919,7 @@ var WarmHookLogsService = class {
10556
9919
  }
10557
9920
  async getCurrentRunLog() {
10558
9921
  try {
10559
- return await readFile12(CURRENT_RUN_LOG, "utf-8");
9922
+ return await readFile11(CURRENT_RUN_LOG, "utf-8");
10560
9923
  } catch (err) {
10561
9924
  if (err.code === "ENOENT") return null;
10562
9925
  throw err;
@@ -10565,7 +9928,7 @@ var WarmHookLogsService = class {
10565
9928
  async getFullOutput(hookType, hookName) {
10566
9929
  const filename = hookType === "global" ? GLOBAL_FILENAME : hookType === "environment" ? ENVIRONMENT_HOOK_LOG_FILENAME : repoHookLogFilename(hookName);
10567
9930
  try {
10568
- const raw = await readFile12(join18(LOGS_DIR2, filename), "utf-8");
9931
+ const raw = await readFile11(join17(LOGS_DIR2, filename), "utf-8");
10569
9932
  const stored = JSON.parse(raw);
10570
9933
  if (stored.hookType !== hookType || stored.hookName !== hookName) {
10571
9934
  return null;
@@ -10584,12 +9947,12 @@ var warmHookLogsService = new WarmHookLogsService();
10584
9947
  // src/services/warm-hooks-service.ts
10585
9948
  async function readRepoWarmHook(repoPath) {
10586
9949
  for (const filename of REPLICAS_CONFIG_FILENAMES) {
10587
- const configPath = join19(repoPath, filename);
10588
- if (!existsSync9(configPath)) {
9950
+ const configPath = join18(repoPath, filename);
9951
+ if (!existsSync8(configPath)) {
10589
9952
  continue;
10590
9953
  }
10591
9954
  try {
10592
- const raw = await readFile13(configPath, "utf-8");
9955
+ const raw = await readFile12(configPath, "utf-8");
10593
9956
  const config = parseReplicasConfigString(raw, filename);
10594
9957
  if (!config.warmHook) {
10595
9958
  return null;
@@ -11482,12 +10845,12 @@ function createV1Routes(deps) {
11482
10845
  });
11483
10846
  app2.get("/logs", async (c) => {
11484
10847
  try {
11485
- const files = await readdir6(LOG_DIR).catch(() => []);
10848
+ const files = await readdir5(LOG_DIR).catch(() => []);
11486
10849
  const logFiles = files.filter((f) => f.endsWith(".log"));
11487
10850
  const sessions = await Promise.all(
11488
10851
  logFiles.map(async (filename) => {
11489
- const filePath = join20(LOG_DIR, filename);
11490
- const fileStat = await stat5(filePath);
10852
+ const filePath = join19(LOG_DIR, filename);
10853
+ const fileStat = await stat4(filePath);
11491
10854
  const sessionId = filename.replace(/\.log$/, "");
11492
10855
  return {
11493
10856
  sessionId,
@@ -11523,7 +10886,7 @@ function createV1Routes(deps) {
11523
10886
  const limit = Math.min(parseInt(c.req.query("limit") || "500", 10), 5e3);
11524
10887
  let content;
11525
10888
  try {
11526
- content = await readFile14(filePath, "utf-8");
10889
+ content = await readFile13(filePath, "utf-8");
11527
10890
  } catch {
11528
10891
  return c.json(jsonError("Log session not found"), 404);
11529
10892
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.277",
3
+ "version": "0.1.279",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -32,7 +32,6 @@
32
32
  "dependencies": {
33
33
  "@anthropic-ai/claude-agent-sdk": "0.2.112",
34
34
  "@hono/node-server": "^1.19.5",
35
- "@openai/codex-sdk": "^0.124.0",
36
35
  "hono": "^4.10.3",
37
36
  "smol-toml": "^1.6.0",
38
37
  "yaml": "^2.8.2",