@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 +6 -12
- package/dist/cli.js +25 -37
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +21 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -33
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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
|
|
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`
|
|
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,
|
|
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
|
|
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
|
|
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 (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
83
|
-
return this.#cacheAccess(exchanged);
|
|
68
|
+
return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));
|
|
84
69
|
} catch (error) {
|
|
85
|
-
if (
|
|
70
|
+
if (!(error instanceof CopilotTokenExchangeHttpError)) {
|
|
86
71
|
throw error;
|
|
87
72
|
}
|
|
88
|
-
this.#logger
|
|
89
|
-
`Copilot token exchange failed; falling back to
|
|
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
|
|
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"
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
120
|
-
return this.#cacheAccess(exchanged);
|
|
105
|
+
return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));
|
|
121
106
|
} catch (error) {
|
|
122
|
-
if (
|
|
107
|
+
if (!(error instanceof CopilotTokenExchangeHttpError)) {
|
|
123
108
|
throw error;
|
|
124
109
|
}
|
|
125
|
-
this.#logger
|
|
126
|
-
`Copilot token exchange failed; falling back to
|
|
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
|
|
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
|
}
|