@openhoo/hoopilot 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +22 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +22 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -962,12 +962,13 @@ function createHoopilotHandler(options = {}) {
|
|
|
962
962
|
return async (request) => {
|
|
963
963
|
const startedAt = performance.now();
|
|
964
964
|
const url = new URL(request.url);
|
|
965
|
+
const apiPath = canonicalApiPath(url.pathname);
|
|
965
966
|
const requestId = requestIdFor(request);
|
|
966
967
|
const requestLogger = logger.child({
|
|
967
968
|
method: request.method,
|
|
968
969
|
path: url.pathname,
|
|
969
970
|
requestId,
|
|
970
|
-
route: routeFor(request.method,
|
|
971
|
+
route: routeFor(request.method, apiPath)
|
|
971
972
|
});
|
|
972
973
|
if (request.method === "OPTIONS") {
|
|
973
974
|
return finishResponse(new Response(null, { headers: corsHeaders() }), {
|
|
@@ -988,7 +989,7 @@ function createHoopilotHandler(options = {}) {
|
|
|
988
989
|
);
|
|
989
990
|
}
|
|
990
991
|
try {
|
|
991
|
-
if (request.method === "GET" && (
|
|
992
|
+
if (request.method === "GET" && (apiPath === "/" || apiPath === "/healthz")) {
|
|
992
993
|
return finishResponse(
|
|
993
994
|
jsonResponse({
|
|
994
995
|
name: "hoopilot",
|
|
@@ -998,28 +999,28 @@ function createHoopilotHandler(options = {}) {
|
|
|
998
999
|
{ logger: requestLogger, requestId, startedAt }
|
|
999
1000
|
);
|
|
1000
1001
|
}
|
|
1001
|
-
if (request.method === "GET" &&
|
|
1002
|
+
if (request.method === "GET" && apiPath === "/v1/models") {
|
|
1002
1003
|
return finishResponse(await handleModels(client, request.signal, requestLogger), {
|
|
1003
1004
|
logger: requestLogger,
|
|
1004
1005
|
requestId,
|
|
1005
1006
|
startedAt
|
|
1006
1007
|
});
|
|
1007
1008
|
}
|
|
1008
|
-
if (request.method === "POST" &&
|
|
1009
|
+
if (request.method === "POST" && apiPath === "/v1/chat/completions") {
|
|
1009
1010
|
return finishResponse(await handleChatCompletions(client, request, requestLogger), {
|
|
1010
1011
|
logger: requestLogger,
|
|
1011
1012
|
requestId,
|
|
1012
1013
|
startedAt
|
|
1013
1014
|
});
|
|
1014
1015
|
}
|
|
1015
|
-
if (request.method === "POST" &&
|
|
1016
|
+
if (request.method === "POST" && apiPath === "/v1/completions") {
|
|
1016
1017
|
return finishResponse(await handleCompletions(client, request, requestLogger), {
|
|
1017
1018
|
logger: requestLogger,
|
|
1018
1019
|
requestId,
|
|
1019
1020
|
startedAt
|
|
1020
1021
|
});
|
|
1021
1022
|
}
|
|
1022
|
-
if (request.method === "POST" &&
|
|
1023
|
+
if (request.method === "POST" && apiPath === "/v1/responses") {
|
|
1023
1024
|
return finishResponse(await handleResponses(client, request, requestLogger), {
|
|
1024
1025
|
logger: requestLogger,
|
|
1025
1026
|
requestId,
|
|
@@ -1284,6 +1285,21 @@ function requestIdFor(request) {
|
|
|
1284
1285
|
const existing = request.headers.get("x-request-id")?.trim();
|
|
1285
1286
|
return existing || crypto.randomUUID();
|
|
1286
1287
|
}
|
|
1288
|
+
function canonicalApiPath(path) {
|
|
1289
|
+
const withoutTrailingSlash = path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
1290
|
+
switch (withoutTrailingSlash) {
|
|
1291
|
+
case "/models":
|
|
1292
|
+
return "/v1/models";
|
|
1293
|
+
case "/chat/completions":
|
|
1294
|
+
return "/v1/chat/completions";
|
|
1295
|
+
case "/completions":
|
|
1296
|
+
return "/v1/completions";
|
|
1297
|
+
case "/responses":
|
|
1298
|
+
return "/v1/responses";
|
|
1299
|
+
default:
|
|
1300
|
+
return withoutTrailingSlash;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1287
1303
|
function routeFor(method, path) {
|
|
1288
1304
|
if (method === "OPTIONS") {
|
|
1289
1305
|
return "cors.preflight";
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/auth-store.ts","../src/auth.ts","../src/copilot.ts","../src/github-device.ts","../src/logger.ts","../src/openai.ts","../src/server.ts"],"sourcesContent":["export { CopilotAuth, CopilotAuthError } from \"./auth\";\nexport { authStorePath, readStoredCopilotAuth, writeStoredCopilotAuth } from \"./auth-store\";\nexport { CopilotClient } from \"./copilot\";\nexport { githubCopilotDeviceLogin } from \"./github-device\";\nexport {\n createHoopilotLogger,\n DEFAULT_LOG_FORMAT,\n DEFAULT_LOG_LEVEL,\n noopLogger,\n parseLogFormat,\n parseLogLevel,\n} from \"./logger\";\nexport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n DEFAULT_MODEL,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nexport { createHoopilotHandler, startHoopilotServer } from \"./server\";\nexport type {\n CopilotAccess,\n CopilotAuthOptions,\n FetchLike,\n HoopilotLogger,\n HoopilotLoggerOptions,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n LogFormat,\n Logger,\n LogLevel,\n LogMethod,\n StartedHoopilotServer,\n} from \"./types\";\n","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredCopilotAuth {\n apiBaseUrl?: string;\n createdAt?: string;\n githubDomain?: string;\n source?: string;\n token: string;\n}\n\nexport function authStorePath(env: NodeJS.ProcessEnv = process.env): string {\n if (env.HOOPILOT_AUTH_FILE) {\n return env.HOOPILOT_AUTH_FILE;\n }\n\n const base =\n env.XDG_CONFIG_HOME ??\n env.APPDATA ??\n (env.HOME ? join(env.HOME, \".config\") : join(process.cwd(), \".config\"));\n return join(base, \"hoopilot\", \"auth.json\");\n}\n\nexport function readStoredCopilotAuth(path = authStorePath()): StoredCopilotAuth | undefined {\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\"));\n if (!parsed || typeof parsed !== \"object\") {\n return undefined;\n }\n const token = typeof parsed.token === \"string\" ? parsed.token.trim() : \"\";\n if (!token) {\n return undefined;\n }\n return {\n apiBaseUrl: typeof parsed.apiBaseUrl === \"string\" ? parsed.apiBaseUrl : undefined,\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : undefined,\n githubDomain: typeof parsed.githubDomain === \"string\" ? parsed.githubDomain : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n token,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function writeStoredCopilotAuth(auth: StoredCopilotAuth, path = authStorePath()): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n `${JSON.stringify(\n {\n ...auth,\n createdAt: auth.createdAt ?? new Date().toISOString(),\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n try {\n chmodSync(path, 0o600);\n } catch {\n // chmod is best-effort on Windows.\n }\n}\n","import { readStoredCopilotAuth } from \"./auth-store\";\nimport type { CopilotAccess, CopilotAuthOptions } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\nconst REFRESH_SKEW_MS = 60_000;\nconst STORED_TOKEN_TTL_MS = 10 * 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nexport class CopilotAuth {\n readonly #authStorePath?: string;\n readonly #copilotApiBaseUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authStorePath = options.authStorePath ?? options.env?.HOOPILOT_AUTH_FILE;\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const stored = readStoredCopilotAuth(this.#authStorePath);\n if (stored) {\n return this.#cacheAccess({\n apiBaseUrl: trimTrailingSlash(stored.apiBaseUrl ?? this.#copilotApiBaseUrl),\n expiresAtMs: Date.now() + STORED_TOKEN_TTL_MS,\n source: \"github-copilot-oauth\",\n token: stored.token,\n });\n }\n\n throw new CopilotAuthError(\n \"No GitHub Copilot OAuth credential found. Run `hoopilot login` to sign in through your browser.\",\n );\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n","import { CopilotAuth } from \"./auth\";\nimport type { CopilotAuthOptions, FetchLike, JsonObject } from \"./types\";\n\nexport class CopilotClient {\n readonly #auth: CopilotAuth;\n readonly #fetch: FetchLike;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#auth = new CopilotAuth(options);\n this.#fetch = options.fetch ?? fetch;\n }\n\n async chatCompletions(body: JsonObject, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body: JSON.stringify(body),\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async forwardChatCompletions(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import { setTimeout as sleep } from \"node:timers/promises\";\nimport type { FetchLike, Logger } from \"./types\";\n\nexport const DEFAULT_GITHUB_COPILOT_CLIENT_ID = \"Iv23lijnNxm2e9UX3CF8\";\nconst DEFAULT_GITHUB_DOMAIN = \"github.com\";\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst POLLING_SAFETY_MARGIN_MS = 3_000;\n\nexport interface GithubCopilotDeviceLoginOptions {\n clientId?: string;\n domain?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n logger?: Logger;\n openBrowser?: (url: string) => void | Promise<void>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface GithubCopilotDeviceLoginResult {\n domain: string;\n token: string;\n}\n\ninterface DeviceCodeResponse {\n device_code?: string;\n expires_in?: number;\n interval?: number;\n user_code?: string;\n verification_uri?: string;\n}\n\ninterface DeviceTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n interval?: number;\n}\n\nexport async function githubCopilotDeviceLogin(\n options: GithubCopilotDeviceLoginOptions = {},\n): Promise<GithubCopilotDeviceLoginResult> {\n const env = options.env ?? process.env;\n const fetcher = options.fetch ?? fetch;\n const sleeper = options.sleep ?? sleep;\n const domain = normalizeDomain(\n options.domain ?? env.HOOPILOT_GITHUB_DOMAIN ?? DEFAULT_GITHUB_DOMAIN,\n );\n const clientId =\n options.clientId ??\n env.HOOPILOT_GITHUB_CLIENT_ID ??\n env.COPILOT_GITHUB_CLIENT_ID ??\n DEFAULT_GITHUB_COPILOT_CLIENT_ID;\n\n const device = await requestDeviceCode(fetcher, domain, clientId);\n const verificationUrl = device.verification_uri;\n const userCode = device.user_code;\n const deviceCode = device.device_code;\n if (!verificationUrl || !userCode || !deviceCode) {\n throw new Error(\"GitHub device authorization response is missing required fields.\");\n }\n\n options.logger?.info(`First copy your one-time code: ${userCode}`);\n options.logger?.info(`Open ${verificationUrl} in your browser to authorize Hoopilot.`);\n await options.openBrowser?.(verificationUrl);\n\n return {\n domain,\n token: await pollForAccessToken(fetcher, sleeper, domain, clientId, {\n deviceCode,\n expiresIn: positiveSeconds(device.expires_in, 900),\n interval: positiveSeconds(device.interval, 5),\n }),\n };\n}\n\nasync function requestDeviceCode(\n fetcher: FetchLike,\n domain: string,\n clientId: string,\n): Promise<DeviceCodeResponse> {\n const response = await fetcher(`https://${domain}/login/device/code`, {\n body: JSON.stringify({\n client_id: clientId,\n scope: \"read:user\",\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n if (!response.ok) {\n throw new Error(\n `GitHub device authorization failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n return (await response.json()) as DeviceCodeResponse;\n}\n\nasync function pollForAccessToken(\n fetcher: FetchLike,\n sleeper: (ms: number) => Promise<void>,\n domain: string,\n clientId: string,\n device: { deviceCode: string; expiresIn: number; interval: number },\n): Promise<string> {\n let intervalMs = device.interval * 1000 + POLLING_SAFETY_MARGIN_MS;\n const deadline = Date.now() + device.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await sleeper(intervalMs);\n const response = await fetcher(`https://${domain}/login/oauth/access_token`, {\n body: JSON.stringify({\n client_id: clientId,\n device_code: device.deviceCode,\n grant_type: DEVICE_GRANT_TYPE,\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub device token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const data = (await response.json()) as DeviceTokenResponse;\n if (data.access_token) {\n return data.access_token;\n }\n\n if (data.error === \"authorization_pending\") {\n continue;\n }\n if (data.error === \"slow_down\") {\n intervalMs =\n positiveSeconds(data.interval, device.interval + 5) * 1000 + POLLING_SAFETY_MARGIN_MS;\n continue;\n }\n if (data.error === \"expired_token\") {\n throw new Error(\"GitHub device login expired. Run `hoopilot login` again.\");\n }\n if (data.error === \"access_denied\") {\n throw new Error(\"GitHub device login was cancelled.\");\n }\n if (data.error) {\n throw new Error(data.error_description || `GitHub device login failed: ${data.error}`);\n }\n }\n\n throw new Error(\"GitHub device login timed out. Run `hoopilot login` again.\");\n}\n\nfunction oauthHeaders(): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"content-type\", \"application/json\");\n headers.set(\"user-agent\", \"hoopilot\");\n return headers;\n}\n\nfunction normalizeDomain(value: string): string {\n return value.replace(/^https?:\\/\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction positiveSeconds(value: unknown, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n","import pino from \"pino\";\nimport pretty from \"pino-pretty\";\nimport type { HoopilotLogger, HoopilotLoggerOptions, LogFormat, LogLevel } from \"./types\";\n\nexport const DEFAULT_LOG_FORMAT: LogFormat = \"pretty\";\nexport const DEFAULT_LOG_LEVEL: LogLevel = \"info\";\n\nconst LOG_FORMATS = [\"json\", \"pretty\"] as const;\nconst LOG_LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\", \"silent\"] as const;\nconst REDACT_PATHS = [\n \"apiKey\",\n \"authorization\",\n \"cookie\",\n \"headers.authorization\",\n \"headers.Authorization\",\n \"headers.cookie\",\n \"headers.Cookie\",\n \"headers.x-api-key\",\n \"headers.X-Api-Key\",\n \"token\",\n \"*.apiKey\",\n \"*.authorization\",\n \"*.cookie\",\n \"*.token\",\n \"*.headers.authorization\",\n \"*.headers.Authorization\",\n \"*.headers.cookie\",\n \"*.headers.Cookie\",\n \"*.headers.x-api-key\",\n \"*.headers.X-Api-Key\",\n];\n\nexport const noopLogger: HoopilotLogger = {\n child: () => noopLogger,\n debug: () => {},\n error: () => {},\n fatal: () => {},\n info: () => {},\n trace: () => {},\n warn: () => {},\n};\n\nexport function createHoopilotLogger(options: HoopilotLoggerOptions = {}): HoopilotLogger {\n const env = options.env ?? process.env;\n const level = parseLogLevel(options.level ?? env.HOOPILOT_LOG_LEVEL);\n const format = parseLogFormat(options.format ?? env.HOOPILOT_LOG_FORMAT);\n const pinoOptions: pino.LoggerOptions = {\n base: {\n service: \"hoopilot\",\n ...options.base,\n },\n level,\n redact: {\n censor: \"[Redacted]\",\n paths: REDACT_PATHS,\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n };\n\n if (format === \"pretty\") {\n return pino(\n pinoOptions,\n pretty({\n colorize: options.colorize ?? process.stderr.isTTY,\n destination: options.stream ?? 1,\n ignore: \"pid,hostname\",\n singleLine: true,\n translateTime: \"SYS:standard\",\n }),\n ) as HoopilotLogger;\n }\n\n if (options.stream) {\n return pino(pinoOptions, options.stream as pino.DestinationStream) as HoopilotLogger;\n }\n return pino(pinoOptions) as HoopilotLogger;\n}\n\nexport function parseLogFormat(value: string | undefined): LogFormat {\n if (!value) {\n return DEFAULT_LOG_FORMAT;\n }\n if (isLogFormat(value)) {\n return value;\n }\n throw new Error(`Invalid log format: ${value}. Expected one of: ${LOG_FORMATS.join(\", \")}.`);\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n if (!value) {\n return DEFAULT_LOG_LEVEL;\n }\n if (isLogLevel(value)) {\n return value;\n }\n throw new Error(`Invalid log level: ${value}. Expected one of: ${LOG_LEVELS.join(\", \")}.`);\n}\n\nexport function shouldCreateLogger(options: {\n env?: NodeJS.ProcessEnv;\n logFormat?: string;\n logger?: HoopilotLogger;\n logLevel?: string;\n}): boolean {\n return Boolean(\n options.logger ||\n options.logFormat ||\n options.logLevel ||\n options.env?.HOOPILOT_LOG_FORMAT ||\n options.env?.HOOPILOT_LOG_LEVEL,\n );\n}\n\nfunction isLogFormat(value: string): value is LogFormat {\n return (LOG_FORMATS as readonly string[]).includes(value);\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return (LOG_LEVELS as readonly string[]).includes(value);\n}\n","import type { JsonObject } from \"./types\";\n\nexport const DEFAULT_MODEL = \"gpt-4.1\";\n\ninterface ResponseStreamOptions {\n model: string;\n responseId?: string;\n}\n\ninterface AccumulatedToolCall {\n arguments: string;\n id: string;\n index: number;\n name: string;\n}\n\nexport function responsesRequestToChatCompletion(request: JsonObject): JsonObject {\n const messages: unknown[] = [];\n const instructions = contentToText(request.instructions);\n if (instructions) {\n messages.push({ content: instructions, role: \"system\" });\n }\n\n for (const message of inputToMessages(request.input)) {\n messages.push(message);\n }\n\n return removeUndefined({\n frequency_penalty: request.frequency_penalty,\n max_tokens: request.max_output_tokens ?? request.max_tokens,\n messages,\n metadata: request.metadata,\n model: contentToText(request.model) || DEFAULT_MODEL,\n presence_penalty: request.presence_penalty,\n reasoning_effort: asRecord(request.reasoning).effort,\n response_format: asRecord(request.text).format,\n seed: request.seed,\n stream: request.stream === true,\n temperature: request.temperature,\n tool_choice: chatToolChoice(request.tool_choice),\n tools: chatTools(request.tools),\n top_p: request.top_p,\n });\n}\n\nexport function completionsRequestToChatCompletion(request: JsonObject): JsonObject {\n return removeUndefined({\n max_tokens: request.max_tokens,\n messages: [{ content: promptToText(request.prompt), role: \"user\" }],\n model: contentToText(request.model) || DEFAULT_MODEL,\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport { createHoopilotLogger, noopLogger, shouldCreateLogger } from \"./logger\";\nimport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type {\n HoopilotLogger,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n StartedHoopilotServer,\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\nconst INVALID_JSON_MESSAGE = \"Request body must be valid JSON.\";\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const logger = serverLogger(options);\n\n return async (request: Request): Promise<Response> => {\n const startedAt = performance.now();\n const url = new URL(request.url);\n const requestId = requestIdFor(request);\n const requestLogger = logger.child({\n method: request.method,\n path: url.pathname,\n requestId,\n route: routeFor(request.method, url.pathname),\n });\n\n if (request.method === \"OPTIONS\") {\n return finishResponse(new Response(null, { headers: corsHeaders() }), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n\n if (!isAuthorized(request, apiKey)) {\n requestLogger.warn({ event: \"http.request.unauthorized\" }, \"invalid hoopilot api key\");\n return finishResponse(\n jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\"),\n {\n logger: requestLogger,\n requestId,\n startedAt,\n },\n );\n }\n\n try {\n if (request.method === \"GET\" && (url.pathname === \"/\" || url.pathname === \"/healthz\")) {\n return finishResponse(\n jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n }),\n { logger: requestLogger, requestId, startedAt },\n );\n }\n if (request.method === \"GET\" && url.pathname === \"/v1/models\") {\n return finishResponse(await handleModels(client, request.signal, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n return finishResponse(await handleChatCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/completions\") {\n return finishResponse(await handleCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/responses\") {\n return finishResponse(await handleResponses(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n return finishResponse(\n jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`),\n { logger: requestLogger, requestId, startedAt },\n );\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"copilot.auth.missing\" },\n \"copilot auth failed\",\n );\n return finishResponse(jsonError(401, \"copilot_auth_error\", error.message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n const message = errorMessage(error);\n if (message === INVALID_JSON_MESSAGE) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request body was invalid json\",\n );\n } else {\n requestLogger.error(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request failed\",\n );\n }\n return finishResponse(jsonError(500, \"internal_error\", message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(\n client: CopilotClient,\n signal: AbortSignal,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n if (isUpstreamAuthStatus(upstream.status)) {\n return proxyError(upstream, logger);\n }\n logger.warn(\n {\n event: \"copilot.models.fallback\",\n upstreamPath: \"/models\",\n upstreamStatus: upstream.status,\n },\n \"falling back to built-in model list\",\n );\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n logUpstreamSuccess(logger, \"/models\", upstream.status);\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const chatRequest = responsesRequestToChatCompletion(body);\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n\n if (body.stream === true && upstream.body) {\n return new Response(\n responsesStreamFromChatStream(upstream.body, {\n model: typeof chatRequest.model === \"string\" ? chatRequest.model : \"gpt-4.1\",\n }),\n {\n headers: {\n ...corsHeaders(),\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"content-type\": \"text/event-stream; charset=utf-8\",\n },\n },\n );\n }\n\n return jsonResponse(chatCompletionToResponse(await upstream.json()));\n}\n\nasync function proxyError(upstream: Response, logger: HoopilotLogger): Promise<Response> {\n const text = await upstream.text();\n if (isUpstreamAuthStatus(upstream.status)) {\n logger.warn(\n { event: \"copilot.auth.rejected\", upstreamStatus: upstream.status },\n \"copilot rejected credential or account access\",\n );\n return jsonError(401, \"copilot_auth_error\", upstreamAuthMessage(text || upstream.statusText));\n }\n logger.warn(\n { event: \"copilot.request.failed\", upstreamStatus: upstream.status },\n \"copilot upstream request failed\",\n );\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isUpstreamAuthStatus(status: number): boolean {\n return status === 401 || status === 403;\n}\n\nfunction upstreamAuthMessage(message: string): string {\n return `GitHub Copilot rejected the credential or account access: ${message}`;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction serverLogger(options: HoopilotServerOptions): HoopilotLogger {\n if (options.logger) {\n return options.logger.child({ component: \"server\" });\n }\n if (shouldCreateLogger(options)) {\n return createHoopilotLogger({\n env: options.env,\n format: options.logFormat,\n level: options.logLevel,\n }).child({ component: \"server\" });\n }\n return noopLogger;\n}\n\nfunction finishResponse(\n response: Response,\n options: { logger: HoopilotLogger; requestId: string; startedAt: number },\n): Response {\n const withRequestId = responseWithRequestId(response, options.requestId);\n logRequestCompleted(options.logger, withRequestId, options.startedAt);\n return withRequestId;\n}\n\nfunction responseWithRequestId(response: Response, requestId: string): Response {\n const headers = new Headers(response.headers);\n headers.set(\"x-request-id\", requestId);\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nfunction logRequestCompleted(logger: HoopilotLogger, response: Response, startedAt: number): void {\n const fields: LogFields = {\n durationMs: Math.round((performance.now() - startedAt) * 100) / 100,\n event: \"http.request.completed\",\n status: response.status,\n stream: isStreamingResponse(response),\n };\n if (response.status >= 500) {\n logger.error(fields, \"request completed with server error\");\n return;\n }\n if (response.status >= 400) {\n logger.warn(fields, \"request completed with client error\");\n return;\n }\n logger.info(fields, \"request completed\");\n}\n\nfunction requestIdFor(request: Request): string {\n const existing = request.headers.get(\"x-request-id\")?.trim();\n return existing || crypto.randomUUID();\n}\n\nfunction routeFor(method: string, path: string): string {\n if (method === \"OPTIONS\") {\n return \"cors.preflight\";\n }\n if (method === \"GET\" && (path === \"/\" || path === \"/healthz\")) {\n return \"health\";\n }\n if (method === \"GET\" && path === \"/v1/models\") {\n return \"models\";\n }\n if (method === \"POST\" && path === \"/v1/chat/completions\") {\n return \"chat_completions\";\n }\n if (method === \"POST\" && path === \"/v1/completions\") {\n return \"completions\";\n }\n if (method === \"POST\" && path === \"/v1/responses\") {\n return \"responses\";\n }\n return \"not_found\";\n}\n\nfunction isStreamingResponse(response: Response): boolean {\n return response.headers.get(\"content-type\")?.includes(\"text/event-stream\") ?? false;\n}\n\nfunction logUpstreamSuccess(logger: HoopilotLogger, upstreamPath: string, status: number): void {\n logger.debug(\n {\n event: \"copilot.request.completed\",\n upstreamPath,\n upstreamStatus: status,\n },\n \"copilot upstream request completed\",\n );\n}\n\nfunction errorDetails(error: unknown): LogFields {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n"],"mappings":"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","names":["sleep","pino","pretty"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/auth-store.ts","../src/auth.ts","../src/copilot.ts","../src/github-device.ts","../src/logger.ts","../src/openai.ts","../src/server.ts"],"sourcesContent":["export { CopilotAuth, CopilotAuthError } from \"./auth\";\nexport { authStorePath, readStoredCopilotAuth, writeStoredCopilotAuth } from \"./auth-store\";\nexport { CopilotClient } from \"./copilot\";\nexport { githubCopilotDeviceLogin } from \"./github-device\";\nexport {\n createHoopilotLogger,\n DEFAULT_LOG_FORMAT,\n DEFAULT_LOG_LEVEL,\n noopLogger,\n parseLogFormat,\n parseLogLevel,\n} from \"./logger\";\nexport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n DEFAULT_MODEL,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nexport { createHoopilotHandler, startHoopilotServer } from \"./server\";\nexport type {\n CopilotAccess,\n CopilotAuthOptions,\n FetchLike,\n HoopilotLogger,\n HoopilotLoggerOptions,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n LogFormat,\n Logger,\n LogLevel,\n LogMethod,\n StartedHoopilotServer,\n} from \"./types\";\n","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredCopilotAuth {\n apiBaseUrl?: string;\n createdAt?: string;\n githubDomain?: string;\n source?: string;\n token: string;\n}\n\nexport function authStorePath(env: NodeJS.ProcessEnv = process.env): string {\n if (env.HOOPILOT_AUTH_FILE) {\n return env.HOOPILOT_AUTH_FILE;\n }\n\n const base =\n env.XDG_CONFIG_HOME ??\n env.APPDATA ??\n (env.HOME ? join(env.HOME, \".config\") : join(process.cwd(), \".config\"));\n return join(base, \"hoopilot\", \"auth.json\");\n}\n\nexport function readStoredCopilotAuth(path = authStorePath()): StoredCopilotAuth | undefined {\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\"));\n if (!parsed || typeof parsed !== \"object\") {\n return undefined;\n }\n const token = typeof parsed.token === \"string\" ? parsed.token.trim() : \"\";\n if (!token) {\n return undefined;\n }\n return {\n apiBaseUrl: typeof parsed.apiBaseUrl === \"string\" ? parsed.apiBaseUrl : undefined,\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : undefined,\n githubDomain: typeof parsed.githubDomain === \"string\" ? parsed.githubDomain : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n token,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function writeStoredCopilotAuth(auth: StoredCopilotAuth, path = authStorePath()): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n `${JSON.stringify(\n {\n ...auth,\n createdAt: auth.createdAt ?? new Date().toISOString(),\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n try {\n chmodSync(path, 0o600);\n } catch {\n // chmod is best-effort on Windows.\n }\n}\n","import { readStoredCopilotAuth } from \"./auth-store\";\nimport type { CopilotAccess, CopilotAuthOptions } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\nconst REFRESH_SKEW_MS = 60_000;\nconst STORED_TOKEN_TTL_MS = 10 * 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nexport class CopilotAuth {\n readonly #authStorePath?: string;\n readonly #copilotApiBaseUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authStorePath = options.authStorePath ?? options.env?.HOOPILOT_AUTH_FILE;\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const stored = readStoredCopilotAuth(this.#authStorePath);\n if (stored) {\n return this.#cacheAccess({\n apiBaseUrl: trimTrailingSlash(stored.apiBaseUrl ?? this.#copilotApiBaseUrl),\n expiresAtMs: Date.now() + STORED_TOKEN_TTL_MS,\n source: \"github-copilot-oauth\",\n token: stored.token,\n });\n }\n\n throw new CopilotAuthError(\n \"No GitHub Copilot OAuth credential found. Run `hoopilot login` to sign in through your browser.\",\n );\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n","import { CopilotAuth } from \"./auth\";\nimport type { CopilotAuthOptions, FetchLike, JsonObject } from \"./types\";\n\nexport class CopilotClient {\n readonly #auth: CopilotAuth;\n readonly #fetch: FetchLike;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#auth = new CopilotAuth(options);\n this.#fetch = options.fetch ?? fetch;\n }\n\n async chatCompletions(body: JsonObject, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body: JSON.stringify(body),\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async forwardChatCompletions(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import { setTimeout as sleep } from \"node:timers/promises\";\nimport type { FetchLike, Logger } from \"./types\";\n\nexport const DEFAULT_GITHUB_COPILOT_CLIENT_ID = \"Iv23lijnNxm2e9UX3CF8\";\nconst DEFAULT_GITHUB_DOMAIN = \"github.com\";\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst POLLING_SAFETY_MARGIN_MS = 3_000;\n\nexport interface GithubCopilotDeviceLoginOptions {\n clientId?: string;\n domain?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n logger?: Logger;\n openBrowser?: (url: string) => void | Promise<void>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface GithubCopilotDeviceLoginResult {\n domain: string;\n token: string;\n}\n\ninterface DeviceCodeResponse {\n device_code?: string;\n expires_in?: number;\n interval?: number;\n user_code?: string;\n verification_uri?: string;\n}\n\ninterface DeviceTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n interval?: number;\n}\n\nexport async function githubCopilotDeviceLogin(\n options: GithubCopilotDeviceLoginOptions = {},\n): Promise<GithubCopilotDeviceLoginResult> {\n const env = options.env ?? process.env;\n const fetcher = options.fetch ?? fetch;\n const sleeper = options.sleep ?? sleep;\n const domain = normalizeDomain(\n options.domain ?? env.HOOPILOT_GITHUB_DOMAIN ?? DEFAULT_GITHUB_DOMAIN,\n );\n const clientId =\n options.clientId ??\n env.HOOPILOT_GITHUB_CLIENT_ID ??\n env.COPILOT_GITHUB_CLIENT_ID ??\n DEFAULT_GITHUB_COPILOT_CLIENT_ID;\n\n const device = await requestDeviceCode(fetcher, domain, clientId);\n const verificationUrl = device.verification_uri;\n const userCode = device.user_code;\n const deviceCode = device.device_code;\n if (!verificationUrl || !userCode || !deviceCode) {\n throw new Error(\"GitHub device authorization response is missing required fields.\");\n }\n\n options.logger?.info(`First copy your one-time code: ${userCode}`);\n options.logger?.info(`Open ${verificationUrl} in your browser to authorize Hoopilot.`);\n await options.openBrowser?.(verificationUrl);\n\n return {\n domain,\n token: await pollForAccessToken(fetcher, sleeper, domain, clientId, {\n deviceCode,\n expiresIn: positiveSeconds(device.expires_in, 900),\n interval: positiveSeconds(device.interval, 5),\n }),\n };\n}\n\nasync function requestDeviceCode(\n fetcher: FetchLike,\n domain: string,\n clientId: string,\n): Promise<DeviceCodeResponse> {\n const response = await fetcher(`https://${domain}/login/device/code`, {\n body: JSON.stringify({\n client_id: clientId,\n scope: \"read:user\",\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n if (!response.ok) {\n throw new Error(\n `GitHub device authorization failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n return (await response.json()) as DeviceCodeResponse;\n}\n\nasync function pollForAccessToken(\n fetcher: FetchLike,\n sleeper: (ms: number) => Promise<void>,\n domain: string,\n clientId: string,\n device: { deviceCode: string; expiresIn: number; interval: number },\n): Promise<string> {\n let intervalMs = device.interval * 1000 + POLLING_SAFETY_MARGIN_MS;\n const deadline = Date.now() + device.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await sleeper(intervalMs);\n const response = await fetcher(`https://${domain}/login/oauth/access_token`, {\n body: JSON.stringify({\n client_id: clientId,\n device_code: device.deviceCode,\n grant_type: DEVICE_GRANT_TYPE,\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub device token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const data = (await response.json()) as DeviceTokenResponse;\n if (data.access_token) {\n return data.access_token;\n }\n\n if (data.error === \"authorization_pending\") {\n continue;\n }\n if (data.error === \"slow_down\") {\n intervalMs =\n positiveSeconds(data.interval, device.interval + 5) * 1000 + POLLING_SAFETY_MARGIN_MS;\n continue;\n }\n if (data.error === \"expired_token\") {\n throw new Error(\"GitHub device login expired. Run `hoopilot login` again.\");\n }\n if (data.error === \"access_denied\") {\n throw new Error(\"GitHub device login was cancelled.\");\n }\n if (data.error) {\n throw new Error(data.error_description || `GitHub device login failed: ${data.error}`);\n }\n }\n\n throw new Error(\"GitHub device login timed out. Run `hoopilot login` again.\");\n}\n\nfunction oauthHeaders(): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"content-type\", \"application/json\");\n headers.set(\"user-agent\", \"hoopilot\");\n return headers;\n}\n\nfunction normalizeDomain(value: string): string {\n return value.replace(/^https?:\\/\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction positiveSeconds(value: unknown, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n","import pino from \"pino\";\nimport pretty from \"pino-pretty\";\nimport type { HoopilotLogger, HoopilotLoggerOptions, LogFormat, LogLevel } from \"./types\";\n\nexport const DEFAULT_LOG_FORMAT: LogFormat = \"pretty\";\nexport const DEFAULT_LOG_LEVEL: LogLevel = \"info\";\n\nconst LOG_FORMATS = [\"json\", \"pretty\"] as const;\nconst LOG_LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\", \"silent\"] as const;\nconst REDACT_PATHS = [\n \"apiKey\",\n \"authorization\",\n \"cookie\",\n \"headers.authorization\",\n \"headers.Authorization\",\n \"headers.cookie\",\n \"headers.Cookie\",\n \"headers.x-api-key\",\n \"headers.X-Api-Key\",\n \"token\",\n \"*.apiKey\",\n \"*.authorization\",\n \"*.cookie\",\n \"*.token\",\n \"*.headers.authorization\",\n \"*.headers.Authorization\",\n \"*.headers.cookie\",\n \"*.headers.Cookie\",\n \"*.headers.x-api-key\",\n \"*.headers.X-Api-Key\",\n];\n\nexport const noopLogger: HoopilotLogger = {\n child: () => noopLogger,\n debug: () => {},\n error: () => {},\n fatal: () => {},\n info: () => {},\n trace: () => {},\n warn: () => {},\n};\n\nexport function createHoopilotLogger(options: HoopilotLoggerOptions = {}): HoopilotLogger {\n const env = options.env ?? process.env;\n const level = parseLogLevel(options.level ?? env.HOOPILOT_LOG_LEVEL);\n const format = parseLogFormat(options.format ?? env.HOOPILOT_LOG_FORMAT);\n const pinoOptions: pino.LoggerOptions = {\n base: {\n service: \"hoopilot\",\n ...options.base,\n },\n level,\n redact: {\n censor: \"[Redacted]\",\n paths: REDACT_PATHS,\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n };\n\n if (format === \"pretty\") {\n return pino(\n pinoOptions,\n pretty({\n colorize: options.colorize ?? process.stderr.isTTY,\n destination: options.stream ?? 1,\n ignore: \"pid,hostname\",\n singleLine: true,\n translateTime: \"SYS:standard\",\n }),\n ) as HoopilotLogger;\n }\n\n if (options.stream) {\n return pino(pinoOptions, options.stream as pino.DestinationStream) as HoopilotLogger;\n }\n return pino(pinoOptions) as HoopilotLogger;\n}\n\nexport function parseLogFormat(value: string | undefined): LogFormat {\n if (!value) {\n return DEFAULT_LOG_FORMAT;\n }\n if (isLogFormat(value)) {\n return value;\n }\n throw new Error(`Invalid log format: ${value}. Expected one of: ${LOG_FORMATS.join(\", \")}.`);\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n if (!value) {\n return DEFAULT_LOG_LEVEL;\n }\n if (isLogLevel(value)) {\n return value;\n }\n throw new Error(`Invalid log level: ${value}. Expected one of: ${LOG_LEVELS.join(\", \")}.`);\n}\n\nexport function shouldCreateLogger(options: {\n env?: NodeJS.ProcessEnv;\n logFormat?: string;\n logger?: HoopilotLogger;\n logLevel?: string;\n}): boolean {\n return Boolean(\n options.logger ||\n options.logFormat ||\n options.logLevel ||\n options.env?.HOOPILOT_LOG_FORMAT ||\n options.env?.HOOPILOT_LOG_LEVEL,\n );\n}\n\nfunction isLogFormat(value: string): value is LogFormat {\n return (LOG_FORMATS as readonly string[]).includes(value);\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return (LOG_LEVELS as readonly string[]).includes(value);\n}\n","import type { JsonObject } from \"./types\";\n\nexport const DEFAULT_MODEL = \"gpt-4.1\";\n\ninterface ResponseStreamOptions {\n model: string;\n responseId?: string;\n}\n\ninterface AccumulatedToolCall {\n arguments: string;\n id: string;\n index: number;\n name: string;\n}\n\nexport function responsesRequestToChatCompletion(request: JsonObject): JsonObject {\n const messages: unknown[] = [];\n const instructions = contentToText(request.instructions);\n if (instructions) {\n messages.push({ content: instructions, role: \"system\" });\n }\n\n for (const message of inputToMessages(request.input)) {\n messages.push(message);\n }\n\n return removeUndefined({\n frequency_penalty: request.frequency_penalty,\n max_tokens: request.max_output_tokens ?? request.max_tokens,\n messages,\n metadata: request.metadata,\n model: contentToText(request.model) || DEFAULT_MODEL,\n presence_penalty: request.presence_penalty,\n reasoning_effort: asRecord(request.reasoning).effort,\n response_format: asRecord(request.text).format,\n seed: request.seed,\n stream: request.stream === true,\n temperature: request.temperature,\n tool_choice: chatToolChoice(request.tool_choice),\n tools: chatTools(request.tools),\n top_p: request.top_p,\n });\n}\n\nexport function completionsRequestToChatCompletion(request: JsonObject): JsonObject {\n return removeUndefined({\n max_tokens: request.max_tokens,\n messages: [{ content: promptToText(request.prompt), role: \"user\" }],\n model: contentToText(request.model) || DEFAULT_MODEL,\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport { createHoopilotLogger, noopLogger, shouldCreateLogger } from \"./logger\";\nimport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type {\n HoopilotLogger,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n StartedHoopilotServer,\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\nconst INVALID_JSON_MESSAGE = \"Request body must be valid JSON.\";\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const logger = serverLogger(options);\n\n return async (request: Request): Promise<Response> => {\n const startedAt = performance.now();\n const url = new URL(request.url);\n const apiPath = canonicalApiPath(url.pathname);\n const requestId = requestIdFor(request);\n const requestLogger = logger.child({\n method: request.method,\n path: url.pathname,\n requestId,\n route: routeFor(request.method, apiPath),\n });\n\n if (request.method === \"OPTIONS\") {\n return finishResponse(new Response(null, { headers: corsHeaders() }), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n\n if (!isAuthorized(request, apiKey)) {\n requestLogger.warn({ event: \"http.request.unauthorized\" }, \"invalid hoopilot api key\");\n return finishResponse(\n jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\"),\n {\n logger: requestLogger,\n requestId,\n startedAt,\n },\n );\n }\n\n try {\n if (request.method === \"GET\" && (apiPath === \"/\" || apiPath === \"/healthz\")) {\n return finishResponse(\n jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n }),\n { logger: requestLogger, requestId, startedAt },\n );\n }\n if (request.method === \"GET\" && apiPath === \"/v1/models\") {\n return finishResponse(await handleModels(client, request.signal, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/chat/completions\") {\n return finishResponse(await handleChatCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/completions\") {\n return finishResponse(await handleCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/responses\") {\n return finishResponse(await handleResponses(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n return finishResponse(\n jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`),\n { logger: requestLogger, requestId, startedAt },\n );\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"copilot.auth.missing\" },\n \"copilot auth failed\",\n );\n return finishResponse(jsonError(401, \"copilot_auth_error\", error.message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n const message = errorMessage(error);\n if (message === INVALID_JSON_MESSAGE) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request body was invalid json\",\n );\n } else {\n requestLogger.error(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request failed\",\n );\n }\n return finishResponse(jsonError(500, \"internal_error\", message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(\n client: CopilotClient,\n signal: AbortSignal,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n if (isUpstreamAuthStatus(upstream.status)) {\n return proxyError(upstream, logger);\n }\n logger.warn(\n {\n event: \"copilot.models.fallback\",\n upstreamPath: \"/models\",\n upstreamStatus: upstream.status,\n },\n \"falling back to built-in model list\",\n );\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n logUpstreamSuccess(logger, \"/models\", upstream.status);\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const chatRequest = responsesRequestToChatCompletion(body);\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n\n if (body.stream === true && upstream.body) {\n return new Response(\n responsesStreamFromChatStream(upstream.body, {\n model: typeof chatRequest.model === \"string\" ? chatRequest.model : \"gpt-4.1\",\n }),\n {\n headers: {\n ...corsHeaders(),\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"content-type\": \"text/event-stream; charset=utf-8\",\n },\n },\n );\n }\n\n return jsonResponse(chatCompletionToResponse(await upstream.json()));\n}\n\nasync function proxyError(upstream: Response, logger: HoopilotLogger): Promise<Response> {\n const text = await upstream.text();\n if (isUpstreamAuthStatus(upstream.status)) {\n logger.warn(\n { event: \"copilot.auth.rejected\", upstreamStatus: upstream.status },\n \"copilot rejected credential or account access\",\n );\n return jsonError(401, \"copilot_auth_error\", upstreamAuthMessage(text || upstream.statusText));\n }\n logger.warn(\n { event: \"copilot.request.failed\", upstreamStatus: upstream.status },\n \"copilot upstream request failed\",\n );\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isUpstreamAuthStatus(status: number): boolean {\n return status === 401 || status === 403;\n}\n\nfunction upstreamAuthMessage(message: string): string {\n return `GitHub Copilot rejected the credential or account access: ${message}`;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction serverLogger(options: HoopilotServerOptions): HoopilotLogger {\n if (options.logger) {\n return options.logger.child({ component: \"server\" });\n }\n if (shouldCreateLogger(options)) {\n return createHoopilotLogger({\n env: options.env,\n format: options.logFormat,\n level: options.logLevel,\n }).child({ component: \"server\" });\n }\n return noopLogger;\n}\n\nfunction finishResponse(\n response: Response,\n options: { logger: HoopilotLogger; requestId: string; startedAt: number },\n): Response {\n const withRequestId = responseWithRequestId(response, options.requestId);\n logRequestCompleted(options.logger, withRequestId, options.startedAt);\n return withRequestId;\n}\n\nfunction responseWithRequestId(response: Response, requestId: string): Response {\n const headers = new Headers(response.headers);\n headers.set(\"x-request-id\", requestId);\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nfunction logRequestCompleted(logger: HoopilotLogger, response: Response, startedAt: number): void {\n const fields: LogFields = {\n durationMs: Math.round((performance.now() - startedAt) * 100) / 100,\n event: \"http.request.completed\",\n status: response.status,\n stream: isStreamingResponse(response),\n };\n if (response.status >= 500) {\n logger.error(fields, \"request completed with server error\");\n return;\n }\n if (response.status >= 400) {\n logger.warn(fields, \"request completed with client error\");\n return;\n }\n logger.info(fields, \"request completed\");\n}\n\nfunction requestIdFor(request: Request): string {\n const existing = request.headers.get(\"x-request-id\")?.trim();\n return existing || crypto.randomUUID();\n}\n\nfunction canonicalApiPath(path: string): string {\n const withoutTrailingSlash = path.length > 1 ? path.replace(/\\/+$/, \"\") : path;\n switch (withoutTrailingSlash) {\n case \"/models\":\n return \"/v1/models\";\n case \"/chat/completions\":\n return \"/v1/chat/completions\";\n case \"/completions\":\n return \"/v1/completions\";\n case \"/responses\":\n return \"/v1/responses\";\n default:\n return withoutTrailingSlash;\n }\n}\n\nfunction routeFor(method: string, path: string): string {\n if (method === \"OPTIONS\") {\n return \"cors.preflight\";\n }\n if (method === \"GET\" && (path === \"/\" || path === \"/healthz\")) {\n return \"health\";\n }\n if (method === \"GET\" && path === \"/v1/models\") {\n return \"models\";\n }\n if (method === \"POST\" && path === \"/v1/chat/completions\") {\n return \"chat_completions\";\n }\n if (method === \"POST\" && path === \"/v1/completions\") {\n return \"completions\";\n }\n if (method === \"POST\" && path === \"/v1/responses\") {\n return \"responses\";\n }\n return \"not_found\";\n}\n\nfunction isStreamingResponse(response: Response): boolean {\n return response.headers.get(\"content-type\")?.includes(\"text/event-stream\") ?? false;\n}\n\nfunction logUpstreamSuccess(logger: HoopilotLogger, upstreamPath: string, status: number): void {\n logger.debug(\n {\n event: \"copilot.request.completed\",\n upstreamPath,\n upstreamStatus: status,\n },\n \"copilot upstream request completed\",\n );\n}\n\nfunction errorDetails(error: unknown): LogFields {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAAkE;AAClE,uBAA8B;AAUvB,SAAS,cAAc,MAAyB,QAAQ,KAAa;AAC1E,MAAI,IAAI,oBAAoB;AAC1B,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,OACJ,IAAI,mBACJ,IAAI,YACH,IAAI,WAAO,uBAAK,IAAI,MAAM,SAAS,QAAI,uBAAK,QAAQ,IAAI,GAAG,SAAS;AACvE,aAAO,uBAAK,MAAM,YAAY,WAAW;AAC3C;AAEO,SAAS,sBAAsB,OAAO,cAAc,GAAkC;AAC3F,MAAI;AACF,UAAM,SAAS,KAAK,UAAM,6BAAa,MAAM,MAAM,CAAC;AACpD,QAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,OAAO,MAAM,KAAK,IAAI;AACvE,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,YAAY,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa;AAAA,MACxE,WAAW,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAAA,MACrE,cAAc,OAAO,OAAO,iBAAiB,WAAW,OAAO,eAAe;AAAA,MAC9E,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AAAA,MAC5D;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,uBAAuB,MAAyB,OAAO,cAAc,GAAS;AAC5F,oCAAU,0BAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C;AAAA,IACE;AAAA,IACA,GAAG,KAAK;AAAA,MACN;AAAA,QACE,GAAG;AAAA,QACH,WAAW,KAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,IACD,EAAE,MAAM,IAAM;AAAA,EAChB;AACA,MAAI;AACF,kCAAU,MAAM,GAAK;AAAA,EACvB,QAAQ;AAAA,EAER;AACF;;;AC7DA,IAAM,+BAA+B;AACrC,IAAM,kBAAkB;AACxB,IAAM,sBAAsB,KAAK;AAE1B,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA,EACA;AAAA,EACT;AAAA,EAEA,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,iBAAiB,QAAQ,iBAAiB,QAAQ,KAAK;AAC5D,SAAK,qBAAqB;AAAA,MACxB,QAAQ,qBACN,QAAQ,KAAK,wBACb;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,YAAoC;AACxC,QAAI,KAAK,iBAAiB,KAAK,cAAc,cAAc,kBAAkB,KAAK,IAAI,GAAG;AACvF,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,SAAS,sBAAsB,KAAK,cAAc;AACxD,QAAI,QAAQ;AACV,aAAO,KAAK,aAAa;AAAA,QACvB,YAAY,kBAAkB,OAAO,cAAc,KAAK,kBAAkB;AAAA,QAC1E,aAAa,KAAK,IAAI,IAAI;AAAA,QAC1B,QAAQ;AAAA,QACR,OAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,QAAsC;AACjD,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,OAAuB;AAChD,SAAO,MAAM,QAAQ,QAAQ,EAAE;AACjC;;;ACrDO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EAET,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,QAAQ,IAAI,YAAY,OAAO;AACpC,SAAK,SAAS,QAAQ,SAAS;AAAA,EACjC;AAAA,EAEA,MAAM,gBAAgB,MAAkB,QAAyC;AAC/E,WAAO,KAAK,aAAa,qBAAqB;AAAA,MAC5C,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,uBAAuB,MAAc,QAAyC;AAClF,WAAO,KAAK,aAAa,qBAAqB;AAAA,MAC5C;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,QAAyC;AACpD,WAAO,KAAK,aAAa,WAAW;AAAA,MAClC,SAAS;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,MAAc,MAAsC;AACrE,UAAM,SAAS,MAAM,KAAK,MAAM,UAAU;AAC1C,UAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;AACxC,YAAQ,IAAI,UAAU,QAAQ,IAAI,QAAQ,KAAK,kBAAkB;AACjE,YAAQ,IAAI,iBAAiB,UAAU,OAAO,KAAK,EAAE;AACrD,YAAQ,IAAI,0BAA0B,aAAa;AACnD,YAAQ,IAAI,yBAAyB,gBAAgB;AACrD,YAAQ,IAAI,kBAAkB,gBAAgB;AAC9C,YAAQ,IAAI,iBAAiB,oBAAoB;AACjD,YAAQ,IAAI,cAAc,gBAAgB;AAC1C,YAAQ,IAAI,wBAAwB,YAAY;AAEhD,WAAO,KAAK,OAAO,GAAG,OAAO,UAAU,GAAG,IAAI,IAAI;AAAA,MAChD,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7DA,sBAAoC;AAG7B,IAAM,mCAAmC;AAChD,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;AAgCjC,eAAsB,yBACpB,UAA2C,CAAC,GACH;AACzC,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,UAAU,QAAQ,SAAS;AACjC,QAAM,UAAU,QAAQ,SAAS,gBAAAA;AACjC,QAAM,SAAS;AAAA,IACb,QAAQ,UAAU,IAAI,0BAA0B;AAAA,EAClD;AACA,QAAM,WACJ,QAAQ,YACR,IAAI,6BACJ,IAAI,4BACJ;AAEF,QAAM,SAAS,MAAM,kBAAkB,SAAS,QAAQ,QAAQ;AAChE,QAAM,kBAAkB,OAAO;AAC/B,QAAM,WAAW,OAAO;AACxB,QAAM,aAAa,OAAO;AAC1B,MAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,YAAY;AAChD,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACpF;AAEA,UAAQ,QAAQ,KAAK,kCAAkC,QAAQ,EAAE;AACjE,UAAQ,QAAQ,KAAK,QAAQ,eAAe,yCAAyC;AACrF,QAAM,QAAQ,cAAc,eAAe;AAE3C,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM,mBAAmB,SAAS,SAAS,QAAQ,UAAU;AAAA,MAClE;AAAA,MACA,WAAW,gBAAgB,OAAO,YAAY,GAAG;AAAA,MACjD,UAAU,gBAAgB,OAAO,UAAU,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AACF;AAEA,eAAe,kBACb,SACA,QACA,UAC6B;AAC7B,QAAM,WAAW,MAAM,QAAQ,WAAW,MAAM,sBAAsB;AAAA,IACpE,MAAM,KAAK,UAAU;AAAA,MACnB,WAAW;AAAA,MACX,OAAO;AAAA,IACT,CAAC;AAAA,IACD,SAAS,aAAa;AAAA,IACtB,QAAQ;AAAA,EACV,CAAC;AACD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,2CAA2C,SAAS,MAAM,KAAK,MAAM;AAAA,QACnE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEA,eAAe,mBACb,SACA,SACA,QACA,UACA,QACiB;AACjB,MAAI,aAAa,OAAO,WAAW,MAAO;AAC1C,QAAM,WAAW,KAAK,IAAI,IAAI,OAAO,YAAY;AAEjD,SAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,UAAM,QAAQ,UAAU;AACxB,UAAM,WAAW,MAAM,QAAQ,WAAW,MAAM,6BAA6B;AAAA,MAC3E,MAAM,KAAK,UAAU;AAAA,QACnB,WAAW;AAAA,QACX,aAAa,OAAO;AAAA,QACpB,YAAY;AAAA,MACd,CAAC;AAAA,MACD,SAAS,aAAa;AAAA,MACtB,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,4CAA4C,SAAS,MAAM,KAAK,MAAM;AAAA,UACpE;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,UAAU,yBAAyB;AAC1C;AAAA,IACF;AACA,QAAI,KAAK,UAAU,aAAa;AAC9B,mBACE,gBAAgB,KAAK,UAAU,OAAO,WAAW,CAAC,IAAI,MAAO;AAC/D;AAAA,IACF;AACA,QAAI,KAAK,UAAU,iBAAiB;AAClC,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,QAAI,KAAK,UAAU,iBAAiB;AAClC,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,QAAI,KAAK,OAAO;AACd,YAAM,IAAI,MAAM,KAAK,qBAAqB,+BAA+B,KAAK,KAAK,EAAE;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,4DAA4D;AAC9E;AAEA,SAAS,eAAwB;AAC/B,QAAM,UAAU,IAAI,QAAQ;AAC5B,UAAQ,IAAI,UAAU,kBAAkB;AACxC,UAAQ,IAAI,gBAAgB,kBAAkB;AAC9C,UAAQ,IAAI,cAAc,UAAU;AACpC,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MAAM,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC7D;AAEA,SAAS,gBAAgB,OAAgB,UAA0B;AACjE,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AACpF;AAEA,eAAe,iBAAiB,UAAqC;AACnE,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO,KAAK,MAAM,GAAG,GAAG;AAC1B;;;AC9KA,kBAAiB;AACjB,yBAAmB;AAGZ,IAAM,qBAAgC;AACtC,IAAM,oBAA8B;AAE3C,IAAM,cAAc,CAAC,QAAQ,QAAQ;AACrC,IAAM,aAAa,CAAC,SAAS,SAAS,QAAQ,QAAQ,SAAS,SAAS,QAAQ;AAChF,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,aAA6B;AAAA,EACxC,OAAO,MAAM;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AACf;AAEO,SAAS,qBAAqB,UAAiC,CAAC,GAAmB;AACxF,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,QAAQ,cAAc,QAAQ,SAAS,IAAI,kBAAkB;AACnE,QAAM,SAAS,eAAe,QAAQ,UAAU,IAAI,mBAAmB;AACvE,QAAM,cAAkC;AAAA,IACtC,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,GAAG,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA,WAAW,YAAAC,QAAK,iBAAiB;AAAA,EACnC;AAEA,MAAI,WAAW,UAAU;AACvB,eAAO,YAAAA;AAAA,MACL;AAAA,UACA,mBAAAC,SAAO;AAAA,QACL,UAAU,QAAQ,YAAY,QAAQ,OAAO;AAAA,QAC7C,aAAa,QAAQ,UAAU;AAAA,QAC/B,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ;AAClB,eAAO,YAAAD,SAAK,aAAa,QAAQ,MAAgC;AAAA,EACnE;AACA,aAAO,YAAAA,SAAK,WAAW;AACzB;AAEO,SAAS,eAAe,OAAsC;AACnE,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,MAAI,YAAY,KAAK,GAAG;AACtB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,uBAAuB,KAAK,sBAAsB,YAAY,KAAK,IAAI,CAAC,GAAG;AAC7F;AAEO,SAAS,cAAc,OAAqC;AACjE,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,MAAI,WAAW,KAAK,GAAG;AACrB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,sBAAsB,KAAK,sBAAsB,WAAW,KAAK,IAAI,CAAC,GAAG;AAC3F;AAEO,SAAS,mBAAmB,SAKvB;AACV,SAAO;AAAA,IACL,QAAQ,UACN,QAAQ,aACR,QAAQ,YACR,QAAQ,KAAK,uBACb,QAAQ,KAAK;AAAA,EACjB;AACF;AAEA,SAAS,YAAY,OAAmC;AACtD,SAAQ,YAAkC,SAAS,KAAK;AAC1D;AAEA,SAAS,WAAW,OAAkC;AACpD,SAAQ,WAAiC,SAAS,KAAK;AACzD;;;ACrHO,IAAM,gBAAgB;AActB,SAAS,iCAAiC,SAAiC;AAChF,QAAM,WAAsB,CAAC;AAC7B,QAAM,eAAe,cAAc,QAAQ,YAAY;AACvD,MAAI,cAAc;AAChB,aAAS,KAAK,EAAE,SAAS,cAAc,MAAM,SAAS,CAAC;AAAA,EACzD;AAEA,aAAW,WAAW,gBAAgB,QAAQ,KAAK,GAAG;AACpD,aAAS,KAAK,OAAO;AAAA,EACvB;AAEA,SAAO,gBAAgB;AAAA,IACrB,mBAAmB,QAAQ;AAAA,IAC3B,YAAY,QAAQ,qBAAqB,QAAQ;AAAA,IACjD;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB,OAAO,cAAc,QAAQ,KAAK,KAAK;AAAA,IACvC,kBAAkB,QAAQ;AAAA,IAC1B,kBAAkB,SAAS,QAAQ,SAAS,EAAE;AAAA,IAC9C,iBAAiB,SAAS,QAAQ,IAAI,EAAE;AAAA,IACxC,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ,WAAW;AAAA,IAC3B,aAAa,QAAQ;AAAA,IACrB,aAAa,eAAe,QAAQ,WAAW;AAAA,IAC/C,OAAO,UAAU,QAAQ,KAAK;AAAA,IAC9B,OAAO,QAAQ;AAAA,EACjB,CAAC;AACH;AAEO,SAAS,mCAAmC,SAAiC;AAClF,SAAO,gBAAgB;AAAA,IACrB,YAAY,QAAQ;AAAA,IACpB,UAAU,CAAC,EAAE,SAAS,aAAa,QAAQ,MAAM,GAAG,MAAM,OAAO,CAAC;AAAA,IAClE,OAAO,cAAc,QAAQ,KAAK,KAAK;AAAA,IACvC,QAAQ,QAAQ,WAAW;AAAA,IAC3B,aAAa,QAAQ;AAAA,IACrB,OAAO,QAAQ;AAAA,EACjB,CAAC;AACH;AAEO,SAAS,yBAAyB,YAAwB,YAAiC;AAChG,QAAM,KAAK,cAAc,QAAQ,SAAS,CAAC;AAC3C,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,UAAU,SAAS,OAAO,OAAO;AACvC,QAAM,QAAQ,cAAc,WAAW,KAAK,KAAK;AACjD,QAAM,SAAS,uBAAuB,OAAO;AAC7C,QAAM,QAAQ,cAAc,WAAW,KAAK;AAE5C,SAAO,gBAAgB;AAAA,IACrB,YAAY,aAAa;AAAA,IACzB,OAAO;AAAA,IACP;AAAA,IACA,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,UAAU,CAAC;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,aAAa,WAAW,MAAM;AAAA,IAC9B,qBAAqB;AAAA,IACrB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,aAAa;AAAA,IACb,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAEO,SAAS,2BAA2B,YAAoC;AAC7E,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,UAAU,SAAS,OAAO,OAAO;AACvC,SAAO,gBAAgB;AAAA,IACrB,SAAS;AAAA,MACP;AAAA,QACE,eAAe,OAAO,iBAAiB;AAAA,QACvC,OAAO;AAAA,QACP,UAAU;AAAA,QACV,MAAM,cAAc,QAAQ,OAAO;AAAA,MACrC;AAAA,IACF;AAAA,IACA,SAAS,WAAW,WAAW,aAAa;AAAA,IAC5C,IAAI,WAAW,MAAM,QAAQ,SAAS,CAAC;AAAA,IACvC,OAAO,WAAW,SAAS;AAAA,IAC3B,QAAQ;AAAA,IACR,OAAO,WAAW;AAAA,EACpB,CAAC;AACH;AAEO,SAAS,wBAAwB,UAA+B;AACrE,QAAM,SAAS,SAAS,QAAQ;AAChC,QAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAC9F,QAAM,SAAS,KACZ,IAAI,CAAC,UAAU,SAAS,KAAK,CAAC,EAC9B,OAAO,CAAC,UAAU,OAAO,MAAM,OAAO,QAAQ,EAC9C,IAAI,CAAC,WAAW;AAAA,IACf,SAAS,MAAM,WAAW;AAAA,IAC1B,IAAI,MAAM;AAAA,IACV,QAAQ;AAAA,IACR,UAAU,MAAM,YAAY;AAAA,EAC9B,EAAE;AAEJ,SAAO;AAAA,IACL,MAAM,OAAO,SAAS,IAAI,SAAS,eAAe;AAAA,IAClD,QAAQ;AAAA,EACV;AACF;AAEO,SAAS,iBAAoC;AAClD,SAAO;AAAA,IACL;AAAA,MACE,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEO,SAAS,8BACd,YACA,SAC4B;AAC5B,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,aAAa,QAAQ,cAAc,QAAQ,SAAS,CAAC;AAC3D,QAAM,YAAY,OAAO,SAAS,CAAC;AACnC,QAAM,YAAY,aAAa;AAC/B,MAAI,SAAS;AACb,MAAI,OAAO;AACX,QAAM,QAAQ,oBAAI,IAAiC;AAEnD,SAAO,IAAI,eAA2B;AAAA,IACpC,MAAM,MAAM,YAAY;AACtB,YAAM,UAAU,CAAC,OAAe,SAAgC;AAC9D,mBAAW,QAAQ,QAAQ,OAAO,UAAU,OAAO,IAAI,CAAC,CAAC;AAAA,MAC3D;AAEA,cAAQ,oBAAoB;AAAA,QAC1B,UAAU,mBAAmB,YAAY,QAAQ,OAAO,WAAW,eAAe,CAAC,CAAC;AAAA,QACpF,MAAM;AAAA,MACR,CAAC;AACD,cAAQ,8BAA8B;AAAA,QACpC,MAAM;AAAA,UACJ,SAAS,CAAC;AAAA,UACV,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,MAAM;AAAA,QACR;AAAA,QACA,cAAc;AAAA,QACd,MAAM;AAAA,MACR,CAAC;AACD,cAAQ,+BAA+B;AAAA,QACrC,eAAe;AAAA,QACf,SAAS;AAAA,QACT,cAAc;AAAA,QACd,MAAM;AAAA,UACJ,aAAa,CAAC;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAED,YAAM,SAAS,WAAW,UAAU;AACpC,UAAI;AACF,eAAO,MAAM;AACX,gBAAM,SAAS,MAAM,OAAO,KAAK;AACjC,cAAI,OAAO,MAAM;AACf;AAAA,UACF;AACA,oBAAU,QAAQ,OAAO,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AACvD,gBAAM,QAAQ,OAAO,MAAM,OAAO;AAClC,mBAAS,MAAM,IAAI,KAAK;AACxB,qBAAW,QAAQ,OAAO;AACxB,+BAAmB,MAAM,SAAS,OAAO,CAAC,UAAU;AAClD,sBAAQ;AAAA,YACV,CAAC;AAAA,UACH;AAAA,QACF;AACA,YAAI,QAAQ;AACV,6BAAmB,QAAQ,SAAS,OAAO,CAAC,UAAU;AACpD,oBAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAEA,cAAM,SAAS,kBAAkB,WAAW,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC;AACrE,gBAAQ,6BAA6B;AAAA,UACnC,eAAe;AAAA,UACf,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AACD,gBAAQ,8BAA8B;AAAA,UACpC,eAAe;AAAA,UACf,SAAS;AAAA,UACT,cAAc;AAAA,UACd,MAAM;AAAA,YACJ,aAAa,CAAC;AAAA,YACd;AAAA,YACA,MAAM;AAAA,UACR;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AACD,gBAAQ,6BAA6B;AAAA,UACnC,MAAM,OAAO,CAAC;AAAA,UACd,cAAc;AAAA,UACd,MAAM;AAAA,QACR,CAAC;AAED,cAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,gBAAM,OAAO,iBAAiB,IAAI;AAClC,gBAAM,cAAc,QAAQ;AAC5B,kBAAQ,8BAA8B;AAAA,YACpC;AAAA,YACA,cAAc;AAAA,YACd,MAAM;AAAA,UACR,CAAC;AACD,kBAAQ,yCAAyC;AAAA,YAC/C,WAAW,KAAK;AAAA,YAChB,SAAS,KAAK;AAAA,YACd,cAAc;AAAA,YACd,MAAM;AAAA,UACR,CAAC;AACD,kBAAQ,6BAA6B;AAAA,YACnC;AAAA,YACA,cAAc;AAAA,YACd,MAAM;AAAA,UACR,CAAC;AAAA,QACH,CAAC;AAED,gBAAQ,sBAAsB;AAAA,UAC5B,UAAU,mBAAmB,YAAY,QAAQ,OAAO,WAAW,aAAa,MAAM;AAAA,UACtF,MAAM;AAAA,QACR,CAAC;AACD,gBAAQ,QAAQ,QAAQ;AACxB,mBAAW,MAAM;AAAA,MACnB,SAAS,OAAO;AACd,mBAAW,MAAM,KAAK;AAAA,MACxB,UAAE;AACA,eAAO,YAAY;AAAA,MACrB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,gBAAgB,OAA2B;AAClD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,CAAC,EAAE,SAAS,OAAO,MAAM,OAAO,CAAC;AAAA,EAC1C;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAsB,CAAC;AAC7B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,OAAO,SAAS,wBAAwB;AAC1C,eAAS,KAAK;AAAA,QACZ,SAAS,cAAc,OAAO,MAAM;AAAA,QACpC,MAAM;AAAA,QACN,cAAc,cAAc,OAAO,OAAO;AAAA,MAC5C,CAAC;AACD;AAAA,IACF;AACA,QAAI,OAAO,SAAS,iBAAiB;AACnC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV;AAAA,YACE,UAAU;AAAA,cACR,WAAW,cAAc,OAAO,SAAS;AAAA,cACzC,MAAM,cAAc,OAAO,IAAI;AAAA,YACjC;AAAA,YACA,IAAI,cAAc,OAAO,OAAO,KAAK,cAAc,OAAO,EAAE;AAAA,YAC5D,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AACA,UAAM,OAAO,eAAe,cAAc,OAAO,IAAI,CAAC;AACtD,UAAM,UAAU,mBAAmB,OAAO,OAAO;AACjD,QAAI,QAAQ,YAAY,QAAW;AACjC,eAAS,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,IACjC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,SAA0D;AACpF,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,cAAc,OAAO,KAAK;AAAA,EACnC;AAEA,QAAM,QAAsB,CAAC;AAC7B,aAAW,QAAQ,SAAS;AAC1B,UAAM,SAAS,SAAS,IAAI;AAC5B,UAAM,OAAO,cAAc,OAAO,IAAI;AACtC,QAAI,SAAS,gBAAgB,SAAS,iBAAiB,SAAS,QAAQ;AACtE,YAAM,KAAK,EAAE,MAAM,cAAc,OAAO,IAAI,GAAG,MAAM,OAAO,CAAC;AAAA,IAC/D;AACA,QAAI,SAAS,eAAe;AAC1B,YAAM,WAAW,cAAc,OAAO,SAAS;AAC/C,UAAI,UAAU;AACZ,cAAM,KAAK,EAAE,WAAW,EAAE,KAAK,SAAS,GAAG,MAAM,YAAY,CAAC;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM,CAAC,SAAS,KAAK,SAAS,MAAM,GAAG;AAC/C,WAAO,MAAM,IAAI,CAAC,SAAS,cAAc,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,aAAa,QAAyB;AAC7C,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO,OAAO,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC,EAAE,KAAK,IAAI;AAAA,EAC5D;AACA,SAAO,cAAc,MAAM;AAC7B;AAEA,SAAS,cAAc,SAA0B;AAC/C,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,YAAY,OAAO,YAAY,WAAW;AAC/D,WAAO,OAAO,OAAO;AAAA,EACvB;AACA,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAO,QACJ,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC,EACjC,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,EACd;AACA,MAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,SAAS,UAAU;AACnC,aAAO,OAAO;AAAA,IAChB;AACA,QAAI,OAAO,OAAO,gBAAgB,UAAU;AAC1C,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAkC;AACxD,MAAI,SAAS,eAAe,SAAS,eAAe,SAAS,YAAY,SAAS,QAAQ;AACxF,WAAO,SAAS,cAAc,WAAW;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,UAAU,OAAuC;AACxD,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,MACf,IAAI,CAAC,SAAS,SAAS,IAAI,CAAC,EAC5B,OAAO,CAAC,SAAS,KAAK,SAAS,UAAU,EACzC,IAAI,CAAC,UAAU;AAAA,IACd,UAAU,gBAAgB;AAAA,MACxB,aAAa,KAAK;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,IACD,MAAM;AAAA,EACR,EAAE;AACJ,SAAO,UAAU,SAAS,IAAI,YAAY;AAC5C;AAEA,SAAS,eAAe,YAA8B;AACpD,MAAI,OAAO,eAAe,YAAY,eAAe,QAAW;AAC9D,WAAO;AAAA,EACT;AACA,QAAM,SAAS,SAAS,UAAU;AAClC,MAAI,OAAO,SAAS,cAAc,OAAO,OAAO,SAAS,UAAU;AACjE,WAAO,EAAE,UAAU,EAAE,MAAM,OAAO,KAAK,GAAG,MAAM,WAAW;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,SAAgD;AAC9E,QAAM,SAAuB,CAAC;AAC9B,QAAM,OAAO,cAAc,QAAQ,OAAO;AAC1C,MAAI,MAAM;AACR,WAAO,KAAK,kBAAkB,IAAI,CAAC;AAAA,EACrC;AACA,QAAM,YAAY,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,aAAa,CAAC;AAC5E,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS,SAAS,QAAQ;AAChC,UAAM,KAAK,SAAS,OAAO,QAAQ;AACnC,WAAO;AAAA,MACL,iBAAiB;AAAA,QACf,WAAW,cAAc,GAAG,SAAS;AAAA,QACrC,IAAI,cAAc,OAAO,EAAE,KAAK,QAAQ,SAAS,CAAC;AAAA,QAClD,OAAO,OAAO;AAAA,QACd,MAAM,cAAc,GAAG,IAAI;AAAA,MAC7B,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,MAAc,KAAK,OAAO,SAAS,CAAC,IAAgB;AAC7E,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,aAAa,CAAC;AAAA,QACd;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AACF;AAEA,SAAS,iBAAiB,MAAuC;AAC/D,SAAO;AAAA,IACL,WAAW,KAAK;AAAA,IAChB,SAAS,KAAK;AAAA,IACd,IAAI,MAAM,SAAS,CAAC;AAAA,IACpB,MAAM,KAAK;AAAA,IACX,QAAQ;AAAA,IACR,MAAM;AAAA,EACR;AACF;AAEA,SAAS,WAAW,QAA8B;AAChD,SAAO,OACJ,QAAQ,CAAC,SAAS;AACjB,UAAM,UAAU,KAAK;AACrB,WAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC;AAAA,EAC7C,CAAC,EACA,IAAI,CAAC,SAAS,cAAc,SAAS,IAAI,EAAE,IAAI,CAAC,EAChD,OAAO,OAAO,EACd,KAAK,EAAE;AACZ;AAEA,SAAS,cAAc,OAAmC;AACxD,QAAM,SAAS,SAAS,KAAK;AAC7B,MAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AACpC,WAAO;AAAA,EACT;AACA,SAAO,gBAAgB;AAAA,IACrB,cAAc,OAAO;AAAA,IACrB,sBAAsB,OAAO;AAAA,IAC7B,eAAe,OAAO;AAAA,IACtB,uBAAuB,OAAO;AAAA,IAC9B,cAAc,OAAO;AAAA,EACvB,CAAC;AACH;AAEA,SAAS,YAAY,YAAiD;AACpE,QAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,IAAI,WAAW,UAAU,CAAC;AAC1E,SAAO,SAAS,QAAQ,CAAC,CAAC;AAC5B;AAEA,SAAS,mBACP,MACA,SACA,OACA,YACM;AACN,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,QAAQ,WAAW,OAAO,GAAG;AAChC;AAAA,EACF;AACA,QAAM,OAAO,QAAQ,MAAM,QAAQ,MAAM,EAAE,KAAK;AAChD,MAAI,CAAC,QAAQ,SAAS,UAAU;AAC9B;AAAA,EACF;AAEA,QAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,CAAC,QAAQ;AACX;AAAA,EACF;AACA,QAAM,SAAS,YAAY,MAAM;AACjC,QAAM,QAAQ,SAAS,OAAO,KAAK;AACnC,QAAM,UAAU,cAAc,MAAM,OAAO;AAC3C,MAAI,SAAS;AACX,eAAW,OAAO;AAClB,YAAQ,8BAA8B;AAAA,MACpC,eAAe;AAAA,MACf,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,MAAM,QAAQ,MAAM,UAAU,IAAI,MAAM,aAAa,CAAC;AACxE,aAAW,YAAY,WAAW;AAChC,UAAM,SAAS,SAAS,QAAQ;AAChC,UAAM,KAAK,SAAS,OAAO,QAAQ;AACnC,UAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,MAAM;AACtE,UAAM,WAAW,MAAM,IAAI,KAAK,KAAK;AAAA,MACnC,WAAW;AAAA,MACX,IAAI,cAAc,OAAO,EAAE,KAAK,QAAQ,SAAS,CAAC;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,IACR;AACA,aAAS,KAAK,cAAc,OAAO,EAAE,KAAK,SAAS;AACnD,aAAS,QAAQ,cAAc,GAAG,IAAI;AACtC,aAAS,aAAa,cAAc,GAAG,SAAS;AAChD,UAAM,IAAI,OAAO,QAAQ;AAAA,EAC3B;AACF;AAEA,SAAS,kBACP,WACA,MACA,OACc;AACd,SAAO,CAAC,kBAAkB,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,iBAAiB,IAAI,CAAC,CAAC;AAC5F;AAEA,SAAS,mBACP,IACA,OACA,WACA,QACA,QACY;AACZ,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,OAAO;AAAA,IACP;AAAA,IACA,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,UAAU,CAAC;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,qBAAqB;AAAA,IACrB;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,OAAe,MAAqC;AACrE,MAAI,SAAS,UAAU;AACrB,WAAO;AAAA,EACT;AACA,SAAO,UAAU,KAAK;AAAA,QAAW,KAAK,UAAU,IAAI,CAAC;AAAA;AAAA;AACvD;AAEA,SAAS,UAAU,MAAsC;AACvD,MAAI;AACF,WAAO,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,QAAgC;AACvD,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC7F;AAEA,SAAS,SAAS,OAA4B;AAC5C,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAuB,CAAC;AAChG;AAEA,SAAS,WAAmB;AAC1B,SAAO,OAAO,WAAW,EAAE,WAAW,KAAK,EAAE;AAC/C;AAEA,SAAS,eAAuB;AAC9B,SAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACrC;;;ACzkBA,IAAM,eAAe;AACrB,IAAM,eAAe;AACrB,IAAM,uBAAuB;AAEtB,SAAS,sBAAsB,UAAiC,CAAC,GAAG;AACzE,QAAM,SAAS,IAAI,cAAc,OAAO;AACxC,QAAM,SAAS,QAAQ,UAAU,QAAQ,KAAK;AAC9C,QAAM,SAAS,aAAa,OAAO;AAEnC,SAAO,OAAO,YAAwC;AACpD,UAAM,YAAY,YAAY,IAAI;AAClC,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,UAAM,UAAU,iBAAiB,IAAI,QAAQ;AAC7C,UAAM,YAAY,aAAa,OAAO;AACtC,UAAM,gBAAgB,OAAO,MAAM;AAAA,MACjC,QAAQ,QAAQ;AAAA,MAChB,MAAM,IAAI;AAAA,MACV;AAAA,MACA,OAAO,SAAS,QAAQ,QAAQ,OAAO;AAAA,IACzC,CAAC;AAED,QAAI,QAAQ,WAAW,WAAW;AAChC,aAAO,eAAe,IAAI,SAAS,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC,GAAG;AAAA,QACpE,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,aAAa,SAAS,MAAM,GAAG;AAClC,oBAAc,KAAK,EAAE,OAAO,4BAA4B,GAAG,0BAA0B;AACrF,aAAO;AAAA,QACL,UAAU,KAAK,mBAAmB,sCAAsC;AAAA,QACxE;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,UAAI,QAAQ,WAAW,UAAU,YAAY,OAAO,YAAY,aAAa;AAC3E,eAAO;AAAA,UACL,aAAa;AAAA,YACX,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,QAAQ;AAAA,UACV,CAAC;AAAA,UACD,EAAE,QAAQ,eAAe,WAAW,UAAU;AAAA,QAChD;AAAA,MACF;AACA,UAAI,QAAQ,WAAW,SAAS,YAAY,cAAc;AACxD,eAAO,eAAe,MAAM,aAAa,QAAQ,QAAQ,QAAQ,aAAa,GAAG;AAAA,UAC/E,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,UAAI,QAAQ,WAAW,UAAU,YAAY,wBAAwB;AACnE,eAAO,eAAe,MAAM,sBAAsB,QAAQ,SAAS,aAAa,GAAG;AAAA,UACjF,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,UAAI,QAAQ,WAAW,UAAU,YAAY,mBAAmB;AAC9D,eAAO,eAAe,MAAM,kBAAkB,QAAQ,SAAS,aAAa,GAAG;AAAA,UAC7E,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,UAAI,QAAQ,WAAW,UAAU,YAAY,iBAAiB;AAC5D,eAAO,eAAe,MAAM,gBAAgB,QAAQ,SAAS,aAAa,GAAG;AAAA,UAC3E,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO;AAAA,QACL,UAAU,KAAK,aAAa,gBAAgB,QAAQ,MAAM,IAAI,IAAI,QAAQ,GAAG;AAAA,QAC7E,EAAE,QAAQ,eAAe,WAAW,UAAU;AAAA,MAChD;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,kBAAkB;AACrC,sBAAc;AAAA,UACZ,EAAE,KAAK,aAAa,KAAK,GAAG,OAAO,uBAAuB;AAAA,UAC1D;AAAA,QACF;AACA,eAAO,eAAe,UAAU,KAAK,sBAAsB,MAAM,OAAO,GAAG;AAAA,UACzE,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AACA,YAAM,UAAU,aAAa,KAAK;AAClC,UAAI,YAAY,sBAAsB;AACpC,sBAAc;AAAA,UACZ,EAAE,KAAK,aAAa,KAAK,GAAG,OAAO,sBAAsB;AAAA,UACzD;AAAA,QACF;AAAA,MACF,OAAO;AACL,sBAAc;AAAA,UACZ,EAAE,KAAK,aAAa,KAAK,GAAG,OAAO,sBAAsB;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AACA,aAAO,eAAe,UAAU,KAAK,kBAAkB,OAAO,GAAG;AAAA,QAC/D,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,UAAiC,CAAC,GAA0B;AAC9F,QAAM,OAAO,QAAQ,QAAQ,QAAQ,KAAK,QAAQ;AAClD,QAAM,OAAO,OAAO,QAAQ,QAAQ,QAAQ,KAAK,QAAQ,YAAY;AACrE,QAAM,SAAS,QAAQ,UAAU,QAAQ,KAAK;AAC9C,QAAM,uBACJ,QAAQ,wBAAwB,QAAQ,KAAK,mCAAmC;AAElF,MAAI,CAAC,eAAe,IAAI,KAAK,CAAC,UAAU,CAAC,sBAAsB;AAC7D,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,MAAM;AAAA,IACvB,OAAO,sBAAsB;AAAA,MAC3B,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,KAAK,UAAU,IAAI,IAAI,OAAO,IAAI;AAAA,EACpC;AACF;AAEA,eAAe,aACb,QACA,QACA,QACmB;AACnB,QAAM,WAAW,MAAM,OAAO,OAAO,MAAM;AAC3C,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,qBAAqB,SAAS,MAAM,GAAG;AACzC,aAAO,WAAW,UAAU,MAAM;AAAA,IACpC;AACA,WAAO;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,cAAc;AAAA,QACd,gBAAgB,SAAS;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AACA,WAAO,aAAa,EAAE,MAAM,eAAe,GAAG,QAAQ,OAAO,CAAC;AAAA,EAChE;AACA,qBAAmB,QAAQ,WAAW,SAAS,MAAM;AACrD,SAAO,aAAa,wBAAwB,MAAM,SAAS,KAAK,CAAC,CAAC;AACpE;AAEA,eAAe,sBACb,QACA,SACA,QACmB;AACnB,QAAM,WAAW,MAAM,OAAO,uBAAuB,MAAM,QAAQ,KAAK,GAAG,QAAQ,MAAM;AACzF,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,WAAW,UAAU,MAAM;AAAA,EACpC;AACA,qBAAmB,QAAQ,qBAAqB,SAAS,MAAM;AAC/D,SAAO,cAAc,QAAQ;AAC/B;AAEA,eAAe,kBACb,QACA,SACA,QACmB;AACnB,QAAM,OAAO,MAAM,SAAS,OAAO;AACnC,QAAM,WAAW,MAAM,OAAO;AAAA,IAC5B,mCAAmC,IAAI;AAAA,IACvC,QAAQ;AAAA,EACV;AACA,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,WAAW,UAAU,MAAM;AAAA,EACpC;AACA,qBAAmB,QAAQ,qBAAqB,SAAS,MAAM;AAC/D,SAAO,aAAa,2BAA2B,MAAM,SAAS,KAAK,CAAC,CAAC;AACvE;AAEA,eAAe,gBACb,QACA,SACA,QACmB;AACnB,QAAM,OAAO,MAAM,SAAS,OAAO;AACnC,QAAM,cAAc,iCAAiC,IAAI;AACzD,QAAM,WAAW,MAAM,OAAO,gBAAgB,aAAa,QAAQ,MAAM;AACzE,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,WAAW,UAAU,MAAM;AAAA,EACpC;AACA,qBAAmB,QAAQ,qBAAqB,SAAS,MAAM;AAE/D,MAAI,KAAK,WAAW,QAAQ,SAAS,MAAM;AACzC,WAAO,IAAI;AAAA,MACT,8BAA8B,SAAS,MAAM;AAAA,QAC3C,OAAO,OAAO,YAAY,UAAU,WAAW,YAAY,QAAQ;AAAA,MACrE,CAAC;AAAA,MACD;AAAA,QACE,SAAS;AAAA,UACP,GAAG,YAAY;AAAA,UACf,iBAAiB;AAAA,UACjB,YAAY;AAAA,UACZ,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,aAAa,yBAAyB,MAAM,SAAS,KAAK,CAAC,CAAC;AACrE;AAEA,eAAe,WAAW,UAAoB,QAA2C;AACvF,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,MAAI,qBAAqB,SAAS,MAAM,GAAG;AACzC,WAAO;AAAA,MACL,EAAE,OAAO,yBAAyB,gBAAgB,SAAS,OAAO;AAAA,MAClE;AAAA,IACF;AACA,WAAO,UAAU,KAAK,sBAAsB,oBAAoB,QAAQ,SAAS,UAAU,CAAC;AAAA,EAC9F;AACA,SAAO;AAAA,IACL,EAAE,OAAO,0BAA0B,gBAAgB,SAAS,OAAO;AAAA,IACnE;AAAA,EACF;AACA,SAAO,UAAU,SAAS,QAAQ,iBAAiB,QAAQ,SAAS,UAAU;AAChF;AAEA,SAAS,cAAc,UAA8B;AACnD,QAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAC5C,UAAQ,OAAO,kBAAkB;AACjC,UAAQ,OAAO,gBAAgB;AAC/B,UAAQ,OAAO,mBAAmB;AAClC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,CAAC,GAAG;AACxD,YAAQ,IAAI,KAAK,KAAK;AAAA,EACxB;AACA,SAAO,IAAI,SAAS,SAAS,MAAM;AAAA,IACjC;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,YAAY,SAAS;AAAA,EACvB,CAAC;AACH;AAEA,eAAe,SAAS,SAAuC;AAC7D,MAAI;AACF,UAAM,QAAQ,MAAM,QAAQ,KAAK;AACjC,WAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAuB,CAAC;AAAA,EAChG,QAAQ;AACN,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AACF;AAEA,SAAS,aAAa,MAAkB,SAAS,KAAe;AAC9D,SAAO,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,IACxC,SAAS;AAAA,MACP,GAAG,YAAY;AAAA,MACf,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,SAAS,UAAU,QAAgB,MAAc,SAA2B;AAC1E,SAAO;AAAA,IACL;AAAA,MACE,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,cAAsC;AAC7C,SAAO;AAAA,IACL,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,IAChC,+BAA+B;AAAA,EACjC;AACF;AAEA,SAAS,aAAa,SAAkB,QAAqC;AAC3E,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,gBAAgB,QAAQ,QAAQ,IAAI,eAAe,KAAK;AAC9D,QAAM,SAAS,cAAc,MAAM,kBAAkB,IAAI,CAAC;AAC1D,SAAO,WAAW,UAAU,QAAQ,QAAQ,IAAI,WAAW,MAAM;AACnE;AAEA,SAAS,qBAAqB,QAAyB;AACrD,SAAO,WAAW,OAAO,WAAW;AACtC;AAEA,SAAS,oBAAoB,SAAyB;AACpD,SAAO,6DAA6D,OAAO;AAC7E;AAEA,SAAS,eAAe,MAAuB;AAC7C,SAAO,SAAS,eAAe,SAAS,eAAe,SAAS;AAClE;AAEA,SAAS,aAAa,OAAwB;AAC5C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,aAAa,SAAgD;AACpE,MAAI,QAAQ,QAAQ;AAClB,WAAO,QAAQ,OAAO,MAAM,EAAE,WAAW,SAAS,CAAC;AAAA,EACrD;AACA,MAAI,mBAAmB,OAAO,GAAG;AAC/B,WAAO,qBAAqB;AAAA,MAC1B,KAAK,QAAQ;AAAA,MACb,QAAQ,QAAQ;AAAA,MAChB,OAAO,QAAQ;AAAA,IACjB,CAAC,EAAE,MAAM,EAAE,WAAW,SAAS,CAAC;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,eACP,UACA,SACU;AACV,QAAM,gBAAgB,sBAAsB,UAAU,QAAQ,SAAS;AACvE,sBAAoB,QAAQ,QAAQ,eAAe,QAAQ,SAAS;AACpE,SAAO;AACT;AAEA,SAAS,sBAAsB,UAAoB,WAA6B;AAC9E,QAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAC5C,UAAQ,IAAI,gBAAgB,SAAS;AACrC,SAAO,IAAI,SAAS,SAAS,MAAM;AAAA,IACjC;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,YAAY,SAAS;AAAA,EACvB,CAAC;AACH;AAEA,SAAS,oBAAoB,QAAwB,UAAoB,WAAyB;AAChG,QAAM,SAAoB;AAAA,IACxB,YAAY,KAAK,OAAO,YAAY,IAAI,IAAI,aAAa,GAAG,IAAI;AAAA,IAChE,OAAO;AAAA,IACP,QAAQ,SAAS;AAAA,IACjB,QAAQ,oBAAoB,QAAQ;AAAA,EACtC;AACA,MAAI,SAAS,UAAU,KAAK;AAC1B,WAAO,MAAM,QAAQ,qCAAqC;AAC1D;AAAA,EACF;AACA,MAAI,SAAS,UAAU,KAAK;AAC1B,WAAO,KAAK,QAAQ,qCAAqC;AACzD;AAAA,EACF;AACA,SAAO,KAAK,QAAQ,mBAAmB;AACzC;AAEA,SAAS,aAAa,SAA0B;AAC9C,QAAM,WAAW,QAAQ,QAAQ,IAAI,cAAc,GAAG,KAAK;AAC3D,SAAO,YAAY,OAAO,WAAW;AACvC;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,QAAM,uBAAuB,KAAK,SAAS,IAAI,KAAK,QAAQ,QAAQ,EAAE,IAAI;AAC1E,UAAQ,sBAAsB;AAAA,IAC5B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,SAAS,QAAgB,MAAsB;AACtD,MAAI,WAAW,WAAW;AACxB,WAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,SAAS,OAAO,SAAS,aAAa;AAC7D,WAAO;AAAA,EACT;AACA,MAAI,WAAW,SAAS,SAAS,cAAc;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,SAAS,wBAAwB;AACxD,WAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,SAAS,mBAAmB;AACnD,WAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAU,SAAS,iBAAiB;AACjD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,UAA6B;AACxD,SAAO,SAAS,QAAQ,IAAI,cAAc,GAAG,SAAS,mBAAmB,KAAK;AAChF;AAEA,SAAS,mBAAmB,QAAwB,cAAsB,QAAsB;AAC9F,SAAO;AAAA,IACL;AAAA,MACE,OAAO;AAAA,MACP;AAAA,MACA,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAA2B;AAC/C,MAAI,iBAAiB,OAAO;AAC1B,WAAO;AAAA,MACL,SAAS,MAAM;AAAA,MACf,MAAM,MAAM;AAAA,MACZ,OAAO,MAAM;AAAA,IACf;AAAA,EACF;AACA,SAAO,EAAE,SAAS,OAAO,KAAK,EAAE;AAClC;","names":["sleep","pino","pretty"]}
|
package/dist/index.js
CHANGED
|
@@ -904,12 +904,13 @@ function createHoopilotHandler(options = {}) {
|
|
|
904
904
|
return async (request) => {
|
|
905
905
|
const startedAt = performance.now();
|
|
906
906
|
const url = new URL(request.url);
|
|
907
|
+
const apiPath = canonicalApiPath(url.pathname);
|
|
907
908
|
const requestId = requestIdFor(request);
|
|
908
909
|
const requestLogger = logger.child({
|
|
909
910
|
method: request.method,
|
|
910
911
|
path: url.pathname,
|
|
911
912
|
requestId,
|
|
912
|
-
route: routeFor(request.method,
|
|
913
|
+
route: routeFor(request.method, apiPath)
|
|
913
914
|
});
|
|
914
915
|
if (request.method === "OPTIONS") {
|
|
915
916
|
return finishResponse(new Response(null, { headers: corsHeaders() }), {
|
|
@@ -930,7 +931,7 @@ function createHoopilotHandler(options = {}) {
|
|
|
930
931
|
);
|
|
931
932
|
}
|
|
932
933
|
try {
|
|
933
|
-
if (request.method === "GET" && (
|
|
934
|
+
if (request.method === "GET" && (apiPath === "/" || apiPath === "/healthz")) {
|
|
934
935
|
return finishResponse(
|
|
935
936
|
jsonResponse({
|
|
936
937
|
name: "hoopilot",
|
|
@@ -940,28 +941,28 @@ function createHoopilotHandler(options = {}) {
|
|
|
940
941
|
{ logger: requestLogger, requestId, startedAt }
|
|
941
942
|
);
|
|
942
943
|
}
|
|
943
|
-
if (request.method === "GET" &&
|
|
944
|
+
if (request.method === "GET" && apiPath === "/v1/models") {
|
|
944
945
|
return finishResponse(await handleModels(client, request.signal, requestLogger), {
|
|
945
946
|
logger: requestLogger,
|
|
946
947
|
requestId,
|
|
947
948
|
startedAt
|
|
948
949
|
});
|
|
949
950
|
}
|
|
950
|
-
if (request.method === "POST" &&
|
|
951
|
+
if (request.method === "POST" && apiPath === "/v1/chat/completions") {
|
|
951
952
|
return finishResponse(await handleChatCompletions(client, request, requestLogger), {
|
|
952
953
|
logger: requestLogger,
|
|
953
954
|
requestId,
|
|
954
955
|
startedAt
|
|
955
956
|
});
|
|
956
957
|
}
|
|
957
|
-
if (request.method === "POST" &&
|
|
958
|
+
if (request.method === "POST" && apiPath === "/v1/completions") {
|
|
958
959
|
return finishResponse(await handleCompletions(client, request, requestLogger), {
|
|
959
960
|
logger: requestLogger,
|
|
960
961
|
requestId,
|
|
961
962
|
startedAt
|
|
962
963
|
});
|
|
963
964
|
}
|
|
964
|
-
if (request.method === "POST" &&
|
|
965
|
+
if (request.method === "POST" && apiPath === "/v1/responses") {
|
|
965
966
|
return finishResponse(await handleResponses(client, request, requestLogger), {
|
|
966
967
|
logger: requestLogger,
|
|
967
968
|
requestId,
|
|
@@ -1226,6 +1227,21 @@ function requestIdFor(request) {
|
|
|
1226
1227
|
const existing = request.headers.get("x-request-id")?.trim();
|
|
1227
1228
|
return existing || crypto.randomUUID();
|
|
1228
1229
|
}
|
|
1230
|
+
function canonicalApiPath(path) {
|
|
1231
|
+
const withoutTrailingSlash = path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
1232
|
+
switch (withoutTrailingSlash) {
|
|
1233
|
+
case "/models":
|
|
1234
|
+
return "/v1/models";
|
|
1235
|
+
case "/chat/completions":
|
|
1236
|
+
return "/v1/chat/completions";
|
|
1237
|
+
case "/completions":
|
|
1238
|
+
return "/v1/completions";
|
|
1239
|
+
case "/responses":
|
|
1240
|
+
return "/v1/responses";
|
|
1241
|
+
default:
|
|
1242
|
+
return withoutTrailingSlash;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1229
1245
|
function routeFor(method, path) {
|
|
1230
1246
|
if (method === "OPTIONS") {
|
|
1231
1247
|
return "cors.preflight";
|