@jeffreycao/copilot-api 2.1.2 → 2.1.4

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/main.js CHANGED
@@ -25,7 +25,7 @@ bindElectronFetch();
25
25
  const { auth } = await import("./auth-DH-ThnhJ.js");
26
26
  const { debug } = await import("./debug-D2giR-Kj.js");
27
27
  const { mcp } = await import("./mcp-BG6fpi6q.js");
28
- const { start } = await import("./start-B5OlQ3jG.js");
28
+ const { start } = await import("./start-B5CJA1Cx.js");
29
29
  await runMain(defineCommand({
30
30
  meta: {
31
31
  name: "copilot-api",
@@ -7339,9 +7339,9 @@ async function handleCompletionPayload(c, anthropicPayload, dispatchOptions = {}
7339
7339
  debugJson(logger$9, "Anthropic request payload:", anthropicPayload);
7340
7340
  normalizeSystemMessages(anthropicPayload);
7341
7341
  sanitizeIdeTools(anthropicPayload);
7342
- const subagentMarker = parseSubagentMarkerFromFirstUser(anthropicPayload);
7342
+ const subagentMarker = dispatchOptions.subagentMarker ?? parseSubagentMarkerFromFirstUser(anthropicPayload);
7343
7343
  if (subagentMarker) debugJson(logger$9, "Detected Subagent marker:", subagentMarker);
7344
- let sessionId = getRootSessionId(anthropicPayload, c);
7344
+ let sessionId = dispatchOptions.sessionId ?? getRootSessionId(anthropicPayload, c);
7345
7345
  const compactType = dispatchOptions.compactType ?? getCompactType(anthropicPayload);
7346
7346
  const anthropicBeta = c.req.header("anthropic-beta");
7347
7347
  logger$9.debug("Anthropic Beta header:", anthropicBeta);
@@ -7357,7 +7357,7 @@ async function handleCompletionPayload(c, anthropicPayload, dispatchOptions = {}
7357
7357
  mergeToolResultForClaude(anthropicPayload, { skipLastMessage: compactType === 1 });
7358
7358
  applyLastMessageCacheControl(anthropicPayload, lastMessageCacheControl);
7359
7359
  }
7360
- const requestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
7360
+ const requestId = dispatchOptions.requestId ?? generateRequestIdFromPayload(anthropicPayload, sessionId);
7361
7361
  logger$9.debug("Generated request ID:", requestId);
7362
7362
  if (!sessionId) sessionId = getUUID(requestId);
7363
7363
  logger$9.debug("Extracted session ID:", sessionId);
@@ -7450,6 +7450,10 @@ const DEFAULT_REASONING_EFFORTS = [
7450
7450
  "max",
7451
7451
  "ultra"
7452
7452
  ];
7453
+ const CODEX_ALIAS_PRIORITY_BASE = 1e3;
7454
+ const COPILOT_PRIORITY_BASE = 2e3;
7455
+ const OPENCODE_GO_PRIORITY_BASE = 3e3;
7456
+ const PROVIDER_PRIORITY_BASE = 4e3;
7453
7457
  const DEFAULT_CODEX_TEMPLATE = {
7454
7458
  slug: "gpt-5.6-sol",
7455
7459
  display_name: "GPT-5.6-Sol",
@@ -7703,25 +7707,33 @@ async function handleMergedCodexModels(c, candidatesRequest, options = {}) {
7703
7707
  const template = selectTemplate(upstreamModels);
7704
7708
  const catalogModelsBySlug = new Map(upstreamModels.map((model) => [model.slug, model]));
7705
7709
  const seenSlugs = new Set(upstreamModels.map((model) => model.slug));
7706
- const codexProviderAliases = options.includeCodexProviderAliases ? upstreamModels.flatMap((model) => {
7710
+ const codexProviderAliases = options.includeCodexProviderAliases ? upstreamModels.flatMap((model, index) => {
7707
7711
  const slug = `codex/${model.slug}`;
7708
7712
  if (seenSlugs.has(slug)) return [];
7709
7713
  seenSlugs.add(slug);
7710
- return [createCatalogAlias(model, slug, options.codexProviderName)];
7714
+ return [{
7715
+ ...createCatalogAlias(model, slug, options.codexProviderName),
7716
+ priority: CODEX_ALIAS_PRIORITY_BASE + index
7717
+ }];
7711
7718
  }) : [];
7712
7719
  const syntheticModels = candidates.filter((candidate) => !seenSlugs.has(candidate.slug)).flatMap((candidate, index) => {
7720
+ const priorityBase = getCandidatePriorityBase(candidate);
7713
7721
  const catalogModel = candidate.catalogSlug ? catalogModelsBySlug.get(candidate.catalogSlug) : void 0;
7714
- if (catalogModel) return [createCatalogAlias(catalogModel, candidate.slug, candidate.providerName)];
7722
+ if (catalogModel) return [{
7723
+ ...createCatalogAlias(catalogModel, candidate.slug, candidate.providerName),
7724
+ priority: priorityBase + index
7725
+ }];
7715
7726
  if (candidate.catalogMatchRequired) return [];
7716
- return [createSyntheticCodexModel(candidate, template, upstreamModels.length + index)];
7727
+ return [createSyntheticCodexModel(candidate, template, priorityBase + index)];
7717
7728
  });
7729
+ const models = [
7730
+ ...upstreamModels,
7731
+ ...codexProviderAliases,
7732
+ ...syntheticModels
7733
+ ].sort((a, b) => getModelPriority(a) - getModelPriority(b));
7718
7734
  const response = {
7719
7735
  ...upstreamCatalog ?? {},
7720
- models: [
7721
- ...upstreamModels,
7722
- ...codexProviderAliases,
7723
- ...syntheticModels
7724
- ]
7736
+ models
7725
7737
  };
7726
7738
  debugJson(logger$8, "models.codex.merged_response", {
7727
7739
  upstreamCount: upstreamModels.length,
@@ -7824,6 +7836,14 @@ async function tryGetCodexCatalog(c) {
7824
7836
  function selectTemplate(models) {
7825
7837
  return models.find((model) => model.visibility === "list" && model.supported_in_api !== false) ?? models[0] ?? DEFAULT_CODEX_TEMPLATE;
7826
7838
  }
7839
+ function getModelPriority(model) {
7840
+ return typeof model.priority === "number" && Number.isFinite(model.priority) ? model.priority : 0;
7841
+ }
7842
+ function getCandidatePriorityBase(candidate) {
7843
+ if (!candidate.providerName) return COPILOT_PRIORITY_BASE;
7844
+ if (candidate.providerName === "opencode-go") return OPENCODE_GO_PRIORITY_BASE;
7845
+ return PROVIDER_PRIORITY_BASE;
7846
+ }
7827
7847
  function isCodexModelsResponse(value) {
7828
7848
  if (!isRecord$2(value) || !Array.isArray(value.models)) return false;
7829
7849
  return value.models.every((model) => isRecord$2(model) && typeof model.slug === "string");
@@ -7961,7 +7981,7 @@ async function getSyntheticCodexModels(requestHeaders, providers) {
7961
7981
  function getCopilotCodexCandidates() {
7962
7982
  const candidates = [];
7963
7983
  for (const model of state.models?.data ?? []) try {
7964
- if (isCopilotMessagesFallbackModel(model)) candidates.push(createCopilotCodexCandidate(model));
7984
+ if (isCopilotCodexCandidate(model)) candidates.push(createCopilotCodexCandidate(model));
7965
7985
  } catch (error) {
7966
7986
  logger$7.warn("models.codex.copilot_skip_error", {
7967
7987
  modelId: model.id,
@@ -7970,17 +7990,17 @@ function getCopilotCodexCandidates() {
7970
7990
  }
7971
7991
  return candidates;
7972
7992
  }
7973
- function isCopilotMessagesFallbackModel(model) {
7974
- const endpoints = model.supported_endpoints ?? [];
7975
- return endpoints.some((endpoint) => endpoint === MESSAGES_ENDPOINT || endpoint === CHAT_COMPLETIONS_ENDPOINT) && !endpoints.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint)) && model.capabilities.supports.tool_calls !== false;
7993
+ function isCopilotCodexCandidate(model) {
7994
+ return (model.supported_endpoints ?? []).some((endpoint) => endpoint === MESSAGES_ENDPOINT || endpoint === CHAT_COMPLETIONS_ENDPOINT || RESPONSES_ENDPOINTS.has(endpoint)) && model.capabilities.supports.tool_calls !== false;
7976
7995
  }
7977
7996
  function createCopilotCodexCandidate(model) {
7978
7997
  const reasoningEfforts = normalizeReasoningEfforts(model.capabilities.supports.reasoning_effort);
7998
+ const usesNativeResponses = model.supported_endpoints?.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint));
7979
7999
  const usesNativeMessages = model.supported_endpoints?.includes(MESSAGES_ENDPOINT);
7980
8000
  return {
7981
8001
  slug: toClientModelId(model.id),
7982
8002
  displayName: model.name,
7983
- description: usesNativeMessages ? `${model.name} through the Copilot Messages adapter.` : `${model.name} through the Copilot Messages-to-Chat adapter.`,
8003
+ description: usesNativeResponses ? `${model.name} through the Copilot Responses API.` : usesNativeMessages ? `${model.name} through the Copilot Messages adapter.` : `${model.name} through the Copilot Messages-to-Chat adapter.`,
7984
8004
  contextWindow: positiveNumber(model.capabilities.limits.max_context_window_tokens, 256e3),
7985
8005
  maxOutputTokens: positiveNumber(model.capabilities.limits.max_output_tokens, 32e3),
7986
8006
  inputModalities: model.capabilities.supports.vision ? ["text", "image"] : ["text"],
@@ -9056,9 +9076,9 @@ var CustomToolInputStreamDecoder = class {
9056
9076
  this.encodedInput = this.encodedInput.slice(this.safeInputLength);
9057
9077
  this.safeInputLength = 0;
9058
9078
  }
9059
- fail(reason) {
9079
+ fail(_reason) {
9060
9080
  this.failed = true;
9061
- throw new ResponsesMessagesTranslationError(`Messages API returned invalid custom tool input JSON at offset ${this.offset}: ${reason}`, 502);
9081
+ throw new ResponsesMessagesTranslationError(`Invalid tool input JSON. Expected format: {"input":"..."}`, 502);
9062
9082
  }
9063
9083
  };
9064
9084
  function isJsonWhitespace(char) {
@@ -9744,7 +9764,10 @@ async function handleResponsesViaMessages(c, options) {
9744
9764
  skipClaudeAutoModel: true,
9745
9765
  skipModelMapping: true,
9746
9766
  skipWebSearch: true,
9747
- usageEndpoint: "responses"
9767
+ usageEndpoint: "responses",
9768
+ subagentMarker: options.subagentMarker,
9769
+ requestId: options.requestId,
9770
+ sessionId: options.sessionId
9748
9771
  });
9749
9772
  if (!messagesResponse.ok) return messagesResponse;
9750
9773
  if ((messagesResponse.headers.get("content-type") ?? "").includes("text/event-stream")) {
@@ -10008,18 +10031,18 @@ const handleResponses = async (c) => {
10008
10031
  const selectedModel = responsesHandlerDependencies.findEndpointModel(payload.model);
10009
10032
  payload.model = selectedModel?.id ?? payload.model;
10010
10033
  const responsesTransport = getResponsesTransportForModel(selectedModel);
10011
- if (!responsesTransport) {
10012
- const supportedEndpoints = selectedModel?.supported_endpoints ?? [];
10013
- if (supportedEndpoints.includes("/v1/messages") || supportedEndpoints.includes("/chat/completions")) return await handleResponsesViaMessages(c, {
10014
- payload,
10015
- publicModel: requestedModel,
10016
- targetModel: payload.model
10017
- });
10018
- return c.json({ error: {
10019
- message: "This model does not support the responses endpoint. Please choose a different model.",
10020
- type: "invalid_request_error"
10021
- } }, 400);
10022
- }
10034
+ if (shouldFallbackToMessages(c, payload.model, selectedModel, responsesTransport)) return await handleResponsesViaMessages(c, {
10035
+ payload,
10036
+ publicModel: requestedModel,
10037
+ targetModel: payload.model,
10038
+ subagentMarker,
10039
+ requestId,
10040
+ sessionId: fallbackSessionId
10041
+ });
10042
+ if (!responsesTransport) return c.json({ error: {
10043
+ message: "This model does not support the responses endpoint. Please choose a different model.",
10044
+ type: "invalid_request_error"
10045
+ } }, 400);
10023
10046
  const recordUsage = createCopilotTokenUsageRecorder({
10024
10047
  endpoint: "responses",
10025
10048
  fallbackSessionId,
@@ -10080,6 +10103,12 @@ const handleResponses = async (c) => {
10080
10103
  return c.json(result);
10081
10104
  };
10082
10105
  const isStreamingRequested = (payload) => Boolean(payload.stream);
10106
+ const shouldFallbackToMessages = (c, modelId, selectedModel, responsesTransport) => {
10107
+ if (isCodexUserAgent(c.req.header("user-agent"))) return !modelId.startsWith("gpt");
10108
+ if (responsesTransport) return false;
10109
+ const supportedEndpoints = selectedModel?.supported_endpoints ?? [];
10110
+ return supportedEndpoints.includes("/v1/messages") || supportedEndpoints.includes("/chat/completions");
10111
+ };
10083
10112
  const parseResponsesStreamEvent = (chunk) => {
10084
10113
  const data = chunk.data;
10085
10114
  if (!data || data === "[DONE]") return null;
@@ -10276,4 +10305,4 @@ server.route("/:provider/images", providerImageRoutes);
10276
10305
  //#endregion
10277
10306
  export { server };
10278
10307
 
10279
- //# sourceMappingURL=server-CFiLrT2j.js.map
10308
+ //# sourceMappingURL=server-BwT9agIL.js.map