@openhoo/hoopilot 0.5.8 → 0.6.0
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 +2 -0
- package/dist/cli.js +114 -55
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -213,6 +213,7 @@ If that returns `401 copilot_auth_error`, rerun `npx @openhoo/hoopilot login` an
|
|
|
213
213
|
```powershell
|
|
214
214
|
hoopilot [serve] [options]
|
|
215
215
|
hoopilot login [options]
|
|
216
|
+
hoopilot models [options]
|
|
216
217
|
```
|
|
217
218
|
|
|
218
219
|
Commands:
|
|
@@ -220,6 +221,7 @@ Commands:
|
|
|
220
221
|
```txt
|
|
221
222
|
serve Start the proxy server (default)
|
|
222
223
|
login Sign in through GitHub OAuth in a browser and verify Copilot access
|
|
224
|
+
models List available GitHub Copilot model IDs
|
|
223
225
|
update, upgrade Update hoopilot to the latest release
|
|
224
226
|
```
|
|
225
227
|
|
package/dist/cli.js
CHANGED
|
@@ -101,6 +101,61 @@ function trimTrailingSlash(value) {
|
|
|
101
101
|
return value.replace(/\/+$/, "");
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// src/copilot.ts
|
|
105
|
+
var CopilotClient = class {
|
|
106
|
+
#auth;
|
|
107
|
+
#fetch;
|
|
108
|
+
constructor(options = {}) {
|
|
109
|
+
this.#auth = new CopilotAuth(options);
|
|
110
|
+
this.#fetch = options.fetch ?? fetch;
|
|
111
|
+
}
|
|
112
|
+
async chatCompletions(body, signal) {
|
|
113
|
+
return this.fetchCopilot("/chat/completions", {
|
|
114
|
+
body: JSON.stringify(body),
|
|
115
|
+
headers: {
|
|
116
|
+
"content-type": "application/json"
|
|
117
|
+
},
|
|
118
|
+
method: "POST",
|
|
119
|
+
signal
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async responses(body, signal) {
|
|
123
|
+
return this.fetchCopilot("/responses", {
|
|
124
|
+
body,
|
|
125
|
+
headers: {
|
|
126
|
+
"content-type": "application/json"
|
|
127
|
+
},
|
|
128
|
+
method: "POST",
|
|
129
|
+
signal
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async models(signal) {
|
|
133
|
+
return this.fetchCopilot("/models", {
|
|
134
|
+
headers: {
|
|
135
|
+
accept: "application/json"
|
|
136
|
+
},
|
|
137
|
+
method: "GET",
|
|
138
|
+
signal
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async fetchCopilot(path, init) {
|
|
142
|
+
const access = await this.#auth.getAccess();
|
|
143
|
+
const headers = new Headers(init.headers);
|
|
144
|
+
headers.set("accept", headers.get("accept") ?? "application/json");
|
|
145
|
+
headers.set("authorization", `Bearer ${access.token}`);
|
|
146
|
+
headers.set("copilot-integration-id", "vscode-chat");
|
|
147
|
+
headers.set("editor-plugin-version", "hoopilot/0.1.0");
|
|
148
|
+
headers.set("editor-version", "Hoopilot/0.1.0");
|
|
149
|
+
headers.set("openai-intent", "conversation-panel");
|
|
150
|
+
headers.set("user-agent", "hoopilot/0.1.0");
|
|
151
|
+
headers.set("x-github-api-version", "2026-06-01");
|
|
152
|
+
return this.#fetch(`${access.apiBaseUrl}${path}`, {
|
|
153
|
+
...init,
|
|
154
|
+
headers
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
104
159
|
// src/github-device.ts
|
|
105
160
|
import { setTimeout as sleep } from "timers/promises";
|
|
106
161
|
var DEFAULT_GITHUB_COPILOT_CLIENT_ID = "Ov23li8tweQw6odWQebz";
|
|
@@ -321,61 +376,6 @@ function isLogLevel(value) {
|
|
|
321
376
|
return LOG_LEVELS.includes(value);
|
|
322
377
|
}
|
|
323
378
|
|
|
324
|
-
// src/copilot.ts
|
|
325
|
-
var CopilotClient = class {
|
|
326
|
-
#auth;
|
|
327
|
-
#fetch;
|
|
328
|
-
constructor(options = {}) {
|
|
329
|
-
this.#auth = new CopilotAuth(options);
|
|
330
|
-
this.#fetch = options.fetch ?? fetch;
|
|
331
|
-
}
|
|
332
|
-
async chatCompletions(body, signal) {
|
|
333
|
-
return this.fetchCopilot("/chat/completions", {
|
|
334
|
-
body: JSON.stringify(body),
|
|
335
|
-
headers: {
|
|
336
|
-
"content-type": "application/json"
|
|
337
|
-
},
|
|
338
|
-
method: "POST",
|
|
339
|
-
signal
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
async responses(body, signal) {
|
|
343
|
-
return this.fetchCopilot("/responses", {
|
|
344
|
-
body,
|
|
345
|
-
headers: {
|
|
346
|
-
"content-type": "application/json"
|
|
347
|
-
},
|
|
348
|
-
method: "POST",
|
|
349
|
-
signal
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
async models(signal) {
|
|
353
|
-
return this.fetchCopilot("/models", {
|
|
354
|
-
headers: {
|
|
355
|
-
accept: "application/json"
|
|
356
|
-
},
|
|
357
|
-
method: "GET",
|
|
358
|
-
signal
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
async fetchCopilot(path, init) {
|
|
362
|
-
const access = await this.#auth.getAccess();
|
|
363
|
-
const headers = new Headers(init.headers);
|
|
364
|
-
headers.set("accept", headers.get("accept") ?? "application/json");
|
|
365
|
-
headers.set("authorization", `Bearer ${access.token}`);
|
|
366
|
-
headers.set("copilot-integration-id", "vscode-chat");
|
|
367
|
-
headers.set("editor-plugin-version", "hoopilot/0.1.0");
|
|
368
|
-
headers.set("editor-version", "Hoopilot/0.1.0");
|
|
369
|
-
headers.set("openai-intent", "conversation-panel");
|
|
370
|
-
headers.set("user-agent", "hoopilot/0.1.0");
|
|
371
|
-
headers.set("x-github-api-version", "2026-06-01");
|
|
372
|
-
return this.#fetch(`${access.apiBaseUrl}${path}`, {
|
|
373
|
-
...init,
|
|
374
|
-
headers
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
|
|
379
379
|
// src/openai.ts
|
|
380
380
|
var DEFAULT_MODEL = "gpt-4.1";
|
|
381
381
|
function normalizeChatCompletionRequest(request) {
|
|
@@ -1460,6 +1460,20 @@ async function main(argv = Bun.argv.slice(2)) {
|
|
|
1460
1460
|
await runLogin(args2);
|
|
1461
1461
|
return;
|
|
1462
1462
|
}
|
|
1463
|
+
if (command === "models") {
|
|
1464
|
+
const args2 = withRuntimeEnv(parseArgs(argv.slice(1)));
|
|
1465
|
+
if (args2.help) {
|
|
1466
|
+
console.log(helpText(await getVersion()));
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
args2.logger = createHoopilotLogger({
|
|
1470
|
+
env: args2.env,
|
|
1471
|
+
format: args2.logFormat,
|
|
1472
|
+
level: args2.logLevel
|
|
1473
|
+
}).child({ component: "cli", command: "models" });
|
|
1474
|
+
await runModels(args2);
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1463
1477
|
const args = withRuntimeEnv(parseArgs(argv));
|
|
1464
1478
|
if (args.help) {
|
|
1465
1479
|
console.log(helpText(await getVersion()));
|
|
@@ -1585,6 +1599,30 @@ async function runLogin(options = {}) {
|
|
|
1585
1599
|
console.log(`Copilot OAuth credential stored at ${path}`);
|
|
1586
1600
|
console.log("Copilot authentication ready.");
|
|
1587
1601
|
}
|
|
1602
|
+
async function runModels(options = {}) {
|
|
1603
|
+
const logger = options.logger?.child({ component: "models" }) ?? noopLogger;
|
|
1604
|
+
logger.debug({ event: "models.list.started" }, "fetching github copilot models");
|
|
1605
|
+
const response = await new CopilotClient(options).models();
|
|
1606
|
+
if (!response.ok) {
|
|
1607
|
+
const message = `GitHub Copilot API model list failed with ${response.status}: ${await safeResponseText2(response)}`;
|
|
1608
|
+
if (response.status === 401 || response.status === 403) {
|
|
1609
|
+
throw new CopilotAuthError(message);
|
|
1610
|
+
}
|
|
1611
|
+
throw new Error(message);
|
|
1612
|
+
}
|
|
1613
|
+
const ids = modelIdsFromResponse(await response.json().catch(() => void 0));
|
|
1614
|
+
if (ids.length === 0) {
|
|
1615
|
+
throw new Error("GitHub Copilot API returned no model IDs.");
|
|
1616
|
+
}
|
|
1617
|
+
logger.debug(
|
|
1618
|
+
{ count: ids.length, event: "models.list.succeeded" },
|
|
1619
|
+
"github copilot models fetched"
|
|
1620
|
+
);
|
|
1621
|
+
for (const id of ids) {
|
|
1622
|
+
console.log(id);
|
|
1623
|
+
}
|
|
1624
|
+
return ids;
|
|
1625
|
+
}
|
|
1588
1626
|
async function verifyCopilotOAuthToken(token, options = {}) {
|
|
1589
1627
|
const apiBaseUrl = trimTrailingSlash2(
|
|
1590
1628
|
options.copilotApiBaseUrl ?? options.env?.COPILOT_API_BASE_URL ?? DEFAULT_COPILOT_API_BASE_URL2
|
|
@@ -1640,6 +1678,24 @@ async function safeResponseText2(response) {
|
|
|
1640
1678
|
function trimTrailingSlash2(value) {
|
|
1641
1679
|
return value.replace(/\/+$/, "");
|
|
1642
1680
|
}
|
|
1681
|
+
function modelIdsFromResponse(body) {
|
|
1682
|
+
const record = asRecord2(body);
|
|
1683
|
+
const data = Array.isArray(record.data) ? record.data : Array.isArray(body) ? body : [];
|
|
1684
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1685
|
+
const ids = [];
|
|
1686
|
+
for (const model of data) {
|
|
1687
|
+
const id = asRecord2(model).id;
|
|
1688
|
+
if (typeof id !== "string" || id.length === 0 || seen.has(id)) {
|
|
1689
|
+
continue;
|
|
1690
|
+
}
|
|
1691
|
+
seen.add(id);
|
|
1692
|
+
ids.push(id);
|
|
1693
|
+
}
|
|
1694
|
+
return ids;
|
|
1695
|
+
}
|
|
1696
|
+
function asRecord2(value) {
|
|
1697
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1698
|
+
}
|
|
1643
1699
|
function withRuntimeEnv(args) {
|
|
1644
1700
|
return { ...args, env: process.env };
|
|
1645
1701
|
}
|
|
@@ -1651,12 +1707,14 @@ OpenAI-compatible proxy for GitHub Copilot.
|
|
|
1651
1707
|
Usage:
|
|
1652
1708
|
hoopilot [serve] [options]
|
|
1653
1709
|
hoopilot login [options]
|
|
1710
|
+
hoopilot models [options]
|
|
1654
1711
|
hoopilot update
|
|
1655
1712
|
npx @openhoo/hoopilot [options]
|
|
1656
1713
|
|
|
1657
1714
|
Commands:
|
|
1658
1715
|
serve Start the proxy server (default)
|
|
1659
1716
|
login Sign in through GitHub OAuth in a browser and verify Copilot access
|
|
1717
|
+
models List available GitHub Copilot model IDs
|
|
1660
1718
|
update, upgrade Update hoopilot to the latest release
|
|
1661
1719
|
|
|
1662
1720
|
Options:
|
|
@@ -1692,6 +1750,7 @@ if (import.meta.main) {
|
|
|
1692
1750
|
export {
|
|
1693
1751
|
main,
|
|
1694
1752
|
parseArgs,
|
|
1753
|
+
runModels,
|
|
1695
1754
|
verifyCopilotOAuthToken
|
|
1696
1755
|
};
|
|
1697
1756
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/auth-store.ts","../src/auth.ts","../src/github-device.ts","../src/logger.ts","../src/copilot.ts","../src/openai.ts","../src/server.ts","../src/update.ts","../src/update-core.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { spawn } from \"node:child_process\";\nimport { CopilotAuthError } from \"./auth\";\nimport { authStorePath, writeStoredCopilotAuth } from \"./auth-store\";\nimport { githubCopilotDeviceLogin } from \"./github-device\";\nimport { createHoopilotLogger, noopLogger, parseLogFormat, parseLogLevel } from \"./logger\";\nimport { startHoopilotServer } from \"./server\";\nimport type { CopilotAccess, FetchLike, HoopilotServerOptions } from \"./types\";\nimport { cleanupOldBinary, maybeNotifyUpdate, runUpdate } from \"./update\";\nimport { getVersion, IS_STANDALONE_BINARY } from \"./version\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n noUpdateCheck?: boolean;\n version?: boolean;\n}\n\ninterface VerifyCopilotOAuthTokenOptions {\n copilotApiBaseUrl?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n}\n\nexport async function main(argv = Bun.argv.slice(2)): Promise<void> {\n // Clear any leftover \".old\" binary from a prior Windows self-update.\n cleanupOldBinary();\n\n const command = argv[0];\n if (command === \"update\" || command === \"upgrade\") {\n const args = withRuntimeEnv(parseArgs(argv.slice(1)));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n const logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command });\n await runUpdate(await getVersion(), logger);\n return;\n }\n if (command === \"login\") {\n const args = withRuntimeEnv(parseArgs(argv.slice(1)));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n args.logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command: \"login\" });\n await runLogin(args);\n return;\n }\n\n const args = withRuntimeEnv(parseArgs(argv));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n if (args.version) {\n console.log(await getVersion());\n return;\n }\n\n const logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command: \"serve\" });\n args.logger = logger;\n const started = startHoopilotServer(args);\n logger.info(\n {\n baseUrl: `${started.url}/v1`,\n event: \"server.started\",\n url: started.url,\n },\n \"hoopilot server started\",\n );\n\n if (!args.noUpdateCheck && process.env.HOOPILOT_NO_UPDATE_CHECK !== \"1\") {\n // Non-blocking: prints a notice from the previous check and refreshes the\n // cache in the background. The running server keeps the refresh alive.\n void maybeNotifyUpdate(\n await getVersion(),\n IS_STANDALONE_BINARY ? \"binary\" : \"npm\",\n logger.child({ component: \"update\" }),\n );\n }\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-update-check\") {\n args.noUpdateCheck = true;\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-file\":\n args.authStorePath = value;\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--log-format\":\n args.logFormat = parseLogFormat(value);\n break;\n case \"--log-level\":\n args.logLevel = parseLogLevel(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\nasync function runLogin(options: HoopilotServerOptions = {}): Promise<void> {\n const logger = options.logger?.child({ component: \"auth\" }) ?? noopLogger;\n logger.debug({ event: \"auth.login.started\" }, \"starting github copilot browser login\");\n console.log(\"Starting GitHub Copilot browser login...\");\n const login = await githubCopilotDeviceLogin({\n env: options.env,\n logger: console,\n openBrowser: openBrowserBestEffort,\n });\n\n console.log(\"Checking GitHub Copilot access...\");\n const access = await verifyCopilotOAuthToken(login.token, options);\n logger.debug(\n { apiBaseUrl: access.apiBaseUrl, event: \"auth.login.verified\" },\n \"github copilot oauth token verified\",\n );\n const path = options.authStorePath ?? authStorePath(options.env);\n writeStoredCopilotAuth(\n {\n apiBaseUrl: access.apiBaseUrl,\n githubDomain: login.domain,\n source: \"github-device-oauth\",\n token: login.token,\n },\n path,\n );\n logger.debug({ authStorePath: path, event: \"auth.login.stored\" }, \"copilot credential stored\");\n console.log(`Copilot OAuth credential stored at ${path}`);\n console.log(\"Copilot authentication ready.\");\n}\n\nexport async function verifyCopilotOAuthToken(\n token: string,\n options: VerifyCopilotOAuthTokenOptions = {},\n): Promise<CopilotAccess> {\n const apiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ?? options.env?.COPILOT_API_BASE_URL ?? DEFAULT_COPILOT_API_BASE_URL,\n );\n const fetcher = options.fetch ?? fetch;\n const response = await fetcher(`${apiBaseUrl}/models`, {\n headers: copilotHeaders(token),\n method: \"GET\",\n });\n\n if (!response.ok) {\n const message = `GitHub Copilot API verification failed with ${\n response.status\n }: ${await safeResponseText(response)}`;\n if (response.status === 401 || response.status === 403) {\n throw new CopilotAuthError(message);\n }\n throw new Error(message);\n }\n\n return {\n apiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"github-copilot-oauth\",\n token,\n };\n}\n\nfunction openBrowserBestEffort(url: string): void {\n const platform = process.platform;\n const command = platform === \"win32\" ? \"cmd\" : platform === \"darwin\" ? \"open\" : \"xdg-open\";\n const args = platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n } catch {\n // The device login code and URL were already printed.\n }\n}\n\nfunction copilotHeaders(token: string): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"authorization\", `Bearer ${token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n return headers;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction withRuntimeEnv(args: ParsedArgs): ParsedArgs {\n return { ...args, env: process.env };\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 hoopilot login [options]\n hoopilot update\n npx @openhoo/hoopilot [options]\n\nCommands:\n serve Start the proxy server (default)\n login Sign in through GitHub OAuth in a browser and verify Copilot access\n update, upgrade Update hoopilot to the latest release\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-file <path> OAuth credential store path\n --copilot-api-base-url <url> Copilot API base URL override\n --log-level <level> trace, debug, info, warn, error, fatal, or silent\n --log-format <format> json or pretty. Default: pretty\n --no-update-check Do not check GitHub for a newer release\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 HOOPILOT_AUTH_FILE\n HOOPILOT_GITHUB_CLIENT_ID\n HOOPILOT_GITHUB_DOMAIN\n HOOPILOT_LOG_FORMAT json or pretty. Default: pretty\n HOOPILOT_LOG_LEVEL trace, debug, info, warn, error, fatal, or silent\n COPILOT_API_BASE_URL\n HOOPILOT_NO_UPDATE_CHECK Set to disable update checks (also NO_UPDATE_NOTIFIER)\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","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredCopilotAuth {\n apiBaseUrl?: string;\n createdAt?: string;\n githubDomain?: string;\n source?: string;\n token: string;\n}\n\nexport function authStorePath(env: NodeJS.ProcessEnv = process.env): string {\n if (env.HOOPILOT_AUTH_FILE) {\n return env.HOOPILOT_AUTH_FILE;\n }\n\n const base =\n env.XDG_CONFIG_HOME ??\n env.APPDATA ??\n (env.HOME ? join(env.HOME, \".config\") : join(process.cwd(), \".config\"));\n return join(base, \"hoopilot\", \"auth.json\");\n}\n\nexport function readStoredCopilotAuth(path = authStorePath()): StoredCopilotAuth | undefined {\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\"));\n if (!parsed || typeof parsed !== \"object\") {\n return undefined;\n }\n const token = typeof parsed.token === \"string\" ? parsed.token.trim() : \"\";\n if (!token) {\n return undefined;\n }\n return {\n apiBaseUrl: typeof parsed.apiBaseUrl === \"string\" ? parsed.apiBaseUrl : undefined,\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : undefined,\n githubDomain: typeof parsed.githubDomain === \"string\" ? parsed.githubDomain : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n token,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function writeStoredCopilotAuth(auth: StoredCopilotAuth, path = authStorePath()): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n `${JSON.stringify(\n {\n ...auth,\n createdAt: auth.createdAt ?? new Date().toISOString(),\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n try {\n chmodSync(path, 0o600);\n } catch {\n // chmod is best-effort on Windows.\n }\n}\n","import { readStoredCopilotAuth } from \"./auth-store\";\nimport type { CopilotAccess, CopilotAuthOptions } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\nconst REFRESH_SKEW_MS = 60_000;\nconst STORED_TOKEN_TTL_MS = 10 * 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nexport class CopilotAuth {\n readonly #authStorePath?: string;\n readonly #copilotApiBaseUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authStorePath = options.authStorePath ?? options.env?.HOOPILOT_AUTH_FILE;\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const stored = readStoredCopilotAuth(this.#authStorePath);\n if (stored) {\n return this.#cacheAccess({\n apiBaseUrl: trimTrailingSlash(stored.apiBaseUrl ?? this.#copilotApiBaseUrl),\n expiresAtMs: Date.now() + STORED_TOKEN_TTL_MS,\n source: \"github-copilot-oauth\",\n token: stored.token,\n });\n }\n\n throw new CopilotAuthError(\n \"No GitHub Copilot OAuth credential found. Run `hoopilot login` to sign in through your browser.\",\n );\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n","import { setTimeout as sleep } from \"node:timers/promises\";\nimport type { FetchLike, Logger } from \"./types\";\n\nexport const DEFAULT_GITHUB_COPILOT_CLIENT_ID = \"Ov23li8tweQw6odWQebz\";\nconst DEFAULT_GITHUB_DOMAIN = \"github.com\";\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst POLLING_SAFETY_MARGIN_MS = 3_000;\n\nexport interface GithubCopilotDeviceLoginOptions {\n clientId?: string;\n domain?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n logger?: Logger;\n openBrowser?: (url: string) => void | Promise<void>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface GithubCopilotDeviceLoginResult {\n domain: string;\n token: string;\n}\n\ninterface DeviceCodeResponse {\n device_code?: string;\n expires_in?: number;\n interval?: number;\n user_code?: string;\n verification_uri?: string;\n}\n\ninterface DeviceTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n interval?: number;\n}\n\nexport async function githubCopilotDeviceLogin(\n options: GithubCopilotDeviceLoginOptions = {},\n): Promise<GithubCopilotDeviceLoginResult> {\n const env = options.env ?? process.env;\n const fetcher = options.fetch ?? fetch;\n const sleeper = options.sleep ?? sleep;\n const domain = normalizeDomain(\n options.domain ?? env.HOOPILOT_GITHUB_DOMAIN ?? DEFAULT_GITHUB_DOMAIN,\n );\n const clientId =\n options.clientId ??\n env.HOOPILOT_GITHUB_CLIENT_ID ??\n env.COPILOT_GITHUB_CLIENT_ID ??\n DEFAULT_GITHUB_COPILOT_CLIENT_ID;\n\n const device = await requestDeviceCode(fetcher, domain, clientId);\n const verificationUrl = device.verification_uri;\n const userCode = device.user_code;\n const deviceCode = device.device_code;\n if (!verificationUrl || !userCode || !deviceCode) {\n throw new Error(\"GitHub device authorization response is missing required fields.\");\n }\n\n options.logger?.info(`First copy your one-time code: ${userCode}`);\n options.logger?.info(`Open ${verificationUrl} in your browser to authorize Hoopilot.`);\n await options.openBrowser?.(verificationUrl);\n\n return {\n domain,\n token: await pollForAccessToken(fetcher, sleeper, domain, clientId, {\n deviceCode,\n expiresIn: positiveSeconds(device.expires_in, 900),\n interval: positiveSeconds(device.interval, 5),\n }),\n };\n}\n\nasync function requestDeviceCode(\n fetcher: FetchLike,\n domain: string,\n clientId: string,\n): Promise<DeviceCodeResponse> {\n const response = await fetcher(`https://${domain}/login/device/code`, {\n body: JSON.stringify({\n client_id: clientId,\n scope: \"read:user\",\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n if (!response.ok) {\n throw new Error(\n `GitHub device authorization failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n return (await response.json()) as DeviceCodeResponse;\n}\n\nasync function pollForAccessToken(\n fetcher: FetchLike,\n sleeper: (ms: number) => Promise<void>,\n domain: string,\n clientId: string,\n device: { deviceCode: string; expiresIn: number; interval: number },\n): Promise<string> {\n let intervalMs = device.interval * 1000 + POLLING_SAFETY_MARGIN_MS;\n const deadline = Date.now() + device.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await sleeper(intervalMs);\n const response = await fetcher(`https://${domain}/login/oauth/access_token`, {\n body: JSON.stringify({\n client_id: clientId,\n device_code: device.deviceCode,\n grant_type: DEVICE_GRANT_TYPE,\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub device token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const data = (await response.json()) as DeviceTokenResponse;\n if (data.access_token) {\n return data.access_token;\n }\n\n if (data.error === \"authorization_pending\") {\n continue;\n }\n if (data.error === \"slow_down\") {\n intervalMs =\n positiveSeconds(data.interval, device.interval + 5) * 1000 + POLLING_SAFETY_MARGIN_MS;\n continue;\n }\n if (data.error === \"expired_token\") {\n throw new Error(\"GitHub device login expired. Run `hoopilot login` again.\");\n }\n if (data.error === \"access_denied\") {\n throw new Error(\"GitHub device login was cancelled.\");\n }\n if (data.error) {\n throw new Error(data.error_description || `GitHub device login failed: ${data.error}`);\n }\n }\n\n throw new Error(\"GitHub device login timed out. Run `hoopilot login` again.\");\n}\n\nfunction oauthHeaders(): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"content-type\", \"application/json\");\n headers.set(\"user-agent\", \"hoopilot\");\n return headers;\n}\n\nfunction normalizeDomain(value: string): string {\n return value.replace(/^https?:\\/\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction positiveSeconds(value: unknown, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n","import pino from \"pino\";\nimport pretty from \"pino-pretty\";\nimport type { HoopilotLogger, HoopilotLoggerOptions, LogFormat, LogLevel } from \"./types\";\n\nexport const DEFAULT_LOG_FORMAT: LogFormat = \"pretty\";\nexport const DEFAULT_LOG_LEVEL: LogLevel = \"info\";\n\nconst LOG_FORMATS = [\"json\", \"pretty\"] as const;\nconst LOG_LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\", \"silent\"] as const;\nconst REDACT_PATHS = [\n \"apiKey\",\n \"authorization\",\n \"cookie\",\n \"headers.authorization\",\n \"headers.Authorization\",\n \"headers.cookie\",\n \"headers.Cookie\",\n \"headers.x-api-key\",\n \"headers.X-Api-Key\",\n \"token\",\n \"*.apiKey\",\n \"*.authorization\",\n \"*.cookie\",\n \"*.token\",\n \"*.headers.authorization\",\n \"*.headers.Authorization\",\n \"*.headers.cookie\",\n \"*.headers.Cookie\",\n \"*.headers.x-api-key\",\n \"*.headers.X-Api-Key\",\n];\n\nexport const noopLogger: HoopilotLogger = {\n child: () => noopLogger,\n debug: () => {},\n error: () => {},\n fatal: () => {},\n info: () => {},\n trace: () => {},\n warn: () => {},\n};\n\nexport function createHoopilotLogger(options: HoopilotLoggerOptions = {}): HoopilotLogger {\n const env = options.env ?? process.env;\n const level = parseLogLevel(options.level ?? env.HOOPILOT_LOG_LEVEL);\n const format = parseLogFormat(options.format ?? env.HOOPILOT_LOG_FORMAT);\n const pinoOptions: pino.LoggerOptions = {\n base: {\n service: \"hoopilot\",\n ...options.base,\n },\n level,\n redact: {\n censor: \"[Redacted]\",\n paths: REDACT_PATHS,\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n };\n\n if (format === \"pretty\") {\n return pino(\n pinoOptions,\n pretty({\n colorize: options.colorize ?? process.stderr.isTTY,\n destination: options.stream ?? 1,\n ignore: \"pid,hostname\",\n singleLine: true,\n translateTime: \"SYS:standard\",\n }),\n ) as HoopilotLogger;\n }\n\n if (options.stream) {\n return pino(pinoOptions, options.stream as pino.DestinationStream) as HoopilotLogger;\n }\n return pino(pinoOptions) as HoopilotLogger;\n}\n\nexport function parseLogFormat(value: string | undefined): LogFormat {\n if (!value) {\n return DEFAULT_LOG_FORMAT;\n }\n if (isLogFormat(value)) {\n return value;\n }\n throw new Error(`Invalid log format: ${value}. Expected one of: ${LOG_FORMATS.join(\", \")}.`);\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n if (!value) {\n return DEFAULT_LOG_LEVEL;\n }\n if (isLogLevel(value)) {\n return value;\n }\n throw new Error(`Invalid log level: ${value}. Expected one of: ${LOG_LEVELS.join(\", \")}.`);\n}\n\nexport function shouldCreateLogger(options: {\n env?: NodeJS.ProcessEnv;\n logFormat?: string;\n logger?: HoopilotLogger;\n logLevel?: string;\n}): boolean {\n return Boolean(\n options.logger ||\n options.logFormat ||\n options.logLevel ||\n options.env?.HOOPILOT_LOG_FORMAT ||\n options.env?.HOOPILOT_LOG_LEVEL,\n );\n}\n\nfunction isLogFormat(value: string): value is LogFormat {\n return (LOG_FORMATS as readonly string[]).includes(value);\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return (LOG_LEVELS as readonly string[]).includes(value);\n}\n","import { 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 responses(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/responses\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import 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: normalizeRequestedModel(request.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 normalizeChatCompletionRequest(request: JsonObject): JsonObject {\n return removeUndefined({\n ...request,\n model: normalizeRequestedModel(request.model),\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: normalizeRequestedModel(request.model),\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function normalizeRequestedModel(model: unknown): string {\n const requested = contentToText(model).trim();\n return requested || DEFAULT_MODEL;\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport { createHoopilotLogger, noopLogger, shouldCreateLogger } from \"./logger\";\nimport {\n chatCompletionToCompletion,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeChatCompletionRequest,\n normalizeModelsResponse,\n} from \"./openai\";\nimport type {\n HoopilotLogger,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n StartedHoopilotServer,\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\nconst INVALID_JSON_MESSAGE = \"Request body must be valid JSON.\";\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const logger = serverLogger(options);\n\n return async (request: Request): Promise<Response> => {\n const startedAt = performance.now();\n const url = new URL(request.url);\n const apiPath = canonicalApiPath(url.pathname);\n const requestId = requestIdFor(request);\n const requestLogger = logger.child({\n method: request.method,\n path: url.pathname,\n requestId,\n route: routeFor(request.method, apiPath),\n });\n\n if (request.method === \"OPTIONS\") {\n return finishResponse(new Response(null, { headers: corsHeaders() }), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n\n if (!isAuthorized(request, apiKey)) {\n requestLogger.warn({ event: \"http.request.unauthorized\" }, \"invalid hoopilot api key\");\n return finishResponse(\n jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\"),\n {\n logger: requestLogger,\n requestId,\n startedAt,\n },\n );\n }\n\n try {\n if (request.method === \"GET\" && (apiPath === \"/\" || apiPath === \"/healthz\")) {\n return finishResponse(\n jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n }),\n { logger: requestLogger, requestId, startedAt },\n );\n }\n if (request.method === \"GET\" && apiPath === \"/v1/responses\") {\n return finishResponse(websocketUnsupportedResponse(), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"GET\" && apiPath === \"/v1/models\") {\n return finishResponse(await handleModels(client, request.signal, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/chat/completions\") {\n return finishResponse(await handleChatCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/completions\") {\n return finishResponse(await handleCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/responses\") {\n return finishResponse(await handleResponses(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n return finishResponse(\n jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`),\n { logger: requestLogger, requestId, startedAt },\n );\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"copilot.auth.missing\" },\n \"copilot auth failed\",\n );\n return finishResponse(jsonError(401, \"copilot_auth_error\", error.message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n const message = errorMessage(error);\n if (message === INVALID_JSON_MESSAGE) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request body was invalid json\",\n );\n } else {\n requestLogger.error(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request failed\",\n );\n }\n return finishResponse(jsonError(500, \"internal_error\", message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(\n client: CopilotClient,\n signal: AbortSignal,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n if (isUpstreamAuthStatus(upstream.status)) {\n return proxyError(upstream, logger);\n }\n logger.warn(\n {\n event: \"copilot.models.fallback\",\n upstreamPath: \"/models\",\n upstreamStatus: upstream.status,\n },\n \"falling back to built-in model list\",\n );\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n logUpstreamSuccess(logger, \"/models\", upstream.status);\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const chatRequest = normalizeChatCompletionRequest(await readJson(request));\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJsonText(request);\n const upstream = await client.responses(body, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/responses\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function proxyError(upstream: Response, logger: HoopilotLogger): Promise<Response> {\n const text = await upstream.text();\n if (isUpstreamAuthStatus(upstream.status)) {\n logger.warn(\n { event: \"copilot.auth.rejected\", upstreamStatus: upstream.status },\n \"copilot rejected credential or account access\",\n );\n return jsonError(401, \"copilot_auth_error\", upstreamAuthMessage(text || upstream.statusText));\n }\n logger.warn(\n { event: \"copilot.request.failed\", upstreamStatus: upstream.status },\n \"copilot upstream request failed\",\n );\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nasync function readJsonText(request: Request): Promise<string> {\n const text = await request.text();\n try {\n JSON.parse(text);\n return text;\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction websocketUnsupportedResponse(): Response {\n const response = jsonError(\n 426,\n \"websocket_not_supported\",\n \"Hoopilot does not support Responses WebSocket transport; retry with HTTP Responses API.\",\n );\n response.headers.set(\"upgrade\", \"websocket\");\n return response;\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isUpstreamAuthStatus(status: number): boolean {\n return status === 401 || status === 403;\n}\n\nfunction upstreamAuthMessage(message: string): string {\n return `GitHub Copilot rejected the credential or account access: ${message}`;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction serverLogger(options: HoopilotServerOptions): HoopilotLogger {\n if (options.logger) {\n return options.logger.child({ component: \"server\" });\n }\n if (shouldCreateLogger(options)) {\n return createHoopilotLogger({\n env: options.env,\n format: options.logFormat,\n level: options.logLevel,\n }).child({ component: \"server\" });\n }\n return noopLogger;\n}\n\nfunction finishResponse(\n response: Response,\n options: { logger: HoopilotLogger; requestId: string; startedAt: number },\n): Response {\n const withRequestId = responseWithRequestId(response, options.requestId);\n logRequestCompleted(options.logger, withRequestId, options.startedAt);\n return withRequestId;\n}\n\nfunction responseWithRequestId(response: Response, requestId: string): Response {\n const headers = new Headers(response.headers);\n headers.set(\"x-request-id\", requestId);\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nfunction logRequestCompleted(logger: HoopilotLogger, response: Response, startedAt: number): void {\n const fields: LogFields = {\n durationMs: Math.round((performance.now() - startedAt) * 100) / 100,\n event: \"http.request.completed\",\n status: response.status,\n stream: isStreamingResponse(response),\n };\n if (response.status >= 500) {\n logger.error(fields, \"request completed with server error\");\n return;\n }\n if (response.status >= 400) {\n logger.warn(fields, \"request completed with client error\");\n return;\n }\n logger.info(fields, \"request completed\");\n}\n\nfunction requestIdFor(request: Request): string {\n const existing = request.headers.get(\"x-request-id\")?.trim();\n return existing || crypto.randomUUID();\n}\n\nfunction canonicalApiPath(path: string): string {\n const withoutTrailingSlash = path.length > 1 ? path.replace(/\\/+$/, \"\") : path;\n switch (withoutTrailingSlash) {\n case \"/models\":\n return \"/v1/models\";\n case \"/chat/completions\":\n return \"/v1/chat/completions\";\n case \"/completions\":\n return \"/v1/completions\";\n case \"/responses\":\n return \"/v1/responses\";\n default:\n return withoutTrailingSlash;\n }\n}\n\nfunction routeFor(method: string, path: string): string {\n if (method === \"OPTIONS\") {\n return \"cors.preflight\";\n }\n if (method === \"GET\" && (path === \"/\" || path === \"/healthz\")) {\n return \"health\";\n }\n if (method === \"GET\" && path === \"/v1/models\") {\n return \"models\";\n }\n if (method === \"POST\" && path === \"/v1/chat/completions\") {\n return \"chat_completions\";\n }\n if (method === \"POST\" && path === \"/v1/completions\") {\n return \"completions\";\n }\n if (method === \"POST\" && path === \"/v1/responses\") {\n return \"responses\";\n }\n if (method === \"GET\" && path === \"/v1/responses\") {\n return \"responses_websocket\";\n }\n return \"not_found\";\n}\n\nfunction isStreamingResponse(response: Response): boolean {\n return response.headers.get(\"content-type\")?.includes(\"text/event-stream\") ?? false;\n}\n\nfunction logUpstreamSuccess(logger: HoopilotLogger, upstreamPath: string, status: number): void {\n logger.debug(\n {\n event: \"copilot.request.completed\",\n upstreamPath,\n upstreamStatus: status,\n },\n \"copilot upstream request completed\",\n );\n}\n\nfunction errorDetails(error: unknown): LogFields {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n","// Self-update and update-notification orchestration. The pure decision logic\n// lives in update-core.ts; this module performs the network and filesystem I/O.\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n mkdirSync,\n realpathSync,\n renameSync,\n rmSync,\n} from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { HoopilotLogger } from \"./types\";\nimport {\n assetNameFor,\n assetSuffixFor,\n checksumFor,\n formatUpdateNotice,\n type InstallKind,\n isOutdated,\n isUpdateCheckDisabled,\n type LatestRelease,\n latestReleaseApiUrl,\n parseLatestRelease,\n parseState,\n resolveCacheDir,\n shouldCleanupOldBinary,\n shouldRefresh,\n type UpdateState,\n upgradeCommandFor,\n} from \"./update-core\";\nimport { BAKED_TARGET, IS_STANDALONE_BINARY } from \"./version\";\n\nconst REQUEST_TIMEOUT_MS = 8_000;\nconst SHA256SUMS = \"SHA256SUMS\";\n\nfunction userAgent(version: string): string {\n return `hoopilot/${version}`;\n}\n\nfunction cacheDir(): string {\n return resolveCacheDir(process.env, process.platform, homedir(), join);\n}\n\nfunction stateFilePath(): string {\n return join(cacheDir(), \"update-check.json\");\n}\n\nasync function readStateSafe(): Promise<UpdateState> {\n try {\n return parseState(await readFile(stateFilePath(), \"utf8\"));\n } catch {\n return { lastCheck: 0, latestVersion: null, etag: null };\n }\n}\n\nasync function writeStateSafe(state: UpdateState): Promise<void> {\n try {\n mkdirSync(cacheDir(), { recursive: true });\n await writeFile(stateFilePath(), JSON.stringify(state), \"utf8\");\n } catch {\n // best effort: a read-only cache dir must never break the CLI\n }\n}\n\ninterface FetchResult {\n status: number;\n etag: string | null;\n release: LatestRelease | null;\n}\n\nasync function fetchLatest(version: string, etag?: string | null): Promise<FetchResult | null> {\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": userAgent(version),\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n };\n if (etag) {\n headers[\"If-None-Match\"] = etag;\n }\n const response = await fetch(latestReleaseApiUrl(), {\n headers,\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n if (response.status === 304) {\n return { status: 304, etag: etag ?? null, release: null };\n }\n if (!response.ok) {\n return { status: response.status, etag: null, release: null };\n }\n return {\n status: response.status,\n etag: response.headers.get(\"etag\"),\n release: parseLatestRelease(await response.json()),\n };\n } catch {\n return null; // offline / timeout: caller leaves state untouched\n }\n}\n\n/**\n * Print a notice if a previously-cached check found a newer release, then kick\n * off a throttled background refresh. Never blocks on the network and never\n * throws. Intended to be called (unawaited is fine) from the serve path.\n */\nexport async function maybeNotifyUpdate(\n currentVersion: string,\n kind: InstallKind,\n logger?: HoopilotLogger,\n): Promise<void> {\n if (isUpdateCheckDisabled(process.env, Boolean(process.stderr.isTTY))) {\n logger?.debug({ event: \"update.check.skipped\" }, \"update check skipped\");\n return;\n }\n const state = await readStateSafe();\n if (state.latestVersion && isOutdated(currentVersion, state.latestVersion)) {\n logger?.debug(\n {\n currentVersion,\n event: \"update.notice.cached\",\n installKind: kind,\n latestVersion: state.latestVersion,\n },\n \"showing cached update notice\",\n );\n process.stderr.write(formatUpdateNotice(currentVersion, state.latestVersion, kind));\n }\n if (shouldRefresh(state.lastCheck, Date.now())) {\n logger?.debug({ event: \"update.check.refresh_queued\" }, \"queued update check refresh\");\n void refreshState(currentVersion, state.etag ?? null, logger).catch((error: unknown) => {\n logger?.debug(\n { err: errorDetails(error), event: \"update.check.refresh_failed\" },\n \"update check refresh failed\",\n );\n });\n }\n}\n\nasync function refreshState(\n currentVersion: string,\n etag: string | null,\n logger?: HoopilotLogger,\n): Promise<void> {\n const result = await fetchLatest(currentVersion, etag);\n if (!result) {\n logger?.debug({ event: \"update.check.unavailable\" }, \"update check unavailable\");\n return; // network error: keep prior state\n }\n if (result.status === 304) {\n const prev = await readStateSafe();\n await writeStateSafe({ ...prev, lastCheck: Date.now() });\n logger?.debug({ event: \"update.check.not_modified\" }, \"latest release unchanged\");\n return;\n }\n if (result.release) {\n await writeStateSafe({\n lastCheck: Date.now(),\n latestVersion: result.release.version,\n etag: result.etag,\n });\n logger?.debug(\n { event: \"update.check.updated\", latestVersion: result.release.version },\n \"updated cached latest release state\",\n );\n }\n}\n\nfunction detectInstallKind(): InstallKind {\n return IS_STANDALONE_BINARY ? \"binary\" : \"npm\";\n}\n\nfunction detectMusl(): boolean {\n if (process.platform !== \"linux\") {\n return false;\n }\n try {\n const report = process.report?.getReport?.() as\n | { header?: Record<string, unknown> }\n | undefined;\n if (report?.header && \"glibcVersionRuntime\" in report.header) {\n return !report.header.glibcVersionRuntime;\n }\n } catch {\n // fall through to file-based detection\n }\n try {\n if (existsSync(\"/etc/alpine-release\")) {\n return true;\n }\n const ldd = execFileSync(\"ldd\", [\"--version\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 2_000,\n });\n return /musl/i.test(ldd);\n } catch {\n return false;\n }\n}\n\nasync function downloadToFile(url: string, dest: string, version: string): Promise<void> {\n const response = await fetch(url, {\n headers: { \"User-Agent\": userAgent(version) },\n redirect: \"follow\",\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS * 10),\n });\n if (!response.ok || !response.body) {\n throw new Error(`Download failed (${response.status}) for ${url}`);\n }\n await writeFile(dest, new Uint8Array(await response.arrayBuffer()));\n}\n\nasync function sha256File(path: string): Promise<string> {\n return createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n}\n\nasync function verifyChecksum(\n release: LatestRelease,\n assetName: string,\n file: string,\n version: string,\n): Promise<void> {\n const sums = release.assets.find((asset) => asset.name === SHA256SUMS);\n if (!sums) {\n // Fail closed: never overwrite the running binary with an unverified download.\n throw new Error(\n `Release ${release.tag} has no ${SHA256SUMS}; refusing to install an unverified binary.`,\n );\n }\n const response = await fetch(sums.url, {\n headers: { \"User-Agent\": userAgent(version) },\n redirect: \"follow\",\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n if (!response.ok) {\n throw new Error(`Could not download ${SHA256SUMS} (${response.status}).`);\n }\n const expected = checksumFor(await response.text(), assetName);\n if (!expected) {\n throw new Error(`No checksum for ${assetName} in ${SHA256SUMS}.`);\n }\n const actual = await sha256File(file);\n if (actual.toLowerCase() !== expected) {\n throw new Error(`Checksum mismatch for ${assetName}: expected ${expected}, got ${actual}.`);\n }\n}\n\nfunction swapBinary(tmpFile: string, exePath: string): void {\n if (process.platform === \"win32\") {\n // A running .exe cannot be overwritten, but it can be renamed aside.\n const oldExe = `${exePath}.old`;\n try {\n rmSync(oldExe, { force: true });\n } catch {\n // a previous .old may still be locked; the new name still wins below\n }\n renameSync(exePath, oldExe);\n const restore = () => {\n try {\n renameSync(oldExe, exePath); // put the working binary back\n } catch {\n // nothing more we can do\n }\n };\n try {\n renameSync(tmpFile, exePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EXDEV\") {\n try {\n copyFileSync(tmpFile, exePath);\n } catch (copyError) {\n restore();\n throw copyError;\n }\n } else {\n restore();\n throw error;\n }\n }\n return;\n }\n // Unix: atomic rename over the running file; the old inode stays mapped until exit.\n try {\n renameSync(tmpFile, exePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EXDEV\") {\n copyFileSync(tmpFile, exePath);\n chmodSync(exePath, 0o755);\n } else if (code === \"EACCES\" || code === \"EPERM\") {\n throw new Error(\n `No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory.`,\n );\n } else {\n throw error;\n }\n }\n}\n\n/** Remove the leftover \".old\" binary from a prior Windows self-update. */\nexport function cleanupOldBinary(): void {\n if (!shouldCleanupOldBinary(process.platform, IS_STANDALONE_BINARY)) {\n return;\n }\n try {\n rmSync(`${realpathSync(process.execPath)}.old`, { force: true });\n } catch {\n // still locked or already gone\n }\n}\n\n/** Implements the `hoopilot update` command. */\nexport async function runUpdate(currentVersion: string, logger?: HoopilotLogger): Promise<void> {\n cleanupOldBinary();\n const kind = detectInstallKind();\n logger?.debug({ currentVersion, event: \"update.started\", installKind: kind }, \"update started\");\n\n if (kind !== \"binary\") {\n console.log(`hoopilot ${currentVersion} was installed via npm.`);\n console.log(`Update with: ${upgradeCommandFor(\"npm\")}`);\n return;\n }\n\n console.log(`hoopilot ${currentVersion} — checking for updates...`);\n const result = await fetchLatest(currentVersion);\n const release = result?.release ?? null;\n if (!release) {\n throw new Error(\"Could not reach GitHub to check for the latest release.\");\n }\n if (!isOutdated(currentVersion, release.version)) {\n logger?.debug(\n { currentVersion, event: \"update.already_current\", latestVersion: release.version },\n \"hoopilot is already up to date\",\n );\n console.log(`Already up to date (latest: ${release.version}).`);\n return;\n }\n\n const suffix = BAKED_TARGET ?? assetSuffixFor(process.platform, process.arch, detectMusl());\n const assetName = assetNameFor(suffix);\n const asset = release.assets.find((entry) => entry.name === assetName);\n if (!asset) {\n const available = release.assets.map((entry) => entry.name).join(\", \") || \"none\";\n throw new Error(`Release ${release.tag} has no asset \"${assetName}\". Available: ${available}.`);\n }\n\n console.log(`Updating ${currentVersion} → ${release.version} (${assetName})...`);\n logger?.debug(\n {\n assetName,\n currentVersion,\n event: \"update.installing\",\n latestVersion: release.version,\n },\n \"installing update\",\n );\n const exePath = realpathSync(process.execPath);\n const tmpFile = join(dirname(exePath), `.hoopilot-update-${process.pid}.tmp`);\n try {\n await downloadToFile(asset.url, tmpFile, currentVersion);\n await verifyChecksum(release, assetName, tmpFile, currentVersion);\n if (process.platform !== \"win32\") {\n chmodSync(tmpFile, 0o755);\n }\n swapBinary(tmpFile, exePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EACCES\" || code === \"EPERM\") {\n throw new Error(\n `No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory (e.g. set HOOPILOT_INSTALL_DIR).`,\n );\n }\n throw error;\n } finally {\n try {\n rmSync(tmpFile, { force: true });\n } catch {\n // already moved into place or never created\n }\n }\n\n console.log(`Updated hoopilot to ${release.version}.`);\n logger?.debug(\n { currentVersion, event: \"update.completed\", latestVersion: release.version },\n \"update completed\",\n );\n if (process.platform === \"win32\") {\n console.log(\"Restart hoopilot to run the new version.\");\n }\n}\n\nfunction errorDetails(error: unknown): Record<string, unknown> {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n","// Pure, dependency-free logic for version checks and self-update decisions.\n// Everything here is side-effect free so it can be unit tested without network\n// or filesystem access; the I/O orchestration lives in update.ts.\n\nexport const REPO_OWNER = \"openhoo\";\nexport const REPO_NAME = \"hoopilot\";\nexport const REPO = `${REPO_OWNER}/${REPO_NAME}`;\nexport const NPM_PACKAGE = \"@openhoo/hoopilot\";\n\n/** How a copy of hoopilot was installed. */\nexport type InstallKind = \"binary\" | \"npm\";\n\n/** How often the background update check is allowed to hit GitHub. */\nexport const UPDATE_CHECK_INTERVAL_MS = 1000 * 60 * 60 * 24; // 24h\n\n/** Persisted state for the throttled update check. */\nexport interface UpdateState {\n lastCheck: number;\n latestVersion: string | null;\n etag?: string | null;\n}\n\ninterface SemVer {\n major: number;\n minor: number;\n patch: number;\n prerelease: string[];\n}\n\nfunction parseSemver(input: string): SemVer | null {\n const value = String(input)\n .trim()\n .replace(/^[v=]+/, \"\");\n const match = value.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/);\n if (!match) {\n return null;\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n // Build metadata (everything after \"+\") is intentionally dropped.\n prerelease: match[4] ? match[4].split(\".\") : [],\n };\n}\n\nfunction comparePrerelease(a: string[], b: string[]): -1 | 0 | 1 {\n if (a.length === 0 && b.length === 0) {\n return 0;\n }\n // A release outranks an otherwise-equal prerelease.\n if (a.length === 0) {\n return 1;\n }\n if (b.length === 0) {\n return -1;\n }\n const len = Math.max(a.length, b.length);\n for (let i = 0; i < len; i++) {\n const x = a[i];\n const y = b[i];\n // The version with more prerelease fields has higher precedence.\n if (x === undefined) {\n return -1;\n }\n if (y === undefined) {\n return 1;\n }\n const xNumeric = /^\\d+$/.test(x);\n const yNumeric = /^\\d+$/.test(y);\n if (xNumeric && yNumeric) {\n const diff = Number(x) - Number(y);\n if (diff !== 0) {\n return diff < 0 ? -1 : 1;\n }\n } else if (xNumeric) {\n return -1; // numeric identifiers sort lower than alphanumeric\n } else if (yNumeric) {\n return 1;\n } else if (x !== y) {\n return x < y ? -1 : 1; // ASCII lexical\n }\n }\n return 0;\n}\n\n/**\n * Compare two semantic versions. Returns -1 if a < b, 0 if equal, 1 if a > b.\n * Tolerates a leading \"v\"/\"=\", ignores build metadata, honors prerelease\n * precedence, and sorts unparseable input low so a bad value never throws.\n */\nexport function compareSemver(a: string, b: string): -1 | 0 | 1 {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) {\n if (!pa && !pb) {\n return 0;\n }\n return pa ? 1 : -1;\n }\n if (pa.major !== pb.major) {\n return pa.major < pb.major ? -1 : 1;\n }\n if (pa.minor !== pb.minor) {\n return pa.minor < pb.minor ? -1 : 1;\n }\n if (pa.patch !== pb.patch) {\n return pa.patch < pb.patch ? -1 : 1;\n }\n return comparePrerelease(pa.prerelease, pb.prerelease);\n}\n\n/** True when `latest` is a strictly newer release than `current`. */\nexport function isOutdated(current: string, latest: string): boolean {\n return compareSemver(current, latest) < 0;\n}\n\n/** Strip a leading \"v\" from a git tag to get a bare version string. */\nexport function versionFromTag(tag: string): string {\n return tag.trim().replace(/^v/, \"\");\n}\n\n/**\n * Compute the release asset suffix for a platform/arch, e.g. \"linux-x64-musl\",\n * \"darwin-arm64\", \"windows-x64\". `platform`/`arch` use Node's process values.\n */\nexport function assetSuffixFor(platform: string, arch: string, isMusl: boolean): string {\n const os = platform === \"win32\" ? \"windows\" : platform === \"darwin\" ? \"darwin\" : \"linux\";\n const cpu = arch === \"arm64\" || arch === \"aarch64\" ? \"arm64\" : \"x64\";\n const libc = os === \"linux\" && isMusl ? \"-musl\" : \"\";\n return `${os}-${cpu}${libc}`;\n}\n\n/** Full release asset file name for a suffix (adds .exe for Windows). */\nexport function assetNameFor(suffix: string): string {\n const name = `hoopilot-${suffix}`;\n return suffix.startsWith(\"windows-\") ? `${name}.exe` : name;\n}\n\n/** Whether automatic update checks should be skipped, per env + TTY. */\nexport function isUpdateCheckDisabled(\n env: Record<string, string | undefined>,\n isTty: boolean,\n): boolean {\n if (env.HOOPILOT_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER) {\n return true;\n }\n if (env.NODE_ENV === \"test\") {\n return true;\n }\n if (!isTty) {\n return true; // piped / non-interactive output\n }\n if (\n (env.CI && env.CI !== \"false\") ||\n env.CONTINUOUS_INTEGRATION ||\n env.GITHUB_ACTIONS ||\n env.BUILD_NUMBER ||\n env.RUN_ID\n ) {\n return true;\n }\n return false;\n}\n\n/** Whether the background check is due again given the last check time. */\nexport function shouldRefresh(\n lastCheck: number,\n now: number,\n intervalMs = UPDATE_CHECK_INTERVAL_MS,\n): boolean {\n return now - lastCheck >= intervalMs;\n}\n\n/** The command a user runs to upgrade, depending on how they installed. */\nexport function upgradeCommandFor(kind: InstallKind): string {\n return kind === \"binary\"\n ? \"hoopilot update\"\n : `npm install -g ${NPM_PACKAGE}@latest (or: bun add -g ${NPM_PACKAGE})`;\n}\n\n/** Whether it is safe to remove a leftover Windows self-update backup. */\nexport function shouldCleanupOldBinary(platform: string, isStandaloneBinary: boolean): boolean {\n return platform === \"win32\" && isStandaloneBinary;\n}\n\n/** Render the \"update available\" notice printed to stderr. */\nexport function formatUpdateNotice(current: string, latest: string, kind: InstallKind): string {\n return (\n `\\nUpdate available for hoopilot: ${current} → ${latest}\\n` +\n `Run: ${upgradeCommandFor(kind)}\\n\\n`\n );\n}\n\n/** Parse the persisted update-check state, tolerating any malformed input. */\nexport function parseState(text: string): UpdateState {\n try {\n const data = JSON.parse(text) as Partial<UpdateState>;\n return {\n lastCheck: typeof data.lastCheck === \"number\" ? data.lastCheck : 0,\n latestVersion: typeof data.latestVersion === \"string\" ? data.latestVersion : null,\n etag: typeof data.etag === \"string\" ? data.etag : null,\n };\n } catch {\n return { lastCheck: 0, latestVersion: null, etag: null };\n }\n}\n\nexport interface LatestRelease {\n version: string;\n tag: string;\n assets: Array<{ name: string; url: string }>;\n}\n\n/** Parse the GitHub `releases/latest` response into the fields we need. */\nexport function parseLatestRelease(json: unknown): LatestRelease | null {\n if (!json || typeof json !== \"object\") {\n return null;\n }\n const record = json as Record<string, unknown>;\n const tag = typeof record.tag_name === \"string\" ? record.tag_name : undefined;\n if (!tag) {\n return null;\n }\n const assets: Array<{ name: string; url: string }> = [];\n if (Array.isArray(record.assets)) {\n for (const item of record.assets) {\n if (item && typeof item === \"object\") {\n const asset = item as Record<string, unknown>;\n if (typeof asset.name === \"string\" && typeof asset.browser_download_url === \"string\") {\n assets.push({ name: asset.name, url: asset.browser_download_url });\n }\n }\n }\n }\n return { version: versionFromTag(tag), tag, assets };\n}\n\n/** Find a checksum line for `fileName` in a `sha256sum`-style SHA256SUMS file. */\nexport function checksumFor(sumsText: string, fileName: string): string | undefined {\n for (const line of sumsText.split(/\\r?\\n/)) {\n const match = line.trim().match(/^([0-9a-fA-F]{64})\\s+\\*?(.+)$/);\n if (match?.[1] && match[2]?.trim() === fileName) {\n return match[1].toLowerCase();\n }\n }\n return undefined;\n}\n\n/**\n * Resolve the per-OS cache directory (no deps). Mirrors env-paths conventions:\n * Windows -> %LOCALAPPDATA%, macOS -> ~/Library/Caches, else $XDG_CACHE_HOME||~/.cache.\n */\nexport function resolveCacheDir(\n env: Record<string, string | undefined>,\n platform: string,\n homedir: string,\n join: (...parts: string[]) => string,\n): string {\n if (platform === \"win32\") {\n const base = env.LOCALAPPDATA || join(homedir, \"AppData\", \"Local\");\n return join(base, \"hoopilot\");\n }\n if (platform === \"darwin\") {\n return join(homedir, \"Library\", \"Caches\", \"hoopilot\");\n }\n const base = env.XDG_CACHE_HOME || join(homedir, \".cache\");\n return join(base, \"hoopilot\");\n}\n\n/** Stable redirect URL that downloads an asset from the latest release. */\nexport function latestDownloadUrl(asset: string): string {\n return `https://github.com/${REPO}/releases/latest/download/${asset}`;\n}\n\n/** GitHub REST endpoint for the latest release. */\nexport function latestReleaseApiUrl(): string {\n return `https://api.github.com/repos/${REPO}/releases/latest`;\n}\n","// Build-time constants. For standalone binaries these identifiers are replaced\n// at compile time via `bun build --compile --define 'HOOPILOT_VERSION=\"x.y.z\"'`\n// (see scripts/build-binaries.sh). In dev runs and the npm package they are not\n// defined, so `typeof` is \"undefined\" and we fall back to reading package.json.\ndeclare const HOOPILOT_VERSION: string;\ndeclare const HOOPILOT_TARGET: string;\n\n/** Version baked into a standalone binary, or undefined for npm/dev installs. */\nexport const BAKED_VERSION: string | undefined =\n typeof HOOPILOT_VERSION !== \"undefined\" ? HOOPILOT_VERSION : undefined;\n\n/**\n * Release asset suffix baked into a standalone binary (e.g. \"linux-x64-musl\",\n * \"windows-x64\", \"darwin-arm64\"), or undefined for npm/dev installs. Lets the\n * self-updater fetch the exact asset variant it was built from.\n */\nexport const BAKED_TARGET: string | undefined =\n typeof HOOPILOT_TARGET !== \"undefined\" ? HOOPILOT_TARGET : undefined;\n\n/** True when running as a `bun build --compile` standalone executable. */\nexport const IS_STANDALONE_BINARY: boolean = BAKED_VERSION !== undefined;\n\nlet cachedVersion: string | undefined;\n\n/** Resolve the running version, preferring the baked value for binaries. */\nexport async function getVersion(): Promise<string> {\n if (cachedVersion !== undefined) {\n return cachedVersion;\n }\n let resolved: string;\n if (BAKED_VERSION) {\n resolved = BAKED_VERSION;\n } else {\n try {\n const manifest = await Bun.file(new URL(\"../package.json\", import.meta.url)).json();\n resolved = typeof manifest.version === \"string\" ? manifest.version : \"0.0.0\";\n } catch {\n resolved = \"0.0.0\";\n }\n }\n cachedVersion = resolved;\n return resolved;\n}\n"],"mappings":"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","names":["chmodSync","mkdirSync","dirname","join","homedir","join","base","join","mkdirSync","errorDetails","chmodSync","dirname","DEFAULT_COPILOT_API_BASE_URL","args","logger","trimTrailingSlash","safeResponseText"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/auth-store.ts","../src/auth.ts","../src/copilot.ts","../src/github-device.ts","../src/logger.ts","../src/openai.ts","../src/server.ts","../src/update.ts","../src/update-core.ts","../src/version.ts"],"sourcesContent":["#!/usr/bin/env bun\n\nimport { spawn } from \"node:child_process\";\nimport { CopilotAuthError } from \"./auth\";\nimport { authStorePath, writeStoredCopilotAuth } from \"./auth-store\";\nimport { CopilotClient } from \"./copilot\";\nimport { githubCopilotDeviceLogin } from \"./github-device\";\nimport { createHoopilotLogger, noopLogger, parseLogFormat, parseLogLevel } from \"./logger\";\nimport { startHoopilotServer } from \"./server\";\nimport type { CopilotAccess, FetchLike, HoopilotServerOptions } from \"./types\";\nimport { cleanupOldBinary, maybeNotifyUpdate, runUpdate } from \"./update\";\nimport { getVersion, IS_STANDALONE_BINARY } from \"./version\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n noUpdateCheck?: boolean;\n version?: boolean;\n}\n\ninterface VerifyCopilotOAuthTokenOptions {\n copilotApiBaseUrl?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n}\n\nexport async function main(argv = Bun.argv.slice(2)): Promise<void> {\n // Clear any leftover \".old\" binary from a prior Windows self-update.\n cleanupOldBinary();\n\n const command = argv[0];\n if (command === \"update\" || command === \"upgrade\") {\n const args = withRuntimeEnv(parseArgs(argv.slice(1)));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n const logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command });\n await runUpdate(await getVersion(), logger);\n return;\n }\n if (command === \"login\") {\n const args = withRuntimeEnv(parseArgs(argv.slice(1)));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n args.logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command: \"login\" });\n await runLogin(args);\n return;\n }\n if (command === \"models\") {\n const args = withRuntimeEnv(parseArgs(argv.slice(1)));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n args.logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command: \"models\" });\n await runModels(args);\n return;\n }\n\n const args = withRuntimeEnv(parseArgs(argv));\n if (args.help) {\n console.log(helpText(await getVersion()));\n return;\n }\n if (args.version) {\n console.log(await getVersion());\n return;\n }\n\n const logger = createHoopilotLogger({\n env: args.env,\n format: args.logFormat,\n level: args.logLevel,\n }).child({ component: \"cli\", command: \"serve\" });\n args.logger = logger;\n const started = startHoopilotServer(args);\n logger.info(\n {\n baseUrl: `${started.url}/v1`,\n event: \"server.started\",\n url: started.url,\n },\n \"hoopilot server started\",\n );\n\n if (!args.noUpdateCheck && process.env.HOOPILOT_NO_UPDATE_CHECK !== \"1\") {\n // Non-blocking: prints a notice from the previous check and refreshes the\n // cache in the background. The running server keeps the refresh alive.\n void maybeNotifyUpdate(\n await getVersion(),\n IS_STANDALONE_BINARY ? \"binary\" : \"npm\",\n logger.child({ component: \"update\" }),\n );\n }\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-update-check\") {\n args.noUpdateCheck = true;\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-file\":\n args.authStorePath = value;\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--log-format\":\n args.logFormat = parseLogFormat(value);\n break;\n case \"--log-level\":\n args.logLevel = parseLogLevel(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\nasync function runLogin(options: HoopilotServerOptions = {}): Promise<void> {\n const logger = options.logger?.child({ component: \"auth\" }) ?? noopLogger;\n logger.debug({ event: \"auth.login.started\" }, \"starting github copilot browser login\");\n console.log(\"Starting GitHub Copilot browser login...\");\n const login = await githubCopilotDeviceLogin({\n env: options.env,\n logger: console,\n openBrowser: openBrowserBestEffort,\n });\n\n console.log(\"Checking GitHub Copilot access...\");\n const access = await verifyCopilotOAuthToken(login.token, options);\n logger.debug(\n { apiBaseUrl: access.apiBaseUrl, event: \"auth.login.verified\" },\n \"github copilot oauth token verified\",\n );\n const path = options.authStorePath ?? authStorePath(options.env);\n writeStoredCopilotAuth(\n {\n apiBaseUrl: access.apiBaseUrl,\n githubDomain: login.domain,\n source: \"github-device-oauth\",\n token: login.token,\n },\n path,\n );\n logger.debug({ authStorePath: path, event: \"auth.login.stored\" }, \"copilot credential stored\");\n console.log(`Copilot OAuth credential stored at ${path}`);\n console.log(\"Copilot authentication ready.\");\n}\n\nexport async function runModels(options: HoopilotServerOptions = {}): Promise<string[]> {\n const logger = options.logger?.child({ component: \"models\" }) ?? noopLogger;\n logger.debug({ event: \"models.list.started\" }, \"fetching github copilot models\");\n\n const response = await new CopilotClient(options).models();\n if (!response.ok) {\n const message = `GitHub Copilot API model list failed with ${\n response.status\n }: ${await safeResponseText(response)}`;\n if (response.status === 401 || response.status === 403) {\n throw new CopilotAuthError(message);\n }\n throw new Error(message);\n }\n\n const ids = modelIdsFromResponse(await response.json().catch(() => undefined));\n if (ids.length === 0) {\n throw new Error(\"GitHub Copilot API returned no model IDs.\");\n }\n\n logger.debug(\n { count: ids.length, event: \"models.list.succeeded\" },\n \"github copilot models fetched\",\n );\n for (const id of ids) {\n console.log(id);\n }\n return ids;\n}\n\nexport async function verifyCopilotOAuthToken(\n token: string,\n options: VerifyCopilotOAuthTokenOptions = {},\n): Promise<CopilotAccess> {\n const apiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ?? options.env?.COPILOT_API_BASE_URL ?? DEFAULT_COPILOT_API_BASE_URL,\n );\n const fetcher = options.fetch ?? fetch;\n const response = await fetcher(`${apiBaseUrl}/models`, {\n headers: copilotHeaders(token),\n method: \"GET\",\n });\n\n if (!response.ok) {\n const message = `GitHub Copilot API verification failed with ${\n response.status\n }: ${await safeResponseText(response)}`;\n if (response.status === 401 || response.status === 403) {\n throw new CopilotAuthError(message);\n }\n throw new Error(message);\n }\n\n return {\n apiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"github-copilot-oauth\",\n token,\n };\n}\n\nfunction openBrowserBestEffort(url: string): void {\n const platform = process.platform;\n const command = platform === \"win32\" ? \"cmd\" : platform === \"darwin\" ? \"open\" : \"xdg-open\";\n const args = platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n });\n child.unref();\n } catch {\n // The device login code and URL were already printed.\n }\n}\n\nfunction copilotHeaders(token: string): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"authorization\", `Bearer ${token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n return headers;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction modelIdsFromResponse(body: unknown): string[] {\n const record = asRecord(body);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(body) ? body : [];\n const seen = new Set<string>();\n const ids: string[] = [];\n for (const model of data) {\n const id = asRecord(model).id;\n if (typeof id !== \"string\" || id.length === 0 || seen.has(id)) {\n continue;\n }\n seen.add(id);\n ids.push(id);\n }\n return ids;\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 withRuntimeEnv(args: ParsedArgs): ParsedArgs {\n return { ...args, env: process.env };\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 hoopilot login [options]\n hoopilot models [options]\n hoopilot update\n npx @openhoo/hoopilot [options]\n\nCommands:\n serve Start the proxy server (default)\n login Sign in through GitHub OAuth in a browser and verify Copilot access\n models List available GitHub Copilot model IDs\n update, upgrade Update hoopilot to the latest release\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-file <path> OAuth credential store path\n --copilot-api-base-url <url> Copilot API base URL override\n --log-level <level> trace, debug, info, warn, error, fatal, or silent\n --log-format <format> json or pretty. Default: pretty\n --no-update-check Do not check GitHub for a newer release\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 HOOPILOT_AUTH_FILE\n HOOPILOT_GITHUB_CLIENT_ID\n HOOPILOT_GITHUB_DOMAIN\n HOOPILOT_LOG_FORMAT json or pretty. Default: pretty\n HOOPILOT_LOG_LEVEL trace, debug, info, warn, error, fatal, or silent\n COPILOT_API_BASE_URL\n HOOPILOT_NO_UPDATE_CHECK Set to disable update checks (also NO_UPDATE_NOTIFIER)\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","import { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface StoredCopilotAuth {\n apiBaseUrl?: string;\n createdAt?: string;\n githubDomain?: string;\n source?: string;\n token: string;\n}\n\nexport function authStorePath(env: NodeJS.ProcessEnv = process.env): string {\n if (env.HOOPILOT_AUTH_FILE) {\n return env.HOOPILOT_AUTH_FILE;\n }\n\n const base =\n env.XDG_CONFIG_HOME ??\n env.APPDATA ??\n (env.HOME ? join(env.HOME, \".config\") : join(process.cwd(), \".config\"));\n return join(base, \"hoopilot\", \"auth.json\");\n}\n\nexport function readStoredCopilotAuth(path = authStorePath()): StoredCopilotAuth | undefined {\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\"));\n if (!parsed || typeof parsed !== \"object\") {\n return undefined;\n }\n const token = typeof parsed.token === \"string\" ? parsed.token.trim() : \"\";\n if (!token) {\n return undefined;\n }\n return {\n apiBaseUrl: typeof parsed.apiBaseUrl === \"string\" ? parsed.apiBaseUrl : undefined,\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : undefined,\n githubDomain: typeof parsed.githubDomain === \"string\" ? parsed.githubDomain : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n token,\n };\n } catch {\n return undefined;\n }\n}\n\nexport function writeStoredCopilotAuth(auth: StoredCopilotAuth, path = authStorePath()): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(\n path,\n `${JSON.stringify(\n {\n ...auth,\n createdAt: auth.createdAt ?? new Date().toISOString(),\n },\n null,\n 2,\n )}\\n`,\n { mode: 0o600 },\n );\n try {\n chmodSync(path, 0o600);\n } catch {\n // chmod is best-effort on Windows.\n }\n}\n","import { readStoredCopilotAuth } from \"./auth-store\";\nimport type { CopilotAccess, CopilotAuthOptions } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.githubcopilot.com\";\nconst REFRESH_SKEW_MS = 60_000;\nconst STORED_TOKEN_TTL_MS = 10 * 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nexport class CopilotAuth {\n readonly #authStorePath?: string;\n readonly #copilotApiBaseUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authStorePath = options.authStorePath ?? options.env?.HOOPILOT_AUTH_FILE;\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const stored = readStoredCopilotAuth(this.#authStorePath);\n if (stored) {\n return this.#cacheAccess({\n apiBaseUrl: trimTrailingSlash(stored.apiBaseUrl ?? this.#copilotApiBaseUrl),\n expiresAtMs: Date.now() + STORED_TOKEN_TTL_MS,\n source: \"github-copilot-oauth\",\n token: stored.token,\n });\n }\n\n throw new CopilotAuthError(\n \"No GitHub Copilot OAuth credential found. Run `hoopilot login` to sign in through your browser.\",\n );\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n","import { CopilotAuth } from \"./auth\";\nimport type { CopilotAuthOptions, FetchLike, JsonObject } from \"./types\";\n\nexport class CopilotClient {\n readonly #auth: CopilotAuth;\n readonly #fetch: FetchLike;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#auth = new CopilotAuth(options);\n this.#fetch = options.fetch ?? fetch;\n }\n\n async chatCompletions(body: JsonObject, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body: JSON.stringify(body),\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async responses(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/responses\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n headers.set(\"x-github-api-version\", \"2026-06-01\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import { setTimeout as sleep } from \"node:timers/promises\";\nimport type { FetchLike, Logger } from \"./types\";\n\nexport const DEFAULT_GITHUB_COPILOT_CLIENT_ID = \"Ov23li8tweQw6odWQebz\";\nconst DEFAULT_GITHUB_DOMAIN = \"github.com\";\nconst DEVICE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst POLLING_SAFETY_MARGIN_MS = 3_000;\n\nexport interface GithubCopilotDeviceLoginOptions {\n clientId?: string;\n domain?: string;\n env?: NodeJS.ProcessEnv;\n fetch?: FetchLike;\n logger?: Logger;\n openBrowser?: (url: string) => void | Promise<void>;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface GithubCopilotDeviceLoginResult {\n domain: string;\n token: string;\n}\n\ninterface DeviceCodeResponse {\n device_code?: string;\n expires_in?: number;\n interval?: number;\n user_code?: string;\n verification_uri?: string;\n}\n\ninterface DeviceTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n interval?: number;\n}\n\nexport async function githubCopilotDeviceLogin(\n options: GithubCopilotDeviceLoginOptions = {},\n): Promise<GithubCopilotDeviceLoginResult> {\n const env = options.env ?? process.env;\n const fetcher = options.fetch ?? fetch;\n const sleeper = options.sleep ?? sleep;\n const domain = normalizeDomain(\n options.domain ?? env.HOOPILOT_GITHUB_DOMAIN ?? DEFAULT_GITHUB_DOMAIN,\n );\n const clientId =\n options.clientId ??\n env.HOOPILOT_GITHUB_CLIENT_ID ??\n env.COPILOT_GITHUB_CLIENT_ID ??\n DEFAULT_GITHUB_COPILOT_CLIENT_ID;\n\n const device = await requestDeviceCode(fetcher, domain, clientId);\n const verificationUrl = device.verification_uri;\n const userCode = device.user_code;\n const deviceCode = device.device_code;\n if (!verificationUrl || !userCode || !deviceCode) {\n throw new Error(\"GitHub device authorization response is missing required fields.\");\n }\n\n options.logger?.info(`First copy your one-time code: ${userCode}`);\n options.logger?.info(`Open ${verificationUrl} in your browser to authorize Hoopilot.`);\n await options.openBrowser?.(verificationUrl);\n\n return {\n domain,\n token: await pollForAccessToken(fetcher, sleeper, domain, clientId, {\n deviceCode,\n expiresIn: positiveSeconds(device.expires_in, 900),\n interval: positiveSeconds(device.interval, 5),\n }),\n };\n}\n\nasync function requestDeviceCode(\n fetcher: FetchLike,\n domain: string,\n clientId: string,\n): Promise<DeviceCodeResponse> {\n const response = await fetcher(`https://${domain}/login/device/code`, {\n body: JSON.stringify({\n client_id: clientId,\n scope: \"read:user\",\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n if (!response.ok) {\n throw new Error(\n `GitHub device authorization failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n return (await response.json()) as DeviceCodeResponse;\n}\n\nasync function pollForAccessToken(\n fetcher: FetchLike,\n sleeper: (ms: number) => Promise<void>,\n domain: string,\n clientId: string,\n device: { deviceCode: string; expiresIn: number; interval: number },\n): Promise<string> {\n let intervalMs = device.interval * 1000 + POLLING_SAFETY_MARGIN_MS;\n const deadline = Date.now() + device.expiresIn * 1000;\n\n while (Date.now() < deadline) {\n await sleeper(intervalMs);\n const response = await fetcher(`https://${domain}/login/oauth/access_token`, {\n body: JSON.stringify({\n client_id: clientId,\n device_code: device.deviceCode,\n grant_type: DEVICE_GRANT_TYPE,\n }),\n headers: oauthHeaders(),\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(\n `GitHub device token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const data = (await response.json()) as DeviceTokenResponse;\n if (data.access_token) {\n return data.access_token;\n }\n\n if (data.error === \"authorization_pending\") {\n continue;\n }\n if (data.error === \"slow_down\") {\n intervalMs =\n positiveSeconds(data.interval, device.interval + 5) * 1000 + POLLING_SAFETY_MARGIN_MS;\n continue;\n }\n if (data.error === \"expired_token\") {\n throw new Error(\"GitHub device login expired. Run `hoopilot login` again.\");\n }\n if (data.error === \"access_denied\") {\n throw new Error(\"GitHub device login was cancelled.\");\n }\n if (data.error) {\n throw new Error(data.error_description || `GitHub device login failed: ${data.error}`);\n }\n }\n\n throw new Error(\"GitHub device login timed out. Run `hoopilot login` again.\");\n}\n\nfunction oauthHeaders(): Headers {\n const headers = new Headers();\n headers.set(\"accept\", \"application/json\");\n headers.set(\"content-type\", \"application/json\");\n headers.set(\"user-agent\", \"hoopilot\");\n return headers;\n}\n\nfunction normalizeDomain(value: string): string {\n return value.replace(/^https?:\\/\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction positiveSeconds(value: unknown, fallback: number): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n","import pino from \"pino\";\nimport pretty from \"pino-pretty\";\nimport type { HoopilotLogger, HoopilotLoggerOptions, LogFormat, LogLevel } from \"./types\";\n\nexport const DEFAULT_LOG_FORMAT: LogFormat = \"pretty\";\nexport const DEFAULT_LOG_LEVEL: LogLevel = \"info\";\n\nconst LOG_FORMATS = [\"json\", \"pretty\"] as const;\nconst LOG_LEVELS = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\", \"silent\"] as const;\nconst REDACT_PATHS = [\n \"apiKey\",\n \"authorization\",\n \"cookie\",\n \"headers.authorization\",\n \"headers.Authorization\",\n \"headers.cookie\",\n \"headers.Cookie\",\n \"headers.x-api-key\",\n \"headers.X-Api-Key\",\n \"token\",\n \"*.apiKey\",\n \"*.authorization\",\n \"*.cookie\",\n \"*.token\",\n \"*.headers.authorization\",\n \"*.headers.Authorization\",\n \"*.headers.cookie\",\n \"*.headers.Cookie\",\n \"*.headers.x-api-key\",\n \"*.headers.X-Api-Key\",\n];\n\nexport const noopLogger: HoopilotLogger = {\n child: () => noopLogger,\n debug: () => {},\n error: () => {},\n fatal: () => {},\n info: () => {},\n trace: () => {},\n warn: () => {},\n};\n\nexport function createHoopilotLogger(options: HoopilotLoggerOptions = {}): HoopilotLogger {\n const env = options.env ?? process.env;\n const level = parseLogLevel(options.level ?? env.HOOPILOT_LOG_LEVEL);\n const format = parseLogFormat(options.format ?? env.HOOPILOT_LOG_FORMAT);\n const pinoOptions: pino.LoggerOptions = {\n base: {\n service: \"hoopilot\",\n ...options.base,\n },\n level,\n redact: {\n censor: \"[Redacted]\",\n paths: REDACT_PATHS,\n },\n timestamp: pino.stdTimeFunctions.isoTime,\n };\n\n if (format === \"pretty\") {\n return pino(\n pinoOptions,\n pretty({\n colorize: options.colorize ?? process.stderr.isTTY,\n destination: options.stream ?? 1,\n ignore: \"pid,hostname\",\n singleLine: true,\n translateTime: \"SYS:standard\",\n }),\n ) as HoopilotLogger;\n }\n\n if (options.stream) {\n return pino(pinoOptions, options.stream as pino.DestinationStream) as HoopilotLogger;\n }\n return pino(pinoOptions) as HoopilotLogger;\n}\n\nexport function parseLogFormat(value: string | undefined): LogFormat {\n if (!value) {\n return DEFAULT_LOG_FORMAT;\n }\n if (isLogFormat(value)) {\n return value;\n }\n throw new Error(`Invalid log format: ${value}. Expected one of: ${LOG_FORMATS.join(\", \")}.`);\n}\n\nexport function parseLogLevel(value: string | undefined): LogLevel {\n if (!value) {\n return DEFAULT_LOG_LEVEL;\n }\n if (isLogLevel(value)) {\n return value;\n }\n throw new Error(`Invalid log level: ${value}. Expected one of: ${LOG_LEVELS.join(\", \")}.`);\n}\n\nexport function shouldCreateLogger(options: {\n env?: NodeJS.ProcessEnv;\n logFormat?: string;\n logger?: HoopilotLogger;\n logLevel?: string;\n}): boolean {\n return Boolean(\n options.logger ||\n options.logFormat ||\n options.logLevel ||\n options.env?.HOOPILOT_LOG_FORMAT ||\n options.env?.HOOPILOT_LOG_LEVEL,\n );\n}\n\nfunction isLogFormat(value: string): value is LogFormat {\n return (LOG_FORMATS as readonly string[]).includes(value);\n}\n\nfunction isLogLevel(value: string): value is LogLevel {\n return (LOG_LEVELS as readonly string[]).includes(value);\n}\n","import type { JsonObject } from \"./types\";\n\nexport const DEFAULT_MODEL = \"gpt-4.1\";\n\ninterface ResponseStreamOptions {\n model: string;\n responseId?: string;\n}\n\ninterface AccumulatedToolCall {\n arguments: string;\n id: string;\n index: number;\n name: string;\n}\n\nexport function responsesRequestToChatCompletion(request: JsonObject): JsonObject {\n const messages: unknown[] = [];\n const instructions = contentToText(request.instructions);\n if (instructions) {\n messages.push({ content: instructions, role: \"system\" });\n }\n\n for (const message of inputToMessages(request.input)) {\n messages.push(message);\n }\n\n return removeUndefined({\n frequency_penalty: request.frequency_penalty,\n max_tokens: request.max_output_tokens ?? request.max_tokens,\n messages,\n metadata: request.metadata,\n model: normalizeRequestedModel(request.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 normalizeChatCompletionRequest(request: JsonObject): JsonObject {\n return removeUndefined({\n ...request,\n model: normalizeRequestedModel(request.model),\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: normalizeRequestedModel(request.model),\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function normalizeRequestedModel(model: unknown): string {\n const requested = contentToText(model).trim();\n return requested || DEFAULT_MODEL;\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport { createHoopilotLogger, noopLogger, shouldCreateLogger } from \"./logger\";\nimport {\n chatCompletionToCompletion,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeChatCompletionRequest,\n normalizeModelsResponse,\n} from \"./openai\";\nimport type {\n HoopilotLogger,\n HoopilotServerOptions,\n JsonObject,\n LogFields,\n StartedHoopilotServer,\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\nconst INVALID_JSON_MESSAGE = \"Request body must be valid JSON.\";\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const logger = serverLogger(options);\n\n return async (request: Request): Promise<Response> => {\n const startedAt = performance.now();\n const url = new URL(request.url);\n const apiPath = canonicalApiPath(url.pathname);\n const requestId = requestIdFor(request);\n const requestLogger = logger.child({\n method: request.method,\n path: url.pathname,\n requestId,\n route: routeFor(request.method, apiPath),\n });\n\n if (request.method === \"OPTIONS\") {\n return finishResponse(new Response(null, { headers: corsHeaders() }), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n\n if (!isAuthorized(request, apiKey)) {\n requestLogger.warn({ event: \"http.request.unauthorized\" }, \"invalid hoopilot api key\");\n return finishResponse(\n jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\"),\n {\n logger: requestLogger,\n requestId,\n startedAt,\n },\n );\n }\n\n try {\n if (request.method === \"GET\" && (apiPath === \"/\" || apiPath === \"/healthz\")) {\n return finishResponse(\n jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n }),\n { logger: requestLogger, requestId, startedAt },\n );\n }\n if (request.method === \"GET\" && apiPath === \"/v1/responses\") {\n return finishResponse(websocketUnsupportedResponse(), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"GET\" && apiPath === \"/v1/models\") {\n return finishResponse(await handleModels(client, request.signal, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/chat/completions\") {\n return finishResponse(await handleChatCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/completions\") {\n return finishResponse(await handleCompletions(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n if (request.method === \"POST\" && apiPath === \"/v1/responses\") {\n return finishResponse(await handleResponses(client, request, requestLogger), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n return finishResponse(\n jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`),\n { logger: requestLogger, requestId, startedAt },\n );\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"copilot.auth.missing\" },\n \"copilot auth failed\",\n );\n return finishResponse(jsonError(401, \"copilot_auth_error\", error.message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n const message = errorMessage(error);\n if (message === INVALID_JSON_MESSAGE) {\n requestLogger.warn(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request body was invalid json\",\n );\n } else {\n requestLogger.error(\n { err: errorDetails(error), event: \"http.request.failed\" },\n \"request failed\",\n );\n }\n return finishResponse(jsonError(500, \"internal_error\", message), {\n logger: requestLogger,\n requestId,\n startedAt,\n });\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(\n client: CopilotClient,\n signal: AbortSignal,\n logger: HoopilotLogger,\n): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n if (isUpstreamAuthStatus(upstream.status)) {\n return proxyError(upstream, logger);\n }\n logger.warn(\n {\n event: \"copilot.models.fallback\",\n upstreamPath: \"/models\",\n upstreamStatus: upstream.status,\n },\n \"falling back to built-in model list\",\n );\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n logUpstreamSuccess(logger, \"/models\", upstream.status);\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const chatRequest = normalizeChatCompletionRequest(await readJson(request));\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/chat/completions\", upstream.status);\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(\n client: CopilotClient,\n request: Request,\n logger: HoopilotLogger,\n): Promise<Response> {\n const body = await readJsonText(request);\n const upstream = await client.responses(body, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream, logger);\n }\n logUpstreamSuccess(logger, \"/responses\", upstream.status);\n return proxyResponse(upstream);\n}\n\nasync function proxyError(upstream: Response, logger: HoopilotLogger): Promise<Response> {\n const text = await upstream.text();\n if (isUpstreamAuthStatus(upstream.status)) {\n logger.warn(\n { event: \"copilot.auth.rejected\", upstreamStatus: upstream.status },\n \"copilot rejected credential or account access\",\n );\n return jsonError(401, \"copilot_auth_error\", upstreamAuthMessage(text || upstream.statusText));\n }\n logger.warn(\n { event: \"copilot.request.failed\", upstreamStatus: upstream.status },\n \"copilot upstream request failed\",\n );\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nasync function readJsonText(request: Request): Promise<string> {\n const text = await request.text();\n try {\n JSON.parse(text);\n return text;\n } catch {\n throw new Error(INVALID_JSON_MESSAGE);\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction websocketUnsupportedResponse(): Response {\n const response = jsonError(\n 426,\n \"websocket_not_supported\",\n \"Hoopilot does not support Responses WebSocket transport; retry with HTTP Responses API.\",\n );\n response.headers.set(\"upgrade\", \"websocket\");\n return response;\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isUpstreamAuthStatus(status: number): boolean {\n return status === 401 || status === 403;\n}\n\nfunction upstreamAuthMessage(message: string): string {\n return `GitHub Copilot rejected the credential or account access: ${message}`;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction serverLogger(options: HoopilotServerOptions): HoopilotLogger {\n if (options.logger) {\n return options.logger.child({ component: \"server\" });\n }\n if (shouldCreateLogger(options)) {\n return createHoopilotLogger({\n env: options.env,\n format: options.logFormat,\n level: options.logLevel,\n }).child({ component: \"server\" });\n }\n return noopLogger;\n}\n\nfunction finishResponse(\n response: Response,\n options: { logger: HoopilotLogger; requestId: string; startedAt: number },\n): Response {\n const withRequestId = responseWithRequestId(response, options.requestId);\n logRequestCompleted(options.logger, withRequestId, options.startedAt);\n return withRequestId;\n}\n\nfunction responseWithRequestId(response: Response, requestId: string): Response {\n const headers = new Headers(response.headers);\n headers.set(\"x-request-id\", requestId);\n return new Response(response.body, {\n headers,\n status: response.status,\n statusText: response.statusText,\n });\n}\n\nfunction logRequestCompleted(logger: HoopilotLogger, response: Response, startedAt: number): void {\n const fields: LogFields = {\n durationMs: Math.round((performance.now() - startedAt) * 100) / 100,\n event: \"http.request.completed\",\n status: response.status,\n stream: isStreamingResponse(response),\n };\n if (response.status >= 500) {\n logger.error(fields, \"request completed with server error\");\n return;\n }\n if (response.status >= 400) {\n logger.warn(fields, \"request completed with client error\");\n return;\n }\n logger.info(fields, \"request completed\");\n}\n\nfunction requestIdFor(request: Request): string {\n const existing = request.headers.get(\"x-request-id\")?.trim();\n return existing || crypto.randomUUID();\n}\n\nfunction canonicalApiPath(path: string): string {\n const withoutTrailingSlash = path.length > 1 ? path.replace(/\\/+$/, \"\") : path;\n switch (withoutTrailingSlash) {\n case \"/models\":\n return \"/v1/models\";\n case \"/chat/completions\":\n return \"/v1/chat/completions\";\n case \"/completions\":\n return \"/v1/completions\";\n case \"/responses\":\n return \"/v1/responses\";\n default:\n return withoutTrailingSlash;\n }\n}\n\nfunction routeFor(method: string, path: string): string {\n if (method === \"OPTIONS\") {\n return \"cors.preflight\";\n }\n if (method === \"GET\" && (path === \"/\" || path === \"/healthz\")) {\n return \"health\";\n }\n if (method === \"GET\" && path === \"/v1/models\") {\n return \"models\";\n }\n if (method === \"POST\" && path === \"/v1/chat/completions\") {\n return \"chat_completions\";\n }\n if (method === \"POST\" && path === \"/v1/completions\") {\n return \"completions\";\n }\n if (method === \"POST\" && path === \"/v1/responses\") {\n return \"responses\";\n }\n if (method === \"GET\" && path === \"/v1/responses\") {\n return \"responses_websocket\";\n }\n return \"not_found\";\n}\n\nfunction isStreamingResponse(response: Response): boolean {\n return response.headers.get(\"content-type\")?.includes(\"text/event-stream\") ?? false;\n}\n\nfunction logUpstreamSuccess(logger: HoopilotLogger, upstreamPath: string, status: number): void {\n logger.debug(\n {\n event: \"copilot.request.completed\",\n upstreamPath,\n upstreamStatus: status,\n },\n \"copilot upstream request completed\",\n );\n}\n\nfunction errorDetails(error: unknown): LogFields {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n","// Self-update and update-notification orchestration. The pure decision logic\n// lives in update-core.ts; this module performs the network and filesystem I/O.\nimport { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n mkdirSync,\n realpathSync,\n renameSync,\n rmSync,\n} from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { HoopilotLogger } from \"./types\";\nimport {\n assetNameFor,\n assetSuffixFor,\n checksumFor,\n formatUpdateNotice,\n type InstallKind,\n isOutdated,\n isUpdateCheckDisabled,\n type LatestRelease,\n latestReleaseApiUrl,\n parseLatestRelease,\n parseState,\n resolveCacheDir,\n shouldCleanupOldBinary,\n shouldRefresh,\n type UpdateState,\n upgradeCommandFor,\n} from \"./update-core\";\nimport { BAKED_TARGET, IS_STANDALONE_BINARY } from \"./version\";\n\nconst REQUEST_TIMEOUT_MS = 8_000;\nconst SHA256SUMS = \"SHA256SUMS\";\n\nfunction userAgent(version: string): string {\n return `hoopilot/${version}`;\n}\n\nfunction cacheDir(): string {\n return resolveCacheDir(process.env, process.platform, homedir(), join);\n}\n\nfunction stateFilePath(): string {\n return join(cacheDir(), \"update-check.json\");\n}\n\nasync function readStateSafe(): Promise<UpdateState> {\n try {\n return parseState(await readFile(stateFilePath(), \"utf8\"));\n } catch {\n return { lastCheck: 0, latestVersion: null, etag: null };\n }\n}\n\nasync function writeStateSafe(state: UpdateState): Promise<void> {\n try {\n mkdirSync(cacheDir(), { recursive: true });\n await writeFile(stateFilePath(), JSON.stringify(state), \"utf8\");\n } catch {\n // best effort: a read-only cache dir must never break the CLI\n }\n}\n\ninterface FetchResult {\n status: number;\n etag: string | null;\n release: LatestRelease | null;\n}\n\nasync function fetchLatest(version: string, etag?: string | null): Promise<FetchResult | null> {\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": userAgent(version),\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n };\n if (etag) {\n headers[\"If-None-Match\"] = etag;\n }\n const response = await fetch(latestReleaseApiUrl(), {\n headers,\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n if (response.status === 304) {\n return { status: 304, etag: etag ?? null, release: null };\n }\n if (!response.ok) {\n return { status: response.status, etag: null, release: null };\n }\n return {\n status: response.status,\n etag: response.headers.get(\"etag\"),\n release: parseLatestRelease(await response.json()),\n };\n } catch {\n return null; // offline / timeout: caller leaves state untouched\n }\n}\n\n/**\n * Print a notice if a previously-cached check found a newer release, then kick\n * off a throttled background refresh. Never blocks on the network and never\n * throws. Intended to be called (unawaited is fine) from the serve path.\n */\nexport async function maybeNotifyUpdate(\n currentVersion: string,\n kind: InstallKind,\n logger?: HoopilotLogger,\n): Promise<void> {\n if (isUpdateCheckDisabled(process.env, Boolean(process.stderr.isTTY))) {\n logger?.debug({ event: \"update.check.skipped\" }, \"update check skipped\");\n return;\n }\n const state = await readStateSafe();\n if (state.latestVersion && isOutdated(currentVersion, state.latestVersion)) {\n logger?.debug(\n {\n currentVersion,\n event: \"update.notice.cached\",\n installKind: kind,\n latestVersion: state.latestVersion,\n },\n \"showing cached update notice\",\n );\n process.stderr.write(formatUpdateNotice(currentVersion, state.latestVersion, kind));\n }\n if (shouldRefresh(state.lastCheck, Date.now())) {\n logger?.debug({ event: \"update.check.refresh_queued\" }, \"queued update check refresh\");\n void refreshState(currentVersion, state.etag ?? null, logger).catch((error: unknown) => {\n logger?.debug(\n { err: errorDetails(error), event: \"update.check.refresh_failed\" },\n \"update check refresh failed\",\n );\n });\n }\n}\n\nasync function refreshState(\n currentVersion: string,\n etag: string | null,\n logger?: HoopilotLogger,\n): Promise<void> {\n const result = await fetchLatest(currentVersion, etag);\n if (!result) {\n logger?.debug({ event: \"update.check.unavailable\" }, \"update check unavailable\");\n return; // network error: keep prior state\n }\n if (result.status === 304) {\n const prev = await readStateSafe();\n await writeStateSafe({ ...prev, lastCheck: Date.now() });\n logger?.debug({ event: \"update.check.not_modified\" }, \"latest release unchanged\");\n return;\n }\n if (result.release) {\n await writeStateSafe({\n lastCheck: Date.now(),\n latestVersion: result.release.version,\n etag: result.etag,\n });\n logger?.debug(\n { event: \"update.check.updated\", latestVersion: result.release.version },\n \"updated cached latest release state\",\n );\n }\n}\n\nfunction detectInstallKind(): InstallKind {\n return IS_STANDALONE_BINARY ? \"binary\" : \"npm\";\n}\n\nfunction detectMusl(): boolean {\n if (process.platform !== \"linux\") {\n return false;\n }\n try {\n const report = process.report?.getReport?.() as\n | { header?: Record<string, unknown> }\n | undefined;\n if (report?.header && \"glibcVersionRuntime\" in report.header) {\n return !report.header.glibcVersionRuntime;\n }\n } catch {\n // fall through to file-based detection\n }\n try {\n if (existsSync(\"/etc/alpine-release\")) {\n return true;\n }\n const ldd = execFileSync(\"ldd\", [\"--version\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 2_000,\n });\n return /musl/i.test(ldd);\n } catch {\n return false;\n }\n}\n\nasync function downloadToFile(url: string, dest: string, version: string): Promise<void> {\n const response = await fetch(url, {\n headers: { \"User-Agent\": userAgent(version) },\n redirect: \"follow\",\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS * 10),\n });\n if (!response.ok || !response.body) {\n throw new Error(`Download failed (${response.status}) for ${url}`);\n }\n await writeFile(dest, new Uint8Array(await response.arrayBuffer()));\n}\n\nasync function sha256File(path: string): Promise<string> {\n return createHash(\"sha256\")\n .update(await readFile(path))\n .digest(\"hex\");\n}\n\nasync function verifyChecksum(\n release: LatestRelease,\n assetName: string,\n file: string,\n version: string,\n): Promise<void> {\n const sums = release.assets.find((asset) => asset.name === SHA256SUMS);\n if (!sums) {\n // Fail closed: never overwrite the running binary with an unverified download.\n throw new Error(\n `Release ${release.tag} has no ${SHA256SUMS}; refusing to install an unverified binary.`,\n );\n }\n const response = await fetch(sums.url, {\n headers: { \"User-Agent\": userAgent(version) },\n redirect: \"follow\",\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n if (!response.ok) {\n throw new Error(`Could not download ${SHA256SUMS} (${response.status}).`);\n }\n const expected = checksumFor(await response.text(), assetName);\n if (!expected) {\n throw new Error(`No checksum for ${assetName} in ${SHA256SUMS}.`);\n }\n const actual = await sha256File(file);\n if (actual.toLowerCase() !== expected) {\n throw new Error(`Checksum mismatch for ${assetName}: expected ${expected}, got ${actual}.`);\n }\n}\n\nfunction swapBinary(tmpFile: string, exePath: string): void {\n if (process.platform === \"win32\") {\n // A running .exe cannot be overwritten, but it can be renamed aside.\n const oldExe = `${exePath}.old`;\n try {\n rmSync(oldExe, { force: true });\n } catch {\n // a previous .old may still be locked; the new name still wins below\n }\n renameSync(exePath, oldExe);\n const restore = () => {\n try {\n renameSync(oldExe, exePath); // put the working binary back\n } catch {\n // nothing more we can do\n }\n };\n try {\n renameSync(tmpFile, exePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EXDEV\") {\n try {\n copyFileSync(tmpFile, exePath);\n } catch (copyError) {\n restore();\n throw copyError;\n }\n } else {\n restore();\n throw error;\n }\n }\n return;\n }\n // Unix: atomic rename over the running file; the old inode stays mapped until exit.\n try {\n renameSync(tmpFile, exePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EXDEV\") {\n copyFileSync(tmpFile, exePath);\n chmodSync(exePath, 0o755);\n } else if (code === \"EACCES\" || code === \"EPERM\") {\n throw new Error(\n `No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory.`,\n );\n } else {\n throw error;\n }\n }\n}\n\n/** Remove the leftover \".old\" binary from a prior Windows self-update. */\nexport function cleanupOldBinary(): void {\n if (!shouldCleanupOldBinary(process.platform, IS_STANDALONE_BINARY)) {\n return;\n }\n try {\n rmSync(`${realpathSync(process.execPath)}.old`, { force: true });\n } catch {\n // still locked or already gone\n }\n}\n\n/** Implements the `hoopilot update` command. */\nexport async function runUpdate(currentVersion: string, logger?: HoopilotLogger): Promise<void> {\n cleanupOldBinary();\n const kind = detectInstallKind();\n logger?.debug({ currentVersion, event: \"update.started\", installKind: kind }, \"update started\");\n\n if (kind !== \"binary\") {\n console.log(`hoopilot ${currentVersion} was installed via npm.`);\n console.log(`Update with: ${upgradeCommandFor(\"npm\")}`);\n return;\n }\n\n console.log(`hoopilot ${currentVersion} — checking for updates...`);\n const result = await fetchLatest(currentVersion);\n const release = result?.release ?? null;\n if (!release) {\n throw new Error(\"Could not reach GitHub to check for the latest release.\");\n }\n if (!isOutdated(currentVersion, release.version)) {\n logger?.debug(\n { currentVersion, event: \"update.already_current\", latestVersion: release.version },\n \"hoopilot is already up to date\",\n );\n console.log(`Already up to date (latest: ${release.version}).`);\n return;\n }\n\n const suffix = BAKED_TARGET ?? assetSuffixFor(process.platform, process.arch, detectMusl());\n const assetName = assetNameFor(suffix);\n const asset = release.assets.find((entry) => entry.name === assetName);\n if (!asset) {\n const available = release.assets.map((entry) => entry.name).join(\", \") || \"none\";\n throw new Error(`Release ${release.tag} has no asset \"${assetName}\". Available: ${available}.`);\n }\n\n console.log(`Updating ${currentVersion} → ${release.version} (${assetName})...`);\n logger?.debug(\n {\n assetName,\n currentVersion,\n event: \"update.installing\",\n latestVersion: release.version,\n },\n \"installing update\",\n );\n const exePath = realpathSync(process.execPath);\n const tmpFile = join(dirname(exePath), `.hoopilot-update-${process.pid}.tmp`);\n try {\n await downloadToFile(asset.url, tmpFile, currentVersion);\n await verifyChecksum(release, assetName, tmpFile, currentVersion);\n if (process.platform !== \"win32\") {\n chmodSync(tmpFile, 0o755);\n }\n swapBinary(tmpFile, exePath);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EACCES\" || code === \"EPERM\") {\n throw new Error(\n `No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory (e.g. set HOOPILOT_INSTALL_DIR).`,\n );\n }\n throw error;\n } finally {\n try {\n rmSync(tmpFile, { force: true });\n } catch {\n // already moved into place or never created\n }\n }\n\n console.log(`Updated hoopilot to ${release.version}.`);\n logger?.debug(\n { currentVersion, event: \"update.completed\", latestVersion: release.version },\n \"update completed\",\n );\n if (process.platform === \"win32\") {\n console.log(\"Restart hoopilot to run the new version.\");\n }\n}\n\nfunction errorDetails(error: unknown): Record<string, unknown> {\n if (error instanceof Error) {\n return {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n }\n return { message: String(error) };\n}\n","// Pure, dependency-free logic for version checks and self-update decisions.\n// Everything here is side-effect free so it can be unit tested without network\n// or filesystem access; the I/O orchestration lives in update.ts.\n\nexport const REPO_OWNER = \"openhoo\";\nexport const REPO_NAME = \"hoopilot\";\nexport const REPO = `${REPO_OWNER}/${REPO_NAME}`;\nexport const NPM_PACKAGE = \"@openhoo/hoopilot\";\n\n/** How a copy of hoopilot was installed. */\nexport type InstallKind = \"binary\" | \"npm\";\n\n/** How often the background update check is allowed to hit GitHub. */\nexport const UPDATE_CHECK_INTERVAL_MS = 1000 * 60 * 60 * 24; // 24h\n\n/** Persisted state for the throttled update check. */\nexport interface UpdateState {\n lastCheck: number;\n latestVersion: string | null;\n etag?: string | null;\n}\n\ninterface SemVer {\n major: number;\n minor: number;\n patch: number;\n prerelease: string[];\n}\n\nfunction parseSemver(input: string): SemVer | null {\n const value = String(input)\n .trim()\n .replace(/^[v=]+/, \"\");\n const match = value.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/);\n if (!match) {\n return null;\n }\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n // Build metadata (everything after \"+\") is intentionally dropped.\n prerelease: match[4] ? match[4].split(\".\") : [],\n };\n}\n\nfunction comparePrerelease(a: string[], b: string[]): -1 | 0 | 1 {\n if (a.length === 0 && b.length === 0) {\n return 0;\n }\n // A release outranks an otherwise-equal prerelease.\n if (a.length === 0) {\n return 1;\n }\n if (b.length === 0) {\n return -1;\n }\n const len = Math.max(a.length, b.length);\n for (let i = 0; i < len; i++) {\n const x = a[i];\n const y = b[i];\n // The version with more prerelease fields has higher precedence.\n if (x === undefined) {\n return -1;\n }\n if (y === undefined) {\n return 1;\n }\n const xNumeric = /^\\d+$/.test(x);\n const yNumeric = /^\\d+$/.test(y);\n if (xNumeric && yNumeric) {\n const diff = Number(x) - Number(y);\n if (diff !== 0) {\n return diff < 0 ? -1 : 1;\n }\n } else if (xNumeric) {\n return -1; // numeric identifiers sort lower than alphanumeric\n } else if (yNumeric) {\n return 1;\n } else if (x !== y) {\n return x < y ? -1 : 1; // ASCII lexical\n }\n }\n return 0;\n}\n\n/**\n * Compare two semantic versions. Returns -1 if a < b, 0 if equal, 1 if a > b.\n * Tolerates a leading \"v\"/\"=\", ignores build metadata, honors prerelease\n * precedence, and sorts unparseable input low so a bad value never throws.\n */\nexport function compareSemver(a: string, b: string): -1 | 0 | 1 {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) {\n if (!pa && !pb) {\n return 0;\n }\n return pa ? 1 : -1;\n }\n if (pa.major !== pb.major) {\n return pa.major < pb.major ? -1 : 1;\n }\n if (pa.minor !== pb.minor) {\n return pa.minor < pb.minor ? -1 : 1;\n }\n if (pa.patch !== pb.patch) {\n return pa.patch < pb.patch ? -1 : 1;\n }\n return comparePrerelease(pa.prerelease, pb.prerelease);\n}\n\n/** True when `latest` is a strictly newer release than `current`. */\nexport function isOutdated(current: string, latest: string): boolean {\n return compareSemver(current, latest) < 0;\n}\n\n/** Strip a leading \"v\" from a git tag to get a bare version string. */\nexport function versionFromTag(tag: string): string {\n return tag.trim().replace(/^v/, \"\");\n}\n\n/**\n * Compute the release asset suffix for a platform/arch, e.g. \"linux-x64-musl\",\n * \"darwin-arm64\", \"windows-x64\". `platform`/`arch` use Node's process values.\n */\nexport function assetSuffixFor(platform: string, arch: string, isMusl: boolean): string {\n const os = platform === \"win32\" ? \"windows\" : platform === \"darwin\" ? \"darwin\" : \"linux\";\n const cpu = arch === \"arm64\" || arch === \"aarch64\" ? \"arm64\" : \"x64\";\n const libc = os === \"linux\" && isMusl ? \"-musl\" : \"\";\n return `${os}-${cpu}${libc}`;\n}\n\n/** Full release asset file name for a suffix (adds .exe for Windows). */\nexport function assetNameFor(suffix: string): string {\n const name = `hoopilot-${suffix}`;\n return suffix.startsWith(\"windows-\") ? `${name}.exe` : name;\n}\n\n/** Whether automatic update checks should be skipped, per env + TTY. */\nexport function isUpdateCheckDisabled(\n env: Record<string, string | undefined>,\n isTty: boolean,\n): boolean {\n if (env.HOOPILOT_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER) {\n return true;\n }\n if (env.NODE_ENV === \"test\") {\n return true;\n }\n if (!isTty) {\n return true; // piped / non-interactive output\n }\n if (\n (env.CI && env.CI !== \"false\") ||\n env.CONTINUOUS_INTEGRATION ||\n env.GITHUB_ACTIONS ||\n env.BUILD_NUMBER ||\n env.RUN_ID\n ) {\n return true;\n }\n return false;\n}\n\n/** Whether the background check is due again given the last check time. */\nexport function shouldRefresh(\n lastCheck: number,\n now: number,\n intervalMs = UPDATE_CHECK_INTERVAL_MS,\n): boolean {\n return now - lastCheck >= intervalMs;\n}\n\n/** The command a user runs to upgrade, depending on how they installed. */\nexport function upgradeCommandFor(kind: InstallKind): string {\n return kind === \"binary\"\n ? \"hoopilot update\"\n : `npm install -g ${NPM_PACKAGE}@latest (or: bun add -g ${NPM_PACKAGE})`;\n}\n\n/** Whether it is safe to remove a leftover Windows self-update backup. */\nexport function shouldCleanupOldBinary(platform: string, isStandaloneBinary: boolean): boolean {\n return platform === \"win32\" && isStandaloneBinary;\n}\n\n/** Render the \"update available\" notice printed to stderr. */\nexport function formatUpdateNotice(current: string, latest: string, kind: InstallKind): string {\n return (\n `\\nUpdate available for hoopilot: ${current} → ${latest}\\n` +\n `Run: ${upgradeCommandFor(kind)}\\n\\n`\n );\n}\n\n/** Parse the persisted update-check state, tolerating any malformed input. */\nexport function parseState(text: string): UpdateState {\n try {\n const data = JSON.parse(text) as Partial<UpdateState>;\n return {\n lastCheck: typeof data.lastCheck === \"number\" ? data.lastCheck : 0,\n latestVersion: typeof data.latestVersion === \"string\" ? data.latestVersion : null,\n etag: typeof data.etag === \"string\" ? data.etag : null,\n };\n } catch {\n return { lastCheck: 0, latestVersion: null, etag: null };\n }\n}\n\nexport interface LatestRelease {\n version: string;\n tag: string;\n assets: Array<{ name: string; url: string }>;\n}\n\n/** Parse the GitHub `releases/latest` response into the fields we need. */\nexport function parseLatestRelease(json: unknown): LatestRelease | null {\n if (!json || typeof json !== \"object\") {\n return null;\n }\n const record = json as Record<string, unknown>;\n const tag = typeof record.tag_name === \"string\" ? record.tag_name : undefined;\n if (!tag) {\n return null;\n }\n const assets: Array<{ name: string; url: string }> = [];\n if (Array.isArray(record.assets)) {\n for (const item of record.assets) {\n if (item && typeof item === \"object\") {\n const asset = item as Record<string, unknown>;\n if (typeof asset.name === \"string\" && typeof asset.browser_download_url === \"string\") {\n assets.push({ name: asset.name, url: asset.browser_download_url });\n }\n }\n }\n }\n return { version: versionFromTag(tag), tag, assets };\n}\n\n/** Find a checksum line for `fileName` in a `sha256sum`-style SHA256SUMS file. */\nexport function checksumFor(sumsText: string, fileName: string): string | undefined {\n for (const line of sumsText.split(/\\r?\\n/)) {\n const match = line.trim().match(/^([0-9a-fA-F]{64})\\s+\\*?(.+)$/);\n if (match?.[1] && match[2]?.trim() === fileName) {\n return match[1].toLowerCase();\n }\n }\n return undefined;\n}\n\n/**\n * Resolve the per-OS cache directory (no deps). Mirrors env-paths conventions:\n * Windows -> %LOCALAPPDATA%, macOS -> ~/Library/Caches, else $XDG_CACHE_HOME||~/.cache.\n */\nexport function resolveCacheDir(\n env: Record<string, string | undefined>,\n platform: string,\n homedir: string,\n join: (...parts: string[]) => string,\n): string {\n if (platform === \"win32\") {\n const base = env.LOCALAPPDATA || join(homedir, \"AppData\", \"Local\");\n return join(base, \"hoopilot\");\n }\n if (platform === \"darwin\") {\n return join(homedir, \"Library\", \"Caches\", \"hoopilot\");\n }\n const base = env.XDG_CACHE_HOME || join(homedir, \".cache\");\n return join(base, \"hoopilot\");\n}\n\n/** Stable redirect URL that downloads an asset from the latest release. */\nexport function latestDownloadUrl(asset: string): string {\n return `https://github.com/${REPO}/releases/latest/download/${asset}`;\n}\n\n/** GitHub REST endpoint for the latest release. */\nexport function latestReleaseApiUrl(): string {\n return `https://api.github.com/repos/${REPO}/releases/latest`;\n}\n","// Build-time constants. For standalone binaries these identifiers are replaced\n// at compile time via `bun build --compile --define 'HOOPILOT_VERSION=\"x.y.z\"'`\n// (see scripts/build-binaries.sh). In dev runs and the npm package they are not\n// defined, so `typeof` is \"undefined\" and we fall back to reading package.json.\ndeclare const HOOPILOT_VERSION: string;\ndeclare const HOOPILOT_TARGET: string;\n\n/** Version baked into a standalone binary, or undefined for npm/dev installs. */\nexport const BAKED_VERSION: string | undefined =\n typeof HOOPILOT_VERSION !== \"undefined\" ? HOOPILOT_VERSION : undefined;\n\n/**\n * Release asset suffix baked into a standalone binary (e.g. \"linux-x64-musl\",\n * \"windows-x64\", \"darwin-arm64\"), or undefined for npm/dev installs. Lets the\n * self-updater fetch the exact asset variant it was built from.\n */\nexport const BAKED_TARGET: string | undefined =\n typeof HOOPILOT_TARGET !== \"undefined\" ? HOOPILOT_TARGET : undefined;\n\n/** True when running as a `bun build --compile` standalone executable. */\nexport const IS_STANDALONE_BINARY: boolean = BAKED_VERSION !== undefined;\n\nlet cachedVersion: string | undefined;\n\n/** Resolve the running version, preferring the baked value for binaries. */\nexport async function getVersion(): Promise<string> {\n if (cachedVersion !== undefined) {\n return cachedVersion;\n }\n let resolved: string;\n if (BAKED_VERSION) {\n resolved = BAKED_VERSION;\n } else {\n try {\n const manifest = await Bun.file(new URL(\"../package.json\", import.meta.url)).json();\n resolved = typeof manifest.version === \"string\" ? manifest.version : \"0.0.0\";\n } catch {\n resolved = \"0.0.0\";\n }\n }\n cachedVersion = resolved;\n return resolved;\n}\n"],"mappings":"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","names":["chmodSync","mkdirSync","dirname","join","homedir","join","base","join","mkdirSync","errorDetails","chmodSync","dirname","DEFAULT_COPILOT_API_BASE_URL","args","logger","safeResponseText","trimTrailingSlash","asRecord"]}
|