replicas-engine 0.1.452 → 0.1.454

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 +177 -101
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -163,6 +163,21 @@ function detectLanguageByPath(filePath) {
163
163
  return EXT_TO_LANGUAGE[ext] ?? null;
164
164
  }
165
165
 
166
+ // ../shared/src/credentials/opencode-go.ts
167
+ import { z } from "zod";
168
+ var OPENCODE_GO_PROVIDER = "opencode-go";
169
+ var opencodeGoModelsDevSchema = z.object({
170
+ "opencode-go": z.object({
171
+ models: z.record(z.string(), z.object({
172
+ id: z.string().optional(),
173
+ name: z.string(),
174
+ description: z.string().optional(),
175
+ status: z.enum(["alpha", "beta", "deprecated"]).optional()
176
+ }))
177
+ }).optional()
178
+ });
179
+ var OPENCODE_GO_CATALOG_CACHE_MS = 5 * 6e4;
180
+
166
181
  // ../shared/src/engine/types.ts
167
182
  var DEFAULT_CHAT_TITLES = {
168
183
  claude: "Claude Code",
@@ -528,7 +543,7 @@ var WORKSPACE_SIZES = ["small", "large"];
528
543
  var INVALID_WORKSPACE_SIZE_ERROR = `Invalid size: must be one of ${WORKSPACE_SIZES.join(", ")}`;
529
544
 
530
545
  // ../shared/src/e2b.ts
531
- var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-v4";
546
+ var E2B_TEMPLATE_NAME = "replicas-sandbox-2026-07-19-v6";
532
547
 
533
548
  // ../shared/src/runtime-env.ts
534
549
  function shellQuotePosix(value) {
@@ -2742,6 +2757,9 @@ var DESKTOP_NOVNC_PORT = 6080;
2742
2757
 
2743
2758
  // ../shared/src/engine/v1.ts
2744
2759
  var MERGED_MESSAGE_SEPARATOR = "\n\n<!-- replicas:merged -->\n\n";
2760
+ var ENGINE_HEALTH_WAIT_HEADER = "X-Replicas-Health-Wait";
2761
+ var ENGINE_HEALTH_WAIT_QUERY_PARAM = "wait_ms";
2762
+ var ENGINE_HEALTH_MAX_WAIT_MS = 2e3;
2745
2763
  function normalizeCodexAspTranscriptStatus(status, failed = false) {
2746
2764
  if (failed || status === "failed" || status === "declined") return "failed";
2747
2765
  if (status === "completed") return "completed";
@@ -5870,7 +5888,7 @@ async function registerDesktopPreview() {
5870
5888
  }
5871
5889
 
5872
5890
  // src/services/chat/chat-service.ts
5873
- import { existsSync as existsSync7 } from "fs";
5891
+ import { existsSync as existsSync8 } from "fs";
5874
5892
  import { appendFile as appendFile3, copyFile, mkdir as mkdir14, readFile as readFile14, rename as rename2, rm as rm2 } from "fs/promises";
5875
5893
  import { homedir as homedir15 } from "os";
5876
5894
  import { join as join22 } from "path";
@@ -8586,7 +8604,7 @@ var DEFAULT_CODEX_ARGS = ["app-server", "--listen", "stdio://"];
8586
8604
  var MIN_CODEX_CLI_VERSION = "0.144.0";
8587
8605
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
8588
8606
  var codexCliVersionEnsured = null;
8589
- var ENGINE_PACKAGE_VERSION = "0.1.452";
8607
+ var ENGINE_PACKAGE_VERSION = "0.1.454";
8590
8608
  var INITIALIZE_METHOD = "initialize";
8591
8609
  var INITIALIZED_NOTIFICATION = "initialized";
8592
8610
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -11080,17 +11098,20 @@ var CursorManager = class extends CodingAgentManager {
11080
11098
  };
11081
11099
 
11082
11100
  // src/managers/opencode-manager.ts
11101
+ import { existsSync as existsSync7 } from "fs";
11083
11102
  import { mkdir as mkdir12, readFile as readFile11 } from "fs/promises";
11084
11103
  import { delimiter, dirname as dirname6, join as join18 } from "path";
11085
11104
  import { randomBytes as randomBytes2 } from "crypto";
11086
11105
  import { fileURLToPath } from "url";
11087
11106
  import { Agent } from "undici";
11107
+ import { z as z2 } from "zod";
11088
11108
  import {
11089
11109
  createOpencodeClient,
11090
11110
  createOpencodeServer
11091
11111
  } from "@opencode-ai/sdk/v2";
11092
11112
  var OPENCODE_SHIM_DIR = dirname6(fileURLToPath(new URL("../../scripts/opencode", import.meta.url)));
11093
11113
  var OPENCODE_CONFIG_PATH = join18(ENGINE_ENV.HOME_DIR, ".config", "opencode", "opencode.json");
11114
+ var OPENCODE_AUTH_PATH2 = join18(ENGINE_ENV.HOME_DIR, ".local", "share", "opencode", "auth.json");
11094
11115
  var OPENCODE_FETCH_DISPATCHER = new Agent({ headersTimeout: 0, bodyTimeout: 0 });
11095
11116
  var OPENCODE_SERVER_STARTUP_TIMEOUT_MS = 3e4;
11096
11117
  var OPENCODE_WORKSPACE_PERMISSION = {
@@ -11118,30 +11139,56 @@ var OPENCODE_VARIANT_CANDIDATES_BY_THINKING_LEVEL = {
11118
11139
  xhigh: ["xhigh", "high"],
11119
11140
  max: ["max", "xhigh", "high"]
11120
11141
  };
11142
+ var opencodeAuthSchema = z2.record(z2.string(), z2.object({
11143
+ type: z2.string().optional(),
11144
+ key: z2.string().optional()
11145
+ }));
11146
+ async function hasOpenCodeGoCredentials() {
11147
+ if (!existsSync7(OPENCODE_AUTH_PATH2)) return false;
11148
+ try {
11149
+ const auth = opencodeAuthSchema.safeParse(JSON.parse(await readFile11(OPENCODE_AUTH_PATH2, "utf8")));
11150
+ return auth.success && auth.data[OPENCODE_GO_PROVIDER]?.type === "api" && Boolean(auth.data[OPENCODE_GO_PROVIDER]?.key);
11151
+ } catch {
11152
+ return false;
11153
+ }
11154
+ }
11155
+ function getOpenCodeGoModel(model) {
11156
+ return model.replace(/^[^/]+\//, "");
11157
+ }
11121
11158
  async function opencodeConfig(model) {
11122
- const models = getConfiguredOpencodeModels(model);
11123
- const mcp = await readProvisionedOpencodeMcpConfig();
11124
- const config = {
11125
- enabled_providers: ["openrouter"],
11126
- model: `openrouter/${model}`,
11127
- provider: {
11128
- openrouter: {
11129
- models: Object.fromEntries(models.map((candidate) => [candidate, {}])),
11130
- options: {
11131
- apiKey: "{env:OPENROUTER_API_KEY}"
11159
+ let config;
11160
+ if (await hasOpenCodeGoCredentials()) {
11161
+ config = {
11162
+ enabled_providers: [OPENCODE_GO_PROVIDER],
11163
+ model: `${OPENCODE_GO_PROVIDER}/${model}`,
11164
+ permission: OPENCODE_WORKSPACE_PERMISSION,
11165
+ share: "disabled"
11166
+ };
11167
+ } else {
11168
+ const models = getConfiguredOpencodeModels(model);
11169
+ config = {
11170
+ enabled_providers: ["openrouter"],
11171
+ model: `openrouter/${model}`,
11172
+ provider: {
11173
+ openrouter: {
11174
+ models: Object.fromEntries(models.map((candidate) => [candidate, {}])),
11175
+ options: {
11176
+ apiKey: "{env:OPENROUTER_API_KEY}"
11177
+ }
11132
11178
  }
11133
- }
11134
- },
11135
- permission: OPENCODE_WORKSPACE_PERMISSION,
11136
- share: "disabled"
11137
- };
11179
+ },
11180
+ permission: OPENCODE_WORKSPACE_PERMISSION,
11181
+ share: "disabled"
11182
+ };
11183
+ }
11184
+ const mcp = await readProvisionedOpencodeMcpConfig();
11138
11185
  if (mcp && Object.keys(mcp).length > 0) {
11139
11186
  config.mcp = mcp;
11140
11187
  }
11141
11188
  return config;
11142
11189
  }
11143
11190
  function getConfiguredOpencodeModels(model) {
11144
- return [.../* @__PURE__ */ new Set([model, ...AGENT_MODELS.opencode])];
11191
+ return [.../* @__PURE__ */ new Set([model, ...OPENROUTER_MODELS])];
11145
11192
  }
11146
11193
  function opencodeCommandToSlashCommand(command) {
11147
11194
  return createProviderSlashCommand("opencode", command.name, command.description);
@@ -11271,6 +11318,7 @@ var OpencodeManager = class extends CodingAgentManager {
11271
11318
  historyFile;
11272
11319
  activeAbortController = null;
11273
11320
  configuredModels = /* @__PURE__ */ new Set();
11321
+ providerId = "openrouter";
11274
11322
  eventAbortController = null;
11275
11323
  eventSubscriptionReady = Promise.resolve();
11276
11324
  resolveEventSubscriptionReady = null;
@@ -11358,9 +11406,21 @@ var OpencodeManager = class extends CodingAgentManager {
11358
11406
  return this.slashCommandsRequest;
11359
11407
  }
11360
11408
  async ensureClient(model) {
11361
- if (this.client && this.configuredModels.has(model)) return this.client;
11362
- if (!ENGINE_ENV.OPENROUTER_API_KEY) {
11363
- throw new Error("OpenRouter API key is not configured for Opencode in this workspace.");
11409
+ const providerId = await hasOpenCodeGoCredentials() ? OPENCODE_GO_PROVIDER : "openrouter";
11410
+ if (this.client && this.providerId !== providerId) {
11411
+ this.eventAbortController?.abort();
11412
+ this.server?.close();
11413
+ this.client = null;
11414
+ this.server = null;
11415
+ this.configuredModels.clear();
11416
+ }
11417
+ this.providerId = providerId;
11418
+ const configuredModel = providerId === OPENCODE_GO_PROVIDER ? getOpenCodeGoModel(model) : model;
11419
+ if (this.client && (providerId === OPENCODE_GO_PROVIDER || this.configuredModels.has(configuredModel))) {
11420
+ return this.client;
11421
+ }
11422
+ if (!ENGINE_ENV.OPENROUTER_API_KEY && this.providerId !== OPENCODE_GO_PROVIDER) {
11423
+ throw new Error("OpenCode Go or OpenRouter credentials are not configured for Opencode in this workspace.");
11364
11424
  }
11365
11425
  this.eventAbortController?.abort();
11366
11426
  this.server?.close();
@@ -11373,7 +11433,7 @@ var OpencodeManager = class extends CodingAgentManager {
11373
11433
  const server = await createOpencodeServer({
11374
11434
  port: 0,
11375
11435
  timeout: OPENCODE_SERVER_STARTUP_TIMEOUT_MS,
11376
- config: await opencodeConfig(model)
11436
+ config: await opencodeConfig(configuredModel)
11377
11437
  });
11378
11438
  const client = createOpencodeClient({
11379
11439
  baseUrl: server.url,
@@ -11384,7 +11444,7 @@ var OpencodeManager = class extends CodingAgentManager {
11384
11444
  });
11385
11445
  this.client = client;
11386
11446
  this.server = server;
11387
- this.configuredModels = new Set(getConfiguredOpencodeModels(model));
11447
+ this.configuredModels = this.providerId === OPENCODE_GO_PROVIDER ? /* @__PURE__ */ new Set() : new Set(getConfiguredOpencodeModels(model));
11388
11448
  const eventController = new AbortController();
11389
11449
  this.eventAbortController = eventController;
11390
11450
  this.eventSubscriptionReady = new Promise((resolve4) => {
@@ -11417,7 +11477,7 @@ var OpencodeManager = class extends CodingAgentManager {
11417
11477
  const result = await client.session.create({
11418
11478
  directory: this.workingDirectory,
11419
11479
  agent,
11420
- model: { providerID: "openrouter", id: model, ...variant ? { variant } : {} }
11480
+ model: { providerID: this.providerId, id: model, ...variant ? { variant } : {} }
11421
11481
  }, { throwOnError: true });
11422
11482
  const session = result.data;
11423
11483
  this.sessionId = session.id;
@@ -11433,7 +11493,7 @@ var OpencodeManager = class extends CodingAgentManager {
11433
11493
  { throwOnError: true }
11434
11494
  );
11435
11495
  for (const candidate of result.data.data) {
11436
- if (candidate.providerID === "openrouter") {
11496
+ if (candidate.providerID === this.providerId) {
11437
11497
  this.modelVariants.set(candidate.id, new Set(candidate.variants.map((variant) => variant.id)));
11438
11498
  }
11439
11499
  }
@@ -11457,9 +11517,10 @@ var OpencodeManager = class extends CodingAgentManager {
11457
11517
  this.forwardedLinearPartKeys.clear();
11458
11518
  try {
11459
11519
  const client = await this.ensureClient(model);
11520
+ const providerModel = this.providerId === OPENCODE_GO_PROVIDER ? getOpenCodeGoModel(model) : model;
11460
11521
  const agent = request.planMode ? "plan" : "build";
11461
- const variant = await this.getThinkingVariant(client, model, request.thinkingLevel);
11462
- const sessionId = await this.ensureSession(client, model, agent, variant);
11522
+ const variant = await this.getThinkingVariant(client, providerModel, request.thinkingLevel);
11523
+ const sessionId = await this.ensureSession(client, providerModel, agent, variant);
11463
11524
  const system = this.buildCombinedInstructions(request.customInstructions);
11464
11525
  this.recordHistoryEvent("event_msg", {
11465
11526
  type: "user_message",
@@ -11469,7 +11530,7 @@ var OpencodeManager = class extends CodingAgentManager {
11469
11530
  sessionID: sessionId,
11470
11531
  directory: this.workingDirectory,
11471
11532
  agent,
11472
- model: { providerID: "openrouter", modelID: model },
11533
+ model: { providerID: this.providerId, modelID: providerModel },
11473
11534
  ...variant ? { variant } : {},
11474
11535
  ...system ? { system } : {},
11475
11536
  parts: [{ type: "text", text: request.message }]
@@ -11921,7 +11982,7 @@ var PiManager = class extends CodingAgentManager {
11921
11982
 
11922
11983
  // src/managers/relay-tools.ts
11923
11984
  import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
11924
- import { z } from "zod";
11985
+ import { z as z3 } from "zod";
11925
11986
 
11926
11987
  // src/managers/relay-providers.ts
11927
11988
  function getAvailableRelayProviders(availability) {
@@ -12033,7 +12094,7 @@ function buildSpawnAgentTool(parentChatId, availability = {}) {
12033
12094
  const cursorAvailable = availability.cursorAvailable ?? false;
12034
12095
  const opencodeAvailable = availability.opencodeAvailable ?? false;
12035
12096
  const availableProviders = getAvailableRelayProviders(availability);
12036
- const providerEnum = z.enum(availableProviders);
12097
+ const providerEnum = z3.enum(availableProviders);
12037
12098
  const codeProviders = getAvailableCodeProviders(availability);
12038
12099
  const providerDesc = codeProviders.length > 0 ? `Which agent to use. Prefer ${codeProviders.join(" or ")} for code writing, claude for exploration/analysis, relay for complex multi-step orchestration.` : "Which agent to use. Use claude for code writing, exploration, and analysis. Use relay for complex multi-step orchestration.";
12039
12100
  const useCases = codeProviders.length > 0 ? `- Complex code writing tasks (use provider '${codeProviders.join("' or '")}' with a capable model)
@@ -12052,18 +12113,18 @@ The tool blocks until the subagent completes and returns its final response.
12052
12113
  You will also receive the chatId so you can send follow-up messages or clean up the chat.`,
12053
12114
  {
12054
12115
  provider: providerEnum.describe(providerDesc),
12055
- prompt: z.string().describe("The full prompt/instructions for the subagent. Be detailed - it has no context from your conversation."),
12056
- model: z.string().optional().describe([
12116
+ prompt: z3.string().describe("The full prompt/instructions for the subagent. Be detailed - it has no context from your conversation."),
12117
+ model: z3.string().optional().describe([
12057
12118
  `Model override. Claude: ${AGENT_MODELS.claude.join(", ")} (opus is the default; sonnet is faster).`,
12058
12119
  codexAvailable ? `Codex: ${AGENT_MODELS.codex.join(", ")}.` : null,
12059
12120
  cursorAvailable ? `Cursor: ${AGENT_MODELS.cursor.join(", ")}.` : null,
12060
12121
  opencodeAvailable ? `Opencode: ${AGENT_MODELS.opencode.join(", ")}.` : null
12061
12122
  ].filter(Boolean).join(" ")),
12062
- thinking_level: z.enum(VALID_THINKING_LEVELS).optional().describe(
12123
+ thinking_level: z3.enum(VALID_THINKING_LEVELS).optional().describe(
12063
12124
  "Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort. Defaults: Claude = high, Codex = medium, Cursor = medium, Opencode = medium."
12064
12125
  ),
12065
- title: z.string().optional().describe("Optional title for the subagent chat (for identification)."),
12066
- timeout_minutes: z.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
12126
+ title: z3.string().optional().describe("Optional title for the subagent chat (for identification)."),
12127
+ timeout_minutes: z3.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
12067
12128
  },
12068
12129
  async (args) => {
12069
12130
  try {
@@ -12124,13 +12185,13 @@ var messageAgentTool = tool(
12124
12185
 
12125
12186
  The tool blocks until the subagent completes and returns its response.`,
12126
12187
  {
12127
- chatId: z.string().describe("The chat ID of the subagent (returned by spawn_agent)."),
12128
- message: z.string().describe("The follow-up message to send."),
12129
- model: z.string().optional().describe("Optional model override for this message."),
12130
- thinking_level: z.enum(VALID_THINKING_LEVELS).optional().describe(
12188
+ chatId: z3.string().describe("The chat ID of the subagent (returned by spawn_agent)."),
12189
+ message: z3.string().describe("The follow-up message to send."),
12190
+ model: z3.string().optional().describe("Optional model override for this message."),
12191
+ thinking_level: z3.enum(VALID_THINKING_LEVELS).optional().describe(
12131
12192
  "Controls how much thinking/reasoning the subagent applies. low = light thinking, medium = moderate, high = deep reasoning, xhigh = extended effort, max = maximum effort. Defaults: Claude = high, Codex = medium, Cursor = medium, Opencode = medium."
12132
12193
  ),
12133
- timeout_minutes: z.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
12194
+ timeout_minutes: z3.number().positive().optional().describe("Timeout in minutes for the subagent to complete (default: 10). Set higher for large tasks to avoid losing work.")
12134
12195
  },
12135
12196
  async (args) => {
12136
12197
  try {
@@ -12168,7 +12229,7 @@ var deleteAgentTool = tool(
12168
12229
  "delete_agent",
12169
12230
  `Delete a subagent chat to free resources. Use this after a subagent has completed its work and you no longer need to send it follow-up messages.`,
12170
12231
  {
12171
- chatId: z.string().describe("The chat ID of the subagent to delete.")
12232
+ chatId: z3.string().describe("The chat ID of the subagent to delete.")
12172
12233
  },
12173
12234
  async (args) => {
12174
12235
  try {
@@ -12846,17 +12907,17 @@ async function flushRepoState() {
12846
12907
  // src/services/chat/chat-service.ts
12847
12908
  var CHAT_SENDERS_DIR = join22(ENGINE_DIR2, "chat-senders");
12848
12909
  var CODEX_AUTH_PATH2 = join22(homedir15(), ".codex", "auth.json");
12849
- var OPENCODE_AUTH_PATH2 = join22(homedir15(), ".local", "share", "opencode", "auth.json");
12910
+ var OPENCODE_AUTH_PATH3 = join22(homedir15(), ".local", "share", "opencode", "auth.json");
12850
12911
  var CHATS_BACKUP_FILE = `${CHATS_FILE}.bak`;
12851
12912
  function isChatMessageSender(value) {
12852
12913
  if (!isRecord4(value)) return false;
12853
12914
  return typeof value.senderUserId === "string" && typeof value.senderEmail === "string" && typeof value.recordedAt === "string";
12854
12915
  }
12855
12916
  function isCodexAvailable() {
12856
- return existsSync7(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
12917
+ return existsSync8(CODEX_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENAI_API_KEY);
12857
12918
  }
12858
12919
  function isOpencodeAvailable() {
12859
- return existsSync7(OPENCODE_AUTH_PATH2) || Boolean(ENGINE_ENV.OPENROUTER_API_KEY);
12920
+ return existsSync8(OPENCODE_AUTH_PATH3) || Boolean(ENGINE_ENV.OPENROUTER_API_KEY);
12860
12921
  }
12861
12922
  function isPiAvailable() {
12862
12923
  return Boolean(ENGINE_ENV.OPENROUTER_API_KEY);
@@ -13942,14 +14003,14 @@ var RepoFileService = class {
13942
14003
 
13943
14004
  // src/v1-routes.ts
13944
14005
  import { Hono } from "hono";
13945
- import { z as z2 } from "zod";
14006
+ import { z as z4 } from "zod";
13946
14007
  import { readdir as readdir9, stat as stat5, readFile as readFile18 } from "fs/promises";
13947
14008
  import { join as join26, resolve as resolve3 } from "path";
13948
14009
 
13949
14010
  // src/services/warm-hooks-service.ts
13950
14011
  import { spawn as spawn4 } from "child_process";
13951
14012
  import { readFile as readFile17 } from "fs/promises";
13952
- import { existsSync as existsSync8 } from "fs";
14013
+ import { existsSync as existsSync9 } from "fs";
13953
14014
  import { join as join25 } from "path";
13954
14015
 
13955
14016
  // src/services/warm-hook-logs-service.ts
@@ -14071,7 +14132,7 @@ var warmHookLogsService = new WarmHookLogsService();
14071
14132
  async function readRepoWarmHook(repoPath) {
14072
14133
  for (const filename of REPLICAS_CONFIG_FILENAMES) {
14073
14134
  const configPath = join25(repoPath, filename);
14074
- if (!existsSync8(configPath)) {
14135
+ if (!existsSync9(configPath)) {
14075
14136
  continue;
14076
14137
  }
14077
14138
  try {
@@ -14332,7 +14393,7 @@ ${combinedScript}` : combinedScript;
14332
14393
 
14333
14394
  // src/services/terminal-service.ts
14334
14395
  import { randomUUID as randomUUID6 } from "crypto";
14335
- import { existsSync as existsSync9 } from "fs";
14396
+ import { existsSync as existsSync10 } from "fs";
14336
14397
  import { spawn as spawn5 } from "node-pty";
14337
14398
  var MAX_REPLAY_CHARS = 1024 * 1024;
14338
14399
  var MAX_TERMINAL_SESSIONS = 8;
@@ -14351,7 +14412,7 @@ var TerminalService = class {
14351
14412
  });
14352
14413
  }
14353
14414
  const id = randomUUID6();
14354
- const shell = process.env.SHELL && existsSync9(process.env.SHELL) ? process.env.SHELL : "/bin/bash";
14415
+ const shell = process.env.SHELL && existsSync10(process.env.SHELL) ? process.env.SHELL : "/bin/bash";
14355
14416
  const pty = spawn5(shell, ["-l"], {
14356
14417
  name: "xterm-256color",
14357
14418
  cols,
@@ -14450,67 +14511,67 @@ var TerminalService = class {
14450
14511
  var terminalService = new TerminalService();
14451
14512
 
14452
14513
  // src/v1-routes.ts
14453
- var setWorkspaceNameSchema = z2.object({
14454
- name: z2.string().min(1).max(48)
14514
+ var setWorkspaceNameSchema = z4.object({
14515
+ name: z4.string().min(1).max(48)
14455
14516
  });
14456
- var createChatSchema = z2.object({
14457
- provider: z2.enum(["claude", "codex", "cursor", "opencode", "pi", "relay"]),
14458
- title: z2.string().min(1).optional(),
14459
- parentChatId: z2.string().uuid().optional(),
14460
- clientRequestId: z2.string().min(1).max(128).optional()
14517
+ var createChatSchema = z4.object({
14518
+ provider: z4.enum(["claude", "codex", "cursor", "opencode", "pi", "relay"]),
14519
+ title: z4.string().min(1).optional(),
14520
+ parentChatId: z4.string().uuid().optional(),
14521
+ clientRequestId: z4.string().min(1).max(128).optional()
14461
14522
  });
14462
- var imageMediaTypeSchema = z2.enum(IMAGE_MEDIA_TYPES);
14463
- var createPreviewSchema = z2.object({
14464
- port: z2.number().int().min(1).max(65535),
14465
- publicUrl: z2.string().min(1)
14523
+ var imageMediaTypeSchema = z4.enum(IMAGE_MEDIA_TYPES);
14524
+ var createPreviewSchema = z4.object({
14525
+ port: z4.number().int().min(1).max(65535),
14526
+ publicUrl: z4.string().min(1)
14466
14527
  });
14467
- var terminalSizeSchema = z2.object({
14468
- cols: z2.number().int().min(2).max(500),
14469
- rows: z2.number().int().min(1).max(200)
14528
+ var terminalSizeSchema = z4.object({
14529
+ cols: z4.number().int().min(2).max(500),
14530
+ rows: z4.number().int().min(1).max(200)
14470
14531
  });
14471
- var writeTerminalSessionSchema = z2.object({
14472
- data: z2.string().max(64 * 1024),
14473
- generation: z2.number().int().nonnegative(),
14474
- sequence: z2.number().int().nonnegative()
14532
+ var writeTerminalSessionSchema = z4.object({
14533
+ data: z4.string().max(64 * 1024),
14534
+ generation: z4.number().int().nonnegative(),
14535
+ sequence: z4.number().int().nonnegative()
14475
14536
  });
14476
- var sendMessageSchema = z2.object({
14477
- message: z2.string().min(1),
14478
- model: z2.string().optional(),
14479
- customInstructions: z2.string().optional(),
14480
- planMode: z2.boolean().optional(),
14481
- images: z2.array(z2.object({
14482
- type: z2.literal("image"),
14483
- source: z2.union([
14484
- z2.object({
14485
- type: z2.literal("base64"),
14537
+ var sendMessageSchema = z4.object({
14538
+ message: z4.string().min(1),
14539
+ model: z4.string().optional(),
14540
+ customInstructions: z4.string().optional(),
14541
+ planMode: z4.boolean().optional(),
14542
+ images: z4.array(z4.object({
14543
+ type: z4.literal("image"),
14544
+ source: z4.union([
14545
+ z4.object({
14546
+ type: z4.literal("base64"),
14486
14547
  media_type: imageMediaTypeSchema,
14487
- data: z2.string().min(1)
14548
+ data: z4.string().min(1)
14488
14549
  }),
14489
- z2.object({
14490
- type: z2.literal("url"),
14491
- url: z2.string().url()
14550
+ z4.object({
14551
+ type: z4.literal("url"),
14552
+ url: z4.string().url()
14492
14553
  })
14493
14554
  ])
14494
14555
  })).optional(),
14495
- thinkingLevel: z2.enum(VALID_THINKING_LEVELS).optional(),
14496
- goalMode: z2.boolean().optional(),
14497
- fastMode: z2.boolean().optional(),
14498
- enableInteractiveTools: z2.boolean().optional(),
14499
- type: z2.string().min(1).optional(),
14500
- merge: z2.boolean().optional(),
14501
- idempotencyKey: z2.string().min(1).max(128).optional(),
14502
- senderUserId: z2.string().optional(),
14503
- senderEmail: z2.string().optional(),
14504
- senderDisplayName: z2.string().optional(),
14505
- senderAvatarUrl: z2.string().optional()
14556
+ thinkingLevel: z4.enum(VALID_THINKING_LEVELS).optional(),
14557
+ goalMode: z4.boolean().optional(),
14558
+ fastMode: z4.boolean().optional(),
14559
+ enableInteractiveTools: z4.boolean().optional(),
14560
+ type: z4.string().min(1).optional(),
14561
+ merge: z4.boolean().optional(),
14562
+ idempotencyKey: z4.string().min(1).max(128).optional(),
14563
+ senderUserId: z4.string().optional(),
14564
+ senderEmail: z4.string().optional(),
14565
+ senderDisplayName: z4.string().optional(),
14566
+ senderAvatarUrl: z4.string().optional()
14506
14567
  });
14507
- var respondToolInputSchema = z2.object({
14508
- requestId: z2.string().min(1),
14509
- selectionId: z2.string().min(1)
14568
+ var respondToolInputSchema = z4.object({
14569
+ requestId: z4.string().min(1),
14570
+ selectionId: z4.string().min(1)
14510
14571
  });
14511
- var updateGoalSchema = z2.object({
14512
- objective: z2.string().trim().min(1).max(MAX_CODEX_GOAL_OBJECTIVE_CHARS).optional(),
14513
- status: z2.enum(["active", "paused"]).optional()
14572
+ var updateGoalSchema = z4.object({
14573
+ objective: z4.string().trim().min(1).max(MAX_CODEX_GOAL_OBJECTIVE_CHARS).optional(),
14574
+ status: z4.enum(["active", "paused"]).optional()
14514
14575
  }).refine((body) => body.objective !== void 0 || body.status !== void 0, {
14515
14576
  message: "Goal objective or status required"
14516
14577
  });
@@ -14701,7 +14762,7 @@ function createV1Routes(deps) {
14701
14762
  const result = await deps.chatService.updateGoal(c.req.param("chatId"), body);
14702
14763
  return c.json(result);
14703
14764
  } catch (error) {
14704
- if (error instanceof z2.ZodError) {
14765
+ if (error instanceof z4.ZodError) {
14705
14766
  return c.json(jsonError(error.issues[0]?.message || "Invalid goal update"), 400);
14706
14767
  }
14707
14768
  if (error instanceof ChatNotFoundError) {
@@ -15411,6 +15472,11 @@ var heartbeatService = new HeartbeatService();
15411
15472
  // src/index.ts
15412
15473
  var startupStartedAt = performance.now();
15413
15474
  var startupTimings = {};
15475
+ var resolveEngineReady = () => {
15476
+ };
15477
+ var engineReadyPromise = new Promise((resolve4) => {
15478
+ resolveEngineReady = resolve4;
15479
+ });
15414
15480
  async function timeStartupStep(name, fn) {
15415
15481
  const startedAt = performance.now();
15416
15482
  try {
@@ -15480,7 +15546,16 @@ var authMiddleware = async (c, next) => {
15480
15546
  await next();
15481
15547
  };
15482
15548
  var chatService = new ChatService(gitService.getWorkspaceRoot());
15483
- app.get("/health", (c) => {
15549
+ app.get("/health", async (c) => {
15550
+ const requestedWaitMs = Number(c.req.query(ENGINE_HEALTH_WAIT_QUERY_PARAM));
15551
+ const waitMs = Number.isFinite(requestedWaitMs) ? Math.min(Math.max(requestedWaitMs, 0), ENGINE_HEALTH_MAX_WAIT_MS) : 0;
15552
+ if (!engineReady && waitMs > 0) {
15553
+ await Promise.race([
15554
+ engineReadyPromise,
15555
+ new Promise((resolve4) => setTimeout(resolve4, waitMs))
15556
+ ]);
15557
+ }
15558
+ c.header(ENGINE_HEALTH_WAIT_HEADER, "1");
15484
15559
  const response = {
15485
15560
  status: engineReady ? "active" : "initializing",
15486
15561
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -15669,6 +15744,7 @@ serve(
15669
15744
  await timeStartupStep("github_token_initialize", () => githubTokenManager.start());
15670
15745
  }
15671
15746
  engineReady = true;
15747
+ resolveEngineReady();
15672
15748
  void registerDesktopPreview();
15673
15749
  heartbeatService.start(bootTimeMs);
15674
15750
  if (!IS_WARMING_MODE) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.452",
3
+ "version": "0.1.454",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",