@openhoo/hoopilot 0.2.3 → 0.2.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/README.md CHANGED
@@ -19,7 +19,7 @@ Before the npm package is published, run the same binary directly from GitHub:
19
19
  npx github:openhoo/hoopilot
20
20
  ```
21
21
 
22
- By default Hoopilot listens on `127.0.0.1:4141`, reads a GitHub token from `COPILOT_GITHUB_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`, or `gh auth token`, and exchanges it for a Copilot API token when GitHub supports the exchange endpoint for the account.
22
+ By default Hoopilot listens on `127.0.0.1:4141`, uses `COPILOT_API_TOKEN` when provided, otherwise reads a GitHub CLI OAuth token from `COPILOT_GITHUB_TOKEN` or `gh auth token`, and uses that token with Copilot.
23
23
 
24
24
  For a local API key:
25
25
 
@@ -61,15 +61,11 @@ or:
61
61
  COPILOT_GITHUB_TOKEN=$(gh auth token) npx @openhoo/hoopilot
62
62
  ```
63
63
 
64
- You can also [create a fine-grained personal access token](https://github.com/settings/personal-access-tokens/new) for the GitHub account that has Copilot access. GitHub's [personal access token documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) explains how fine-grained tokens and permissions work.
65
-
66
- ```sh
67
- COPILOT_GITHUB_TOKEN=github_pat_... HOOPILOT_API_KEY=local-key npx @openhoo/hoopilot
68
- ```
64
+ Personal access tokens are not supported by GitHub Copilot's token exchange or chat endpoints. Hoopilot rejects classic and fine-grained PAT prefixes. Use `gh auth token` for the GitHub CLI OAuth path, or pass a short-lived Copilot bearer token with `COPILOT_API_TOKEN`.
69
65
 
70
66
  Supported credential environment variables:
71
67
 
72
- - `COPILOT_GITHUB_TOKEN`, `GITHUB_COPILOT_GITHUB_TOKEN`, `GITHUB_TOKEN`, or `GH_TOKEN`: GitHub OAuth token for an account with Copilot access.
68
+ - `COPILOT_GITHUB_TOKEN` or `GITHUB_COPILOT_GITHUB_TOKEN`: GitHub CLI OAuth token for an account with Copilot access. Personal access tokens are rejected.
73
69
  - `COPILOT_API_TOKEN`, `GITHUB_COPILOT_API_TOKEN`, or `GITHUB_COPILOT_TOKEN`: short-lived Copilot API bearer token.
74
70
  - `COPILOT_API_BASE_URL`: upstream Copilot API base URL override.
75
71
  - `COPILOT_TOKEN_EXCHANGE_URL`: GitHub token exchange endpoint override.
@@ -78,12 +74,10 @@ Auth modes:
78
74
 
79
75
  ```sh
80
76
  npx @openhoo/hoopilot --auth-mode auto
81
- npx @openhoo/hoopilot --auth-mode github-token
82
- npx @openhoo/hoopilot --auth-mode direct-github-token
83
77
  npx @openhoo/hoopilot --auth-mode copilot-token
84
78
  ```
85
79
 
86
- `auto` first tries the GitHub Copilot token exchange endpoint, then falls back to direct GitHub-token mode against the individual Copilot API base URL. Use `github-token` when you want exchange failures to fail fast.
80
+ `auto` uses a direct Copilot token when one is configured, otherwise it uses GitHub's Copilot token exchange endpoint and falls back to the GitHub CLI OAuth token when the exchange endpoint is unavailable.
87
81
 
88
82
  ## CLI
89
83
 
@@ -97,8 +91,8 @@ Options:
97
91
  -p, --port <port> Port to listen on. Default: 4141
98
92
  --host <host> Host to listen on. Default: 127.0.0.1
99
93
  --api-key <key> Require clients to send Authorization: Bearer <key>
100
- --auth-mode <mode> auto, github-token, direct-github-token, copilot-token
101
- --github-token <token> GitHub OAuth token for a Copilot account
94
+ --auth-mode <mode> auto, copilot-token
95
+ --github-token <token> GitHub CLI OAuth token for a Copilot account. PATs are rejected.
102
96
  --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token
103
97
  --copilot-token <token> Short-lived Copilot API bearer token
104
98
  --copilot-api-base-url <url> Copilot API base URL override
package/dist/cli.js CHANGED
@@ -5,17 +5,14 @@ import { execFileSync } from "child_process";
5
5
  var DEFAULT_COPILOT_API_BASE_URL = "https://api.individual.githubcopilot.com";
6
6
  var DEFAULT_TOKEN_EXCHANGE_URL = "https://api.github.com/copilot_internal/v2/token";
7
7
  var REFRESH_SKEW_MS = 6e4;
8
- var defaultLogger = {
9
- info: () => void 0,
10
- warn: () => void 0,
11
- error: () => void 0
12
- };
13
8
  var CopilotAuthError = class extends Error {
14
9
  constructor(message) {
15
10
  super(message);
16
11
  this.name = "CopilotAuthError";
17
12
  }
18
13
  };
14
+ var CopilotTokenExchangeHttpError = class extends CopilotAuthError {
15
+ };
19
16
  var CopilotAuth = class {
20
17
  #authMode;
21
18
  #copilotApiBaseUrl;
@@ -37,7 +34,7 @@ var CopilotAuth = class {
37
34
  this.#fetch = options.fetch ?? fetch;
38
35
  this.#githubToken = options.githubToken;
39
36
  this.#githubTokenCommand = options.githubTokenCommand ?? "gh auth token";
40
- this.#logger = options.logger ?? defaultLogger;
37
+ this.#logger = options.logger;
41
38
  this.#tokenExchangeUrl = options.tokenExchangeUrl ?? options.env?.COPILOT_TOKEN_EXCHANGE_URL ?? DEFAULT_TOKEN_EXCHANGE_URL;
42
39
  }
43
40
  async getAccess() {
@@ -45,17 +42,6 @@ var CopilotAuth = class {
45
42
  return this.#cachedAccess;
46
43
  }
47
44
  const directCopilotToken = this.#resolveDirectCopilotToken();
48
- if (this.#authMode === "copilot-token") {
49
- if (!directCopilotToken) {
50
- throw new CopilotAuthError("COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.");
51
- }
52
- return this.#cacheAccess({
53
- apiBaseUrl: this.#copilotApiBaseUrl,
54
- expiresAtMs: Date.now() + 10 * 6e4,
55
- source: "copilot-token",
56
- token: directCopilotToken
57
- });
58
- }
59
45
  if (directCopilotToken) {
60
46
  return this.#cacheAccess({
61
47
  apiBaseUrl: this.#copilotApiBaseUrl,
@@ -64,29 +50,30 @@ var CopilotAuth = class {
64
50
  token: directCopilotToken
65
51
  });
66
52
  }
53
+ if (this.#authMode === "copilot-token") {
54
+ throw new CopilotAuthError("COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.");
55
+ }
67
56
  const githubToken = this.#resolveGithubToken();
68
57
  if (!githubToken) {
69
58
  throw new CopilotAuthError(
70
- "No Copilot credential found. Set COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, or sign in with gh auth login."
59
+ "No Copilot credential found. Set COPILOT_API_TOKEN, set COPILOT_GITHUB_TOKEN from gh auth token, or sign in with gh auth login."
71
60
  );
72
61
  }
73
- if (this.#authMode === "direct-github-token") {
74
- return this.#cacheAccess({
75
- apiBaseUrl: this.#copilotApiBaseUrl,
76
- expiresAtMs: Date.now() + 10 * 6e4,
77
- source: "direct-github-token",
78
- token: githubToken
79
- });
62
+ if (isPersonalAccessToken(githubToken)) {
63
+ throw new CopilotAuthError(
64
+ "GitHub personal access tokens are not supported for Copilot authentication. Use gh auth login or COPILOT_API_TOKEN."
65
+ );
80
66
  }
81
67
  try {
82
- const exchanged = await this.#exchangeGithubToken(githubToken);
83
- return this.#cacheAccess(exchanged);
68
+ return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));
84
69
  } catch (error) {
85
- if (this.#authMode === "github-token") {
70
+ if (!(error instanceof CopilotTokenExchangeHttpError)) {
86
71
  throw error;
87
72
  }
88
- this.#logger.warn(
89
- `Copilot token exchange failed; falling back to direct GitHub token mode: ${errorMessage(error)}`
73
+ this.#logger?.warn(
74
+ `Copilot token exchange failed; falling back to GitHub CLI token mode: ${errorMessage(
75
+ error
76
+ )}`
90
77
  );
91
78
  return this.#cacheAccess({
92
79
  apiBaseUrl: this.#copilotApiBaseUrl,
@@ -112,7 +99,7 @@ var CopilotAuth = class {
112
99
  method: "GET"
113
100
  });
114
101
  if (!response.ok) {
115
- throw new CopilotAuthError(
102
+ throw new CopilotTokenExchangeHttpError(
116
103
  `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(
117
104
  response
118
105
  )}`
@@ -143,8 +130,6 @@ var CopilotAuth = class {
143
130
  this.#githubToken,
144
131
  this.#env.COPILOT_GITHUB_TOKEN,
145
132
  this.#env.GITHUB_COPILOT_GITHUB_TOKEN,
146
- this.#env.GH_TOKEN,
147
- this.#env.GITHUB_TOKEN,
148
133
  this.#readGithubTokenCommand()
149
134
  );
150
135
  }
@@ -259,6 +244,9 @@ async function safeResponseText(response) {
259
244
  const text = await response.text();
260
245
  return text.slice(0, 500);
261
246
  }
247
+ function isPersonalAccessToken(token) {
248
+ return token.startsWith("github_pat_") || token.startsWith("ghp_");
249
+ }
262
250
  function errorMessage(error) {
263
251
  return error instanceof Error ? error.message : String(error);
264
252
  }
@@ -1106,7 +1094,7 @@ function parseArgs(argv) {
1106
1094
  return args;
1107
1095
  }
1108
1096
  function parseAuthMode(value) {
1109
- if (value === "auto" || value === "copilot-token" || value === "github-token" || value === "direct-github-token") {
1097
+ if (value === "auto" || value === "copilot-token") {
1110
1098
  return value;
1111
1099
  }
1112
1100
  throw new Error(`Invalid auth mode: ${value}.`);
@@ -1132,8 +1120,8 @@ Options:
1132
1120
  -p, --port <port> Port to listen on. Default: 4141
1133
1121
  --host <host> Host to listen on. Default: 127.0.0.1
1134
1122
  --api-key <key> Require clients to send Authorization: Bearer <key>
1135
- --auth-mode <mode> auto, github-token, direct-github-token, copilot-token
1136
- --github-token <token> GitHub OAuth token for a Copilot account
1123
+ --auth-mode <mode> auto, copilot-token
1124
+ --github-token <token> GitHub CLI OAuth token for a Copilot account. PATs are rejected.
1137
1125
  --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token
1138
1126
  --copilot-token <token> Short-lived Copilot API bearer token
1139
1127
  --copilot-api-base-url <url> Copilot API base URL override
@@ -1144,7 +1132,7 @@ Options:
1144
1132
 
1145
1133
  Environment:
1146
1134
  HOOPILOT_API_KEY
1147
- COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN
1135
+ COPILOT_GITHUB_TOKEN
1148
1136
  COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN
1149
1137
  COPILOT_API_BASE_URL
1150
1138
  `;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth.ts","../src/copilot.ts","../src/openai.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport type { CopilotAccess, CopilotAuthOptions, FetchLike, Logger } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.individual.githubcopilot.com\";\nconst DEFAULT_TOKEN_EXCHANGE_URL = \"https://api.github.com/copilot_internal/v2/token\";\nconst REFRESH_SKEW_MS = 60_000;\n\nconst defaultLogger: Logger = {\n info: () => undefined,\n warn: () => undefined,\n error: () => undefined,\n};\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 #authMode: NonNullable<CopilotAuthOptions[\"authMode\"]>;\n readonly #copilotApiBaseUrl: string;\n readonly #copilotToken?: string;\n readonly #env: NodeJS.ProcessEnv;\n readonly #fetch: FetchLike;\n readonly #githubToken?: string;\n readonly #githubTokenCommand: string | false;\n readonly #logger: Logger;\n readonly #tokenExchangeUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authMode = options.authMode ?? \"auto\";\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n this.#copilotToken = options.copilotToken;\n this.#env = options.env ?? process.env;\n this.#fetch = options.fetch ?? fetch;\n this.#githubToken = options.githubToken;\n this.#githubTokenCommand = options.githubTokenCommand ?? \"gh auth token\";\n this.#logger = options.logger ?? defaultLogger;\n this.#tokenExchangeUrl =\n options.tokenExchangeUrl ??\n options.env?.COPILOT_TOKEN_EXCHANGE_URL ??\n DEFAULT_TOKEN_EXCHANGE_URL;\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 directCopilotToken = this.#resolveDirectCopilotToken();\n if (this.#authMode === \"copilot-token\") {\n if (!directCopilotToken) {\n throw new CopilotAuthError(\"COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.\");\n }\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"copilot-token\",\n token: directCopilotToken,\n });\n }\n\n if (directCopilotToken) {\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"copilot-token\",\n token: directCopilotToken,\n });\n }\n\n const githubToken = this.#resolveGithubToken();\n if (!githubToken) {\n throw new CopilotAuthError(\n \"No Copilot credential found. Set COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, or sign in with gh auth login.\",\n );\n }\n\n if (this.#authMode === \"direct-github-token\") {\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"direct-github-token\",\n token: githubToken,\n });\n }\n\n try {\n const exchanged = await this.#exchangeGithubToken(githubToken);\n return this.#cacheAccess(exchanged);\n } catch (error) {\n if (this.#authMode === \"github-token\") {\n throw error;\n }\n this.#logger.warn(\n `Copilot token exchange failed; falling back to direct GitHub token mode: ${errorMessage(error)}`,\n );\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"direct-github-token\",\n token: githubToken,\n });\n }\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n\n async #exchangeGithubToken(githubToken: string): Promise<CopilotAccess> {\n const response = await this.#fetch(this.#tokenExchangeUrl, {\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": \"hoopilot/0.1.0\",\n \"editor-version\": \"Hoopilot/0.1.0\",\n \"user-agent\": \"hoopilot/0.1.0\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new CopilotAuthError(\n `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const body = asRecord(await response.json());\n const token = getString(body, \"token\");\n if (!token) {\n throw new CopilotAuthError(\"GitHub Copilot token exchange response did not include a token.\");\n }\n\n return {\n apiBaseUrl: endpointFromResponse(body) ?? this.#copilotApiBaseUrl,\n expiresAtMs: expiresAtFromResponse(body),\n source: \"github-token\",\n token,\n };\n }\n\n #resolveDirectCopilotToken(): string | undefined {\n return firstNonEmpty(\n this.#copilotToken,\n this.#env.COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_TOKEN,\n );\n }\n\n #resolveGithubToken(): string | undefined {\n return firstNonEmpty(\n this.#githubToken,\n this.#env.COPILOT_GITHUB_TOKEN,\n this.#env.GITHUB_COPILOT_GITHUB_TOKEN,\n this.#env.GH_TOKEN,\n this.#env.GITHUB_TOKEN,\n this.#readGithubTokenCommand(),\n );\n }\n\n #readGithubTokenCommand(): string | undefined {\n if (this.#githubTokenCommand === false) {\n return undefined;\n }\n const parts = splitCommand(this.#githubTokenCommand);\n const [command, ...args] = parts;\n if (!command) {\n return undefined;\n }\n try {\n const output = execFileSync(command, args, {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5_000,\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n }\n}\n\nexport function splitCommand(command: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | undefined;\n let escaping = false;\n\n for (const character of command.trim()) {\n if (escaping) {\n current += character;\n escaping = false;\n continue;\n }\n if (character === \"\\\\\") {\n escaping = true;\n continue;\n }\n if (quote) {\n if (character === quote) {\n quote = undefined;\n } else {\n current += character;\n }\n continue;\n }\n if (character === \"'\" || character === '\"') {\n quote = character;\n continue;\n }\n if (/\\s/.test(character)) {\n if (current) {\n parts.push(current);\n current = \"\";\n }\n continue;\n }\n current += character;\n }\n\n if (current) {\n parts.push(current);\n }\n\n return parts;\n}\n\nfunction endpointFromResponse(body: Record<string, unknown>): string | undefined {\n const endpoints = asRecord(body.endpoints);\n const apiUrl = getString(endpoints, \"api\") ?? getString(endpoints, \"proxy\");\n return apiUrl ? trimTrailingSlash(apiUrl) : undefined;\n}\n\nfunction expiresAtFromResponse(body: Record<string, unknown>): number {\n const expiresAt = body.expires_at;\n if (typeof expiresAt === \"number\") {\n return expiresAt < 10_000_000_000 ? expiresAt * 1000 : expiresAt;\n }\n if (typeof expiresAt === \"string\") {\n const asNumber = Number(expiresAt);\n if (Number.isFinite(asNumber)) {\n return asNumber < 10_000_000_000 ? asNumber * 1000 : asNumber;\n }\n const parsed = Date.parse(expiresAt);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n const refreshIn = body.refresh_in;\n if (typeof refreshIn === \"number\" && Number.isFinite(refreshIn)) {\n return Date.now() + refreshIn * 1000;\n }\n return Date.now() + 10 * 60_000;\n}\n\nfunction firstNonEmpty(...values: Array<string | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = value?.trim();\n if (trimmed) {\n return trimmed;\n }\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction getString(record: Record<string, unknown>, key: string): string | undefined {\n const value = record[key];\n return typeof value === \"string\" && value ? value : undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\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\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\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 {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type { HoopilotServerOptions, JsonObject, StartedHoopilotServer } from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders() });\n }\n\n if (!isAuthorized(request, apiKey)) {\n return jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\");\n }\n\n try {\n if (request.method === \"GET\" && (url.pathname === \"/\" || url.pathname === \"/healthz\")) {\n return jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n });\n }\n if (request.method === \"GET\" && url.pathname === \"/v1/models\") {\n return await handleModels(client, request.signal);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n return await handleChatCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/completions\") {\n return await handleCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/responses\") {\n return await handleResponses(client, request);\n }\n return jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`);\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n return jsonError(401, \"copilot_auth_error\", error.message);\n }\n return jsonError(500, \"internal_error\", errorMessage(error));\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(client: CopilotClient, signal: AbortSignal): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(client: CopilotClient, request: Request): 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);\n }\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(client: CopilotClient, request: Request): 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);\n }\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): Promise<Response> {\n const text = await upstream.text();\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(\"Request body must be valid JSON.\");\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 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","#!/usr/bin/env bun\n\nimport { startHoopilotServer } from \"./server\";\nimport type { AuthMode, HoopilotServerOptions } from \"./types\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n version?: boolean;\n}\n\nexport async function main(argv = Bun.argv.slice(2)): Promise<void> {\n const args = parseArgs(argv);\n if (args.help) {\n console.log(helpText(await packageVersion()));\n return;\n }\n if (args.version) {\n console.log(await packageVersion());\n return;\n }\n\n const started = startHoopilotServer(args);\n console.log(`hoopilot listening on ${started.url}`);\n console.log(`OpenAI base URL: ${started.url}/v1`);\n console.log(\"Use Ctrl+C to stop.\");\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args: ParsedArgs = {};\n const rest = [...argv];\n if (rest[0] === \"serve\") {\n rest.shift();\n }\n\n while (rest.length > 0) {\n const arg = rest.shift();\n if (!arg) {\n continue;\n }\n if (arg === \"--help\" || arg === \"-h\") {\n args.help = true;\n continue;\n }\n if (arg === \"--version\" || arg === \"-v\") {\n args.version = true;\n continue;\n }\n if (arg === \"--allow-unauthenticated\") {\n args.allowUnauthenticated = true;\n continue;\n }\n if (arg === \"--no-gh\") {\n args.githubTokenCommand = false;\n continue;\n }\n\n const [name, inlineValue] = arg.split(\"=\", 2);\n const value = inlineValue ?? rest.shift();\n if (!value) {\n throw new Error(`Missing value for ${arg}.`);\n }\n\n switch (name) {\n case \"--api-key\":\n args.apiKey = value;\n break;\n case \"--auth-mode\":\n args.authMode = parseAuthMode(value);\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--copilot-token\":\n args.copilotToken = value;\n break;\n case \"--github-token\":\n args.githubToken = value;\n break;\n case \"--github-token-command\":\n args.githubTokenCommand = value;\n break;\n case \"--host\":\n args.host = value;\n break;\n case \"--port\":\n case \"-p\":\n args.port = Number(value);\n if (!Number.isInteger(args.port) || args.port <= 0) {\n throw new Error(`Invalid port: ${value}.`);\n }\n break;\n default:\n throw new Error(`Unknown option: ${name}.`);\n }\n }\n\n return args;\n}\n\nfunction parseAuthMode(value: string): AuthMode {\n if (\n value === \"auto\" ||\n value === \"copilot-token\" ||\n value === \"github-token\" ||\n value === \"direct-github-token\"\n ) {\n return value;\n }\n throw new Error(`Invalid auth mode: ${value}.`);\n}\n\nasync function packageVersion(): Promise<string> {\n try {\n const manifest = await Bun.file(new URL(\"../package.json\", import.meta.url)).json();\n return typeof manifest.version === \"string\" ? manifest.version : \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction helpText(version: string): string {\n return `hoopilot ${version}\n\nOpenAI-compatible proxy for GitHub Copilot.\n\nUsage:\n hoopilot [serve] [options]\n npx @openhoo/hoopilot [options]\n\nOptions:\n -p, --port <port> Port to listen on. Default: 4141\n --host <host> Host to listen on. Default: 127.0.0.1\n --api-key <key> Require clients to send Authorization: Bearer <key>\n --auth-mode <mode> auto, github-token, direct-github-token, copilot-token\n --github-token <token> GitHub OAuth token for a Copilot account\n --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token\n --copilot-token <token> Short-lived Copilot API bearer token\n --copilot-api-base-url <url> Copilot API base URL override\n --no-gh Do not try gh auth token\n --allow-unauthenticated Allow non-loopback bind without --api-key\n -h, --help Show help\n -v, --version Show version\n\nEnvironment:\n HOOPILOT_API_KEY\n COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN\n COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN\n COPILOT_API_BASE_URL\n`;\n}\n\nif (import.meta.main) {\n main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["asRecord","errorMessage"]}
1
+ {"version":3,"sources":["../src/auth.ts","../src/copilot.ts","../src/openai.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport type { CopilotAccess, CopilotAuthOptions, FetchLike, Logger } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.individual.githubcopilot.com\";\nconst DEFAULT_TOKEN_EXCHANGE_URL = \"https://api.github.com/copilot_internal/v2/token\";\nconst REFRESH_SKEW_MS = 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nclass CopilotTokenExchangeHttpError extends CopilotAuthError {}\n\nexport class CopilotAuth {\n readonly #authMode: NonNullable<CopilotAuthOptions[\"authMode\"]>;\n readonly #copilotApiBaseUrl: string;\n readonly #copilotToken?: string;\n readonly #env: NodeJS.ProcessEnv;\n readonly #fetch: FetchLike;\n readonly #githubToken?: string;\n readonly #githubTokenCommand: string | false;\n readonly #logger?: Logger;\n readonly #tokenExchangeUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authMode = options.authMode ?? \"auto\";\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n this.#copilotToken = options.copilotToken;\n this.#env = options.env ?? process.env;\n this.#fetch = options.fetch ?? fetch;\n this.#githubToken = options.githubToken;\n this.#githubTokenCommand = options.githubTokenCommand ?? \"gh auth token\";\n this.#logger = options.logger;\n this.#tokenExchangeUrl =\n options.tokenExchangeUrl ??\n options.env?.COPILOT_TOKEN_EXCHANGE_URL ??\n DEFAULT_TOKEN_EXCHANGE_URL;\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 directCopilotToken = this.#resolveDirectCopilotToken();\n if (directCopilotToken) {\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"copilot-token\",\n token: directCopilotToken,\n });\n }\n\n if (this.#authMode === \"copilot-token\") {\n throw new CopilotAuthError(\"COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.\");\n }\n\n const githubToken = this.#resolveGithubToken();\n if (!githubToken) {\n throw new CopilotAuthError(\n \"No Copilot credential found. Set COPILOT_API_TOKEN, set COPILOT_GITHUB_TOKEN from gh auth token, or sign in with gh auth login.\",\n );\n }\n\n if (isPersonalAccessToken(githubToken)) {\n throw new CopilotAuthError(\n \"GitHub personal access tokens are not supported for Copilot authentication. Use gh auth login or COPILOT_API_TOKEN.\",\n );\n }\n\n try {\n return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));\n } catch (error) {\n if (!(error instanceof CopilotTokenExchangeHttpError)) {\n throw error;\n }\n this.#logger?.warn(\n `Copilot token exchange failed; falling back to GitHub CLI token mode: ${errorMessage(\n error,\n )}`,\n );\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"direct-github-token\",\n token: githubToken,\n });\n }\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n\n async #exchangeGithubToken(githubToken: string): Promise<CopilotAccess> {\n const response = await this.#fetch(this.#tokenExchangeUrl, {\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": \"hoopilot/0.1.0\",\n \"editor-version\": \"Hoopilot/0.1.0\",\n \"user-agent\": \"hoopilot/0.1.0\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new CopilotTokenExchangeHttpError(\n `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const body = asRecord(await response.json());\n const token = getString(body, \"token\");\n if (!token) {\n throw new CopilotAuthError(\"GitHub Copilot token exchange response did not include a token.\");\n }\n\n return {\n apiBaseUrl: endpointFromResponse(body) ?? this.#copilotApiBaseUrl,\n expiresAtMs: expiresAtFromResponse(body),\n source: \"github-token\",\n token,\n };\n }\n\n #resolveDirectCopilotToken(): string | undefined {\n return firstNonEmpty(\n this.#copilotToken,\n this.#env.COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_TOKEN,\n );\n }\n\n #resolveGithubToken(): string | undefined {\n return firstNonEmpty(\n this.#githubToken,\n this.#env.COPILOT_GITHUB_TOKEN,\n this.#env.GITHUB_COPILOT_GITHUB_TOKEN,\n this.#readGithubTokenCommand(),\n );\n }\n\n #readGithubTokenCommand(): string | undefined {\n if (this.#githubTokenCommand === false) {\n return undefined;\n }\n const parts = splitCommand(this.#githubTokenCommand);\n const [command, ...args] = parts;\n if (!command) {\n return undefined;\n }\n try {\n const output = execFileSync(command, args, {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5_000,\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n }\n}\n\nexport function splitCommand(command: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | undefined;\n let escaping = false;\n\n for (const character of command.trim()) {\n if (escaping) {\n current += character;\n escaping = false;\n continue;\n }\n if (character === \"\\\\\") {\n escaping = true;\n continue;\n }\n if (quote) {\n if (character === quote) {\n quote = undefined;\n } else {\n current += character;\n }\n continue;\n }\n if (character === \"'\" || character === '\"') {\n quote = character;\n continue;\n }\n if (/\\s/.test(character)) {\n if (current) {\n parts.push(current);\n current = \"\";\n }\n continue;\n }\n current += character;\n }\n\n if (current) {\n parts.push(current);\n }\n\n return parts;\n}\n\nfunction endpointFromResponse(body: Record<string, unknown>): string | undefined {\n const endpoints = asRecord(body.endpoints);\n const apiUrl = getString(endpoints, \"api\") ?? getString(endpoints, \"proxy\");\n return apiUrl ? trimTrailingSlash(apiUrl) : undefined;\n}\n\nfunction expiresAtFromResponse(body: Record<string, unknown>): number {\n const expiresAt = body.expires_at;\n if (typeof expiresAt === \"number\") {\n return expiresAt < 10_000_000_000 ? expiresAt * 1000 : expiresAt;\n }\n if (typeof expiresAt === \"string\") {\n const asNumber = Number(expiresAt);\n if (Number.isFinite(asNumber)) {\n return asNumber < 10_000_000_000 ? asNumber * 1000 : asNumber;\n }\n const parsed = Date.parse(expiresAt);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n const refreshIn = body.refresh_in;\n if (typeof refreshIn === \"number\" && Number.isFinite(refreshIn)) {\n return Date.now() + refreshIn * 1000;\n }\n return Date.now() + 10 * 60_000;\n}\n\nfunction firstNonEmpty(...values: Array<string | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = value?.trim();\n if (trimmed) {\n return trimmed;\n }\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction getString(record: Record<string, unknown>, key: string): string | undefined {\n const value = record[key];\n return typeof value === \"string\" && value ? value : undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction isPersonalAccessToken(token: string): boolean {\n return token.startsWith(\"github_pat_\") || token.startsWith(\"ghp_\");\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\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\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\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 {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type { HoopilotServerOptions, JsonObject, StartedHoopilotServer } from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders() });\n }\n\n if (!isAuthorized(request, apiKey)) {\n return jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\");\n }\n\n try {\n if (request.method === \"GET\" && (url.pathname === \"/\" || url.pathname === \"/healthz\")) {\n return jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n });\n }\n if (request.method === \"GET\" && url.pathname === \"/v1/models\") {\n return await handleModels(client, request.signal);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n return await handleChatCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/completions\") {\n return await handleCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/responses\") {\n return await handleResponses(client, request);\n }\n return jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`);\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n return jsonError(401, \"copilot_auth_error\", error.message);\n }\n return jsonError(500, \"internal_error\", errorMessage(error));\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(client: CopilotClient, signal: AbortSignal): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(client: CopilotClient, request: Request): 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);\n }\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(client: CopilotClient, request: Request): 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);\n }\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): Promise<Response> {\n const text = await upstream.text();\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(\"Request body must be valid JSON.\");\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 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","#!/usr/bin/env bun\n\nimport { startHoopilotServer } from \"./server\";\nimport type { AuthMode, HoopilotServerOptions } from \"./types\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n version?: boolean;\n}\n\nexport async function main(argv = Bun.argv.slice(2)): Promise<void> {\n const args = parseArgs(argv);\n if (args.help) {\n console.log(helpText(await packageVersion()));\n return;\n }\n if (args.version) {\n console.log(await packageVersion());\n return;\n }\n\n const started = startHoopilotServer(args);\n console.log(`hoopilot listening on ${started.url}`);\n console.log(`OpenAI base URL: ${started.url}/v1`);\n console.log(\"Use Ctrl+C to stop.\");\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args: ParsedArgs = {};\n const rest = [...argv];\n if (rest[0] === \"serve\") {\n rest.shift();\n }\n\n while (rest.length > 0) {\n const arg = rest.shift();\n if (!arg) {\n continue;\n }\n if (arg === \"--help\" || arg === \"-h\") {\n args.help = true;\n continue;\n }\n if (arg === \"--version\" || arg === \"-v\") {\n args.version = true;\n continue;\n }\n if (arg === \"--allow-unauthenticated\") {\n args.allowUnauthenticated = true;\n continue;\n }\n if (arg === \"--no-gh\") {\n args.githubTokenCommand = false;\n continue;\n }\n\n const [name, inlineValue] = arg.split(\"=\", 2);\n const value = inlineValue ?? rest.shift();\n if (!value) {\n throw new Error(`Missing value for ${arg}.`);\n }\n\n switch (name) {\n case \"--api-key\":\n args.apiKey = value;\n break;\n case \"--auth-mode\":\n args.authMode = parseAuthMode(value);\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--copilot-token\":\n args.copilotToken = value;\n break;\n case \"--github-token\":\n args.githubToken = value;\n break;\n case \"--github-token-command\":\n args.githubTokenCommand = value;\n break;\n case \"--host\":\n args.host = value;\n break;\n case \"--port\":\n case \"-p\":\n args.port = Number(value);\n if (!Number.isInteger(args.port) || args.port <= 0) {\n throw new Error(`Invalid port: ${value}.`);\n }\n break;\n default:\n throw new Error(`Unknown option: ${name}.`);\n }\n }\n\n return args;\n}\n\nfunction parseAuthMode(value: string): AuthMode {\n if (value === \"auto\" || value === \"copilot-token\") {\n return value;\n }\n throw new Error(`Invalid auth mode: ${value}.`);\n}\n\nasync function packageVersion(): Promise<string> {\n try {\n const manifest = await Bun.file(new URL(\"../package.json\", import.meta.url)).json();\n return typeof manifest.version === \"string\" ? manifest.version : \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction helpText(version: string): string {\n return `hoopilot ${version}\n\nOpenAI-compatible proxy for GitHub Copilot.\n\nUsage:\n hoopilot [serve] [options]\n npx @openhoo/hoopilot [options]\n\nOptions:\n -p, --port <port> Port to listen on. Default: 4141\n --host <host> Host to listen on. Default: 127.0.0.1\n --api-key <key> Require clients to send Authorization: Bearer <key>\n --auth-mode <mode> auto, copilot-token\n --github-token <token> GitHub CLI OAuth token for a Copilot account. PATs are rejected.\n --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token\n --copilot-token <token> Short-lived Copilot API bearer token\n --copilot-api-base-url <url> Copilot API base URL override\n --no-gh Do not try gh auth token\n --allow-unauthenticated Allow non-loopback bind without --api-key\n -h, --help Show help\n -v, --version Show version\n\nEnvironment:\n HOOPILOT_API_KEY\n COPILOT_GITHUB_TOKEN\n COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN\n COPILOT_API_BASE_URL\n`;\n}\n\nif (import.meta.main) {\n main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["asRecord","errorMessage"]}
package/dist/index.cjs CHANGED
@@ -42,17 +42,14 @@ var import_node_child_process = require("child_process");
42
42
  var DEFAULT_COPILOT_API_BASE_URL = "https://api.individual.githubcopilot.com";
43
43
  var DEFAULT_TOKEN_EXCHANGE_URL = "https://api.github.com/copilot_internal/v2/token";
44
44
  var REFRESH_SKEW_MS = 6e4;
45
- var defaultLogger = {
46
- info: () => void 0,
47
- warn: () => void 0,
48
- error: () => void 0
49
- };
50
45
  var CopilotAuthError = class extends Error {
51
46
  constructor(message) {
52
47
  super(message);
53
48
  this.name = "CopilotAuthError";
54
49
  }
55
50
  };
51
+ var CopilotTokenExchangeHttpError = class extends CopilotAuthError {
52
+ };
56
53
  var CopilotAuth = class {
57
54
  #authMode;
58
55
  #copilotApiBaseUrl;
@@ -74,7 +71,7 @@ var CopilotAuth = class {
74
71
  this.#fetch = options.fetch ?? fetch;
75
72
  this.#githubToken = options.githubToken;
76
73
  this.#githubTokenCommand = options.githubTokenCommand ?? "gh auth token";
77
- this.#logger = options.logger ?? defaultLogger;
74
+ this.#logger = options.logger;
78
75
  this.#tokenExchangeUrl = options.tokenExchangeUrl ?? options.env?.COPILOT_TOKEN_EXCHANGE_URL ?? DEFAULT_TOKEN_EXCHANGE_URL;
79
76
  }
80
77
  async getAccess() {
@@ -82,17 +79,6 @@ var CopilotAuth = class {
82
79
  return this.#cachedAccess;
83
80
  }
84
81
  const directCopilotToken = this.#resolveDirectCopilotToken();
85
- if (this.#authMode === "copilot-token") {
86
- if (!directCopilotToken) {
87
- throw new CopilotAuthError("COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.");
88
- }
89
- return this.#cacheAccess({
90
- apiBaseUrl: this.#copilotApiBaseUrl,
91
- expiresAtMs: Date.now() + 10 * 6e4,
92
- source: "copilot-token",
93
- token: directCopilotToken
94
- });
95
- }
96
82
  if (directCopilotToken) {
97
83
  return this.#cacheAccess({
98
84
  apiBaseUrl: this.#copilotApiBaseUrl,
@@ -101,29 +87,30 @@ var CopilotAuth = class {
101
87
  token: directCopilotToken
102
88
  });
103
89
  }
90
+ if (this.#authMode === "copilot-token") {
91
+ throw new CopilotAuthError("COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.");
92
+ }
104
93
  const githubToken = this.#resolveGithubToken();
105
94
  if (!githubToken) {
106
95
  throw new CopilotAuthError(
107
- "No Copilot credential found. Set COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, or sign in with gh auth login."
96
+ "No Copilot credential found. Set COPILOT_API_TOKEN, set COPILOT_GITHUB_TOKEN from gh auth token, or sign in with gh auth login."
108
97
  );
109
98
  }
110
- if (this.#authMode === "direct-github-token") {
111
- return this.#cacheAccess({
112
- apiBaseUrl: this.#copilotApiBaseUrl,
113
- expiresAtMs: Date.now() + 10 * 6e4,
114
- source: "direct-github-token",
115
- token: githubToken
116
- });
99
+ if (isPersonalAccessToken(githubToken)) {
100
+ throw new CopilotAuthError(
101
+ "GitHub personal access tokens are not supported for Copilot authentication. Use gh auth login or COPILOT_API_TOKEN."
102
+ );
117
103
  }
118
104
  try {
119
- const exchanged = await this.#exchangeGithubToken(githubToken);
120
- return this.#cacheAccess(exchanged);
105
+ return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));
121
106
  } catch (error) {
122
- if (this.#authMode === "github-token") {
107
+ if (!(error instanceof CopilotTokenExchangeHttpError)) {
123
108
  throw error;
124
109
  }
125
- this.#logger.warn(
126
- `Copilot token exchange failed; falling back to direct GitHub token mode: ${errorMessage(error)}`
110
+ this.#logger?.warn(
111
+ `Copilot token exchange failed; falling back to GitHub CLI token mode: ${errorMessage(
112
+ error
113
+ )}`
127
114
  );
128
115
  return this.#cacheAccess({
129
116
  apiBaseUrl: this.#copilotApiBaseUrl,
@@ -149,7 +136,7 @@ var CopilotAuth = class {
149
136
  method: "GET"
150
137
  });
151
138
  if (!response.ok) {
152
- throw new CopilotAuthError(
139
+ throw new CopilotTokenExchangeHttpError(
153
140
  `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(
154
141
  response
155
142
  )}`
@@ -180,8 +167,6 @@ var CopilotAuth = class {
180
167
  this.#githubToken,
181
168
  this.#env.COPILOT_GITHUB_TOKEN,
182
169
  this.#env.GITHUB_COPILOT_GITHUB_TOKEN,
183
- this.#env.GH_TOKEN,
184
- this.#env.GITHUB_TOKEN,
185
170
  this.#readGithubTokenCommand()
186
171
  );
187
172
  }
@@ -296,6 +281,9 @@ async function safeResponseText(response) {
296
281
  const text = await response.text();
297
282
  return text.slice(0, 500);
298
283
  }
284
+ function isPersonalAccessToken(token) {
285
+ return token.startsWith("github_pat_") || token.startsWith("ghp_");
286
+ }
299
287
  function errorMessage(error) {
300
288
  return error instanceof Error ? error.message : String(error);
301
289
  }