@jacobbd/relay-ai 0.9.3 → 0.9.5

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.
@@ -11,7 +11,7 @@ import { join } from "path";
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@jacobbd/relay-ai",
14
- version: "0.9.3",
14
+ version: "0.9.5",
15
15
  publishConfig: {
16
16
  access: "public"
17
17
  },
@@ -1693,10 +1693,86 @@ function thinkingProviderOptions(npm) {
1693
1693
  }
1694
1694
 
1695
1695
  // src/codex/multi-agent.ts
1696
- import { execFileSync } from "child_process";
1697
1696
  import { mkdtempSync, rmSync, writeFileSync } from "fs";
1698
1697
  import { tmpdir } from "os";
1699
1698
  import { join as join2 } from "path";
1699
+
1700
+ // src/codex/process.ts
1701
+ import spawn from "cross-spawn";
1702
+ function commandError(binaryPath, args, stdout, stderr, detail) {
1703
+ const error = new Error(`Command failed: ${binaryPath} ${args.join(" ")} (${detail})`);
1704
+ return Object.assign(error, { stdout, stderr });
1705
+ }
1706
+ function runCodexCommandSync(binaryPath, args, options = {}) {
1707
+ const result = spawn.sync(binaryPath, args, {
1708
+ encoding: "utf8",
1709
+ stdio: ["ignore", "pipe", "pipe"],
1710
+ env: options.env,
1711
+ timeout: options.timeout,
1712
+ maxBuffer: options.maxBuffer
1713
+ });
1714
+ const stdout = result.stdout ?? "";
1715
+ const stderr = result.stderr ?? "";
1716
+ if (result.error) {
1717
+ throw Object.assign(result.error, { stdout, stderr });
1718
+ }
1719
+ if (result.status !== 0) {
1720
+ throw commandError(binaryPath, args, stdout, stderr, `exit ${result.status ?? result.signal ?? "unknown"}`);
1721
+ }
1722
+ return { stdout, stderr };
1723
+ }
1724
+ function runCodexCommand(binaryPath, args, options = {}) {
1725
+ return new Promise((resolve, reject) => {
1726
+ const child = spawn(binaryPath, args, {
1727
+ stdio: ["ignore", "pipe", "pipe"],
1728
+ env: options.env
1729
+ });
1730
+ const stdoutChunks = [];
1731
+ const stderrChunks = [];
1732
+ let outputBytes = 0;
1733
+ let settled = false;
1734
+ const finishError = (error) => {
1735
+ if (settled) return;
1736
+ settled = true;
1737
+ reject(Object.assign(error, {
1738
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
1739
+ stderr: Buffer.concat(stderrChunks).toString("utf8")
1740
+ }));
1741
+ };
1742
+ const collect = (target, chunk) => {
1743
+ target.push(chunk);
1744
+ outputBytes += chunk.length;
1745
+ if (options.maxBuffer !== void 0 && outputBytes > options.maxBuffer) {
1746
+ child.kill();
1747
+ finishError(commandError(binaryPath, args, "", "", `output exceeded ${options.maxBuffer} bytes`));
1748
+ }
1749
+ };
1750
+ child.stdout?.on("data", (chunk) => collect(stdoutChunks, chunk));
1751
+ child.stderr?.on("data", (chunk) => collect(stderrChunks, chunk));
1752
+ child.on("error", finishError);
1753
+ let timer;
1754
+ if (options.timeout !== void 0) {
1755
+ timer = setTimeout(() => {
1756
+ child.kill();
1757
+ finishError(commandError(binaryPath, args, "", "", `timed out after ${options.timeout}ms`));
1758
+ }, options.timeout);
1759
+ }
1760
+ child.on("close", (code, signal) => {
1761
+ if (timer) clearTimeout(timer);
1762
+ if (settled) return;
1763
+ const stdout = Buffer.concat(stdoutChunks).toString("utf8");
1764
+ const stderr = Buffer.concat(stderrChunks).toString("utf8");
1765
+ if (code !== 0) {
1766
+ finishError(commandError(binaryPath, args, stdout, stderr, `exit ${code ?? signal ?? "unknown"}`));
1767
+ return;
1768
+ }
1769
+ settled = true;
1770
+ resolve({ stdout, stderr });
1771
+ });
1772
+ });
1773
+ }
1774
+
1775
+ // src/codex/multi-agent.ts
1700
1776
  var CODEX_MULTI_AGENT_V2 = Object.freeze({
1701
1777
  enabled: true,
1702
1778
  max_concurrent_threads_per_session: 6,
@@ -1711,12 +1787,7 @@ function probeText(value) {
1711
1787
  return `${result.stdout ?? ""}
1712
1788
  ${result.stderr ?? ""}`;
1713
1789
  }
1714
- function supportsMultiAgentV2(binaryPath, run3 = (path, args, env) => execFileSync(path, args, {
1715
- encoding: "utf8",
1716
- stdio: ["ignore", "pipe", "pipe"],
1717
- timeout: 1e4,
1718
- env
1719
- })) {
1790
+ function supportsMultiAgentV2(binaryPath, run3 = (path, args, env) => runCodexCommandSync(path, args, { timeout: 1e4, env })) {
1720
1791
  const probeHome = mkdtempSync(join2(tmpdir(), "relay-codex-v2-probe-"));
1721
1792
  try {
1722
1793
  writeFileSync(join2(probeHome, "config.toml"), renderMultiAgentV2Feature(), { encoding: "utf8", mode: 384 });
@@ -2410,18 +2481,18 @@ function resolveServerAutostart(env = process.env) {
2410
2481
 
2411
2482
  // src/launch.ts
2412
2483
  import { execSync } from "child_process";
2413
- import spawn from "cross-spawn";
2484
+ import spawn2 from "cross-spawn";
2414
2485
  import { existsSync as existsSync3, appendFileSync } from "fs";
2415
2486
  import { homedir as homedir3 } from "os";
2416
2487
  import { join as join5 } from "path";
2417
2488
 
2418
2489
  // src/binary-lookup.ts
2419
- import { execFileSync as execFileSync2 } from "child_process";
2490
+ import { execFileSync } from "child_process";
2420
2491
  import { existsSync as existsSync2 } from "fs";
2421
2492
  function findBinaryOnPath(name, fallbackPaths, options = {}) {
2422
2493
  const isWindows2 = options.isWindows ?? process.platform === "win32";
2423
2494
  const exists = options.exists ?? existsSync2;
2424
- const runWhich = options.runWhich ?? ((binary, win) => execFileSync2(win ? "where.exe" : "which", [binary], {
2495
+ const runWhich = options.runWhich ?? ((binary, win) => execFileSync(win ? "where.exe" : "which", [binary], {
2425
2496
  encoding: "utf8",
2426
2497
  stdio: ["pipe", "pipe", "pipe"]
2427
2498
  }));
@@ -2499,7 +2570,7 @@ function launchClaude(env, model, extraArgs) {
2499
2570
  process.stdout.write = originalStdoutWrite;
2500
2571
  process.stderr.write = originalStderrWrite;
2501
2572
  };
2502
- const child = spawn(claudePath, args, {
2573
+ const child = spawn2(claudePath, args, {
2503
2574
  stdio: "inherit",
2504
2575
  env
2505
2576
  });
@@ -3746,8 +3817,11 @@ function buildChildEnv(baseUrl, model, apiKey, proxyPort, contextWindow2, enable
3746
3817
  env["ANTHROPIC_API_KEY"] = apiKey;
3747
3818
  const bareModel = stripOneMContextSuffix(model);
3748
3819
  env["ANTHROPIC_MODEL"] = claudeCodeClientModelId(model, contextWindow2);
3749
- env["CLAUDE_CODE_MAX_CONTEXT_TOKENS"] = String(resolveContextWindow(bareModel, contextWindow2));
3820
+ if (!enableGatewayDiscovery) {
3821
+ env["CLAUDE_CODE_MAX_CONTEXT_TOKENS"] = String(resolveContextWindow(bareModel, contextWindow2));
3822
+ }
3750
3823
  if (enableGatewayDiscovery) {
3824
+ delete env["CLAUDE_CODE_MAX_CONTEXT_TOKENS"];
3751
3825
  env["CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"] = "1";
3752
3826
  }
3753
3827
  applyClaudeCodeThirdPartyCompat(env);
@@ -5138,9 +5212,9 @@ function claudeModelFamily(modelId) {
5138
5212
  if (!normalized.startsWith("claude-")) return void 0;
5139
5213
  return CLAUDE_MODEL_FAMILIES.find((family) => normalized.includes(family));
5140
5214
  }
5141
- function isClaudeAgentTool(tool4) {
5142
- if (tool4.name !== "Agent" || !isRecord2(tool4.input_schema)) return false;
5143
- const properties = tool4.input_schema.properties;
5215
+ function isClaudeAgentTool(tool3) {
5216
+ if (tool3.name !== "Agent" || !isRecord2(tool3.input_schema)) return false;
5217
+ const properties = tool3.input_schema.properties;
5144
5218
  if (!isRecord2(properties)) return false;
5145
5219
  return ["description", "prompt", "subagent_type"].every((name) => isRecord2(properties[name]));
5146
5220
  }
@@ -5230,8 +5304,8 @@ function prepareClaudeAgentInput(input, routing) {
5230
5304
  clientInput.prompt = appendSubagentRouteMarker(prompt, token);
5231
5305
  return { input: clientInput, decision };
5232
5306
  }
5233
- function augmentClaudeAgentTool(tool4, routing) {
5234
- const inputSchema = isRecord2(tool4.input_schema) ? tool4.input_schema : {};
5307
+ function augmentClaudeAgentTool(tool3, routing) {
5308
+ const inputSchema = isRecord2(tool3.input_schema) ? tool3.input_schema : {};
5235
5309
  const properties = isRecord2(inputSchema.properties) ? inputSchema.properties : {};
5236
5310
  const originalModel = isRecord2(properties.model) ? properties.model : {};
5237
5311
  const smallCatalog = routing.models.length <= MAX_MODEL_CATALOG;
@@ -5247,8 +5321,8 @@ function augmentClaudeAgentTool(tool4, routing) {
5247
5321
  }
5248
5322
  const guidance = smallCatalog ? `Relay AI subagent model routing (default: ${routing.parentModelId}). ` + routing.models.map((model) => `${model.displayName}: ${model.id}`).join("; ") : `Relay AI subagent model routing (default: ${routing.parentModelId}). Other explicit model values must be exact ids from the current session catalog.`;
5249
5323
  return {
5250
- ...tool4,
5251
- description: [tool4.description?.trim(), guidance].filter(Boolean).join("\n\n"),
5324
+ ...tool3,
5325
+ description: [tool3.description?.trim(), guidance].filter(Boolean).join("\n\n"),
5252
5326
  input_schema: {
5253
5327
  ...inputSchema,
5254
5328
  properties: {
@@ -5580,11 +5654,7 @@ async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWant
5580
5654
  }
5581
5655
 
5582
5656
  // src/antigravity/anthropic-to-cloudcode.ts
5583
- import { randomUUID as randomUUID4 } from "crypto";
5584
-
5585
- // src/antigravity/request-adapter.ts
5586
5657
  import { randomUUID as randomUUID3 } from "crypto";
5587
- import { tool, jsonSchema } from "ai";
5588
5658
 
5589
5659
  // src/proxy-shared.ts
5590
5660
  function grabRoundTripSignature(part) {
@@ -5692,265 +5762,6 @@ function serializeToolResultContent(content) {
5692
5762
  return JSON.stringify(content);
5693
5763
  }
5694
5764
 
5695
- // src/antigravity/request-adapter.ts
5696
- var UNSUPPORTED_VOICE_MESSAGE = "Voice transcription isn\u2019t supported by Relay AI yet. Please type your message. Your coding session remains active.";
5697
- var OMITTED_VOICE_TEXT = "[Voice recording omitted because transcription is not supported by Relay AI.]";
5698
- function isSupportedImage(part) {
5699
- return part.inlineData?.mimeType.toLowerCase().startsWith("image/") ?? false;
5700
- }
5701
- function isUnsupportedInlineData(part) {
5702
- return !!part.inlineData && !isSupportedImage(part);
5703
- }
5704
- function sanitizeUnsupportedInlineData(ccReq) {
5705
- const contents = ccReq.request?.contents ?? [];
5706
- let latestUserIndex = -1;
5707
- for (let i = contents.length - 1; i >= 0; i--) {
5708
- if (contents[i].role === "user") {
5709
- latestUserIndex = i;
5710
- break;
5711
- }
5712
- }
5713
- let latestUserTurnHasUnsupportedMedia = false;
5714
- const sanitizedContents = contents.map((message, index) => ({
5715
- ...message,
5716
- parts: message.parts.map((part) => {
5717
- if (!isUnsupportedInlineData(part)) return part;
5718
- if (index === latestUserIndex) latestUserTurnHasUnsupportedMedia = true;
5719
- return { text: OMITTED_VOICE_TEXT };
5720
- })
5721
- }));
5722
- return {
5723
- request: {
5724
- ...ccReq,
5725
- request: {
5726
- ...ccReq.request,
5727
- contents: sanitizedContents
5728
- }
5729
- },
5730
- latestUserTurnHasUnsupportedMedia
5731
- };
5732
- }
5733
- function tracePartChars(part) {
5734
- if (typeof part.text === "string") return part.text.length;
5735
- if (part.type !== "tool-result") return void 0;
5736
- const output = part.output;
5737
- if (typeof output === "string") return output.length;
5738
- if (output && typeof output === "object" && typeof output.value === "string") {
5739
- return output.value.length;
5740
- }
5741
- try {
5742
- return output === void 0 ? void 0 : JSON.stringify(output).length;
5743
- } catch {
5744
- return void 0;
5745
- }
5746
- }
5747
- function summarizeSdkRequestForTrace(request) {
5748
- const messages = request.messages.map((message) => {
5749
- const content = message.content;
5750
- if (typeof content === "string") {
5751
- return { role: message.role, parts: [{ type: "text", chars: content.length }] };
5752
- }
5753
- const parts = Array.isArray(content) ? content.map((rawPart) => {
5754
- const part = rawPart;
5755
- const summary = {
5756
- type: typeof part.type === "string" ? part.type : typeof rawPart
5757
- };
5758
- const chars = tracePartChars(part);
5759
- if (chars !== void 0) summary.chars = chars;
5760
- if (typeof part.toolName === "string") summary.toolName = part.toolName;
5761
- if (typeof part.toolCallId === "string") summary.toolCallId = part.toolCallId;
5762
- return summary;
5763
- }) : [{ type: typeof content }];
5764
- return { role: message.role, parts };
5765
- });
5766
- return {
5767
- systemChars: request.system?.length ?? 0,
5768
- messages,
5769
- toolNames: Object.keys(request.tools ?? {}),
5770
- ...request.toolChoice ? { toolChoice: request.toolChoice } : {}
5771
- };
5772
- }
5773
- var JSON_SCHEMA_TYPES = /* @__PURE__ */ new Map([
5774
- ["ARRAY", "array"],
5775
- ["BOOLEAN", "boolean"],
5776
- ["INTEGER", "integer"],
5777
- ["NULL", "null"],
5778
- ["NUMBER", "number"],
5779
- ["OBJECT", "object"],
5780
- ["STRING", "string"]
5781
- ]);
5782
- function expandTextWithThinking(text4) {
5783
- if (!text4.includes("<thinking>")) {
5784
- return [{ type: "text", text: text4 }];
5785
- }
5786
- const out = [];
5787
- const tokens = text4.split(/<thinking>([\s\S]*?)<\/thinking>/);
5788
- for (let i = 0; i < tokens.length; i++) {
5789
- const token = tokens[i] ?? "";
5790
- if (!token.trim()) continue;
5791
- out.push({ type: i % 2 === 1 ? "reasoning" : "text", text: token });
5792
- }
5793
- return out.length > 0 ? out : [{ type: "text", text: text4 }];
5794
- }
5795
- function normalizeSchemaType(value) {
5796
- if (typeof value === "string") {
5797
- return JSON_SCHEMA_TYPES.get(value) ?? value;
5798
- }
5799
- if (Array.isArray(value)) {
5800
- return value.map(normalizeSchemaType);
5801
- }
5802
- return value;
5803
- }
5804
- function normalizeJsonSchema(value) {
5805
- if (Array.isArray(value)) {
5806
- return value.map(normalizeJsonSchema);
5807
- }
5808
- if (!value || typeof value !== "object") {
5809
- return value;
5810
- }
5811
- return Object.fromEntries(
5812
- Object.entries(value).map(([key, child]) => [
5813
- key,
5814
- key === "type" ? normalizeSchemaType(child) : normalizeJsonSchema(child)
5815
- ])
5816
- );
5817
- }
5818
- function translateTools(ccTools, options = {}) {
5819
- if (!ccTools?.length) return void 0;
5820
- const tools = {};
5821
- let toolCount = 0;
5822
- for (const t of ccTools) {
5823
- if (t.functionDeclarations) {
5824
- for (const fd of t.functionDeclarations) {
5825
- if (options.maxTools !== void 0 && toolCount >= options.maxTools) break;
5826
- tools[fd.name] = tool({
5827
- description: fd.description || "",
5828
- inputSchema: jsonSchema(
5829
- normalizeJsonSchema(fd.parameters || { type: "object", properties: {} })
5830
- )
5831
- });
5832
- toolCount++;
5833
- }
5834
- }
5835
- }
5836
- return Object.keys(tools).length > 0 ? tools : void 0;
5837
- }
5838
- function translateRequest(ccReq, options = {}) {
5839
- const systemInstructions = [];
5840
- const sdkMessages = [];
5841
- const nameToIdList = /* @__PURE__ */ new Map();
5842
- const fallbackAssistantReasoning = [...options.fallbackAssistantReasoning ?? []];
5843
- const request = ccReq.request || {};
5844
- if (request.systemInstruction?.parts) {
5845
- for (const part of request.systemInstruction.parts) {
5846
- if (part.text) {
5847
- systemInstructions.push(part.text);
5848
- }
5849
- }
5850
- }
5851
- const contents = request.contents || [];
5852
- for (const msg of contents) {
5853
- const role = msg.role;
5854
- if (role === "system") {
5855
- for (const part of msg.parts) {
5856
- if (part.text) {
5857
- systemInstructions.push(part.text);
5858
- }
5859
- }
5860
- continue;
5861
- }
5862
- const sdkRole = role === "model" ? "assistant" : "user";
5863
- const hasFunctionCall = msg.parts.some((p8) => p8.functionCall);
5864
- const hasAssistantReasoning = role === "model" && msg.parts.some((p8) => p8.thought || p8.text?.includes("<thinking>"));
5865
- const hasComplexParts = msg.parts.some((p8) => p8.thought || p8.inlineData || p8.functionCall || p8.functionResponse);
5866
- const singleText = msg.parts.length === 1 ? msg.parts[0]?.text : void 0;
5867
- if (!hasComplexParts && singleText !== void 0 && !singleText.includes("<thinking>")) {
5868
- sdkMessages.push({
5869
- role: sdkRole,
5870
- content: singleText
5871
- });
5872
- continue;
5873
- }
5874
- const contentParts = [];
5875
- const toolResults = [];
5876
- if (role === "model" && hasFunctionCall && !hasAssistantReasoning) {
5877
- const fallback = fallbackAssistantReasoning.shift();
5878
- if (fallback?.trim()) {
5879
- contentParts.push({ type: "reasoning", text: fallback });
5880
- }
5881
- }
5882
- for (const part of msg.parts) {
5883
- if (part.text !== void 0) {
5884
- if (part.thought) {
5885
- contentParts.push({ type: "reasoning", text: part.text });
5886
- } else {
5887
- for (const piece of expandTextWithThinking(part.text)) {
5888
- contentParts.push(piece);
5889
- }
5890
- }
5891
- } else if (part.inlineData) {
5892
- if (isSupportedImage(part)) {
5893
- contentParts.push({
5894
- type: "image",
5895
- image: part.inlineData.data,
5896
- mimeType: part.inlineData.mimeType
5897
- });
5898
- } else {
5899
- contentParts.push({ type: "text", text: OMITTED_VOICE_TEXT });
5900
- }
5901
- } else if (part.functionCall) {
5902
- const id = "call_" + randomUUID3().replace(/-/g, "");
5903
- const name = part.functionCall.name;
5904
- if (!nameToIdList.has(name)) nameToIdList.set(name, []);
5905
- nameToIdList.get(name).push(id);
5906
- contentParts.push({
5907
- type: "tool-call",
5908
- toolCallId: id,
5909
- toolName: name,
5910
- input: part.functionCall.args || {}
5911
- });
5912
- } else if (part.functionResponse) {
5913
- const name = part.functionResponse.name;
5914
- const idList = nameToIdList.get(name) || [];
5915
- const id = idList.shift() || "call_" + randomUUID3().replace(/-/g, "");
5916
- toolResults.push({
5917
- type: "tool-result",
5918
- toolCallId: id,
5919
- toolName: name,
5920
- output: { type: "text", value: serializeToolResultContent(part.functionResponse.response) }
5921
- });
5922
- }
5923
- }
5924
- if (toolResults.length > 0) {
5925
- sdkMessages.push({
5926
- role: "tool",
5927
- content: toolResults
5928
- });
5929
- }
5930
- if (contentParts.length > 0) {
5931
- sdkMessages.push({
5932
- role: sdkRole,
5933
- content: contentParts
5934
- });
5935
- }
5936
- }
5937
- const system = systemInstructions.length > 0 ? systemInstructions.join("\n\n") : void 0;
5938
- const tools = translateTools(request.tools, options);
5939
- let toolChoice;
5940
- const mode = request.toolConfig?.functionCallingConfig?.mode;
5941
- if (mode === "ANY") {
5942
- toolChoice = "required";
5943
- } else if (mode === "AUTO" || tools) {
5944
- toolChoice = "auto";
5945
- }
5946
- return {
5947
- system,
5948
- messages: sdkMessages,
5949
- tools,
5950
- toolChoice
5951
- };
5952
- }
5953
-
5954
5765
  // src/antigravity/anthropic-to-cloudcode.ts
5955
5766
  var DEFAULT_SAFETY_SETTINGS = [
5956
5767
  { category: "HARM_CATEGORY_HATE_SPEECH", threshold: "OFF" },
@@ -5960,7 +5771,6 @@ var DEFAULT_SAFETY_SETTINGS = [
5960
5771
  ];
5961
5772
  var ANTIGRAVITY_USER_AGENT2 = "vscode/1.X.X (Antigravity/4.2.0)";
5962
5773
  var MIN_ANTIGRAVITY_OUTPUT_TOKENS = 1024;
5963
- var DISABLE_CLOUD_CODE_THINKING = { thinkingBudget: 0, includeThoughts: false };
5964
5774
  var STRIP_KEYS = /* @__PURE__ */ new Set([
5965
5775
  "$schema",
5966
5776
  "$defs",
@@ -5970,6 +5780,7 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
5970
5780
  "additionalProperties",
5971
5781
  "propertyNames",
5972
5782
  "patternProperties",
5783
+ "prefixItems",
5973
5784
  "title",
5974
5785
  "exclusiveMinimum",
5975
5786
  "exclusiveMaximum",
@@ -6003,15 +5814,105 @@ var STRIP_KEYS = /* @__PURE__ */ new Set([
6003
5814
  "examples",
6004
5815
  "readOnly",
6005
5816
  "writeOnly",
6006
- "deprecated"
5817
+ "deprecated",
5818
+ // Codex app tool schemas can include this internal annotation. It is not a
5819
+ // JSON Schema keyword and Cloud Code's Schema protobuf rejects it.
5820
+ "encrypted"
6007
5821
  ]);
6008
- function stripDraftMeta(obj) {
5822
+ var CLOUD_CODE_SCHEMA_TYPES = /* @__PURE__ */ new Map([
5823
+ ["array", "ARRAY"],
5824
+ ["boolean", "BOOLEAN"],
5825
+ ["integer", "INTEGER"],
5826
+ ["null", "NULL"],
5827
+ ["number", "NUMBER"],
5828
+ ["object", "OBJECT"],
5829
+ ["string", "STRING"]
5830
+ ]);
5831
+ function normalizeCloudCodeSchemaType(value) {
5832
+ if (typeof value === "string") {
5833
+ return CLOUD_CODE_SCHEMA_TYPES.get(value.toLowerCase()) ?? value;
5834
+ }
5835
+ return value;
5836
+ }
5837
+ function isNullSchema(obj) {
5838
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
5839
+ const type = obj.type;
5840
+ return type === "null" || type === "NULL" || Array.isArray(type) && type.every((value) => value === "null" || value === "NULL");
5841
+ }
5842
+ function resolveLocalSchemaRef(ref, root) {
5843
+ if (!ref.startsWith("#/$defs/")) return void 0;
5844
+ const name = ref.slice("#/$defs/".length).replace(/~1/g, "/").replace(/~0/g, "~");
5845
+ const defs = root.$defs;
5846
+ if (!defs || typeof defs !== "object" || Array.isArray(defs)) return void 0;
5847
+ return defs[name];
5848
+ }
5849
+ function stripDraftMeta(obj, root = void 0, resolvingRefs = /* @__PURE__ */ new Set()) {
6009
5850
  if (!obj || typeof obj !== "object") return obj;
6010
- if (Array.isArray(obj)) return obj.map(stripDraftMeta);
5851
+ if (Array.isArray(obj)) return obj.map((value) => stripDraftMeta(value, root, resolvingRefs));
5852
+ const source = obj;
5853
+ const schemaRoot = root ?? source;
5854
+ if (typeof source.$ref === "string") {
5855
+ const resolved = resolveLocalSchemaRef(source.$ref, schemaRoot);
5856
+ if (resolved !== void 0) {
5857
+ if (resolvingRefs.has(source.$ref)) return { type: "OBJECT" };
5858
+ const nextRefs = new Set(resolvingRefs);
5859
+ nextRefs.add(source.$ref);
5860
+ const dereferenced = stripDraftMeta(resolved, schemaRoot, nextRefs);
5861
+ if (dereferenced && typeof dereferenced === "object" && !Array.isArray(dereferenced)) {
5862
+ const siblings = { ...source };
5863
+ delete siblings.$ref;
5864
+ const sanitizedSiblings = stripDraftMeta(siblings, schemaRoot, resolvingRefs);
5865
+ return {
5866
+ ...dereferenced,
5867
+ ...sanitizedSiblings
5868
+ };
5869
+ }
5870
+ return dereferenced;
5871
+ }
5872
+ }
6011
5873
  const out = {};
6012
- for (const [k, v] of Object.entries(obj)) {
5874
+ for (const [k, v] of Object.entries(source)) {
6013
5875
  if (STRIP_KEYS.has(k) || k.startsWith("x-")) continue;
6014
- out[k] = stripDraftMeta(v);
5876
+ if (k === "properties" && v && typeof v === "object" && !Array.isArray(v)) {
5877
+ out.properties = Object.fromEntries(
5878
+ Object.entries(v).map(([name, schema]) => [
5879
+ name,
5880
+ stripDraftMeta(schema, schemaRoot, resolvingRefs)
5881
+ ])
5882
+ );
5883
+ continue;
5884
+ }
5885
+ if (k === "type") {
5886
+ const types = (Array.isArray(v) ? v : [v]).map(normalizeCloudCodeSchemaType).filter((type) => typeof type === "string");
5887
+ const concreteType = types.find((type) => type !== "NULL");
5888
+ out.type = concreteType ?? "STRING";
5889
+ if (types.includes("NULL")) out.nullable = true;
5890
+ continue;
5891
+ }
5892
+ if (k === "enum" && Array.isArray(v)) {
5893
+ out.enum = v.filter((value) => value !== null && value !== void 0).map(String);
5894
+ continue;
5895
+ }
5896
+ if (k === "items" && Array.isArray(v)) {
5897
+ out.items = stripDraftMeta(v[0] ?? {}, schemaRoot, resolvingRefs);
5898
+ continue;
5899
+ }
5900
+ out[k] = stripDraftMeta(v, schemaRoot, resolvingRefs);
5901
+ }
5902
+ const union = Array.isArray(source.anyOf) ? source.anyOf : Array.isArray(source.oneOf) ? source.oneOf : void 0;
5903
+ if (union) {
5904
+ const nullable = union.some(isNullSchema);
5905
+ const alternatives = union.filter((branch) => !isNullSchema(branch)).map((branch) => stripDraftMeta(branch, schemaRoot, resolvingRefs)).filter((branch) => Boolean(branch) && typeof branch === "object" && !Array.isArray(branch));
5906
+ if (alternatives.length === 1) Object.assign(out, alternatives[0], out);
5907
+ else if (alternatives.length > 1) out.anyOf = alternatives;
5908
+ if (nullable) out.nullable = true;
5909
+ }
5910
+ if (!out.type) {
5911
+ if (out.properties && typeof out.properties === "object" && !Array.isArray(out.properties)) {
5912
+ out.type = "OBJECT";
5913
+ } else if (out.items && typeof out.items === "object" && !Array.isArray(out.items)) {
5914
+ out.type = "ARRAY";
5915
+ }
6015
5916
  }
6016
5917
  if (Array.isArray(out.required) && out.properties && typeof out.properties === "object") {
6017
5918
  const props = out.properties;
@@ -6072,15 +5973,18 @@ function extractSystem(system) {
6072
5973
  }
6073
5974
  return void 0;
6074
5975
  }
6075
- function translateTools2(tools) {
5976
+ function translateTools(tools) {
6076
5977
  if (!Array.isArray(tools) || tools.length === 0) return void 0;
6077
5978
  const decls = [];
6078
5979
  for (const t of tools) {
6079
5980
  if (typeof t.name !== "string") continue;
5981
+ const translated = stripDraftMeta(t.input_schema ?? { type: "object", properties: {} });
5982
+ const parameters = translated && typeof translated === "object" && !Array.isArray(translated) ? translated : { type: "OBJECT", properties: {} };
5983
+ if (!parameters.type) parameters.type = "OBJECT";
6080
5984
  decls.push({
6081
5985
  name: t.name,
6082
5986
  description: typeof t.description === "string" ? t.description : "",
6083
- parameters: stripDraftMeta(normalizeJsonSchema(t.input_schema ?? { type: "object", properties: {} }))
5987
+ parameters
6084
5988
  });
6085
5989
  }
6086
5990
  return decls.length > 0 ? [{ functionDeclarations: decls }] : void 0;
@@ -6106,8 +6010,7 @@ function anthropicToCloudCode(body, realModelId, projectId) {
6106
6010
  }
6107
6011
  if (typeof body.temperature === "number") generationConfig.temperature = body.temperature;
6108
6012
  if (typeof body.top_p === "number") generationConfig.topP = body.top_p;
6109
- generationConfig.thinkingConfig = DISABLE_CLOUD_CODE_THINKING;
6110
- const ccTools = translateTools2(body.tools);
6013
+ const ccTools = translateTools(body.tools);
6111
6014
  const systemInstruction = extractSystem(body.system);
6112
6015
  const request = {
6113
6016
  contents,
@@ -6121,7 +6024,7 @@ function anthropicToCloudCode(body, realModelId, projectId) {
6121
6024
  }
6122
6025
  return {
6123
6026
  project: projectId,
6124
- requestId: randomUUID4(),
6027
+ requestId: randomUUID3(),
6125
6028
  model: realModelId,
6126
6029
  userAgent: ANTIGRAVITY_USER_AGENT2,
6127
6030
  requestType: "agent",
@@ -6131,7 +6034,7 @@ function anthropicToCloudCode(body, realModelId, projectId) {
6131
6034
  }
6132
6035
 
6133
6036
  // src/antigravity/cloudcode-to-anthropic.ts
6134
- import { randomUUID as randomUUID5 } from "crypto";
6037
+ import { randomUUID as randomUUID4 } from "crypto";
6135
6038
  function writeEvent(res, event, data) {
6136
6039
  res.write(`event: ${event}
6137
6040
  data: ${JSON.stringify(data)}
@@ -6221,7 +6124,7 @@ function closeBlock(res, state) {
6221
6124
  }
6222
6125
  async function streamCloudCodeToAnthropic(res, upstreamRes, model, log7) {
6223
6126
  const state = {
6224
- messageId: `msg_${randomUUID5().replace(/-/g, "").slice(0, 24)}`,
6127
+ messageId: `msg_${randomUUID4().replace(/-/g, "").slice(0, 24)}`,
6225
6128
  model,
6226
6129
  blockIdx: 0,
6227
6130
  textBlockOpen: false,
@@ -6310,7 +6213,7 @@ async function streamCloudCodeToAnthropic(res, upstreamRes, model, log7) {
6310
6213
  closeBlock(res, state);
6311
6214
  }
6312
6215
  for (const tc of state.toolCalls) {
6313
- const rawToolId = `toolu_${randomUUID5().replace(/-/g, "").slice(0, 16)}`;
6216
+ const rawToolId = `toolu_${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
6314
6217
  const toolId = encodeToolUseId(rawToolId, tc.signature);
6315
6218
  writeEvent(res, "content_block_start", {
6316
6219
  type: "content_block_start",
@@ -6361,7 +6264,7 @@ async function streamCloudCodeToAnthropic(res, upstreamRes, model, log7) {
6361
6264
  }
6362
6265
  async function collectCloudCodeToAnthropic(upstreamRes, model, log7) {
6363
6266
  const text4 = await upstreamRes.text();
6364
- const messageId = `msg_${randomUUID5().replace(/-/g, "").slice(0, 24)}`;
6267
+ const messageId = `msg_${randomUUID4().replace(/-/g, "").slice(0, 24)}`;
6365
6268
  const content = [];
6366
6269
  let stopReason = "end_turn";
6367
6270
  let inputTokens = 0;
@@ -6390,7 +6293,7 @@ async function collectCloudCodeToAnthropic(upstreamRes, model, log7) {
6390
6293
  else content.push({ type: "text", text: part.text });
6391
6294
  } else if (part.functionCall && typeof part.functionCall === "object") {
6392
6295
  const fc = part.functionCall;
6393
- const rawToolId = `toolu_${randomUUID5().replace(/-/g, "").slice(0, 16)}`;
6296
+ const rawToolId = `toolu_${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
6394
6297
  content.push({
6395
6298
  type: "tool_use",
6396
6299
  id: encodeToolUseId(rawToolId, signature ?? pendingThoughtSignature),
@@ -6423,16 +6326,16 @@ async function collectCloudCodeToAnthropic(upstreamRes, model, log7) {
6423
6326
  }
6424
6327
 
6425
6328
  // src/proxy.ts
6426
- import { randomUUID as randomUUID6 } from "crypto";
6329
+ import { randomUUID as randomUUID5 } from "crypto";
6427
6330
 
6428
6331
  // src/sdk-adapter.ts
6429
- import { streamText, generateText, tool as tool2, jsonSchema as jsonSchema2 } from "ai";
6332
+ import { streamText, generateText, tool, jsonSchema } from "ai";
6430
6333
 
6431
6334
  // src/tool-search.ts
6432
6335
  var TOOL_SEARCH_TYPE_PREFIX = "tool_search_tool";
6433
- function isToolSearchTool(tool4) {
6434
- if (typeof tool4.type === "string" && tool4.type.startsWith(TOOL_SEARCH_TYPE_PREFIX)) return true;
6435
- const name = tool4.name ?? "";
6336
+ function isToolSearchTool(tool3) {
6337
+ if (typeof tool3.type === "string" && tool3.type.startsWith(TOOL_SEARCH_TYPE_PREFIX)) return true;
6338
+ const name = tool3.name ?? "";
6436
6339
  return name.includes("tool_search") || name === "ToolSearch";
6437
6340
  }
6438
6341
  function extractReferencedToolNames(messages) {
@@ -6471,16 +6374,16 @@ function resolveUpstreamTools(tools, messages) {
6471
6374
  if (!tools?.length) return [];
6472
6375
  const referenced = extractReferencedToolNames(messages);
6473
6376
  const upstream = [];
6474
- for (const tool4 of tools) {
6475
- if (isToolSearchTool(tool4)) {
6476
- upstream.push(tool4);
6377
+ for (const tool3 of tools) {
6378
+ if (isToolSearchTool(tool3)) {
6379
+ upstream.push(tool3);
6477
6380
  continue;
6478
6381
  }
6479
- if (tool4.defer_loading === true) {
6480
- if (referenced.has(tool4.name)) upstream.push(tool4);
6382
+ if (tool3.defer_loading === true) {
6383
+ if (referenced.has(tool3.name)) upstream.push(tool3);
6481
6384
  continue;
6482
6385
  }
6483
- upstream.push(tool4);
6386
+ upstream.push(tool3);
6484
6387
  }
6485
6388
  return upstream;
6486
6389
  }
@@ -6727,12 +6630,12 @@ function stripNullInputs(input) {
6727
6630
  }
6728
6631
  return out;
6729
6632
  }
6730
- function translateTools3(anthropicTools) {
6633
+ function translateTools2(anthropicTools) {
6731
6634
  if (!anthropicTools?.length) return void 0;
6732
6635
  const tools = {};
6733
6636
  for (const t of anthropicTools) {
6734
6637
  if (!t.name || !t.input_schema) continue;
6735
- tools[t.name] = tool2({ description: t.description ?? "", inputSchema: jsonSchema2(t.input_schema) });
6638
+ tools[t.name] = tool({ description: t.description ?? "", inputSchema: jsonSchema(t.input_schema) });
6736
6639
  }
6737
6640
  return Object.keys(tools).length ? tools : void 0;
6738
6641
  }
@@ -6743,7 +6646,7 @@ function translateToolChoice(tc) {
6743
6646
  if (tc.type === "tool" && tc.name) return { type: "tool", toolName: tc.name };
6744
6647
  return void 0;
6745
6648
  }
6746
- function translateRequest2(body, npm, options) {
6649
+ function translateRequest(body, npm, options) {
6747
6650
  const messages = body.messages ?? [];
6748
6651
  annotateToolNames(messages);
6749
6652
  const baseSystem = systemToString(body.system);
@@ -6780,7 +6683,7 @@ function translateRequest2(body, npm, options) {
6780
6683
  return {
6781
6684
  system: options?.openAiOAuth ? void 0 : systemText,
6782
6685
  messages: translateMessages(messages, npm, options?.onDebug),
6783
- tools: translateTools3(upstreamTools.length ? upstreamTools : void 0),
6686
+ tools: translateTools2(upstreamTools.length ? upstreamTools : void 0),
6784
6687
  toolChoice: translateToolChoice(body.tool_choice),
6785
6688
  maxOutputTokens: options?.openAiOAuth ? void 0 : body.max_tokens,
6786
6689
  temperature: body.temperature,
@@ -7116,7 +7019,7 @@ function lookupRoute(byAlias, id) {
7116
7019
  return void 0;
7117
7020
  }
7118
7021
  function startProxyCatalog(routes, defaultAliasId, debug = false) {
7119
- const proxyToken = randomUUID6();
7022
+ const proxyToken = randomUUID5();
7120
7023
  silenceSdkWarnings();
7121
7024
  if (routes.length === 0) {
7122
7025
  return Promise.reject(new Error("Proxy catalog requires at least one route"));
@@ -7243,7 +7146,7 @@ function startProxyCatalog(routes, defaultAliasId, debug = false) {
7243
7146
  if (sessionId) {
7244
7147
  subagentRouting.registerSubagentRoute = (modelId) => subagentRouteRegistry.register(sessionId, modelId);
7245
7148
  }
7246
- const params = translateRequest2(anthropicBody, route.npm, {
7149
+ const params = translateRequest(anthropicBody, route.npm, {
7247
7150
  openAiOAuth,
7248
7151
  maxTools: maxToolsForNpm(route.npm),
7249
7152
  onDebug: (msg) => plog(() => msg),
@@ -10394,6 +10297,20 @@ async function refreshAntigravityOAuthModels(accessToken) {
10394
10297
  }).finally(() => clearTimeout(timer));
10395
10298
  if (!res.ok) continue;
10396
10299
  const body = await res.json();
10300
+ const deprecatedModelIds = body.deprecatedModelIds && typeof body.deprecatedModelIds === "object" && !Array.isArray(body.deprecatedModelIds) ? body.deprecatedModelIds : {};
10301
+ const resolveUpstreamModelId = (id) => {
10302
+ let current = id;
10303
+ const seen = /* @__PURE__ */ new Set();
10304
+ while (!seen.has(current)) {
10305
+ seen.add(current);
10306
+ const alias = deprecatedModelIds[current];
10307
+ if (!alias || typeof alias !== "object" || Array.isArray(alias)) break;
10308
+ const next = alias.newModelId;
10309
+ if (typeof next !== "string" || next.length === 0) break;
10310
+ current = next;
10311
+ }
10312
+ return current;
10313
+ };
10397
10314
  const raw = body.models && typeof body.models === "object" && !Array.isArray(body.models) ? Object.entries(body.models).map(([id, model]) => ({ id, ...model })) : Array.isArray(body.models) ? body.models.filter((m) => typeof m.id === "string" && m.id.length > 0) : [];
10398
10315
  if (raw.length === 0) continue;
10399
10316
  const models = raw.filter((m) => typeof m.id === "string" && m.id.length > 0 && !isAntigravityCloudCodeHelperSlot(m.id)).map((m) => {
@@ -10406,7 +10323,7 @@ async function refreshAntigravityOAuthModels(accessToken) {
10406
10323
  return {
10407
10324
  id,
10408
10325
  name,
10409
- upstreamModelId: id,
10326
+ upstreamModelId: resolveUpstreamModelId(id),
10410
10327
  family: isGemini ? "gemini" : id.split("-")[0] ?? id,
10411
10328
  brand: isGemini ? "Google" : isClaude ? "Anthropic" : isOpenAi ? "OpenAI" : "Other",
10412
10329
  contextWindow: maxTokens ?? resolveContextWindow(id),
@@ -11147,7 +11064,7 @@ async function askSaveServerPassword() {
11147
11064
  import { createServer as createServer2 } from "http";
11148
11065
 
11149
11066
  // src/openai-adapter.ts
11150
- import { tool as tool3, jsonSchema as jsonSchema3, streamText as streamText2, generateText as generateText2 } from "ai";
11067
+ import { tool as tool2, jsonSchema as jsonSchema2, streamText as streamText2, generateText as generateText2 } from "ai";
11151
11068
  function translateOpenAiRequest(body) {
11152
11069
  const toolNameById = /* @__PURE__ */ new Map();
11153
11070
  for (const msg of body.messages) {
@@ -11213,10 +11130,10 @@ function translateOpenAiRequest(body) {
11213
11130
  tools = {};
11214
11131
  for (const t of body.tools) {
11215
11132
  if (t.type === "function" && t.function.name) {
11216
- const schema = t.function.parameters ? jsonSchema3(t.function.parameters) : void 0;
11217
- tools[t.function.name] = tool3({
11133
+ const schema = t.function.parameters ? jsonSchema2(t.function.parameters) : void 0;
11134
+ tools[t.function.name] = tool2({
11218
11135
  description: t.function.description ?? "",
11219
- inputSchema: schema ?? jsonSchema3({ type: "object", properties: {} })
11136
+ inputSchema: schema ?? jsonSchema2({ type: "object", properties: {} })
11220
11137
  });
11221
11138
  }
11222
11139
  }
@@ -11506,7 +11423,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog, suba
11506
11423
  if (sessionId) {
11507
11424
  subagentRouting.registerSubagentRoute = (modelId) => subagentRouteRegistry.register(sessionId, modelId);
11508
11425
  }
11509
- const params = translateRequest2(body, model.npm, {
11426
+ const params = translateRequest(body, model.npm, {
11510
11427
  defaultEffort: anthropicEffortFromRequest(body) ? void 0 : model.defaultEffort,
11511
11428
  openAiOAuth: model.npm === "@ai-sdk/openai" && model.authType === "oauth",
11512
11429
  onDebug: plog,
@@ -12982,18 +12899,18 @@ ${pc6.dim("OpenCode CLI configs: use")} relay-ai providers import${pc6.dim(" (op
12982
12899
  }
12983
12900
 
12984
12901
  // src/codex/app-launch.ts
12985
- import { execSync as execSync2, spawn as spawn2 } from "child_process";
12986
- import { existsSync as existsSync11, readdirSync as readdirSync2, realpathSync, statSync as statSync3 } from "fs";
12902
+ import { execSync as execSync2, spawn as spawn3 } from "child_process";
12903
+ import { copyFileSync as copyFileSync3, existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync2, realpathSync, statSync as statSync3 } from "fs";
12987
12904
  import { homedir as homedir7 } from "os";
12988
- import { dirname as dirname5, join as join12 } from "path";
12905
+ import { dirname as dirname5, join as join12, win32 as winPath } from "path";
12989
12906
  import * as p6 from "@clack/prompts";
12990
12907
 
12991
12908
  // src/linux-display.ts
12992
- import { execFileSync as execFileSync3 } from "child_process";
12909
+ import { execFileSync as execFileSync2 } from "child_process";
12993
12910
  import { readdirSync } from "fs";
12994
12911
  function displayHasWindow(display, windowId) {
12995
12912
  try {
12996
- const output = execFileSync3("xprop", ["-display", display, "-id", windowId, "WM_CLASS"], {
12913
+ const output = execFileSync2("xprop", ["-display", display, "-id", windowId, "WM_CLASS"], {
12997
12914
  encoding: "utf8",
12998
12915
  stdio: ["ignore", "pipe", "ignore"]
12999
12916
  });
@@ -13071,6 +12988,54 @@ function linuxEmbeddedCodexCandidates(appPath) {
13071
12988
  function winLocalAppData() {
13072
12989
  return process.env.LOCALAPPDATA ?? join12(homedir7(), "AppData", "Local");
13073
12990
  }
12991
+ function windowsEmbeddedCodexCandidates(appPath, packageInstallLocations) {
12992
+ const candidates = [];
12993
+ if (appPath && !appPath.startsWith("shell:AppsFolder\\")) {
12994
+ const appDir = winPath.dirname(appPath);
12995
+ candidates.push(
12996
+ winPath.join(appDir, "resources", "codex.exe"),
12997
+ winPath.join(appDir, "app", "resources", "codex.exe")
12998
+ );
12999
+ }
13000
+ for (const installLocation of packageInstallLocations) {
13001
+ if (!installLocation.trim()) continue;
13002
+ candidates.push(
13003
+ winPath.join(installLocation, "app", "resources", "codex.exe"),
13004
+ winPath.join(installLocation, "resources", "codex.exe")
13005
+ );
13006
+ }
13007
+ return [...new Set(candidates)];
13008
+ }
13009
+ function windowsEmbeddedCodexCachePath(sourcePath, home = homedir7()) {
13010
+ const normalized = sourcePath.replaceAll("/", "\\");
13011
+ const match = normalized.match(/\\WindowsApps\\([^\\]+)\\/i);
13012
+ if (!match) return null;
13013
+ const packageDirectory = match[1].replace(/[^a-zA-Z0-9._-]/g, "_");
13014
+ return winPath.join(home, ".relay-ai", "codex", "embedded-runtime", packageDirectory, "codex.exe");
13015
+ }
13016
+ function executableWindowsEmbeddedCodexPath(sourcePath) {
13017
+ const cachePath2 = windowsEmbeddedCodexCachePath(sourcePath);
13018
+ if (!cachePath2) return sourcePath;
13019
+ try {
13020
+ const sourceSize = statSync3(sourcePath).size;
13021
+ if (existsSync11(cachePath2) && statSync3(cachePath2).size === sourceSize) return cachePath2;
13022
+ mkdirSync8(winPath.dirname(cachePath2), { recursive: true });
13023
+ copyFileSync3(sourcePath, cachePath2);
13024
+ return statSync3(cachePath2).size === sourceSize ? cachePath2 : null;
13025
+ } catch {
13026
+ return null;
13027
+ }
13028
+ }
13029
+ function winCodexPackageInstallLocations() {
13030
+ try {
13031
+ const out = runPowerShell(
13032
+ "Get-AppxPackage -Name 'OpenAI.Codex' | Sort-Object Version -Descending | Select-Object -ExpandProperty InstallLocation"
13033
+ );
13034
+ return out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
13035
+ } catch {
13036
+ return [];
13037
+ }
13038
+ }
13074
13039
  function winCodexExeCandidates() {
13075
13040
  const local = winLocalAppData();
13076
13041
  const bases = WIN_APP_NAMES.flatMap((name) => [
@@ -13140,14 +13105,25 @@ function findCodexApp(platform = process.platform) {
13140
13105
  }
13141
13106
  function findEmbeddedCodexBinary(platform = process.platform) {
13142
13107
  const appPath = findCodexApp(platform);
13143
- if (!appPath) return null;
13144
13108
  if (platform === "darwin") {
13109
+ if (!appPath) return null;
13145
13110
  const binary = join12(appPath, "Contents", "Resources", "codex");
13146
13111
  return existsSync11(binary) ? binary : null;
13147
13112
  }
13148
13113
  if (platform === "linux") {
13114
+ if (!appPath) return null;
13149
13115
  return linuxEmbeddedCodexCandidates(appPath).find((path) => existsSync11(path)) ?? null;
13150
13116
  }
13117
+ if (platform === "win32") {
13118
+ const sourcePath = windowsEmbeddedCodexCandidates(appPath, winCodexPackageInstallLocations()).find((path) => {
13119
+ try {
13120
+ return existsSync11(path) && statSync3(path).isFile();
13121
+ } catch {
13122
+ return false;
13123
+ }
13124
+ });
13125
+ return sourcePath ? executableWindowsEmbeddedCodexPath(sourcePath) : null;
13126
+ }
13151
13127
  return null;
13152
13128
  }
13153
13129
  function darwinIsRunning() {
@@ -13224,14 +13200,14 @@ function openCodexAppAt(path) {
13224
13200
  }
13225
13201
  if (process.platform === "win32") {
13226
13202
  if (path.startsWith("shell:AppsFolder\\")) {
13227
- spawn2("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
13203
+ spawn3("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
13228
13204
  } else {
13229
13205
  runPowerShell(`Start-Process -FilePath '${path.replace(/'/g, "''")}'`);
13230
13206
  }
13231
13207
  return;
13232
13208
  }
13233
13209
  if (process.platform === "linux") {
13234
- spawn2(path, [], { stdio: "ignore", detached: true, env: linuxLaunchEnv() }).unref();
13210
+ spawn3(path, [], { stdio: "ignore", detached: true, env: linuxLaunchEnv() }).unref();
13235
13211
  }
13236
13212
  }
13237
13213
  function openCodexApp() {
@@ -13275,7 +13251,7 @@ function winForceQuit() {
13275
13251
  if (pids.length === 0) return;
13276
13252
  runPowerShell(`Stop-Process -Id ${pids.join(",")} -Force -ErrorAction SilentlyContinue`);
13277
13253
  }
13278
- async function launchOrRestartCodexApp(prompt = "Restart ChatGPT Desktop to apply relay-ai settings?") {
13254
+ async function launchOrRestartCodexApp(prompt = "Restart ChatGPT Desktop to apply relay-ai settings?", assumeYes = false) {
13279
13255
  const appPath = findCodexApp();
13280
13256
  if (!isCodexAppRunning()) {
13281
13257
  if (!appPath) {
@@ -13289,6 +13265,9 @@ async function launchOrRestartCodexApp(prompt = "Restart ChatGPT Desktop to appl
13289
13265
  if (process.platform === "linux") {
13290
13266
  p6.log.info("Restarting ChatGPT Desktop to apply relay-ai settings...");
13291
13267
  linuxQuitGraceful();
13268
+ } else if (assumeYes) {
13269
+ if (process.platform === "darwin") darwinQuit();
13270
+ else if (process.platform === "win32") winQuitGraceful();
13292
13271
  } else {
13293
13272
  const restart = await p6.confirm({ message: prompt, initialValue: true });
13294
13273
  if (p6.isCancel(restart) || !restart) {
@@ -13310,7 +13289,7 @@ function codexAppInstallHint() {
13310
13289
  }
13311
13290
 
13312
13291
  // src/claude-desktop/app-launch.ts
13313
- import { execSync as execSync3, spawn as spawn3 } from "child_process";
13292
+ import { execSync as execSync3, spawn as spawn4 } from "child_process";
13314
13293
  import { existsSync as existsSync12, readdirSync as readdirSync3, readFileSync as readFileSync12, statSync as statSync4 } from "fs";
13315
13294
  import { homedir as homedir8 } from "os";
13316
13295
  import { join as join13 } from "path";
@@ -13517,14 +13496,14 @@ function openClaudeAppAt(path) {
13517
13496
  }
13518
13497
  if (process.platform === "win32") {
13519
13498
  if (path.startsWith("shell:AppsFolder\\")) {
13520
- spawn3("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
13499
+ spawn4("cmd.exe", ["/c", "start", "", path], { stdio: "ignore", detached: true }).unref();
13521
13500
  } else {
13522
13501
  runPowerShell2(`Start-Process -FilePath '${path.replace(/'/g, "''")}'`);
13523
13502
  }
13524
13503
  return;
13525
13504
  }
13526
13505
  if (process.platform === "linux") {
13527
- spawn3(path, [], { stdio: "ignore", detached: true, env: linuxLaunchEnv() }).unref();
13506
+ spawn4(path, [], { stdio: "ignore", detached: true, env: linuxLaunchEnv() }).unref();
13528
13507
  }
13529
13508
  }
13530
13509
  function openClaudeApp() {
@@ -13610,6 +13589,8 @@ export {
13610
13589
  effortProviderOptions,
13611
13590
  deepMergeProviderOptions,
13612
13591
  thinkingProviderOptions,
13592
+ runCodexCommandSync,
13593
+ runCodexCommand,
13613
13594
  renderMultiAgentV2Feature,
13614
13595
  supportsMultiAgentV2,
13615
13596
  CODEX_APP_PROVIDER_ID,
@@ -13760,10 +13741,6 @@ export {
13760
13741
  splitToolUseId,
13761
13742
  encodeToolUseId,
13762
13743
  serializeToolResultContent,
13763
- UNSUPPORTED_VOICE_MESSAGE,
13764
- sanitizeUnsupportedInlineData,
13765
- summarizeSdkRequestForTrace,
13766
- translateRequest,
13767
13744
  formatUpstreamErrorTrace,
13768
13745
  formatUpstreamError,
13769
13746
  upstreamHttpStatus,
@@ -13841,4 +13818,4 @@ export {
13841
13818
  supportsClaudeTransparentMode,
13842
13819
  buildHttpProxyRoutes
13843
13820
  };
13844
- //# sourceMappingURL=chunk-PVGAE7HA.js.map
13821
+ //# sourceMappingURL=chunk-SCW2TYSG.js.map