@jacobbd/relay-ai 0.12.6 → 0.12.9

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.
@@ -87,7 +87,7 @@ import {
87
87
  translateRequest,
88
88
  upstreamHttpStatus,
89
89
  validateCustomEndpointUrl
90
- } from "./chunk-VPDX24ZR.js";
90
+ } from "./chunk-3KCKQRRR.js";
91
91
 
92
92
  // src/registry/google-model-id.ts
93
93
  var GOOGLE_MODEL_PREFIX = "models/";
@@ -9806,4 +9806,4 @@ export {
9806
9806
  supportsClaudeTransparentMode,
9807
9807
  buildHttpProxyRoutes
9808
9808
  };
9809
- //# sourceMappingURL=chunk-5MEDBKPX.js.map
9809
+ //# sourceMappingURL=chunk-KVH362S4.js.map
@@ -10,7 +10,7 @@ import {
10
10
  supportsManualModels,
11
11
  translateRequest,
12
12
  validateCustomEndpointUrl
13
- } from "./chunk-VPDX24ZR.js";
13
+ } from "./chunk-3KCKQRRR.js";
14
14
 
15
15
  // src/registry/validate-manual-model.ts
16
16
  import { randomUUID } from "crypto";
@@ -149,4 +149,4 @@ export {
149
149
  addManualModel,
150
150
  removeManualModel
151
151
  };
152
- //# sourceMappingURL=chunk-6ULON7FU.js.map
152
+ //# sourceMappingURL=chunk-TRCGBOYR.js.map
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  addManualModel,
4
4
  removeManualModel
5
- } from "./chunk-6ULON7FU.js";
5
+ } from "./chunk-TRCGBOYR.js";
6
6
  import {
7
7
  CODEX_APP_AUTO_COMPACT_RATIO,
8
8
  CODEX_APP_PROVIDER_ID,
@@ -148,7 +148,7 @@ import {
148
148
  waitForCodexAppQuit,
149
149
  writeSecureLogLine,
150
150
  zenRegistryStub
151
- } from "./chunk-5MEDBKPX.js";
151
+ } from "./chunk-KVH362S4.js";
152
152
  import {
153
153
  filterTemplates,
154
154
  getTemplateById,
@@ -222,7 +222,7 @@ import {
222
222
  thinkingProviderOptions,
223
223
  upstreamHttpStatus,
224
224
  validateCustomEndpointUrl
225
- } from "./chunk-VPDX24ZR.js";
225
+ } from "./chunk-3KCKQRRR.js";
226
226
  import "./chunk-JIDIH7DS.js";
227
227
 
228
228
  // src/cli.ts
@@ -2544,6 +2544,22 @@ function messageContent(content) {
2544
2544
  });
2545
2545
  return parts.length > 0 ? parts : [{ type: "text", text: "" }];
2546
2546
  }
2547
+ function splitToolOutputImages(output) {
2548
+ if (!Array.isArray(output)) return { content: serializeToolResultContent(output), images: [] };
2549
+ const images = [];
2550
+ const rest = [];
2551
+ for (const part of output) {
2552
+ const record = part && typeof part === "object" ? part : void 0;
2553
+ const imageUrl = record?.["type"] === "input_image" ? record["image_url"] : void 0;
2554
+ if (typeof imageUrl === "string" && imageUrl.trim()) images.push(imageUrl);
2555
+ else rest.push(part);
2556
+ }
2557
+ if (images.length === 0) return { content: serializeToolResultContent(output), images };
2558
+ return {
2559
+ content: rest.length > 0 ? serializeToolResultContent(rest) : "[image attached in the following message]",
2560
+ images
2561
+ };
2562
+ }
2547
2563
  function extractDeveloperAndInstructions(items, instructions) {
2548
2564
  const developerParts = [];
2549
2565
  const remaining = [];
@@ -2668,15 +2684,26 @@ function translateResponsesInput(input, instructions, npm, toolContext = createC
2668
2684
  messages.push({ role: "assistant", content: parts });
2669
2685
  } else if (item.type === "function_call_output") {
2670
2686
  const { rawId } = splitToolUseId(item.call_id);
2687
+ const toolName = toolNames.get(rawId) ?? "unknown";
2688
+ const { content, images } = splitToolOutputImages(item.output);
2671
2689
  messages.push({
2672
2690
  role: "tool",
2673
2691
  content: [{
2674
2692
  type: "tool-result",
2675
2693
  toolCallId: rawId,
2676
- toolName: toolNames.get(rawId) ?? "unknown",
2677
- output: { type: "text", value: serializeToolResultContent(item.output) }
2694
+ toolName,
2695
+ output: { type: "text", value: content }
2678
2696
  }]
2679
2697
  });
2698
+ if (images.length > 0) {
2699
+ messages.push({
2700
+ role: "user",
2701
+ content: [
2702
+ { type: "text", text: `Image${images.length > 1 ? "s" : ""} returned by ${toolName} (${rawId}):` },
2703
+ ...images.map((image) => ({ type: "image", image }))
2704
+ ]
2705
+ });
2706
+ }
2680
2707
  } else if (item.type === "tool_search_call") {
2681
2708
  const { rawId } = splitToolUseId(item.call_id);
2682
2709
  messages.push({
@@ -2875,6 +2902,16 @@ function resolveOutputKind(flatName, ctx) {
2875
2902
  if (ns) return { kind: "namespace", namespace: ns.namespace, name: ns.name };
2876
2903
  return { kind: "plain" };
2877
2904
  }
2905
+ function toolItemId(kind, upstreamId) {
2906
+ switch (kind.kind) {
2907
+ case "tool_search":
2908
+ return upstreamId.startsWith("tsc_") ? upstreamId : newItemId("tsc");
2909
+ case "custom":
2910
+ return upstreamId.startsWith("ctc_") ? upstreamId : newItemId("ctc");
2911
+ default:
2912
+ return functionCallItemId(upstreamId);
2913
+ }
2914
+ }
2878
2915
  function buildFinalToolItem(kind, flatName, callId, itemId, argsStr) {
2879
2916
  argsStr = normalizeCodexSubagentArguments(flatName, argsStr);
2880
2917
  switch (kind.kind) {
@@ -2962,14 +2999,16 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
2962
2999
  return state;
2963
3000
  };
2964
3001
  const createToolState = (rawId, name, signature) => {
3002
+ const kind = resolveOutputKind(name ?? "", options?.toolContext);
2965
3003
  const upstreamId = rawId ?? newItemId("call");
2966
- const itemId = functionCallItemId(upstreamId);
3004
+ const itemId = toolItemId(kind, upstreamId);
2967
3005
  const state = rememberToolState({
2968
3006
  itemId,
2969
3007
  callId: encodeToolUseId(upstreamId, signature, false),
2970
3008
  name: name ?? "unknown",
2971
3009
  outputIndex: outputIndex++,
2972
- args: ""
3010
+ args: "",
3011
+ kind
2973
3012
  });
2974
3013
  emit("response.output_item.added", {
2975
3014
  type: "response.output_item.added",
@@ -3256,7 +3295,7 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
3256
3295
  output_index: tool4.outputIndex,
3257
3296
  arguments: normalizedArgs
3258
3297
  });
3259
- const fcItem = buildFinalToolItem(resolveOutputKind(tool4.name, options?.toolContext), tool4.name, tool4.callId, tool4.itemId, normalizedArgs);
3298
+ const fcItem = buildFinalToolItem(tool4.kind, tool4.name, tool4.callId, tool4.itemId, normalizedArgs);
3260
3299
  emit("response.output_item.done", {
3261
3300
  type: "response.output_item.done",
3262
3301
  output_index: tool4.outputIndex,
@@ -3352,11 +3391,12 @@ async function generateResponsesResponse(model, params, modelId) {
3352
3391
  for (const tc of r.toolCalls) {
3353
3392
  const encodedId = encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc), false);
3354
3393
  const argsStr = JSON.stringify(tc.input ?? {});
3394
+ const kind = resolveOutputKind(tc.toolName, toolContext);
3355
3395
  output.push(buildFinalToolItem(
3356
- resolveOutputKind(tc.toolName, toolContext),
3396
+ kind,
3357
3397
  tc.toolName,
3358
3398
  encodedId,
3359
- functionCallItemId(tc.toolCallId),
3399
+ toolItemId(kind, tc.toolCallId),
3360
3400
  argsStr
3361
3401
  ));
3362
3402
  }
@@ -4059,6 +4099,11 @@ var EXTERNAL_TOOL_OUTPUT_TYPES = /* @__PURE__ */ new Set([
4059
4099
  "custom_tool_call_output",
4060
4100
  "tool_search_output"
4061
4101
  ]);
4102
+ var EXTERNAL_TOOL_CALL_TYPES = /* @__PURE__ */ new Set([
4103
+ "function_call",
4104
+ "custom_tool_call",
4105
+ "tool_search_call"
4106
+ ]);
4062
4107
  function responsesInputItems(input) {
4063
4108
  if (Array.isArray(input)) return input;
4064
4109
  if (typeof input === "string") {
@@ -4071,8 +4116,18 @@ function isExternalToolOutputItem(item) {
4071
4116
  const type = item.type;
4072
4117
  return typeof type === "string" && EXTERNAL_TOOL_OUTPUT_TYPES.has(type);
4073
4118
  }
4119
+ function isExternalToolCallItem(item) {
4120
+ if (!item || typeof item !== "object" || Array.isArray(item)) return false;
4121
+ const type = item.type;
4122
+ return typeof type === "string" && EXTERNAL_TOOL_CALL_TYPES.has(type);
4123
+ }
4074
4124
  function isExternalToolContinuation(input) {
4075
- return Array.isArray(input) && input.length > 0 && input.every(isExternalToolOutputItem);
4125
+ return Array.isArray(input) && input.length > 0 && input.some(isExternalToolOutputItem) && !input.some(isExternalToolCallItem);
4126
+ }
4127
+ var IMAGE_PART_CHAR_WEIGHT = 4e3;
4128
+ function isImageContentPart(part) {
4129
+ if (part["type"] === "image") return true;
4130
+ return part["type"] === "file" && typeof part["mediaType"] === "string" && part["mediaType"].startsWith("image");
4076
4131
  }
4077
4132
  function estimateCodexRequestChars(params) {
4078
4133
  let chars = (params.instructions ?? "").length;
@@ -4083,6 +4138,8 @@ function estimateCodexRequestChars(params) {
4083
4138
  const p16 = part;
4084
4139
  if (typeof p16["text"] === "string") {
4085
4140
  chars += p16["text"].length;
4141
+ } else if (isImageContentPart(p16)) {
4142
+ chars += IMAGE_PART_CHAR_WEIGHT;
4086
4143
  } else {
4087
4144
  chars += JSON.stringify(part).length;
4088
4145
  }
@@ -4114,6 +4171,17 @@ function clipLargeTextParts(params, maxCharsPerPart) {
4114
4171
  content: msg.content.map((part) => {
4115
4172
  if (!part || typeof part !== "object") return part;
4116
4173
  const p16 = part;
4174
+ if (p16["type"] === "tool-result") {
4175
+ const output = p16["output"];
4176
+ if (!output) return part;
4177
+ if (typeof output["value"] === "string" && (output["type"] === "text" || output["type"] === "error-text")) {
4178
+ return { ...p16, output: { ...output, value: clipTextForContext(output["value"], maxCharsPerPart) } };
4179
+ }
4180
+ if (output["type"] === "json") {
4181
+ return { ...p16, output: { type: "text", value: clipTextForContext(JSON.stringify(output["value"]), maxCharsPerPart) } };
4182
+ }
4183
+ return part;
4184
+ }
4117
4185
  if (typeof p16.text !== "string") return part;
4118
4186
  return { ...p16, text: clipTextForContext(p16.text, maxCharsPerPart) };
4119
4187
  })
@@ -6044,6 +6112,12 @@ function buildCodexProxyRoutesFromResolved(resolved, providersById) {
6044
6112
  oauthAccountId: route.oauthAccountId,
6045
6113
  providerData: route.providerData,
6046
6114
  contextWindow: route.contextWindow,
6115
+ // Reasoning metadata decides whether a picked effort can be translated
6116
+ // at all (e.g. OpenRouter's supportedParameters gate). Dropping these
6117
+ // silently turned every effort selection into a no-op on the wire.
6118
+ supportedParameters: route.supportedParameters,
6119
+ reasoning: route.reasoning,
6120
+ interleavedReasoningField: route.interleavedReasoningField,
6047
6121
  headers: route.headers
6048
6122
  };
6049
6123
  }).filter((r) => r !== void 0);
@@ -6327,7 +6401,10 @@ async function prepareCodexMixedRelayRoutes(models, trace = false) {
6327
6401
  authType: "oauth",
6328
6402
  oauthAccountId: original.oauthAccountId,
6329
6403
  providerData: original.providerData,
6330
- contextWindow: proxyRoute.contextWindow
6404
+ contextWindow: proxyRoute.contextWindow,
6405
+ supportedParameters: original.model.supportedParameters,
6406
+ reasoning: original.model.reasoning,
6407
+ interleavedReasoningField: original.model.interleavedReasoningField
6331
6408
  }),
6332
6409
  trace
6333
6410
  );
@@ -16156,7 +16233,7 @@ Options:
16156
16233
  --trace Write debug logs under ~/.relay-ai/logs/`);
16157
16234
  return 0;
16158
16235
  }
16159
- const { runUiCommand } = await import("./ui-command-U3L4LI2K.js");
16236
+ const { runUiCommand } = await import("./ui-command-CLMJUDHR.js");
16160
16237
  return runUiCommand({ trace: parsed.trace, serverMode: parsed.uiServerMode });
16161
16238
  }
16162
16239
  if (parsed.command === "models") {