@jacobbd/relay-ai 0.7.4 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  GLOBAL_OPENCODE_KEYRING_ACCOUNT,
9
9
  MAX_MODEL_CATALOG,
10
10
  PREVIEW_PROXY_PORT,
11
+ UNSUPPORTED_VOICE_MESSAGE,
11
12
  VERSION,
12
13
  VERTEX_ANTHROPIC_NPM,
13
14
  addCustomEndpointProvider,
@@ -69,6 +70,8 @@ import {
69
70
  formatRegistryAuthLabel,
70
71
  formatUpdateNotification,
71
72
  formatUpstreamError,
73
+ formatUpstreamErrorTrace,
74
+ getAntigravityDebugLogPath,
72
75
  getAppHome,
73
76
  getAppPathOverride,
74
77
  getClaudeDebugLogPath,
@@ -152,6 +155,7 @@ import {
152
155
  routableModelsForTarget,
153
156
  routeLookupIds,
154
157
  runServerCommand,
158
+ sanitizeUnsupportedInlineData,
155
159
  savePreferences,
156
160
  saveProviderCredential,
157
161
  saveRegistry,
@@ -167,6 +171,7 @@ import {
167
171
  startProxy,
168
172
  startProxyCatalog,
169
173
  startServer,
174
+ summarizeSdkRequestForTrace,
170
175
  supportsClaudeTransparentMode,
171
176
  supportsNativeOAuth,
172
177
  syntheticTemplate,
@@ -177,7 +182,7 @@ import {
177
182
  validateCustomEndpointUrl,
178
183
  writeSecureLogLine,
179
184
  zenRegistryStub
180
- } from "./chunk-EUY2MVOS.js";
185
+ } from "./chunk-GHSURQOK.js";
181
186
  import {
182
187
  filterTemplates,
183
188
  init_provider_templates,
@@ -2342,6 +2347,9 @@ function newResponseId() {
2342
2347
  function newItemId(prefix) {
2343
2348
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
2344
2349
  }
2350
+ function functionCallItemId(upstreamId) {
2351
+ return upstreamId.startsWith("fc_") ? upstreamId : newItemId("fc");
2352
+ }
2345
2353
  function usageFromPart(part) {
2346
2354
  const input = part.totalUsage?.inputTokens ?? 0;
2347
2355
  const output = part.totalUsage?.outputTokens ?? 0;
@@ -2441,10 +2449,11 @@ async function writeResponsesStream(fullStream, modelId, write, onDone, onProgre
2441
2449
  return state;
2442
2450
  };
2443
2451
  const createToolState = (rawId, name, signature) => {
2444
- const itemId = rawId ?? newItemId("fc");
2452
+ const upstreamId = rawId ?? newItemId("call");
2453
+ const itemId = functionCallItemId(upstreamId);
2445
2454
  const state = rememberToolState({
2446
2455
  itemId,
2447
- callId: encodeToolUseId(itemId, signature, false),
2456
+ callId: encodeToolUseId(upstreamId, signature, false),
2448
2457
  name: name ?? "unknown",
2449
2458
  outputIndex: outputIndex++,
2450
2459
  args: ""
@@ -2828,7 +2837,13 @@ async function generateResponsesResponse(model, params, modelId) {
2828
2837
  for (const tc of r.toolCalls) {
2829
2838
  const encodedId = encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc), false);
2830
2839
  const argsStr = JSON.stringify(tc.input ?? {});
2831
- output.push(buildFinalToolItem(resolveOutputKind(tc.toolName, toolContext), tc.toolName, encodedId, tc.toolCallId, argsStr));
2840
+ output.push(buildFinalToolItem(
2841
+ resolveOutputKind(tc.toolName, toolContext),
2842
+ tc.toolName,
2843
+ encodedId,
2844
+ functionCallItemId(tc.toolCallId),
2845
+ argsStr
2846
+ ));
2832
2847
  }
2833
2848
  if (output.length === 0) {
2834
2849
  output.push({ id: newItemId("msg"), type: "message", role: "assistant", status: "completed", content: [{ type: "output_text", text: "(conversation context was too large to summarize)" }] });
@@ -6416,7 +6431,6 @@ Error: ${launchPlan.error}
6416
6431
  // src/antigravity.ts
6417
6432
  import pc9 from "picocolors";
6418
6433
  import * as p11 from "@clack/prompts";
6419
- import { appendFileSync as appendFileSync2 } from "fs";
6420
6434
 
6421
6435
  // src/antigravity/cloud-code-gateway.ts
6422
6436
  import http from "http";
@@ -7535,7 +7549,12 @@ async function startCloudCodeGateway(routes, opts = {}) {
7535
7549
  } catch {
7536
7550
  }
7537
7551
  if (trace && parsed) {
7538
- const preview = JSON.stringify(parsed).slice(0, 500);
7552
+ const preview = JSON.stringify(parsed, function(key, value) {
7553
+ if (key === "data" && typeof value === "string" && this && typeof this === "object" && typeof this.mimeType === "string") {
7554
+ return `[${value.length} media chars]`;
7555
+ }
7556
+ return value;
7557
+ }).slice(0, 500);
7539
7558
  log14(`[gateway] body-preview: ${preview}`);
7540
7559
  }
7541
7560
  if (lowerUrl.includes("loadcodeassist")) {
@@ -7558,6 +7577,18 @@ async function startCloudCodeGateway(routes, opts = {}) {
7558
7577
  if (trace) log14(`[gateway] extracted model: ${model ?? "N/A"}`);
7559
7578
  const route = resolveRouteForModel(model);
7560
7579
  if (route) {
7580
+ if (trace) {
7581
+ log14(
7582
+ `[gateway] resolved route: ${route.catalogId} (${route.providerId}/${route.upstreamModelId} via ${model})`
7583
+ );
7584
+ }
7585
+ const media = sanitizeUnsupportedInlineData(parsed);
7586
+ parsed = media.request;
7587
+ if (media.latestUserTurnHasUnsupportedMedia) {
7588
+ if (trace) log14("[gateway] unsupported media in current user turn; provider call skipped");
7589
+ respondUnsupportedMedia(res, route, lowerUrl.includes("stream"));
7590
+ return;
7591
+ }
7561
7592
  if (trackActiveRoute && selectedSlotIds.has(model ?? "") && isUserTurnRequest(parsed)) {
7562
7593
  activeRoute = route;
7563
7594
  if (trace) log14(`[gateway] active route: ${route.catalogId} via ${model}`);
@@ -7584,9 +7615,11 @@ async function startCloudCodeGateway(routes, opts = {}) {
7584
7615
  if (isStream) {
7585
7616
  handleStreamingRequest(res, route, baseProviderOptions, parsed, log14, {
7586
7617
  requestOptions,
7587
- onReasoningWithToolCall: rememberReasoning
7618
+ onReasoningWithToolCall: rememberReasoning,
7619
+ trace
7588
7620
  }).catch((err) => {
7589
- log14(`[gateway] stream error: ${err instanceof Error ? err.stack || err.message : String(err)}`);
7621
+ log14(`[gateway] stream error: ${formatUpstreamError(err)}`);
7622
+ if (trace) log14(`[gateway] stream error detail: ${formatUpstreamErrorTrace(err)}`);
7590
7623
  if (!res.headersSent) {
7591
7624
  respondJson(res, 500, { error: { code: 500, message: formatUpstreamError(err) } });
7592
7625
  } else if (!res.writableEnded) {
@@ -7596,9 +7629,11 @@ async function startCloudCodeGateway(routes, opts = {}) {
7596
7629
  } else {
7597
7630
  handleUnaryRequest(res, route, baseProviderOptions, parsed, log14, {
7598
7631
  requestOptions,
7599
- onReasoningWithToolCall: rememberReasoning
7632
+ onReasoningWithToolCall: rememberReasoning,
7633
+ trace
7600
7634
  }).catch((err) => {
7601
- log14(`[gateway] unary error: ${err instanceof Error ? err.stack || err.message : String(err)}`);
7635
+ log14(`[gateway] unary error: ${formatUpstreamError(err)}`);
7636
+ if (trace) log14(`[gateway] unary error detail: ${formatUpstreamErrorTrace(err)}`);
7602
7637
  if (!res.headersSent) {
7603
7638
  respondJson(res, 500, { error: { code: 500, message: formatUpstreamError(err) } });
7604
7639
  }
@@ -7766,7 +7801,7 @@ function shouldEchoReasoningForRoute(route) {
7766
7801
  route.displayName,
7767
7802
  route.baseURL
7768
7803
  ].join(" ");
7769
- return /deepseek/i.test(routeIdentity);
7804
+ return /deepseek|big[\s_-]?pickle|\bglm[\s_-]/i.test(routeIdentity);
7770
7805
  }
7771
7806
  function reasoningEchoOptionsForRoute(route, parsed, cache) {
7772
7807
  if (!shouldEchoReasoningForRoute(route)) return {};
@@ -7923,6 +7958,41 @@ function respondJson(res, status, data) {
7923
7958
  });
7924
7959
  res.end(body);
7925
7960
  }
7961
+ function respondUnsupportedMedia(res, route, streaming) {
7962
+ const responseId = `relay-${Date.now()}`;
7963
+ if (streaming) {
7964
+ const chunk = formatCloudCodeChunk({
7965
+ text: UNSUPPORTED_VOICE_MESSAGE,
7966
+ modelVersion: route.catalogId,
7967
+ responseId,
7968
+ finishReason: "STOP"
7969
+ });
7970
+ res.writeHead(200, {
7971
+ "content-type": "text/event-stream",
7972
+ "cache-control": "no-cache",
7973
+ "grpc-status": "0"
7974
+ });
7975
+ res.end(`data: ${JSON.stringify(chunk)}
7976
+
7977
+ `);
7978
+ return;
7979
+ }
7980
+ respondJson(res, 200, {
7981
+ response: {
7982
+ candidates: [{
7983
+ content: {
7984
+ role: "model",
7985
+ parts: [{ text: UNSUPPORTED_VOICE_MESSAGE }]
7986
+ },
7987
+ finishReason: "STOP"
7988
+ }],
7989
+ modelVersion: route.catalogId,
7990
+ responseId
7991
+ },
7992
+ traceId: "relay-trace",
7993
+ metadata: {}
7994
+ });
7995
+ }
7926
7996
  function parsePseudoToolCall(text4, knownToolNames) {
7927
7997
  const trimmed = text4.trim();
7928
7998
  if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return null;
@@ -7944,6 +8014,9 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log14
7944
8014
  ...options.requestOptions,
7945
8015
  maxTools: maxToolsForNpm(route.npm)
7946
8016
  }));
8017
+ if (options.trace) {
8018
+ log14(`[gateway] sdk request: ${JSON.stringify(summarizeSdkRequestForTrace(sdkParams))}`);
8019
+ }
7947
8020
  const effectiveProviderOptions = deepMergeProviderOptions(
7948
8021
  providerOptions,
7949
8022
  sdkParams.providerOptions
@@ -8104,6 +8177,9 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log14
8104
8177
  } else if (p15.type === "error") {
8105
8178
  const message = formatUpstreamError(p15.error);
8106
8179
  log14(`[gateway] stream provider error: ${message}`);
8180
+ if (options.trace) {
8181
+ log14(`[gateway] stream provider error detail: ${formatUpstreamErrorTrace(p15.error)}`);
8182
+ }
8107
8183
  flushBufferedText();
8108
8184
  emitStreamError(res, route, responseId, message, startSse);
8109
8185
  break;
@@ -8119,11 +8195,14 @@ async function handleStreamingRequest(res, route, providerOptions, parsed, log14
8119
8195
  }
8120
8196
  res.end();
8121
8197
  }
8122
- async function handleUnaryRequest(res, route, providerOptions, parsed, _log, options = {}) {
8198
+ async function handleUnaryRequest(res, route, providerOptions, parsed, log14, options = {}) {
8123
8199
  const sdkParams = applyClaudeCodeOAuthIdentity(route, translateRequest(parsed, {
8124
8200
  ...options.requestOptions,
8125
8201
  maxTools: maxToolsForNpm(route.npm)
8126
8202
  }));
8203
+ if (options.trace) {
8204
+ log14(`[gateway] sdk request: ${JSON.stringify(summarizeSdkRequestForTrace(sdkParams))}`);
8205
+ }
8127
8206
  const effectiveProviderOptions = deepMergeProviderOptions(
8128
8207
  providerOptions,
8129
8208
  sdkParams.providerOptions
@@ -8230,7 +8309,8 @@ async function resolveAntigravityLaunchRoutes(opts) {
8230
8309
  }
8231
8310
 
8232
8311
  // src/antigravity/launch-cli.ts
8233
- import { execFileSync as execFileSync2, execSync as execSync3, spawn as spawn4 } from "child_process";
8312
+ import { execFileSync as execFileSync2, execSync as execSync3 } from "child_process";
8313
+ import spawn4 from "cross-spawn";
8234
8314
  import { existsSync as existsSync6 } from "fs";
8235
8315
  import { homedir as homedir6 } from "os";
8236
8316
  import { join as join6 } from "path";
@@ -8290,8 +8370,7 @@ function launchAntigravityCli(env, extraArgs) {
8290
8370
  }
8291
8371
  const child = spawn4(binaryPath, extraArgs, {
8292
8372
  stdio: "inherit",
8293
- env,
8294
- shell: isWindows4
8373
+ env
8295
8374
  });
8296
8375
  const forward = (signal) => {
8297
8376
  child.kill(signal);
@@ -8589,11 +8668,17 @@ function launchAntigravityApp(env, profileDir, gatewayUrl, extraArgs) {
8589
8668
  }
8590
8669
  function launchAntigravityIde(env, profileDir, gatewayUrl, extraArgs) {
8591
8670
  return new Promise((resolve2) => {
8671
+ let settled = false;
8672
+ const settle = (code) => {
8673
+ if (settled) return;
8674
+ settled = true;
8675
+ resolve2(code);
8676
+ };
8592
8677
  const binaryPath = findAntigravityIdeBinary();
8593
8678
  if (!binaryPath) {
8594
8679
  console.error("Antigravity IDE not found.");
8595
8680
  console.error("Please make sure Antigravity IDE is installed.");
8596
- resolve2(127);
8681
+ settle(127);
8597
8682
  return;
8598
8683
  }
8599
8684
  prepareIdeProfile(profileDir, gatewayUrl);
@@ -8612,12 +8697,15 @@ function launchAntigravityIde(env, profileDir, gatewayUrl, extraArgs) {
8612
8697
  detached: true,
8613
8698
  env
8614
8699
  });
8700
+ child.on("spawn", () => {
8701
+ settle(0);
8702
+ });
8615
8703
  child.on("exit", (code) => {
8616
- resolve2(code ?? 1);
8704
+ settle(code ?? 1);
8617
8705
  });
8618
8706
  child.on("error", (err) => {
8619
8707
  console.error(`Failed to launch Antigravity IDE: ${err.message}`);
8620
- resolve2(1);
8708
+ settle(1);
8621
8709
  });
8622
8710
  });
8623
8711
  }
@@ -8809,12 +8897,20 @@ async function resolveAndBuildRoutes(provider, model, allProviders, prefs, opts)
8809
8897
  }
8810
8898
  return { routes: result.routes, apiKey: result.apiKey };
8811
8899
  }
8812
- function waitForShutdown() {
8900
+ function waitForShutdown(input = process.stdin, platform = process.platform) {
8813
8901
  return new Promise((resolve2) => {
8902
+ const captureWindowsCtrlC = platform === "win32" && input.isTTY;
8903
+ const wasRaw = input.isRaw;
8904
+ const wasPaused = input.isPaused();
8814
8905
  const cleanup = () => {
8815
8906
  process.removeListener("SIGINT", onSigint);
8816
8907
  process.removeListener("SIGTERM", onSigterm);
8817
8908
  process.removeListener("SIGHUP", onSighup);
8909
+ if (captureWindowsCtrlC) {
8910
+ input.removeListener("data", onInput);
8911
+ input.setRawMode(wasRaw);
8912
+ if (wasPaused) input.pause();
8913
+ }
8818
8914
  };
8819
8915
  const onSigint = () => {
8820
8916
  cleanup();
@@ -8828,9 +8924,18 @@ function waitForShutdown() {
8828
8924
  cleanup();
8829
8925
  resolve2("sighup");
8830
8926
  };
8927
+ const onInput = (chunk) => {
8928
+ const receivedCtrlC = typeof chunk === "string" ? chunk.includes("") : chunk.includes(3);
8929
+ if (receivedCtrlC) onSigint();
8930
+ };
8831
8931
  process.once("SIGINT", onSigint);
8832
8932
  process.once("SIGTERM", onSigterm);
8833
8933
  process.once("SIGHUP", onSighup);
8934
+ if (captureWindowsCtrlC) {
8935
+ input.on("data", onInput);
8936
+ input.setRawMode(true);
8937
+ input.resume();
8938
+ }
8834
8939
  });
8835
8940
  }
8836
8941
  async function runAntigravityCommand(intro, tracePrefix, trace, boot, launch, opts = {}) {
@@ -8864,14 +8969,8 @@ async function runAntigravityCommand(intro, tracePrefix, trace, boot, launch, op
8864
8969
  lastAntigravityProvider: provider.id,
8865
8970
  lastAntigravityModel: model.id
8866
8971
  });
8867
- const traceLogPath = `/tmp/relay-ai-${tracePrefix}-trace-${Date.now()}.log`;
8868
- const logFn = trace ? (msg) => {
8869
- try {
8870
- appendFileSync2(traceLogPath, `${msg}
8871
- `);
8872
- } catch {
8873
- }
8874
- } : void 0;
8972
+ const traceLogPath = trace ? getAntigravityDebugLogPath(tracePrefix) : void 0;
8973
+ const logFn = traceLogPath ? makeTraceLogger(traceLogPath) : void 0;
8875
8974
  let gatewayHandle;
8876
8975
  try {
8877
8976
  gatewayHandle = await startCloudCodeGateway(routeResult.routes, { trace, logFn });
@@ -8881,7 +8980,7 @@ async function runAntigravityCommand(intro, tracePrefix, trace, boot, launch, op
8881
8980
  }
8882
8981
  p11.log.info(`Cloud Code gateway on ${pc9.cyan(`127.0.0.1:${gatewayHandle.port}`)}`);
8883
8982
  p11.log.success(`Active model: ${formatCodexModelLabel(model)} ${pc9.dim("via")} ${provider.name}`);
8884
- if (trace) p11.log.info(`Gateway trace \u2192 ${pc9.dim(traceLogPath)}`);
8983
+ if (traceLogPath) p11.log.info(`Gateway trace \u2192 ${pc9.dim(traceLogPath)}`);
8885
8984
  relayOutro("Launching", `${formatCodexModelLabel(model)} (${provider.name})`);
8886
8985
  try {
8887
8986
  const cleanEnv = buildAntigravityChildEnv(gatewayHandle.url);
@@ -12611,7 +12710,7 @@ ${pc12.bold("Usage:")}
12611
12710
  ${pc12.bold("Relay options:")}
12612
12711
  --provider <id> Use a specific provider (skip picker)
12613
12712
  --model <id> Use a specific model (skip picker)
12614
- --trace Write debug log to /tmp/relay-ai-debug.log
12713
+ --trace Write debug log to ~/.relay-ai/logs/antigravity-agy-debug.log
12615
12714
  -h, --help Show this help
12616
12715
  -v, --version Show version
12617
12716
 
@@ -12637,7 +12736,7 @@ ${pc12.bold("Usage:")}
12637
12736
  ${pc12.bold("Relay options:")}
12638
12737
  --provider <id> Use a specific provider (skip picker)
12639
12738
  --model <id> Use a specific model (skip picker)
12640
- --trace Write debug log to /tmp/relay-ai-debug.log
12739
+ --trace Write debug log to ~/.relay-ai/logs/antigravity-ide-debug.log
12641
12740
  -h, --help Show this help
12642
12741
  -v, --version Show version
12643
12742
 
@@ -12665,7 +12764,7 @@ ${pc12.bold("Usage:")}
12665
12764
  ${pc12.bold("Relay options:")}
12666
12765
  --provider <id> Use a specific provider (skip picker)
12667
12766
  --model <id> Use a specific model (skip picker)
12668
- --trace Write debug log to /tmp/relay-ai-debug.log
12767
+ --trace Write debug log to ~/.relay-ai/logs/antigravity-app-debug.log
12669
12768
  -h, --help Show this help
12670
12769
  -v, --version Show version
12671
12770
 
@@ -13393,7 +13492,7 @@ Options:
13393
13492
  --trace Write debug logs under ~/.relay-ai/logs/`);
13394
13493
  return 0;
13395
13494
  }
13396
- const { runUiCommand } = await import("./ui-command-CF3IEIZP.js");
13495
+ const { runUiCommand } = await import("./ui-command-27X4WJKC.js");
13397
13496
  return runUiCommand({ trace: parsed.trace, serverMode: parsed.uiServerMode });
13398
13497
  }
13399
13498
  if (parsed.command === "models") {