@hsupu/copilot-api 0.7.18 → 0.7.19

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.
@@ -56,7 +56,7 @@ model_overrides:
56
56
  stream_idle_timeout: 300 # Max seconds between SSE events (0 = no timeout).
57
57
  # Applies to all streaming paths (Anthropic, Chat Completions, Responses).
58
58
 
59
- fetch_timeout: 60 # Seconds: request start → HTTP response headers (0 = no timeout).
59
+ fetch_timeout: 300 # Seconds: request start → HTTP response headers (0 = no timeout).
60
60
  # Applies to all upstream API clients.
61
61
 
62
62
  stale_request_max_age: 600 # Max seconds an active request can live before the stale reaper
package/dist/main.mjs CHANGED
@@ -63,24 +63,25 @@ const DEFAULT_MODEL_OVERRIDES = {
63
63
  };
64
64
  const state = {
65
65
  accountType: "individual",
66
- modelIndex: /* @__PURE__ */ new Map(),
67
- modelIds: /* @__PURE__ */ new Set(),
68
- showGitHubToken: false,
69
- verbose: false,
70
66
  autoTruncate: true,
71
67
  compressToolResultsBeforeTruncate: true,
72
68
  convertServerToolsToCustom: true,
73
- modelOverrides: { ...DEFAULT_MODEL_OVERRIDES },
74
69
  dedupToolCalls: false,
75
- rewriteSystemReminders: false,
76
- truncateReadToolResult: false,
77
- systemPromptOverrides: [],
70
+ fetchTimeout: 300,
71
+ filterToolSearchBlocks: false,
78
72
  historyLimit: 200,
79
- fetchTimeout: 60,
80
- streamIdleTimeout: 300,
81
- shutdownGracefulWait: 60,
73
+ modelIds: /* @__PURE__ */ new Set(),
74
+ modelIndex: /* @__PURE__ */ new Map(),
75
+ modelOverrides: { ...DEFAULT_MODEL_OVERRIDES },
76
+ rewriteSystemReminders: false,
77
+ showGitHubToken: false,
82
78
  shutdownAbortWait: 120,
83
- staleRequestMaxAge: 600
79
+ shutdownGracefulWait: 60,
80
+ staleRequestMaxAge: 600,
81
+ streamIdleTimeout: 300,
82
+ systemPromptOverrides: [],
83
+ truncateReadToolResult: false,
84
+ verbose: false
84
85
  };
85
86
 
86
87
  //#endregion
@@ -105,7 +106,7 @@ const GITHUB_API_VERSION = "2022-11-28";
105
106
  */
106
107
  const INTERACTION_ID = randomUUID();
107
108
  const copilotBaseUrl = (state) => state.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${state.accountType}.githubcopilot.com`;
108
- const copilotHeaders = (state, vision = false) => {
109
+ const copilotHeaders = (state, opts) => {
109
110
  const headers = {
110
111
  Authorization: `Bearer ${state.copilotToken}`,
111
112
  "content-type": standardHeaders()["content-type"],
@@ -113,13 +114,17 @@ const copilotHeaders = (state, vision = false) => {
113
114
  "editor-version": `vscode/${state.vsCodeVersion}`,
114
115
  "editor-plugin-version": EDITOR_PLUGIN_VERSION,
115
116
  "user-agent": USER_AGENT,
116
- "openai-intent": "conversation-panel",
117
+ "openai-intent": opts?.intent ?? "conversation-panel",
117
118
  "x-github-api-version": COPILOT_API_VERSION,
118
119
  "x-request-id": randomUUID(),
119
120
  "X-Interaction-Id": INTERACTION_ID,
120
121
  "x-vscode-user-agent-library-version": "electron-fetch"
121
122
  };
122
- if (vision) headers["copilot-vision-request"] = "true";
123
+ if (opts?.vision) headers["copilot-vision-request"] = "true";
124
+ if (opts?.modelRequestHeaders) {
125
+ const coreKeysLower = new Set(Object.keys(headers).map((k) => k.toLowerCase()));
126
+ for (const [key, value] of Object.entries(opts.modelRequestHeaders)) if (!coreKeysLower.has(key.toLowerCase())) headers[key] = value;
127
+ }
123
128
  return headers;
124
129
  };
125
130
  const GITHUB_API_BASE_URL = "https://api.github.com";
@@ -744,7 +749,10 @@ function forwardError(c, error) {
744
749
  consola.warn(`HTTP 429: Rate limit exceeded`);
745
750
  return c.json(formattedError, 429);
746
751
  }
747
- consola.error(`HTTP ${error.status}:`, errorJson);
752
+ if (typeof errorJson === "string") {
753
+ const preview = errorJson.trimStart().startsWith("<") ? `[HTML ${errorJson.length} bytes]` : truncateForLog(errorJson, 200);
754
+ consola.error(`HTTP ${error.status}: ${preview}`);
755
+ } else consola.error(`HTTP ${error.status}:`, errorJson);
748
756
  return c.json({ error: {
749
757
  message: error.responseText,
750
758
  type: "error"
@@ -984,6 +992,11 @@ function formatErrorWithCause(error) {
984
992
  if (error.cause instanceof Error && error.cause.message && error.cause.message !== error.message) msg += ` (cause: ${stripBunVerboseHint(error.cause.message)})`;
985
993
  return msg;
986
994
  }
995
+ /** Truncate a string for log display, adding ellipsis if truncated */
996
+ function truncateForLog(text, maxLen) {
997
+ if (text.length <= maxLen) return text;
998
+ return `${text.slice(0, maxLen)}… (${text.length} bytes total)`;
999
+ }
987
1000
  /** Extract error message with fallback. For HTTPError, extracts the actual API error response. */
988
1001
  function getErrorMessage(error, fallback = "Unknown error") {
989
1002
  if (error instanceof Error) {
@@ -4268,7 +4281,7 @@ const setupClaudeCode = defineCommand({
4268
4281
 
4269
4282
  //#endregion
4270
4283
  //#region package.json
4271
- var version = "0.7.18";
4284
+ var version = "0.7.19";
4272
4285
 
4273
4286
  //#endregion
4274
4287
  //#region src/lib/config/config.ts
@@ -4367,6 +4380,7 @@ async function applyConfigToState() {
4367
4380
  if (a.convert_server_tools_to_custom !== void 0) state.convertServerToolsToCustom = a.convert_server_tools_to_custom;
4368
4381
  if (a.dedup_tool_calls !== void 0) state.dedupToolCalls = a.dedup_tool_calls === true ? "input" : a.dedup_tool_calls;
4369
4382
  if (a.truncate_read_tool_result !== void 0) state.truncateReadToolResult = a.truncate_read_tool_result;
4383
+ if (a.filter_tool_search_blocks !== void 0) state.filterToolSearchBlocks = a.filter_tool_search_blocks;
4370
4384
  if (a.rewrite_system_reminders !== void 0) {
4371
4385
  if (typeof a.rewrite_system_reminders === "boolean") state.rewriteSystemReminders = a.rewrite_system_reminders;
4372
4386
  else if (Array.isArray(a.rewrite_system_reminders)) state.rewriteSystemReminders = compileRewriteRules(a.rewrite_system_reminders);
@@ -4578,7 +4592,8 @@ function toHistoryResponse(entryData) {
4578
4592
  input_tokens: r.usage.input_tokens,
4579
4593
  output_tokens: r.usage.output_tokens,
4580
4594
  cache_read_input_tokens: r.usage.cache_read_input_tokens,
4581
- cache_creation_input_tokens: r.usage.cache_creation_input_tokens
4595
+ cache_creation_input_tokens: r.usage.cache_creation_input_tokens,
4596
+ output_tokens_details: r.usage.output_tokens_details
4582
4597
  },
4583
4598
  stop_reason: r.stop_reason,
4584
4599
  error: r.error,
@@ -5343,30 +5358,31 @@ function mapAnthropicContentBlocks(acc) {
5343
5358
  const { _generic: _, ...rest } = block;
5344
5359
  return rest;
5345
5360
  }
5346
- switch (block.type) {
5361
+ if ("_brand" in block) return {
5362
+ type: block.type,
5363
+ tool_use_id: block.tool_use_id,
5364
+ content: block.content
5365
+ };
5366
+ const narrowed = block;
5367
+ switch (narrowed.type) {
5347
5368
  case "text": return {
5348
5369
  type: "text",
5349
- text: block.text
5370
+ text: narrowed.text
5350
5371
  };
5351
5372
  case "thinking": return {
5352
5373
  type: "thinking",
5353
- thinking: block.thinking
5374
+ thinking: narrowed.thinking
5354
5375
  };
5355
5376
  case "redacted_thinking": return { type: "redacted_thinking" };
5356
5377
  case "tool_use":
5357
5378
  case "server_tool_use": return {
5358
- type: block.type,
5359
- id: block.id,
5360
- name: block.name,
5361
- input: safeParseJson(block.input)
5362
- };
5363
- case "web_search_tool_result": return {
5364
- type: "web_search_tool_result",
5365
- tool_use_id: block.tool_use_id,
5366
- content: block.content
5379
+ type: narrowed.type,
5380
+ id: narrowed.id,
5381
+ name: narrowed.name,
5382
+ input: safeParseJson(narrowed.input)
5367
5383
  };
5368
5384
  default: {
5369
- const unknown = block;
5385
+ const unknown = narrowed;
5370
5386
  consola.warn(`[recording] Unhandled content block type in stream result: ${unknown.type}`);
5371
5387
  return { type: unknown.type };
5372
5388
  }
@@ -5419,6 +5435,7 @@ function buildOpenAIResponseData(acc, fallbackModel) {
5419
5435
  usage: {
5420
5436
  input_tokens: acc.inputTokens,
5421
5437
  output_tokens: acc.outputTokens,
5438
+ ...acc.reasoningTokens > 0 && { output_tokens_details: { reasoning_tokens: acc.reasoningTokens } },
5422
5439
  ...acc.cachedTokens > 0 && { cache_read_input_tokens: acc.cachedTokens }
5423
5440
  },
5424
5441
  stop_reason: acc.finishReason || void 0,
@@ -5640,12 +5657,17 @@ async function processResponsesInstructions(instructions, model) {
5640
5657
  //#endregion
5641
5658
  //#region src/lib/openai/responses-client.ts
5642
5659
  /** Call Copilot /responses endpoint */
5643
- const createResponses = async (payload) => {
5660
+ const createResponses = async (payload, opts) => {
5644
5661
  if (!state.copilotToken) throw new Error("Copilot token not found");
5645
5662
  const enableVision = hasVisionContent(payload.input);
5646
5663
  const isAgentCall = Array.isArray(payload.input) && payload.input.some((item) => item.role === "assistant" || item.type === "function_call" || item.type === "function_call_output");
5664
+ const modelSupportsVision = opts?.resolvedModel?.capabilities?.supports?.vision !== false;
5647
5665
  const headers = {
5648
- ...copilotHeaders(state, enableVision),
5666
+ ...copilotHeaders(state, {
5667
+ vision: enableVision && modelSupportsVision,
5668
+ modelRequestHeaders: opts?.resolvedModel?.request_headers,
5669
+ intent: isAgentCall ? "conversation-agent" : "conversation-panel"
5670
+ }),
5649
5671
  "X-Initiator": isAgentCall ? "agent" : "user"
5650
5672
  };
5651
5673
  const fetchSignal = createFetchSignal();
@@ -5771,7 +5793,7 @@ function createTokenRefreshStrategy() {
5771
5793
  * centralizes that configuration to avoid duplication.
5772
5794
  */
5773
5795
  /** Create the FormatAdapter for Responses API pipeline execution */
5774
- function createResponsesAdapter() {
5796
+ function createResponsesAdapter(selectedModel) {
5775
5797
  return {
5776
5798
  format: "openai-responses",
5777
5799
  sanitize: (p) => ({
@@ -5779,7 +5801,7 @@ function createResponsesAdapter() {
5779
5801
  removedCount: 0,
5780
5802
  systemReminderRemovals: 0
5781
5803
  }),
5782
- execute: (p) => executeWithAdaptiveRateLimit(() => createResponses(p)),
5804
+ execute: (p) => executeWithAdaptiveRateLimit(() => createResponses(p, { resolvedModel: selectedModel })),
5783
5805
  logPayloadSize: (p) => {
5784
5806
  const count = typeof p.input === "string" ? 1 : p.input.length;
5785
5807
  consola.debug(`Responses payload: ${count} input item(s), model: ${p.model}`);
@@ -5871,7 +5893,7 @@ async function handleResponseCreate(ws, payload) {
5871
5893
  model: resolvedModel,
5872
5894
  clientModel: requestedModel
5873
5895
  });
5874
- const adapter = createResponsesAdapter();
5896
+ const adapter = createResponsesAdapter(selectedModel);
5875
5897
  const strategies = createResponsesStrategies();
5876
5898
  try {
5877
5899
  const iterator = (await executeRequestPipeline({
@@ -6689,12 +6711,17 @@ function createTruncationResponseMarkerOpenAI(result) {
6689
6711
 
6690
6712
  //#endregion
6691
6713
  //#region src/lib/openai/client.ts
6692
- const createChatCompletions = async (payload) => {
6714
+ const createChatCompletions = async (payload, opts) => {
6693
6715
  if (!state.copilotToken) throw new Error("Copilot token not found");
6694
6716
  const enableVision = payload.messages.some((x) => typeof x.content !== "string" && x.content?.some((x) => x.type === "image_url"));
6695
6717
  const isAgentCall = payload.messages.some((msg) => ["assistant", "tool"].includes(msg.role));
6718
+ const modelSupportsVision = opts?.resolvedModel?.capabilities?.supports?.vision !== false;
6696
6719
  const headers = {
6697
- ...copilotHeaders(state, enableVision),
6720
+ ...copilotHeaders(state, {
6721
+ vision: enableVision && modelSupportsVision,
6722
+ modelRequestHeaders: opts?.resolvedModel?.request_headers,
6723
+ intent: isAgentCall ? "conversation-agent" : "conversation-panel"
6724
+ }),
6698
6725
  "X-Initiator": isAgentCall ? "agent" : "user"
6699
6726
  };
6700
6727
  const fetchSignal = createFetchSignal();
@@ -6823,6 +6850,7 @@ function createOpenAIStreamAccumulator() {
6823
6850
  inputTokens: 0,
6824
6851
  outputTokens: 0,
6825
6852
  cachedTokens: 0,
6853
+ reasoningTokens: 0,
6826
6854
  finishReason: "",
6827
6855
  content: "",
6828
6856
  toolCalls: [],
@@ -6836,6 +6864,7 @@ function accumulateOpenAIStreamEvent(parsed, acc) {
6836
6864
  acc.inputTokens = parsed.usage.prompt_tokens;
6837
6865
  acc.outputTokens = parsed.usage.completion_tokens;
6838
6866
  if (parsed.usage.prompt_tokens_details?.cached_tokens !== void 0) acc.cachedTokens = parsed.usage.prompt_tokens_details.cached_tokens;
6867
+ if (parsed.usage.completion_tokens_details?.reasoning_tokens !== void 0) acc.reasoningTokens = parsed.usage.completion_tokens_details.reasoning_tokens;
6839
6868
  }
6840
6869
  const choice = parsed.choices[0];
6841
6870
  if (choice) {
@@ -7088,7 +7117,7 @@ async function executeRequest(opts) {
7088
7117
  const adapter = {
7089
7118
  format: "openai-chat-completions",
7090
7119
  sanitize: (p) => sanitizeOpenAIMessages(p),
7091
- execute: (p) => executeWithAdaptiveRateLimit(() => createChatCompletions(p)),
7120
+ execute: (p) => executeWithAdaptiveRateLimit(() => createChatCompletions(p, { resolvedModel: selectedModel })),
7092
7121
  logPayloadSize: (p) => logPayloadSizeInfo(p, selectedModel)
7093
7122
  };
7094
7123
  const strategies = [
@@ -7978,9 +8007,6 @@ function contentToText(content, options) {
7978
8007
  case "server_tool_use":
7979
8008
  parts.push(`[server_tool_use: ${block.name}]`, JSON.stringify(block.input));
7980
8009
  break;
7981
- case "web_search_tool_result":
7982
- parts.push(`[web_search_tool_result]`);
7983
- break;
7984
8010
  default: {
7985
8011
  const genericBlock = block;
7986
8012
  if ("tool_use_id" in genericBlock && genericBlock.type !== "image") {
@@ -8679,7 +8705,7 @@ const NON_DEFERRED_TOOL_NAMES = new Set([
8679
8705
  "switch_agent",
8680
8706
  ...CLAUDE_CODE_OFFICIAL_TOOLS
8681
8707
  ]);
8682
- const TOOL_SEARCH_TOOL_NAME = "tool_search_tool_regex";
8708
+ const TOOL_SEARCH_TOOL_NAME$1 = "tool_search_tool_regex";
8683
8709
  const TOOL_SEARCH_TOOL_TYPE = "tool_search_tool_regex_20251119";
8684
8710
  const EMPTY_INPUT_SCHEMA = {
8685
8711
  type: "object",
@@ -8743,7 +8769,7 @@ function processToolPipeline(tools, modelId, messages) {
8743
8769
  const historyToolNames = toolSearchEnabled ? collectHistoryToolNames(messages) : void 0;
8744
8770
  const result = [];
8745
8771
  if (toolSearchEnabled) result.push({
8746
- name: TOOL_SEARCH_TOOL_NAME,
8772
+ name: TOOL_SEARCH_TOOL_NAME$1,
8747
8773
  type: TOOL_SEARCH_TOOL_TYPE,
8748
8774
  defer_loading: false
8749
8775
  });
@@ -8946,7 +8972,7 @@ function adjustThinkingBudget(wire) {
8946
8972
  * Create messages using Anthropic-style API directly.
8947
8973
  * Calls Copilot's native Anthropic endpoint for Anthropic-vendor models.
8948
8974
  */
8949
- async function createAnthropicMessages(payload) {
8975
+ async function createAnthropicMessages(payload, opts) {
8950
8976
  if (!state.copilotToken) throw new Error("Copilot token not found");
8951
8977
  const wire = buildWirePayload(payload);
8952
8978
  adjustThinkingBudget(wire);
@@ -8959,8 +8985,13 @@ async function createAnthropicMessages(payload) {
8959
8985
  return msg.content.some((block) => block.type === "image");
8960
8986
  });
8961
8987
  const isAgentCall = messages.some((msg) => msg.role === "assistant");
8988
+ const modelSupportsVision = opts?.resolvedModel?.capabilities?.supports?.vision !== false;
8962
8989
  const headers = {
8963
- ...copilotHeaders(state, enableVision),
8990
+ ...copilotHeaders(state, {
8991
+ vision: enableVision && modelSupportsVision,
8992
+ modelRequestHeaders: opts?.resolvedModel?.request_headers,
8993
+ intent: isAgentCall ? "conversation-agent" : "conversation-panel"
8994
+ }),
8964
8995
  "X-Initiator": isAgentCall ? "agent" : "user",
8965
8996
  "anthropic-version": "2023-06-01",
8966
8997
  ...buildAnthropicBetaHeaders(model)
@@ -9095,25 +9126,29 @@ function handleContentBlockStart(index, block, acc) {
9095
9126
  input: ""
9096
9127
  };
9097
9128
  break;
9098
- case "web_search_tool_result":
9099
- newBlock = {
9100
- type: "web_search_tool_result",
9101
- tool_use_id: block.tool_use_id,
9102
- content: block.content
9103
- };
9104
- break;
9105
- default: {
9106
- const unknownBlock = block;
9107
- consola.warn(`[stream-accumulator] Unknown content block type: ${String(unknownBlock.type)}`);
9129
+ default:
9130
+ if (isServerToolResultType(block.type) && "tool_use_id" in block) {
9131
+ newBlock = {
9132
+ _brand: "server_tool_result",
9133
+ type: block.type,
9134
+ tool_use_id: block.tool_use_id,
9135
+ content: block.content
9136
+ };
9137
+ break;
9138
+ }
9139
+ consola.warn(`[stream-accumulator] Unknown content block type: ${block.type}`);
9108
9140
  newBlock = {
9109
- ...unknownBlock,
9141
+ ...block,
9110
9142
  _generic: true
9111
9143
  };
9112
9144
  break;
9113
- }
9114
9145
  }
9115
9146
  acc.contentBlocks[index] = newBlock;
9116
9147
  }
9148
+ /** Check if a block type is a server-side tool result (ends with _tool_result, but not plain tool_result) */
9149
+ function isServerToolResultType(type) {
9150
+ return type !== "tool_result" && type.endsWith("_tool_result");
9151
+ }
9117
9152
  function handleContentBlockDelta(index, delta, acc, copilotAnnotations) {
9118
9153
  const block = acc.contentBlocks[index];
9119
9154
  if (!block) return;
@@ -9556,7 +9591,7 @@ async function handleDirectAnthropicCompletion(c, anthropicPayload, reqCtx) {
9556
9591
  const adapter = {
9557
9592
  format: "anthropic-messages",
9558
9593
  sanitize: (p) => sanitizeAnthropicMessages(preprocessTools(p)),
9559
- execute: (p) => executeWithAdaptiveRateLimit(() => createAnthropicMessages(p)),
9594
+ execute: (p) => executeWithAdaptiveRateLimit(() => createAnthropicMessages(p, { resolvedModel: selectedModel })),
9560
9595
  logPayloadSize: (p) => logPayloadSizeInfoAnthropic(p, selectedModel)
9561
9596
  };
9562
9597
  const strategies = [
@@ -9638,6 +9673,7 @@ async function handleDirectAnthropicStreamingResponse(opts) {
9638
9673
  let eventsIn = 0;
9639
9674
  let currentBlockType = "";
9640
9675
  let firstEventLogged = false;
9676
+ const toolSearchFilter = state.filterToolSearchBlocks ? createToolSearchBlockFilter() : null;
9641
9677
  try {
9642
9678
  for await (const { raw: rawEvent, parsed } of processAnthropicStream(response, acc, clientAbortSignal)) {
9643
9679
  const dataLen = rawEvent.data?.length ?? 0;
@@ -9670,8 +9706,10 @@ async function handleDirectAnthropicStreamingResponse(opts) {
9670
9706
  const delta = parsed.delta;
9671
9707
  if (delta.type === "text_delta" && delta.text) checkRepetition(delta.text);
9672
9708
  }
9709
+ const forwardData = toolSearchFilter ? toolSearchFilter.rewriteEvent(parsed, rawEvent.data ?? "") : rawEvent.data ?? "";
9710
+ if (forwardData === null) continue;
9673
9711
  await stream.writeSSE({
9674
- data: rawEvent.data ?? "",
9712
+ data: forwardData,
9675
9713
  event: rawEvent.event,
9676
9714
  id: rawEvent.id !== void 0 ? String(rawEvent.id) : void 0,
9677
9715
  retry: rawEvent.retry
@@ -9720,6 +9758,7 @@ function handleDirectAnthropicNonStreamingResponse(c, response, reqCtx, truncate
9720
9758
  });
9721
9759
  let finalResponse = response;
9722
9760
  if (state.verbose && truncateResult?.wasTruncated) finalResponse = prependMarkerToResponse(response, createTruncationMarker$1(truncateResult));
9761
+ if (state.filterToolSearchBlocks) finalResponse = filterToolSearchBlocksFromResponse(finalResponse);
9723
9762
  return c.json(finalResponse);
9724
9763
  }
9725
9764
  /** Convert SanitizationStats to the format expected by rewrites */
@@ -9733,6 +9772,69 @@ function toSanitizationInfo(stats) {
9733
9772
  systemReminderRemovals: stats.systemReminderRemovals
9734
9773
  };
9735
9774
  }
9775
+ const TOOL_SEARCH_TOOL_NAME = "tool_search_tool_regex";
9776
+ const TOOL_SEARCH_RESULT_TYPE = "tool_search_tool_result";
9777
+ /** Check if a content block is an internal tool_search block */
9778
+ function isToolSearchBlock(block) {
9779
+ if (block.type === "server_tool_use" && block.name === TOOL_SEARCH_TOOL_NAME) return true;
9780
+ if (block.type === TOOL_SEARCH_RESULT_TYPE) return true;
9781
+ return false;
9782
+ }
9783
+ /**
9784
+ * Filters tool_search blocks from the SSE stream before forwarding to the client.
9785
+ * Handles index remapping so block indices remain dense/sequential after filtering.
9786
+ */
9787
+ function createToolSearchBlockFilter() {
9788
+ const filteredIndices = /* @__PURE__ */ new Set();
9789
+ const clientIndexMap = /* @__PURE__ */ new Map();
9790
+ let nextClientIndex = 0;
9791
+ function getClientIndex(apiIndex) {
9792
+ let idx = clientIndexMap.get(apiIndex);
9793
+ if (idx === void 0) {
9794
+ idx = nextClientIndex++;
9795
+ clientIndexMap.set(apiIndex, idx);
9796
+ }
9797
+ return idx;
9798
+ }
9799
+ return { rewriteEvent(parsed, rawData) {
9800
+ if (!parsed) return rawData;
9801
+ if (parsed.type === "content_block_start") {
9802
+ const block = parsed.content_block;
9803
+ if (isToolSearchBlock(block)) {
9804
+ filteredIndices.add(parsed.index);
9805
+ return null;
9806
+ }
9807
+ if (filteredIndices.size === 0) {
9808
+ getClientIndex(parsed.index);
9809
+ return rawData;
9810
+ }
9811
+ const clientIndex = getClientIndex(parsed.index);
9812
+ if (clientIndex === parsed.index) return rawData;
9813
+ const obj = JSON.parse(rawData);
9814
+ obj.index = clientIndex;
9815
+ return JSON.stringify(obj);
9816
+ }
9817
+ if (parsed.type === "content_block_delta" || parsed.type === "content_block_stop") {
9818
+ if (filteredIndices.has(parsed.index)) return null;
9819
+ if (filteredIndices.size === 0) return rawData;
9820
+ const clientIndex = getClientIndex(parsed.index);
9821
+ if (clientIndex === parsed.index) return rawData;
9822
+ const obj = JSON.parse(rawData);
9823
+ obj.index = clientIndex;
9824
+ return JSON.stringify(obj);
9825
+ }
9826
+ return rawData;
9827
+ } };
9828
+ }
9829
+ /** Filter tool_search blocks from a non-streaming response */
9830
+ function filterToolSearchBlocksFromResponse(response) {
9831
+ const filtered = response.content.filter((block) => !isToolSearchBlock(block));
9832
+ if (filtered.length === response.content.length) return response;
9833
+ return {
9834
+ ...response,
9835
+ content: filtered
9836
+ };
9837
+ }
9736
9838
 
9737
9839
  //#endregion
9738
9840
  //#region src/routes/messages/route.ts
@@ -9840,9 +9942,9 @@ async function handleResponses(c) {
9840
9942
  /** Pass through to Copilot /responses endpoint directly */
9841
9943
  async function handleDirectResponses(opts) {
9842
9944
  const { c, payload, reqCtx } = opts;
9843
- const adapter = createResponsesAdapter();
9844
- const strategies = createResponsesStrategies();
9845
9945
  const selectedModel = state.modelIndex.get(payload.model);
9946
+ const adapter = createResponsesAdapter(selectedModel);
9947
+ const strategies = createResponsesStrategies();
9846
9948
  try {
9847
9949
  const pipelineResult = await executeRequestPipeline({
9848
9950
  adapter,
@@ -10072,7 +10174,16 @@ function parseIntOrDefault(value, defaultValue) {
10072
10174
  const parsed = Number.parseInt(value, 10);
10073
10175
  return Number.isFinite(parsed) ? parsed : defaultValue;
10074
10176
  }
10177
+ const VALID_ACCOUNT_TYPES = [
10178
+ "individual",
10179
+ "business",
10180
+ "enterprise"
10181
+ ];
10075
10182
  async function runServer(options) {
10183
+ if (!VALID_ACCOUNT_TYPES.includes(options.accountType)) {
10184
+ consola.error(`Invalid account type: "${options.accountType}". Must be one of: ${VALID_ACCOUNT_TYPES.join(", ")}`);
10185
+ process.exit(1);
10186
+ }
10076
10187
  if (options.verbose) {
10077
10188
  consola.level = 5;
10078
10189
  state.verbose = true;
@@ -10146,7 +10257,9 @@ async function runServer(options) {
10146
10257
  try {
10147
10258
  await cacheModels();
10148
10259
  } catch (error) {
10149
- consola.warn("Failed to fetch models from Copilot API:", error instanceof Error ? error.message : error);
10260
+ consola.error("Failed to fetch models from Copilot API:", error instanceof Error ? error.message : error);
10261
+ consola.error(`Verify that --account-type "${state.accountType}" is correct. Available types: ${VALID_ACCOUNT_TYPES.join(", ")}`);
10262
+ process.exit(1);
10150
10263
  }
10151
10264
  consola.info(`Available models:\n${state.models?.data.map((m) => formatModelInfo(m)).join("\n")}`);
10152
10265
  await loadPersistedLimits();