@ashsec/copilot-api 0.7.7 → 0.7.8

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
@@ -1922,7 +1922,7 @@ function translateAnthropicToolChoiceToOpenAI(anthropicToolChoice) {
1922
1922
  default: return;
1923
1923
  }
1924
1924
  }
1925
- function translateToAnthropic(response) {
1925
+ function translateToAnthropic(response, originalModel) {
1926
1926
  const allTextBlocks = [];
1927
1927
  const allToolUseBlocks = [];
1928
1928
  let stopReason = null;
@@ -1938,7 +1938,7 @@ function translateToAnthropic(response) {
1938
1938
  id: response.id,
1939
1939
  type: "message",
1940
1940
  role: "assistant",
1941
- model: response.model,
1941
+ model: originalModel ?? response.model,
1942
1942
  content: [...allTextBlocks, ...allToolUseBlocks],
1943
1943
  stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),
1944
1944
  stop_sequence: null,
@@ -2012,12 +2012,55 @@ function isToolBlockOpen(state$1) {
2012
2012
  if (!state$1.contentBlockOpen) return false;
2013
2013
  return Object.values(state$1.toolCalls).some((tc) => tc.anthropicBlockIndex === state$1.contentBlockIndex);
2014
2014
  }
2015
- function translateChunkToAnthropicEvents(chunk, state$1) {
2015
+ function createMessageDeltaEvents(finishReason, usage) {
2016
+ return [{
2017
+ type: "message_delta",
2018
+ delta: {
2019
+ stop_reason: mapOpenAIStopReasonToAnthropic(finishReason),
2020
+ stop_sequence: null
2021
+ },
2022
+ usage: {
2023
+ input_tokens: usage.prompt_tokens,
2024
+ output_tokens: usage.completion_tokens,
2025
+ cache_creation_input_tokens: 0,
2026
+ cache_read_input_tokens: usage.cached_tokens
2027
+ }
2028
+ }, { type: "message_stop" }];
2029
+ }
2030
+ function createFallbackMessageDeltaEvents(state$1) {
2031
+ if (state$1.messageDeltaSent) return [];
2032
+ if (state$1.pendingFinishReason) {
2033
+ const usage = state$1.pendingUsage ?? {
2034
+ prompt_tokens: 0,
2035
+ completion_tokens: 0,
2036
+ cached_tokens: 0
2037
+ };
2038
+ return createMessageDeltaEvents(state$1.pendingFinishReason, usage);
2039
+ }
2040
+ return [];
2041
+ }
2042
+ function translateChunkToAnthropicEvents(chunk, state$1, originalModel) {
2016
2043
  const events$1 = [];
2044
+ if (chunk.usage) {
2045
+ state$1.pendingUsage = {
2046
+ prompt_tokens: chunk.usage.prompt_tokens ?? 0,
2047
+ completion_tokens: chunk.usage.completion_tokens ?? 0,
2048
+ cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
2049
+ };
2050
+ if (state$1.pendingFinishReason && !state$1.messageDeltaSent) {
2051
+ events$1.push(...createMessageDeltaEvents(state$1.pendingFinishReason, state$1.pendingUsage));
2052
+ state$1.messageDeltaSent = true;
2053
+ }
2054
+ }
2017
2055
  if (chunk.choices.length === 0) return events$1;
2018
2056
  const choice = chunk.choices[0];
2019
2057
  const { delta } = choice;
2020
2058
  if (!state$1.messageStartSent) {
2059
+ const usage = state$1.pendingUsage ?? {
2060
+ prompt_tokens: 0,
2061
+ completion_tokens: 0,
2062
+ cached_tokens: 0
2063
+ };
2021
2064
  events$1.push({
2022
2065
  type: "message_start",
2023
2066
  message: {
@@ -2025,9 +2068,15 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
2025
2068
  type: "message",
2026
2069
  role: "assistant",
2027
2070
  content: [],
2028
- model: chunk.model,
2071
+ model: originalModel ?? chunk.model,
2029
2072
  stop_reason: null,
2030
- stop_sequence: null
2073
+ stop_sequence: null,
2074
+ usage: {
2075
+ input_tokens: usage.prompt_tokens,
2076
+ output_tokens: usage.completion_tokens,
2077
+ cache_creation_input_tokens: 0,
2078
+ cache_read_input_tokens: usage.cached_tokens
2079
+ }
2031
2080
  }
2032
2081
  });
2033
2082
  state$1.messageStartSent = true;
@@ -2109,28 +2158,44 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
2109
2158
  });
2110
2159
  state$1.contentBlockOpen = false;
2111
2160
  }
2112
- const inputTokens = chunk.usage?.prompt_tokens ?? 0;
2113
- const outputTokens = chunk.usage?.completion_tokens ?? 0;
2114
- const cachedTokens = chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0;
2115
- events$1.push({
2116
- type: "message_delta",
2117
- delta: {
2118
- stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),
2119
- stop_sequence: null
2120
- },
2121
- usage: {
2122
- input_tokens: inputTokens,
2123
- output_tokens: outputTokens,
2124
- cache_creation_input_tokens: 0,
2125
- cache_read_input_tokens: cachedTokens
2126
- }
2127
- }, { type: "message_stop" });
2161
+ if (chunk.usage || state$1.pendingUsage) {
2162
+ const usage = {
2163
+ prompt_tokens: chunk.usage?.prompt_tokens ?? state$1.pendingUsage?.prompt_tokens ?? 0,
2164
+ completion_tokens: chunk.usage?.completion_tokens ?? state$1.pendingUsage?.completion_tokens ?? 0,
2165
+ cached_tokens: chunk.usage?.prompt_tokens_details?.cached_tokens ?? state$1.pendingUsage?.cached_tokens ?? 0
2166
+ };
2167
+ events$1.push(...createMessageDeltaEvents(choice.finish_reason, usage));
2168
+ state$1.messageDeltaSent = true;
2169
+ } else state$1.pendingFinishReason = choice.finish_reason;
2128
2170
  }
2129
2171
  return events$1;
2130
2172
  }
2131
2173
 
2132
2174
  //#endregion
2133
2175
  //#region src/routes/messages/handler.ts
2176
+ /** Collect all chunks and extract usage data */
2177
+ async function collectChunksWithUsage(eventStream) {
2178
+ const chunks = [];
2179
+ let usage = null;
2180
+ for await (const event of eventStream) {
2181
+ if (!event.data || event.data === "[DONE]") continue;
2182
+ try {
2183
+ const chunk = JSON.parse(event.data);
2184
+ chunks.push(chunk);
2185
+ if (chunk.usage) usage = {
2186
+ prompt_tokens: chunk.usage.prompt_tokens,
2187
+ completion_tokens: chunk.usage.completion_tokens,
2188
+ cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
2189
+ };
2190
+ } catch (error) {
2191
+ consola.error("Failed to parse chunk:", error, event.data);
2192
+ }
2193
+ }
2194
+ return {
2195
+ chunks,
2196
+ usage
2197
+ };
2198
+ }
2134
2199
  async function handleCompletion(c) {
2135
2200
  await checkRateLimit(state);
2136
2201
  const anthropicPayload = await c.req.json();
@@ -2141,7 +2206,6 @@ async function handleCompletion(c) {
2141
2206
  ...openAIPayload,
2142
2207
  model: normalizeModelName(openAIPayload.model)
2143
2208
  };
2144
- consola.debug("Translated OpenAI request payload:", JSON.stringify(openAIPayload));
2145
2209
  if (state.manualApprove) await awaitApproval();
2146
2210
  const isAzureModel = isAzureOpenAIModel(openAIPayload.model);
2147
2211
  if (isAzureModel) {
@@ -2162,33 +2226,26 @@ async function handleCompletion(c) {
2162
2226
  };
2163
2227
  const eventStream = isAzureModel ? await createAzureOpenAIChatCompletions(state.azureOpenAIConfig, streamPayload) : await createChatCompletions(streamPayload);
2164
2228
  return streamSSE(c, async (stream) => {
2229
+ const { chunks, usage } = await collectChunksWithUsage(eventStream);
2230
+ if (usage) setRequestContext(c, {
2231
+ inputTokens: usage.prompt_tokens,
2232
+ outputTokens: usage.completion_tokens
2233
+ });
2165
2234
  const streamState = {
2166
2235
  messageStartSent: false,
2167
2236
  contentBlockOpen: false,
2168
2237
  contentBlockIndex: 0,
2169
- toolCalls: {}
2238
+ toolCalls: {},
2239
+ pendingUsage: usage ?? void 0
2170
2240
  };
2171
- for await (const event of eventStream) {
2172
- if (!event.data || event.data === "[DONE]") continue;
2173
- try {
2174
- const chunk = JSON.parse(event.data);
2175
- consola.debug("OpenAI chunk:", JSON.stringify(chunk));
2176
- const anthropicEvents = translateChunkToAnthropicEvents(chunk, streamState);
2177
- for (const anthropicEvent of anthropicEvents) {
2178
- consola.debug("Anthropic event:", JSON.stringify(anthropicEvent));
2179
- await stream.writeSSE({
2180
- event: anthropicEvent.type,
2181
- data: JSON.stringify(anthropicEvent)
2182
- });
2183
- }
2184
- if (chunk.usage) setRequestContext(c, {
2185
- inputTokens: chunk.usage.prompt_tokens,
2186
- outputTokens: chunk.usage.completion_tokens
2187
- });
2188
- } catch (error) {
2189
- consola.error("Failed to parse chunk:", error, event.data);
2190
- }
2191
- }
2241
+ for (const chunk of chunks) for (const evt of translateChunkToAnthropicEvents(chunk, streamState, anthropicPayload.model)) await stream.writeSSE({
2242
+ event: evt.type,
2243
+ data: JSON.stringify(evt)
2244
+ });
2245
+ for (const evt of createFallbackMessageDeltaEvents(streamState)) await stream.writeSSE({
2246
+ event: evt.type,
2247
+ data: JSON.stringify(evt)
2248
+ });
2192
2249
  });
2193
2250
  }
2194
2251
  const nonStreamPayload = {
@@ -2196,13 +2253,11 @@ async function handleCompletion(c) {
2196
2253
  stream: false
2197
2254
  };
2198
2255
  const response = isAzureModel ? await createAzureOpenAIChatCompletions(state.azureOpenAIConfig, nonStreamPayload) : await createChatCompletions(nonStreamPayload);
2199
- consola.debug("Response from upstream:", JSON.stringify(response).slice(-400));
2200
2256
  if (response.usage) setRequestContext(c, {
2201
2257
  inputTokens: response.usage.prompt_tokens,
2202
2258
  outputTokens: response.usage.completion_tokens
2203
2259
  });
2204
- const anthropicResponse = translateToAnthropic(response);
2205
- consola.debug("Translated Anthropic response:", JSON.stringify(anthropicResponse));
2260
+ const anthropicResponse = translateToAnthropic(response, anthropicPayload.model);
2206
2261
  return c.json(anthropicResponse);
2207
2262
  }
2208
2263
 
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","config","config: AzureOpenAIConfig","lastError: Error | undefined","lastResponse: Response | undefined","config","config","errorDetails: string","parsed: unknown","config","token","SYSTEM_REPLACEMENTS: Array<ReplacementRule>","userReplacements: Array<ReplacementRule>","rule: ReplacementRule","result","appliedRules: string[]","rule","process","commandBlock: string","lines: string[]","sanitized: Record<string, unknown>","path","tokenParts: string[]","state","x","headers: Record<string, string>","handleCompletion","response","handleCompletion","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","state","events: Array<AnthropicStreamEventData>","events","streamState: AnthropicStreamState"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/azure-openai/config.ts","../src/lib/retry-fetch.ts","../src/services/azure-openai/create-chat-completions.ts","../src/services/azure-openai/get-models.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/lib/auto-replace.ts","../src/config.ts","../src/debug.ts","../src/lib/proxy.ts","../src/lib/shell.ts","../src/lib/request-logger.ts","../src/lib/approval.ts","../src/lib/model-resolver.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/replacements/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\r\nimport os from \"node:os\"\r\nimport path from \"node:path\"\r\n\r\nconst APP_DIR = path.join(os.homedir(), \".local\", \"share\", \"copilot-api\")\r\n\r\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\r\nconst AZURE_OPENAI_CONFIG_PATH = path.join(APP_DIR, \"azure_openai_config\")\r\nconst REPLACEMENTS_CONFIG_PATH = path.join(APP_DIR, \"replacements.json\")\r\n\r\nexport const PATHS = {\r\n APP_DIR,\r\n GITHUB_TOKEN_PATH,\r\n AZURE_OPENAI_CONFIG_PATH,\r\n REPLACEMENTS_CONFIG_PATH,\r\n}\r\n\r\nexport async function ensurePaths(): Promise<void> {\r\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\r\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\r\n await ensureFile(PATHS.AZURE_OPENAI_CONFIG_PATH)\r\n}\r\n\r\nasync function ensureFile(filePath: string): Promise<void> {\r\n try {\r\n await fs.access(filePath, fs.constants.W_OK)\r\n } catch {\r\n await fs.writeFile(filePath, \"\")\r\n await fs.chmod(filePath, 0o600)\r\n }\r\n}\r\n","import type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n} from \"~/services/azure-openai/types\"\r\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\r\n\r\nexport interface State {\r\n githubToken?: string\r\n copilotToken?: string\r\n\r\n accountType: string\r\n models?: ModelsResponse\r\n vsCodeVersion?: string\r\n\r\n manualApprove: boolean\r\n rateLimitWait: boolean\r\n showToken: boolean\r\n debug: boolean\r\n\r\n // Rate limiting configuration\r\n rateLimitSeconds?: number\r\n lastRequestTimestamp?: number\r\n\r\n // Azure OpenAI configuration\r\n azureOpenAIConfig?: AzureOpenAIConfig\r\n azureOpenAIDeployments?: Array<AzureOpenAIDeploymentInfo>\r\n}\r\n\r\nexport const state: State = {\r\n accountType: \"individual\",\r\n manualApprove: false,\r\n rateLimitWait: false,\r\n showToken: false,\r\n debug: false,\r\n}\r\n","import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-04-01\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nexport class HTTPError extends Error {\n response: Response\n requestPayload?: unknown\n\n constructor(message: string, response: Response, requestPayload?: unknown) {\n super(message)\n this.response = response\n this.requestPayload = requestPayload\n }\n}\n\ninterface ContentFilterError {\n error: {\n code: string\n innererror?: {\n code: string\n content_filter_result?: unknown\n }\n }\n}\n\nfunction isContentFilterError(obj: unknown): obj is ContentFilterError {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"error\" in obj &&\n typeof (obj as ContentFilterError).error === \"object\" &&\n (obj as ContentFilterError).error?.code === \"content_filter\"\n )\n}\n\nexport async function forwardError(c: Context, error: unknown) {\n consola.error(\"Error occurred:\", error)\n\n if (error instanceof HTTPError) {\n const errorText = await error.response.text()\n let errorJson: unknown\n try {\n errorJson = JSON.parse(errorText)\n } catch {\n errorJson = errorText\n }\n consola.error(\"HTTP error:\", errorJson)\n\n // Check for content filter error and log full details\n if (isContentFilterError(errorJson)) {\n consola.box(\"CONTENT FILTER TRIGGERED\")\n consola.error(\"Full error response:\")\n console.log(JSON.stringify(errorJson, null, 2))\n\n if (error.requestPayload) {\n consola.error(\"Request payload that triggered the filter:\")\n console.log(JSON.stringify(error.requestPayload, null, 2))\n }\n }\n\n return c.json(\n {\n error: {\n message: errorText,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: (error as Error).message,\n type: \"error\",\n },\n },\n 500,\n )\n}\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\n\nimport type { AzureOpenAIConfig } from \"./types\"\n\nexport const AZURE_OPENAI_MODEL_PREFIX = \"azure_openai_\"\n\nexport async function loadAzureOpenAIConfig(): Promise<AzureOpenAIConfig | null> {\n try {\n const content = await fs.readFile(PATHS.AZURE_OPENAI_CONFIG_PATH, \"utf8\")\n if (!content.trim()) {\n return null\n }\n\n const decoded = Buffer.from(content.trim(), \"base64\").toString(\"utf8\")\n const config = JSON.parse(decoded) as AzureOpenAIConfig\n\n if (!config.endpoint || !config.apiKey) {\n return null\n }\n\n return config\n } catch {\n return null\n }\n}\n\nexport async function saveAzureOpenAIConfig(\n config: AzureOpenAIConfig,\n): Promise<void> {\n const encoded = Buffer.from(JSON.stringify(config)).toString(\"base64\")\n await fs.writeFile(PATHS.AZURE_OPENAI_CONFIG_PATH, encoded, \"utf8\")\n await fs.chmod(PATHS.AZURE_OPENAI_CONFIG_PATH, 0o600)\n consola.success(\"Azure OpenAI configuration saved\")\n}\n\nexport async function promptAzureOpenAISetup(): Promise<AzureOpenAIConfig | null> {\n const wantToAdd = await consola.prompt(\n \"Would you like to add a custom Azure OpenAI endpoint?\",\n {\n type: \"confirm\",\n initial: false,\n },\n )\n\n if (!wantToAdd) {\n return null\n }\n\n const endpoint = await consola.prompt(\n \"Enter your Azure OpenAI endpoint URL (e.g., https://your-resource.openai.azure.com):\",\n {\n type: \"text\",\n },\n )\n\n if (!endpoint || typeof endpoint !== \"string\" || !endpoint.trim()) {\n consola.warn(\"No endpoint provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const apiKey = await consola.prompt(\"Enter your Azure OpenAI API key:\", {\n type: \"text\",\n })\n\n if (!apiKey || typeof apiKey !== \"string\" || !apiKey.trim()) {\n consola.warn(\"No API key provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const config: AzureOpenAIConfig = {\n endpoint: endpoint.trim().replace(/\\/$/, \"\"), // Remove trailing slash\n apiKey: apiKey.trim(),\n }\n\n await saveAzureOpenAIConfig(config)\n return config\n}\n\nexport function isAzureOpenAIModel(modelId: string): boolean {\n return modelId.startsWith(AZURE_OPENAI_MODEL_PREFIX)\n}\n\nexport function getAzureDeploymentName(modelId: string): string {\n return modelId.slice(AZURE_OPENAI_MODEL_PREFIX.length)\n}\n","import consola from \"consola\"\r\n\r\nimport { sleep } from \"./utils\"\r\n\r\n// Fast retry: 100ms, 200ms, 300ms, then stop (max ~600ms total wait)\r\nconst RETRY_DELAYS_MS = [100, 200, 300]\r\n\r\n/**\r\n * Check if an error is retryable (transient network error)\r\n */\r\nfunction isRetryableError(error: unknown): boolean {\r\n if (!(error instanceof Error)) return false\r\n\r\n const message = error.message.toLowerCase()\r\n const causeMessage =\r\n error.cause instanceof Error ? error.cause.message.toLowerCase() : \"\"\r\n\r\n // Common transient error patterns\r\n const retryablePatterns = [\r\n \"fetch failed\",\r\n \"other side closed\",\r\n \"connection reset\",\r\n \"econnreset\",\r\n \"socket hang up\",\r\n \"socket connection was closed unexpectedly\",\r\n \"etimedout\",\r\n \"econnrefused\",\r\n \"network error\",\r\n \"aborted\",\r\n \"timeout\",\r\n ]\r\n\r\n return retryablePatterns.some(\r\n (pattern) => message.includes(pattern) || causeMessage.includes(pattern),\r\n )\r\n}\r\n\r\n/**\r\n * Check if an HTTP response status is retryable\r\n */\r\nfunction isRetryableStatus(status: number): boolean {\r\n // 4xx client errors (except 400, 401, 403, 404) and 5xx server errors\r\n // Retry: 408 Timeout, 429 Rate Limit, and all 5xx\r\n return status === 408 || status === 429 || (status >= 500 && status <= 599)\r\n}\r\n\r\n/**\r\n * Fetch with automatic fast retry on transient failures\r\n * Retries with delays: 100ms, 200ms, 300ms (max ~600ms total wait)\r\n */\r\nexport async function fetchWithRetry(\r\n input: string | URL | Request,\r\n init?: RequestInit,\r\n): Promise<Response> {\r\n const maxAttempts = RETRY_DELAYS_MS.length + 1 // 4 total attempts\r\n\r\n let lastError: Error | undefined\r\n let lastResponse: Response | undefined\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n try {\r\n // Force a new connection by adding cache-busting and connection headers\r\n const headers = new Headers(init?.headers)\r\n\r\n // Ensure we're not reusing potentially stale connections\r\n headers.set(\"Connection\", \"close\")\r\n\r\n const response = await fetch(input, {\r\n ...init,\r\n headers,\r\n // Disable keep-alive to force fresh connections on each attempt\r\n keepalive: false,\r\n })\r\n\r\n // Check for retryable HTTP status codes\r\n if (isRetryableStatus(response.status) && attempt < maxAttempts - 1) {\r\n lastResponse = response\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `HTTP ${response.status} (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms`,\r\n )\r\n await sleep(delayMs)\r\n continue\r\n }\r\n\r\n return response\r\n } catch (error) {\r\n lastError = error as Error\r\n\r\n if (!isRetryableError(error) || attempt === maxAttempts - 1) {\r\n throw error\r\n }\r\n\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `Fetch failed (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms:`,\r\n lastError.message,\r\n )\r\n await sleep(delayMs)\r\n }\r\n }\r\n\r\n // If we exhausted retries due to HTTP status, return the last response\r\n if (lastResponse) {\r\n return lastResponse\r\n }\r\n\r\n throw lastError\r\n}\r\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport type {\r\n ChatCompletionResponse,\r\n ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type { AzureOpenAIConfig } from \"./types\"\r\n\r\nimport { getAzureDeploymentName } from \"./config\"\r\n\r\nconst AZURE_API_VERSION = \"2024-10-21\"\r\n\r\nexport async function createAzureOpenAIChatCompletions(\r\n config: AzureOpenAIConfig,\r\n payload: ChatCompletionsPayload,\r\n) {\r\n // Extract the actual deployment name from the prefixed model ID\r\n const deploymentName = getAzureDeploymentName(payload.model)\r\n\r\n // Convert max_tokens to max_completion_tokens for newer models (GPT-4o, GPT-5, etc.)\r\n // Azure OpenAI newer models require max_completion_tokens instead of max_tokens\r\n const { max_tokens, ...restPayload } = payload\r\n const azurePayload = {\r\n ...restPayload,\r\n model: deploymentName,\r\n ...(max_tokens != null && { max_completion_tokens: max_tokens }),\r\n }\r\n\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments/${deploymentName}/chat/completions?api-version=${AZURE_API_VERSION}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify(azurePayload),\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create Azure OpenAI chat completions:\", response)\r\n throw new HTTPError(\r\n \"Failed to create Azure OpenAI chat completions\",\r\n response,\r\n payload,\r\n )\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n AzureOpenAIDeploymentsResponse,\r\n} from \"./types\"\r\n\r\nimport { AZURE_OPENAI_MODEL_PREFIX } from \"./config\"\r\n\r\n// Different API versions for different endpoints\r\nconst AZURE_DEPLOYMENTS_API_VERSION = \"2022-12-01\"\r\n\r\nexport async function getAzureOpenAIDeployments(\r\n config: AzureOpenAIConfig,\r\n): Promise<Array<AzureOpenAIDeploymentInfo>> {\r\n try {\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments?api-version=${AZURE_DEPLOYMENTS_API_VERSION}`,\r\n {\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => \"\")\r\n consola.error(\r\n `Failed to fetch Azure OpenAI deployments: ${response.status}`,\r\n errorText,\r\n )\r\n throw new HTTPError(\"Failed to fetch Azure OpenAI deployments\", response)\r\n }\r\n\r\n const data = (await response.json()) as AzureOpenAIDeploymentsResponse\r\n\r\n // Only include deployments that are successfully deployed\r\n return data.data\r\n .filter((deployment) => deployment.status === \"succeeded\")\r\n .map((deployment) => ({\r\n id: `${AZURE_OPENAI_MODEL_PREFIX}${deployment.id}`,\r\n deploymentName: deployment.id,\r\n model: deployment.model,\r\n created: deployment.created_at,\r\n object: \"deployment\",\r\n owned_by: deployment.owner || \"azure-openai\",\r\n }))\r\n } catch (error) {\r\n if (error instanceof HTTPError) {\r\n throw error\r\n }\r\n consola.error(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n return []\r\n }\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const getModels = async () => {\r\n const url = `${copilotBaseUrl(state)}/models`\r\n const response = await fetchWithRetry(url, {\r\n headers: copilotHeaders(state),\r\n })\r\n\r\n if (!response.ok) {\r\n const errorBody = await response.text()\r\n let errorDetails: string\r\n try {\r\n const parsed: unknown = JSON.parse(errorBody)\r\n errorDetails = JSON.stringify(parsed, null, 2)\r\n } catch {\r\n errorDetails = errorBody || \"(empty response)\"\r\n }\r\n consola.error(\r\n `Failed to get models from ${url}\\n`\r\n + `Status: ${response.status} ${response.statusText}\\n`\r\n + `Response: ${errorDetails}`,\r\n )\r\n throw new HTTPError(\r\n `Failed to get models: ${response.status} ${response.statusText}`,\r\n response,\r\n )\r\n }\r\n\r\n return (await response.json()) as ModelsResponse\r\n}\r\n\r\nexport interface ModelsResponse {\r\n data: Array<Model>\r\n object: string\r\n}\r\n\r\ninterface ModelLimits {\r\n max_context_window_tokens?: number\r\n max_output_tokens?: number\r\n max_prompt_tokens?: number\r\n max_inputs?: number\r\n}\r\n\r\ninterface ModelSupports {\r\n tool_calls?: boolean\r\n parallel_tool_calls?: boolean\r\n dimensions?: boolean\r\n}\r\n\r\ninterface ModelCapabilities {\r\n family: string\r\n limits: ModelLimits\r\n object: string\r\n supports: ModelSupports\r\n tokenizer: string\r\n type: string\r\n}\r\n\r\nexport interface Model {\r\n capabilities: ModelCapabilities\r\n id: string\r\n model_picker_enabled: boolean\r\n name: string\r\n object: string\r\n preview: boolean\r\n vendor: string\r\n version: string\r\n policy?: {\r\n state: string\r\n terms: string\r\n }\r\n}\r\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\r\n\r\nimport {\r\n getAzureOpenAIDeployments,\r\n loadAzureOpenAIConfig,\r\n promptAzureOpenAISetup,\r\n} from \"~/services/azure-openai\"\r\nimport { getModels } from \"~/services/copilot/get-models\"\r\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\r\n\r\nimport { state } from \"./state\"\r\n\r\nexport const sleep = (ms: number) =>\r\n new Promise((resolve) => {\r\n setTimeout(resolve, ms)\r\n })\r\n\r\nexport const isNullish = (value: unknown): value is null | undefined =>\r\n value === null || value === undefined\r\n\r\nexport async function cacheModels(): Promise<void> {\r\n try {\r\n const models = await getModels()\r\n state.models = models\r\n } catch (error) {\r\n consola.error(\"Failed to fetch and cache models. This could be due to:\")\r\n consola.error(\" - Invalid or expired Copilot token\")\r\n consola.error(\" - Network connectivity issues\")\r\n consola.error(\" - GitHub Copilot service unavailable\")\r\n consola.error(\r\n \" - Account type mismatch (try --account-type=individual or --account-type=business)\",\r\n )\r\n throw error\r\n }\r\n}\r\n\r\nexport const cacheVSCodeVersion = async () => {\r\n const response = await getVSCodeVersion()\r\n state.vsCodeVersion = response\r\n\r\n consola.info(`Using VSCode version: ${response}`)\r\n}\r\n\r\nexport async function setupAzureOpenAI(): Promise<void> {\r\n // Try to load existing config\r\n let config = await loadAzureOpenAIConfig()\r\n\r\n // If no config exists, prompt user on first run\r\n if (!config) {\r\n config = await promptAzureOpenAISetup()\r\n }\r\n\r\n if (!config) {\r\n consola.info(\"Azure OpenAI not configured\")\r\n return\r\n }\r\n\r\n state.azureOpenAIConfig = config\r\n consola.info(\"Azure OpenAI configuration loaded\")\r\n\r\n // Fetch and cache Azure OpenAI deployments\r\n try {\r\n const deployments = await getAzureOpenAIDeployments(config)\r\n state.azureOpenAIDeployments = deployments\r\n if (deployments.length > 0) {\r\n consola.info(\r\n `Loaded ${deployments.length} Azure OpenAI deployment(s):\\n${deployments.map((d) => `- ${d.id} (${d.model})`).join(\"\\n\")}`,\r\n )\r\n } else {\r\n consola.warn(\"No Azure OpenAI deployments found\")\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n }\r\n}\r\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n while (true) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\n continue\n }\n\n const json = await response.json()\n consola.debug(\"Polling access token response:\", json)\n\n const { access_token } = json as AccessTokenResponse\n\n if (access_token) {\n return access_token\n } else {\n await sleep(sleepDuration)\n }\n }\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n throw error\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","import consola from \"consola\"\r\nimport fs from \"node:fs/promises\"\r\n\r\nimport type { ChatCompletionsPayload } from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { PATHS } from \"./paths\"\r\n\r\nexport interface ReplacementRule {\r\n id: string\r\n name?: string // Human-readable name/description\r\n pattern: string\r\n replacement: string\r\n isRegex: boolean\r\n enabled: boolean\r\n isSystem?: boolean // System rules cannot be deleted by user\r\n}\r\n\r\n// Built-in system replacement that cannot be removed\r\nconst SYSTEM_REPLACEMENTS: Array<ReplacementRule> = [\r\n {\r\n id: \"system-anthropic-billing\",\r\n name: \"Remove Anthropic billing header\",\r\n pattern: \"x-anthropic-billing-header:[^\\\\n]*\\\\n?\",\r\n replacement: \"\",\r\n isRegex: true,\r\n enabled: true,\r\n isSystem: true,\r\n },\r\n]\r\n\r\n// User-configured replacements (loaded from disk)\r\nlet userReplacements: Array<ReplacementRule> = []\r\nlet isLoaded = false\r\n\r\n/**\r\n * Load user replacements from disk\r\n */\r\nexport async function loadReplacements(): Promise<void> {\r\n try {\r\n const data = await fs.readFile(PATHS.REPLACEMENTS_CONFIG_PATH)\r\n const parsed = JSON.parse(data.toString()) as Array<ReplacementRule>\r\n userReplacements = parsed.filter((r) => !r.isSystem)\r\n isLoaded = true\r\n consola.debug(`Loaded ${userReplacements.length} user replacement rules`)\r\n } catch {\r\n // File doesn't exist or is invalid - start with empty array\r\n userReplacements = []\r\n isLoaded = true\r\n }\r\n}\r\n\r\n/**\r\n * Save user replacements to disk\r\n */\r\nexport async function saveReplacements(): Promise<void> {\r\n try {\r\n await fs.writeFile(\r\n PATHS.REPLACEMENTS_CONFIG_PATH,\r\n JSON.stringify(userReplacements, null, 2),\r\n \"utf8\",\r\n )\r\n consola.debug(`Saved ${userReplacements.length} user replacement rules`)\r\n } catch (error) {\r\n consola.error(\"Failed to save replacement rules:\", error)\r\n throw error\r\n }\r\n}\r\n\r\n/**\r\n * Ensure replacements are loaded before accessing\r\n */\r\nexport async function ensureLoaded(): Promise<void> {\r\n if (!isLoaded) {\r\n await loadReplacements()\r\n }\r\n}\r\n\r\n/**\r\n * Get all replacement rules (system + user)\r\n */\r\nexport async function getAllReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return [...SYSTEM_REPLACEMENTS, ...userReplacements]\r\n}\r\n\r\n/**\r\n * Get only user-configurable replacements\r\n */\r\nexport async function getUserReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return userReplacements\r\n}\r\n\r\n/**\r\n * Add a new user replacement rule\r\n */\r\nexport async function addReplacement(\r\n pattern: string,\r\n replacement: string,\r\n isRegex = false,\r\n name?: string,\r\n): Promise<ReplacementRule> {\r\n await ensureLoaded()\r\n const rule: ReplacementRule = {\r\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,\r\n name,\r\n pattern,\r\n replacement,\r\n isRegex,\r\n enabled: true,\r\n isSystem: false,\r\n }\r\n userReplacements.push(rule)\r\n await saveReplacements()\r\n consola.info(`Added replacement rule: \"${pattern}\" -> \"${replacement}\"`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Remove a user replacement rule by ID\r\n */\r\nexport async function removeReplacement(id: string): Promise<boolean> {\r\n await ensureLoaded()\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return false\r\n }\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot remove system replacement rule\")\r\n return false\r\n }\r\n userReplacements = userReplacements.filter((r) => r.id !== id)\r\n await saveReplacements()\r\n consola.info(`Removed replacement rule: ${id}`)\r\n return true\r\n}\r\n\r\n/**\r\n * Update an existing user replacement rule\r\n */\r\nexport async function updateReplacement(\r\n id: string,\r\n updates: {\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n },\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return null\r\n }\r\n\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot update system replacement rule\")\r\n return null\r\n }\r\n\r\n if (updates.name !== undefined) rule.name = updates.name\r\n if (updates.pattern !== undefined) rule.pattern = updates.pattern\r\n if (updates.replacement !== undefined) rule.replacement = updates.replacement\r\n if (updates.isRegex !== undefined) rule.isRegex = updates.isRegex\r\n if (updates.enabled !== undefined) rule.enabled = updates.enabled\r\n\r\n await saveReplacements()\r\n consola.info(`Updated replacement rule: ${rule.name || rule.id}`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Toggle a replacement rule on/off\r\n */\r\nexport async function toggleReplacement(\r\n id: string,\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n // Check user replacements first\r\n const userRule = userReplacements.find((r) => r.id === id)\r\n if (userRule) {\r\n userRule.enabled = !userRule.enabled\r\n await saveReplacements()\r\n consola.info(\r\n `Toggled replacement rule ${id}: ${userRule.enabled ? \"enabled\" : \"disabled\"}`,\r\n )\r\n return userRule\r\n }\r\n\r\n // System rules cannot be toggled\r\n const systemRule = SYSTEM_REPLACEMENTS.find((r) => r.id === id)\r\n if (systemRule) {\r\n consola.warn(\"Cannot toggle system replacement rule\")\r\n return null\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * Clear all user replacements\r\n */\r\nexport async function clearUserReplacements(): Promise<void> {\r\n userReplacements = []\r\n await saveReplacements()\r\n consola.info(\"Cleared all user replacement rules\")\r\n}\r\n\r\n/**\r\n * Apply a single replacement rule to text and return info about whether it matched\r\n */\r\nfunction applyRule(\r\n text: string,\r\n rule: ReplacementRule,\r\n): { result: string; matched: boolean } {\r\n if (!rule.enabled) return { result: text, matched: false }\r\n\r\n if (rule.isRegex) {\r\n try {\r\n const regex = new RegExp(rule.pattern, \"g\")\r\n const result = text.replace(regex, rule.replacement)\r\n return { result, matched: result !== text }\r\n } catch {\r\n consola.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.pattern}`)\r\n return { result: text, matched: false }\r\n }\r\n }\r\n\r\n const result = text.split(rule.pattern).join(rule.replacement)\r\n return { result, matched: result !== text }\r\n}\r\n\r\n/**\r\n * Apply all replacement rules to text\r\n */\r\nexport async function applyReplacements(text: string): Promise<string> {\r\n let result = text\r\n const allRules = await getAllReplacements()\r\n const appliedRules: string[] = []\r\n\r\n for (const rule of allRules) {\r\n const { result: newResult, matched } = applyRule(result, rule)\r\n if (matched) {\r\n result = newResult\r\n appliedRules.push(rule.name || rule.id)\r\n }\r\n }\r\n\r\n if (appliedRules.length > 0) {\r\n consola.info(`Replacements applied: ${appliedRules.join(\", \")}`)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Apply replacements to a chat completions payload\r\n * This modifies message content in place\r\n */\r\nexport async function applyReplacementsToPayload(\r\n payload: ChatCompletionsPayload,\r\n): Promise<ChatCompletionsPayload> {\r\n const processedMessages = await Promise.all(\r\n payload.messages.map(async (message) => {\r\n if (typeof message.content === \"string\") {\r\n return {\r\n ...message,\r\n content: await applyReplacements(message.content),\r\n }\r\n }\r\n\r\n // Handle array content (multimodal)\r\n if (Array.isArray(message.content)) {\r\n return {\r\n ...message,\r\n content: await Promise.all(\r\n message.content.map(async (part) => {\r\n if (\r\n typeof part === \"object\"\r\n && part.type === \"text\"\r\n && part.text\r\n ) {\r\n return {\r\n ...part,\r\n text: await applyReplacements(part.text),\r\n }\r\n }\r\n return part\r\n }),\r\n ),\r\n }\r\n }\r\n\r\n return message\r\n }),\r\n )\r\n\r\n return {\r\n ...payload,\r\n messages: processedMessages,\r\n }\r\n}\r\n","import { defineCommand } from \"citty\"\r\nimport consola from \"consola\"\r\n\r\nimport {\r\n addReplacement,\r\n applyReplacements,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n type ReplacementRule,\r\n} from \"~/lib/auto-replace\"\r\nimport { ensurePaths, PATHS } from \"~/lib/paths\"\r\n\r\ntype MenuAction =\r\n | \"list\"\r\n | \"add\"\r\n | \"edit\"\r\n | \"remove\"\r\n | \"toggle\"\r\n | \"test\"\r\n | \"clear\"\r\n | \"exit\"\r\n\r\nfunction formatRule(rule: ReplacementRule, index: number): string {\r\n const status = rule.enabled ? \"✓\" : \"✗\"\r\n const type = rule.isRegex ? \"regex\" : \"string\"\r\n const system = rule.isSystem ? \" [system]\" : \"\"\r\n const name = rule.name ? ` \"${rule.name}\"` : \"\"\r\n const replacement = rule.replacement || \"(empty)\"\r\n return `${index + 1}. [${status}] (${type})${system}${name} \"${rule.pattern}\" → \"${replacement}\"`\r\n}\r\n\r\nasync function listReplacements(): Promise<void> {\r\n const all = await getAllReplacements()\r\n\r\n if (all.length === 0) {\r\n consola.info(\"No replacement rules configured.\")\r\n return\r\n }\r\n\r\n consola.info(\"\\n📋 Replacement Rules:\\n\")\r\n for (const [i, element] of all.entries()) {\r\n console.log(formatRule(element, i))\r\n }\r\n console.log()\r\n}\r\n\r\nasync function addNewReplacement(): Promise<void> {\r\n const name = await consola.prompt(\"Name (optional, short description):\", {\r\n type: \"text\",\r\n default: \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\r\n \"Replacement text (leave empty to delete matches):\",\r\n {\r\n type: \"text\",\r\n default: \"\",\r\n },\r\n )\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await addReplacement(\r\n pattern,\r\n replacement,\r\n matchType === \"regex\",\r\n name || undefined,\r\n )\r\n\r\n consola.success(`Added rule: ${rule.name || rule.id}`)\r\n}\r\n\r\nasync function editExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to edit.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to edit:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = userRules.find((r) => r.id === selected)\r\n if (!rule) {\r\n consola.error(\"Rule not found.\")\r\n return\r\n }\r\n\r\n consola.info(`\\nEditing rule: ${rule.name || rule.id}`)\r\n consola.info(\"Press Enter to keep current value.\\n\")\r\n\r\n const name = await consola.prompt(\"Name:\", {\r\n type: \"text\",\r\n default: rule.name || \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n initial: rule.isRegex ? \"regex\" : \"string\",\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n default: rule.pattern,\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\"Replacement text:\", {\r\n type: \"text\",\r\n default: rule.replacement,\r\n })\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const updated = await updateReplacement(selected, {\r\n name: name || undefined,\r\n pattern,\r\n replacement,\r\n isRegex: matchType === \"regex\",\r\n })\r\n\r\n if (updated) {\r\n consola.success(`Updated rule: ${updated.name || updated.id}`)\r\n } else {\r\n consola.error(\"Failed to update rule.\")\r\n }\r\n}\r\n\r\nasync function removeExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to remove.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to remove:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const success = await removeReplacement(selected)\r\n if (success) {\r\n consola.success(\"Rule removed.\")\r\n } else {\r\n consola.error(\"Failed to remove rule.\")\r\n }\r\n}\r\n\r\nasync function toggleExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to toggle.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to toggle:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await toggleReplacement(selected)\r\n if (rule) {\r\n consola.success(`Rule ${rule.enabled ? \"enabled\" : \"disabled\"}.`)\r\n } else {\r\n consola.error(\"Failed to toggle rule.\")\r\n }\r\n}\r\n\r\nasync function testReplacements(): Promise<void> {\r\n const testText = await consola.prompt(\"Enter text to test replacements:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof testText === \"symbol\" || !testText) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const result = await applyReplacements(testText)\r\n\r\n consola.info(\"\\n📝 Original:\")\r\n console.log(testText)\r\n consola.info(\"\\n✨ After replacements:\")\r\n console.log(result)\r\n console.log()\r\n}\r\n\r\nasync function clearAllReplacements(): Promise<void> {\r\n const confirm = await consola.prompt(\r\n \"Are you sure you want to clear all user replacements?\",\r\n {\r\n type: \"confirm\",\r\n initial: false,\r\n },\r\n )\r\n\r\n if (confirm) {\r\n await clearUserReplacements()\r\n consola.success(\"All user replacements cleared.\")\r\n } else {\r\n consola.info(\"Cancelled.\")\r\n }\r\n}\r\n\r\nasync function mainMenu(): Promise<void> {\r\n consola.info(`\\n🔧 Copilot API - Replacement Configuration`)\r\n consola.info(`Config file: ${PATHS.REPLACEMENTS_CONFIG_PATH}\\n`)\r\n\r\n let running = true\r\n\r\n while (running) {\r\n const action = await consola.prompt(\"What would you like to do?\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"📋 List all rules\", value: \"list\" as MenuAction },\r\n { label: \"➕ Add new rule\", value: \"add\" as MenuAction },\r\n { label: \"✏️ Edit rule\", value: \"edit\" as MenuAction },\r\n { label: \"➖ Remove rule\", value: \"remove\" as MenuAction },\r\n { label: \"🔄 Toggle rule on/off\", value: \"toggle\" as MenuAction },\r\n { label: \"🧪 Test replacements\", value: \"test\" as MenuAction },\r\n { label: \"🗑️ Clear all user rules\", value: \"clear\" as MenuAction },\r\n { label: \"🚪 Exit\", value: \"exit\" as MenuAction },\r\n ],\r\n })\r\n\r\n if (typeof action === \"symbol\") {\r\n break\r\n }\r\n\r\n switch (action) {\r\n case \"list\": {\r\n await listReplacements()\r\n break\r\n }\r\n case \"add\": {\r\n await addNewReplacement()\r\n break\r\n }\r\n case \"edit\": {\r\n await editExistingReplacement()\r\n break\r\n }\r\n case \"remove\": {\r\n await removeExistingReplacement()\r\n break\r\n }\r\n case \"toggle\": {\r\n await toggleExistingReplacement()\r\n break\r\n }\r\n case \"test\": {\r\n await testReplacements()\r\n break\r\n }\r\n case \"clear\": {\r\n await clearAllReplacements()\r\n break\r\n }\r\n case \"exit\": {\r\n running = false\r\n break\r\n }\r\n default: {\r\n break\r\n }\r\n }\r\n }\r\n\r\n consola.info(\"Goodbye! 👋\")\r\n}\r\n\r\nexport const config = defineCommand({\r\n meta: {\r\n name: \"config\",\r\n description: \"Configure replacement rules interactively\",\r\n },\r\n run: async () => {\r\n await ensurePaths()\r\n await mainMenu()\r\n },\r\n})\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n tokenExists: boolean\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`copilot-api debug\n\nVersion: ${info.version}\nRuntime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})\n\nPaths:\n- APP_DIR: ${info.paths.APP_DIR}\n- GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}\n\nToken exists: ${info.tokenExists ? \"Yes\" : \"No\"}`)\n}\n\nfunction printDebugInfoJson(info: DebugInfo): void {\n console.log(JSON.stringify(info, null, 2))\n}\n\nexport async function runDebug(options: RunDebugOptions): Promise<void> {\n const debugInfo = await getDebugInfo()\n\n if (options.json) {\n printDebugInfoJson(debugInfo)\n } else {\n printDebugInfoPlain(debugInfo)\n }\n}\n\nexport const debug = defineCommand({\n meta: {\n name: \"debug\",\n description: \"Print debug information about the application\",\n },\n args: {\n json: {\n type: \"boolean\",\n default: false,\n description: \"Output debug information as JSON\",\n },\n },\n run({ args }) {\n return runDebug({\n json: args.json,\n })\n },\n})\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n","import { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","import type { Context, Next } from \"hono\"\r\n\r\nimport { state } from \"./state\"\r\n\r\n/**\r\n * Request context stored for logging on response\r\n */\r\nexport interface RequestContext {\r\n startTime: number\r\n model?: string\r\n inputTokens?: number\r\n outputTokens?: number\r\n provider?: \"Copilot\" | \"Azure OpenAI\"\r\n}\r\n\r\nconst REQUEST_CONTEXT_KEY = \"requestContext\"\r\n\r\n// ANSI color codes\r\nconst colors = {\r\n reset: \"\\x1b[0m\",\r\n dim: \"\\x1b[2m\",\r\n bold: \"\\x1b[1m\",\r\n cyan: \"\\x1b[36m\",\r\n green: \"\\x1b[32m\",\r\n yellow: \"\\x1b[33m\",\r\n red: \"\\x1b[31m\",\r\n magenta: \"\\x1b[35m\",\r\n blue: \"\\x1b[34m\",\r\n white: \"\\x1b[37m\",\r\n gray: \"\\x1b[90m\",\r\n}\r\n\r\n/**\r\n * Get the current time formatted as HH:MM:SS\r\n */\r\nfunction getTimeString(): string {\r\n return new Date().toLocaleTimeString(\"en-US\", {\r\n hour12: false,\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n second: \"2-digit\",\r\n })\r\n}\r\n\r\n/**\r\n * Get status color based on HTTP status code\r\n */\r\nfunction getStatusColor(status: number): string {\r\n if (status >= 500) return colors.red\r\n if (status >= 400) return colors.yellow\r\n if (status >= 300) return colors.cyan\r\n return colors.green\r\n}\r\n\r\n/**\r\n * Log raw HTTP request details (for debug mode)\r\n */\r\nasync function logRawRequest(c: Context): Promise<void> {\r\n const method = c.req.method\r\n const url = c.req.url\r\n const headers = Object.fromEntries(c.req.raw.headers.entries())\r\n\r\n const lines: string[] = []\r\n lines.push(`${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`)\r\n lines.push(`${colors.cyan}${method}${colors.reset} ${url}`)\r\n lines.push(`${colors.dim}Headers:${colors.reset}`)\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n // Mask authorization headers\r\n const displayValue = key.toLowerCase().includes(\"authorization\")\r\n ? `${value.slice(0, 20)}...`\r\n : value\r\n lines.push(` ${colors.gray}${key}:${colors.reset} ${displayValue}`)\r\n }\r\n\r\n // Try to get body info without consuming it\r\n if (method !== \"GET\" && method !== \"HEAD\") {\r\n try {\r\n const clonedRequest = c.req.raw.clone()\r\n const body = await clonedRequest.text()\r\n if (body) {\r\n // Parse JSON to extract model, omit messages/prompt\r\n try {\r\n const parsed = JSON.parse(body)\r\n const sanitized: Record<string, unknown> = {}\r\n\r\n for (const [key, value] of Object.entries(parsed)) {\r\n if (key === \"messages\" || key === \"prompt\") {\r\n sanitized[key] = `[${Array.isArray(value) ? value.length : 1} items omitted]`\r\n } else {\r\n sanitized[key] = value\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}Body (sanitized):${colors.reset}`)\r\n lines.push(` ${JSON.stringify(sanitized, null, 2).split(\"\\n\").join(\"\\n \")}`)\r\n } catch {\r\n // Not JSON, show length\r\n lines.push(`${colors.dim}Body:${colors.reset} [${body.length} bytes]`)\r\n }\r\n }\r\n } catch {\r\n lines.push(`${colors.dim}Body:${colors.reset} [unable to read]`)\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n console.log(lines.join(\"\\n\"))\r\n}\r\n\r\n/**\r\n * Set request context for logging\r\n */\r\nexport function setRequestContext(\r\n c: Context,\r\n ctx: Partial<Omit<RequestContext, \"startTime\">>,\r\n): void {\r\n const existing = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n if (existing) {\r\n c.set(REQUEST_CONTEXT_KEY, { ...existing, ...ctx })\r\n }\r\n}\r\n\r\n/**\r\n * Custom request logger middleware\r\n */\r\nexport async function requestLogger(c: Context, next: Next): Promise<void> {\r\n // Log raw request in debug mode\r\n if (state.debug) {\r\n await logRawRequest(c)\r\n }\r\n\r\n const startTime = Date.now()\r\n const method = c.req.method\r\n const path =\r\n c.req.path +\r\n (c.req.raw.url.includes(\"?\") ? \"?\" + c.req.raw.url.split(\"?\")[1] : \"\")\r\n\r\n // Initialize request context\r\n c.set(REQUEST_CONTEXT_KEY, { startTime } as RequestContext)\r\n\r\n await next()\r\n\r\n // Get context that may have been set during request handling\r\n const ctx = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n const duration = ((Date.now() - startTime) / 1000).toFixed(1)\r\n const status = c.res.status\r\n const statusColor = getStatusColor(status)\r\n\r\n // Build the log block\r\n const lines: string[] = []\r\n\r\n // Separator\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n\r\n // Main request line: method, path, status, duration\r\n const statusBadge = `${statusColor}${status}${colors.reset}`\r\n const durationStr = `${colors.cyan}${duration}s${colors.reset}`\r\n lines.push(\r\n `${colors.bold}${method}${colors.reset} ${path} ${statusBadge} ${durationStr}`,\r\n )\r\n\r\n // Provider and model info\r\n if (ctx?.provider && ctx?.model) {\r\n const providerColor =\r\n ctx.provider === \"Azure OpenAI\" ? colors.blue : colors.magenta\r\n lines.push(\r\n ` ${colors.gray}Provider:${colors.reset} ${providerColor}${ctx.provider}${colors.reset} ${colors.gray}->${colors.reset} ${colors.white}${ctx.model}${colors.reset}`,\r\n )\r\n }\r\n\r\n // Token info\r\n if (ctx?.inputTokens !== undefined || ctx?.outputTokens !== undefined) {\r\n const tokenParts: string[] = []\r\n if (ctx.inputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Input:${colors.reset} ${colors.yellow}${ctx.inputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n if (ctx.outputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Output:${colors.reset} ${colors.green}${ctx.outputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n lines.push(` ${tokenParts.join(\" \")}`)\r\n }\r\n\r\n // Timestamp\r\n lines.push(` ${colors.dim}${getTimeString()}${colors.reset}`)\r\n\r\n // Print all lines\r\n console.log(lines.join(\"\\n\"))\r\n}\r\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","/**\r\n * Normalize a model name by converting dashes to dots between numbers.\r\n * e.g., \"claude-opus-4-5\" -> \"claude-opus-4.5\"\r\n * \"gpt-4-1\" -> \"gpt-4.1\"\r\n * \"gpt-5-1-codex\" -> \"gpt-5.1-codex\"\r\n */\r\nexport function normalizeModelName(model: string): string {\r\n // Replace dash with dot only between two digits: \"4-5\" -> \"4.5\"\r\n return model.replace(/(\\d)-(\\d)/g, (_, p1, p2) => `${p1}.${p2}`)\r\n}\r\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates\n state.lastRequestTimestamp = now\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n\n/**\n * Estimate token count for a payload without model info (uses o200k_base encoding)\n * This is a rough estimate used when we don't have model-specific info\n */\nexport const estimateTokenCount = async (\n payload: ChatCompletionsPayload,\n): Promise<number> => {\n const encoder = await getEncodeChatFunction(\"o200k_base\")\n\n // Simple estimation: encode all message content\n let tokens = 0\n for (const message of payload.messages) {\n // 3 tokens per message overhead\n tokens += 3\n\n if (typeof message.content === \"string\") {\n tokens += encoder.encode(message.content).length\n } else if (Array.isArray(message.content)) {\n for (const part of message.content) {\n if (part.type === \"text\" && part.text) {\n tokens += encoder.encode(part.text).length\n } else if (part.type === \"image_url\") {\n // Rough estimate for images\n tokens += 85\n }\n }\n }\n\n // Add role tokens\n if (message.role) {\n tokens += encoder.encode(message.role).length\n }\n\n // Tool calls in messages (assistant responses with tool use)\n if (message.tool_calls) {\n tokens += encoder.encode(JSON.stringify(message.tool_calls)).length\n }\n }\n\n // Add tool definitions if present (but don't double count - use simplified estimate)\n // Tool definitions add overhead but the full JSON stringify overcounts\n if (payload.tools && payload.tools.length > 0) {\n // Estimate ~50 tokens per tool on average for function name + description + params\n tokens += payload.tools.length * 50\n }\n\n // Priming tokens\n tokens += 3\n\n return tokens\n}\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createChatCompletions = async (\r\n payload: ChatCompletionsPayload,\r\n) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const enableVision = payload.messages.some(\r\n (x) =>\r\n typeof x.content !== \"string\"\r\n && x.content?.some((x) => x.type === \"image_url\"),\r\n )\r\n\r\n // Agent/user check for X-Initiator header\r\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\r\n const isAgentCall = payload.messages.some((msg) =>\r\n [\"assistant\", \"tool\"].includes(msg.role),\r\n )\r\n\r\n // Build headers and add X-Initiator\r\n const headers: Record<string, string> = {\r\n ...copilotHeaders(state, enableVision),\r\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\r\n }\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/chat/completions`, {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create chat completions\", response)\r\n throw new HTTPError(\"Failed to create chat completions\", response)\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n\r\n// Streaming types\r\n\r\nexport interface ChatCompletionChunk {\r\n id: string\r\n object: \"chat.completion.chunk\"\r\n created: number\r\n model: string\r\n choices: Array<Choice>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n completion_tokens_details?: {\r\n accepted_prediction_tokens: number\r\n rejected_prediction_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface Delta {\r\n content?: string | null\r\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\r\n tool_calls?: Array<{\r\n index: number\r\n id?: string\r\n type?: \"function\"\r\n function?: {\r\n name?: string\r\n arguments?: string\r\n }\r\n }>\r\n}\r\n\r\ninterface Choice {\r\n index: number\r\n delta: Delta\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\r\n logprobs: object | null\r\n}\r\n\r\n// Non-streaming types\r\n\r\nexport interface ChatCompletionResponse {\r\n id: string\r\n object: \"chat.completion\"\r\n created: number\r\n model: string\r\n choices: Array<ChoiceNonStreaming>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface ResponseMessage {\r\n role: \"assistant\"\r\n content: string | null\r\n tool_calls?: Array<ToolCall>\r\n}\r\n\r\ninterface ChoiceNonStreaming {\r\n index: number\r\n message: ResponseMessage\r\n logprobs: object | null\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\r\n}\r\n\r\n// Payload types\r\n\r\nexport interface ChatCompletionsPayload {\r\n messages: Array<Message>\r\n model: string\r\n temperature?: number | null\r\n top_p?: number | null\r\n max_tokens?: number | null\r\n stop?: string | Array<string> | null\r\n n?: number | null\r\n stream?: boolean | null\r\n stream_options?: { include_usage?: boolean } | null\r\n\r\n frequency_penalty?: number | null\r\n presence_penalty?: number | null\r\n logit_bias?: Record<string, number> | null\r\n logprobs?: boolean | null\r\n response_format?: { type: \"json_object\" } | null\r\n seed?: number | null\r\n tools?: Array<Tool> | null\r\n tool_choice?:\r\n | \"none\"\r\n | \"auto\"\r\n | \"required\"\r\n | { type: \"function\"; function: { name: string } }\r\n | null\r\n user?: string | null\r\n}\r\n\r\nexport interface Tool {\r\n type: \"function\"\r\n function: {\r\n name: string\r\n description?: string\r\n parameters: Record<string, unknown>\r\n }\r\n}\r\n\r\nexport interface Message {\r\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\r\n content: string | Array<ContentPart> | null\r\n\r\n name?: string\r\n tool_calls?: Array<ToolCall>\r\n tool_call_id?: string\r\n}\r\n\r\nexport interface ToolCall {\r\n id: string\r\n type: \"function\"\r\n function: {\r\n name: string\r\n arguments: string\r\n }\r\n}\r\n\r\nexport type ContentPart = TextPart | ImagePart\r\n\r\nexport interface TextPart {\r\n type: \"text\"\r\n text: string\r\n}\r\n\r\nexport interface ImagePart {\r\n type: \"image_url\"\r\n image_url: {\r\n url: string\r\n detail?: \"low\" | \"high\" | \"auto\"\r\n }\r\n}\r\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport { getTokenCount } from \"~/lib/tokenizer\"\r\nimport { isNullish } from \"~/lib/utils\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n type ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const rawPayload = await c.req.json<ChatCompletionsPayload>()\r\n\r\n // Apply auto-replacements to the payload\r\n // eslint-disable-next-line require-atomic-updates\r\n let payload = await applyReplacementsToPayload(rawPayload)\r\n\r\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5)\r\n payload = {\r\n ...payload,\r\n model: normalizeModelName(payload.model),\r\n }\r\n\r\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\r\n\r\n // Check if this is an Azure OpenAI model\r\n if (isAzureOpenAIModel(payload.model)) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n\r\n setRequestContext(c, { provider: \"Azure OpenAI\", model: payload.model })\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n const response = await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig,\r\n payload,\r\n )\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n }\r\n\r\n setRequestContext(c, { provider: \"Copilot\", model: payload.model })\r\n\r\n // Find the selected model\r\n const selectedModel = state.models?.data.find(\r\n (model) => model.id === payload.model,\r\n )\r\n\r\n // Calculate and display token count\r\n try {\r\n if (selectedModel) {\r\n const tokenCount = await getTokenCount(payload, selectedModel)\r\n setRequestContext(c, { inputTokens: tokenCount.input })\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to calculate token count:\", error)\r\n }\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n if (isNullish(payload.max_tokens)) {\r\n payload = {\r\n ...payload,\r\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\r\n }\r\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\r\n }\r\n\r\n const response = await createChatCompletions(payload)\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n}\r\n\r\nconst isNonStreaming = (\r\n response: Awaited<ReturnType<typeof createChatCompletions>>,\r\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/embeddings`, {\r\n method: \"POST\",\r\n headers: copilotHeaders(state),\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\r\n\r\n return (await response.json()) as EmbeddingResponse\r\n}\r\n\r\nexport interface EmbeddingRequest {\r\n input: string | Array<string>\r\n model: string\r\n}\r\n\r\nexport interface Embedding {\r\n object: string\r\n embedding: Array<number>\r\n index: number\r\n}\r\n\r\nexport interface EmbeddingResponse {\r\n object: string\r\n data: Array<Embedding>\r\n model: string\r\n usage: {\r\n prompt_tokens: number\r\n total_tokens: number\r\n }\r\n}\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const paylod = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(paylod)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import {\n type ChatCompletionResponse,\n type ChatCompletionsPayload,\n type ContentPart,\n type Message,\n type TextPart,\n type Tool,\n type ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicAssistantContentBlock,\n type AnthropicAssistantMessage,\n type AnthropicMessage,\n type AnthropicMessagesPayload,\n type AnthropicResponse,\n type AnthropicTextBlock,\n type AnthropicThinkingBlock,\n type AnthropicTool,\n type AnthropicToolResultBlock,\n type AnthropicToolUseBlock,\n type AnthropicUserContentBlock,\n type AnthropicUserMessage,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\n// Payload translation\n\nexport function translateToOpenAI(\n payload: AnthropicMessagesPayload,\n): ChatCompletionsPayload {\n return {\n model: translateModelName(payload.model),\n messages: translateAnthropicMessagesToOpenAI(\n payload.messages,\n payload.system,\n ),\n max_tokens: payload.max_tokens,\n stop: payload.stop_sequences,\n stream: payload.stream,\n temperature: payload.temperature,\n top_p: payload.top_p,\n user: payload.metadata?.user_id,\n tools: translateAnthropicToolsToOpenAI(payload.tools),\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\n }\n}\n\nfunction translateModelName(model: string): string {\n // Subagent requests use a specific dated model which Copilot doesn't support\n // e.g., claude-sonnet-4-20250514 -> claude-sonnet-4\n // But preserve version numbers like claude-opus-4-5 (normalized to claude-opus-4.5 later)\n if (model.match(/^claude-sonnet-4-\\d{8}/)) {\n return \"claude-sonnet-4\"\n } else if (model.match(/^claude-opus-4-\\d{8}/)) {\n return \"claude-opus-4\"\n }\n return model\n}\n\nfunction translateAnthropicMessagesToOpenAI(\n anthropicMessages: Array<AnthropicMessage>,\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n const systemMessages = handleSystemPrompt(system)\n\n const otherMessages = anthropicMessages.flatMap((message) =>\n message.role === \"user\" ?\n handleUserMessage(message)\n : handleAssistantMessage(message),\n )\n\n return [...systemMessages, ...otherMessages]\n}\n\nfunction handleSystemPrompt(\n system: string | Array<AnthropicTextBlock> | undefined,\n): Array<Message> {\n if (!system) {\n return []\n }\n\n if (typeof system === \"string\") {\n return [{ role: \"system\", content: system }]\n } else {\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\n return [{ role: \"system\", content: systemText }]\n }\n}\n\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\n const newMessages: Array<Message> = []\n\n if (Array.isArray(message.content)) {\n const toolResultBlocks = message.content.filter(\n (block): block is AnthropicToolResultBlock =>\n block.type === \"tool_result\",\n )\n const otherBlocks = message.content.filter(\n (block) => block.type !== \"tool_result\",\n )\n\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\n for (const block of toolResultBlocks) {\n newMessages.push({\n role: \"tool\",\n tool_call_id: block.tool_use_id,\n content: mapContent(block.content),\n })\n }\n\n if (otherBlocks.length > 0) {\n newMessages.push({\n role: \"user\",\n content: mapContent(otherBlocks),\n })\n }\n } else {\n newMessages.push({\n role: \"user\",\n content: mapContent(message.content),\n })\n }\n\n return newMessages\n}\n\nfunction handleAssistantMessage(\n message: AnthropicAssistantMessage,\n): Array<Message> {\n if (!Array.isArray(message.content)) {\n return [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n }\n\n const toolUseBlocks = message.content.filter(\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\n )\n\n const textBlocks = message.content.filter(\n (block): block is AnthropicTextBlock => block.type === \"text\",\n )\n\n const thinkingBlocks = message.content.filter(\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\n )\n\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\n const allTextContent = [\n ...textBlocks.map((b) => b.text),\n ...thinkingBlocks.map((b) => b.thinking),\n ].join(\"\\n\\n\")\n\n return toolUseBlocks.length > 0 ?\n [\n {\n role: \"assistant\",\n content: allTextContent || null,\n tool_calls: toolUseBlocks.map((toolUse) => ({\n id: toolUse.id,\n type: \"function\",\n function: {\n name: toolUse.name,\n arguments: JSON.stringify(toolUse.input),\n },\n })),\n },\n ]\n : [\n {\n role: \"assistant\",\n content: mapContent(message.content),\n },\n ]\n}\n\nfunction mapContent(\n content:\n | string\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\n): string | Array<ContentPart> | null {\n if (typeof content === \"string\") {\n return content\n }\n if (!Array.isArray(content)) {\n return null\n }\n\n const hasImage = content.some((block) => block.type === \"image\")\n if (!hasImage) {\n return content\n .filter(\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\n block.type === \"text\" || block.type === \"thinking\",\n )\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\n .join(\"\\n\\n\")\n }\n\n const contentParts: Array<ContentPart> = []\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n contentParts.push({ type: \"text\", text: block.text })\n\n break\n }\n case \"thinking\": {\n contentParts.push({ type: \"text\", text: block.thinking })\n\n break\n }\n case \"image\": {\n contentParts.push({\n type: \"image_url\",\n image_url: {\n url: `data:${block.source.media_type};base64,${block.source.data}`,\n },\n })\n\n break\n }\n // No default\n }\n }\n return contentParts\n}\n\nfunction translateAnthropicToolsToOpenAI(\n anthropicTools: Array<AnthropicTool> | undefined,\n): Array<Tool> | undefined {\n if (!anthropicTools) {\n return undefined\n }\n return anthropicTools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n }))\n}\n\nfunction translateAnthropicToolChoiceToOpenAI(\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\n): ChatCompletionsPayload[\"tool_choice\"] {\n if (!anthropicToolChoice) {\n return undefined\n }\n\n switch (anthropicToolChoice.type) {\n case \"auto\": {\n return \"auto\"\n }\n case \"any\": {\n return \"required\"\n }\n case \"tool\": {\n if (anthropicToolChoice.name) {\n return {\n type: \"function\",\n function: { name: anthropicToolChoice.name },\n }\n }\n return undefined\n }\n case \"none\": {\n return \"none\"\n }\n default: {\n return undefined\n }\n }\n}\n\n// Response translation\n\nexport function translateToAnthropic(\n response: ChatCompletionResponse,\n): AnthropicResponse {\n // Merge content from all choices\n const allTextBlocks: Array<AnthropicTextBlock> = []\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\n null // default\n stopReason = response.choices[0]?.finish_reason ?? stopReason\n\n // Process all choices to extract text and tool use blocks\n for (const choice of response.choices) {\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\n\n allTextBlocks.push(...textBlocks)\n allToolUseBlocks.push(...toolUseBlocks)\n\n // Use the finish_reason from the first choice, or prioritize tool_calls\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\n stopReason = choice.finish_reason\n }\n }\n\n // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses\n\n return {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n model: response.model,\n content: [...allTextBlocks, ...allToolUseBlocks],\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\n stop_sequence: null,\n usage: {\n input_tokens:\n (response.usage?.prompt_tokens ?? 0)\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\n output_tokens: response.usage?.completion_tokens ?? 0,\n ...(response.usage?.prompt_tokens_details?.cached_tokens\n !== undefined && {\n cache_read_input_tokens:\n response.usage.prompt_tokens_details.cached_tokens,\n }),\n },\n }\n}\n\nfunction getAnthropicTextBlocks(\n messageContent: Message[\"content\"],\n): Array<AnthropicTextBlock> {\n if (typeof messageContent === \"string\") {\n return [{ type: \"text\", text: messageContent }]\n }\n\n if (Array.isArray(messageContent)) {\n return messageContent\n .filter((part): part is TextPart => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text }))\n }\n\n return []\n}\n\nfunction getAnthropicToolUseBlocks(\n toolCalls: Array<ToolCall> | undefined,\n): Array<AnthropicToolUseBlock> {\n if (!toolCalls) {\n return []\n }\n return toolCalls.map((toolCall) => ({\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\n }))\n}\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5) before lookup\n const normalizedModel = normalizeModelName(anthropicPayload.model)\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === normalizedModel,\n )\n\n if (!selectedModel) {\n consola.warn(\"Model not found, returning default token count\")\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n consola.info(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import {\n type ChatCompletionChunk,\n type ChatCompletionResponse,\n} from \"~/services/copilot/create-chat-completions\"\n\nimport {\n type AnthropicStreamEventData,\n type AnthropicStreamState,\n} from \"./anthropic-types\"\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\n\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\n if (!state.contentBlockOpen) {\n return false\n }\n // Check if the current block index corresponds to any known tool call\n return Object.values(state.toolCalls).some(\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\n )\n}\n\n// eslint-disable-next-line max-lines-per-function, complexity\nexport function translateChunkToAnthropicEvents(\n chunk: ChatCompletionChunk,\n state: AnthropicStreamState,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n if (chunk.choices.length === 0) {\n return events\n }\n\n const choice = chunk.choices[0]\n const { delta } = choice\n\n if (!state.messageStartSent) {\n // Don't include usage in message_start - we don't have accurate data yet\n // Claude Code will fall back to its own estimation\n // The actual usage will be sent in message_delta at the end\n events.push({\n type: \"message_start\",\n message: {\n id: chunk.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: chunk.model,\n stop_reason: null,\n stop_sequence: null,\n // Note: Intentionally omitting usage here so Claude Code uses its own estimates\n // until we get actual data in message_delta\n },\n })\n state.messageStartSent = true\n }\n\n if (delta.content) {\n if (isToolBlockOpen(state)) {\n // A tool block was open, so close it before starting a text block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n if (!state.contentBlockOpen) {\n events.push({\n type: \"content_block_start\",\n index: state.contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n state.contentBlockOpen = true\n }\n\n events.push({\n type: \"content_block_delta\",\n index: state.contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: delta.content,\n },\n })\n }\n\n if (delta.tool_calls) {\n for (const toolCall of delta.tool_calls) {\n if (toolCall.id && toolCall.function?.name) {\n // New tool call starting.\n if (state.contentBlockOpen) {\n // Close any previously open block.\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockIndex++\n state.contentBlockOpen = false\n }\n\n const anthropicBlockIndex = state.contentBlockIndex\n state.toolCalls[toolCall.index] = {\n id: toolCall.id,\n name: toolCall.function.name,\n anthropicBlockIndex,\n }\n\n events.push({\n type: \"content_block_start\",\n index: anthropicBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n state.contentBlockOpen = true\n }\n\n if (toolCall.function?.arguments) {\n const toolCallInfo = state.toolCalls[toolCall.index]\n // Tool call can still be empty\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (toolCallInfo) {\n events.push({\n type: \"content_block_delta\",\n index: toolCallInfo.anthropicBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n }\n }\n }\n }\n\n if (choice.finish_reason) {\n if (state.contentBlockOpen) {\n events.push({\n type: \"content_block_stop\",\n index: state.contentBlockIndex,\n })\n state.contentBlockOpen = false\n }\n\n // Get final usage from chunk - this is where the actual token counts are\n const inputTokens = chunk.usage?.prompt_tokens ?? 0\n const outputTokens = chunk.usage?.completion_tokens ?? 0\n const cachedTokens = chunk.usage?.prompt_tokens_details?.cached_tokens ?? 0\n\n events.push(\n {\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens: inputTokens,\n output_tokens: outputTokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: cachedTokens,\n },\n },\n {\n type: \"message_stop\",\n },\n )\n }\n\n return events\n}\n\n/**\n * Convert a complete OpenAI ChatCompletionResponse to Anthropic streaming events.\n * This is used when we fetch non-streaming from upstream but need to simulate\n * streaming to the client with accurate token counts.\n */\nexport function translateResponseToAnthropicEvents(\n response: ChatCompletionResponse,\n): Array<AnthropicStreamEventData> {\n const events: Array<AnthropicStreamEventData> = []\n\n const choice = response.choices[0]\n if (!choice) {\n return events\n }\n\n const inputTokens = response.usage?.prompt_tokens ?? 0\n const outputTokens = response.usage?.completion_tokens ?? 0\n const cachedTokens =\n response.usage?.prompt_tokens_details?.cached_tokens ?? 0\n\n // 1. message_start - with actual token counts from response\n events.push({\n type: \"message_start\",\n message: {\n id: response.id,\n type: \"message\",\n role: \"assistant\",\n content: [],\n model: response.model,\n stop_reason: null,\n stop_sequence: null,\n usage: {\n input_tokens: inputTokens,\n output_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: cachedTokens,\n },\n },\n })\n\n let contentBlockIndex = 0\n\n // Handle text content\n if (choice.message.content) {\n // 2. content_block_start for text\n events.push({\n type: \"content_block_start\",\n index: contentBlockIndex,\n content_block: {\n type: \"text\",\n text: \"\",\n },\n })\n\n // 3. content_block_delta with the full text\n events.push({\n type: \"content_block_delta\",\n index: contentBlockIndex,\n delta: {\n type: \"text_delta\",\n text: choice.message.content,\n },\n })\n\n // 4. content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: contentBlockIndex,\n })\n\n contentBlockIndex++\n }\n\n // Handle tool calls\n if (choice.message.tool_calls) {\n for (const toolCall of choice.message.tool_calls) {\n // content_block_start for tool_use\n events.push({\n type: \"content_block_start\",\n index: contentBlockIndex,\n content_block: {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.function.name,\n input: {},\n },\n })\n\n // content_block_delta with tool arguments\n events.push({\n type: \"content_block_delta\",\n index: contentBlockIndex,\n delta: {\n type: \"input_json_delta\",\n partial_json: toolCall.function.arguments,\n },\n })\n\n // content_block_stop\n events.push({\n type: \"content_block_stop\",\n index: contentBlockIndex,\n })\n\n contentBlockIndex++\n }\n }\n\n // 5. message_delta with final usage\n events.push({\n type: \"message_delta\",\n delta: {\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\n stop_sequence: null,\n },\n usage: {\n input_tokens: inputTokens,\n output_tokens: outputTokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: cachedTokens,\n },\n })\n\n // 6. message_stop\n events.push({\n type: \"message_stop\",\n })\n\n return events\n}\n\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\n return {\n type: \"error\",\n error: {\n type: \"api_error\",\n message: \"An unexpected error occurred during streaming.\",\n },\n }\n}\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicMessagesPayload,\r\n type AnthropicStreamState,\r\n} from \"./anthropic-types\"\r\nimport {\r\n translateToAnthropic,\r\n translateToOpenAI,\r\n} from \"./non-stream-translation\"\r\nimport {\r\n translateChunkToAnthropicEvents,\r\n} from \"./stream-translation\"\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\r\n consola.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\r\n\r\n const translatedPayload = translateToOpenAI(anthropicPayload)\r\n\r\n // Apply auto-replacements to the payload\r\n let openAIPayload = await applyReplacementsToPayload(translatedPayload)\r\n\r\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5)\r\n openAIPayload = {\r\n ...openAIPayload,\r\n model: normalizeModelName(openAIPayload.model),\r\n }\r\n\r\n consola.debug(\r\n \"Translated OpenAI request payload:\",\r\n JSON.stringify(openAIPayload),\r\n )\r\n\r\n if (state.manualApprove) {\r\n await awaitApproval()\r\n }\r\n\r\n // Route to Azure OpenAI if the model has the azure_openai_ prefix\r\n const isAzureModel = isAzureOpenAIModel(openAIPayload.model)\r\n\r\n if (isAzureModel) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n\r\n setRequestContext(c, {\r\n provider: \"Azure OpenAI\",\r\n model: openAIPayload.model,\r\n })\r\n } else {\r\n setRequestContext(c, { provider: \"Copilot\", model: openAIPayload.model })\r\n }\r\n\r\n // Handle streaming\r\n if (anthropicPayload.stream) {\r\n const streamPayload = {\r\n ...openAIPayload,\r\n stream: true,\r\n stream_options: { include_usage: true },\r\n }\r\n\r\n const response = isAzureModel\r\n ? await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig!,\r\n streamPayload,\r\n )\r\n : await createChatCompletions(streamPayload)\r\n\r\n // Response is an async iterable of SSE events\r\n const eventStream = response as AsyncIterable<{ event?: string; data?: string }>\r\n\r\n return streamSSE(c, async (stream) => {\r\n const streamState: AnthropicStreamState = {\r\n messageStartSent: false,\r\n contentBlockOpen: false,\r\n contentBlockIndex: 0,\r\n toolCalls: {},\r\n }\r\n\r\n for await (const event of eventStream) {\r\n if (!event.data || event.data === \"[DONE]\") {\r\n continue\r\n }\r\n\r\n try {\r\n const chunk = JSON.parse(event.data) as ChatCompletionChunk\r\n consola.debug(\"OpenAI chunk:\", JSON.stringify(chunk))\r\n\r\n const anthropicEvents = translateChunkToAnthropicEvents(\r\n chunk,\r\n streamState,\r\n )\r\n\r\n for (const anthropicEvent of anthropicEvents) {\r\n consola.debug(\"Anthropic event:\", JSON.stringify(anthropicEvent))\r\n await stream.writeSSE({\r\n event: anthropicEvent.type,\r\n data: JSON.stringify(anthropicEvent),\r\n })\r\n }\r\n\r\n // Update token counts from final chunk if available\r\n if (chunk.usage) {\r\n setRequestContext(c, {\r\n inputTokens: chunk.usage.prompt_tokens,\r\n outputTokens: chunk.usage.completion_tokens,\r\n })\r\n }\r\n } catch (error) {\r\n consola.error(\"Failed to parse chunk:\", error, event.data)\r\n }\r\n }\r\n })\r\n }\r\n\r\n // Non-streaming response\r\n const nonStreamPayload = { ...openAIPayload, stream: false }\r\n\r\n const response = isAzureModel\r\n ? ((await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig!,\r\n nonStreamPayload,\r\n )) as ChatCompletionResponse)\r\n : ((await createChatCompletions(nonStreamPayload)) as ChatCompletionResponse)\r\n\r\n consola.debug(\"Response from upstream:\", JSON.stringify(response).slice(-400))\r\n\r\n // Set token counts from response\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n\r\n // Translate to Anthropic format\r\n const anthropicResponse = translateToAnthropic(response)\r\n consola.debug(\r\n \"Translated Anthropic response:\",\r\n JSON.stringify(anthropicResponse),\r\n )\r\n return c.json(anthropicResponse)\r\n}\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n // Copilot models\n const copilotModels =\n state.models?.data.map((model) => ({\n id: model.id,\n object: \"model\",\n type: \"model\",\n created: 0, // No date available from source\n created_at: new Date(0).toISOString(), // No date available from source\n owned_by: model.vendor,\n display_name: model.name,\n })) ?? []\n\n // Azure OpenAI deployments\n const azureModels =\n state.azureOpenAIDeployments?.map((deployment) => ({\n id: deployment.id,\n object: \"model\",\n type: \"model\",\n created: deployment.created,\n created_at: new Date(deployment.created * 1000).toISOString(),\n owned_by: deployment.owned_by,\n display_name: `${deployment.deploymentName} (${deployment.model})`,\n })) ?? []\n\n const allModels = [...copilotModels, ...azureModels]\n\n return c.json({\n object: \"list\",\n data: allModels,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\r\n\r\nimport {\r\n addReplacement,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n} from \"~/lib/auto-replace\"\r\n\r\nexport const replacementsRoute = new Hono()\r\n\r\n// Get all replacement rules\r\nreplacementsRoute.get(\"/\", async (c) => {\r\n return c.json({\r\n all: await getAllReplacements(),\r\n user: await getUserReplacements(),\r\n })\r\n})\r\n\r\n// Add a new replacement rule\r\nreplacementsRoute.post(\"/\", async (c) => {\r\n const body = await c.req.json<{\r\n pattern: string\r\n replacement?: string\r\n isRegex?: boolean\r\n name?: string\r\n }>()\r\n\r\n if (!body.pattern) {\r\n return c.json({ error: \"Pattern is required\" }, 400)\r\n }\r\n\r\n const rule = await addReplacement(\r\n body.pattern,\r\n body.replacement ?? \"\",\r\n body.isRegex ?? false,\r\n body.name,\r\n )\r\n\r\n return c.json(rule, 201)\r\n})\r\n\r\n// Delete a replacement rule\r\nreplacementsRoute.delete(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const success = await removeReplacement(id)\r\n\r\n if (!success) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json({ success: true })\r\n})\r\n\r\n// Update a replacement rule\r\nreplacementsRoute.patch(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const body = await c.req.json<{\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n }>()\r\n\r\n const rule = await updateReplacement(id, body)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Toggle a replacement rule\r\nreplacementsRoute.patch(\"/:id/toggle\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const rule = await toggleReplacement(id)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Clear all user replacements\r\nreplacementsRoute.delete(\"/\", async (c) => {\r\n await clearUserReplacements()\r\n return c.json({ success: true })\r\n})\r\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n console.error(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n console.error(\"Error fetching Copilot usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\r\nimport { cors } from \"hono/cors\"\r\n\r\nimport { requestLogger } from \"./lib/request-logger\"\r\nimport { completionRoutes } from \"./routes/chat-completions/route\"\r\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\r\nimport { messageRoutes } from \"./routes/messages/route\"\r\nimport { modelRoutes } from \"./routes/models/route\"\r\nimport { replacementsRoute } from \"./routes/replacements/route\"\r\nimport { tokenRoute } from \"./routes/token/route\"\r\nimport { usageRoute } from \"./routes/usage/route\"\r\n\r\nexport const server = new Hono()\r\n\r\nserver.use(requestLogger)\r\nserver.use(cors())\r\n\r\nserver.get(\"/\", (c) => c.text(\"Server running\"))\r\n\r\nserver.route(\"/chat/completions\", completionRoutes)\r\nserver.route(\"/models\", modelRoutes)\r\nserver.route(\"/embeddings\", embeddingRoutes)\r\nserver.route(\"/usage\", usageRoute)\r\nserver.route(\"/token\", tokenRoute)\r\nserver.route(\"/replacements\", replacementsRoute)\r\n\r\n// Compatibility with tools that expect v1/ prefix\r\nserver.route(\"/v1/chat/completions\", completionRoutes)\r\nserver.route(\"/v1/models\", modelRoutes)\r\nserver.route(\"/v1/embeddings\", embeddingRoutes)\r\n\r\n// Anthropic compatible endpoints\r\nserver.route(\"/v1/messages\", messageRoutes)\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion, setupAzureOpenAI } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n insecure: boolean\n debug: boolean\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n if (options.insecure) {\n // Disable SSL certificate verification globally\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\"\n consola.warn(\"SSL certificate verification disabled (insecure mode)\")\n }\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.debug = options.debug\n\n if (options.debug) {\n consola.info(\"Debug mode enabled - raw HTTP requests will be logged\")\n }\n\n await ensurePaths()\n await cacheVSCodeVersion()\n\n if (options.githubToken) {\n state.githubToken = options.githubToken\n consola.info(\"Using provided GitHub token\")\n } else {\n await setupGitHubToken()\n }\n\n await setupCopilotToken()\n await cacheModels()\n\n // Setup Azure OpenAI (prompt on first run, load from config thereafter)\n await setupAzureOpenAI()\n\n // Build combined model list for display\n const copilotModelIds = state.models?.data.map((model) => model.id) ?? []\n const azureModelIds =\n state.azureOpenAIDeployments?.map((deployment) => deployment.id) ?? []\n const allModelIds = [...copilotModelIds, ...azureModelIds]\n\n consola.info(\n `Available models: \\n${allModelIds.map((id) => `- ${id}`).join(\"\\n\")}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n invariant(state.models, \"Models should be loaded by now\")\n\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n }\n\n consola.box(\n `🌐 Usage Viewer: https://ericc-ch.github.io/copilot-api?endpoint=${serverUrl}/usage`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n insecure: {\n type: \"boolean\",\n default: false,\n description:\n \"Disable SSL certificate verification (for corporate proxies with self-signed certs)\",\n },\n debug: {\n alias: \"d\",\n type: \"boolean\",\n default: false,\n description: \"Log raw HTTP requests received by the server (headers, method, path)\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n insecure: args.insecure,\n debug: args.debug,\n })\n },\n})\n","#!/usr/bin/env node\r\n\r\nimport { defineCommand, runMain } from \"citty\"\r\n\r\nimport { auth } from \"./auth\"\r\nimport { checkUsage } from \"./check-usage\"\r\nimport { config } from \"./config\"\r\nimport { debug } from \"./debug\"\r\nimport { start } from \"./start\"\r\n\r\nconst main = defineCommand({\r\n meta: {\r\n name: \"copilot-api\",\r\n description:\r\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\r\n },\r\n subCommands: { auth, start, \"check-usage\": checkUsage, debug, config },\r\n})\r\n\r\nawait runMain(main)\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAIA,MAAM,UAAU,KAAK,KAAK,GAAG,SAAS,EAAE,UAAU,SAAS,cAAc;AAEzE,MAAM,oBAAoB,KAAK,KAAK,SAAS,eAAe;AAC5D,MAAM,2BAA2B,KAAK,KAAK,SAAS,sBAAsB;AAC1E,MAAM,2BAA2B,KAAK,KAAK,SAAS,oBAAoB;AAExE,MAAa,QAAQ;CACnB;CACA;CACA;CACA;CACD;AAED,eAAsB,cAA6B;AACjD,OAAM,GAAG,MAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;AAClD,OAAM,WAAW,MAAM,kBAAkB;AACzC,OAAM,WAAW,MAAM,yBAAyB;;AAGlD,eAAe,WAAW,UAAiC;AACzD,KAAI;AACF,QAAM,GAAG,OAAO,UAAU,GAAG,UAAU,KAAK;SACtC;AACN,QAAM,GAAG,UAAU,UAAU,GAAG;AAChC,QAAM,GAAG,MAAM,UAAU,IAAM;;;;;;ACAnC,MAAaA,QAAe;CAC1B,aAAa;CACb,eAAe;CACf,eAAe;CACf,WAAW;CACX,OAAO;CACR;;;;AC9BD,MAAa,yBAAyB;CACpC,gBAAgB;CAChB,QAAQ;CACT;AAED,MAAM,kBAAkB;AACxB,MAAM,wBAAwB,gBAAgB;AAC9C,MAAM,aAAa,qBAAqB;AAExC,MAAM,cAAc;AAEpB,MAAa,kBAAkB,YAC7BC,QAAM,gBAAgB,eACpB,kCACA,eAAeA,QAAM,YAAY;AACrC,MAAa,kBAAkB,SAAc,SAAkB,UAAU;CACvE,MAAMC,UAAkC;EACtC,eAAe,UAAUD,QAAM;EAC/B,gBAAgB,iBAAiB,CAAC;EAClC,0BAA0B;EAC1B,kBAAkB,UAAUA,QAAM;EAClC,yBAAyB;EACzB,cAAc;EACd,iBAAiB;EACjB,wBAAwB;EACxB,gBAAgB,YAAY;EAC5B,uCAAuC;EACxC;AAED,KAAI,OAAQ,SAAQ,4BAA4B;AAEhD,QAAO;;AAGT,MAAa,sBAAsB;AACnC,MAAa,iBAAiB,aAAkB;CAC9C,GAAG,iBAAiB;CACpB,eAAe,SAASA,QAAM;CAC9B,kBAAkB,UAAUA,QAAM;CAClC,yBAAyB;CACzB,cAAc;CACd,wBAAwB;CACxB,uCAAuC;CACxC;AAED,MAAa,kBAAkB;AAC/B,MAAa,mBAAmB;AAChC,MAAa,oBAAoB,CAAC,YAAY,CAAC,KAAK,IAAI;;;;AC9CxD,IAAa,YAAb,cAA+B,MAAM;CACnC;CACA;CAEA,YAAY,SAAiB,UAAoB,gBAA0B;AACzE,QAAM,QAAQ;AACd,OAAK,WAAW;AAChB,OAAK,iBAAiB;;;AAc1B,SAAS,qBAAqB,KAAyC;AACrE,QACE,OAAO,QAAQ,YACf,QAAQ,QACR,WAAW,OACX,OAAQ,IAA2B,UAAU,YAC5C,IAA2B,OAAO,SAAS;;AAIhD,eAAsB,aAAa,GAAY,OAAgB;AAC7D,SAAQ,MAAM,mBAAmB,MAAM;AAEvC,KAAI,iBAAiB,WAAW;EAC9B,MAAM,YAAY,MAAM,MAAM,SAAS,MAAM;EAC7C,IAAIE;AACJ,MAAI;AACF,eAAY,KAAK,MAAM,UAAU;UAC3B;AACN,eAAY;;AAEd,UAAQ,MAAM,eAAe,UAAU;AAGvC,MAAI,qBAAqB,UAAU,EAAE;AACnC,WAAQ,IAAI,2BAA2B;AACvC,WAAQ,MAAM,uBAAuB;AACrC,WAAQ,IAAI,KAAK,UAAU,WAAW,MAAM,EAAE,CAAC;AAE/C,OAAI,MAAM,gBAAgB;AACxB,YAAQ,MAAM,6CAA6C;AAC3D,YAAQ,IAAI,KAAK,UAAU,MAAM,gBAAgB,MAAM,EAAE,CAAC;;;AAI9D,SAAO,EAAE,KACP,EACE,OAAO;GACL,SAAS;GACT,MAAM;GACP,EACF,EACD,MAAM,SAAS,OAChB;;AAGH,QAAO,EAAE,KACP,EACE,OAAO;EACL,SAAU,MAAgB;EAC1B,MAAM;EACP,EACF,EACD,IACD;;;;;AC5EH,MAAa,kBAAkB,YAAY;CACzC,MAAM,WAAW,MAAM,MACrB,GAAG,oBAAoB,6BACvB,EACE,SAAS,cAAc,MAAM,EAC9B,CACF;AAED,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,+BAA+B,SAAS;AAE9E,QAAQ,MAAM,SAAS,MAAM;;;;;ACN/B,eAAsB,gBAA6C;CACjE,MAAM,WAAW,MAAM,MAAM,GAAG,gBAAgB,qBAAqB;EACnE,QAAQ;EACR,SAAS,iBAAiB;EAC1B,MAAM,KAAK,UAAU;GACnB,WAAW;GACX,OAAO;GACR,CAAC;EACH,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,6BAA6B,SAAS;AAE5E,QAAQ,MAAM,SAAS,MAAM;;;;;AChB/B,eAAsB,gBAAgB;CACpC,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAC1D,SAAS;EACP,eAAe,SAAS,MAAM;EAC9B,GAAG,iBAAiB;EACrB,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,6BAA6B,SAAS;AAE5E,QAAQ,MAAM,SAAS,MAAM;;;;;ACP/B,MAAa,4BAA4B;AAEzC,eAAsB,wBAA2D;AAC/E,KAAI;EACF,MAAM,UAAU,MAAM,GAAG,SAAS,MAAM,0BAA0B,OAAO;AACzE,MAAI,CAAC,QAAQ,MAAM,CACjB,QAAO;EAGT,MAAM,UAAU,OAAO,KAAK,QAAQ,MAAM,EAAE,SAAS,CAAC,SAAS,OAAO;EACtE,MAAMC,WAAS,KAAK,MAAM,QAAQ;AAElC,MAAI,CAACA,SAAO,YAAY,CAACA,SAAO,OAC9B,QAAO;AAGT,SAAOA;SACD;AACN,SAAO;;;AAIX,eAAsB,sBACpB,UACe;CACf,MAAM,UAAU,OAAO,KAAK,KAAK,UAAUA,SAAO,CAAC,CAAC,SAAS,SAAS;AACtE,OAAM,GAAG,UAAU,MAAM,0BAA0B,SAAS,OAAO;AACnE,OAAM,GAAG,MAAM,MAAM,0BAA0B,IAAM;AACrD,SAAQ,QAAQ,mCAAmC;;AAGrD,eAAsB,yBAA4D;AAShF,KAAI,CARc,MAAM,QAAQ,OAC9B,yDACA;EACE,MAAM;EACN,SAAS;EACV,CACF,CAGC,QAAO;CAGT,MAAM,WAAW,MAAM,QAAQ,OAC7B,wFACA,EACE,MAAM,QACP,CACF;AAED,KAAI,CAAC,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM,EAAE;AACjE,UAAQ,KAAK,oDAAoD;AACjE,SAAO;;CAGT,MAAM,SAAS,MAAM,QAAQ,OAAO,oCAAoC,EACtE,MAAM,QACP,CAAC;AAEF,KAAI,CAAC,UAAU,OAAO,WAAW,YAAY,CAAC,OAAO,MAAM,EAAE;AAC3D,UAAQ,KAAK,mDAAmD;AAChE,SAAO;;CAGT,MAAMC,WAA4B;EAChC,UAAU,SAAS,MAAM,CAAC,QAAQ,OAAO,GAAG;EAC5C,QAAQ,OAAO,MAAM;EACtB;AAED,OAAM,sBAAsBD,SAAO;AACnC,QAAOA;;AAGT,SAAgB,mBAAmB,SAA0B;AAC3D,QAAO,QAAQ,WAAW,0BAA0B;;AAGtD,SAAgB,uBAAuB,SAAyB;AAC9D,QAAO,QAAQ,MAAM,GAAiC;;;;;ACjFxD,MAAM,kBAAkB;CAAC;CAAK;CAAK;CAAI;;;;AAKvC,SAAS,iBAAiB,OAAyB;AACjD,KAAI,EAAE,iBAAiB,OAAQ,QAAO;CAEtC,MAAM,UAAU,MAAM,QAAQ,aAAa;CAC3C,MAAM,eACJ,MAAM,iBAAiB,QAAQ,MAAM,MAAM,QAAQ,aAAa,GAAG;AAiBrE,QAd0B;EACxB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAEwB,MACtB,YAAY,QAAQ,SAAS,QAAQ,IAAI,aAAa,SAAS,QAAQ,CACzE;;;;;AAMH,SAAS,kBAAkB,QAAyB;AAGlD,QAAO,WAAW,OAAO,WAAW,OAAQ,UAAU,OAAO,UAAU;;;;;;AAOzE,eAAsB,eACpB,OACA,MACmB;CACnB,MAAM,cAAc,gBAAgB,SAAS;CAE7C,IAAIE;CACJ,IAAIC;AAEJ,MAAK,IAAI,UAAU,GAAG,UAAU,aAAa,UAC3C,KAAI;EAEF,MAAM,UAAU,IAAI,QAAQ,MAAM,QAAQ;AAG1C,UAAQ,IAAI,cAAc,QAAQ;EAElC,MAAM,WAAW,MAAM,MAAM,OAAO;GAClC,GAAG;GACH;GAEA,WAAW;GACZ,CAAC;AAGF,MAAI,kBAAkB,SAAS,OAAO,IAAI,UAAU,cAAc,GAAG;AACnE,kBAAe;GACf,MAAM,UAAU,gBAAgB;AAChC,WAAQ,KACN,QAAQ,SAAS,OAAO,YAAY,UAAU,EAAE,GAAG,YAAY,iBAAiB,QAAQ,IACzF;AACD,SAAM,MAAM,QAAQ;AACpB;;AAGF,SAAO;UACA,OAAO;AACd,cAAY;AAEZ,MAAI,CAAC,iBAAiB,MAAM,IAAI,YAAY,cAAc,EACxD,OAAM;EAGR,MAAM,UAAU,gBAAgB;AAChC,UAAQ,KACN,yBAAyB,UAAU,EAAE,GAAG,YAAY,iBAAiB,QAAQ,MAC7E,UAAU,QACX;AACD,QAAM,MAAM,QAAQ;;AAKxB,KAAI,aACF,QAAO;AAGT,OAAM;;;;;AC5FR,MAAM,oBAAoB;AAE1B,eAAsB,iCACpB,UACA,SACA;CAEA,MAAM,iBAAiB,uBAAuB,QAAQ,MAAM;CAI5D,MAAM,EAAE,WAAY,GAAG,gBAAgB;CACvC,MAAM,eAAe;EACnB,GAAG;EACH,OAAO;EACP,GAAI,cAAc,QAAQ,EAAE,uBAAuB,YAAY;EAChE;CAED,MAAM,WAAW,MAAM,eACrB,GAAGC,SAAO,SAAS,sBAAsB,eAAe,gCAAgC,qBACxF;EACE,QAAQ;EACR,SAAS;GACP,WAAWA,SAAO;GAClB,gBAAgB;GACjB;EACD,MAAM,KAAK,UAAU,aAAa;EACnC,CACF;AAED,KAAI,CAAC,SAAS,IAAI;AAChB,UAAQ,MAAM,mDAAmD,SAAS;AAC1E,QAAM,IAAI,UACR,kDACA,UACA,QACD;;AAGH,KAAI,QAAQ,OACV,QAAO,OAAO,SAAS;AAGzB,QAAQ,MAAM,SAAS,MAAM;;;;;AC5C/B,MAAM,gCAAgC;AAEtC,eAAsB,0BACpB,UAC2C;AAC3C,KAAI;EACF,MAAM,WAAW,MAAM,eACrB,GAAGC,SAAO,SAAS,kCAAkC,iCACrD,EACE,SAAS;GACP,WAAWA,SAAO;GAClB,gBAAgB;GACjB,EACF,CACF;AAED,MAAI,CAAC,SAAS,IAAI;GAChB,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,YAAY,GAAG;AACvD,WAAQ,MACN,6CAA6C,SAAS,UACtD,UACD;AACD,SAAM,IAAI,UAAU,4CAA4C,SAAS;;AAM3E,UAHc,MAAM,SAAS,MAAM,EAGvB,KACT,QAAQ,eAAe,WAAW,WAAW,YAAY,CACzD,KAAK,gBAAgB;GACpB,IAAI,GAAG,4BAA4B,WAAW;GAC9C,gBAAgB,WAAW;GAC3B,OAAO,WAAW;GAClB,SAAS,WAAW;GACpB,QAAQ;GACR,UAAU,WAAW,SAAS;GAC/B,EAAE;UACE,OAAO;AACd,MAAI,iBAAiB,UACnB,OAAM;AAER,UAAQ,MAAM,6CAA6C,MAAM;AACjE,SAAO,EAAE;;;;;;AClDb,MAAa,YAAY,YAAY;CACnC,MAAM,MAAM,GAAG,eAAe,MAAM,CAAC;CACrC,MAAM,WAAW,MAAM,eAAe,KAAK,EACzC,SAAS,eAAe,MAAM,EAC/B,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,YAAY,MAAM,SAAS,MAAM;EACvC,IAAIC;AACJ,MAAI;GACF,MAAMC,SAAkB,KAAK,MAAM,UAAU;AAC7C,kBAAe,KAAK,UAAU,QAAQ,MAAM,EAAE;UACxC;AACN,kBAAe,aAAa;;AAE9B,UAAQ,MACN,6BAA6B,IAAI,YAClB,SAAS,OAAO,GAAG,SAAS,WAAW,cACrC,eAClB;AACD,QAAM,IAAI,UACR,yBAAyB,SAAS,OAAO,GAAG,SAAS,cACrD,SACD;;AAGH,QAAQ,MAAM,SAAS,MAAM;;;;;ACjC/B,MAAM,WAAW;AAEjB,eAAsB,mBAAmB;CACvC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,UAAU,iBAAiB;AAC/B,aAAW,OAAO;IACjB,IAAK;AAER,KAAI;EAUF,MAAM,SAFW,OAPA,MAAM,MACrB,kFACA,EACE,QAAQ,WAAW,QACpB,CACF,EAE+B,MAAM,EAEf,MADH,mBACqB;AAEzC,MAAI,MACF,QAAO,MAAM;AAGf,SAAO;SACD;AACN,SAAO;WACC;AACR,eAAa,QAAQ;;;AAIzB,MAAM,kBAAkB;;;;ACpBxB,MAAa,SAAS,OACpB,IAAI,SAAS,YAAY;AACvB,YAAW,SAAS,GAAG;EACvB;AAEJ,MAAa,aAAa,UACxB,UAAU,QAAQ,UAAU;AAE9B,eAAsB,cAA6B;AACjD,KAAI;AAEF,QAAM,SADS,MAAM,WAAW;UAEzB,OAAO;AACd,UAAQ,MAAM,0DAA0D;AACxE,UAAQ,MAAM,uCAAuC;AACrD,UAAQ,MAAM,kCAAkC;AAChD,UAAQ,MAAM,yCAAyC;AACvD,UAAQ,MACN,uFACD;AACD,QAAM;;;AAIV,MAAa,qBAAqB,YAAY;CAC5C,MAAM,WAAW,MAAM,kBAAkB;AACzC,OAAM,gBAAgB;AAEtB,SAAQ,KAAK,yBAAyB,WAAW;;AAGnD,eAAsB,mBAAkC;CAEtD,IAAIC,WAAS,MAAM,uBAAuB;AAG1C,KAAI,CAACA,SACH,YAAS,MAAM,wBAAwB;AAGzC,KAAI,CAACA,UAAQ;AACX,UAAQ,KAAK,8BAA8B;AAC3C;;AAGF,OAAM,oBAAoBA;AAC1B,SAAQ,KAAK,oCAAoC;AAGjD,KAAI;EACF,MAAM,cAAc,MAAM,0BAA0BA,SAAO;AAC3D,QAAM,yBAAyB;AAC/B,MAAI,YAAY,SAAS,EACvB,SAAQ,KACN,UAAU,YAAY,OAAO,gCAAgC,YAAY,KAAK,MAAM,KAAK,EAAE,GAAG,IAAI,EAAE,MAAM,GAAG,CAAC,KAAK,KAAK,GACzH;MAED,SAAQ,KAAK,oCAAoC;UAE5C,OAAO;AACd,UAAQ,KAAK,6CAA6C,MAAM;;;;;;AC7DpE,eAAsB,gBACpB,YACiB;CAGjB,MAAM,iBAAiB,WAAW,WAAW,KAAK;AAClD,SAAQ,MAAM,yCAAyC,cAAc,IAAI;AAEzE,QAAO,MAAM;EACX,MAAM,WAAW,MAAM,MACrB,GAAG,gBAAgB,4BACnB;GACE,QAAQ;GACR,SAAS,iBAAiB;GAC1B,MAAM,KAAK,UAAU;IACnB,WAAW;IACX,aAAa,WAAW;IACxB,YAAY;IACb,CAAC;GACH,CACF;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,SAAM,MAAM,cAAc;AAC1B,WAAQ,MAAM,gCAAgC,MAAM,SAAS,MAAM,CAAC;AAEpE;;EAGF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,UAAQ,MAAM,kCAAkC,KAAK;EAErD,MAAM,EAAE,iBAAiB;AAEzB,MAAI,aACF,QAAO;MAEP,OAAM,MAAM,cAAc;;;;;;ACpChC,MAAM,wBAAwB,GAAG,SAAS,MAAM,mBAAmB,OAAO;AAE1E,MAAM,oBAAoB,UACxB,GAAG,UAAU,MAAM,mBAAmB,MAAM;AAE9C,MAAa,oBAAoB,YAAY;CAC3C,MAAM,EAAE,OAAO,eAAe,MAAM,iBAAiB;AACrD,OAAM,eAAe;AAGrB,SAAQ,MAAM,6CAA6C;AAC3D,KAAI,MAAM,UACR,SAAQ,KAAK,kBAAkB,MAAM;CAGvC,MAAM,mBAAmB,aAAa,MAAM;AAC5C,aAAY,YAAY;AACtB,UAAQ,MAAM,2BAA2B;AACzC,MAAI;GACF,MAAM,EAAE,mBAAU,MAAM,iBAAiB;AACzC,SAAM,eAAeC;AACrB,WAAQ,MAAM,0BAA0B;AACxC,OAAI,MAAM,UACR,SAAQ,KAAK,4BAA4BA,QAAM;WAE1C,OAAO;AACd,WAAQ,MAAM,oCAAoC,MAAM;AACxD,SAAM;;IAEP,gBAAgB;;AAOrB,eAAsB,iBACpB,SACe;AACf,KAAI;EACF,MAAM,cAAc,MAAM,iBAAiB;AAE3C,MAAI,eAAe,CAAC,SAAS,OAAO;AAClC,SAAM,cAAc;AACpB,OAAI,MAAM,UACR,SAAQ,KAAK,iBAAiB,YAAY;AAE5C,SAAM,SAAS;AAEf;;AAGF,UAAQ,KAAK,0CAA0C;EACvD,MAAM,WAAW,MAAM,eAAe;AACtC,UAAQ,MAAM,yBAAyB,SAAS;AAEhD,UAAQ,KACN,0BAA0B,SAAS,UAAU,OAAO,SAAS,mBAC9D;EAED,MAAM,QAAQ,MAAM,gBAAgB,SAAS;AAC7C,QAAM,iBAAiB,MAAM;AAC7B,QAAM,cAAc;AAEpB,MAAI,MAAM,UACR,SAAQ,KAAK,iBAAiB,MAAM;AAEtC,QAAM,SAAS;UACR,OAAO;AACd,MAAI,iBAAiB,WAAW;AAC9B,WAAQ,MAAM,+BAA+B,MAAM,MAAM,SAAS,MAAM,CAAC;AACzE,SAAM;;AAGR,UAAQ,MAAM,+BAA+B,MAAM;AACnD,QAAM;;;AAIV,eAAe,UAAU;CACvB,MAAM,OAAO,MAAM,eAAe;AAClC,SAAQ,KAAK,gBAAgB,KAAK,QAAQ;;;;;AC/E5C,eAAsB,QAAQ,SAAwC;AACpE,KAAI,QAAQ,SAAS;AACnB,UAAQ,QAAQ;AAChB,UAAQ,KAAK,0BAA0B;;AAGzC,OAAM,YAAY,QAAQ;AAE1B,OAAM,aAAa;AACnB,OAAM,iBAAiB,EAAE,OAAO,MAAM,CAAC;AACvC,SAAQ,QAAQ,2BAA2B,MAAM,kBAAkB;;AAGrE,MAAa,OAAO,cAAc;CAChC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM;EACJ,SAAS;GACP,OAAO;GACP,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,cAAc;GACZ,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACF;CACD,IAAI,EAAE,QAAQ;AACZ,SAAO,QAAQ;GACb,SAAS,KAAK;GACd,WAAW,KAAK;GACjB,CAAC;;CAEL,CAAC;;;;AC/CF,MAAa,kBAAkB,YAA2C;CACxE,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,yBAAyB,EAC3E,SAAS,cAAc,MAAM,EAC9B,CAAC;AAEF,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,UAAU,+BAA+B,SAAS;AAG9D,QAAQ,MAAM,SAAS,MAAM;;;;;ACH/B,MAAa,aAAa,cAAc;CACtC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,MAAM;AACV,QAAM,aAAa;AACnB,QAAM,kBAAkB;AACxB,MAAI;GACF,MAAM,QAAQ,MAAM,iBAAiB;GACrC,MAAM,UAAU,MAAM,gBAAgB;GACtC,MAAM,eAAe,QAAQ;GAC7B,MAAM,cAAc,eAAe,QAAQ;GAC3C,MAAM,qBACJ,eAAe,IAAK,cAAc,eAAgB,MAAM;GAC1D,MAAM,0BAA0B,QAAQ;GAGxC,SAAS,eAAe,MAAc,MAA+B;AACnE,QAAI,CAAC,KAAM,QAAO,GAAG,KAAK;IAC1B,MAAM,QAAQ,KAAK;IACnB,MAAM,OAAO,QAAQ,KAAK;IAC1B,MAAM,cAAc,QAAQ,IAAK,OAAO,QAAS,MAAM;IACvD,MAAM,mBAAmB,KAAK;AAC9B,WAAO,GAAG,KAAK,IAAI,KAAK,GAAG,MAAM,SAAS,YAAY,QAAQ,EAAE,CAAC,UAAU,iBAAiB,QAAQ,EAAE,CAAC;;GAGzG,MAAM,cAAc,YAAY,YAAY,GAAG,aAAa,SAAS,mBAAmB,QAAQ,EAAE,CAAC,UAAU,wBAAwB,QAAQ,EAAE,CAAC;GAChJ,MAAM,WAAW,eAAe,QAAQ,MAAM,gBAAgB,KAAK;GACnE,MAAM,kBAAkB,eACtB,eACA,MAAM,gBAAgB,YACvB;AAED,WAAQ,IACN,wBAAwB,MAAM,aAAa,mBACtB,MAAM,iBAAiB,iBAEnC,YAAY,MACZ,SAAS,MACT,kBACV;WACM,KAAK;AACZ,WAAQ,MAAM,kCAAkC,IAAI;AACpD,WAAQ,KAAK,EAAE;;;CAGpB,CAAC;;;;ACvCF,MAAMC,sBAA8C,CAClD;CACE,IAAI;CACJ,MAAM;CACN,SAAS;CACT,aAAa;CACb,SAAS;CACT,SAAS;CACT,UAAU;CACX,CACF;AAGD,IAAIC,mBAA2C,EAAE;AACjD,IAAI,WAAW;;;;AAKf,eAAsB,mBAAkC;AACtD,KAAI;EACF,MAAM,OAAO,MAAM,GAAG,SAAS,MAAM,yBAAyB;AAE9D,qBADe,KAAK,MAAM,KAAK,UAAU,CAAC,CAChB,QAAQ,MAAM,CAAC,EAAE,SAAS;AACpD,aAAW;AACX,UAAQ,MAAM,UAAU,iBAAiB,OAAO,yBAAyB;SACnE;AAEN,qBAAmB,EAAE;AACrB,aAAW;;;;;;AAOf,eAAsB,mBAAkC;AACtD,KAAI;AACF,QAAM,GAAG,UACP,MAAM,0BACN,KAAK,UAAU,kBAAkB,MAAM,EAAE,EACzC,OACD;AACD,UAAQ,MAAM,SAAS,iBAAiB,OAAO,yBAAyB;UACjE,OAAO;AACd,UAAQ,MAAM,qCAAqC,MAAM;AACzD,QAAM;;;;;;AAOV,eAAsB,eAA8B;AAClD,KAAI,CAAC,SACH,OAAM,kBAAkB;;;;;AAO5B,eAAsB,qBAAsD;AAC1E,OAAM,cAAc;AACpB,QAAO,CAAC,GAAG,qBAAqB,GAAG,iBAAiB;;;;;AAMtD,eAAsB,sBAAuD;AAC3E,OAAM,cAAc;AACpB,QAAO;;;;;AAMT,eAAsB,eACpB,SACA,aACA,UAAU,OACV,MAC0B;AAC1B,OAAM,cAAc;CACpB,MAAMC,OAAwB;EAC5B,IAAI,QAAQ,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;EAChE;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACX;AACD,kBAAiB,KAAK,KAAK;AAC3B,OAAM,kBAAkB;AACxB,SAAQ,KAAK,4BAA4B,QAAQ,QAAQ,YAAY,GAAG;AACxE,QAAO;;;;;AAMT,eAAsB,kBAAkB,IAA8B;AACpE,OAAM,cAAc;CACpB,MAAM,OAAO,iBAAiB,MAAM,MAAM,EAAE,OAAO,GAAG;AACtD,KAAI,CAAC,KACH,QAAO;AAET,KAAI,KAAK,UAAU;AACjB,UAAQ,KAAK,wCAAwC;AACrD,SAAO;;AAET,oBAAmB,iBAAiB,QAAQ,MAAM,EAAE,OAAO,GAAG;AAC9D,OAAM,kBAAkB;AACxB,SAAQ,KAAK,6BAA6B,KAAK;AAC/C,QAAO;;;;;AAMT,eAAsB,kBACpB,IACA,SAOiC;AACjC,OAAM,cAAc;CAEpB,MAAM,OAAO,iBAAiB,MAAM,MAAM,EAAE,OAAO,GAAG;AACtD,KAAI,CAAC,KACH,QAAO;AAGT,KAAI,KAAK,UAAU;AACjB,UAAQ,KAAK,wCAAwC;AACrD,SAAO;;AAGT,KAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AACpD,KAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAC1D,KAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,KAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAC1D,KAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAE1D,OAAM,kBAAkB;AACxB,SAAQ,KAAK,6BAA6B,KAAK,QAAQ,KAAK,KAAK;AACjE,QAAO;;;;;AAMT,eAAsB,kBACpB,IACiC;AACjC,OAAM,cAAc;CAEpB,MAAM,WAAW,iBAAiB,MAAM,MAAM,EAAE,OAAO,GAAG;AAC1D,KAAI,UAAU;AACZ,WAAS,UAAU,CAAC,SAAS;AAC7B,QAAM,kBAAkB;AACxB,UAAQ,KACN,4BAA4B,GAAG,IAAI,SAAS,UAAU,YAAY,aACnE;AACD,SAAO;;AAKT,KADmB,oBAAoB,MAAM,MAAM,EAAE,OAAO,GAAG,EAC/C;AACd,UAAQ,KAAK,wCAAwC;AACrD,SAAO;;AAGT,QAAO;;;;;AAMT,eAAsB,wBAAuC;AAC3D,oBAAmB,EAAE;AACrB,OAAM,kBAAkB;AACxB,SAAQ,KAAK,qCAAqC;;;;;AAMpD,SAAS,UACP,MACA,MACsC;AACtC,KAAI,CAAC,KAAK,QAAS,QAAO;EAAE,QAAQ;EAAM,SAAS;EAAO;AAE1D,KAAI,KAAK,QACP,KAAI;EACF,MAAM,QAAQ,IAAI,OAAO,KAAK,SAAS,IAAI;EAC3C,MAAMC,WAAS,KAAK,QAAQ,OAAO,KAAK,YAAY;AACpD,SAAO;GAAE;GAAQ,SAASA,aAAW;GAAM;SACrC;AACN,UAAQ,KAAK,iCAAiC,KAAK,GAAG,IAAI,KAAK,UAAU;AACzE,SAAO;GAAE,QAAQ;GAAM,SAAS;GAAO;;CAI3C,MAAM,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,YAAY;AAC9D,QAAO;EAAE;EAAQ,SAAS,WAAW;EAAM;;;;;AAM7C,eAAsB,kBAAkB,MAA+B;CACrE,IAAI,SAAS;CACb,MAAM,WAAW,MAAM,oBAAoB;CAC3C,MAAMC,eAAyB,EAAE;AAEjC,MAAK,MAAM,QAAQ,UAAU;EAC3B,MAAM,EAAE,QAAQ,WAAW,YAAY,UAAU,QAAQ,KAAK;AAC9D,MAAI,SAAS;AACX,YAAS;AACT,gBAAa,KAAK,KAAK,QAAQ,KAAK,GAAG;;;AAI3C,KAAI,aAAa,SAAS,EACxB,SAAQ,KAAK,yBAAyB,aAAa,KAAK,KAAK,GAAG;AAGlE,QAAO;;;;;;AAOT,eAAsB,2BACpB,SACiC;CACjC,MAAM,oBAAoB,MAAM,QAAQ,IACtC,QAAQ,SAAS,IAAI,OAAO,YAAY;AACtC,MAAI,OAAO,QAAQ,YAAY,SAC7B,QAAO;GACL,GAAG;GACH,SAAS,MAAM,kBAAkB,QAAQ,QAAQ;GAClD;AAIH,MAAI,MAAM,QAAQ,QAAQ,QAAQ,CAChC,QAAO;GACL,GAAG;GACH,SAAS,MAAM,QAAQ,IACrB,QAAQ,QAAQ,IAAI,OAAO,SAAS;AAClC,QACE,OAAO,SAAS,YACb,KAAK,SAAS,UACd,KAAK,KAER,QAAO;KACL,GAAG;KACH,MAAM,MAAM,kBAAkB,KAAK,KAAK;KACzC;AAEH,WAAO;KACP,CACH;GACF;AAGH,SAAO;GACP,CACH;AAED,QAAO;EACL,GAAG;EACH,UAAU;EACX;;;;;ACpRH,SAAS,WAAW,MAAuB,OAAuB;CAChE,MAAM,SAAS,KAAK,UAAU,MAAM;CACpC,MAAM,OAAO,KAAK,UAAU,UAAU;CACtC,MAAM,SAAS,KAAK,WAAW,cAAc;CAC7C,MAAM,OAAO,KAAK,OAAO,KAAK,KAAK,KAAK,KAAK;CAC7C,MAAM,cAAc,KAAK,eAAe;AACxC,QAAO,GAAG,QAAQ,EAAE,KAAK,OAAO,KAAK,KAAK,GAAG,SAAS,KAAK,IAAI,KAAK,QAAQ,OAAO,YAAY;;AAGjG,eAAe,mBAAkC;CAC/C,MAAM,MAAM,MAAM,oBAAoB;AAEtC,KAAI,IAAI,WAAW,GAAG;AACpB,UAAQ,KAAK,mCAAmC;AAChD;;AAGF,SAAQ,KAAK,4BAA4B;AACzC,MAAK,MAAM,CAAC,GAAG,YAAY,IAAI,SAAS,CACtC,SAAQ,IAAI,WAAW,SAAS,EAAE,CAAC;AAErC,SAAQ,KAAK;;AAGf,eAAe,oBAAmC;CAChD,MAAM,OAAO,MAAM,QAAQ,OAAO,uCAAuC;EACvE,MAAM;EACN,SAAS;EACV,CAAC;AAEF,KAAI,OAAO,SAAS,UAAU;AAC5B,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,YAAY,MAAM,QAAQ,OAAO,eAAe;EACpD,MAAM;EACN,SAAS,CACP;GAAE,OAAO;GAAwB,OAAO;GAAU,EAClD;GAAE,OAAO;GAA8B,OAAO;GAAS,CACxD;EACF,CAAC;AAEF,KAAI,OAAO,cAAc,UAAU;AACjC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,UAAU,MAAM,QAAQ,OAAO,qBAAqB,EACxD,MAAM,QACP,CAAC;AAEF,KAAI,OAAO,YAAY,YAAY,CAAC,SAAS;AAC3C,UAAQ,KAAK,aAAa;AAC1B;;AAIF,KAAI,cAAc,QAChB,KAAI;AACF,MAAI,OAAO,QAAQ;SACb;AACN,UAAQ,MAAM,0BAA0B,UAAU;AAClD;;CAIJ,MAAM,cAAc,MAAM,QAAQ,OAChC,qDACA;EACE,MAAM;EACN,SAAS;EACV,CACF;AAED,KAAI,OAAO,gBAAgB,UAAU;AACnC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,OAAO,MAAM,eACjB,SACA,aACA,cAAc,SACd,QAAQ,OACT;AAED,SAAQ,QAAQ,eAAe,KAAK,QAAQ,KAAK,KAAK;;AAGxD,eAAe,0BAAyC;CACtD,MAAM,YAAY,MAAM,qBAAqB;AAE7C,KAAI,UAAU,WAAW,GAAG;AAC1B,UAAQ,KAAK,yBAAyB;AACtC;;CAGF,MAAM,UAAU,UAAU,KAAK,QAAM,OAAO;EAC1C,OAAO,WAAWC,QAAM,EAAE;EAC1B,OAAOA,OAAK;EACb,EAAE;CAEH,MAAM,WAAW,MAAM,QAAQ,OAAO,wBAAwB;EAC5D,MAAM;EACN;EACD,CAAC;AAEF,KAAI,OAAO,aAAa,UAAU;AAChC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,OAAO,UAAU,MAAM,MAAM,EAAE,OAAO,SAAS;AACrD,KAAI,CAAC,MAAM;AACT,UAAQ,MAAM,kBAAkB;AAChC;;AAGF,SAAQ,KAAK,mBAAmB,KAAK,QAAQ,KAAK,KAAK;AACvD,SAAQ,KAAK,uCAAuC;CAEpD,MAAM,OAAO,MAAM,QAAQ,OAAO,SAAS;EACzC,MAAM;EACN,SAAS,KAAK,QAAQ;EACvB,CAAC;AAEF,KAAI,OAAO,SAAS,UAAU;AAC5B,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,YAAY,MAAM,QAAQ,OAAO,eAAe;EACpD,MAAM;EACN,SAAS,CACP;GAAE,OAAO;GAAwB,OAAO;GAAU,EAClD;GAAE,OAAO;GAA8B,OAAO;GAAS,CACxD;EACD,SAAS,KAAK,UAAU,UAAU;EACnC,CAAC;AAEF,KAAI,OAAO,cAAc,UAAU;AACjC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,UAAU,MAAM,QAAQ,OAAO,qBAAqB;EACxD,MAAM;EACN,SAAS,KAAK;EACf,CAAC;AAEF,KAAI,OAAO,YAAY,YAAY,CAAC,SAAS;AAC3C,UAAQ,KAAK,aAAa;AAC1B;;AAIF,KAAI,cAAc,QAChB,KAAI;AACF,MAAI,OAAO,QAAQ;SACb;AACN,UAAQ,MAAM,0BAA0B,UAAU;AAClD;;CAIJ,MAAM,cAAc,MAAM,QAAQ,OAAO,qBAAqB;EAC5D,MAAM;EACN,SAAS,KAAK;EACf,CAAC;AAEF,KAAI,OAAO,gBAAgB,UAAU;AACnC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,UAAU,MAAM,kBAAkB,UAAU;EAChD,MAAM,QAAQ;EACd;EACA;EACA,SAAS,cAAc;EACxB,CAAC;AAEF,KAAI,QACF,SAAQ,QAAQ,iBAAiB,QAAQ,QAAQ,QAAQ,KAAK;KAE9D,SAAQ,MAAM,yBAAyB;;AAI3C,eAAe,4BAA2C;CACxD,MAAM,YAAY,MAAM,qBAAqB;AAE7C,KAAI,UAAU,WAAW,GAAG;AAC1B,UAAQ,KAAK,2BAA2B;AACxC;;CAGF,MAAM,UAAU,UAAU,KAAK,MAAM,OAAO;EAC1C,OAAO,WAAW,MAAM,EAAE;EAC1B,OAAO,KAAK;EACb,EAAE;CAEH,MAAM,WAAW,MAAM,QAAQ,OAAO,0BAA0B;EAC9D,MAAM;EACN;EACD,CAAC;AAEF,KAAI,OAAO,aAAa,UAAU;AAChC,UAAQ,KAAK,aAAa;AAC1B;;AAIF,KADgB,MAAM,kBAAkB,SAAS,CAE/C,SAAQ,QAAQ,gBAAgB;KAEhC,SAAQ,MAAM,yBAAyB;;AAI3C,eAAe,4BAA2C;CACxD,MAAM,YAAY,MAAM,qBAAqB;AAE7C,KAAI,UAAU,WAAW,GAAG;AAC1B,UAAQ,KAAK,2BAA2B;AACxC;;CAGF,MAAM,UAAU,UAAU,KAAK,QAAM,OAAO;EAC1C,OAAO,WAAWA,QAAM,EAAE;EAC1B,OAAOA,OAAK;EACb,EAAE;CAEH,MAAM,WAAW,MAAM,QAAQ,OAAO,0BAA0B;EAC9D,MAAM;EACN;EACD,CAAC;AAEF,KAAI,OAAO,aAAa,UAAU;AAChC,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,OAAO,MAAM,kBAAkB,SAAS;AAC9C,KAAI,KACF,SAAQ,QAAQ,QAAQ,KAAK,UAAU,YAAY,WAAW,GAAG;KAEjE,SAAQ,MAAM,yBAAyB;;AAI3C,eAAe,mBAAkC;CAC/C,MAAM,WAAW,MAAM,QAAQ,OAAO,oCAAoC,EACxE,MAAM,QACP,CAAC;AAEF,KAAI,OAAO,aAAa,YAAY,CAAC,UAAU;AAC7C,UAAQ,KAAK,aAAa;AAC1B;;CAGF,MAAM,SAAS,MAAM,kBAAkB,SAAS;AAEhD,SAAQ,KAAK,iBAAiB;AAC9B,SAAQ,IAAI,SAAS;AACrB,SAAQ,KAAK,0BAA0B;AACvC,SAAQ,IAAI,OAAO;AACnB,SAAQ,KAAK;;AAGf,eAAe,uBAAsC;AASnD,KARgB,MAAM,QAAQ,OAC5B,yDACA;EACE,MAAM;EACN,SAAS;EACV,CACF,EAEY;AACX,QAAM,uBAAuB;AAC7B,UAAQ,QAAQ,iCAAiC;OAEjD,SAAQ,KAAK,aAAa;;AAI9B,eAAe,WAA0B;AACvC,SAAQ,KAAK,+CAA+C;AAC5D,SAAQ,KAAK,gBAAgB,MAAM,yBAAyB,IAAI;CAEhE,IAAI,UAAU;AAEd,QAAO,SAAS;EACd,MAAM,SAAS,MAAM,QAAQ,OAAO,8BAA8B;GAChE,MAAM;GACN,SAAS;IACP;KAAE,OAAO;KAAqB,OAAO;KAAsB;IAC3D;KAAE,OAAO;KAAkB,OAAO;KAAqB;IACvD;KAAE,OAAO;KAAiB,OAAO;KAAsB;IACvD;KAAE,OAAO;KAAiB,OAAO;KAAwB;IACzD;KAAE,OAAO;KAAyB,OAAO;KAAwB;IACjE;KAAE,OAAO;KAAwB,OAAO;KAAsB;IAC9D;KAAE,OAAO;KAA6B,OAAO;KAAuB;IACpE;KAAE,OAAO;KAAW,OAAO;KAAsB;IAClD;GACF,CAAC;AAEF,MAAI,OAAO,WAAW,SACpB;AAGF,UAAQ,QAAR;GACE,KAAK;AACH,UAAM,kBAAkB;AACxB;GAEF,KAAK;AACH,UAAM,mBAAmB;AACzB;GAEF,KAAK;AACH,UAAM,yBAAyB;AAC/B;GAEF,KAAK;AACH,UAAM,2BAA2B;AACjC;GAEF,KAAK;AACH,UAAM,2BAA2B;AACjC;GAEF,KAAK;AACH,UAAM,kBAAkB;AACxB;GAEF,KAAK;AACH,UAAM,sBAAsB;AAC5B;GAEF,KAAK;AACH,cAAU;AACV;GAEF,QACE;;;AAKN,SAAQ,KAAK,cAAc;;AAG7B,MAAa,SAAS,cAAc;CAClC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,KAAK,YAAY;AACf,QAAM,aAAa;AACnB,QAAM,UAAU;;CAEnB,CAAC;;;;AC1WF,eAAe,oBAAqC;AAClD,KAAI;EACF,MAAM,kBAAkB,IAAI,IAAI,mBAAmB,OAAO,KAAK,IAAI,CAAC;AAMpE,SAHoB,KAAK,MAAM,MAAM,GAAG,SAAS,gBAAgB,CAAC,CAG/C;SACb;AACN,SAAO;;;AAIX,SAAS,iBAAiB;CACxB,MAAM,QAAQ,OAAO,QAAQ;AAE7B,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,SAAS,QAAQ,IAAI,UAAU,QAAQ,QAAQ,MAAM,EAAE;EACvD,UAAU,GAAG,UAAU;EACvB,MAAM,GAAG,MAAM;EAChB;;AAGH,eAAe,mBAAqC;AAClD,KAAI;AAEF,MAAI,EADU,MAAM,GAAG,KAAK,MAAM,kBAAkB,EACzC,QAAQ,CAAE,QAAO;AAG5B,UADgB,MAAM,GAAG,SAAS,MAAM,mBAAmB,OAAO,EACnD,MAAM,CAAC,SAAS;SACzB;AACN,SAAO;;;AAIX,eAAe,eAAmC;CAChD,MAAM,CAAC,SAAS,eAAe,MAAM,QAAQ,IAAI,CAC/C,mBAAmB,EACnB,kBAAkB,CACnB,CAAC;AAEF,QAAO;EACL;EACA,SAAS,gBAAgB;EACzB,OAAO;GACL,SAAS,MAAM;GACf,mBAAmB,MAAM;GAC1B;EACD;EACD;;AAGH,SAAS,oBAAoB,MAAuB;AAClD,SAAQ,KAAK;;WAEJ,KAAK,QAAQ;WACb,KAAK,QAAQ,KAAK,GAAG,KAAK,QAAQ,QAAQ,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,KAAK;;;aAGvF,KAAK,MAAM,QAAQ;uBACT,KAAK,MAAM,kBAAkB;;gBAEpC,KAAK,cAAc,QAAQ,OAAO;;AAGlD,SAAS,mBAAmB,MAAuB;AACjD,SAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;AAG5C,eAAsB,SAAS,SAAyC;CACtE,MAAM,YAAY,MAAM,cAAc;AAEtC,KAAI,QAAQ,KACV,oBAAmB,UAAU;KAE7B,qBAAoB,UAAU;;AAIlC,MAAa,QAAQ,cAAc;CACjC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,SAAS;EACT,aAAa;EACd,EACF;CACD,IAAI,EAAE,QAAQ;AACZ,SAAO,SAAS,EACd,MAAM,KAAK,MACZ,CAAC;;CAEL,CAAC;;;;AC1HF,SAAgB,mBAAyB;AACvC,KAAI,OAAO,QAAQ,YAAa;AAEhC,KAAI;EACF,MAAM,SAAS,IAAI,OAAO;EAC1B,MAAM,0BAAU,IAAI,KAAyB;AAmD7C,sBA7CmB;GACjB,SACE,SACA,SACA;AACA,QAAI;KACF,MAAM,SACJ,OAAO,QAAQ,WAAW,WACxB,IAAI,IAAI,QAAQ,OAAO,GACtB,QAAQ;KAIb,MAAM,MAHM,eAGI,OAAO,UAAU,CAAC;KAClC,MAAM,WAAW,OAAO,IAAI,SAAS,IAAI,MAAM;AAC/C,SAAI,CAAC,UAAU;AACb,cAAQ,MAAM,sBAAsB,OAAO,WAAW;AACtD,aAAQ,OAAiC,SAAS,SAAS,QAAQ;;KAErE,IAAI,QAAQ,QAAQ,IAAI,SAAS;AACjC,SAAI,CAAC,OAAO;AACV,cAAQ,IAAI,WAAW,SAAS;AAChC,cAAQ,IAAI,UAAU,MAAM;;KAE9B,IAAI,QAAQ;AACZ,SAAI;MACF,MAAM,IAAI,IAAI,IAAI,SAAS;AAC3B,cAAQ,GAAG,EAAE,SAAS,IAAI,EAAE;aACtB;AAGR,aAAQ,MAAM,qBAAqB,OAAO,SAAS,OAAO,QAAQ;AAClE,YAAQ,MAAgC,SAAS,SAAS,QAAQ;YAC5D;AACN,YAAQ,OAAiC,SAAS,SAAS,QAAQ;;;GAGvE,QAAQ;AACN,WAAO,OAAO,OAAO;;GAEvB,UAAU;AACR,WAAO,OAAO,SAAS;;GAE1B,CAEuD;AACxD,UAAQ,MAAM,mDAAmD;UAC1D,KAAK;AACZ,UAAQ,MAAM,wBAAwB,IAAI;;;;;;ACzD9C,SAAS,WAAsB;CAC7B,MAAM,EAAE,UAAU,MAAM,QAAQC;AAEhC,KAAI,aAAa,SAAS;AACxB,MAAI;GACF,MAAM,UAAU,oDAAoD,KAAK;AAGzE,OAFsB,SAAS,SAAS,EAAE,OAAO,QAAQ,CAAC,CAAC,UAAU,CAEnD,aAAa,CAAC,SAAS,iBAAiB,CACxD,QAAO;UAEH;AACN,UAAO;;AAGT,SAAO;QACF;EACL,MAAM,YAAY,IAAI;AACtB,MAAI,WAAW;AACb,OAAI,UAAU,SAAS,MAAM,CAAE,QAAO;AACtC,OAAI,UAAU,SAAS,OAAO,CAAE,QAAO;AACvC,OAAI,UAAU,SAAS,OAAO,CAAE,QAAO;;AAGzC,SAAO;;;;;;;;;;AAWX,SAAgB,kBACd,SACA,eAAuB,IACf;CACR,MAAM,QAAQ,UAAU;CACxB,MAAM,kBAAkB,OAAO,QAAQ,QAAQ,CAAC,QAC7C,GAAG,WAAW,UAAU,OAC1B;CAED,IAAIC;AAEJ,SAAQ,OAAR;EACE,KAAK;AACH,kBAAe,gBACZ,KAAK,CAAC,KAAK,WAAW,QAAQ,IAAI,KAAK,QAAQ,CAC/C,KAAK,KAAK;AACb;EAEF,KAAK;AACH,kBAAe,gBACZ,KAAK,CAAC,KAAK,WAAW,OAAO,IAAI,GAAG,QAAQ,CAC5C,KAAK,MAAM;AACd;EAEF,KAAK;AACH,kBAAe,gBACZ,KAAK,CAAC,KAAK,WAAW,WAAW,IAAI,GAAG,QAAQ,CAChD,KAAK,KAAK;AACb;EAEF,SAAS;GAEP,MAAM,cAAc,gBACjB,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,GAAG,QAAQ,CACxC,KAAK,IAAI;AACZ,kBAAe,gBAAgB,SAAS,IAAI,UAAU,gBAAgB;AACtE;;;AAIJ,KAAI,gBAAgB,aAElB,QAAO,GAAG,eADQ,UAAU,QAAQ,QAAQ,SACP;AAGvC,QAAO,gBAAgB;;;;;ACvEzB,MAAM,sBAAsB;AAG5B,MAAM,SAAS;CACb,OAAO;CACP,KAAK;CACL,MAAM;CACN,MAAM;CACN,OAAO;CACP,QAAQ;CACR,KAAK;CACL,SAAS;CACT,MAAM;CACN,OAAO;CACP,MAAM;CACP;;;;AAKD,SAAS,gBAAwB;AAC/B,yBAAO,IAAI,MAAM,EAAC,mBAAmB,SAAS;EAC5C,QAAQ;EACR,MAAM;EACN,QAAQ;EACR,QAAQ;EACT,CAAC;;;;;AAMJ,SAAS,eAAe,QAAwB;AAC9C,KAAI,UAAU,IAAK,QAAO,OAAO;AACjC,KAAI,UAAU,IAAK,QAAO,OAAO;AACjC,KAAI,UAAU,IAAK,QAAO,OAAO;AACjC,QAAO,OAAO;;;;;AAMhB,eAAe,cAAc,GAA2B;CACtD,MAAM,SAAS,EAAE,IAAI;CACrB,MAAM,MAAM,EAAE,IAAI;CAClB,MAAM,UAAU,OAAO,YAAY,EAAE,IAAI,IAAI,QAAQ,SAAS,CAAC;CAE/D,MAAMC,QAAkB,EAAE;AAC1B,OAAM,KAAK,GAAG,OAAO,UAAU,OAAO,KAAK,0BAA0B,OAAO,QAAQ;AACpF,OAAM,KAAK,GAAG,OAAO,OAAO,SAAS,OAAO,MAAM,GAAG,MAAM;AAC3D,OAAM,KAAK,GAAG,OAAO,IAAI,UAAU,OAAO,QAAQ;AAElD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE;EAElD,MAAM,eAAe,IAAI,aAAa,CAAC,SAAS,gBAAgB,GAC5D,GAAG,MAAM,MAAM,GAAG,GAAG,CAAC,OACtB;AACJ,QAAM,KAAK,KAAK,OAAO,OAAO,IAAI,GAAG,OAAO,MAAM,GAAG,eAAe;;AAItE,KAAI,WAAW,SAAS,WAAW,OACjC,KAAI;EAEF,MAAM,OAAO,MADS,EAAE,IAAI,IAAI,OAAO,CACN,MAAM;AACvC,MAAI,KAEF,KAAI;GACF,MAAM,SAAS,KAAK,MAAM,KAAK;GAC/B,MAAMC,YAAqC,EAAE;AAE7C,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,QAAQ,cAAc,QAAQ,SAChC,WAAU,OAAO,IAAI,MAAM,QAAQ,MAAM,GAAG,MAAM,SAAS,EAAE;OAE7D,WAAU,OAAO;AAIrB,SAAM,KAAK,GAAG,OAAO,IAAI,mBAAmB,OAAO,QAAQ;AAC3D,SAAM,KAAK,KAAK,KAAK,UAAU,WAAW,MAAM,EAAE,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,GAAG;UACxE;AAEN,SAAM,KAAK,GAAG,OAAO,IAAI,OAAO,OAAO,MAAM,IAAI,KAAK,OAAO,SAAS;;SAGpE;AACN,QAAM,KAAK,GAAG,OAAO,IAAI,OAAO,OAAO,MAAM,mBAAmB;;AAIpE,OAAM,KAAK,GAAG,OAAO,MAAM,IAAI,OAAO,GAAG,GAAG,OAAO,QAAQ;AAC3D,SAAQ,IAAI,MAAM,KAAK,KAAK,CAAC;;;;;AAM/B,SAAgB,kBACd,GACA,KACM;CACN,MAAM,WAAW,EAAE,IAAI,oBAAoB;AAC3C,KAAI,SACF,GAAE,IAAI,qBAAqB;EAAE,GAAG;EAAU,GAAG;EAAK,CAAC;;;;;AAOvD,eAAsB,cAAc,GAAY,MAA2B;AAEzE,KAAI,MAAM,MACR,OAAM,cAAc,EAAE;CAGxB,MAAM,YAAY,KAAK,KAAK;CAC5B,MAAM,SAAS,EAAE,IAAI;CACrB,MAAMC,SACJ,EAAE,IAAI,QACL,EAAE,IAAI,IAAI,IAAI,SAAS,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,KAAK;AAGrE,GAAE,IAAI,qBAAqB,EAAE,WAAW,CAAmB;AAE3D,OAAM,MAAM;CAGZ,MAAM,MAAM,EAAE,IAAI,oBAAoB;CACtC,MAAM,aAAa,KAAK,KAAK,GAAG,aAAa,KAAM,QAAQ,EAAE;CAC7D,MAAM,SAAS,EAAE,IAAI;CACrB,MAAM,cAAc,eAAe,OAAO;CAG1C,MAAMF,QAAkB,EAAE;AAG1B,OAAM,KAAK,GAAG,OAAO,MAAM,IAAI,OAAO,GAAG,GAAG,OAAO,QAAQ;CAG3D,MAAM,cAAc,GAAG,cAAc,SAAS,OAAO;CACrD,MAAM,cAAc,GAAG,OAAO,OAAO,SAAS,GAAG,OAAO;AACxD,OAAM,KACJ,GAAG,OAAO,OAAO,SAAS,OAAO,MAAM,GAAGE,OAAK,GAAG,YAAY,GAAG,cAClE;AAGD,KAAI,KAAK,YAAY,KAAK,OAAO;EAC/B,MAAM,gBACJ,IAAI,aAAa,iBAAiB,OAAO,OAAO,OAAO;AACzD,QAAM,KACJ,KAAK,OAAO,KAAK,WAAW,OAAO,MAAM,GAAG,gBAAgB,IAAI,WAAW,OAAO,MAAM,GAAG,OAAO,KAAK,IAAI,OAAO,MAAM,GAAG,OAAO,QAAQ,IAAI,QAAQ,OAAO,QAC9J;;AAIH,KAAI,KAAK,gBAAgB,UAAa,KAAK,iBAAiB,QAAW;EACrE,MAAMC,aAAuB,EAAE;AAC/B,MAAI,IAAI,gBAAgB,OACtB,YAAW,KACT,GAAG,OAAO,KAAK,QAAQ,OAAO,MAAM,GAAG,OAAO,SAAS,IAAI,YAAY,gBAAgB,GAAG,OAAO,QAClG;AAEH,MAAI,IAAI,iBAAiB,OACvB,YAAW,KACT,GAAG,OAAO,KAAK,SAAS,OAAO,MAAM,GAAG,OAAO,QAAQ,IAAI,aAAa,gBAAgB,GAAG,OAAO,QACnG;AAEH,QAAM,KAAK,KAAK,WAAW,KAAK,KAAK,GAAG;;AAI1C,OAAM,KAAK,KAAK,OAAO,MAAM,eAAe,GAAG,OAAO,QAAQ;AAG9D,SAAQ,IAAI,MAAM,KAAK,KAAK,CAAC;;;;;AC3L/B,MAAa,gBAAgB,YAAY;AAKvC,KAAI,CAJa,MAAM,QAAQ,OAAO,4BAA4B,EAChE,MAAM,WACP,CAAC,CAGA,OAAM,IAAI,UACR,oBACA,SAAS,KAAK,EAAE,SAAS,oBAAoB,EAAE,EAAE,QAAQ,KAAK,CAAC,CAChE;;;;;;;;;;;ACPL,SAAgB,mBAAmB,OAAuB;AAExD,QAAO,MAAM,QAAQ,eAAe,GAAG,IAAI,OAAO,GAAG,GAAG,GAAG,KAAK;;;;;ACDlE,eAAsB,eAAe,SAAc;AACjD,KAAIC,QAAM,qBAAqB,OAAW;CAE1C,MAAM,MAAM,KAAK,KAAK;AAEtB,KAAI,CAACA,QAAM,sBAAsB;AAC/B,UAAM,uBAAuB;AAC7B;;CAGF,MAAM,kBAAkB,MAAMA,QAAM,wBAAwB;AAE5D,KAAI,iBAAiBA,QAAM,kBAAkB;AAC3C,UAAM,uBAAuB;AAC7B;;CAGF,MAAM,kBAAkB,KAAK,KAAKA,QAAM,mBAAmB,eAAe;AAE1E,KAAI,CAACA,QAAM,eAAe;AACxB,UAAQ,KACN,qCAAqC,gBAAgB,gBACtD;AACD,QAAM,IAAI,UACR,uBACA,SAAS,KAAK,EAAE,SAAS,uBAAuB,EAAE,EAAE,QAAQ,KAAK,CAAC,CACnE;;CAGH,MAAM,aAAa,kBAAkB;AACrC,SAAQ,KACN,+BAA+B,gBAAgB,+BAChD;AACD,OAAM,MAAM,WAAW;AAEvB,SAAM,uBAAuB;AAC7B,SAAQ,KAAK,qDAAqD;;;;;ACjCpE,MAAM,eAAe;CACnB,kBAAkB,OAAO;CACzB,mBAAmB,OAAO;CAC1B,iBAAiB,OAAO;CACxB,iBAAiB,OAAO;CACxB,iBAAiB,OAAO;CACzB;AAUD,MAAM,gCAAgB,IAAI,KAAsB;;;;AAKhD,MAAM,4BACJ,WACA,SACA,cACW;CACX,IAAI,SAAS;AACb,MAAK,MAAM,YAAY,WAAW;AAChC,YAAU,UAAU;AACpB,YAAU,QAAQ,OAAO,KAAK,UAAU,SAAS,CAAC,CAAC;;AAErD,WAAU,UAAU;AACpB,QAAO;;;;;AAMT,MAAM,+BACJ,cACA,YACW;CACX,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,aACjB,KAAI,KAAK,SAAS,YAChB,WAAU,QAAQ,OAAO,KAAK,UAAU,IAAI,CAAC,SAAS;UAC7C,KAAK,KACd,WAAU,QAAQ,OAAO,KAAK,KAAK,CAAC;AAGxC,QAAO;;;;;AAMT,MAAM,0BACJ,SACA,SACA,cACW;CACX,MAAM,mBAAmB;CACzB,MAAM,gBAAgB;CACtB,IAAI,SAAS;AACb,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE;AAClD,MAAI,OAAO,UAAU,SACnB,WAAU,QAAQ,OAAO,MAAM,CAAC;AAElC,MAAI,QAAQ,OACV,WAAU;AAEZ,MAAI,QAAQ,aACV,WAAU,yBACR,OACA,SACA,UACD;AAEH,MAAI,QAAQ,aAAa,MAAM,QAAQ,MAAM,CAC3C,WAAU,4BACR,OACA,QACD;;AAGL,QAAO;;;;;AAMT,MAAM,mBACJ,UACA,SACA,cACW;AACX,KAAI,SAAS,WAAW,EACtB,QAAO;CAET,IAAI,YAAY;AAChB,MAAK,MAAM,WAAW,SACpB,cAAa,uBAAuB,SAAS,SAAS,UAAU;AAGlE,cAAa;AACb,QAAO;;;;;AAMT,MAAM,wBAAwB,OAAO,aAAuC;AAC1E,KAAI,cAAc,IAAI,SAAS,EAAE;EAC/B,MAAM,SAAS,cAAc,IAAI,SAAS;AAC1C,MAAI,OACF,QAAO;;CAIX,MAAM,oBAAoB;AAC1B,KAAI,EAAE,qBAAqB,eAAe;EACxC,MAAM,iBAAkB,MAAM,aAAa,YAAY;AACvD,gBAAc,IAAI,UAAU,eAAe;AAC3C,SAAO;;CAGT,MAAM,iBAAkB,MAAM,aAAa,oBAAoB;AAC/D,eAAc,IAAI,UAAU,eAAe;AAC3C,QAAO;;;;;AAMT,MAAa,yBAAyB,UAAyB;AAC7D,QAAO,MAAM,aAAa,aAAa;;;;;AAMzC,MAAM,qBAAqB,UAAiB;AAC1C,QAAO,MAAM,OAAO,mBAAmB,MAAM,OAAO,UAChD;EACE,UAAU;EACV,UAAU;EACV,SAAS;EACT,UAAU;EACV,UAAU;EACV,SAAS;EACV,GACD;EACE,UAAU;EACV,UAAU;EACV,SAAS;EACT,UAAU;EACV,UAAU;EACV,SAAS;EACV;;;;;AAMP,MAAM,4BACJ,KACA,MACA,YAIW;CACX,MAAM,EAAE,SAAS,cAAc;CAC/B,IAAI,SAAS,UAAU;AAGvB,KAAI,OAAO,SAAS,YAAY,SAAS,KACvC,QAAO;CAIT,MAAM,QAAQ;CAOd,MAAM,YAAY;CAClB,MAAM,YAAY,MAAM,QAAQ;CAChC,IAAI,YAAY,MAAM,eAAe;AAGrC,KAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,EAAE;AAC3C,YAAU,UAAU;AACpB,OAAK,MAAM,QAAQ,MAAM,MAAM;AAC7B,aAAU,UAAU;AACpB,aAAU,QAAQ,OAAO,OAAO,KAAK,CAAC,CAAC;;;AAK3C,KAAI,UAAU,SAAS,IAAI,CACzB,aAAY,UAAU,MAAM,GAAG,GAAG;CAIpC,MAAM,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG;AAC1C,WAAU,QAAQ,OAAO,KAAK,CAAC;CAG/B,MAAM,eAAe,IAAI,IAAI;EAAC;EAAQ;EAAe;EAAO,CAAC;AAC7D,MAAK,MAAM,gBAAgB,OAAO,KAAK,MAAM,CAC3C,KAAI,CAAC,aAAa,IAAI,aAAa,EAAE;EACnC,MAAM,gBAAgB,MAAM;EAC5B,MAAM,eACJ,OAAO,kBAAkB,WAAW,gBAClC,KAAK,UAAU,cAAc;AAEjC,YAAU,QAAQ,OAAO,GAAG,aAAa,GAAG,eAAe,CAAC;;AAIhE,QAAO;;;;;AAMT,MAAM,6BACJ,YACA,SACA,cACW;AACX,KAAI,CAAC,cAAc,OAAO,eAAe,SACvC,QAAO;CAGT,MAAM,SAAS;CACf,IAAI,SAAS;AAEb,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,QAAQ,cAAc;EACxB,MAAM,aAAa;AACnB,MAAI,OAAO,KAAK,WAAW,CAAC,SAAS,GAAG;AACtC,aAAU,UAAU;AACpB,QAAK,MAAM,WAAW,OAAO,KAAK,WAAW,CAC3C,WAAU,yBAAyB,SAAS,WAAW,UAAU;IAC/D;IACA;IACD,CAAC;;QAGD;EACL,MAAM,YACJ,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM;AAC3D,YAAU,QAAQ,OAAO,GAAG,IAAI,GAAG,YAAY,CAAC;;AAIpD,QAAO;;;;;AAMT,MAAM,uBACJ,MACA,SACA,cACW;CACX,IAAI,SAAS,UAAU;CACvB,MAAM,OAAO,KAAK;CAClB,MAAM,QAAQ,KAAK;CACnB,IAAI,QAAQ,KAAK,eAAe;AAChC,KAAI,MAAM,SAAS,IAAI,CACrB,SAAQ,MAAM,MAAM,GAAG,GAAG;CAE5B,MAAM,OAAO,QAAQ,MAAM;AAC3B,WAAU,QAAQ,OAAO,KAAK,CAAC;AAC/B,KACE,OAAO,KAAK,eAAe,YACxB,KAAK,eAAe,KAEvB,WAAU,0BAA0B,KAAK,YAAY,SAAS,UAAU;AAE1E,QAAO;;;;;AAMT,MAAa,qBACX,OACA,SACA,cACW;CACX,IAAI,iBAAiB;AACrB,MAAK,MAAM,QAAQ,MACjB,mBAAkB,oBAAoB,MAAM,SAAS,UAAU;AAEjE,mBAAkB,UAAU;AAC5B,QAAO;;;;;AAMT,MAAa,gBAAgB,OAC3B,SACA,UAC+C;CAE/C,MAAM,YAAY,sBAAsB,MAAM;CAG9C,MAAM,UAAU,MAAM,sBAAsB,UAAU;CAEtD,MAAM,qBAAqB,QAAQ;CACnC,MAAM,gBAAgB,mBAAmB,QACtC,QAAQ,IAAI,SAAS,YACvB;CACD,MAAM,iBAAiB,mBAAmB,QACvC,QAAQ,IAAI,SAAS,YACvB;CAED,MAAM,YAAY,kBAAkB,MAAM;CAC1C,IAAI,cAAc,gBAAgB,eAAe,SAAS,UAAU;AACpE,KAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS,EAC1C,gBAAe,kBAAkB,QAAQ,OAAO,SAAS,UAAU;CAErE,MAAM,eAAe,gBAAgB,gBAAgB,SAAS,UAAU;AAExE,QAAO;EACL,OAAO;EACP,QAAQ;EACT;;;;;AClVH,MAAa,wBAAwB,OACnC,YACG;AACH,KAAI,CAAC,MAAM,aAAc,OAAM,IAAI,MAAM,0BAA0B;CAEnE,MAAM,eAAe,QAAQ,SAAS,MACnC,MACC,OAAO,EAAE,YAAY,YAClB,EAAE,SAAS,MAAM,QAAMC,IAAE,SAAS,YAAY,CACpD;CAID,MAAM,cAAc,QAAQ,SAAS,MAAM,QACzC,CAAC,aAAa,OAAO,CAAC,SAAS,IAAI,KAAK,CACzC;CAGD,MAAMC,UAAkC;EACtC,GAAG,eAAe,OAAO,aAAa;EACtC,eAAe,cAAc,UAAU;EACxC;CAED,MAAM,WAAW,MAAM,eAAe,GAAG,eAAe,MAAM,CAAC,oBAAoB;EACjF,QAAQ;EACR;EACA,MAAM,KAAK,UAAU,QAAQ;EAC9B,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;AAChB,UAAQ,MAAM,qCAAqC,SAAS;AAC5D,QAAM,IAAI,UAAU,qCAAqC,SAAS;;AAGpE,KAAI,QAAQ,OACV,QAAO,OAAO,SAAS;AAGzB,QAAQ,MAAM,SAAS,MAAM;;;;;ACtB/B,eAAsBC,mBAAiB,GAAY;AACjD,OAAM,eAAe,MAAM;CAE3B,MAAM,aAAa,MAAM,EAAE,IAAI,MAA8B;CAI7D,IAAI,UAAU,MAAM,2BAA2B,WAAW;AAG1D,WAAU;EACR,GAAG;EACH,OAAO,mBAAmB,QAAQ,MAAM;EACzC;AAED,SAAQ,MAAM,oBAAoB,KAAK,UAAU,QAAQ,CAAC,MAAM,KAAK,CAAC;AAGtE,KAAI,mBAAmB,QAAQ,MAAM,EAAE;AACrC,MAAI,CAAC,MAAM,kBACT,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,EAAE,IAAI;AAG9D,oBAAkB,GAAG;GAAE,UAAU;GAAgB,OAAO,QAAQ;GAAO,CAAC;AAExE,MAAI,MAAM,cAAe,OAAM,eAAe;EAE9C,MAAMC,aAAW,MAAM,iCACrB,MAAM,mBACN,QACD;AAED,MAAI,eAAeA,WAAS,EAAE;AAC5B,WAAQ,MAAM,2BAA2B,KAAK,UAAUA,WAAS,CAAC;AAClE,OAAIA,WAAS,MACX,mBAAkB,GAAG;IACnB,aAAaA,WAAS,MAAM;IAC5B,cAAcA,WAAS,MAAM;IAC9B,CAAC;AAEJ,UAAO,EAAE,KAAKA,WAAS;;AAGzB,UAAQ,MAAM,qBAAqB;AACnC,SAAO,UAAU,GAAG,OAAO,WAAW;AACpC,cAAW,MAAM,SAASA,YAAU;AAClC,YAAQ,MAAM,oBAAoB,KAAK,UAAU,MAAM,CAAC;AAExD,QAAI,MAAM,QAAQ,MAAM,SAAS,UAAU;KACzC,MAAM,SAAS,KAAK,MAAM,MAAM,KAAK;AACrC,SAAI,OAAO,MACT,mBAAkB,GAAG;MACnB,aAAa,OAAO,MAAM;MAC1B,cAAc,OAAO,MAAM;MAC5B,CAAC;;AAGN,UAAM,OAAO,SAAS,MAAoB;;IAE5C;;AAGJ,mBAAkB,GAAG;EAAE,UAAU;EAAW,OAAO,QAAQ;EAAO,CAAC;CAGnE,MAAM,gBAAgB,MAAM,QAAQ,KAAK,MACtC,UAAU,MAAM,OAAO,QAAQ,MACjC;AAGD,KAAI;AACF,MAAI,eAAe;GACjB,MAAM,aAAa,MAAM,cAAc,SAAS,cAAc;AAC9D,qBAAkB,GAAG,EAAE,aAAa,WAAW,OAAO,CAAC;;UAElD,OAAO;AACd,UAAQ,KAAK,oCAAoC,MAAM;;AAGzD,KAAI,MAAM,cAAe,OAAM,eAAe;AAE9C,KAAI,UAAU,QAAQ,WAAW,EAAE;AACjC,YAAU;GACR,GAAG;GACH,YAAY,eAAe,aAAa,OAAO;GAChD;AACD,UAAQ,MAAM,sBAAsB,KAAK,UAAU,QAAQ,WAAW,CAAC;;CAGzE,MAAM,WAAW,MAAM,sBAAsB,QAAQ;AAErD,KAAI,eAAe,SAAS,EAAE;AAC5B,UAAQ,MAAM,2BAA2B,KAAK,UAAU,SAAS,CAAC;AAClE,MAAI,SAAS,MACX,mBAAkB,GAAG;GACnB,aAAa,SAAS,MAAM;GAC5B,cAAc,SAAS,MAAM;GAC9B,CAAC;AAEJ,SAAO,EAAE,KAAK,SAAS;;AAGzB,SAAQ,MAAM,qBAAqB;AACnC,QAAO,UAAU,GAAG,OAAO,WAAW;AACpC,aAAW,MAAM,SAAS,UAAU;AAClC,WAAQ,MAAM,oBAAoB,KAAK,UAAU,MAAM,CAAC;AAExD,OAAI,MAAM,QAAQ,MAAM,SAAS,UAAU;IACzC,MAAM,SAAS,KAAK,MAAM,MAAM,KAAK;AACrC,QAAI,OAAO,MACT,mBAAkB,GAAG;KACnB,aAAa,OAAO,MAAM;KAC1B,cAAc,OAAO,MAAM;KAC5B,CAAC;;AAGN,SAAM,OAAO,SAAS,MAAoB;;GAE5C;;AAGJ,MAAM,kBACJ,aACuC,OAAO,OAAO,UAAU,UAAU;;;;AC7I3E,MAAa,mBAAmB,IAAI,MAAM;AAE1C,iBAAiB,KAAK,KAAK,OAAO,MAAM;AACtC,KAAI;AACF,SAAO,MAAMC,mBAAiB,EAAE;UACzB,OAAO;AACd,SAAO,MAAM,aAAa,GAAG,MAAM;;EAErC;;;;ACTF,MAAa,mBAAmB,OAAO,YAA8B;AACnE,KAAI,CAAC,MAAM,aAAc,OAAM,IAAI,MAAM,0BAA0B;CAEnE,MAAM,WAAW,MAAM,eAAe,GAAG,eAAe,MAAM,CAAC,cAAc;EAC3E,QAAQ;EACR,SAAS,eAAe,MAAM;EAC9B,MAAM,KAAK,UAAU,QAAQ;EAC9B,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,+BAA+B,SAAS;AAE9E,QAAQ,MAAM,SAAS,MAAM;;;;;ACR/B,MAAa,kBAAkB,IAAI,MAAM;AAEzC,gBAAgB,KAAK,KAAK,OAAO,MAAM;AACrC,KAAI;EACF,MAAM,SAAS,MAAM,EAAE,IAAI,MAAwB;EACnD,MAAM,WAAW,MAAM,iBAAiB,OAAO;AAE/C,SAAO,EAAE,KAAK,SAAS;UAChB,OAAO;AACd,SAAO,MAAM,aAAa,GAAG,MAAM;;EAErC;;;;ACjBF,SAAgB,+BACd,cACkC;AAClC,KAAI,iBAAiB,KACnB,QAAO;AAQT,QANsB;EACpB,MAAM;EACN,QAAQ;EACR,YAAY;EACZ,gBAAgB;EACjB,CACoB;;;;;ACcvB,SAAgB,kBACd,SACwB;AACxB,QAAO;EACL,OAAO,mBAAmB,QAAQ,MAAM;EACxC,UAAU,mCACR,QAAQ,UACR,QAAQ,OACT;EACD,YAAY,QAAQ;EACpB,MAAM,QAAQ;EACd,QAAQ,QAAQ;EAChB,aAAa,QAAQ;EACrB,OAAO,QAAQ;EACf,MAAM,QAAQ,UAAU;EACxB,OAAO,gCAAgC,QAAQ,MAAM;EACrD,aAAa,qCAAqC,QAAQ,YAAY;EACvE;;AAGH,SAAS,mBAAmB,OAAuB;AAIjD,KAAI,MAAM,MAAM,yBAAyB,CACvC,QAAO;UACE,MAAM,MAAM,uBAAuB,CAC5C,QAAO;AAET,QAAO;;AAGT,SAAS,mCACP,mBACA,QACgB;CAChB,MAAM,iBAAiB,mBAAmB,OAAO;CAEjD,MAAM,gBAAgB,kBAAkB,SAAS,YAC/C,QAAQ,SAAS,SACf,kBAAkB,QAAQ,GAC1B,uBAAuB,QAAQ,CAClC;AAED,QAAO,CAAC,GAAG,gBAAgB,GAAG,cAAc;;AAG9C,SAAS,mBACP,QACgB;AAChB,KAAI,CAAC,OACH,QAAO,EAAE;AAGX,KAAI,OAAO,WAAW,SACpB,QAAO,CAAC;EAAE,MAAM;EAAU,SAAS;EAAQ,CAAC;KAG5C,QAAO,CAAC;EAAE,MAAM;EAAU,SADP,OAAO,KAAK,UAAU,MAAM,KAAK,CAAC,KAAK,OAAO;EAClB,CAAC;;AAIpD,SAAS,kBAAkB,SAA+C;CACxE,MAAMC,cAA8B,EAAE;AAEtC,KAAI,MAAM,QAAQ,QAAQ,QAAQ,EAAE;EAClC,MAAM,mBAAmB,QAAQ,QAAQ,QACtC,UACC,MAAM,SAAS,cAClB;EACD,MAAM,cAAc,QAAQ,QAAQ,QACjC,UAAU,MAAM,SAAS,cAC3B;AAGD,OAAK,MAAM,SAAS,iBAClB,aAAY,KAAK;GACf,MAAM;GACN,cAAc,MAAM;GACpB,SAAS,WAAW,MAAM,QAAQ;GACnC,CAAC;AAGJ,MAAI,YAAY,SAAS,EACvB,aAAY,KAAK;GACf,MAAM;GACN,SAAS,WAAW,YAAY;GACjC,CAAC;OAGJ,aAAY,KAAK;EACf,MAAM;EACN,SAAS,WAAW,QAAQ,QAAQ;EACrC,CAAC;AAGJ,QAAO;;AAGT,SAAS,uBACP,SACgB;AAChB,KAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,CACjC,QAAO,CACL;EACE,MAAM;EACN,SAAS,WAAW,QAAQ,QAAQ;EACrC,CACF;CAGH,MAAM,gBAAgB,QAAQ,QAAQ,QACnC,UAA0C,MAAM,SAAS,WAC3D;CAED,MAAM,aAAa,QAAQ,QAAQ,QAChC,UAAuC,MAAM,SAAS,OACxD;CAED,MAAM,iBAAiB,QAAQ,QAAQ,QACpC,UAA2C,MAAM,SAAS,WAC5D;CAGD,MAAM,iBAAiB,CACrB,GAAG,WAAW,KAAK,MAAM,EAAE,KAAK,EAChC,GAAG,eAAe,KAAK,MAAM,EAAE,SAAS,CACzC,CAAC,KAAK,OAAO;AAEd,QAAO,cAAc,SAAS,IAC1B,CACE;EACE,MAAM;EACN,SAAS,kBAAkB;EAC3B,YAAY,cAAc,KAAK,aAAa;GAC1C,IAAI,QAAQ;GACZ,MAAM;GACN,UAAU;IACR,MAAM,QAAQ;IACd,WAAW,KAAK,UAAU,QAAQ,MAAM;IACzC;GACF,EAAE;EACJ,CACF,GACD,CACE;EACE,MAAM;EACN,SAAS,WAAW,QAAQ,QAAQ;EACrC,CACF;;AAGP,SAAS,WACP,SAGoC;AACpC,KAAI,OAAO,YAAY,SACrB,QAAO;AAET,KAAI,CAAC,MAAM,QAAQ,QAAQ,CACzB,QAAO;AAIT,KAAI,CADa,QAAQ,MAAM,UAAU,MAAM,SAAS,QAAQ,CAE9D,QAAO,QACJ,QACE,UACC,MAAM,SAAS,UAAU,MAAM,SAAS,WAC3C,CACA,KAAK,UAAW,MAAM,SAAS,SAAS,MAAM,OAAO,MAAM,SAAU,CACrE,KAAK,OAAO;CAGjB,MAAMC,eAAmC,EAAE;AAC3C,MAAK,MAAM,SAAS,QAClB,SAAQ,MAAM,MAAd;EACE,KAAK;AACH,gBAAa,KAAK;IAAE,MAAM;IAAQ,MAAM,MAAM;IAAM,CAAC;AAErD;EAEF,KAAK;AACH,gBAAa,KAAK;IAAE,MAAM;IAAQ,MAAM,MAAM;IAAU,CAAC;AAEzD;EAEF,KAAK;AACH,gBAAa,KAAK;IAChB,MAAM;IACN,WAAW,EACT,KAAK,QAAQ,MAAM,OAAO,WAAW,UAAU,MAAM,OAAO,QAC7D;IACF,CAAC;AAEF;;AAKN,QAAO;;AAGT,SAAS,gCACP,gBACyB;AACzB,KAAI,CAAC,eACH;AAEF,QAAO,eAAe,KAAK,UAAU;EACnC,MAAM;EACN,UAAU;GACR,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,YAAY,KAAK;GAClB;EACF,EAAE;;AAGL,SAAS,qCACP,qBACuC;AACvC,KAAI,CAAC,oBACH;AAGF,SAAQ,oBAAoB,MAA5B;EACE,KAAK,OACH,QAAO;EAET,KAAK,MACH,QAAO;EAET,KAAK;AACH,OAAI,oBAAoB,KACtB,QAAO;IACL,MAAM;IACN,UAAU,EAAE,MAAM,oBAAoB,MAAM;IAC7C;AAEH;EAEF,KAAK,OACH,QAAO;EAET,QACE;;;AAON,SAAgB,qBACd,UACmB;CAEnB,MAAMC,gBAA2C,EAAE;CACnD,MAAMC,mBAAiD,EAAE;CACzD,IAAIC,aACF;AACF,cAAa,SAAS,QAAQ,IAAI,iBAAiB;AAGnD,MAAK,MAAM,UAAU,SAAS,SAAS;EACrC,MAAM,aAAa,uBAAuB,OAAO,QAAQ,QAAQ;EACjE,MAAM,gBAAgB,0BAA0B,OAAO,QAAQ,WAAW;AAE1E,gBAAc,KAAK,GAAG,WAAW;AACjC,mBAAiB,KAAK,GAAG,cAAc;AAGvC,MAAI,OAAO,kBAAkB,gBAAgB,eAAe,OAC1D,cAAa,OAAO;;AAMxB,QAAO;EACL,IAAI,SAAS;EACb,MAAM;EACN,MAAM;EACN,OAAO,SAAS;EAChB,SAAS,CAAC,GAAG,eAAe,GAAG,iBAAiB;EAChD,aAAa,+BAA+B,WAAW;EACvD,eAAe;EACf,OAAO;GACL,eACG,SAAS,OAAO,iBAAiB,MAC/B,SAAS,OAAO,uBAAuB,iBAAiB;GAC7D,eAAe,SAAS,OAAO,qBAAqB;GACpD,GAAI,SAAS,OAAO,uBAAuB,kBACrC,UAAa,EACjB,yBACE,SAAS,MAAM,sBAAsB,eACxC;GACF;EACF;;AAGH,SAAS,uBACP,gBAC2B;AAC3B,KAAI,OAAO,mBAAmB,SAC5B,QAAO,CAAC;EAAE,MAAM;EAAQ,MAAM;EAAgB,CAAC;AAGjD,KAAI,MAAM,QAAQ,eAAe,CAC/B,QAAO,eACJ,QAAQ,SAA2B,KAAK,SAAS,OAAO,CACxD,KAAK,UAAU;EAAE,MAAM;EAAQ,MAAM,KAAK;EAAM,EAAE;AAGvD,QAAO,EAAE;;AAGX,SAAS,0BACP,WAC8B;AAC9B,KAAI,CAAC,UACH,QAAO,EAAE;AAEX,QAAO,UAAU,KAAK,cAAc;EAClC,MAAM;EACN,IAAI,SAAS;EACb,MAAM,SAAS,SAAS;EACxB,OAAO,KAAK,MAAM,SAAS,SAAS,UAAU;EAC/C,EAAE;;;;;;;;ACvVL,eAAsB,kBAAkB,GAAY;AAClD,KAAI;EACF,MAAM,gBAAgB,EAAE,IAAI,OAAO,iBAAiB;EAEpD,MAAM,mBAAmB,MAAM,EAAE,IAAI,MAAgC;EAErE,MAAM,gBAAgB,kBAAkB,iBAAiB;EAGzD,MAAM,kBAAkB,mBAAmB,iBAAiB,MAAM;EAElE,MAAM,gBAAgB,MAAM,QAAQ,KAAK,MACtC,UAAU,MAAM,OAAO,gBACzB;AAED,MAAI,CAAC,eAAe;AAClB,WAAQ,KAAK,iDAAiD;AAC9D,UAAO,EAAE,KAAK,EACZ,cAAc,GACf,CAAC;;EAGJ,MAAM,aAAa,MAAM,cAAc,eAAe,cAAc;AAEpE,MAAI,iBAAiB,SAAS,iBAAiB,MAAM,SAAS,GAAG;GAC/D,IAAI,eAAe;AACnB,OAAI,eAAe,WAAW,cAAc,CAC1C,gBAAe,iBAAiB,MAAM,MAAM,SAC1C,KAAK,KAAK,WAAW,QAAQ,CAC9B;AAEH,OAAI,CAAC,cACH;QAAI,iBAAiB,MAAM,WAAW,SAAS,CAE7C,YAAW,QAAQ,WAAW,QAAQ;aAC7B,iBAAiB,MAAM,WAAW,OAAO,CAClD,YAAW,QAAQ,WAAW,QAAQ;;;EAK5C,IAAI,kBAAkB,WAAW,QAAQ,WAAW;AACpD,MAAI,iBAAiB,MAAM,WAAW,SAAS,CAC7C,mBAAkB,KAAK,MAAM,kBAAkB,KAAK;WAC3C,iBAAiB,MAAM,WAAW,OAAO,CAClD,mBAAkB,KAAK,MAAM,kBAAkB,KAAK;AAGtD,UAAQ,KAAK,gBAAgB,gBAAgB;AAE7C,SAAO,EAAE,KAAK,EACZ,cAAc,iBACf,CAAC;UACK,OAAO;AACd,UAAQ,MAAM,0BAA0B,MAAM;AAC9C,SAAO,EAAE,KAAK,EACZ,cAAc,GACf,CAAC;;;;;;AC5DN,SAAS,gBAAgB,SAAsC;AAC7D,KAAI,CAACC,QAAM,iBACT,QAAO;AAGT,QAAO,OAAO,OAAOA,QAAM,UAAU,CAAC,MACnC,OAAO,GAAG,wBAAwBA,QAAM,kBAC1C;;AAIH,SAAgB,gCACd,OACA,SACiC;CACjC,MAAMC,WAA0C,EAAE;AAElD,KAAI,MAAM,QAAQ,WAAW,EAC3B,QAAOC;CAGT,MAAM,SAAS,MAAM,QAAQ;CAC7B,MAAM,EAAE,UAAU;AAElB,KAAI,CAACF,QAAM,kBAAkB;AAI3B,WAAO,KAAK;GACV,MAAM;GACN,SAAS;IACP,IAAI,MAAM;IACV,MAAM;IACN,MAAM;IACN,SAAS,EAAE;IACX,OAAO,MAAM;IACb,aAAa;IACb,eAAe;IAGhB;GACF,CAAC;AACF,UAAM,mBAAmB;;AAG3B,KAAI,MAAM,SAAS;AACjB,MAAI,gBAAgBA,QAAM,EAAE;AAE1B,YAAO,KAAK;IACV,MAAM;IACN,OAAOA,QAAM;IACd,CAAC;AACF,WAAM;AACN,WAAM,mBAAmB;;AAG3B,MAAI,CAACA,QAAM,kBAAkB;AAC3B,YAAO,KAAK;IACV,MAAM;IACN,OAAOA,QAAM;IACb,eAAe;KACb,MAAM;KACN,MAAM;KACP;IACF,CAAC;AACF,WAAM,mBAAmB;;AAG3B,WAAO,KAAK;GACV,MAAM;GACN,OAAOA,QAAM;GACb,OAAO;IACL,MAAM;IACN,MAAM,MAAM;IACb;GACF,CAAC;;AAGJ,KAAI,MAAM,WACR,MAAK,MAAM,YAAY,MAAM,YAAY;AACvC,MAAI,SAAS,MAAM,SAAS,UAAU,MAAM;AAE1C,OAAIA,QAAM,kBAAkB;AAE1B,aAAO,KAAK;KACV,MAAM;KACN,OAAOA,QAAM;KACd,CAAC;AACF,YAAM;AACN,YAAM,mBAAmB;;GAG3B,MAAM,sBAAsBA,QAAM;AAClC,WAAM,UAAU,SAAS,SAAS;IAChC,IAAI,SAAS;IACb,MAAM,SAAS,SAAS;IACxB;IACD;AAED,YAAO,KAAK;IACV,MAAM;IACN,OAAO;IACP,eAAe;KACb,MAAM;KACN,IAAI,SAAS;KACb,MAAM,SAAS,SAAS;KACxB,OAAO,EAAE;KACV;IACF,CAAC;AACF,WAAM,mBAAmB;;AAG3B,MAAI,SAAS,UAAU,WAAW;GAChC,MAAM,eAAeA,QAAM,UAAU,SAAS;AAG9C,OAAI,aACF,UAAO,KAAK;IACV,MAAM;IACN,OAAO,aAAa;IACpB,OAAO;KACL,MAAM;KACN,cAAc,SAAS,SAAS;KACjC;IACF,CAAC;;;AAMV,KAAI,OAAO,eAAe;AACxB,MAAIA,QAAM,kBAAkB;AAC1B,YAAO,KAAK;IACV,MAAM;IACN,OAAOA,QAAM;IACd,CAAC;AACF,WAAM,mBAAmB;;EAI3B,MAAM,cAAc,MAAM,OAAO,iBAAiB;EAClD,MAAM,eAAe,MAAM,OAAO,qBAAqB;EACvD,MAAM,eAAe,MAAM,OAAO,uBAAuB,iBAAiB;AAE1E,WAAO,KACL;GACE,MAAM;GACN,OAAO;IACL,aAAa,+BAA+B,OAAO,cAAc;IACjE,eAAe;IAChB;GACD,OAAO;IACL,cAAc;IACd,eAAe;IACf,6BAA6B;IAC7B,yBAAyB;IAC1B;GACF,EACD,EACE,MAAM,gBACP,CACF;;AAGH,QAAOE;;;;;AC9IT,eAAsB,iBAAiB,GAAY;AACjD,OAAM,eAAe,MAAM;CAE3B,MAAM,mBAAmB,MAAM,EAAE,IAAI,MAAgC;AACrE,SAAQ,MAAM,8BAA8B,KAAK,UAAU,iBAAiB,CAAC;CAE7E,MAAM,oBAAoB,kBAAkB,iBAAiB;CAG7D,IAAI,gBAAgB,MAAM,2BAA2B,kBAAkB;AAGvE,iBAAgB;EACd,GAAG;EACH,OAAO,mBAAmB,cAAc,MAAM;EAC/C;AAED,SAAQ,MACN,sCACA,KAAK,UAAU,cAAc,CAC9B;AAED,KAAI,MAAM,cACR,OAAM,eAAe;CAIvB,MAAM,eAAe,mBAAmB,cAAc,MAAM;AAE5D,KAAI,cAAc;AAChB,MAAI,CAAC,MAAM,kBACT,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,EAAE,IAAI;AAG9D,oBAAkB,GAAG;GACnB,UAAU;GACV,OAAO,cAAc;GACtB,CAAC;OAEF,mBAAkB,GAAG;EAAE,UAAU;EAAW,OAAO,cAAc;EAAO,CAAC;AAI3E,KAAI,iBAAiB,QAAQ;EAC3B,MAAM,gBAAgB;GACpB,GAAG;GACH,QAAQ;GACR,gBAAgB,EAAE,eAAe,MAAM;GACxC;EAUD,MAAM,cARW,eACb,MAAM,iCACJ,MAAM,mBACN,cACD,GACD,MAAM,sBAAsB,cAAc;AAK9C,SAAO,UAAU,GAAG,OAAO,WAAW;GACpC,MAAMC,cAAoC;IACxC,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,WAAW,EAAE;IACd;AAED,cAAW,MAAM,SAAS,aAAa;AACrC,QAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,SAChC;AAGF,QAAI;KACF,MAAM,QAAQ,KAAK,MAAM,MAAM,KAAK;AACpC,aAAQ,MAAM,iBAAiB,KAAK,UAAU,MAAM,CAAC;KAErD,MAAM,kBAAkB,gCACtB,OACA,YACD;AAED,UAAK,MAAM,kBAAkB,iBAAiB;AAC5C,cAAQ,MAAM,oBAAoB,KAAK,UAAU,eAAe,CAAC;AACjE,YAAM,OAAO,SAAS;OACpB,OAAO,eAAe;OACtB,MAAM,KAAK,UAAU,eAAe;OACrC,CAAC;;AAIJ,SAAI,MAAM,MACR,mBAAkB,GAAG;MACnB,aAAa,MAAM,MAAM;MACzB,cAAc,MAAM,MAAM;MAC3B,CAAC;aAEG,OAAO;AACd,aAAQ,MAAM,0BAA0B,OAAO,MAAM,KAAK;;;IAG9D;;CAIJ,MAAM,mBAAmB;EAAE,GAAG;EAAe,QAAQ;EAAO;CAE5D,MAAM,WAAW,eACX,MAAM,iCACN,MAAM,mBACN,iBACD,GACC,MAAM,sBAAsB,iBAAiB;AAEnD,SAAQ,MAAM,2BAA2B,KAAK,UAAU,SAAS,CAAC,MAAM,KAAK,CAAC;AAG9E,KAAI,SAAS,MACX,mBAAkB,GAAG;EACnB,aAAa,SAAS,MAAM;EAC5B,cAAc,SAAS,MAAM;EAC9B,CAAC;CAIJ,MAAM,oBAAoB,qBAAqB,SAAS;AACxD,SAAQ,MACN,kCACA,KAAK,UAAU,kBAAkB,CAClC;AACD,QAAO,EAAE,KAAK,kBAAkB;;;;;AC5JlC,MAAa,gBAAgB,IAAI,MAAM;AAEvC,cAAc,KAAK,KAAK,OAAO,MAAM;AACnC,KAAI;AACF,SAAO,MAAM,iBAAiB,EAAE;UACzB,OAAO;AACd,SAAO,MAAM,aAAa,GAAG,MAAM;;EAErC;AAEF,cAAc,KAAK,iBAAiB,OAAO,MAAM;AAC/C,KAAI;AACF,SAAO,MAAM,kBAAkB,EAAE;UAC1B,OAAO;AACd,SAAO,MAAM,aAAa,GAAG,MAAM;;EAErC;;;;ACjBF,MAAa,cAAc,IAAI,MAAM;AAErC,YAAY,IAAI,KAAK,OAAO,MAAM;AAChC,KAAI;AACF,MAAI,CAAC,MAAM,OAET,OAAM,aAAa;EAIrB,MAAM,gBACJ,MAAM,QAAQ,KAAK,KAAK,WAAW;GACjC,IAAI,MAAM;GACV,QAAQ;GACR,MAAM;GACN,SAAS;GACT,6BAAY,IAAI,KAAK,EAAE,EAAC,aAAa;GACrC,UAAU,MAAM;GAChB,cAAc,MAAM;GACrB,EAAE,IAAI,EAAE;EAGX,MAAM,cACJ,MAAM,wBAAwB,KAAK,gBAAgB;GACjD,IAAI,WAAW;GACf,QAAQ;GACR,MAAM;GACN,SAAS,WAAW;GACpB,6BAAY,IAAI,KAAK,WAAW,UAAU,IAAK,EAAC,aAAa;GAC7D,UAAU,WAAW;GACrB,cAAc,GAAG,WAAW,eAAe,IAAI,WAAW,MAAM;GACjE,EAAE,IAAI,EAAE;EAEX,MAAM,YAAY,CAAC,GAAG,eAAe,GAAG,YAAY;AAEpD,SAAO,EAAE,KAAK;GACZ,QAAQ;GACR,MAAM;GACN,UAAU;GACX,CAAC;UACK,OAAO;AACd,SAAO,MAAM,aAAa,GAAG,MAAM;;EAErC;;;;ACrCF,MAAa,oBAAoB,IAAI,MAAM;AAG3C,kBAAkB,IAAI,KAAK,OAAO,MAAM;AACtC,QAAO,EAAE,KAAK;EACZ,KAAK,MAAM,oBAAoB;EAC/B,MAAM,MAAM,qBAAqB;EAClC,CAAC;EACF;AAGF,kBAAkB,KAAK,KAAK,OAAO,MAAM;CACvC,MAAM,OAAO,MAAM,EAAE,IAAI,MAKrB;AAEJ,KAAI,CAAC,KAAK,QACR,QAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,EAAE,IAAI;CAGtD,MAAM,OAAO,MAAM,eACjB,KAAK,SACL,KAAK,eAAe,IACpB,KAAK,WAAW,OAChB,KAAK,KACN;AAED,QAAO,EAAE,KAAK,MAAM,IAAI;EACxB;AAGF,kBAAkB,OAAO,QAAQ,OAAO,MAAM;CAC5C,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;AAG5B,KAAI,CAFY,MAAM,kBAAkB,GAAG,CAGzC,QAAO,EAAE,KAAK,EAAE,OAAO,6CAA6C,EAAE,IAAI;AAG5E,QAAO,EAAE,KAAK,EAAE,SAAS,MAAM,CAAC;EAChC;AAGF,kBAAkB,MAAM,QAAQ,OAAO,MAAM;CAC3C,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;CAC5B,MAAM,OAAO,MAAM,EAAE,IAAI,MAMrB;CAEJ,MAAM,OAAO,MAAM,kBAAkB,IAAI,KAAK;AAE9C,KAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,6CAA6C,EAAE,IAAI;AAG5E,QAAO,EAAE,KAAK,KAAK;EACnB;AAGF,kBAAkB,MAAM,eAAe,OAAO,MAAM;CAClD,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK;CAC5B,MAAM,OAAO,MAAM,kBAAkB,GAAG;AAExC,KAAI,CAAC,KACH,QAAO,EAAE,KAAK,EAAE,OAAO,6CAA6C,EAAE,IAAI;AAG5E,QAAO,EAAE,KAAK,KAAK;EACnB;AAGF,kBAAkB,OAAO,KAAK,OAAO,MAAM;AACzC,OAAM,uBAAuB;AAC7B,QAAO,EAAE,KAAK,EAAE,SAAS,MAAM,CAAC;EAChC;;;;ACzFF,MAAa,aAAa,IAAI,MAAM;AAEpC,WAAW,IAAI,MAAM,MAAM;AACzB,KAAI;AACF,SAAO,EAAE,KAAK,EACZ,OAAO,MAAM,cACd,CAAC;UACK,OAAO;AACd,UAAQ,MAAM,yBAAyB,MAAM;AAC7C,SAAO,EAAE,KAAK;GAAE,OAAO;GAAyB,OAAO;GAAM,EAAE,IAAI;;EAErE;;;;ACXF,MAAa,aAAa,IAAI,MAAM;AAEpC,WAAW,IAAI,KAAK,OAAO,MAAM;AAC/B,KAAI;EACF,MAAM,QAAQ,MAAM,iBAAiB;AACrC,SAAO,EAAE,KAAK,MAAM;UACb,OAAO;AACd,UAAQ,MAAM,iCAAiC,MAAM;AACrD,SAAO,EAAE,KAAK,EAAE,OAAO,iCAAiC,EAAE,IAAI;;EAEhE;;;;ACFF,MAAa,SAAS,IAAI,MAAM;AAEhC,OAAO,IAAI,cAAc;AACzB,OAAO,IAAI,MAAM,CAAC;AAElB,OAAO,IAAI,MAAM,MAAM,EAAE,KAAK,iBAAiB,CAAC;AAEhD,OAAO,MAAM,qBAAqB,iBAAiB;AACnD,OAAO,MAAM,WAAW,YAAY;AACpC,OAAO,MAAM,eAAe,gBAAgB;AAC5C,OAAO,MAAM,UAAU,WAAW;AAClC,OAAO,MAAM,UAAU,WAAW;AAClC,OAAO,MAAM,iBAAiB,kBAAkB;AAGhD,OAAO,MAAM,wBAAwB,iBAAiB;AACtD,OAAO,MAAM,cAAc,YAAY;AACvC,OAAO,MAAM,kBAAkB,gBAAgB;AAG/C,OAAO,MAAM,gBAAgB,cAAc;;;;ACD3C,eAAsB,UAAU,SAA0C;AACxE,KAAI,QAAQ,UAAU;AAEpB,UAAQ,IAAI,+BAA+B;AAC3C,UAAQ,KAAK,wDAAwD;;AAGvE,KAAI,QAAQ,SACV,mBAAkB;AAGpB,KAAI,QAAQ,SAAS;AACnB,UAAQ,QAAQ;AAChB,UAAQ,KAAK,0BAA0B;;AAGzC,OAAM,cAAc,QAAQ;AAC5B,KAAI,QAAQ,gBAAgB,aAC1B,SAAQ,KAAK,SAAS,QAAQ,YAAY,sBAAsB;AAGlE,OAAM,gBAAgB,QAAQ;AAC9B,OAAM,mBAAmB,QAAQ;AACjC,OAAM,gBAAgB,QAAQ;AAC9B,OAAM,YAAY,QAAQ;AAC1B,OAAM,QAAQ,QAAQ;AAEtB,KAAI,QAAQ,MACV,SAAQ,KAAK,wDAAwD;AAGvE,OAAM,aAAa;AACnB,OAAM,oBAAoB;AAE1B,KAAI,QAAQ,aAAa;AACvB,QAAM,cAAc,QAAQ;AAC5B,UAAQ,KAAK,8BAA8B;OAE3C,OAAM,kBAAkB;AAG1B,OAAM,mBAAmB;AACzB,OAAM,aAAa;AAGnB,OAAM,kBAAkB;CAGxB,MAAM,kBAAkB,MAAM,QAAQ,KAAK,KAAK,UAAU,MAAM,GAAG,IAAI,EAAE;CACzE,MAAM,gBACJ,MAAM,wBAAwB,KAAK,eAAe,WAAW,GAAG,IAAI,EAAE;CACxE,MAAM,cAAc,CAAC,GAAG,iBAAiB,GAAG,cAAc;AAE1D,SAAQ,KACN,uBAAuB,YAAY,KAAK,OAAO,KAAK,KAAK,CAAC,KAAK,KAAK,GACrE;CAED,MAAM,YAAY,oBAAoB,QAAQ;AAE9C,KAAI,QAAQ,YAAY;AACtB,YAAU,MAAM,QAAQ,iCAAiC;EAEzD,MAAM,gBAAgB,MAAM,QAAQ,OAClC,0CACA;GACE,MAAM;GACN,SAAS;GACV,CACF;EAED,MAAM,qBAAqB,MAAM,QAAQ,OACvC,gDACA;GACE,MAAM;GACN,SAAS;GACV,CACF;EAED,MAAM,UAAU,kBACd;GACE,oBAAoB;GACpB,sBAAsB;GACtB,iBAAiB;GACjB,gCAAgC;GAChC,4BAA4B;GAC5B,+BAA+B;GAC/B,mCAAmC;GACnC,0CAA0C;GAC3C,EACD,SACD;AAED,MAAI;AACF,aAAU,UAAU,QAAQ;AAC5B,WAAQ,QAAQ,2CAA2C;UACrD;AACN,WAAQ,KACN,gEACD;AACD,WAAQ,IAAI,QAAQ;;;AAIxB,SAAQ,IACN,oEAAoE,UAAU,QAC/E;AAED,OAAM;EACJ,OAAO,OAAO;EACd,MAAM,QAAQ;EACf,CAAC;;AAGJ,MAAa,QAAQ,cAAc;CACjC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM;EACJ,MAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,SAAS;GACP,OAAO;GACP,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,gBAAgB;GACd,OAAO;GACP,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,QAAQ;GACN,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,cAAc;GACZ,OAAO;GACP,MAAM;GACN,aAAa;GACd;EACD,MAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,aACE;GACH;EACD,gBAAgB;GACd,OAAO;GACP,MAAM;GACN,aACE;GACH;EACD,eAAe;GACb,OAAO;GACP,MAAM;GACN,SAAS;GACT,aACE;GACH;EACD,cAAc;GACZ,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,aAAa;GACX,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACD,UAAU;GACR,MAAM;GACN,SAAS;GACT,aACE;GACH;EACD,OAAO;GACL,OAAO;GACP,MAAM;GACN,SAAS;GACT,aAAa;GACd;EACF;CACD,IAAI,EAAE,QAAQ;EACZ,MAAM,eAAe,KAAK;EAC1B,MAAM,YAEJ,iBAAiB,SAAY,SAAY,OAAO,SAAS,cAAc,GAAG;AAE5E,SAAO,UAAU;GACf,MAAM,OAAO,SAAS,KAAK,MAAM,GAAG;GACpC,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,QAAQ,KAAK;GACb;GACA,eAAe,KAAK;GACpB,aAAa,KAAK;GAClB,YAAY,KAAK;GACjB,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,UAAU,KAAK;GACf,OAAO,KAAK;GACb,CAAC;;CAEL,CAAC;;;;ACxOF,MAAM,OAAO,cAAc;CACzB,MAAM;EACJ,MAAM;EACN,aACE;EACH;CACD,aAAa;EAAE;EAAM;EAAO,eAAe;EAAY;EAAO;EAAQ;CACvE,CAAC;AAEF,MAAM,QAAQ,KAAK"}
1
+ {"version":3,"file":"main.js","names":["state: State","state","headers: Record<string, string>","errorJson: unknown","config","config: AzureOpenAIConfig","lastError: Error | undefined","lastResponse: Response | undefined","config","config","errorDetails: string","parsed: unknown","config","token","SYSTEM_REPLACEMENTS: Array<ReplacementRule>","userReplacements: Array<ReplacementRule>","rule: ReplacementRule","result","appliedRules: string[]","rule","process","commandBlock: string","lines: string[]","sanitized: Record<string, unknown>","path","tokenParts: string[]","state","x","headers: Record<string, string>","handleCompletion","response","handleCompletion","newMessages: Array<Message>","contentParts: Array<ContentPart>","allTextBlocks: Array<AnthropicTextBlock>","allToolUseBlocks: Array<AnthropicToolUseBlock>","stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null","state","events: Array<AnthropicStreamEventData>","events","chunks: Array<ChatCompletionChunk>","usage: UsageData | null","streamState: AnthropicStreamState"],"sources":["../src/lib/paths.ts","../src/lib/state.ts","../src/lib/api-config.ts","../src/lib/error.ts","../src/services/github/get-copilot-token.ts","../src/services/github/get-device-code.ts","../src/services/github/get-user.ts","../src/services/azure-openai/config.ts","../src/lib/retry-fetch.ts","../src/services/azure-openai/create-chat-completions.ts","../src/services/azure-openai/get-models.ts","../src/services/copilot/get-models.ts","../src/services/get-vscode-version.ts","../src/lib/utils.ts","../src/services/github/poll-access-token.ts","../src/lib/token.ts","../src/auth.ts","../src/services/github/get-copilot-usage.ts","../src/check-usage.ts","../src/lib/auto-replace.ts","../src/config.ts","../src/debug.ts","../src/lib/proxy.ts","../src/lib/shell.ts","../src/lib/request-logger.ts","../src/lib/approval.ts","../src/lib/model-resolver.ts","../src/lib/rate-limit.ts","../src/lib/tokenizer.ts","../src/services/copilot/create-chat-completions.ts","../src/routes/chat-completions/handler.ts","../src/routes/chat-completions/route.ts","../src/services/copilot/create-embeddings.ts","../src/routes/embeddings/route.ts","../src/routes/messages/utils.ts","../src/routes/messages/non-stream-translation.ts","../src/routes/messages/count-tokens-handler.ts","../src/routes/messages/stream-translation.ts","../src/routes/messages/handler.ts","../src/routes/messages/route.ts","../src/routes/models/route.ts","../src/routes/replacements/route.ts","../src/routes/token/route.ts","../src/routes/usage/route.ts","../src/server.ts","../src/start.ts","../src/main.ts"],"sourcesContent":["import fs from \"node:fs/promises\"\r\nimport os from \"node:os\"\r\nimport path from \"node:path\"\r\n\r\nconst APP_DIR = path.join(os.homedir(), \".local\", \"share\", \"copilot-api\")\r\n\r\nconst GITHUB_TOKEN_PATH = path.join(APP_DIR, \"github_token\")\r\nconst AZURE_OPENAI_CONFIG_PATH = path.join(APP_DIR, \"azure_openai_config\")\r\nconst REPLACEMENTS_CONFIG_PATH = path.join(APP_DIR, \"replacements.json\")\r\n\r\nexport const PATHS = {\r\n APP_DIR,\r\n GITHUB_TOKEN_PATH,\r\n AZURE_OPENAI_CONFIG_PATH,\r\n REPLACEMENTS_CONFIG_PATH,\r\n}\r\n\r\nexport async function ensurePaths(): Promise<void> {\r\n await fs.mkdir(PATHS.APP_DIR, { recursive: true })\r\n await ensureFile(PATHS.GITHUB_TOKEN_PATH)\r\n await ensureFile(PATHS.AZURE_OPENAI_CONFIG_PATH)\r\n}\r\n\r\nasync function ensureFile(filePath: string): Promise<void> {\r\n try {\r\n await fs.access(filePath, fs.constants.W_OK)\r\n } catch {\r\n await fs.writeFile(filePath, \"\")\r\n await fs.chmod(filePath, 0o600)\r\n }\r\n}\r\n","import type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n} from \"~/services/azure-openai/types\"\r\nimport type { ModelsResponse } from \"~/services/copilot/get-models\"\r\n\r\nexport interface State {\r\n githubToken?: string\r\n copilotToken?: string\r\n\r\n accountType: string\r\n models?: ModelsResponse\r\n vsCodeVersion?: string\r\n\r\n manualApprove: boolean\r\n rateLimitWait: boolean\r\n showToken: boolean\r\n debug: boolean\r\n\r\n // Rate limiting configuration\r\n rateLimitSeconds?: number\r\n lastRequestTimestamp?: number\r\n\r\n // Azure OpenAI configuration\r\n azureOpenAIConfig?: AzureOpenAIConfig\r\n azureOpenAIDeployments?: Array<AzureOpenAIDeploymentInfo>\r\n}\r\n\r\nexport const state: State = {\r\n accountType: \"individual\",\r\n manualApprove: false,\r\n rateLimitWait: false,\r\n showToken: false,\r\n debug: false,\r\n}\r\n","import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\nconst API_VERSION = \"2025-04-01\"\n\nexport const copilotBaseUrl = (state: State) =>\n state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nexport class HTTPError extends Error {\n response: Response\n requestPayload?: unknown\n\n constructor(message: string, response: Response, requestPayload?: unknown) {\n super(message)\n this.response = response\n this.requestPayload = requestPayload\n }\n}\n\ninterface ContentFilterError {\n error: {\n code: string\n innererror?: {\n code: string\n content_filter_result?: unknown\n }\n }\n}\n\nfunction isContentFilterError(obj: unknown): obj is ContentFilterError {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"error\" in obj &&\n typeof (obj as ContentFilterError).error === \"object\" &&\n (obj as ContentFilterError).error?.code === \"content_filter\"\n )\n}\n\nexport async function forwardError(c: Context, error: unknown) {\n consola.error(\"Error occurred:\", error)\n\n if (error instanceof HTTPError) {\n const errorText = await error.response.text()\n let errorJson: unknown\n try {\n errorJson = JSON.parse(errorText)\n } catch {\n errorJson = errorText\n }\n consola.error(\"HTTP error:\", errorJson)\n\n // Check for content filter error and log full details\n if (isContentFilterError(errorJson)) {\n consola.box(\"CONTENT FILTER TRIGGERED\")\n consola.error(\"Full error response:\")\n console.log(JSON.stringify(errorJson, null, 2))\n\n if (error.requestPayload) {\n consola.error(\"Request payload that triggered the filter:\")\n console.log(JSON.stringify(error.requestPayload, null, 2))\n }\n }\n\n return c.json(\n {\n error: {\n message: errorText,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n return c.json(\n {\n error: {\n message: (error as Error).message,\n type: \"error\",\n },\n },\n 500,\n )\n}\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotToken = async () => {\n const response = await fetch(\n `${GITHUB_API_BASE_URL}/copilot_internal/v2/token`,\n {\n headers: githubHeaders(state),\n },\n )\n\n if (!response.ok) throw new HTTPError(\"Failed to get Copilot token\", response)\n\n return (await response.json()) as GetCopilotTokenResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GetCopilotTokenResponse {\n expires_at: number\n refresh_in: number\n token: string\n}\n","import {\n GITHUB_APP_SCOPES,\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\n\nexport async function getDeviceCode(): Promise<DeviceCodeResponse> {\n const response = await fetch(`${GITHUB_BASE_URL}/login/device/code`, {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n scope: GITHUB_APP_SCOPES,\n }),\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get device code\", response)\n\n return (await response.json()) as DeviceCodeResponse\n}\n\nexport interface DeviceCodeResponse {\n device_code: string\n user_code: string\n verification_uri: string\n expires_in: number\n interval: number\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\n\nimport type { AzureOpenAIConfig } from \"./types\"\n\nexport const AZURE_OPENAI_MODEL_PREFIX = \"azure_openai_\"\n\nexport async function loadAzureOpenAIConfig(): Promise<AzureOpenAIConfig | null> {\n try {\n const content = await fs.readFile(PATHS.AZURE_OPENAI_CONFIG_PATH, \"utf8\")\n if (!content.trim()) {\n return null\n }\n\n const decoded = Buffer.from(content.trim(), \"base64\").toString(\"utf8\")\n const config = JSON.parse(decoded) as AzureOpenAIConfig\n\n if (!config.endpoint || !config.apiKey) {\n return null\n }\n\n return config\n } catch {\n return null\n }\n}\n\nexport async function saveAzureOpenAIConfig(\n config: AzureOpenAIConfig,\n): Promise<void> {\n const encoded = Buffer.from(JSON.stringify(config)).toString(\"base64\")\n await fs.writeFile(PATHS.AZURE_OPENAI_CONFIG_PATH, encoded, \"utf8\")\n await fs.chmod(PATHS.AZURE_OPENAI_CONFIG_PATH, 0o600)\n consola.success(\"Azure OpenAI configuration saved\")\n}\n\nexport async function promptAzureOpenAISetup(): Promise<AzureOpenAIConfig | null> {\n const wantToAdd = await consola.prompt(\n \"Would you like to add a custom Azure OpenAI endpoint?\",\n {\n type: \"confirm\",\n initial: false,\n },\n )\n\n if (!wantToAdd) {\n return null\n }\n\n const endpoint = await consola.prompt(\n \"Enter your Azure OpenAI endpoint URL (e.g., https://your-resource.openai.azure.com):\",\n {\n type: \"text\",\n },\n )\n\n if (!endpoint || typeof endpoint !== \"string\" || !endpoint.trim()) {\n consola.warn(\"No endpoint provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const apiKey = await consola.prompt(\"Enter your Azure OpenAI API key:\", {\n type: \"text\",\n })\n\n if (!apiKey || typeof apiKey !== \"string\" || !apiKey.trim()) {\n consola.warn(\"No API key provided, skipping Azure OpenAI setup\")\n return null\n }\n\n const config: AzureOpenAIConfig = {\n endpoint: endpoint.trim().replace(/\\/$/, \"\"), // Remove trailing slash\n apiKey: apiKey.trim(),\n }\n\n await saveAzureOpenAIConfig(config)\n return config\n}\n\nexport function isAzureOpenAIModel(modelId: string): boolean {\n return modelId.startsWith(AZURE_OPENAI_MODEL_PREFIX)\n}\n\nexport function getAzureDeploymentName(modelId: string): string {\n return modelId.slice(AZURE_OPENAI_MODEL_PREFIX.length)\n}\n","import consola from \"consola\"\r\n\r\nimport { sleep } from \"./utils\"\r\n\r\n// Fast retry: 100ms, 200ms, 300ms, then stop (max ~600ms total wait)\r\nconst RETRY_DELAYS_MS = [100, 200, 300]\r\n\r\n/**\r\n * Check if an error is retryable (transient network error)\r\n */\r\nfunction isRetryableError(error: unknown): boolean {\r\n if (!(error instanceof Error)) return false\r\n\r\n const message = error.message.toLowerCase()\r\n const causeMessage =\r\n error.cause instanceof Error ? error.cause.message.toLowerCase() : \"\"\r\n\r\n // Common transient error patterns\r\n const retryablePatterns = [\r\n \"fetch failed\",\r\n \"other side closed\",\r\n \"connection reset\",\r\n \"econnreset\",\r\n \"socket hang up\",\r\n \"socket connection was closed unexpectedly\",\r\n \"etimedout\",\r\n \"econnrefused\",\r\n \"network error\",\r\n \"aborted\",\r\n \"timeout\",\r\n ]\r\n\r\n return retryablePatterns.some(\r\n (pattern) => message.includes(pattern) || causeMessage.includes(pattern),\r\n )\r\n}\r\n\r\n/**\r\n * Check if an HTTP response status is retryable\r\n */\r\nfunction isRetryableStatus(status: number): boolean {\r\n // 4xx client errors (except 400, 401, 403, 404) and 5xx server errors\r\n // Retry: 408 Timeout, 429 Rate Limit, and all 5xx\r\n return status === 408 || status === 429 || (status >= 500 && status <= 599)\r\n}\r\n\r\n/**\r\n * Fetch with automatic fast retry on transient failures\r\n * Retries with delays: 100ms, 200ms, 300ms (max ~600ms total wait)\r\n */\r\nexport async function fetchWithRetry(\r\n input: string | URL | Request,\r\n init?: RequestInit,\r\n): Promise<Response> {\r\n const maxAttempts = RETRY_DELAYS_MS.length + 1 // 4 total attempts\r\n\r\n let lastError: Error | undefined\r\n let lastResponse: Response | undefined\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n try {\r\n // Force a new connection by adding cache-busting and connection headers\r\n const headers = new Headers(init?.headers)\r\n\r\n // Ensure we're not reusing potentially stale connections\r\n headers.set(\"Connection\", \"close\")\r\n\r\n const response = await fetch(input, {\r\n ...init,\r\n headers,\r\n // Disable keep-alive to force fresh connections on each attempt\r\n keepalive: false,\r\n })\r\n\r\n // Check for retryable HTTP status codes\r\n if (isRetryableStatus(response.status) && attempt < maxAttempts - 1) {\r\n lastResponse = response\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `HTTP ${response.status} (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms`,\r\n )\r\n await sleep(delayMs)\r\n continue\r\n }\r\n\r\n return response\r\n } catch (error) {\r\n lastError = error as Error\r\n\r\n if (!isRetryableError(error) || attempt === maxAttempts - 1) {\r\n throw error\r\n }\r\n\r\n const delayMs = RETRY_DELAYS_MS[attempt]\r\n consola.warn(\r\n `Fetch failed (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delayMs}ms:`,\r\n lastError.message,\r\n )\r\n await sleep(delayMs)\r\n }\r\n }\r\n\r\n // If we exhausted retries due to HTTP status, return the last response\r\n if (lastResponse) {\r\n return lastResponse\r\n }\r\n\r\n throw lastError\r\n}\r\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport type {\r\n ChatCompletionResponse,\r\n ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type { AzureOpenAIConfig } from \"./types\"\r\n\r\nimport { getAzureDeploymentName } from \"./config\"\r\n\r\nconst AZURE_API_VERSION = \"2024-10-21\"\r\n\r\nexport async function createAzureOpenAIChatCompletions(\r\n config: AzureOpenAIConfig,\r\n payload: ChatCompletionsPayload,\r\n) {\r\n // Extract the actual deployment name from the prefixed model ID\r\n const deploymentName = getAzureDeploymentName(payload.model)\r\n\r\n // Convert max_tokens to max_completion_tokens for newer models (GPT-4o, GPT-5, etc.)\r\n // Azure OpenAI newer models require max_completion_tokens instead of max_tokens\r\n const { max_tokens, ...restPayload } = payload\r\n const azurePayload = {\r\n ...restPayload,\r\n model: deploymentName,\r\n ...(max_tokens != null && { max_completion_tokens: max_tokens }),\r\n }\r\n\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments/${deploymentName}/chat/completions?api-version=${AZURE_API_VERSION}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify(azurePayload),\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create Azure OpenAI chat completions:\", response)\r\n throw new HTTPError(\r\n \"Failed to create Azure OpenAI chat completions\",\r\n response,\r\n payload,\r\n )\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\n\r\nimport type {\r\n AzureOpenAIConfig,\r\n AzureOpenAIDeploymentInfo,\r\n AzureOpenAIDeploymentsResponse,\r\n} from \"./types\"\r\n\r\nimport { AZURE_OPENAI_MODEL_PREFIX } from \"./config\"\r\n\r\n// Different API versions for different endpoints\r\nconst AZURE_DEPLOYMENTS_API_VERSION = \"2022-12-01\"\r\n\r\nexport async function getAzureOpenAIDeployments(\r\n config: AzureOpenAIConfig,\r\n): Promise<Array<AzureOpenAIDeploymentInfo>> {\r\n try {\r\n const response = await fetchWithRetry(\r\n `${config.endpoint}/openai/deployments?api-version=${AZURE_DEPLOYMENTS_API_VERSION}`,\r\n {\r\n headers: {\r\n \"api-key\": config.apiKey,\r\n \"Content-Type\": \"application/json\",\r\n },\r\n },\r\n )\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => \"\")\r\n consola.error(\r\n `Failed to fetch Azure OpenAI deployments: ${response.status}`,\r\n errorText,\r\n )\r\n throw new HTTPError(\"Failed to fetch Azure OpenAI deployments\", response)\r\n }\r\n\r\n const data = (await response.json()) as AzureOpenAIDeploymentsResponse\r\n\r\n // Only include deployments that are successfully deployed\r\n return data.data\r\n .filter((deployment) => deployment.status === \"succeeded\")\r\n .map((deployment) => ({\r\n id: `${AZURE_OPENAI_MODEL_PREFIX}${deployment.id}`,\r\n deploymentName: deployment.id,\r\n model: deployment.model,\r\n created: deployment.created_at,\r\n object: \"deployment\",\r\n owned_by: deployment.owner || \"azure-openai\",\r\n }))\r\n } catch (error) {\r\n if (error instanceof HTTPError) {\r\n throw error\r\n }\r\n consola.error(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n return []\r\n }\r\n}\r\n","import consola from \"consola\"\r\n\r\nimport { copilotBaseUrl, copilotHeaders } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const getModels = async () => {\r\n const url = `${copilotBaseUrl(state)}/models`\r\n const response = await fetchWithRetry(url, {\r\n headers: copilotHeaders(state),\r\n })\r\n\r\n if (!response.ok) {\r\n const errorBody = await response.text()\r\n let errorDetails: string\r\n try {\r\n const parsed: unknown = JSON.parse(errorBody)\r\n errorDetails = JSON.stringify(parsed, null, 2)\r\n } catch {\r\n errorDetails = errorBody || \"(empty response)\"\r\n }\r\n consola.error(\r\n `Failed to get models from ${url}\\n`\r\n + `Status: ${response.status} ${response.statusText}\\n`\r\n + `Response: ${errorDetails}`,\r\n )\r\n throw new HTTPError(\r\n `Failed to get models: ${response.status} ${response.statusText}`,\r\n response,\r\n )\r\n }\r\n\r\n return (await response.json()) as ModelsResponse\r\n}\r\n\r\nexport interface ModelsResponse {\r\n data: Array<Model>\r\n object: string\r\n}\r\n\r\ninterface ModelLimits {\r\n max_context_window_tokens?: number\r\n max_output_tokens?: number\r\n max_prompt_tokens?: number\r\n max_inputs?: number\r\n}\r\n\r\ninterface ModelSupports {\r\n tool_calls?: boolean\r\n parallel_tool_calls?: boolean\r\n dimensions?: boolean\r\n}\r\n\r\ninterface ModelCapabilities {\r\n family: string\r\n limits: ModelLimits\r\n object: string\r\n supports: ModelSupports\r\n tokenizer: string\r\n type: string\r\n}\r\n\r\nexport interface Model {\r\n capabilities: ModelCapabilities\r\n id: string\r\n model_picker_enabled: boolean\r\n name: string\r\n object: string\r\n preview: boolean\r\n vendor: string\r\n version: string\r\n policy?: {\r\n state: string\r\n terms: string\r\n }\r\n}\r\n","const FALLBACK = \"1.104.3\"\n\nexport async function getVSCodeVersion() {\n const controller = new AbortController()\n const timeout = setTimeout(() => {\n controller.abort()\n }, 5000)\n\n try {\n const response = await fetch(\n \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=visual-studio-code-bin\",\n {\n signal: controller.signal,\n },\n )\n\n const pkgbuild = await response.text()\n const pkgverRegex = /pkgver=([0-9.]+)/\n const match = pkgbuild.match(pkgverRegex)\n\n if (match) {\n return match[1]\n }\n\n return FALLBACK\n } catch {\n return FALLBACK\n } finally {\n clearTimeout(timeout)\n }\n}\n\nawait getVSCodeVersion()\n","import consola from \"consola\"\r\n\r\nimport {\r\n getAzureOpenAIDeployments,\r\n loadAzureOpenAIConfig,\r\n promptAzureOpenAISetup,\r\n} from \"~/services/azure-openai\"\r\nimport { getModels } from \"~/services/copilot/get-models\"\r\nimport { getVSCodeVersion } from \"~/services/get-vscode-version\"\r\n\r\nimport { state } from \"./state\"\r\n\r\nexport const sleep = (ms: number) =>\r\n new Promise((resolve) => {\r\n setTimeout(resolve, ms)\r\n })\r\n\r\nexport const isNullish = (value: unknown): value is null | undefined =>\r\n value === null || value === undefined\r\n\r\nexport async function cacheModels(): Promise<void> {\r\n try {\r\n const models = await getModels()\r\n state.models = models\r\n } catch (error) {\r\n consola.error(\"Failed to fetch and cache models. This could be due to:\")\r\n consola.error(\" - Invalid or expired Copilot token\")\r\n consola.error(\" - Network connectivity issues\")\r\n consola.error(\" - GitHub Copilot service unavailable\")\r\n consola.error(\r\n \" - Account type mismatch (try --account-type=individual or --account-type=business)\",\r\n )\r\n throw error\r\n }\r\n}\r\n\r\nexport const cacheVSCodeVersion = async () => {\r\n const response = await getVSCodeVersion()\r\n state.vsCodeVersion = response\r\n\r\n consola.info(`Using VSCode version: ${response}`)\r\n}\r\n\r\nexport async function setupAzureOpenAI(): Promise<void> {\r\n // Try to load existing config\r\n let config = await loadAzureOpenAIConfig()\r\n\r\n // If no config exists, prompt user on first run\r\n if (!config) {\r\n config = await promptAzureOpenAISetup()\r\n }\r\n\r\n if (!config) {\r\n consola.info(\"Azure OpenAI not configured\")\r\n return\r\n }\r\n\r\n state.azureOpenAIConfig = config\r\n consola.info(\"Azure OpenAI configuration loaded\")\r\n\r\n // Fetch and cache Azure OpenAI deployments\r\n try {\r\n const deployments = await getAzureOpenAIDeployments(config)\r\n state.azureOpenAIDeployments = deployments\r\n if (deployments.length > 0) {\r\n consola.info(\r\n `Loaded ${deployments.length} Azure OpenAI deployment(s):\\n${deployments.map((d) => `- ${d.id} (${d.model})`).join(\"\\n\")}`,\r\n )\r\n } else {\r\n consola.warn(\"No Azure OpenAI deployments found\")\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to fetch Azure OpenAI deployments:\", error)\r\n }\r\n}\r\n","import consola from \"consola\"\n\nimport {\n GITHUB_BASE_URL,\n GITHUB_CLIENT_ID,\n standardHeaders,\n} from \"~/lib/api-config\"\nimport { sleep } from \"~/lib/utils\"\n\nimport type { DeviceCodeResponse } from \"./get-device-code\"\n\nexport async function pollAccessToken(\n deviceCode: DeviceCodeResponse,\n): Promise<string> {\n // Interval is in seconds, we need to multiply by 1000 to get milliseconds\n // I'm also adding another second, just to be safe\n const sleepDuration = (deviceCode.interval + 1) * 1000\n consola.debug(`Polling access token with interval of ${sleepDuration}ms`)\n\n while (true) {\n const response = await fetch(\n `${GITHUB_BASE_URL}/login/oauth/access_token`,\n {\n method: \"POST\",\n headers: standardHeaders(),\n body: JSON.stringify({\n client_id: GITHUB_CLIENT_ID,\n device_code: deviceCode.device_code,\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n }),\n },\n )\n\n if (!response.ok) {\n await sleep(sleepDuration)\n consola.error(\"Failed to poll access token:\", await response.text())\n\n continue\n }\n\n const json = await response.json()\n consola.debug(\"Polling access token response:\", json)\n\n const { access_token } = json as AccessTokenResponse\n\n if (access_token) {\n return access_token\n } else {\n await sleep(sleepDuration)\n }\n }\n}\n\ninterface AccessTokenResponse {\n access_token: string\n token_type: string\n scope: string\n}\n","import consola from \"consola\"\nimport fs from \"node:fs/promises\"\n\nimport { PATHS } from \"~/lib/paths\"\nimport { getCopilotToken } from \"~/services/github/get-copilot-token\"\nimport { getDeviceCode } from \"~/services/github/get-device-code\"\nimport { getGitHubUser } from \"~/services/github/get-user\"\nimport { pollAccessToken } from \"~/services/github/poll-access-token\"\n\nimport { HTTPError } from \"./error\"\nimport { state } from \"./state\"\n\nconst readGithubToken = () => fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n\nconst writeGithubToken = (token: string) =>\n fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)\n\nexport const setupCopilotToken = async () => {\n const { token, refresh_in } = await getCopilotToken()\n state.copilotToken = token\n\n // Display the Copilot token to the screen\n consola.debug(\"GitHub Copilot Token fetched successfully!\")\n if (state.showToken) {\n consola.info(\"Copilot token:\", token)\n }\n\n const refreshInterval = (refresh_in - 60) * 1000\n setInterval(async () => {\n consola.debug(\"Refreshing Copilot token\")\n try {\n const { token } = await getCopilotToken()\n state.copilotToken = token\n consola.debug(\"Copilot token refreshed\")\n if (state.showToken) {\n consola.info(\"Refreshed Copilot token:\", token)\n }\n } catch (error) {\n consola.error(\"Failed to refresh Copilot token:\", error)\n throw error\n }\n }, refreshInterval)\n}\n\ninterface SetupGitHubTokenOptions {\n force?: boolean\n}\n\nexport async function setupGitHubToken(\n options?: SetupGitHubTokenOptions,\n): Promise<void> {\n try {\n const githubToken = await readGithubToken()\n\n if (githubToken && !options?.force) {\n state.githubToken = githubToken\n if (state.showToken) {\n consola.info(\"GitHub token:\", githubToken)\n }\n await logUser()\n\n return\n }\n\n consola.info(\"Not logged in, getting new access token\")\n const response = await getDeviceCode()\n consola.debug(\"Device code response:\", response)\n\n consola.info(\n `Please enter the code \"${response.user_code}\" in ${response.verification_uri}`,\n )\n\n const token = await pollAccessToken(response)\n await writeGithubToken(token)\n state.githubToken = token\n\n if (state.showToken) {\n consola.info(\"GitHub token:\", token)\n }\n await logUser()\n } catch (error) {\n if (error instanceof HTTPError) {\n consola.error(\"Failed to get GitHub token:\", await error.response.json())\n throw error\n }\n\n consola.error(\"Failed to get GitHub token:\", error)\n throw error\n }\n}\n\nasync function logUser() {\n const user = await getGitHubUser()\n consola.info(`Logged in as ${user.login}`)\n}\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"./lib/paths\"\nimport { state } from \"./lib/state\"\nimport { setupGitHubToken } from \"./lib/token\"\n\ninterface RunAuthOptions {\n verbose: boolean\n showToken: boolean\n}\n\nexport async function runAuth(options: RunAuthOptions): Promise<void> {\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.showToken = options.showToken\n\n await ensurePaths()\n await setupGitHubToken({ force: true })\n consola.success(\"GitHub token written to\", PATHS.GITHUB_TOKEN_PATH)\n}\n\nexport const auth = defineCommand({\n meta: {\n name: \"auth\",\n description: \"Run GitHub auth flow without running the server\",\n },\n args: {\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub token on auth\",\n },\n },\n run({ args }) {\n return runAuth({\n verbose: args.verbose,\n showToken: args[\"show-token\"],\n })\n },\n})\n","import { GITHUB_API_BASE_URL, githubHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport const getCopilotUsage = async (): Promise<CopilotUsageResponse> => {\n const response = await fetch(`${GITHUB_API_BASE_URL}/copilot_internal/user`, {\n headers: githubHeaders(state),\n })\n\n if (!response.ok) {\n throw new HTTPError(\"Failed to get Copilot usage\", response)\n }\n\n return (await response.json()) as CopilotUsageResponse\n}\n\nexport interface QuotaDetail {\n entitlement: number\n overage_count: number\n overage_permitted: boolean\n percent_remaining: number\n quota_id: string\n quota_remaining: number\n remaining: number\n unlimited: boolean\n}\n\ninterface QuotaSnapshots {\n chat: QuotaDetail\n completions: QuotaDetail\n premium_interactions: QuotaDetail\n}\n\ninterface CopilotUsageResponse {\n access_type_sku: string\n analytics_tracking_id: string\n assigned_date: string\n can_signup_for_limited: boolean\n chat_enabled: boolean\n copilot_plan: string\n organization_login_list: Array<unknown>\n organization_list: Array<unknown>\n quota_reset_date: string\n quota_snapshots: QuotaSnapshots\n}\n","import { defineCommand } from \"citty\"\nimport consola from \"consola\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { setupGitHubToken } from \"./lib/token\"\nimport {\n getCopilotUsage,\n type QuotaDetail,\n} from \"./services/github/get-copilot-usage\"\n\nexport const checkUsage = defineCommand({\n meta: {\n name: \"check-usage\",\n description: \"Show current GitHub Copilot usage/quota information\",\n },\n async run() {\n await ensurePaths()\n await setupGitHubToken()\n try {\n const usage = await getCopilotUsage()\n const premium = usage.quota_snapshots.premium_interactions\n const premiumTotal = premium.entitlement\n const premiumUsed = premiumTotal - premium.remaining\n const premiumPercentUsed =\n premiumTotal > 0 ? (premiumUsed / premiumTotal) * 100 : 0\n const premiumPercentRemaining = premium.percent_remaining\n\n // Helper to summarize a quota snapshot\n function summarizeQuota(name: string, snap: QuotaDetail | undefined) {\n if (!snap) return `${name}: N/A`\n const total = snap.entitlement\n const used = total - snap.remaining\n const percentUsed = total > 0 ? (used / total) * 100 : 0\n const percentRemaining = snap.percent_remaining\n return `${name}: ${used}/${total} used (${percentUsed.toFixed(1)}% used, ${percentRemaining.toFixed(1)}% remaining)`\n }\n\n const premiumLine = `Premium: ${premiumUsed}/${premiumTotal} used (${premiumPercentUsed.toFixed(1)}% used, ${premiumPercentRemaining.toFixed(1)}% remaining)`\n const chatLine = summarizeQuota(\"Chat\", usage.quota_snapshots.chat)\n const completionsLine = summarizeQuota(\n \"Completions\",\n usage.quota_snapshots.completions,\n )\n\n consola.box(\n `Copilot Usage (plan: ${usage.copilot_plan})\\n`\n + `Quota resets: ${usage.quota_reset_date}\\n`\n + `\\nQuotas:\\n`\n + ` ${premiumLine}\\n`\n + ` ${chatLine}\\n`\n + ` ${completionsLine}`,\n )\n } catch (err) {\n consola.error(\"Failed to fetch Copilot usage:\", err)\n process.exit(1)\n }\n },\n})\n","import consola from \"consola\"\r\nimport fs from \"node:fs/promises\"\r\n\r\nimport type { ChatCompletionsPayload } from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport { PATHS } from \"./paths\"\r\n\r\nexport interface ReplacementRule {\r\n id: string\r\n name?: string // Human-readable name/description\r\n pattern: string\r\n replacement: string\r\n isRegex: boolean\r\n enabled: boolean\r\n isSystem?: boolean // System rules cannot be deleted by user\r\n}\r\n\r\n// Built-in system replacement that cannot be removed\r\nconst SYSTEM_REPLACEMENTS: Array<ReplacementRule> = [\r\n {\r\n id: \"system-anthropic-billing\",\r\n name: \"Remove Anthropic billing header\",\r\n pattern: \"x-anthropic-billing-header:[^\\\\n]*\\\\n?\",\r\n replacement: \"\",\r\n isRegex: true,\r\n enabled: true,\r\n isSystem: true,\r\n },\r\n]\r\n\r\n// User-configured replacements (loaded from disk)\r\nlet userReplacements: Array<ReplacementRule> = []\r\nlet isLoaded = false\r\n\r\n/**\r\n * Load user replacements from disk\r\n */\r\nexport async function loadReplacements(): Promise<void> {\r\n try {\r\n const data = await fs.readFile(PATHS.REPLACEMENTS_CONFIG_PATH)\r\n const parsed = JSON.parse(data.toString()) as Array<ReplacementRule>\r\n userReplacements = parsed.filter((r) => !r.isSystem)\r\n isLoaded = true\r\n consola.debug(`Loaded ${userReplacements.length} user replacement rules`)\r\n } catch {\r\n // File doesn't exist or is invalid - start with empty array\r\n userReplacements = []\r\n isLoaded = true\r\n }\r\n}\r\n\r\n/**\r\n * Save user replacements to disk\r\n */\r\nexport async function saveReplacements(): Promise<void> {\r\n try {\r\n await fs.writeFile(\r\n PATHS.REPLACEMENTS_CONFIG_PATH,\r\n JSON.stringify(userReplacements, null, 2),\r\n \"utf8\",\r\n )\r\n consola.debug(`Saved ${userReplacements.length} user replacement rules`)\r\n } catch (error) {\r\n consola.error(\"Failed to save replacement rules:\", error)\r\n throw error\r\n }\r\n}\r\n\r\n/**\r\n * Ensure replacements are loaded before accessing\r\n */\r\nexport async function ensureLoaded(): Promise<void> {\r\n if (!isLoaded) {\r\n await loadReplacements()\r\n }\r\n}\r\n\r\n/**\r\n * Get all replacement rules (system + user)\r\n */\r\nexport async function getAllReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return [...SYSTEM_REPLACEMENTS, ...userReplacements]\r\n}\r\n\r\n/**\r\n * Get only user-configurable replacements\r\n */\r\nexport async function getUserReplacements(): Promise<Array<ReplacementRule>> {\r\n await ensureLoaded()\r\n return userReplacements\r\n}\r\n\r\n/**\r\n * Add a new user replacement rule\r\n */\r\nexport async function addReplacement(\r\n pattern: string,\r\n replacement: string,\r\n isRegex = false,\r\n name?: string,\r\n): Promise<ReplacementRule> {\r\n await ensureLoaded()\r\n const rule: ReplacementRule = {\r\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,\r\n name,\r\n pattern,\r\n replacement,\r\n isRegex,\r\n enabled: true,\r\n isSystem: false,\r\n }\r\n userReplacements.push(rule)\r\n await saveReplacements()\r\n consola.info(`Added replacement rule: \"${pattern}\" -> \"${replacement}\"`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Remove a user replacement rule by ID\r\n */\r\nexport async function removeReplacement(id: string): Promise<boolean> {\r\n await ensureLoaded()\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return false\r\n }\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot remove system replacement rule\")\r\n return false\r\n }\r\n userReplacements = userReplacements.filter((r) => r.id !== id)\r\n await saveReplacements()\r\n consola.info(`Removed replacement rule: ${id}`)\r\n return true\r\n}\r\n\r\n/**\r\n * Update an existing user replacement rule\r\n */\r\nexport async function updateReplacement(\r\n id: string,\r\n updates: {\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n },\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n\r\n const rule = userReplacements.find((r) => r.id === id)\r\n if (!rule) {\r\n return null\r\n }\r\n\r\n if (rule.isSystem) {\r\n consola.warn(\"Cannot update system replacement rule\")\r\n return null\r\n }\r\n\r\n if (updates.name !== undefined) rule.name = updates.name\r\n if (updates.pattern !== undefined) rule.pattern = updates.pattern\r\n if (updates.replacement !== undefined) rule.replacement = updates.replacement\r\n if (updates.isRegex !== undefined) rule.isRegex = updates.isRegex\r\n if (updates.enabled !== undefined) rule.enabled = updates.enabled\r\n\r\n await saveReplacements()\r\n consola.info(`Updated replacement rule: ${rule.name || rule.id}`)\r\n return rule\r\n}\r\n\r\n/**\r\n * Toggle a replacement rule on/off\r\n */\r\nexport async function toggleReplacement(\r\n id: string,\r\n): Promise<ReplacementRule | null> {\r\n await ensureLoaded()\r\n // Check user replacements first\r\n const userRule = userReplacements.find((r) => r.id === id)\r\n if (userRule) {\r\n userRule.enabled = !userRule.enabled\r\n await saveReplacements()\r\n consola.info(\r\n `Toggled replacement rule ${id}: ${userRule.enabled ? \"enabled\" : \"disabled\"}`,\r\n )\r\n return userRule\r\n }\r\n\r\n // System rules cannot be toggled\r\n const systemRule = SYSTEM_REPLACEMENTS.find((r) => r.id === id)\r\n if (systemRule) {\r\n consola.warn(\"Cannot toggle system replacement rule\")\r\n return null\r\n }\r\n\r\n return null\r\n}\r\n\r\n/**\r\n * Clear all user replacements\r\n */\r\nexport async function clearUserReplacements(): Promise<void> {\r\n userReplacements = []\r\n await saveReplacements()\r\n consola.info(\"Cleared all user replacement rules\")\r\n}\r\n\r\n/**\r\n * Apply a single replacement rule to text and return info about whether it matched\r\n */\r\nfunction applyRule(\r\n text: string,\r\n rule: ReplacementRule,\r\n): { result: string; matched: boolean } {\r\n if (!rule.enabled) return { result: text, matched: false }\r\n\r\n if (rule.isRegex) {\r\n try {\r\n const regex = new RegExp(rule.pattern, \"g\")\r\n const result = text.replace(regex, rule.replacement)\r\n return { result, matched: result !== text }\r\n } catch {\r\n consola.warn(`Invalid regex pattern in rule ${rule.id}: ${rule.pattern}`)\r\n return { result: text, matched: false }\r\n }\r\n }\r\n\r\n const result = text.split(rule.pattern).join(rule.replacement)\r\n return { result, matched: result !== text }\r\n}\r\n\r\n/**\r\n * Apply all replacement rules to text\r\n */\r\nexport async function applyReplacements(text: string): Promise<string> {\r\n let result = text\r\n const allRules = await getAllReplacements()\r\n const appliedRules: string[] = []\r\n\r\n for (const rule of allRules) {\r\n const { result: newResult, matched } = applyRule(result, rule)\r\n if (matched) {\r\n result = newResult\r\n appliedRules.push(rule.name || rule.id)\r\n }\r\n }\r\n\r\n if (appliedRules.length > 0) {\r\n consola.info(`Replacements applied: ${appliedRules.join(\", \")}`)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Apply replacements to a chat completions payload\r\n * This modifies message content in place\r\n */\r\nexport async function applyReplacementsToPayload(\r\n payload: ChatCompletionsPayload,\r\n): Promise<ChatCompletionsPayload> {\r\n const processedMessages = await Promise.all(\r\n payload.messages.map(async (message) => {\r\n if (typeof message.content === \"string\") {\r\n return {\r\n ...message,\r\n content: await applyReplacements(message.content),\r\n }\r\n }\r\n\r\n // Handle array content (multimodal)\r\n if (Array.isArray(message.content)) {\r\n return {\r\n ...message,\r\n content: await Promise.all(\r\n message.content.map(async (part) => {\r\n if (\r\n typeof part === \"object\"\r\n && part.type === \"text\"\r\n && part.text\r\n ) {\r\n return {\r\n ...part,\r\n text: await applyReplacements(part.text),\r\n }\r\n }\r\n return part\r\n }),\r\n ),\r\n }\r\n }\r\n\r\n return message\r\n }),\r\n )\r\n\r\n return {\r\n ...payload,\r\n messages: processedMessages,\r\n }\r\n}\r\n","import { defineCommand } from \"citty\"\r\nimport consola from \"consola\"\r\n\r\nimport {\r\n addReplacement,\r\n applyReplacements,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n type ReplacementRule,\r\n} from \"~/lib/auto-replace\"\r\nimport { ensurePaths, PATHS } from \"~/lib/paths\"\r\n\r\ntype MenuAction =\r\n | \"list\"\r\n | \"add\"\r\n | \"edit\"\r\n | \"remove\"\r\n | \"toggle\"\r\n | \"test\"\r\n | \"clear\"\r\n | \"exit\"\r\n\r\nfunction formatRule(rule: ReplacementRule, index: number): string {\r\n const status = rule.enabled ? \"✓\" : \"✗\"\r\n const type = rule.isRegex ? \"regex\" : \"string\"\r\n const system = rule.isSystem ? \" [system]\" : \"\"\r\n const name = rule.name ? ` \"${rule.name}\"` : \"\"\r\n const replacement = rule.replacement || \"(empty)\"\r\n return `${index + 1}. [${status}] (${type})${system}${name} \"${rule.pattern}\" → \"${replacement}\"`\r\n}\r\n\r\nasync function listReplacements(): Promise<void> {\r\n const all = await getAllReplacements()\r\n\r\n if (all.length === 0) {\r\n consola.info(\"No replacement rules configured.\")\r\n return\r\n }\r\n\r\n consola.info(\"\\n📋 Replacement Rules:\\n\")\r\n for (const [i, element] of all.entries()) {\r\n console.log(formatRule(element, i))\r\n }\r\n console.log()\r\n}\r\n\r\nasync function addNewReplacement(): Promise<void> {\r\n const name = await consola.prompt(\"Name (optional, short description):\", {\r\n type: \"text\",\r\n default: \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\r\n \"Replacement text (leave empty to delete matches):\",\r\n {\r\n type: \"text\",\r\n default: \"\",\r\n },\r\n )\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await addReplacement(\r\n pattern,\r\n replacement,\r\n matchType === \"regex\",\r\n name || undefined,\r\n )\r\n\r\n consola.success(`Added rule: ${rule.name || rule.id}`)\r\n}\r\n\r\nasync function editExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to edit.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to edit:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = userRules.find((r) => r.id === selected)\r\n if (!rule) {\r\n consola.error(\"Rule not found.\")\r\n return\r\n }\r\n\r\n consola.info(`\\nEditing rule: ${rule.name || rule.id}`)\r\n consola.info(\"Press Enter to keep current value.\\n\")\r\n\r\n const name = await consola.prompt(\"Name:\", {\r\n type: \"text\",\r\n default: rule.name || \"\",\r\n })\r\n\r\n if (typeof name === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const matchType = await consola.prompt(\"Match type:\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"String (exact match)\", value: \"string\" },\r\n { label: \"Regex (regular expression)\", value: \"regex\" },\r\n ],\r\n initial: rule.isRegex ? \"regex\" : \"string\",\r\n })\r\n\r\n if (typeof matchType === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const pattern = await consola.prompt(\"Pattern to match:\", {\r\n type: \"text\",\r\n default: rule.pattern,\r\n })\r\n\r\n if (typeof pattern === \"symbol\" || !pattern) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n // Validate regex if needed\r\n if (matchType === \"regex\") {\r\n try {\r\n new RegExp(pattern)\r\n } catch {\r\n consola.error(`Invalid regex pattern: ${pattern}`)\r\n return\r\n }\r\n }\r\n\r\n const replacement = await consola.prompt(\"Replacement text:\", {\r\n type: \"text\",\r\n default: rule.replacement,\r\n })\r\n\r\n if (typeof replacement === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const updated = await updateReplacement(selected, {\r\n name: name || undefined,\r\n pattern,\r\n replacement,\r\n isRegex: matchType === \"regex\",\r\n })\r\n\r\n if (updated) {\r\n consola.success(`Updated rule: ${updated.name || updated.id}`)\r\n } else {\r\n consola.error(\"Failed to update rule.\")\r\n }\r\n}\r\n\r\nasync function removeExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to remove.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to remove:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const success = await removeReplacement(selected)\r\n if (success) {\r\n consola.success(\"Rule removed.\")\r\n } else {\r\n consola.error(\"Failed to remove rule.\")\r\n }\r\n}\r\n\r\nasync function toggleExistingReplacement(): Promise<void> {\r\n const userRules = await getUserReplacements()\r\n\r\n if (userRules.length === 0) {\r\n consola.info(\"No user rules to toggle.\")\r\n return\r\n }\r\n\r\n const options = userRules.map((rule, i) => ({\r\n label: formatRule(rule, i),\r\n value: rule.id,\r\n }))\r\n\r\n const selected = await consola.prompt(\"Select rule to toggle:\", {\r\n type: \"select\",\r\n options,\r\n })\r\n\r\n if (typeof selected === \"symbol\") {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const rule = await toggleReplacement(selected)\r\n if (rule) {\r\n consola.success(`Rule ${rule.enabled ? \"enabled\" : \"disabled\"}.`)\r\n } else {\r\n consola.error(\"Failed to toggle rule.\")\r\n }\r\n}\r\n\r\nasync function testReplacements(): Promise<void> {\r\n const testText = await consola.prompt(\"Enter text to test replacements:\", {\r\n type: \"text\",\r\n })\r\n\r\n if (typeof testText === \"symbol\" || !testText) {\r\n consola.info(\"Cancelled.\")\r\n return\r\n }\r\n\r\n const result = await applyReplacements(testText)\r\n\r\n consola.info(\"\\n📝 Original:\")\r\n console.log(testText)\r\n consola.info(\"\\n✨ After replacements:\")\r\n console.log(result)\r\n console.log()\r\n}\r\n\r\nasync function clearAllReplacements(): Promise<void> {\r\n const confirm = await consola.prompt(\r\n \"Are you sure you want to clear all user replacements?\",\r\n {\r\n type: \"confirm\",\r\n initial: false,\r\n },\r\n )\r\n\r\n if (confirm) {\r\n await clearUserReplacements()\r\n consola.success(\"All user replacements cleared.\")\r\n } else {\r\n consola.info(\"Cancelled.\")\r\n }\r\n}\r\n\r\nasync function mainMenu(): Promise<void> {\r\n consola.info(`\\n🔧 Copilot API - Replacement Configuration`)\r\n consola.info(`Config file: ${PATHS.REPLACEMENTS_CONFIG_PATH}\\n`)\r\n\r\n let running = true\r\n\r\n while (running) {\r\n const action = await consola.prompt(\"What would you like to do?\", {\r\n type: \"select\",\r\n options: [\r\n { label: \"📋 List all rules\", value: \"list\" as MenuAction },\r\n { label: \"➕ Add new rule\", value: \"add\" as MenuAction },\r\n { label: \"✏️ Edit rule\", value: \"edit\" as MenuAction },\r\n { label: \"➖ Remove rule\", value: \"remove\" as MenuAction },\r\n { label: \"🔄 Toggle rule on/off\", value: \"toggle\" as MenuAction },\r\n { label: \"🧪 Test replacements\", value: \"test\" as MenuAction },\r\n { label: \"🗑️ Clear all user rules\", value: \"clear\" as MenuAction },\r\n { label: \"🚪 Exit\", value: \"exit\" as MenuAction },\r\n ],\r\n })\r\n\r\n if (typeof action === \"symbol\") {\r\n break\r\n }\r\n\r\n switch (action) {\r\n case \"list\": {\r\n await listReplacements()\r\n break\r\n }\r\n case \"add\": {\r\n await addNewReplacement()\r\n break\r\n }\r\n case \"edit\": {\r\n await editExistingReplacement()\r\n break\r\n }\r\n case \"remove\": {\r\n await removeExistingReplacement()\r\n break\r\n }\r\n case \"toggle\": {\r\n await toggleExistingReplacement()\r\n break\r\n }\r\n case \"test\": {\r\n await testReplacements()\r\n break\r\n }\r\n case \"clear\": {\r\n await clearAllReplacements()\r\n break\r\n }\r\n case \"exit\": {\r\n running = false\r\n break\r\n }\r\n default: {\r\n break\r\n }\r\n }\r\n }\r\n\r\n consola.info(\"Goodbye! 👋\")\r\n}\r\n\r\nexport const config = defineCommand({\r\n meta: {\r\n name: \"config\",\r\n description: \"Configure replacement rules interactively\",\r\n },\r\n run: async () => {\r\n await ensurePaths()\r\n await mainMenu()\r\n },\r\n})\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport consola from \"consola\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\n\nimport { PATHS } from \"./lib/paths\"\n\ninterface DebugInfo {\n version: string\n runtime: {\n name: string\n version: string\n platform: string\n arch: string\n }\n paths: {\n APP_DIR: string\n GITHUB_TOKEN_PATH: string\n }\n tokenExists: boolean\n}\n\ninterface RunDebugOptions {\n json: boolean\n}\n\nasync function getPackageVersion(): Promise<string> {\n try {\n const packageJsonPath = new URL(\"../package.json\", import.meta.url).pathname\n // @ts-expect-error https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v59.0.1/docs/rules/prefer-json-parse-buffer.md\n // JSON.parse() can actually parse buffers\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath)) as {\n version: string\n }\n return packageJson.version\n } catch {\n return \"unknown\"\n }\n}\n\nfunction getRuntimeInfo() {\n const isBun = typeof Bun !== \"undefined\"\n\n return {\n name: isBun ? \"bun\" : \"node\",\n version: isBun ? Bun.version : process.version.slice(1),\n platform: os.platform(),\n arch: os.arch(),\n }\n}\n\nasync function checkTokenExists(): Promise<boolean> {\n try {\n const stats = await fs.stat(PATHS.GITHUB_TOKEN_PATH)\n if (!stats.isFile()) return false\n\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\nasync function getDebugInfo(): Promise<DebugInfo> {\n const [version, tokenExists] = await Promise.all([\n getPackageVersion(),\n checkTokenExists(),\n ])\n\n return {\n version,\n runtime: getRuntimeInfo(),\n paths: {\n APP_DIR: PATHS.APP_DIR,\n GITHUB_TOKEN_PATH: PATHS.GITHUB_TOKEN_PATH,\n },\n tokenExists,\n }\n}\n\nfunction printDebugInfoPlain(info: DebugInfo): void {\n consola.info(`copilot-api debug\n\nVersion: ${info.version}\nRuntime: ${info.runtime.name} ${info.runtime.version} (${info.runtime.platform} ${info.runtime.arch})\n\nPaths:\n- APP_DIR: ${info.paths.APP_DIR}\n- GITHUB_TOKEN_PATH: ${info.paths.GITHUB_TOKEN_PATH}\n\nToken exists: ${info.tokenExists ? \"Yes\" : \"No\"}`)\n}\n\nfunction printDebugInfoJson(info: DebugInfo): void {\n console.log(JSON.stringify(info, null, 2))\n}\n\nexport async function runDebug(options: RunDebugOptions): Promise<void> {\n const debugInfo = await getDebugInfo()\n\n if (options.json) {\n printDebugInfoJson(debugInfo)\n } else {\n printDebugInfoPlain(debugInfo)\n }\n}\n\nexport const debug = defineCommand({\n meta: {\n name: \"debug\",\n description: \"Print debug information about the application\",\n },\n args: {\n json: {\n type: \"boolean\",\n default: false,\n description: \"Output debug information as JSON\",\n },\n },\n run({ args }) {\n return runDebug({\n json: args.json,\n })\n },\n})\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nexport function initProxyFromEnv(): void {\n if (typeof Bun !== \"undefined\") return\n\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n setGlobalDispatcher(dispatcher as unknown as Dispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n","import { execSync } from \"node:child_process\"\nimport process from \"node:process\"\n\ntype ShellName = \"bash\" | \"zsh\" | \"fish\" | \"powershell\" | \"cmd\" | \"sh\"\ntype EnvVars = Record<string, string | undefined>\n\nfunction getShell(): ShellName {\n const { platform, ppid, env } = process\n\n if (platform === \"win32\") {\n try {\n const command = `wmic process get ParentProcessId,Name | findstr \"${ppid}\"`\n const parentProcess = execSync(command, { stdio: \"pipe\" }).toString()\n\n if (parentProcess.toLowerCase().includes(\"powershell.exe\")) {\n return \"powershell\"\n }\n } catch {\n return \"cmd\"\n }\n\n return \"cmd\"\n } else {\n const shellPath = env.SHELL\n if (shellPath) {\n if (shellPath.endsWith(\"zsh\")) return \"zsh\"\n if (shellPath.endsWith(\"fish\")) return \"fish\"\n if (shellPath.endsWith(\"bash\")) return \"bash\"\n }\n\n return \"sh\"\n }\n}\n\n/**\n * Generates a copy-pasteable script to set multiple environment variables\n * and run a subsequent command.\n * @param {EnvVars} envVars - An object of environment variables to set.\n * @param {string} commandToRun - The command to run after setting the variables.\n * @returns {string} The formatted script string.\n */\nexport function generateEnvScript(\n envVars: EnvVars,\n commandToRun: string = \"\",\n): string {\n const shell = getShell()\n const filteredEnvVars = Object.entries(envVars).filter(\n ([, value]) => value !== undefined,\n ) as Array<[string, string]>\n\n let commandBlock: string\n\n switch (shell) {\n case \"powershell\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `$env:${key} = ${value}`)\n .join(\"; \")\n break\n }\n case \"cmd\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set ${key}=${value}`)\n .join(\" & \")\n break\n }\n case \"fish\": {\n commandBlock = filteredEnvVars\n .map(([key, value]) => `set -gx ${key} ${value}`)\n .join(\"; \")\n break\n }\n default: {\n // bash, zsh, sh\n const assignments = filteredEnvVars\n .map(([key, value]) => `${key}=${value}`)\n .join(\" \")\n commandBlock = filteredEnvVars.length > 0 ? `export ${assignments}` : \"\"\n break\n }\n }\n\n if (commandBlock && commandToRun) {\n const separator = shell === \"cmd\" ? \" & \" : \" && \"\n return `${commandBlock}${separator}${commandToRun}`\n }\n\n return commandBlock || commandToRun\n}\n","import type { Context, Next } from \"hono\"\r\n\r\nimport { state } from \"./state\"\r\n\r\n/**\r\n * Request context stored for logging on response\r\n */\r\nexport interface RequestContext {\r\n startTime: number\r\n model?: string\r\n inputTokens?: number\r\n outputTokens?: number\r\n provider?: \"Copilot\" | \"Azure OpenAI\"\r\n}\r\n\r\nconst REQUEST_CONTEXT_KEY = \"requestContext\"\r\n\r\n// ANSI color codes\r\nconst colors = {\r\n reset: \"\\x1b[0m\",\r\n dim: \"\\x1b[2m\",\r\n bold: \"\\x1b[1m\",\r\n cyan: \"\\x1b[36m\",\r\n green: \"\\x1b[32m\",\r\n yellow: \"\\x1b[33m\",\r\n red: \"\\x1b[31m\",\r\n magenta: \"\\x1b[35m\",\r\n blue: \"\\x1b[34m\",\r\n white: \"\\x1b[37m\",\r\n gray: \"\\x1b[90m\",\r\n}\r\n\r\n/**\r\n * Get the current time formatted as HH:MM:SS\r\n */\r\nfunction getTimeString(): string {\r\n return new Date().toLocaleTimeString(\"en-US\", {\r\n hour12: false,\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n second: \"2-digit\",\r\n })\r\n}\r\n\r\n/**\r\n * Get status color based on HTTP status code\r\n */\r\nfunction getStatusColor(status: number): string {\r\n if (status >= 500) return colors.red\r\n if (status >= 400) return colors.yellow\r\n if (status >= 300) return colors.cyan\r\n return colors.green\r\n}\r\n\r\n/**\r\n * Log raw HTTP request details (for debug mode)\r\n */\r\nasync function logRawRequest(c: Context): Promise<void> {\r\n const method = c.req.method\r\n const url = c.req.url\r\n const headers = Object.fromEntries(c.req.raw.headers.entries())\r\n\r\n const lines: string[] = []\r\n lines.push(`${colors.magenta}${colors.bold}[DEBUG] Incoming Request${colors.reset}`)\r\n lines.push(`${colors.cyan}${method}${colors.reset} ${url}`)\r\n lines.push(`${colors.dim}Headers:${colors.reset}`)\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n // Mask authorization headers\r\n const displayValue = key.toLowerCase().includes(\"authorization\")\r\n ? `${value.slice(0, 20)}...`\r\n : value\r\n lines.push(` ${colors.gray}${key}:${colors.reset} ${displayValue}`)\r\n }\r\n\r\n // Try to get body info without consuming it\r\n if (method !== \"GET\" && method !== \"HEAD\") {\r\n try {\r\n const clonedRequest = c.req.raw.clone()\r\n const body = await clonedRequest.text()\r\n if (body) {\r\n // Parse JSON to extract model, omit messages/prompt\r\n try {\r\n const parsed = JSON.parse(body)\r\n const sanitized: Record<string, unknown> = {}\r\n\r\n for (const [key, value] of Object.entries(parsed)) {\r\n if (key === \"messages\" || key === \"prompt\") {\r\n sanitized[key] = `[${Array.isArray(value) ? value.length : 1} items omitted]`\r\n } else {\r\n sanitized[key] = value\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}Body (sanitized):${colors.reset}`)\r\n lines.push(` ${JSON.stringify(sanitized, null, 2).split(\"\\n\").join(\"\\n \")}`)\r\n } catch {\r\n // Not JSON, show length\r\n lines.push(`${colors.dim}Body:${colors.reset} [${body.length} bytes]`)\r\n }\r\n }\r\n } catch {\r\n lines.push(`${colors.dim}Body:${colors.reset} [unable to read]`)\r\n }\r\n }\r\n\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n console.log(lines.join(\"\\n\"))\r\n}\r\n\r\n/**\r\n * Set request context for logging\r\n */\r\nexport function setRequestContext(\r\n c: Context,\r\n ctx: Partial<Omit<RequestContext, \"startTime\">>,\r\n): void {\r\n const existing = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n if (existing) {\r\n c.set(REQUEST_CONTEXT_KEY, { ...existing, ...ctx })\r\n }\r\n}\r\n\r\n/**\r\n * Custom request logger middleware\r\n */\r\nexport async function requestLogger(c: Context, next: Next): Promise<void> {\r\n // Log raw request in debug mode\r\n if (state.debug) {\r\n await logRawRequest(c)\r\n }\r\n\r\n const startTime = Date.now()\r\n const method = c.req.method\r\n const path =\r\n c.req.path +\r\n (c.req.raw.url.includes(\"?\") ? \"?\" + c.req.raw.url.split(\"?\")[1] : \"\")\r\n\r\n // Initialize request context\r\n c.set(REQUEST_CONTEXT_KEY, { startTime } as RequestContext)\r\n\r\n await next()\r\n\r\n // Get context that may have been set during request handling\r\n const ctx = c.get(REQUEST_CONTEXT_KEY) as RequestContext | undefined\r\n const duration = ((Date.now() - startTime) / 1000).toFixed(1)\r\n const status = c.res.status\r\n const statusColor = getStatusColor(status)\r\n\r\n // Build the log block\r\n const lines: string[] = []\r\n\r\n // Separator\r\n lines.push(`${colors.dim}${\"─\".repeat(60)}${colors.reset}`)\r\n\r\n // Main request line: method, path, status, duration\r\n const statusBadge = `${statusColor}${status}${colors.reset}`\r\n const durationStr = `${colors.cyan}${duration}s${colors.reset}`\r\n lines.push(\r\n `${colors.bold}${method}${colors.reset} ${path} ${statusBadge} ${durationStr}`,\r\n )\r\n\r\n // Provider and model info\r\n if (ctx?.provider && ctx?.model) {\r\n const providerColor =\r\n ctx.provider === \"Azure OpenAI\" ? colors.blue : colors.magenta\r\n lines.push(\r\n ` ${colors.gray}Provider:${colors.reset} ${providerColor}${ctx.provider}${colors.reset} ${colors.gray}->${colors.reset} ${colors.white}${ctx.model}${colors.reset}`,\r\n )\r\n }\r\n\r\n // Token info\r\n if (ctx?.inputTokens !== undefined || ctx?.outputTokens !== undefined) {\r\n const tokenParts: string[] = []\r\n if (ctx.inputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Input:${colors.reset} ${colors.yellow}${ctx.inputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n if (ctx.outputTokens !== undefined) {\r\n tokenParts.push(\r\n `${colors.gray}Output:${colors.reset} ${colors.green}${ctx.outputTokens.toLocaleString()}${colors.reset}`,\r\n )\r\n }\r\n lines.push(` ${tokenParts.join(\" \")}`)\r\n }\r\n\r\n // Timestamp\r\n lines.push(` ${colors.dim}${getTimeString()}${colors.reset}`)\r\n\r\n // Print all lines\r\n console.log(lines.join(\"\\n\"))\r\n}\r\n","import consola from \"consola\"\n\nimport { HTTPError } from \"./error\"\n\nexport const awaitApproval = async () => {\n const response = await consola.prompt(`Accept incoming request?`, {\n type: \"confirm\",\n })\n\n if (!response)\n throw new HTTPError(\n \"Request rejected\",\n Response.json({ message: \"Request rejected\" }, { status: 403 }),\n )\n}\n","/**\r\n * Normalize a model name by converting dashes to dots between numbers.\r\n * e.g., \"claude-opus-4-5\" -> \"claude-opus-4.5\"\r\n * \"gpt-4-1\" -> \"gpt-4.1\"\r\n * \"gpt-5-1-codex\" -> \"gpt-5.1-codex\"\r\n */\r\nexport function normalizeModelName(model: string): string {\r\n // Replace dash with dot only between two digits: \"4-5\" -> \"4.5\"\r\n return model.replace(/(\\d)-(\\d)/g, (_, p1, p2) => `${p1}.${p2}`)\r\n}\r\n","import consola from \"consola\"\n\nimport type { State } from \"./state\"\n\nimport { HTTPError } from \"./error\"\nimport { sleep } from \"./utils\"\n\nexport async function checkRateLimit(state: State) {\n if (state.rateLimitSeconds === undefined) return\n\n const now = Date.now()\n\n if (!state.lastRequestTimestamp) {\n state.lastRequestTimestamp = now\n return\n }\n\n const elapsedSeconds = (now - state.lastRequestTimestamp) / 1000\n\n if (elapsedSeconds > state.rateLimitSeconds) {\n state.lastRequestTimestamp = now\n return\n }\n\n const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds)\n\n if (!state.rateLimitWait) {\n consola.warn(\n `Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`,\n )\n throw new HTTPError(\n \"Rate limit exceeded\",\n Response.json({ message: \"Rate limit exceeded\" }, { status: 429 }),\n )\n }\n\n const waitTimeMs = waitTimeSeconds * 1000\n consola.warn(\n `Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`,\n )\n await sleep(waitTimeMs)\n // eslint-disable-next-line require-atomic-updates\n state.lastRequestTimestamp = now\n consola.info(\"Rate limit wait completed, proceeding with request\")\n return\n}\n","import type {\n ChatCompletionsPayload,\n ContentPart,\n Message,\n Tool,\n ToolCall,\n} from \"~/services/copilot/create-chat-completions\"\nimport type { Model } from \"~/services/copilot/get-models\"\n\n// Encoder type mapping\nconst ENCODING_MAP = {\n o200k_base: () => import(\"gpt-tokenizer/encoding/o200k_base\"),\n cl100k_base: () => import(\"gpt-tokenizer/encoding/cl100k_base\"),\n p50k_base: () => import(\"gpt-tokenizer/encoding/p50k_base\"),\n p50k_edit: () => import(\"gpt-tokenizer/encoding/p50k_edit\"),\n r50k_base: () => import(\"gpt-tokenizer/encoding/r50k_base\"),\n} as const\n\ntype SupportedEncoding = keyof typeof ENCODING_MAP\n\n// Define encoder interface\ninterface Encoder {\n encode: (text: string) => Array<number>\n}\n\n// Cache loaded encoders to avoid repeated imports\nconst encodingCache = new Map<string, Encoder>()\n\n/**\n * Calculate tokens for tool calls\n */\nconst calculateToolCallsTokens = (\n toolCalls: Array<ToolCall>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = 0\n for (const toolCall of toolCalls) {\n tokens += constants.funcInit\n tokens += encoder.encode(JSON.stringify(toolCall)).length\n }\n tokens += constants.funcEnd\n return tokens\n}\n\n/**\n * Calculate tokens for content parts\n */\nconst calculateContentPartsTokens = (\n contentParts: Array<ContentPart>,\n encoder: Encoder,\n): number => {\n let tokens = 0\n for (const part of contentParts) {\n if (part.type === \"image_url\") {\n tokens += encoder.encode(part.image_url.url).length + 85\n } else if (part.text) {\n tokens += encoder.encode(part.text).length\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens for a single message\n */\nconst calculateMessageTokens = (\n message: Message,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n const tokensPerMessage = 3\n const tokensPerName = 1\n let tokens = tokensPerMessage\n for (const [key, value] of Object.entries(message)) {\n if (typeof value === \"string\") {\n tokens += encoder.encode(value).length\n }\n if (key === \"name\") {\n tokens += tokensPerName\n }\n if (key === \"tool_calls\") {\n tokens += calculateToolCallsTokens(\n value as Array<ToolCall>,\n encoder,\n constants,\n )\n }\n if (key === \"content\" && Array.isArray(value)) {\n tokens += calculateContentPartsTokens(\n value as Array<ContentPart>,\n encoder,\n )\n }\n }\n return tokens\n}\n\n/**\n * Calculate tokens using custom algorithm\n */\nconst calculateTokens = (\n messages: Array<Message>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (messages.length === 0) {\n return 0\n }\n let numTokens = 0\n for (const message of messages) {\n numTokens += calculateMessageTokens(message, encoder, constants)\n }\n // every reply is primed with <|start|>assistant<|message|>\n numTokens += 3\n return numTokens\n}\n\n/**\n * Get the corresponding encoder module based on encoding type\n */\nconst getEncodeChatFunction = async (encoding: string): Promise<Encoder> => {\n if (encodingCache.has(encoding)) {\n const cached = encodingCache.get(encoding)\n if (cached) {\n return cached\n }\n }\n\n const supportedEncoding = encoding as SupportedEncoding\n if (!(supportedEncoding in ENCODING_MAP)) {\n const fallbackModule = (await ENCODING_MAP.o200k_base()) as Encoder\n encodingCache.set(encoding, fallbackModule)\n return fallbackModule\n }\n\n const encodingModule = (await ENCODING_MAP[supportedEncoding]()) as Encoder\n encodingCache.set(encoding, encodingModule)\n return encodingModule\n}\n\n/**\n * Get tokenizer type from model information\n */\nexport const getTokenizerFromModel = (model: Model): string => {\n return model.capabilities.tokenizer || \"o200k_base\"\n}\n\n/**\n * Get model-specific constants for token calculation\n */\nconst getModelConstants = (model: Model) => {\n return model.id === \"gpt-3.5-turbo\" || model.id === \"gpt-4\" ?\n {\n funcInit: 10,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n : {\n funcInit: 7,\n propInit: 3,\n propKey: 3,\n enumInit: -3,\n enumItem: 3,\n funcEnd: 12,\n }\n}\n\n/**\n * Calculate tokens for a single parameter\n */\nconst calculateParameterTokens = (\n key: string,\n prop: unknown,\n context: {\n encoder: Encoder\n constants: ReturnType<typeof getModelConstants>\n },\n): number => {\n const { encoder, constants } = context\n let tokens = constants.propKey\n\n // Early return if prop is not an object\n if (typeof prop !== \"object\" || prop === null) {\n return tokens\n }\n\n // Type assertion for parameter properties\n const param = prop as {\n type?: string\n description?: string\n enum?: Array<unknown>\n [key: string]: unknown\n }\n\n const paramName = key\n const paramType = param.type || \"string\"\n let paramDesc = param.description || \"\"\n\n // Handle enum values\n if (param.enum && Array.isArray(param.enum)) {\n tokens += constants.enumInit\n for (const item of param.enum) {\n tokens += constants.enumItem\n tokens += encoder.encode(String(item)).length\n }\n }\n\n // Clean up description\n if (paramDesc.endsWith(\".\")) {\n paramDesc = paramDesc.slice(0, -1)\n }\n\n // Encode the main parameter line\n const line = `${paramName}:${paramType}:${paramDesc}`\n tokens += encoder.encode(line).length\n\n // Handle additional properties (excluding standard ones)\n const excludedKeys = new Set([\"type\", \"description\", \"enum\"])\n for (const propertyName of Object.keys(param)) {\n if (!excludedKeys.has(propertyName)) {\n const propertyValue = param[propertyName]\n const propertyText =\n typeof propertyValue === \"string\" ? propertyValue : (\n JSON.stringify(propertyValue)\n )\n tokens += encoder.encode(`${propertyName}:${propertyText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for function parameters\n */\nconst calculateParametersTokens = (\n parameters: unknown,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n if (!parameters || typeof parameters !== \"object\") {\n return 0\n }\n\n const params = parameters as Record<string, unknown>\n let tokens = 0\n\n for (const [key, value] of Object.entries(params)) {\n if (key === \"properties\") {\n const properties = value as Record<string, unknown>\n if (Object.keys(properties).length > 0) {\n tokens += constants.propInit\n for (const propKey of Object.keys(properties)) {\n tokens += calculateParameterTokens(propKey, properties[propKey], {\n encoder,\n constants,\n })\n }\n }\n } else {\n const paramText =\n typeof value === \"string\" ? value : JSON.stringify(value)\n tokens += encoder.encode(`${key}:${paramText}`).length\n }\n }\n\n return tokens\n}\n\n/**\n * Calculate tokens for a single tool\n */\nconst calculateToolTokens = (\n tool: Tool,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let tokens = constants.funcInit\n const func = tool.function\n const fName = func.name\n let fDesc = func.description || \"\"\n if (fDesc.endsWith(\".\")) {\n fDesc = fDesc.slice(0, -1)\n }\n const line = fName + \":\" + fDesc\n tokens += encoder.encode(line).length\n if (\n typeof func.parameters === \"object\" // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n && func.parameters !== null\n ) {\n tokens += calculateParametersTokens(func.parameters, encoder, constants)\n }\n return tokens\n}\n\n/**\n * Calculate token count for tools based on model\n */\nexport const numTokensForTools = (\n tools: Array<Tool>,\n encoder: Encoder,\n constants: ReturnType<typeof getModelConstants>,\n): number => {\n let funcTokenCount = 0\n for (const tool of tools) {\n funcTokenCount += calculateToolTokens(tool, encoder, constants)\n }\n funcTokenCount += constants.funcEnd\n return funcTokenCount\n}\n\n/**\n * Calculate the token count of messages, supporting multiple GPT encoders\n */\nexport const getTokenCount = async (\n payload: ChatCompletionsPayload,\n model: Model,\n): Promise<{ input: number; output: number }> => {\n // Get tokenizer string\n const tokenizer = getTokenizerFromModel(model)\n\n // Get corresponding encoder module\n const encoder = await getEncodeChatFunction(tokenizer)\n\n const simplifiedMessages = payload.messages\n const inputMessages = simplifiedMessages.filter(\n (msg) => msg.role !== \"assistant\",\n )\n const outputMessages = simplifiedMessages.filter(\n (msg) => msg.role === \"assistant\",\n )\n\n const constants = getModelConstants(model)\n let inputTokens = calculateTokens(inputMessages, encoder, constants)\n if (payload.tools && payload.tools.length > 0) {\n inputTokens += numTokensForTools(payload.tools, encoder, constants)\n }\n const outputTokens = calculateTokens(outputMessages, encoder, constants)\n\n return {\n input: inputTokens,\n output: outputTokens,\n }\n}\n\n/**\n * Estimate token count for a payload without model info (uses o200k_base encoding)\n * This is a rough estimate used when we don't have model-specific info\n */\nexport const estimateTokenCount = async (\n payload: ChatCompletionsPayload,\n): Promise<number> => {\n const encoder = await getEncodeChatFunction(\"o200k_base\")\n\n // Simple estimation: encode all message content\n let tokens = 0\n for (const message of payload.messages) {\n // 3 tokens per message overhead\n tokens += 3\n\n if (typeof message.content === \"string\") {\n tokens += encoder.encode(message.content).length\n } else if (Array.isArray(message.content)) {\n for (const part of message.content) {\n if (part.type === \"text\" && part.text) {\n tokens += encoder.encode(part.text).length\n } else if (part.type === \"image_url\") {\n // Rough estimate for images\n tokens += 85\n }\n }\n }\n\n // Add role tokens\n if (message.role) {\n tokens += encoder.encode(message.role).length\n }\n\n // Tool calls in messages (assistant responses with tool use)\n if (message.tool_calls) {\n tokens += encoder.encode(JSON.stringify(message.tool_calls)).length\n }\n }\n\n // Add tool definitions if present (but don't double count - use simplified estimate)\n // Tool definitions add overhead but the full JSON stringify overcounts\n if (payload.tools && payload.tools.length > 0) {\n // Estimate ~50 tokens per tool on average for function name + description + params\n tokens += payload.tools.length * 50\n }\n\n // Priming tokens\n tokens += 3\n\n return tokens\n}\n","import consola from \"consola\"\r\nimport { events } from \"fetch-event-stream\"\r\n\r\nimport { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createChatCompletions = async (\r\n payload: ChatCompletionsPayload,\r\n) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const enableVision = payload.messages.some(\r\n (x) =>\r\n typeof x.content !== \"string\"\r\n && x.content?.some((x) => x.type === \"image_url\"),\r\n )\r\n\r\n // Agent/user check for X-Initiator header\r\n // Determine if any message is from an agent (\"assistant\" or \"tool\")\r\n const isAgentCall = payload.messages.some((msg) =>\r\n [\"assistant\", \"tool\"].includes(msg.role),\r\n )\r\n\r\n // Build headers and add X-Initiator\r\n const headers: Record<string, string> = {\r\n ...copilotHeaders(state, enableVision),\r\n \"X-Initiator\": isAgentCall ? \"agent\" : \"user\",\r\n }\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/chat/completions`, {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) {\r\n consola.error(\"Failed to create chat completions\", response)\r\n throw new HTTPError(\"Failed to create chat completions\", response)\r\n }\r\n\r\n if (payload.stream) {\r\n return events(response)\r\n }\r\n\r\n return (await response.json()) as ChatCompletionResponse\r\n}\r\n\r\n// Streaming types\r\n\r\nexport interface ChatCompletionChunk {\r\n id: string\r\n object: \"chat.completion.chunk\"\r\n created: number\r\n model: string\r\n choices: Array<Choice>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n completion_tokens_details?: {\r\n accepted_prediction_tokens: number\r\n rejected_prediction_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface Delta {\r\n content?: string | null\r\n role?: \"user\" | \"assistant\" | \"system\" | \"tool\"\r\n tool_calls?: Array<{\r\n index: number\r\n id?: string\r\n type?: \"function\"\r\n function?: {\r\n name?: string\r\n arguments?: string\r\n }\r\n }>\r\n}\r\n\r\ninterface Choice {\r\n index: number\r\n delta: Delta\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null\r\n logprobs: object | null\r\n}\r\n\r\n// Non-streaming types\r\n\r\nexport interface ChatCompletionResponse {\r\n id: string\r\n object: \"chat.completion\"\r\n created: number\r\n model: string\r\n choices: Array<ChoiceNonStreaming>\r\n system_fingerprint?: string\r\n usage?: {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n total_tokens: number\r\n prompt_tokens_details?: {\r\n cached_tokens: number\r\n }\r\n }\r\n}\r\n\r\ninterface ResponseMessage {\r\n role: \"assistant\"\r\n content: string | null\r\n tool_calls?: Array<ToolCall>\r\n}\r\n\r\ninterface ChoiceNonStreaming {\r\n index: number\r\n message: ResponseMessage\r\n logprobs: object | null\r\n finish_reason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\"\r\n}\r\n\r\n// Payload types\r\n\r\nexport interface ChatCompletionsPayload {\r\n messages: Array<Message>\r\n model: string\r\n temperature?: number | null\r\n top_p?: number | null\r\n max_tokens?: number | null\r\n stop?: string | Array<string> | null\r\n n?: number | null\r\n stream?: boolean | null\r\n stream_options?: { include_usage?: boolean } | null\r\n\r\n frequency_penalty?: number | null\r\n presence_penalty?: number | null\r\n logit_bias?: Record<string, number> | null\r\n logprobs?: boolean | null\r\n response_format?: { type: \"json_object\" } | null\r\n seed?: number | null\r\n tools?: Array<Tool> | null\r\n tool_choice?:\r\n | \"none\"\r\n | \"auto\"\r\n | \"required\"\r\n | { type: \"function\"; function: { name: string } }\r\n | null\r\n user?: string | null\r\n}\r\n\r\nexport interface Tool {\r\n type: \"function\"\r\n function: {\r\n name: string\r\n description?: string\r\n parameters: Record<string, unknown>\r\n }\r\n}\r\n\r\nexport interface Message {\r\n role: \"user\" | \"assistant\" | \"system\" | \"tool\" | \"developer\"\r\n content: string | Array<ContentPart> | null\r\n\r\n name?: string\r\n tool_calls?: Array<ToolCall>\r\n tool_call_id?: string\r\n}\r\n\r\nexport interface ToolCall {\r\n id: string\r\n type: \"function\"\r\n function: {\r\n name: string\r\n arguments: string\r\n }\r\n}\r\n\r\nexport type ContentPart = TextPart | ImagePart\r\n\r\nexport interface TextPart {\r\n type: \"text\"\r\n text: string\r\n}\r\n\r\nexport interface ImagePart {\r\n type: \"image_url\"\r\n image_url: {\r\n url: string\r\n detail?: \"low\" | \"high\" | \"auto\"\r\n }\r\n}\r\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE, type SSEMessage } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport { getTokenCount } from \"~/lib/tokenizer\"\r\nimport { isNullish } from \"~/lib/utils\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n type ChatCompletionsPayload,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const rawPayload = await c.req.json<ChatCompletionsPayload>()\r\n\r\n // Apply auto-replacements to the payload\r\n // eslint-disable-next-line require-atomic-updates\r\n let payload = await applyReplacementsToPayload(rawPayload)\r\n\r\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5)\r\n payload = {\r\n ...payload,\r\n model: normalizeModelName(payload.model),\r\n }\r\n\r\n consola.debug(\"Request payload:\", JSON.stringify(payload).slice(-400))\r\n\r\n // Check if this is an Azure OpenAI model\r\n if (isAzureOpenAIModel(payload.model)) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n\r\n setRequestContext(c, { provider: \"Azure OpenAI\", model: payload.model })\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n const response = await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig,\r\n payload,\r\n )\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n }\r\n\r\n setRequestContext(c, { provider: \"Copilot\", model: payload.model })\r\n\r\n // Find the selected model\r\n const selectedModel = state.models?.data.find(\r\n (model) => model.id === payload.model,\r\n )\r\n\r\n // Calculate and display token count\r\n try {\r\n if (selectedModel) {\r\n const tokenCount = await getTokenCount(payload, selectedModel)\r\n setRequestContext(c, { inputTokens: tokenCount.input })\r\n }\r\n } catch (error) {\r\n consola.warn(\"Failed to calculate token count:\", error)\r\n }\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n if (isNullish(payload.max_tokens)) {\r\n payload = {\r\n ...payload,\r\n max_tokens: selectedModel?.capabilities.limits.max_output_tokens,\r\n }\r\n consola.debug(\"Set max_tokens to:\", JSON.stringify(payload.max_tokens))\r\n }\r\n\r\n const response = await createChatCompletions(payload)\r\n\r\n if (isNonStreaming(response)) {\r\n consola.debug(\"Non-streaming response:\", JSON.stringify(response))\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n return c.json(response)\r\n }\r\n\r\n consola.debug(\"Streaming response\")\r\n return streamSSE(c, async (stream) => {\r\n for await (const chunk of response) {\r\n consola.debug(\"Streaming chunk:\", JSON.stringify(chunk))\r\n // Capture usage from final chunk if available\r\n if (chunk.data && chunk.data !== \"[DONE]\") {\r\n const parsed = JSON.parse(chunk.data) as ChatCompletionChunk\r\n if (parsed.usage) {\r\n setRequestContext(c, {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n })\r\n }\r\n }\r\n await stream.writeSSE(chunk as SSEMessage)\r\n }\r\n })\r\n}\r\n\r\nconst isNonStreaming = (\r\n response: Awaited<ReturnType<typeof createChatCompletions>>,\r\n): response is ChatCompletionResponse => Object.hasOwn(response, \"choices\")\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCompletion } from \"./handler\"\n\nexport const completionRoutes = new Hono()\n\ncompletionRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { copilotHeaders, copilotBaseUrl } from \"~/lib/api-config\"\r\nimport { HTTPError } from \"~/lib/error\"\r\nimport { fetchWithRetry } from \"~/lib/retry-fetch\"\r\nimport { state } from \"~/lib/state\"\r\n\r\nexport const createEmbeddings = async (payload: EmbeddingRequest) => {\r\n if (!state.copilotToken) throw new Error(\"Copilot token not found\")\r\n\r\n const response = await fetchWithRetry(`${copilotBaseUrl(state)}/embeddings`, {\r\n method: \"POST\",\r\n headers: copilotHeaders(state),\r\n body: JSON.stringify(payload),\r\n })\r\n\r\n if (!response.ok) throw new HTTPError(\"Failed to create embeddings\", response)\r\n\r\n return (await response.json()) as EmbeddingResponse\r\n}\r\n\r\nexport interface EmbeddingRequest {\r\n input: string | Array<string>\r\n model: string\r\n}\r\n\r\nexport interface Embedding {\r\n object: string\r\n embedding: Array<number>\r\n index: number\r\n}\r\n\r\nexport interface EmbeddingResponse {\r\n object: string\r\n data: Array<Embedding>\r\n model: string\r\n usage: {\r\n prompt_tokens: number\r\n total_tokens: number\r\n }\r\n}\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport {\n createEmbeddings,\n type EmbeddingRequest,\n} from \"~/services/copilot/create-embeddings\"\n\nexport const embeddingRoutes = new Hono()\n\nembeddingRoutes.post(\"/\", async (c) => {\n try {\n const paylod = await c.req.json<EmbeddingRequest>()\n const response = await createEmbeddings(paylod)\n\n return c.json(response)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { type AnthropicResponse } from \"./anthropic-types\"\n\nexport function mapOpenAIStopReasonToAnthropic(\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null,\n): AnthropicResponse[\"stop_reason\"] {\n if (finishReason === null) {\n return null\n }\n const stopReasonMap = {\n stop: \"end_turn\",\n length: \"max_tokens\",\n tool_calls: \"tool_use\",\n content_filter: \"end_turn\",\n } as const\n return stopReasonMap[finishReason]\n}\n","import {\r\n type ChatCompletionResponse,\r\n type ChatCompletionsPayload,\r\n type ContentPart,\r\n type Message,\r\n type TextPart,\r\n type Tool,\r\n type ToolCall,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicAssistantContentBlock,\r\n type AnthropicAssistantMessage,\r\n type AnthropicMessage,\r\n type AnthropicMessagesPayload,\r\n type AnthropicResponse,\r\n type AnthropicTextBlock,\r\n type AnthropicThinkingBlock,\r\n type AnthropicTool,\r\n type AnthropicToolResultBlock,\r\n type AnthropicToolUseBlock,\r\n type AnthropicUserContentBlock,\r\n type AnthropicUserMessage,\r\n} from \"./anthropic-types\"\r\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\r\n\r\n// Payload translation\r\n\r\nexport function translateToOpenAI(\r\n payload: AnthropicMessagesPayload,\r\n): ChatCompletionsPayload {\r\n return {\r\n model: translateModelName(payload.model),\r\n messages: translateAnthropicMessagesToOpenAI(\r\n payload.messages,\r\n payload.system,\r\n ),\r\n max_tokens: payload.max_tokens,\r\n stop: payload.stop_sequences,\r\n stream: payload.stream,\r\n temperature: payload.temperature,\r\n top_p: payload.top_p,\r\n user: payload.metadata?.user_id,\r\n tools: translateAnthropicToolsToOpenAI(payload.tools),\r\n tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),\r\n }\r\n}\r\n\r\nfunction translateModelName(model: string): string {\r\n // Subagent requests use a specific dated model which Copilot doesn't support\r\n // e.g., claude-sonnet-4-20250514 -> claude-sonnet-4\r\n // But preserve version numbers like claude-opus-4-5 (normalized to claude-opus-4.5 later)\r\n if (model.match(/^claude-sonnet-4-\\d{8}/)) {\r\n return \"claude-sonnet-4\"\r\n } else if (model.match(/^claude-opus-4-\\d{8}/)) {\r\n return \"claude-opus-4\"\r\n }\r\n return model\r\n}\r\n\r\nfunction translateAnthropicMessagesToOpenAI(\r\n anthropicMessages: Array<AnthropicMessage>,\r\n system: string | Array<AnthropicTextBlock> | undefined,\r\n): Array<Message> {\r\n const systemMessages = handleSystemPrompt(system)\r\n\r\n const otherMessages = anthropicMessages.flatMap((message) =>\r\n message.role === \"user\" ?\r\n handleUserMessage(message)\r\n : handleAssistantMessage(message),\r\n )\r\n\r\n return [...systemMessages, ...otherMessages]\r\n}\r\n\r\nfunction handleSystemPrompt(\r\n system: string | Array<AnthropicTextBlock> | undefined,\r\n): Array<Message> {\r\n if (!system) {\r\n return []\r\n }\r\n\r\n if (typeof system === \"string\") {\r\n return [{ role: \"system\", content: system }]\r\n } else {\r\n const systemText = system.map((block) => block.text).join(\"\\n\\n\")\r\n return [{ role: \"system\", content: systemText }]\r\n }\r\n}\r\n\r\nfunction handleUserMessage(message: AnthropicUserMessage): Array<Message> {\r\n const newMessages: Array<Message> = []\r\n\r\n if (Array.isArray(message.content)) {\r\n const toolResultBlocks = message.content.filter(\r\n (block): block is AnthropicToolResultBlock =>\r\n block.type === \"tool_result\",\r\n )\r\n const otherBlocks = message.content.filter(\r\n (block) => block.type !== \"tool_result\",\r\n )\r\n\r\n // Tool results must come first to maintain protocol: tool_use -> tool_result -> user\r\n for (const block of toolResultBlocks) {\r\n newMessages.push({\r\n role: \"tool\",\r\n tool_call_id: block.tool_use_id,\r\n content: mapContent(block.content),\r\n })\r\n }\r\n\r\n if (otherBlocks.length > 0) {\r\n newMessages.push({\r\n role: \"user\",\r\n content: mapContent(otherBlocks),\r\n })\r\n }\r\n } else {\r\n newMessages.push({\r\n role: \"user\",\r\n content: mapContent(message.content),\r\n })\r\n }\r\n\r\n return newMessages\r\n}\r\n\r\nfunction handleAssistantMessage(\r\n message: AnthropicAssistantMessage,\r\n): Array<Message> {\r\n if (!Array.isArray(message.content)) {\r\n return [\r\n {\r\n role: \"assistant\",\r\n content: mapContent(message.content),\r\n },\r\n ]\r\n }\r\n\r\n const toolUseBlocks = message.content.filter(\r\n (block): block is AnthropicToolUseBlock => block.type === \"tool_use\",\r\n )\r\n\r\n const textBlocks = message.content.filter(\r\n (block): block is AnthropicTextBlock => block.type === \"text\",\r\n )\r\n\r\n const thinkingBlocks = message.content.filter(\r\n (block): block is AnthropicThinkingBlock => block.type === \"thinking\",\r\n )\r\n\r\n // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks\r\n const allTextContent = [\r\n ...textBlocks.map((b) => b.text),\r\n ...thinkingBlocks.map((b) => b.thinking),\r\n ].join(\"\\n\\n\")\r\n\r\n return toolUseBlocks.length > 0 ?\r\n [\r\n {\r\n role: \"assistant\",\r\n content: allTextContent || null,\r\n tool_calls: toolUseBlocks.map((toolUse) => ({\r\n id: toolUse.id,\r\n type: \"function\",\r\n function: {\r\n name: toolUse.name,\r\n arguments: JSON.stringify(toolUse.input),\r\n },\r\n })),\r\n },\r\n ]\r\n : [\r\n {\r\n role: \"assistant\",\r\n content: mapContent(message.content),\r\n },\r\n ]\r\n}\r\n\r\nfunction mapContent(\r\n content:\r\n | string\r\n | Array<AnthropicUserContentBlock | AnthropicAssistantContentBlock>,\r\n): string | Array<ContentPart> | null {\r\n if (typeof content === \"string\") {\r\n return content\r\n }\r\n if (!Array.isArray(content)) {\r\n return null\r\n }\r\n\r\n const hasImage = content.some((block) => block.type === \"image\")\r\n if (!hasImage) {\r\n return content\r\n .filter(\r\n (block): block is AnthropicTextBlock | AnthropicThinkingBlock =>\r\n block.type === \"text\" || block.type === \"thinking\",\r\n )\r\n .map((block) => (block.type === \"text\" ? block.text : block.thinking))\r\n .join(\"\\n\\n\")\r\n }\r\n\r\n const contentParts: Array<ContentPart> = []\r\n for (const block of content) {\r\n switch (block.type) {\r\n case \"text\": {\r\n contentParts.push({ type: \"text\", text: block.text })\r\n\r\n break\r\n }\r\n case \"thinking\": {\r\n contentParts.push({ type: \"text\", text: block.thinking })\r\n\r\n break\r\n }\r\n case \"image\": {\r\n contentParts.push({\r\n type: \"image_url\",\r\n image_url: {\r\n url: `data:${block.source.media_type};base64,${block.source.data}`,\r\n },\r\n })\r\n\r\n break\r\n }\r\n // No default\r\n }\r\n }\r\n return contentParts\r\n}\r\n\r\nfunction translateAnthropicToolsToOpenAI(\r\n anthropicTools: Array<AnthropicTool> | undefined,\r\n): Array<Tool> | undefined {\r\n if (!anthropicTools) {\r\n return undefined\r\n }\r\n return anthropicTools.map((tool) => ({\r\n type: \"function\",\r\n function: {\r\n name: tool.name,\r\n description: tool.description,\r\n parameters: tool.input_schema,\r\n },\r\n }))\r\n}\r\n\r\nfunction translateAnthropicToolChoiceToOpenAI(\r\n anthropicToolChoice: AnthropicMessagesPayload[\"tool_choice\"],\r\n): ChatCompletionsPayload[\"tool_choice\"] {\r\n if (!anthropicToolChoice) {\r\n return undefined\r\n }\r\n\r\n switch (anthropicToolChoice.type) {\r\n case \"auto\": {\r\n return \"auto\"\r\n }\r\n case \"any\": {\r\n return \"required\"\r\n }\r\n case \"tool\": {\r\n if (anthropicToolChoice.name) {\r\n return {\r\n type: \"function\",\r\n function: { name: anthropicToolChoice.name },\r\n }\r\n }\r\n return undefined\r\n }\r\n case \"none\": {\r\n return \"none\"\r\n }\r\n default: {\r\n return undefined\r\n }\r\n }\r\n}\r\n\r\n// Response translation\r\n\r\nexport function translateToAnthropic(\r\n response: ChatCompletionResponse,\r\n originalModel?: string,\r\n): AnthropicResponse {\r\n // Merge content from all choices\r\n const allTextBlocks: Array<AnthropicTextBlock> = []\r\n const allToolUseBlocks: Array<AnthropicToolUseBlock> = []\r\n let stopReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\" | null =\r\n null // default\r\n stopReason = response.choices[0]?.finish_reason ?? stopReason\r\n\r\n // Process all choices to extract text and tool use blocks\r\n for (const choice of response.choices) {\r\n const textBlocks = getAnthropicTextBlocks(choice.message.content)\r\n const toolUseBlocks = getAnthropicToolUseBlocks(choice.message.tool_calls)\r\n\r\n allTextBlocks.push(...textBlocks)\r\n allToolUseBlocks.push(...toolUseBlocks)\r\n\r\n // Use the finish_reason from the first choice, or prioritize tool_calls\r\n if (choice.finish_reason === \"tool_calls\" || stopReason === \"stop\") {\r\n stopReason = choice.finish_reason\r\n }\r\n }\r\n\r\n // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses\r\n\r\n return {\r\n id: response.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? response.model,\r\n content: [...allTextBlocks, ...allToolUseBlocks],\r\n stop_reason: mapOpenAIStopReasonToAnthropic(stopReason),\r\n stop_sequence: null,\r\n usage: {\r\n input_tokens:\r\n (response.usage?.prompt_tokens ?? 0)\r\n - (response.usage?.prompt_tokens_details?.cached_tokens ?? 0),\r\n output_tokens: response.usage?.completion_tokens ?? 0,\r\n ...(response.usage?.prompt_tokens_details?.cached_tokens\r\n !== undefined && {\r\n cache_read_input_tokens:\r\n response.usage.prompt_tokens_details.cached_tokens,\r\n }),\r\n },\r\n }\r\n}\r\n\r\nfunction getAnthropicTextBlocks(\r\n messageContent: Message[\"content\"],\r\n): Array<AnthropicTextBlock> {\r\n if (typeof messageContent === \"string\") {\r\n return [{ type: \"text\", text: messageContent }]\r\n }\r\n\r\n if (Array.isArray(messageContent)) {\r\n return messageContent\r\n .filter((part): part is TextPart => part.type === \"text\")\r\n .map((part) => ({ type: \"text\", text: part.text }))\r\n }\r\n\r\n return []\r\n}\r\n\r\nfunction getAnthropicToolUseBlocks(\r\n toolCalls: Array<ToolCall> | undefined,\r\n): Array<AnthropicToolUseBlock> {\r\n if (!toolCalls) {\r\n return []\r\n }\r\n return toolCalls.map((toolCall) => ({\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: JSON.parse(toolCall.function.arguments) as Record<string, unknown>,\r\n }))\r\n}\r\n","import type { Context } from \"hono\"\n\nimport consola from \"consola\"\n\nimport { normalizeModelName } from \"~/lib/model-resolver\"\nimport { state } from \"~/lib/state\"\nimport { getTokenCount } from \"~/lib/tokenizer\"\n\nimport { type AnthropicMessagesPayload } from \"./anthropic-types\"\nimport { translateToOpenAI } from \"./non-stream-translation\"\n\n/**\n * Handles token counting for Anthropic messages\n */\nexport async function handleCountTokens(c: Context) {\n try {\n const anthropicBeta = c.req.header(\"anthropic-beta\")\n\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\n\n const openAIPayload = translateToOpenAI(anthropicPayload)\n\n // Normalize model name (e.g., claude-opus-4-5 -> claude-opus-4.5) before lookup\n const normalizedModel = normalizeModelName(anthropicPayload.model)\n\n const selectedModel = state.models?.data.find(\n (model) => model.id === normalizedModel,\n )\n\n if (!selectedModel) {\n consola.warn(\"Model not found, returning default token count\")\n return c.json({\n input_tokens: 1,\n })\n }\n\n const tokenCount = await getTokenCount(openAIPayload, selectedModel)\n\n if (anthropicPayload.tools && anthropicPayload.tools.length > 0) {\n let mcpToolExist = false\n if (anthropicBeta?.startsWith(\"claude-code\")) {\n mcpToolExist = anthropicPayload.tools.some((tool) =>\n tool.name.startsWith(\"mcp__\"),\n )\n }\n if (!mcpToolExist) {\n if (anthropicPayload.model.startsWith(\"claude\")) {\n // https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview#pricing\n tokenCount.input = tokenCount.input + 346\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n tokenCount.input = tokenCount.input + 480\n }\n }\n }\n\n let finalTokenCount = tokenCount.input + tokenCount.output\n if (anthropicPayload.model.startsWith(\"claude\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.15)\n } else if (anthropicPayload.model.startsWith(\"grok\")) {\n finalTokenCount = Math.round(finalTokenCount * 1.03)\n }\n\n consola.info(\"Token count:\", finalTokenCount)\n\n return c.json({\n input_tokens: finalTokenCount,\n })\n } catch (error) {\n consola.error(\"Error counting tokens:\", error)\n return c.json({\n input_tokens: 1,\n })\n }\n}\n","import {\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicStreamEventData,\r\n type AnthropicStreamState,\r\n} from \"./anthropic-types\"\r\nimport { mapOpenAIStopReasonToAnthropic } from \"./utils\"\r\n\r\nfunction isToolBlockOpen(state: AnthropicStreamState): boolean {\r\n if (!state.contentBlockOpen) {\r\n return false\r\n }\r\n // Check if the current block index corresponds to any known tool call\r\n return Object.values(state.toolCalls).some(\r\n (tc) => tc.anthropicBlockIndex === state.contentBlockIndex,\r\n )\r\n}\r\n\r\n// Helper to create message_delta and message_stop events\r\nfunction createMessageDeltaEvents(\r\n finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\",\r\n usage: { prompt_tokens: number; completion_tokens: number; cached_tokens: number },\r\n): Array<AnthropicStreamEventData> {\r\n return [\r\n {\r\n type: \"message_delta\",\r\n delta: {\r\n stop_reason: mapOpenAIStopReasonToAnthropic(finishReason),\r\n stop_sequence: null,\r\n },\r\n usage: {\r\n input_tokens: usage.prompt_tokens,\r\n output_tokens: usage.completion_tokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: usage.cached_tokens,\r\n },\r\n },\r\n {\r\n type: \"message_stop\",\r\n },\r\n ]\r\n}\r\n\r\n// Export for use in handler fallback\r\nexport function createFallbackMessageDeltaEvents(\r\n state: AnthropicStreamState,\r\n): Array<AnthropicStreamEventData> {\r\n // If message_delta was already sent, return empty\r\n if (state.messageDeltaSent) {\r\n return []\r\n }\r\n\r\n // If we have a pending finish_reason, send message_delta with whatever usage we have\r\n if (state.pendingFinishReason) {\r\n const usage = state.pendingUsage ?? { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0 }\r\n return createMessageDeltaEvents(state.pendingFinishReason, usage)\r\n }\r\n\r\n return []\r\n}\r\n\r\n// eslint-disable-next-line max-lines-per-function, complexity\r\nexport function translateChunkToAnthropicEvents(\r\n chunk: ChatCompletionChunk,\r\n state: AnthropicStreamState,\r\n originalModel?: string,\r\n): Array<AnthropicStreamEventData> {\r\n const events: Array<AnthropicStreamEventData> = []\r\n\r\n // Capture usage from any chunk that has it (may come before, with, or after finish_reason)\r\n if (chunk.usage) {\r\n state.pendingUsage = {\r\n prompt_tokens: chunk.usage.prompt_tokens ?? 0,\r\n completion_tokens: chunk.usage.completion_tokens ?? 0,\r\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\r\n }\r\n\r\n // If we already saw finish_reason but deferred message_delta, send it now\r\n if (state.pendingFinishReason && !state.messageDeltaSent) {\r\n events.push(\r\n ...createMessageDeltaEvents(state.pendingFinishReason, state.pendingUsage),\r\n )\r\n state.messageDeltaSent = true\r\n }\r\n }\r\n\r\n if (chunk.choices.length === 0) {\r\n // Empty choices chunk - usage already captured above\r\n return events\r\n }\r\n\r\n const choice = chunk.choices[0]\r\n const { delta } = choice\r\n\r\n if (!state.messageStartSent) {\r\n // Include usage in message_start for context window display\r\n // Use pending usage if available (captured from earlier chunks)\r\n const usage = state.pendingUsage ?? { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0 }\r\n events.push({\r\n type: \"message_start\",\r\n message: {\r\n id: chunk.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n content: [],\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? chunk.model,\r\n stop_reason: null,\r\n stop_sequence: null,\r\n // Include usage for context window display\r\n usage: {\r\n input_tokens: usage.prompt_tokens,\r\n output_tokens: usage.completion_tokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: usage.cached_tokens,\r\n },\r\n },\r\n })\r\n state.messageStartSent = true\r\n }\r\n\r\n if (delta.content) {\r\n if (isToolBlockOpen(state)) {\r\n // A tool block was open, so close it before starting a text block.\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockIndex++\r\n state.contentBlockOpen = false\r\n }\r\n\r\n if (!state.contentBlockOpen) {\r\n events.push({\r\n type: \"content_block_start\",\r\n index: state.contentBlockIndex,\r\n content_block: {\r\n type: \"text\",\r\n text: \"\",\r\n },\r\n })\r\n state.contentBlockOpen = true\r\n }\r\n\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: state.contentBlockIndex,\r\n delta: {\r\n type: \"text_delta\",\r\n text: delta.content,\r\n },\r\n })\r\n }\r\n\r\n if (delta.tool_calls) {\r\n for (const toolCall of delta.tool_calls) {\r\n if (toolCall.id && toolCall.function?.name) {\r\n // New tool call starting.\r\n if (state.contentBlockOpen) {\r\n // Close any previously open block.\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockIndex++\r\n state.contentBlockOpen = false\r\n }\r\n\r\n const anthropicBlockIndex = state.contentBlockIndex\r\n state.toolCalls[toolCall.index] = {\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n anthropicBlockIndex,\r\n }\r\n\r\n events.push({\r\n type: \"content_block_start\",\r\n index: anthropicBlockIndex,\r\n content_block: {\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: {},\r\n },\r\n })\r\n state.contentBlockOpen = true\r\n }\r\n\r\n if (toolCall.function?.arguments) {\r\n const toolCallInfo = state.toolCalls[toolCall.index]\r\n // Tool call can still be empty\r\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\r\n if (toolCallInfo) {\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: toolCallInfo.anthropicBlockIndex,\r\n delta: {\r\n type: \"input_json_delta\",\r\n partial_json: toolCall.function.arguments,\r\n },\r\n })\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (choice.finish_reason) {\r\n if (state.contentBlockOpen) {\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: state.contentBlockIndex,\r\n })\r\n state.contentBlockOpen = false\r\n }\r\n\r\n // Check if we have usage data (from this chunk or previously captured)\r\n const hasUsage = chunk.usage || state.pendingUsage\r\n\r\n if (hasUsage) {\r\n // We have usage - send message_delta immediately\r\n const usage = {\r\n prompt_tokens: chunk.usage?.prompt_tokens ?? state.pendingUsage?.prompt_tokens ?? 0,\r\n completion_tokens: chunk.usage?.completion_tokens ?? state.pendingUsage?.completion_tokens ?? 0,\r\n cached_tokens: chunk.usage?.prompt_tokens_details?.cached_tokens ?? state.pendingUsage?.cached_tokens ?? 0,\r\n }\r\n\r\n events.push(...createMessageDeltaEvents(choice.finish_reason, usage))\r\n state.messageDeltaSent = true\r\n } else {\r\n // No usage yet - defer message_delta until we receive usage in a later chunk\r\n state.pendingFinishReason = choice.finish_reason\r\n }\r\n }\r\n\r\n return events\r\n}\r\n\r\n/**\r\n * Convert a complete OpenAI ChatCompletionResponse to Anthropic streaming events.\r\n * This is used when we fetch non-streaming from upstream but need to simulate\r\n * streaming to the client with accurate token counts.\r\n */\r\nexport function translateResponseToAnthropicEvents(\r\n response: ChatCompletionResponse,\r\n originalModel?: string,\r\n): Array<AnthropicStreamEventData> {\r\n const events: Array<AnthropicStreamEventData> = []\r\n\r\n const choice = response.choices[0]\r\n if (!choice) {\r\n return events\r\n }\r\n\r\n const inputTokens = response.usage?.prompt_tokens ?? 0\r\n const outputTokens = response.usage?.completion_tokens ?? 0\r\n const cachedTokens =\r\n response.usage?.prompt_tokens_details?.cached_tokens ?? 0\r\n\r\n // 1. message_start - with actual token counts from response\r\n events.push({\r\n type: \"message_start\",\r\n message: {\r\n id: response.id,\r\n type: \"message\",\r\n role: \"assistant\",\r\n content: [],\r\n // Use original requested model for cost calculation in Claude Code\r\n model: originalModel ?? response.model,\r\n stop_reason: null,\r\n stop_sequence: null,\r\n usage: {\r\n input_tokens: inputTokens,\r\n output_tokens: 0,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: cachedTokens,\r\n },\r\n },\r\n })\r\n\r\n let contentBlockIndex = 0\r\n\r\n // Handle text content\r\n if (choice.message.content) {\r\n // 2. content_block_start for text\r\n events.push({\r\n type: \"content_block_start\",\r\n index: contentBlockIndex,\r\n content_block: {\r\n type: \"text\",\r\n text: \"\",\r\n },\r\n })\r\n\r\n // 3. content_block_delta with the full text\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: contentBlockIndex,\r\n delta: {\r\n type: \"text_delta\",\r\n text: choice.message.content,\r\n },\r\n })\r\n\r\n // 4. content_block_stop\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: contentBlockIndex,\r\n })\r\n\r\n contentBlockIndex++\r\n }\r\n\r\n // Handle tool calls\r\n if (choice.message.tool_calls) {\r\n for (const toolCall of choice.message.tool_calls) {\r\n // content_block_start for tool_use\r\n events.push({\r\n type: \"content_block_start\",\r\n index: contentBlockIndex,\r\n content_block: {\r\n type: \"tool_use\",\r\n id: toolCall.id,\r\n name: toolCall.function.name,\r\n input: {},\r\n },\r\n })\r\n\r\n // content_block_delta with tool arguments\r\n events.push({\r\n type: \"content_block_delta\",\r\n index: contentBlockIndex,\r\n delta: {\r\n type: \"input_json_delta\",\r\n partial_json: toolCall.function.arguments,\r\n },\r\n })\r\n\r\n // content_block_stop\r\n events.push({\r\n type: \"content_block_stop\",\r\n index: contentBlockIndex,\r\n })\r\n\r\n contentBlockIndex++\r\n }\r\n }\r\n\r\n // 5. message_delta with final usage\r\n events.push({\r\n type: \"message_delta\",\r\n delta: {\r\n stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),\r\n stop_sequence: null,\r\n },\r\n usage: {\r\n input_tokens: inputTokens,\r\n output_tokens: outputTokens,\r\n cache_creation_input_tokens: 0,\r\n cache_read_input_tokens: cachedTokens,\r\n },\r\n })\r\n\r\n // 6. message_stop\r\n events.push({\r\n type: \"message_stop\",\r\n })\r\n\r\n return events\r\n}\r\n\r\nexport function translateErrorToAnthropicErrorEvent(): AnthropicStreamEventData {\r\n return {\r\n type: \"error\",\r\n error: {\r\n type: \"api_error\",\r\n message: \"An unexpected error occurred during streaming.\",\r\n },\r\n }\r\n}\r\n","import type { Context } from \"hono\"\r\n\r\nimport consola from \"consola\"\r\nimport { streamSSE } from \"hono/streaming\"\r\n\r\nimport { awaitApproval } from \"~/lib/approval\"\r\nimport { applyReplacementsToPayload } from \"~/lib/auto-replace\"\r\nimport { normalizeModelName } from \"~/lib/model-resolver\"\r\nimport { checkRateLimit } from \"~/lib/rate-limit\"\r\nimport { setRequestContext } from \"~/lib/request-logger\"\r\nimport { state } from \"~/lib/state\"\r\nimport {\r\n createAzureOpenAIChatCompletions,\r\n isAzureOpenAIModel,\r\n} from \"~/services/azure-openai\"\r\nimport {\r\n createChatCompletions,\r\n type ChatCompletionChunk,\r\n type ChatCompletionResponse,\r\n} from \"~/services/copilot/create-chat-completions\"\r\n\r\nimport {\r\n type AnthropicMessagesPayload,\r\n type AnthropicStreamState,\r\n} from \"./anthropic-types\"\r\nimport {\r\n translateToAnthropic,\r\n translateToOpenAI,\r\n} from \"./non-stream-translation\"\r\nimport {\r\n createFallbackMessageDeltaEvents,\r\n translateChunkToAnthropicEvents,\r\n} from \"./stream-translation\"\r\n\r\ninterface UsageData {\r\n prompt_tokens: number\r\n completion_tokens: number\r\n cached_tokens: number\r\n}\r\n\r\n/** Collect all chunks and extract usage data */\r\nasync function collectChunksWithUsage(\r\n eventStream: AsyncIterable<{ event?: string; data?: string }>,\r\n): Promise<{ chunks: Array<ChatCompletionChunk>; usage: UsageData | null }> {\r\n const chunks: Array<ChatCompletionChunk> = []\r\n let usage: UsageData | null = null\r\n\r\n for await (const event of eventStream) {\r\n if (!event.data || event.data === \"[DONE]\") continue\r\n try {\r\n const chunk = JSON.parse(event.data) as ChatCompletionChunk\r\n chunks.push(chunk)\r\n if (chunk.usage) {\r\n usage = {\r\n prompt_tokens: chunk.usage.prompt_tokens,\r\n completion_tokens: chunk.usage.completion_tokens,\r\n cached_tokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0,\r\n }\r\n }\r\n } catch (error) {\r\n consola.error(\"Failed to parse chunk:\", error, event.data)\r\n }\r\n }\r\n return { chunks, usage }\r\n}\r\n\r\nexport async function handleCompletion(c: Context) {\r\n await checkRateLimit(state)\r\n\r\n const anthropicPayload = await c.req.json<AnthropicMessagesPayload>()\r\n consola.debug(\"Anthropic request payload:\", JSON.stringify(anthropicPayload))\r\n\r\n const translatedPayload = translateToOpenAI(anthropicPayload)\r\n let openAIPayload = await applyReplacementsToPayload(translatedPayload)\r\n openAIPayload = { ...openAIPayload, model: normalizeModelName(openAIPayload.model) }\r\n\r\n if (state.manualApprove) await awaitApproval()\r\n\r\n const isAzureModel = isAzureOpenAIModel(openAIPayload.model)\r\n\r\n if (isAzureModel) {\r\n if (!state.azureOpenAIConfig) {\r\n return c.json({ error: \"Azure OpenAI not configured\" }, 500)\r\n }\r\n setRequestContext(c, { provider: \"Azure OpenAI\", model: openAIPayload.model })\r\n } else {\r\n setRequestContext(c, { provider: \"Copilot\", model: openAIPayload.model })\r\n }\r\n\r\n if (anthropicPayload.stream) {\r\n const streamPayload = {\r\n ...openAIPayload,\r\n stream: true,\r\n stream_options: { include_usage: true },\r\n }\r\n\r\n const response = isAzureModel\r\n ? await createAzureOpenAIChatCompletions(state.azureOpenAIConfig!, streamPayload)\r\n : await createChatCompletions(streamPayload)\r\n\r\n const eventStream = response as AsyncIterable<{ event?: string; data?: string }>\r\n\r\n return streamSSE(c, async (stream) => {\r\n // Buffer all chunks first to get usage before emitting message_start\r\n const { chunks, usage } = await collectChunksWithUsage(eventStream)\r\n\r\n if (usage) {\r\n setRequestContext(c, {\r\n inputTokens: usage.prompt_tokens,\r\n outputTokens: usage.completion_tokens,\r\n })\r\n }\r\n\r\n const streamState: AnthropicStreamState = {\r\n messageStartSent: false,\r\n contentBlockOpen: false,\r\n contentBlockIndex: 0,\r\n toolCalls: {},\r\n pendingUsage: usage ?? undefined,\r\n }\r\n\r\n // Emit all events with correct usage in message_start\r\n for (const chunk of chunks) {\r\n for (const evt of translateChunkToAnthropicEvents(chunk, streamState, anthropicPayload.model)) {\r\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\r\n }\r\n }\r\n\r\n for (const evt of createFallbackMessageDeltaEvents(streamState)) {\r\n await stream.writeSSE({ event: evt.type, data: JSON.stringify(evt) })\r\n }\r\n })\r\n }\r\n\r\n // Non-streaming response\r\n const nonStreamPayload = { ...openAIPayload, stream: false }\r\n\r\n const response = isAzureModel\r\n ? ((await createAzureOpenAIChatCompletions(\r\n state.azureOpenAIConfig!,\r\n nonStreamPayload,\r\n )) as ChatCompletionResponse)\r\n : ((await createChatCompletions(nonStreamPayload)) as ChatCompletionResponse)\r\n\r\n if (response.usage) {\r\n setRequestContext(c, {\r\n inputTokens: response.usage.prompt_tokens,\r\n outputTokens: response.usage.completion_tokens,\r\n })\r\n }\r\n\r\n const anthropicResponse = translateToAnthropic(response, anthropicPayload.model)\r\n return c.json(anthropicResponse)\r\n}\r\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\n\nimport { handleCountTokens } from \"./count-tokens-handler\"\nimport { handleCompletion } from \"./handler\"\n\nexport const messageRoutes = new Hono()\n\nmessageRoutes.post(\"/\", async (c) => {\n try {\n return await handleCompletion(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n\nmessageRoutes.post(\"/count_tokens\", async (c) => {\n try {\n return await handleCountTokens(c)\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { forwardError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\nimport { cacheModels } from \"~/lib/utils\"\n\nexport const modelRoutes = new Hono()\n\nmodelRoutes.get(\"/\", async (c) => {\n try {\n if (!state.models) {\n // This should be handled by startup logic, but as a fallback.\n await cacheModels()\n }\n\n // Copilot models\n const copilotModels =\n state.models?.data.map((model) => ({\n id: model.id,\n object: \"model\",\n type: \"model\",\n created: 0, // No date available from source\n created_at: new Date(0).toISOString(), // No date available from source\n owned_by: model.vendor,\n display_name: model.name,\n })) ?? []\n\n // Azure OpenAI deployments\n const azureModels =\n state.azureOpenAIDeployments?.map((deployment) => ({\n id: deployment.id,\n object: \"model\",\n type: \"model\",\n created: deployment.created,\n created_at: new Date(deployment.created * 1000).toISOString(),\n owned_by: deployment.owned_by,\n display_name: `${deployment.deploymentName} (${deployment.model})`,\n })) ?? []\n\n const allModels = [...copilotModels, ...azureModels]\n\n return c.json({\n object: \"list\",\n data: allModels,\n has_more: false,\n })\n } catch (error) {\n return await forwardError(c, error)\n }\n})\n","import { Hono } from \"hono\"\r\n\r\nimport {\r\n addReplacement,\r\n clearUserReplacements,\r\n getAllReplacements,\r\n getUserReplacements,\r\n removeReplacement,\r\n toggleReplacement,\r\n updateReplacement,\r\n} from \"~/lib/auto-replace\"\r\n\r\nexport const replacementsRoute = new Hono()\r\n\r\n// Get all replacement rules\r\nreplacementsRoute.get(\"/\", async (c) => {\r\n return c.json({\r\n all: await getAllReplacements(),\r\n user: await getUserReplacements(),\r\n })\r\n})\r\n\r\n// Add a new replacement rule\r\nreplacementsRoute.post(\"/\", async (c) => {\r\n const body = await c.req.json<{\r\n pattern: string\r\n replacement?: string\r\n isRegex?: boolean\r\n name?: string\r\n }>()\r\n\r\n if (!body.pattern) {\r\n return c.json({ error: \"Pattern is required\" }, 400)\r\n }\r\n\r\n const rule = await addReplacement(\r\n body.pattern,\r\n body.replacement ?? \"\",\r\n body.isRegex ?? false,\r\n body.name,\r\n )\r\n\r\n return c.json(rule, 201)\r\n})\r\n\r\n// Delete a replacement rule\r\nreplacementsRoute.delete(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const success = await removeReplacement(id)\r\n\r\n if (!success) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json({ success: true })\r\n})\r\n\r\n// Update a replacement rule\r\nreplacementsRoute.patch(\"/:id\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const body = await c.req.json<{\r\n name?: string\r\n pattern?: string\r\n replacement?: string\r\n isRegex?: boolean\r\n enabled?: boolean\r\n }>()\r\n\r\n const rule = await updateReplacement(id, body)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Toggle a replacement rule\r\nreplacementsRoute.patch(\"/:id/toggle\", async (c) => {\r\n const id = c.req.param(\"id\")\r\n const rule = await toggleReplacement(id)\r\n\r\n if (!rule) {\r\n return c.json({ error: \"Replacement not found or is a system rule\" }, 404)\r\n }\r\n\r\n return c.json(rule)\r\n})\r\n\r\n// Clear all user replacements\r\nreplacementsRoute.delete(\"/\", async (c) => {\r\n await clearUserReplacements()\r\n return c.json({ success: true })\r\n})\r\n","import { Hono } from \"hono\"\n\nimport { state } from \"~/lib/state\"\n\nexport const tokenRoute = new Hono()\n\ntokenRoute.get(\"/\", (c) => {\n try {\n return c.json({\n token: state.copilotToken,\n })\n } catch (error) {\n console.error(\"Error fetching token:\", error)\n return c.json({ error: \"Failed to fetch token\", token: null }, 500)\n }\n})\n","import { Hono } from \"hono\"\n\nimport { getCopilotUsage } from \"~/services/github/get-copilot-usage\"\n\nexport const usageRoute = new Hono()\n\nusageRoute.get(\"/\", async (c) => {\n try {\n const usage = await getCopilotUsage()\n return c.json(usage)\n } catch (error) {\n console.error(\"Error fetching Copilot usage:\", error)\n return c.json({ error: \"Failed to fetch Copilot usage\" }, 500)\n }\n})\n","import { Hono } from \"hono\"\r\nimport { cors } from \"hono/cors\"\r\n\r\nimport { requestLogger } from \"./lib/request-logger\"\r\nimport { completionRoutes } from \"./routes/chat-completions/route\"\r\nimport { embeddingRoutes } from \"./routes/embeddings/route\"\r\nimport { messageRoutes } from \"./routes/messages/route\"\r\nimport { modelRoutes } from \"./routes/models/route\"\r\nimport { replacementsRoute } from \"./routes/replacements/route\"\r\nimport { tokenRoute } from \"./routes/token/route\"\r\nimport { usageRoute } from \"./routes/usage/route\"\r\n\r\nexport const server = new Hono()\r\n\r\nserver.use(requestLogger)\r\nserver.use(cors())\r\n\r\nserver.get(\"/\", (c) => c.text(\"Server running\"))\r\n\r\nserver.route(\"/chat/completions\", completionRoutes)\r\nserver.route(\"/models\", modelRoutes)\r\nserver.route(\"/embeddings\", embeddingRoutes)\r\nserver.route(\"/usage\", usageRoute)\r\nserver.route(\"/token\", tokenRoute)\r\nserver.route(\"/replacements\", replacementsRoute)\r\n\r\n// Compatibility with tools that expect v1/ prefix\r\nserver.route(\"/v1/chat/completions\", completionRoutes)\r\nserver.route(\"/v1/models\", modelRoutes)\r\nserver.route(\"/v1/embeddings\", embeddingRoutes)\r\n\r\n// Anthropic compatible endpoints\r\nserver.route(\"/v1/messages\", messageRoutes)\r\n","#!/usr/bin/env node\n\nimport { defineCommand } from \"citty\"\nimport clipboard from \"clipboardy\"\nimport consola from \"consola\"\nimport { serve, type ServerHandler } from \"srvx\"\nimport invariant from \"tiny-invariant\"\n\nimport { ensurePaths } from \"./lib/paths\"\nimport { initProxyFromEnv } from \"./lib/proxy\"\nimport { generateEnvScript } from \"./lib/shell\"\nimport { state } from \"./lib/state\"\nimport { setupCopilotToken, setupGitHubToken } from \"./lib/token\"\nimport { cacheModels, cacheVSCodeVersion, setupAzureOpenAI } from \"./lib/utils\"\nimport { server } from \"./server\"\n\ninterface RunServerOptions {\n port: number\n verbose: boolean\n accountType: string\n manual: boolean\n rateLimit?: number\n rateLimitWait: boolean\n githubToken?: string\n claudeCode: boolean\n showToken: boolean\n proxyEnv: boolean\n insecure: boolean\n debug: boolean\n}\n\nexport async function runServer(options: RunServerOptions): Promise<void> {\n if (options.insecure) {\n // Disable SSL certificate verification globally\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\"\n consola.warn(\"SSL certificate verification disabled (insecure mode)\")\n }\n\n if (options.proxyEnv) {\n initProxyFromEnv()\n }\n\n if (options.verbose) {\n consola.level = 5\n consola.info(\"Verbose logging enabled\")\n }\n\n state.accountType = options.accountType\n if (options.accountType !== \"individual\") {\n consola.info(`Using ${options.accountType} plan GitHub account`)\n }\n\n state.manualApprove = options.manual\n state.rateLimitSeconds = options.rateLimit\n state.rateLimitWait = options.rateLimitWait\n state.showToken = options.showToken\n state.debug = options.debug\n\n if (options.debug) {\n consola.info(\"Debug mode enabled - raw HTTP requests will be logged\")\n }\n\n await ensurePaths()\n await cacheVSCodeVersion()\n\n if (options.githubToken) {\n state.githubToken = options.githubToken\n consola.info(\"Using provided GitHub token\")\n } else {\n await setupGitHubToken()\n }\n\n await setupCopilotToken()\n await cacheModels()\n\n // Setup Azure OpenAI (prompt on first run, load from config thereafter)\n await setupAzureOpenAI()\n\n // Build combined model list for display\n const copilotModelIds = state.models?.data.map((model) => model.id) ?? []\n const azureModelIds =\n state.azureOpenAIDeployments?.map((deployment) => deployment.id) ?? []\n const allModelIds = [...copilotModelIds, ...azureModelIds]\n\n consola.info(\n `Available models: \\n${allModelIds.map((id) => `- ${id}`).join(\"\\n\")}`,\n )\n\n const serverUrl = `http://localhost:${options.port}`\n\n if (options.claudeCode) {\n invariant(state.models, \"Models should be loaded by now\")\n\n const selectedModel = await consola.prompt(\n \"Select a model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const selectedSmallModel = await consola.prompt(\n \"Select a small model to use with Claude Code\",\n {\n type: \"select\",\n options: allModelIds,\n },\n )\n\n const command = generateEnvScript(\n {\n ANTHROPIC_BASE_URL: serverUrl,\n ANTHROPIC_AUTH_TOKEN: \"dummy\",\n ANTHROPIC_MODEL: selectedModel,\n ANTHROPIC_DEFAULT_SONNET_MODEL: selectedModel,\n ANTHROPIC_SMALL_FAST_MODEL: selectedSmallModel,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: selectedSmallModel,\n DISABLE_NON_ESSENTIAL_MODEL_CALLS: \"1\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n },\n \"claude\",\n )\n\n try {\n clipboard.writeSync(command)\n consola.success(\"Copied Claude Code command to clipboard!\")\n } catch {\n consola.warn(\n \"Failed to copy to clipboard. Here is the Claude Code command:\",\n )\n consola.log(command)\n }\n }\n\n consola.box(\n `🌐 Usage Viewer: https://ericc-ch.github.io/copilot-api?endpoint=${serverUrl}/usage`,\n )\n\n serve({\n fetch: server.fetch as ServerHandler,\n port: options.port,\n })\n}\n\nexport const start = defineCommand({\n meta: {\n name: \"start\",\n description: \"Start the Copilot API server\",\n },\n args: {\n port: {\n alias: \"p\",\n type: \"string\",\n default: \"4141\",\n description: \"Port to listen on\",\n },\n verbose: {\n alias: \"v\",\n type: \"boolean\",\n default: false,\n description: \"Enable verbose logging\",\n },\n \"account-type\": {\n alias: \"a\",\n type: \"string\",\n default: \"individual\",\n description: \"Account type to use (individual, business, enterprise)\",\n },\n manual: {\n type: \"boolean\",\n default: false,\n description: \"Enable manual request approval\",\n },\n \"rate-limit\": {\n alias: \"r\",\n type: \"string\",\n description: \"Rate limit in seconds between requests\",\n },\n wait: {\n alias: \"w\",\n type: \"boolean\",\n default: false,\n description:\n \"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set\",\n },\n \"github-token\": {\n alias: \"g\",\n type: \"string\",\n description:\n \"Provide GitHub token directly (must be generated using the `auth` subcommand)\",\n },\n \"claude-code\": {\n alias: \"c\",\n type: \"boolean\",\n default: false,\n description:\n \"Generate a command to launch Claude Code with Copilot API config\",\n },\n \"show-token\": {\n type: \"boolean\",\n default: false,\n description: \"Show GitHub and Copilot tokens on fetch and refresh\",\n },\n \"proxy-env\": {\n type: \"boolean\",\n default: false,\n description: \"Initialize proxy from environment variables\",\n },\n insecure: {\n type: \"boolean\",\n default: false,\n description:\n \"Disable SSL certificate verification (for corporate proxies with self-signed certs)\",\n },\n debug: {\n alias: \"d\",\n type: \"boolean\",\n default: false,\n description: \"Log raw HTTP requests received by the server (headers, method, path)\",\n },\n },\n run({ args }) {\n const rateLimitRaw = args[\"rate-limit\"]\n const rateLimit =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n rateLimitRaw === undefined ? undefined : Number.parseInt(rateLimitRaw, 10)\n\n return runServer({\n port: Number.parseInt(args.port, 10),\n verbose: args.verbose,\n accountType: args[\"account-type\"],\n manual: args.manual,\n rateLimit,\n rateLimitWait: args.wait,\n githubToken: args[\"github-token\"],\n claudeCode: args[\"claude-code\"],\n showToken: args[\"show-token\"],\n proxyEnv: args[\"proxy-env\"],\n insecure: args.insecure,\n debug: args.debug,\n })\n },\n})\n","#!/usr/bin/env node\r\n\r\nimport { defineCommand, runMain } from \"citty\"\r\n\r\nimport { auth } from \"./auth\"\r\nimport { checkUsage } from \"./check-usage\"\r\nimport { config } from \"./config\"\r\nimport { debug } from \"./debug\"\r\nimport { start } from \"./start\"\r\n\r\nconst main = defineCommand({\r\n meta: {\r\n name: \"copilot-api\",\r\n description:\r\n \"A wrapper around GitHub Copilot API to make it OpenAI compatible, making it usable for other tools.\",\r\n },\r\n subCommands: { auth, start, \"check-usage\": checkUsage, debug, config },\r\n})\r\n\r\nawait runMain(main)\r\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ashsec/copilot-api",
3
- "version": "0.7.7",
3
+ "version": "0.7.8",
4
4
  "description": "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code!",
5
5
  "keywords": [
6
6
  "proxy",