@openhoo/hoopilot 0.2.4 → 0.3.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 +64 -4
- package/dist/cli.js +508 -10
- package/dist/cli.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -7,16 +7,76 @@ OpenAI-compatible local proxy for GitHub Copilot accounts. It runs on Bun and ex
|
|
|
7
7
|
|
|
8
8
|
This project uses GitHub Copilot's service endpoints and is not an official GitHub product. The upstream API can change without notice. Use it only with accounts and usage patterns you are allowed to use.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
### npm (recommended when the registry is reachable)
|
|
11
13
|
|
|
12
14
|
```sh
|
|
13
15
|
npx @openhoo/hoopilot
|
|
14
16
|
```
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Or install it globally:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm install -g @openhoo/hoopilot
|
|
22
|
+
# or
|
|
23
|
+
bun add -g @openhoo/hoopilot
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Standalone binary (no npm, no runtime required)
|
|
27
|
+
|
|
28
|
+
When the npm registry is unreachable but GitHub is, install a prebuilt,
|
|
29
|
+
self-contained binary straight from the latest GitHub release. No Node.js or Bun
|
|
30
|
+
is needed to run it.
|
|
31
|
+
|
|
32
|
+
Linux / macOS:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
curl -fsSL https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.sh | sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Windows (PowerShell):
|
|
39
|
+
|
|
40
|
+
```powershell
|
|
41
|
+
irm https://raw.githubusercontent.com/openhoo/hoopilot/main/scripts/install.ps1 | iex
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The installer detects your OS, CPU architecture (x64/arm64), and libc (glibc or
|
|
45
|
+
musl), downloads the matching binary, verifies its SHA-256 checksum, and installs
|
|
46
|
+
it to `~/.local/bin` (Linux/macOS) or `%LOCALAPPDATA%\Programs\hoopilot`
|
|
47
|
+
(Windows). Override the location with `HOOPILOT_INSTALL_DIR`, or pin a version:
|
|
17
48
|
|
|
18
49
|
```sh
|
|
19
|
-
|
|
50
|
+
curl -fsSL .../install.sh | sh -s -- --version 0.2.5 --dir ~/bin
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
& ([scriptblock]::Create((irm .../install.ps1))) -Version 0.2.5
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Prebuilt binaries are available for Linux (x64/arm64, glibc and musl), macOS
|
|
58
|
+
(Intel/Apple Silicon), and Windows (x64/arm64).
|
|
59
|
+
|
|
60
|
+
## Update
|
|
61
|
+
|
|
62
|
+
Standalone binaries update themselves in place from the latest GitHub release
|
|
63
|
+
(checksum-verified):
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
hoopilot update
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
npm installs report when a newer version is available and print the right command
|
|
70
|
+
(`npm install -g @openhoo/hoopilot@latest`). Either way, Hoopilot checks GitHub at
|
|
71
|
+
most once a day in the background and prints a one-line notice to stderr when an
|
|
72
|
+
update exists. Disable the check with `--no-update-check`, or by setting
|
|
73
|
+
`HOOPILOT_NO_UPDATE_CHECK` / `NO_UPDATE_NOTIFIER`; it is also skipped in CI and
|
|
74
|
+
when output is not a terminal.
|
|
75
|
+
|
|
76
|
+
## Run
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
npx @openhoo/hoopilot
|
|
20
80
|
```
|
|
21
81
|
|
|
22
82
|
By default Hoopilot listens on `127.0.0.1:4141`, uses `COPILOT_API_TOKEN` when provided, otherwise reads a GitHub CLI OAuth token from `COPILOT_GITHUB_TOKEN` or `gh auth token`, and uses that token with Copilot.
|
|
@@ -129,7 +189,7 @@ bun run biome:fix
|
|
|
129
189
|
|
|
130
190
|
## Release
|
|
131
191
|
|
|
132
|
-
Commits merged to `main` are evaluated by hooversion after CI passes. When a release is produced, the release workflow creates the release commit, tag, and GitHub release automatically,
|
|
192
|
+
Commits merged to `main` are evaluated by hooversion after CI passes. When a release is produced, the release workflow creates the release commit, tag, and GitHub release automatically, publishes the package through npm trusted publishing, then cross-compiles standalone binaries for every supported platform (`scripts/build-binaries.sh`) and attaches them — plus a `SHA256SUMS` manifest — to the GitHub release. Build all binaries locally with `bun run build:binaries`.
|
|
133
193
|
|
|
134
194
|
Configure npm trusted publishing for `@openhoo/hoopilot` on npmjs.com before relying on automatic publication. The workflow uses GitHub Actions OIDC with `npm publish --access public --provenance`.
|
|
135
195
|
|
package/dist/cli.js
CHANGED
|
@@ -1010,21 +1010,516 @@ function errorMessage2(error) {
|
|
|
1010
1010
|
return error instanceof Error ? error.message : String(error);
|
|
1011
1011
|
}
|
|
1012
1012
|
|
|
1013
|
+
// src/update.ts
|
|
1014
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
1015
|
+
import {
|
|
1016
|
+
chmodSync,
|
|
1017
|
+
copyFileSync,
|
|
1018
|
+
existsSync,
|
|
1019
|
+
mkdirSync,
|
|
1020
|
+
realpathSync,
|
|
1021
|
+
renameSync,
|
|
1022
|
+
rmSync
|
|
1023
|
+
} from "fs";
|
|
1024
|
+
import { readFile, writeFile } from "fs/promises";
|
|
1025
|
+
import { homedir } from "os";
|
|
1026
|
+
import { dirname, join } from "path";
|
|
1027
|
+
|
|
1028
|
+
// src/update-core.ts
|
|
1029
|
+
var REPO_OWNER = "openhoo";
|
|
1030
|
+
var REPO_NAME = "hoopilot";
|
|
1031
|
+
var REPO = `${REPO_OWNER}/${REPO_NAME}`;
|
|
1032
|
+
var NPM_PACKAGE = "@openhoo/hoopilot";
|
|
1033
|
+
var UPDATE_CHECK_INTERVAL_MS = 1e3 * 60 * 60 * 24;
|
|
1034
|
+
function parseSemver(input) {
|
|
1035
|
+
const value = String(input).trim().replace(/^[v=]+/, "");
|
|
1036
|
+
const match = value.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);
|
|
1037
|
+
if (!match) {
|
|
1038
|
+
return null;
|
|
1039
|
+
}
|
|
1040
|
+
return {
|
|
1041
|
+
major: Number(match[1]),
|
|
1042
|
+
minor: Number(match[2]),
|
|
1043
|
+
patch: Number(match[3]),
|
|
1044
|
+
// Build metadata (everything after "+") is intentionally dropped.
|
|
1045
|
+
prerelease: match[4] ? match[4].split(".") : []
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
function comparePrerelease(a, b) {
|
|
1049
|
+
if (a.length === 0 && b.length === 0) {
|
|
1050
|
+
return 0;
|
|
1051
|
+
}
|
|
1052
|
+
if (a.length === 0) {
|
|
1053
|
+
return 1;
|
|
1054
|
+
}
|
|
1055
|
+
if (b.length === 0) {
|
|
1056
|
+
return -1;
|
|
1057
|
+
}
|
|
1058
|
+
const len = Math.max(a.length, b.length);
|
|
1059
|
+
for (let i = 0; i < len; i++) {
|
|
1060
|
+
const x = a[i];
|
|
1061
|
+
const y = b[i];
|
|
1062
|
+
if (x === void 0) {
|
|
1063
|
+
return -1;
|
|
1064
|
+
}
|
|
1065
|
+
if (y === void 0) {
|
|
1066
|
+
return 1;
|
|
1067
|
+
}
|
|
1068
|
+
const xNumeric = /^\d+$/.test(x);
|
|
1069
|
+
const yNumeric = /^\d+$/.test(y);
|
|
1070
|
+
if (xNumeric && yNumeric) {
|
|
1071
|
+
const diff = Number(x) - Number(y);
|
|
1072
|
+
if (diff !== 0) {
|
|
1073
|
+
return diff < 0 ? -1 : 1;
|
|
1074
|
+
}
|
|
1075
|
+
} else if (xNumeric) {
|
|
1076
|
+
return -1;
|
|
1077
|
+
} else if (yNumeric) {
|
|
1078
|
+
return 1;
|
|
1079
|
+
} else if (x !== y) {
|
|
1080
|
+
return x < y ? -1 : 1;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
return 0;
|
|
1084
|
+
}
|
|
1085
|
+
function compareSemver(a, b) {
|
|
1086
|
+
const pa = parseSemver(a);
|
|
1087
|
+
const pb = parseSemver(b);
|
|
1088
|
+
if (!pa || !pb) {
|
|
1089
|
+
if (!pa && !pb) {
|
|
1090
|
+
return 0;
|
|
1091
|
+
}
|
|
1092
|
+
return pa ? 1 : -1;
|
|
1093
|
+
}
|
|
1094
|
+
if (pa.major !== pb.major) {
|
|
1095
|
+
return pa.major < pb.major ? -1 : 1;
|
|
1096
|
+
}
|
|
1097
|
+
if (pa.minor !== pb.minor) {
|
|
1098
|
+
return pa.minor < pb.minor ? -1 : 1;
|
|
1099
|
+
}
|
|
1100
|
+
if (pa.patch !== pb.patch) {
|
|
1101
|
+
return pa.patch < pb.patch ? -1 : 1;
|
|
1102
|
+
}
|
|
1103
|
+
return comparePrerelease(pa.prerelease, pb.prerelease);
|
|
1104
|
+
}
|
|
1105
|
+
function isOutdated(current, latest) {
|
|
1106
|
+
return compareSemver(current, latest) < 0;
|
|
1107
|
+
}
|
|
1108
|
+
function versionFromTag(tag) {
|
|
1109
|
+
return tag.trim().replace(/^v/, "");
|
|
1110
|
+
}
|
|
1111
|
+
function assetSuffixFor(platform, arch, isMusl) {
|
|
1112
|
+
const os = platform === "win32" ? "windows" : platform === "darwin" ? "darwin" : "linux";
|
|
1113
|
+
const cpu = arch === "arm64" || arch === "aarch64" ? "arm64" : "x64";
|
|
1114
|
+
const libc = os === "linux" && isMusl ? "-musl" : "";
|
|
1115
|
+
return `${os}-${cpu}${libc}`;
|
|
1116
|
+
}
|
|
1117
|
+
function assetNameFor(suffix) {
|
|
1118
|
+
const name = `hoopilot-${suffix}`;
|
|
1119
|
+
return suffix.startsWith("windows-") ? `${name}.exe` : name;
|
|
1120
|
+
}
|
|
1121
|
+
function isUpdateCheckDisabled(env, isTty) {
|
|
1122
|
+
if (env.HOOPILOT_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER) {
|
|
1123
|
+
return true;
|
|
1124
|
+
}
|
|
1125
|
+
if (env.NODE_ENV === "test") {
|
|
1126
|
+
return true;
|
|
1127
|
+
}
|
|
1128
|
+
if (!isTty) {
|
|
1129
|
+
return true;
|
|
1130
|
+
}
|
|
1131
|
+
if (env.CI && env.CI !== "false" || env.CONTINUOUS_INTEGRATION || env.GITHUB_ACTIONS || env.BUILD_NUMBER || env.RUN_ID) {
|
|
1132
|
+
return true;
|
|
1133
|
+
}
|
|
1134
|
+
return false;
|
|
1135
|
+
}
|
|
1136
|
+
function shouldRefresh(lastCheck, now, intervalMs = UPDATE_CHECK_INTERVAL_MS) {
|
|
1137
|
+
return now - lastCheck >= intervalMs;
|
|
1138
|
+
}
|
|
1139
|
+
function upgradeCommandFor(kind) {
|
|
1140
|
+
return kind === "binary" ? "hoopilot update" : `npm install -g ${NPM_PACKAGE}@latest (or: bun add -g ${NPM_PACKAGE})`;
|
|
1141
|
+
}
|
|
1142
|
+
function shouldCleanupOldBinary(platform, isStandaloneBinary) {
|
|
1143
|
+
return platform === "win32" && isStandaloneBinary;
|
|
1144
|
+
}
|
|
1145
|
+
function formatUpdateNotice(current, latest, kind) {
|
|
1146
|
+
return `
|
|
1147
|
+
Update available for hoopilot: ${current} \u2192 ${latest}
|
|
1148
|
+
Run: ${upgradeCommandFor(kind)}
|
|
1149
|
+
|
|
1150
|
+
`;
|
|
1151
|
+
}
|
|
1152
|
+
function parseState(text) {
|
|
1153
|
+
try {
|
|
1154
|
+
const data = JSON.parse(text);
|
|
1155
|
+
return {
|
|
1156
|
+
lastCheck: typeof data.lastCheck === "number" ? data.lastCheck : 0,
|
|
1157
|
+
latestVersion: typeof data.latestVersion === "string" ? data.latestVersion : null,
|
|
1158
|
+
etag: typeof data.etag === "string" ? data.etag : null
|
|
1159
|
+
};
|
|
1160
|
+
} catch {
|
|
1161
|
+
return { lastCheck: 0, latestVersion: null, etag: null };
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
function parseLatestRelease(json) {
|
|
1165
|
+
if (!json || typeof json !== "object") {
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1168
|
+
const record = json;
|
|
1169
|
+
const tag = typeof record.tag_name === "string" ? record.tag_name : void 0;
|
|
1170
|
+
if (!tag) {
|
|
1171
|
+
return null;
|
|
1172
|
+
}
|
|
1173
|
+
const assets = [];
|
|
1174
|
+
if (Array.isArray(record.assets)) {
|
|
1175
|
+
for (const item of record.assets) {
|
|
1176
|
+
if (item && typeof item === "object") {
|
|
1177
|
+
const asset = item;
|
|
1178
|
+
if (typeof asset.name === "string" && typeof asset.browser_download_url === "string") {
|
|
1179
|
+
assets.push({ name: asset.name, url: asset.browser_download_url });
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return { version: versionFromTag(tag), tag, assets };
|
|
1185
|
+
}
|
|
1186
|
+
function checksumFor(sumsText, fileName) {
|
|
1187
|
+
for (const line of sumsText.split(/\r?\n/)) {
|
|
1188
|
+
const match = line.trim().match(/^([0-9a-fA-F]{64})\s+\*?(.+)$/);
|
|
1189
|
+
if (match?.[1] && match[2]?.trim() === fileName) {
|
|
1190
|
+
return match[1].toLowerCase();
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
function resolveCacheDir(env, platform, homedir2, join2) {
|
|
1196
|
+
if (platform === "win32") {
|
|
1197
|
+
const base2 = env.LOCALAPPDATA || join2(homedir2, "AppData", "Local");
|
|
1198
|
+
return join2(base2, "hoopilot");
|
|
1199
|
+
}
|
|
1200
|
+
if (platform === "darwin") {
|
|
1201
|
+
return join2(homedir2, "Library", "Caches", "hoopilot");
|
|
1202
|
+
}
|
|
1203
|
+
const base = env.XDG_CACHE_HOME || join2(homedir2, ".cache");
|
|
1204
|
+
return join2(base, "hoopilot");
|
|
1205
|
+
}
|
|
1206
|
+
function latestReleaseApiUrl() {
|
|
1207
|
+
return `https://api.github.com/repos/${REPO}/releases/latest`;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// src/version.ts
|
|
1211
|
+
var BAKED_VERSION = typeof HOOPILOT_VERSION !== "undefined" ? HOOPILOT_VERSION : void 0;
|
|
1212
|
+
var BAKED_TARGET = typeof HOOPILOT_TARGET !== "undefined" ? HOOPILOT_TARGET : void 0;
|
|
1213
|
+
var IS_STANDALONE_BINARY = BAKED_VERSION !== void 0;
|
|
1214
|
+
var cachedVersion;
|
|
1215
|
+
async function getVersion() {
|
|
1216
|
+
if (cachedVersion !== void 0) {
|
|
1217
|
+
return cachedVersion;
|
|
1218
|
+
}
|
|
1219
|
+
let resolved;
|
|
1220
|
+
if (BAKED_VERSION) {
|
|
1221
|
+
resolved = BAKED_VERSION;
|
|
1222
|
+
} else {
|
|
1223
|
+
try {
|
|
1224
|
+
const manifest = await Bun.file(new URL("../package.json", import.meta.url)).json();
|
|
1225
|
+
resolved = typeof manifest.version === "string" ? manifest.version : "0.0.0";
|
|
1226
|
+
} catch {
|
|
1227
|
+
resolved = "0.0.0";
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
cachedVersion = resolved;
|
|
1231
|
+
return resolved;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// src/update.ts
|
|
1235
|
+
var REQUEST_TIMEOUT_MS = 8e3;
|
|
1236
|
+
var SHA256SUMS = "SHA256SUMS";
|
|
1237
|
+
function userAgent(version) {
|
|
1238
|
+
return `hoopilot/${version}`;
|
|
1239
|
+
}
|
|
1240
|
+
function cacheDir() {
|
|
1241
|
+
return resolveCacheDir(process.env, process.platform, homedir(), join);
|
|
1242
|
+
}
|
|
1243
|
+
function stateFilePath() {
|
|
1244
|
+
return join(cacheDir(), "update-check.json");
|
|
1245
|
+
}
|
|
1246
|
+
async function readStateSafe() {
|
|
1247
|
+
try {
|
|
1248
|
+
return parseState(await readFile(stateFilePath(), "utf8"));
|
|
1249
|
+
} catch {
|
|
1250
|
+
return { lastCheck: 0, latestVersion: null, etag: null };
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
async function writeStateSafe(state) {
|
|
1254
|
+
try {
|
|
1255
|
+
mkdirSync(cacheDir(), { recursive: true });
|
|
1256
|
+
await writeFile(stateFilePath(), JSON.stringify(state), "utf8");
|
|
1257
|
+
} catch {
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
async function fetchLatest(version, etag) {
|
|
1261
|
+
try {
|
|
1262
|
+
const headers = {
|
|
1263
|
+
Accept: "application/vnd.github+json",
|
|
1264
|
+
"User-Agent": userAgent(version),
|
|
1265
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1266
|
+
};
|
|
1267
|
+
if (etag) {
|
|
1268
|
+
headers["If-None-Match"] = etag;
|
|
1269
|
+
}
|
|
1270
|
+
const response = await fetch(latestReleaseApiUrl(), {
|
|
1271
|
+
headers,
|
|
1272
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
1273
|
+
});
|
|
1274
|
+
if (response.status === 304) {
|
|
1275
|
+
return { status: 304, etag: etag ?? null, release: null };
|
|
1276
|
+
}
|
|
1277
|
+
if (!response.ok) {
|
|
1278
|
+
return { status: response.status, etag: null, release: null };
|
|
1279
|
+
}
|
|
1280
|
+
return {
|
|
1281
|
+
status: response.status,
|
|
1282
|
+
etag: response.headers.get("etag"),
|
|
1283
|
+
release: parseLatestRelease(await response.json())
|
|
1284
|
+
};
|
|
1285
|
+
} catch {
|
|
1286
|
+
return null;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
async function maybeNotifyUpdate(currentVersion, kind) {
|
|
1290
|
+
if (isUpdateCheckDisabled(process.env, Boolean(process.stderr.isTTY))) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const state = await readStateSafe();
|
|
1294
|
+
if (state.latestVersion && isOutdated(currentVersion, state.latestVersion)) {
|
|
1295
|
+
process.stderr.write(formatUpdateNotice(currentVersion, state.latestVersion, kind));
|
|
1296
|
+
}
|
|
1297
|
+
if (shouldRefresh(state.lastCheck, Date.now())) {
|
|
1298
|
+
void refreshState(currentVersion, state.etag ?? null).catch(() => {
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
async function refreshState(currentVersion, etag) {
|
|
1303
|
+
const result = await fetchLatest(currentVersion, etag);
|
|
1304
|
+
if (!result) {
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
if (result.status === 304) {
|
|
1308
|
+
const prev = await readStateSafe();
|
|
1309
|
+
await writeStateSafe({ ...prev, lastCheck: Date.now() });
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
if (result.release) {
|
|
1313
|
+
await writeStateSafe({
|
|
1314
|
+
lastCheck: Date.now(),
|
|
1315
|
+
latestVersion: result.release.version,
|
|
1316
|
+
etag: result.etag
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
function detectInstallKind() {
|
|
1321
|
+
return IS_STANDALONE_BINARY ? "binary" : "npm";
|
|
1322
|
+
}
|
|
1323
|
+
function detectMusl() {
|
|
1324
|
+
if (process.platform !== "linux") {
|
|
1325
|
+
return false;
|
|
1326
|
+
}
|
|
1327
|
+
try {
|
|
1328
|
+
const report = process.report?.getReport?.();
|
|
1329
|
+
if (report?.header && "glibcVersionRuntime" in report.header) {
|
|
1330
|
+
return !report.header.glibcVersionRuntime;
|
|
1331
|
+
}
|
|
1332
|
+
} catch {
|
|
1333
|
+
}
|
|
1334
|
+
try {
|
|
1335
|
+
if (existsSync("/etc/alpine-release")) {
|
|
1336
|
+
return true;
|
|
1337
|
+
}
|
|
1338
|
+
const ldd = execFileSync2("ldd", ["--version"], {
|
|
1339
|
+
encoding: "utf8",
|
|
1340
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1341
|
+
timeout: 2e3
|
|
1342
|
+
});
|
|
1343
|
+
return /musl/i.test(ldd);
|
|
1344
|
+
} catch {
|
|
1345
|
+
return false;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
async function downloadToFile(url, dest, version) {
|
|
1349
|
+
const response = await fetch(url, {
|
|
1350
|
+
headers: { "User-Agent": userAgent(version) },
|
|
1351
|
+
redirect: "follow",
|
|
1352
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS * 10)
|
|
1353
|
+
});
|
|
1354
|
+
if (!response.ok || !response.body) {
|
|
1355
|
+
throw new Error(`Download failed (${response.status}) for ${url}`);
|
|
1356
|
+
}
|
|
1357
|
+
await Bun.write(dest, response);
|
|
1358
|
+
}
|
|
1359
|
+
async function sha256File(path) {
|
|
1360
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
1361
|
+
hasher.update(await Bun.file(path).arrayBuffer());
|
|
1362
|
+
return hasher.digest("hex");
|
|
1363
|
+
}
|
|
1364
|
+
async function verifyChecksum(release, assetName, file, version) {
|
|
1365
|
+
const sums = release.assets.find((asset) => asset.name === SHA256SUMS);
|
|
1366
|
+
if (!sums) {
|
|
1367
|
+
throw new Error(
|
|
1368
|
+
`Release ${release.tag} has no ${SHA256SUMS}; refusing to install an unverified binary.`
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
const response = await fetch(sums.url, {
|
|
1372
|
+
headers: { "User-Agent": userAgent(version) },
|
|
1373
|
+
redirect: "follow",
|
|
1374
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
1375
|
+
});
|
|
1376
|
+
if (!response.ok) {
|
|
1377
|
+
throw new Error(`Could not download ${SHA256SUMS} (${response.status}).`);
|
|
1378
|
+
}
|
|
1379
|
+
const expected = checksumFor(await response.text(), assetName);
|
|
1380
|
+
if (!expected) {
|
|
1381
|
+
throw new Error(`No checksum for ${assetName} in ${SHA256SUMS}.`);
|
|
1382
|
+
}
|
|
1383
|
+
const actual = await sha256File(file);
|
|
1384
|
+
if (actual.toLowerCase() !== expected) {
|
|
1385
|
+
throw new Error(`Checksum mismatch for ${assetName}: expected ${expected}, got ${actual}.`);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
function swapBinary(tmpFile, exePath) {
|
|
1389
|
+
if (process.platform === "win32") {
|
|
1390
|
+
const oldExe = `${exePath}.old`;
|
|
1391
|
+
try {
|
|
1392
|
+
rmSync(oldExe, { force: true });
|
|
1393
|
+
} catch {
|
|
1394
|
+
}
|
|
1395
|
+
renameSync(exePath, oldExe);
|
|
1396
|
+
const restore = () => {
|
|
1397
|
+
try {
|
|
1398
|
+
renameSync(oldExe, exePath);
|
|
1399
|
+
} catch {
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
try {
|
|
1403
|
+
renameSync(tmpFile, exePath);
|
|
1404
|
+
} catch (error) {
|
|
1405
|
+
if (error.code === "EXDEV") {
|
|
1406
|
+
try {
|
|
1407
|
+
copyFileSync(tmpFile, exePath);
|
|
1408
|
+
} catch (copyError) {
|
|
1409
|
+
restore();
|
|
1410
|
+
throw copyError;
|
|
1411
|
+
}
|
|
1412
|
+
} else {
|
|
1413
|
+
restore();
|
|
1414
|
+
throw error;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
try {
|
|
1420
|
+
renameSync(tmpFile, exePath);
|
|
1421
|
+
} catch (error) {
|
|
1422
|
+
const code = error.code;
|
|
1423
|
+
if (code === "EXDEV") {
|
|
1424
|
+
copyFileSync(tmpFile, exePath);
|
|
1425
|
+
chmodSync(exePath, 493);
|
|
1426
|
+
} else if (code === "EACCES" || code === "EPERM") {
|
|
1427
|
+
throw new Error(
|
|
1428
|
+
`No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory.`
|
|
1429
|
+
);
|
|
1430
|
+
} else {
|
|
1431
|
+
throw error;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
function cleanupOldBinary() {
|
|
1436
|
+
if (!shouldCleanupOldBinary(process.platform, IS_STANDALONE_BINARY)) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
try {
|
|
1440
|
+
rmSync(`${realpathSync(process.execPath)}.old`, { force: true });
|
|
1441
|
+
} catch {
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
async function runUpdate(currentVersion) {
|
|
1445
|
+
cleanupOldBinary();
|
|
1446
|
+
const kind = detectInstallKind();
|
|
1447
|
+
if (kind !== "binary") {
|
|
1448
|
+
console.log(`hoopilot ${currentVersion} was installed via npm.`);
|
|
1449
|
+
console.log(`Update with: ${upgradeCommandFor("npm")}`);
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
console.log(`hoopilot ${currentVersion} \u2014 checking for updates...`);
|
|
1453
|
+
const result = await fetchLatest(currentVersion);
|
|
1454
|
+
const release = result?.release ?? null;
|
|
1455
|
+
if (!release) {
|
|
1456
|
+
throw new Error("Could not reach GitHub to check for the latest release.");
|
|
1457
|
+
}
|
|
1458
|
+
if (!isOutdated(currentVersion, release.version)) {
|
|
1459
|
+
console.log(`Already up to date (latest: ${release.version}).`);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
const suffix = BAKED_TARGET ?? assetSuffixFor(process.platform, process.arch, detectMusl());
|
|
1463
|
+
const assetName = assetNameFor(suffix);
|
|
1464
|
+
const asset = release.assets.find((entry) => entry.name === assetName);
|
|
1465
|
+
if (!asset) {
|
|
1466
|
+
const available = release.assets.map((entry) => entry.name).join(", ") || "none";
|
|
1467
|
+
throw new Error(`Release ${release.tag} has no asset "${assetName}". Available: ${available}.`);
|
|
1468
|
+
}
|
|
1469
|
+
console.log(`Updating ${currentVersion} \u2192 ${release.version} (${assetName})...`);
|
|
1470
|
+
const exePath = realpathSync(process.execPath);
|
|
1471
|
+
const tmpFile = join(dirname(exePath), `.hoopilot-update-${process.pid}.tmp`);
|
|
1472
|
+
try {
|
|
1473
|
+
await downloadToFile(asset.url, tmpFile, currentVersion);
|
|
1474
|
+
await verifyChecksum(release, assetName, tmpFile, currentVersion);
|
|
1475
|
+
if (process.platform !== "win32") {
|
|
1476
|
+
chmodSync(tmpFile, 493);
|
|
1477
|
+
}
|
|
1478
|
+
swapBinary(tmpFile, exePath);
|
|
1479
|
+
} catch (error) {
|
|
1480
|
+
const code = error.code;
|
|
1481
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
1482
|
+
throw new Error(
|
|
1483
|
+
`No permission to update ${exePath}. Re-run with sudo, or reinstall to a writable directory (e.g. set HOOPILOT_INSTALL_DIR).`
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
throw error;
|
|
1487
|
+
} finally {
|
|
1488
|
+
try {
|
|
1489
|
+
rmSync(tmpFile, { force: true });
|
|
1490
|
+
} catch {
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
console.log(`Updated hoopilot to ${release.version}.`);
|
|
1494
|
+
if (process.platform === "win32") {
|
|
1495
|
+
console.log("Restart hoopilot to run the new version.");
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1013
1499
|
// src/cli.ts
|
|
1014
1500
|
async function main(argv = Bun.argv.slice(2)) {
|
|
1501
|
+
cleanupOldBinary();
|
|
1502
|
+
const command = argv[0];
|
|
1503
|
+
if (command === "update" || command === "upgrade") {
|
|
1504
|
+
await runUpdate(await getVersion());
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1015
1507
|
const args = parseArgs(argv);
|
|
1016
1508
|
if (args.help) {
|
|
1017
|
-
console.log(helpText(await
|
|
1509
|
+
console.log(helpText(await getVersion()));
|
|
1018
1510
|
return;
|
|
1019
1511
|
}
|
|
1020
1512
|
if (args.version) {
|
|
1021
|
-
console.log(await
|
|
1513
|
+
console.log(await getVersion());
|
|
1022
1514
|
return;
|
|
1023
1515
|
}
|
|
1024
1516
|
const started = startHoopilotServer(args);
|
|
1025
1517
|
console.log(`hoopilot listening on ${started.url}`);
|
|
1026
1518
|
console.log(`OpenAI base URL: ${started.url}/v1`);
|
|
1027
1519
|
console.log("Use Ctrl+C to stop.");
|
|
1520
|
+
if (!args.noUpdateCheck) {
|
|
1521
|
+
void maybeNotifyUpdate(await getVersion(), IS_STANDALONE_BINARY ? "binary" : "npm");
|
|
1522
|
+
}
|
|
1028
1523
|
}
|
|
1029
1524
|
function parseArgs(argv) {
|
|
1030
1525
|
const args = {};
|
|
@@ -1053,6 +1548,10 @@ function parseArgs(argv) {
|
|
|
1053
1548
|
args.githubTokenCommand = false;
|
|
1054
1549
|
continue;
|
|
1055
1550
|
}
|
|
1551
|
+
if (arg === "--no-update-check") {
|
|
1552
|
+
args.noUpdateCheck = true;
|
|
1553
|
+
continue;
|
|
1554
|
+
}
|
|
1056
1555
|
const [name, inlineValue] = arg.split("=", 2);
|
|
1057
1556
|
const value = inlineValue ?? rest.shift();
|
|
1058
1557
|
if (!value) {
|
|
@@ -1099,14 +1598,6 @@ function parseAuthMode(value) {
|
|
|
1099
1598
|
}
|
|
1100
1599
|
throw new Error(`Invalid auth mode: ${value}.`);
|
|
1101
1600
|
}
|
|
1102
|
-
async function packageVersion() {
|
|
1103
|
-
try {
|
|
1104
|
-
const manifest = await Bun.file(new URL("../package.json", import.meta.url)).json();
|
|
1105
|
-
return typeof manifest.version === "string" ? manifest.version : "0.0.0";
|
|
1106
|
-
} catch {
|
|
1107
|
-
return "0.0.0";
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
1601
|
function helpText(version) {
|
|
1111
1602
|
return `hoopilot ${version}
|
|
1112
1603
|
|
|
@@ -1114,8 +1605,13 @@ OpenAI-compatible proxy for GitHub Copilot.
|
|
|
1114
1605
|
|
|
1115
1606
|
Usage:
|
|
1116
1607
|
hoopilot [serve] [options]
|
|
1608
|
+
hoopilot update
|
|
1117
1609
|
npx @openhoo/hoopilot [options]
|
|
1118
1610
|
|
|
1611
|
+
Commands:
|
|
1612
|
+
serve Start the proxy server (default)
|
|
1613
|
+
update, upgrade Update hoopilot to the latest release
|
|
1614
|
+
|
|
1119
1615
|
Options:
|
|
1120
1616
|
-p, --port <port> Port to listen on. Default: 4141
|
|
1121
1617
|
--host <host> Host to listen on. Default: 127.0.0.1
|
|
@@ -1126,6 +1622,7 @@ Options:
|
|
|
1126
1622
|
--copilot-token <token> Short-lived Copilot API bearer token
|
|
1127
1623
|
--copilot-api-base-url <url> Copilot API base URL override
|
|
1128
1624
|
--no-gh Do not try gh auth token
|
|
1625
|
+
--no-update-check Do not check GitHub for a newer release
|
|
1129
1626
|
--allow-unauthenticated Allow non-loopback bind without --api-key
|
|
1130
1627
|
-h, --help Show help
|
|
1131
1628
|
-v, --version Show version
|
|
@@ -1135,6 +1632,7 @@ Environment:
|
|
|
1135
1632
|
COPILOT_GITHUB_TOKEN
|
|
1136
1633
|
COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN
|
|
1137
1634
|
COPILOT_API_BASE_URL
|
|
1635
|
+
HOOPILOT_NO_UPDATE_CHECK Set to disable update checks (also NO_UPDATE_NOTIFIER)
|
|
1138
1636
|
`;
|
|
1139
1637
|
}
|
|
1140
1638
|
if (import.meta.main) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth.ts","../src/copilot.ts","../src/openai.ts","../src/server.ts","../src/cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport type { CopilotAccess, CopilotAuthOptions, FetchLike, Logger } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.individual.githubcopilot.com\";\nconst DEFAULT_TOKEN_EXCHANGE_URL = \"https://api.github.com/copilot_internal/v2/token\";\nconst REFRESH_SKEW_MS = 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nclass CopilotTokenExchangeHttpError extends CopilotAuthError {}\n\nexport class CopilotAuth {\n readonly #authMode: NonNullable<CopilotAuthOptions[\"authMode\"]>;\n readonly #copilotApiBaseUrl: string;\n readonly #copilotToken?: string;\n readonly #env: NodeJS.ProcessEnv;\n readonly #fetch: FetchLike;\n readonly #githubToken?: string;\n readonly #githubTokenCommand: string | false;\n readonly #logger?: Logger;\n readonly #tokenExchangeUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authMode = options.authMode ?? \"auto\";\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n this.#copilotToken = options.copilotToken;\n this.#env = options.env ?? process.env;\n this.#fetch = options.fetch ?? fetch;\n this.#githubToken = options.githubToken;\n this.#githubTokenCommand = options.githubTokenCommand ?? \"gh auth token\";\n this.#logger = options.logger;\n this.#tokenExchangeUrl =\n options.tokenExchangeUrl ??\n options.env?.COPILOT_TOKEN_EXCHANGE_URL ??\n DEFAULT_TOKEN_EXCHANGE_URL;\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const directCopilotToken = this.#resolveDirectCopilotToken();\n if (directCopilotToken) {\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"copilot-token\",\n token: directCopilotToken,\n });\n }\n\n if (this.#authMode === \"copilot-token\") {\n throw new CopilotAuthError(\"COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.\");\n }\n\n const githubToken = this.#resolveGithubToken();\n if (!githubToken) {\n throw new CopilotAuthError(\n \"No Copilot credential found. Set COPILOT_API_TOKEN, set COPILOT_GITHUB_TOKEN from gh auth token, or sign in with gh auth login.\",\n );\n }\n\n if (isPersonalAccessToken(githubToken)) {\n throw new CopilotAuthError(\n \"GitHub personal access tokens are not supported for Copilot authentication. Use gh auth login or COPILOT_API_TOKEN.\",\n );\n }\n\n try {\n return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));\n } catch (error) {\n if (!(error instanceof CopilotTokenExchangeHttpError)) {\n throw error;\n }\n this.#logger?.warn(\n `Copilot token exchange failed; falling back to GitHub CLI token mode: ${errorMessage(\n error,\n )}`,\n );\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"direct-github-token\",\n token: githubToken,\n });\n }\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n\n async #exchangeGithubToken(githubToken: string): Promise<CopilotAccess> {\n const response = await this.#fetch(this.#tokenExchangeUrl, {\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": \"hoopilot/0.1.0\",\n \"editor-version\": \"Hoopilot/0.1.0\",\n \"user-agent\": \"hoopilot/0.1.0\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new CopilotTokenExchangeHttpError(\n `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const body = asRecord(await response.json());\n const token = getString(body, \"token\");\n if (!token) {\n throw new CopilotAuthError(\"GitHub Copilot token exchange response did not include a token.\");\n }\n\n return {\n apiBaseUrl: endpointFromResponse(body) ?? this.#copilotApiBaseUrl,\n expiresAtMs: expiresAtFromResponse(body),\n source: \"github-token\",\n token,\n };\n }\n\n #resolveDirectCopilotToken(): string | undefined {\n return firstNonEmpty(\n this.#copilotToken,\n this.#env.COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_TOKEN,\n );\n }\n\n #resolveGithubToken(): string | undefined {\n return firstNonEmpty(\n this.#githubToken,\n this.#env.COPILOT_GITHUB_TOKEN,\n this.#env.GITHUB_COPILOT_GITHUB_TOKEN,\n this.#readGithubTokenCommand(),\n );\n }\n\n #readGithubTokenCommand(): string | undefined {\n if (this.#githubTokenCommand === false) {\n return undefined;\n }\n const parts = splitCommand(this.#githubTokenCommand);\n const [command, ...args] = parts;\n if (!command) {\n return undefined;\n }\n try {\n const output = execFileSync(command, args, {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5_000,\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n }\n}\n\nexport function splitCommand(command: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | undefined;\n let escaping = false;\n\n for (const character of command.trim()) {\n if (escaping) {\n current += character;\n escaping = false;\n continue;\n }\n if (character === \"\\\\\") {\n escaping = true;\n continue;\n }\n if (quote) {\n if (character === quote) {\n quote = undefined;\n } else {\n current += character;\n }\n continue;\n }\n if (character === \"'\" || character === '\"') {\n quote = character;\n continue;\n }\n if (/\\s/.test(character)) {\n if (current) {\n parts.push(current);\n current = \"\";\n }\n continue;\n }\n current += character;\n }\n\n if (current) {\n parts.push(current);\n }\n\n return parts;\n}\n\nfunction endpointFromResponse(body: Record<string, unknown>): string | undefined {\n const endpoints = asRecord(body.endpoints);\n const apiUrl = getString(endpoints, \"api\") ?? getString(endpoints, \"proxy\");\n return apiUrl ? trimTrailingSlash(apiUrl) : undefined;\n}\n\nfunction expiresAtFromResponse(body: Record<string, unknown>): number {\n const expiresAt = body.expires_at;\n if (typeof expiresAt === \"number\") {\n return expiresAt < 10_000_000_000 ? expiresAt * 1000 : expiresAt;\n }\n if (typeof expiresAt === \"string\") {\n const asNumber = Number(expiresAt);\n if (Number.isFinite(asNumber)) {\n return asNumber < 10_000_000_000 ? asNumber * 1000 : asNumber;\n }\n const parsed = Date.parse(expiresAt);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n const refreshIn = body.refresh_in;\n if (typeof refreshIn === \"number\" && Number.isFinite(refreshIn)) {\n return Date.now() + refreshIn * 1000;\n }\n return Date.now() + 10 * 60_000;\n}\n\nfunction firstNonEmpty(...values: Array<string | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = value?.trim();\n if (trimmed) {\n return trimmed;\n }\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction getString(record: Record<string, unknown>, key: string): string | undefined {\n const value = record[key];\n return typeof value === \"string\" && value ? value : undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction isPersonalAccessToken(token: string): boolean {\n return token.startsWith(\"github_pat_\") || token.startsWith(\"ghp_\");\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { CopilotAuth } from \"./auth\";\nimport type { CopilotAuthOptions, FetchLike, JsonObject } from \"./types\";\n\nexport class CopilotClient {\n readonly #auth: CopilotAuth;\n readonly #fetch: FetchLike;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#auth = new CopilotAuth(options);\n this.#fetch = options.fetch ?? fetch;\n }\n\n async chatCompletions(body: JsonObject, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body: JSON.stringify(body),\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async forwardChatCompletions(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import type { JsonObject } from \"./types\";\n\nexport const DEFAULT_MODEL = \"gpt-4.1\";\n\ninterface ResponseStreamOptions {\n model: string;\n responseId?: string;\n}\n\ninterface AccumulatedToolCall {\n arguments: string;\n id: string;\n index: number;\n name: string;\n}\n\nexport function responsesRequestToChatCompletion(request: JsonObject): JsonObject {\n const messages: unknown[] = [];\n const instructions = contentToText(request.instructions);\n if (instructions) {\n messages.push({ content: instructions, role: \"system\" });\n }\n\n for (const message of inputToMessages(request.input)) {\n messages.push(message);\n }\n\n return removeUndefined({\n frequency_penalty: request.frequency_penalty,\n max_tokens: request.max_output_tokens ?? request.max_tokens,\n messages,\n metadata: request.metadata,\n model: contentToText(request.model) || DEFAULT_MODEL,\n presence_penalty: request.presence_penalty,\n reasoning_effort: asRecord(request.reasoning).effort,\n response_format: asRecord(request.text).format,\n seed: request.seed,\n stream: request.stream === true,\n temperature: request.temperature,\n tool_choice: chatToolChoice(request.tool_choice),\n tools: chatTools(request.tools),\n top_p: request.top_p,\n });\n}\n\nexport function completionsRequestToChatCompletion(request: JsonObject): JsonObject {\n return removeUndefined({\n max_tokens: request.max_tokens,\n messages: [{ content: promptToText(request.prompt), role: \"user\" }],\n model: contentToText(request.model) || DEFAULT_MODEL,\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type { HoopilotServerOptions, JsonObject, StartedHoopilotServer } from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders() });\n }\n\n if (!isAuthorized(request, apiKey)) {\n return jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\");\n }\n\n try {\n if (request.method === \"GET\" && (url.pathname === \"/\" || url.pathname === \"/healthz\")) {\n return jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n });\n }\n if (request.method === \"GET\" && url.pathname === \"/v1/models\") {\n return await handleModels(client, request.signal);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n return await handleChatCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/completions\") {\n return await handleCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/responses\") {\n return await handleResponses(client, request);\n }\n return jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`);\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n return jsonError(401, \"copilot_auth_error\", error.message);\n }\n return jsonError(500, \"internal_error\", errorMessage(error));\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(client: CopilotClient, signal: AbortSignal): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream);\n }\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(client: CopilotClient, request: Request): Promise<Response> {\n const body = await readJson(request);\n const chatRequest = responsesRequestToChatCompletion(body);\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream);\n }\n\n if (body.stream === true && upstream.body) {\n return new Response(\n responsesStreamFromChatStream(upstream.body, {\n model: typeof chatRequest.model === \"string\" ? chatRequest.model : \"gpt-4.1\",\n }),\n {\n headers: {\n ...corsHeaders(),\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"content-type\": \"text/event-stream; charset=utf-8\",\n },\n },\n );\n }\n\n return jsonResponse(chatCompletionToResponse(await upstream.json()));\n}\n\nasync function proxyError(upstream: Response): Promise<Response> {\n const text = await upstream.text();\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(\"Request body must be valid JSON.\");\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","#!/usr/bin/env bun\n\nimport { startHoopilotServer } from \"./server\";\nimport type { AuthMode, HoopilotServerOptions } from \"./types\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n version?: boolean;\n}\n\nexport async function main(argv = Bun.argv.slice(2)): Promise<void> {\n const args = parseArgs(argv);\n if (args.help) {\n console.log(helpText(await packageVersion()));\n return;\n }\n if (args.version) {\n console.log(await packageVersion());\n return;\n }\n\n const started = startHoopilotServer(args);\n console.log(`hoopilot listening on ${started.url}`);\n console.log(`OpenAI base URL: ${started.url}/v1`);\n console.log(\"Use Ctrl+C to stop.\");\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args: ParsedArgs = {};\n const rest = [...argv];\n if (rest[0] === \"serve\") {\n rest.shift();\n }\n\n while (rest.length > 0) {\n const arg = rest.shift();\n if (!arg) {\n continue;\n }\n if (arg === \"--help\" || arg === \"-h\") {\n args.help = true;\n continue;\n }\n if (arg === \"--version\" || arg === \"-v\") {\n args.version = true;\n continue;\n }\n if (arg === \"--allow-unauthenticated\") {\n args.allowUnauthenticated = true;\n continue;\n }\n if (arg === \"--no-gh\") {\n args.githubTokenCommand = false;\n continue;\n }\n\n const [name, inlineValue] = arg.split(\"=\", 2);\n const value = inlineValue ?? rest.shift();\n if (!value) {\n throw new Error(`Missing value for ${arg}.`);\n }\n\n switch (name) {\n case \"--api-key\":\n args.apiKey = value;\n break;\n case \"--auth-mode\":\n args.authMode = parseAuthMode(value);\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--copilot-token\":\n args.copilotToken = value;\n break;\n case \"--github-token\":\n args.githubToken = value;\n break;\n case \"--github-token-command\":\n args.githubTokenCommand = value;\n break;\n case \"--host\":\n args.host = value;\n break;\n case \"--port\":\n case \"-p\":\n args.port = Number(value);\n if (!Number.isInteger(args.port) || args.port <= 0) {\n throw new Error(`Invalid port: ${value}.`);\n }\n break;\n default:\n throw new Error(`Unknown option: ${name}.`);\n }\n }\n\n return args;\n}\n\nfunction parseAuthMode(value: string): AuthMode {\n if (value === \"auto\" || value === \"copilot-token\") {\n return value;\n }\n throw new Error(`Invalid auth mode: ${value}.`);\n}\n\nasync function packageVersion(): Promise<string> {\n try {\n const manifest = await Bun.file(new URL(\"../package.json\", import.meta.url)).json();\n return typeof manifest.version === \"string\" ? manifest.version : \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction helpText(version: string): string {\n return `hoopilot ${version}\n\nOpenAI-compatible proxy for GitHub Copilot.\n\nUsage:\n hoopilot [serve] [options]\n npx @openhoo/hoopilot [options]\n\nOptions:\n -p, --port <port> Port to listen on. Default: 4141\n --host <host> Host to listen on. Default: 127.0.0.1\n --api-key <key> Require clients to send Authorization: Bearer <key>\n --auth-mode <mode> auto, copilot-token\n --github-token <token> GitHub CLI OAuth token for a Copilot account. PATs are rejected.\n --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token\n --copilot-token <token> Short-lived Copilot API bearer token\n --copilot-api-base-url <url> Copilot API base URL override\n --no-gh Do not try gh auth token\n --allow-unauthenticated Allow non-loopback bind without --api-key\n -h, --help Show help\n -v, --version Show version\n\nEnvironment:\n HOOPILOT_API_KEY\n COPILOT_GITHUB_TOKEN\n COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN\n COPILOT_API_BASE_URL\n`;\n}\n\nif (import.meta.main) {\n main().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["asRecord","errorMessage"]}
|
|
1
|
+
{"version":3,"sources":["../src/auth.ts","../src/copilot.ts","../src/openai.ts","../src/server.ts","../src/update.ts","../src/update-core.ts","../src/version.ts","../src/cli.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport type { CopilotAccess, CopilotAuthOptions, FetchLike, Logger } from \"./types\";\n\nconst DEFAULT_COPILOT_API_BASE_URL = \"https://api.individual.githubcopilot.com\";\nconst DEFAULT_TOKEN_EXCHANGE_URL = \"https://api.github.com/copilot_internal/v2/token\";\nconst REFRESH_SKEW_MS = 60_000;\n\nexport class CopilotAuthError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CopilotAuthError\";\n }\n}\n\nclass CopilotTokenExchangeHttpError extends CopilotAuthError {}\n\nexport class CopilotAuth {\n readonly #authMode: NonNullable<CopilotAuthOptions[\"authMode\"]>;\n readonly #copilotApiBaseUrl: string;\n readonly #copilotToken?: string;\n readonly #env: NodeJS.ProcessEnv;\n readonly #fetch: FetchLike;\n readonly #githubToken?: string;\n readonly #githubTokenCommand: string | false;\n readonly #logger?: Logger;\n readonly #tokenExchangeUrl: string;\n #cachedAccess?: CopilotAccess;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#authMode = options.authMode ?? \"auto\";\n this.#copilotApiBaseUrl = trimTrailingSlash(\n options.copilotApiBaseUrl ??\n options.env?.COPILOT_API_BASE_URL ??\n DEFAULT_COPILOT_API_BASE_URL,\n );\n this.#copilotToken = options.copilotToken;\n this.#env = options.env ?? process.env;\n this.#fetch = options.fetch ?? fetch;\n this.#githubToken = options.githubToken;\n this.#githubTokenCommand = options.githubTokenCommand ?? \"gh auth token\";\n this.#logger = options.logger;\n this.#tokenExchangeUrl =\n options.tokenExchangeUrl ??\n options.env?.COPILOT_TOKEN_EXCHANGE_URL ??\n DEFAULT_TOKEN_EXCHANGE_URL;\n }\n\n async getAccess(): Promise<CopilotAccess> {\n if (this.#cachedAccess && this.#cachedAccess.expiresAtMs - REFRESH_SKEW_MS > Date.now()) {\n return this.#cachedAccess;\n }\n\n const directCopilotToken = this.#resolveDirectCopilotToken();\n if (directCopilotToken) {\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"copilot-token\",\n token: directCopilotToken,\n });\n }\n\n if (this.#authMode === \"copilot-token\") {\n throw new CopilotAuthError(\"COPILOT_API_TOKEN or GITHUB_COPILOT_API_TOKEN is required.\");\n }\n\n const githubToken = this.#resolveGithubToken();\n if (!githubToken) {\n throw new CopilotAuthError(\n \"No Copilot credential found. Set COPILOT_API_TOKEN, set COPILOT_GITHUB_TOKEN from gh auth token, or sign in with gh auth login.\",\n );\n }\n\n if (isPersonalAccessToken(githubToken)) {\n throw new CopilotAuthError(\n \"GitHub personal access tokens are not supported for Copilot authentication. Use gh auth login or COPILOT_API_TOKEN.\",\n );\n }\n\n try {\n return this.#cacheAccess(await this.#exchangeGithubToken(githubToken));\n } catch (error) {\n if (!(error instanceof CopilotTokenExchangeHttpError)) {\n throw error;\n }\n this.#logger?.warn(\n `Copilot token exchange failed; falling back to GitHub CLI token mode: ${errorMessage(\n error,\n )}`,\n );\n return this.#cacheAccess({\n apiBaseUrl: this.#copilotApiBaseUrl,\n expiresAtMs: Date.now() + 10 * 60_000,\n source: \"direct-github-token\",\n token: githubToken,\n });\n }\n }\n\n #cacheAccess(access: CopilotAccess): CopilotAccess {\n this.#cachedAccess = access;\n return access;\n }\n\n async #exchangeGithubToken(githubToken: string): Promise<CopilotAccess> {\n const response = await this.#fetch(this.#tokenExchangeUrl, {\n headers: {\n accept: \"application/vnd.github+json\",\n authorization: `token ${githubToken}`,\n \"editor-plugin-version\": \"hoopilot/0.1.0\",\n \"editor-version\": \"Hoopilot/0.1.0\",\n \"user-agent\": \"hoopilot/0.1.0\",\n },\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new CopilotTokenExchangeHttpError(\n `GitHub Copilot token exchange failed with ${response.status}: ${await safeResponseText(\n response,\n )}`,\n );\n }\n\n const body = asRecord(await response.json());\n const token = getString(body, \"token\");\n if (!token) {\n throw new CopilotAuthError(\"GitHub Copilot token exchange response did not include a token.\");\n }\n\n return {\n apiBaseUrl: endpointFromResponse(body) ?? this.#copilotApiBaseUrl,\n expiresAtMs: expiresAtFromResponse(body),\n source: \"github-token\",\n token,\n };\n }\n\n #resolveDirectCopilotToken(): string | undefined {\n return firstNonEmpty(\n this.#copilotToken,\n this.#env.COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_API_TOKEN,\n this.#env.GITHUB_COPILOT_TOKEN,\n );\n }\n\n #resolveGithubToken(): string | undefined {\n return firstNonEmpty(\n this.#githubToken,\n this.#env.COPILOT_GITHUB_TOKEN,\n this.#env.GITHUB_COPILOT_GITHUB_TOKEN,\n this.#readGithubTokenCommand(),\n );\n }\n\n #readGithubTokenCommand(): string | undefined {\n if (this.#githubTokenCommand === false) {\n return undefined;\n }\n const parts = splitCommand(this.#githubTokenCommand);\n const [command, ...args] = parts;\n if (!command) {\n return undefined;\n }\n try {\n const output = execFileSync(command, args, {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5_000,\n });\n return output.trim() || undefined;\n } catch {\n return undefined;\n }\n }\n}\n\nexport function splitCommand(command: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | undefined;\n let escaping = false;\n\n for (const character of command.trim()) {\n if (escaping) {\n current += character;\n escaping = false;\n continue;\n }\n if (character === \"\\\\\") {\n escaping = true;\n continue;\n }\n if (quote) {\n if (character === quote) {\n quote = undefined;\n } else {\n current += character;\n }\n continue;\n }\n if (character === \"'\" || character === '\"') {\n quote = character;\n continue;\n }\n if (/\\s/.test(character)) {\n if (current) {\n parts.push(current);\n current = \"\";\n }\n continue;\n }\n current += character;\n }\n\n if (current) {\n parts.push(current);\n }\n\n return parts;\n}\n\nfunction endpointFromResponse(body: Record<string, unknown>): string | undefined {\n const endpoints = asRecord(body.endpoints);\n const apiUrl = getString(endpoints, \"api\") ?? getString(endpoints, \"proxy\");\n return apiUrl ? trimTrailingSlash(apiUrl) : undefined;\n}\n\nfunction expiresAtFromResponse(body: Record<string, unknown>): number {\n const expiresAt = body.expires_at;\n if (typeof expiresAt === \"number\") {\n return expiresAt < 10_000_000_000 ? expiresAt * 1000 : expiresAt;\n }\n if (typeof expiresAt === \"string\") {\n const asNumber = Number(expiresAt);\n if (Number.isFinite(asNumber)) {\n return asNumber < 10_000_000_000 ? asNumber * 1000 : asNumber;\n }\n const parsed = Date.parse(expiresAt);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n const refreshIn = body.refresh_in;\n if (typeof refreshIn === \"number\" && Number.isFinite(refreshIn)) {\n return Date.now() + refreshIn * 1000;\n }\n return Date.now() + 10 * 60_000;\n}\n\nfunction firstNonEmpty(...values: Array<string | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = value?.trim();\n if (trimmed) {\n return trimmed;\n }\n }\n return undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction getString(record: Record<string, unknown>, key: string): string | undefined {\n const value = record[key];\n return typeof value === \"string\" && value ? value : undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nasync function safeResponseText(response: Response): Promise<string> {\n const text = await response.text();\n return text.slice(0, 500);\n}\n\nfunction isPersonalAccessToken(token: string): boolean {\n return token.startsWith(\"github_pat_\") || token.startsWith(\"ghp_\");\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { CopilotAuth } from \"./auth\";\nimport type { CopilotAuthOptions, FetchLike, JsonObject } from \"./types\";\n\nexport class CopilotClient {\n readonly #auth: CopilotAuth;\n readonly #fetch: FetchLike;\n\n constructor(options: CopilotAuthOptions = {}) {\n this.#auth = new CopilotAuth(options);\n this.#fetch = options.fetch ?? fetch;\n }\n\n async chatCompletions(body: JsonObject, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body: JSON.stringify(body),\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async forwardChatCompletions(body: string, signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/chat/completions\", {\n body,\n headers: {\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n signal,\n });\n }\n\n async models(signal?: AbortSignal): Promise<Response> {\n return this.fetchCopilot(\"/models\", {\n headers: {\n accept: \"application/json\",\n },\n method: \"GET\",\n signal,\n });\n }\n\n async fetchCopilot(path: string, init: RequestInit): Promise<Response> {\n const access = await this.#auth.getAccess();\n const headers = new Headers(init.headers);\n headers.set(\"accept\", headers.get(\"accept\") ?? \"application/json\");\n headers.set(\"authorization\", `Bearer ${access.token}`);\n headers.set(\"copilot-integration-id\", \"vscode-chat\");\n headers.set(\"editor-plugin-version\", \"hoopilot/0.1.0\");\n headers.set(\"editor-version\", \"Hoopilot/0.1.0\");\n headers.set(\"openai-intent\", \"conversation-panel\");\n headers.set(\"user-agent\", \"hoopilot/0.1.0\");\n\n return this.#fetch(`${access.apiBaseUrl}${path}`, {\n ...init,\n headers,\n });\n }\n}\n","import type { JsonObject } from \"./types\";\n\nexport const DEFAULT_MODEL = \"gpt-4.1\";\n\ninterface ResponseStreamOptions {\n model: string;\n responseId?: string;\n}\n\ninterface AccumulatedToolCall {\n arguments: string;\n id: string;\n index: number;\n name: string;\n}\n\nexport function responsesRequestToChatCompletion(request: JsonObject): JsonObject {\n const messages: unknown[] = [];\n const instructions = contentToText(request.instructions);\n if (instructions) {\n messages.push({ content: instructions, role: \"system\" });\n }\n\n for (const message of inputToMessages(request.input)) {\n messages.push(message);\n }\n\n return removeUndefined({\n frequency_penalty: request.frequency_penalty,\n max_tokens: request.max_output_tokens ?? request.max_tokens,\n messages,\n metadata: request.metadata,\n model: contentToText(request.model) || DEFAULT_MODEL,\n presence_penalty: request.presence_penalty,\n reasoning_effort: asRecord(request.reasoning).effort,\n response_format: asRecord(request.text).format,\n seed: request.seed,\n stream: request.stream === true,\n temperature: request.temperature,\n tool_choice: chatToolChoice(request.tool_choice),\n tools: chatTools(request.tools),\n top_p: request.top_p,\n });\n}\n\nexport function completionsRequestToChatCompletion(request: JsonObject): JsonObject {\n return removeUndefined({\n max_tokens: request.max_tokens,\n messages: [{ content: promptToText(request.prompt), role: \"user\" }],\n model: contentToText(request.model) || DEFAULT_MODEL,\n stream: request.stream === true,\n temperature: request.temperature,\n top_p: request.top_p,\n });\n}\n\nexport function chatCompletionToResponse(completion: JsonObject, responseId?: string): JsonObject {\n const id = responseId ?? `resp_${randomId()}`;\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n const model = contentToText(completion.model) || DEFAULT_MODEL;\n const output = outputItemsFromMessage(message);\n const usage = responseUsage(completion.usage);\n\n return removeUndefined({\n created_at: epochSeconds(),\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n output_text: outputText(output),\n parallel_tool_calls: true,\n status: \"completed\",\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n usage,\n });\n}\n\nexport function chatCompletionToCompletion(completion: JsonObject): JsonObject {\n const choice = firstChoice(completion);\n const message = asRecord(choice.message);\n return removeUndefined({\n choices: [\n {\n finish_reason: choice.finish_reason ?? \"stop\",\n index: 0,\n logprobs: null,\n text: contentToText(message.content),\n },\n ],\n created: completion.created ?? epochSeconds(),\n id: completion.id ?? `cmpl_${randomId()}`,\n model: completion.model ?? DEFAULT_MODEL,\n object: \"text_completion\",\n usage: completion.usage,\n });\n}\n\nexport function normalizeModelsResponse(upstream: unknown): JsonObject {\n const record = asRecord(upstream);\n const data = Array.isArray(record.data) ? record.data : Array.isArray(upstream) ? upstream : [];\n const models = data\n .map((model) => asRecord(model))\n .filter((model) => typeof model.id === \"string\")\n .map((model) => ({\n created: model.created ?? 0,\n id: model.id,\n object: \"model\",\n owned_by: model.owned_by ?? \"github-copilot\",\n }));\n\n return {\n data: models.length > 0 ? models : fallbackModels(),\n object: \"list\",\n };\n}\n\nexport function fallbackModels(): Array<JsonObject> {\n return [\n {\n created: 0,\n id: DEFAULT_MODEL,\n object: \"model\",\n owned_by: \"github-copilot\",\n },\n ];\n}\n\nexport function responsesStreamFromChatStream(\n chatStream: ReadableStream<Uint8Array>,\n options: ResponseStreamOptions,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n const responseId = options.responseId ?? `resp_${randomId()}`;\n const messageId = `msg_${randomId()}`;\n const createdAt = epochSeconds();\n let buffer = \"\";\n let text = \"\";\n const tools = new Map<number, AccumulatedToolCall>();\n\n return new ReadableStream<Uint8Array>({\n async start(controller) {\n const enqueue = (event: string, data: JsonObject | \"[DONE]\") => {\n controller.enqueue(encoder.encode(encodeSse(event, data)));\n };\n\n enqueue(\"response.created\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"in_progress\", []),\n type: \"response.created\",\n });\n enqueue(\"response.output_item.added\", {\n item: {\n content: [],\n id: messageId,\n role: \"assistant\",\n status: \"in_progress\",\n type: \"message\",\n },\n output_index: 0,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.content_part.added\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text: \"\",\n type: \"output_text\",\n },\n type: \"response.content_part.added\",\n });\n\n const reader = chatStream.getReader();\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n buffer += decoder.decode(result.value, { stream: true });\n const lines = buffer.split(/\\r?\\n/);\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n processChatSseLine(line, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n }\n if (buffer) {\n processChatSseLine(buffer, enqueue, tools, (delta) => {\n text += delta;\n });\n }\n\n const output = streamOutputItems(messageId, text, [...tools.values()]);\n enqueue(\"response.output_text.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n text,\n type: \"response.output_text.done\",\n });\n enqueue(\"response.content_part.done\", {\n content_index: 0,\n item_id: messageId,\n output_index: 0,\n part: {\n annotations: [],\n text,\n type: \"output_text\",\n },\n type: \"response.content_part.done\",\n });\n enqueue(\"response.output_item.done\", {\n item: output[0],\n output_index: 0,\n type: \"response.output_item.done\",\n });\n\n tools.forEach((tool, index) => {\n const item = functionCallItem(tool);\n const outputIndex = index + 1;\n enqueue(\"response.output_item.added\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.added\",\n });\n enqueue(\"response.function_call_arguments.done\", {\n arguments: tool.arguments,\n item_id: item.id,\n output_index: outputIndex,\n type: \"response.function_call_arguments.done\",\n });\n enqueue(\"response.output_item.done\", {\n item,\n output_index: outputIndex,\n type: \"response.output_item.done\",\n });\n });\n\n enqueue(\"response.completed\", {\n response: baseStreamResponse(responseId, options.model, createdAt, \"completed\", output),\n type: \"response.completed\",\n });\n enqueue(\"done\", \"[DONE]\");\n controller.close();\n } catch (error) {\n controller.error(error);\n } finally {\n reader.releaseLock();\n }\n },\n });\n}\n\nfunction inputToMessages(input: unknown): unknown[] {\n if (typeof input === \"string\") {\n return [{ content: input, role: \"user\" }];\n }\n if (!Array.isArray(input)) {\n return [];\n }\n\n const messages: unknown[] = [];\n for (const item of input) {\n const record = asRecord(item);\n if (record.type === \"function_call_output\") {\n messages.push({\n content: contentToText(record.output),\n role: \"tool\",\n tool_call_id: contentToText(record.call_id),\n });\n continue;\n }\n if (record.type === \"function_call\") {\n messages.push({\n role: \"assistant\",\n tool_calls: [\n {\n function: {\n arguments: contentToText(record.arguments),\n name: contentToText(record.name),\n },\n id: contentToText(record.call_id) || contentToText(record.id),\n type: \"function\",\n },\n ],\n });\n continue;\n }\n const role = roleToChatRole(contentToText(record.role));\n const content = chatMessageContent(record.content);\n if (role && content !== undefined) {\n messages.push({ content, role });\n }\n }\n return messages;\n}\n\nfunction chatMessageContent(content: unknown): string | Array<JsonObject> | undefined {\n if (typeof content === \"string\") {\n return content;\n }\n if (!Array.isArray(content)) {\n return contentToText(content) || undefined;\n }\n\n const parts: JsonObject[] = [];\n for (const part of content) {\n const record = asRecord(part);\n const type = contentToText(record.type);\n if (type === \"input_text\" || type === \"output_text\" || type === \"text\") {\n parts.push({ text: contentToText(record.text), type: \"text\" });\n }\n if (type === \"input_image\") {\n const imageUrl = contentToText(record.image_url);\n if (imageUrl) {\n parts.push({ image_url: { url: imageUrl }, type: \"image_url\" });\n }\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n if (parts.every((part) => part.type === \"text\")) {\n return parts.map((part) => contentToText(part.text)).join(\"\\n\");\n }\n return parts;\n}\n\nfunction promptToText(prompt: unknown): string {\n if (Array.isArray(prompt)) {\n return prompt.map((item) => contentToText(item)).join(\"\\n\");\n }\n return contentToText(prompt);\n}\n\nfunction contentToText(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n if (typeof content === \"number\" || typeof content === \"boolean\") {\n return String(content);\n }\n if (Array.isArray(content)) {\n return content\n .map((item) => contentToText(item))\n .filter(Boolean)\n .join(\"\\n\");\n }\n if (content && typeof content === \"object\") {\n const record = content as Record<string, unknown>;\n if (typeof record.text === \"string\") {\n return record.text;\n }\n if (typeof record.output_text === \"string\") {\n return record.output_text;\n }\n return JSON.stringify(content);\n }\n return \"\";\n}\n\nfunction roleToChatRole(role: string): string | undefined {\n if (role === \"assistant\" || role === \"developer\" || role === \"system\" || role === \"tool\") {\n return role === \"developer\" ? \"system\" : role;\n }\n return \"user\";\n}\n\nfunction chatTools(tools: unknown): unknown[] | undefined {\n if (!Array.isArray(tools)) {\n return undefined;\n }\n const converted = tools\n .map((tool) => asRecord(tool))\n .filter((tool) => tool.type === \"function\")\n .map((tool) => ({\n function: removeUndefined({\n description: tool.description,\n name: tool.name,\n parameters: tool.parameters,\n strict: tool.strict,\n }),\n type: \"function\",\n }));\n return converted.length > 0 ? converted : undefined;\n}\n\nfunction chatToolChoice(toolChoice: unknown): unknown {\n if (typeof toolChoice === \"string\" || toolChoice === undefined) {\n return toolChoice;\n }\n const record = asRecord(toolChoice);\n if (record.type === \"function\" && typeof record.name === \"string\") {\n return { function: { name: record.name }, type: \"function\" };\n }\n return toolChoice;\n}\n\nfunction outputItemsFromMessage(message: Record<string, unknown>): JsonObject[] {\n const output: JsonObject[] = [];\n const text = contentToText(message.content);\n if (text) {\n output.push(messageOutputItem(text));\n }\n const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n output.push(\n functionCallItem({\n arguments: contentToText(fn.arguments),\n id: contentToText(record.id) || `call_${randomId()}`,\n index: output.length,\n name: contentToText(fn.name),\n }),\n );\n }\n return output;\n}\n\nfunction messageOutputItem(text: string, id = `msg_${randomId()}`): JsonObject {\n return {\n content: [\n {\n annotations: [],\n text,\n type: \"output_text\",\n },\n ],\n id,\n role: \"assistant\",\n status: \"completed\",\n type: \"message\",\n };\n}\n\nfunction functionCallItem(tool: AccumulatedToolCall): JsonObject {\n return {\n arguments: tool.arguments,\n call_id: tool.id,\n id: `fc_${randomId()}`,\n name: tool.name,\n status: \"completed\",\n type: \"function_call\",\n };\n}\n\nfunction outputText(output: JsonObject[]): string {\n return output\n .flatMap((item) => {\n const content = item.content;\n return Array.isArray(content) ? content : [];\n })\n .map((part) => contentToText(asRecord(part).text))\n .filter(Boolean)\n .join(\"\");\n}\n\nfunction responseUsage(usage: unknown): JsonObject | null {\n const record = asRecord(usage);\n if (Object.keys(record).length === 0) {\n return null;\n }\n return removeUndefined({\n input_tokens: record.prompt_tokens,\n input_tokens_details: record.prompt_tokens_details,\n output_tokens: record.completion_tokens,\n output_tokens_details: record.completion_tokens_details,\n total_tokens: record.total_tokens,\n });\n}\n\nfunction firstChoice(completion: JsonObject): Record<string, unknown> {\n const choices = Array.isArray(completion.choices) ? completion.choices : [];\n return asRecord(choices[0]);\n}\n\nfunction processChatSseLine(\n line: string,\n enqueue: (event: string, data: JsonObject | \"[DONE]\") => void,\n tools: Map<number, AccumulatedToolCall>,\n appendText: (delta: string) => void,\n): void {\n const trimmed = line.trim();\n if (!trimmed.startsWith(\"data:\")) {\n return;\n }\n const data = trimmed.slice(\"data:\".length).trim();\n if (!data || data === \"[DONE]\") {\n return;\n }\n\n const parsed = parseJson(data);\n if (!parsed) {\n return;\n }\n const choice = firstChoice(parsed);\n const delta = asRecord(choice.delta);\n const content = contentToText(delta.content);\n if (content) {\n appendText(content);\n enqueue(\"response.output_text.delta\", {\n content_index: 0,\n delta: content,\n item_id: \"\",\n output_index: 0,\n type: \"response.output_text.delta\",\n });\n }\n\n const toolCalls = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];\n for (const toolCall of toolCalls) {\n const record = asRecord(toolCall);\n const fn = asRecord(record.function);\n const index = typeof record.index === \"number\" ? record.index : tools.size;\n const existing = tools.get(index) ?? {\n arguments: \"\",\n id: contentToText(record.id) || `call_${randomId()}`,\n index,\n name: \"\",\n };\n existing.id = contentToText(record.id) || existing.id;\n existing.name += contentToText(fn.name);\n existing.arguments += contentToText(fn.arguments);\n tools.set(index, existing);\n }\n}\n\nfunction streamOutputItems(\n messageId: string,\n text: string,\n tools: AccumulatedToolCall[],\n): JsonObject[] {\n return [messageOutputItem(text, messageId), ...tools.map((tool) => functionCallItem(tool))];\n}\n\nfunction baseStreamResponse(\n id: string,\n model: string,\n createdAt: number,\n status: \"in_progress\" | \"completed\",\n output: JsonObject[],\n): JsonObject {\n return {\n created_at: createdAt,\n error: null,\n id,\n incomplete_details: null,\n instructions: null,\n max_output_tokens: null,\n metadata: {},\n model,\n object: \"response\",\n output,\n parallel_tool_calls: true,\n status,\n temperature: null,\n tool_choice: \"auto\",\n tools: [],\n top_p: null,\n };\n}\n\nfunction encodeSse(event: string, data: JsonObject | \"[DONE]\"): string {\n if (data === \"[DONE]\") {\n return \"data: [DONE]\\n\\n\";\n }\n return `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n}\n\nfunction parseJson(data: string): JsonObject | undefined {\n try {\n return asRecord(JSON.parse(data));\n } catch {\n return undefined;\n }\n}\n\nfunction removeUndefined(record: JsonObject): JsonObject {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction asRecord(value: unknown): JsonObject {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n}\n\nfunction randomId(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\");\n}\n\nfunction epochSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { CopilotAuthError } from \"./auth\";\nimport { CopilotClient } from \"./copilot\";\nimport {\n chatCompletionToCompletion,\n chatCompletionToResponse,\n completionsRequestToChatCompletion,\n fallbackModels,\n normalizeModelsResponse,\n responsesRequestToChatCompletion,\n responsesStreamFromChatStream,\n} from \"./openai\";\nimport type { HoopilotServerOptions, JsonObject, StartedHoopilotServer } from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_PORT = 4141;\n\nexport function createHoopilotHandler(options: HoopilotServerOptions = {}) {\n const client = new CopilotClient(options);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method === \"OPTIONS\") {\n return new Response(null, { headers: corsHeaders() });\n }\n\n if (!isAuthorized(request, apiKey)) {\n return jsonError(401, \"invalid_api_key\", \"Invalid or missing Hoopilot API key.\");\n }\n\n try {\n if (request.method === \"GET\" && (url.pathname === \"/\" || url.pathname === \"/healthz\")) {\n return jsonResponse({\n name: \"hoopilot\",\n object: \"health\",\n status: \"ok\",\n });\n }\n if (request.method === \"GET\" && url.pathname === \"/v1/models\") {\n return await handleModels(client, request.signal);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n return await handleChatCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/completions\") {\n return await handleCompletions(client, request);\n }\n if (request.method === \"POST\" && url.pathname === \"/v1/responses\") {\n return await handleResponses(client, request);\n }\n return jsonError(404, \"not_found\", `No route for ${request.method} ${url.pathname}.`);\n } catch (error) {\n if (error instanceof CopilotAuthError) {\n return jsonError(401, \"copilot_auth_error\", error.message);\n }\n return jsonError(500, \"internal_error\", errorMessage(error));\n }\n };\n}\n\nexport function startHoopilotServer(options: HoopilotServerOptions = {}): StartedHoopilotServer {\n const host = options.host ?? options.env?.HOST ?? DEFAULT_HOST;\n const port = Number(options.port ?? options.env?.PORT ?? DEFAULT_PORT);\n const apiKey = options.apiKey ?? options.env?.HOOPILOT_API_KEY;\n const allowUnauthenticated =\n options.allowUnauthenticated ?? options.env?.HOOPILOT_ALLOW_UNAUTHENTICATED === \"1\";\n\n if (!isLoopbackHost(host) && !apiKey && !allowUnauthenticated) {\n throw new Error(\n \"Refusing to listen on a non-loopback host without HOOPILOT_API_KEY. Set an API key or pass --allow-unauthenticated.\",\n );\n }\n\n const server = Bun.serve({\n fetch: createHoopilotHandler({\n ...options,\n apiKey,\n host,\n port,\n }),\n hostname: host,\n port,\n });\n\n return {\n server,\n url: `http://${host}:${server.port}`,\n };\n}\n\nasync function handleModels(client: CopilotClient, signal: AbortSignal): Promise<Response> {\n const upstream = await client.models(signal);\n if (!upstream.ok) {\n return jsonResponse({ data: fallbackModels(), object: \"list\" });\n }\n return jsonResponse(normalizeModelsResponse(await upstream.json()));\n}\n\nasync function handleChatCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const upstream = await client.forwardChatCompletions(await request.text(), request.signal);\n return proxyResponse(upstream);\n}\n\nasync function handleCompletions(client: CopilotClient, request: Request): Promise<Response> {\n const body = await readJson(request);\n const upstream = await client.chatCompletions(\n completionsRequestToChatCompletion(body),\n request.signal,\n );\n if (!upstream.ok) {\n return proxyError(upstream);\n }\n return jsonResponse(chatCompletionToCompletion(await upstream.json()));\n}\n\nasync function handleResponses(client: CopilotClient, request: Request): Promise<Response> {\n const body = await readJson(request);\n const chatRequest = responsesRequestToChatCompletion(body);\n const upstream = await client.chatCompletions(chatRequest, request.signal);\n if (!upstream.ok) {\n return proxyError(upstream);\n }\n\n if (body.stream === true && upstream.body) {\n return new Response(\n responsesStreamFromChatStream(upstream.body, {\n model: typeof chatRequest.model === \"string\" ? chatRequest.model : \"gpt-4.1\",\n }),\n {\n headers: {\n ...corsHeaders(),\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n \"content-type\": \"text/event-stream; charset=utf-8\",\n },\n },\n );\n }\n\n return jsonResponse(chatCompletionToResponse(await upstream.json()));\n}\n\nasync function proxyError(upstream: Response): Promise<Response> {\n const text = await upstream.text();\n return jsonError(upstream.status, \"copilot_error\", text || upstream.statusText);\n}\n\nfunction proxyResponse(upstream: Response): Response {\n const headers = new Headers(upstream.headers);\n headers.delete(\"content-encoding\");\n headers.delete(\"content-length\");\n headers.delete(\"transfer-encoding\");\n for (const [key, value] of Object.entries(corsHeaders())) {\n headers.set(key, value);\n }\n return new Response(upstream.body, {\n headers,\n status: upstream.status,\n statusText: upstream.statusText,\n });\n}\n\nasync function readJson(request: Request): Promise<JsonObject> {\n try {\n const value = await request.json();\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as JsonObject) : {};\n } catch {\n throw new Error(\"Request body must be valid JSON.\");\n }\n}\n\nfunction jsonResponse(body: JsonObject, status = 200): Response {\n return new Response(JSON.stringify(body), {\n headers: {\n ...corsHeaders(),\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status,\n });\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return jsonResponse(\n {\n error: {\n code,\n message,\n type: code,\n },\n },\n status,\n );\n}\n\nfunction corsHeaders(): Record<string, string> {\n return {\n \"access-control-allow-headers\": \"authorization, content-type, x-api-key\",\n \"access-control-allow-methods\": \"GET, POST, OPTIONS\",\n \"access-control-allow-origin\": \"*\",\n };\n}\n\nfunction isAuthorized(request: Request, apiKey: string | undefined): boolean {\n if (!apiKey) {\n return true;\n }\n const authorization = request.headers.get(\"authorization\") ?? \"\";\n const bearer = authorization.match(/^Bearer\\s+(.+)$/i)?.[1];\n return bearer === apiKey || request.headers.get(\"x-api-key\") === apiKey;\n}\n\nfunction isLoopbackHost(host: string): boolean {\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","// 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 {\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 {\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(currentVersion: string, kind: InstallKind): Promise<void> {\n if (isUpdateCheckDisabled(process.env, Boolean(process.stderr.isTTY))) {\n return;\n }\n const state = await readStateSafe();\n if (state.latestVersion && isOutdated(currentVersion, state.latestVersion)) {\n process.stderr.write(formatUpdateNotice(currentVersion, state.latestVersion, kind));\n }\n if (shouldRefresh(state.lastCheck, Date.now())) {\n void refreshState(currentVersion, state.etag ?? null).catch(() => {\n // best effort\n });\n }\n}\n\nasync function refreshState(currentVersion: string, etag: string | null): Promise<void> {\n const result = await fetchLatest(currentVersion, etag);\n if (!result) {\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 return;\n }\n if (result.release) {\n await writeStateSafe({\n lastCheck: Date.now(),\n latestVersion: result.release.version,\n etag: result.etag,\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 Bun.write(dest, response);\n}\n\nasync function sha256File(path: string): Promise<string> {\n const hasher = new Bun.CryptoHasher(\"sha256\");\n hasher.update(await Bun.file(path).arrayBuffer());\n return hasher.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): Promise<void> {\n cleanupOldBinary();\n const kind = detectInstallKind();\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 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 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 if (process.platform === \"win32\") {\n console.log(\"Restart hoopilot to run the new version.\");\n }\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","#!/usr/bin/env bun\n\nimport { startHoopilotServer } from \"./server\";\nimport type { AuthMode, HoopilotServerOptions } from \"./types\";\nimport { cleanupOldBinary, maybeNotifyUpdate, runUpdate } from \"./update\";\nimport { getVersion, IS_STANDALONE_BINARY } from \"./version\";\n\ninterface ParsedArgs extends HoopilotServerOptions {\n help?: boolean;\n version?: boolean;\n noUpdateCheck?: boolean;\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 await runUpdate(await getVersion());\n return;\n }\n\n const args = 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 started = startHoopilotServer(args);\n console.log(`hoopilot listening on ${started.url}`);\n console.log(`OpenAI base URL: ${started.url}/v1`);\n console.log(\"Use Ctrl+C to stop.\");\n\n if (!args.noUpdateCheck) {\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(await getVersion(), IS_STANDALONE_BINARY ? \"binary\" : \"npm\");\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-gh\") {\n args.githubTokenCommand = false;\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-mode\":\n args.authMode = parseAuthMode(value);\n break;\n case \"--copilot-api-base-url\":\n args.copilotApiBaseUrl = value;\n break;\n case \"--copilot-token\":\n args.copilotToken = value;\n break;\n case \"--github-token\":\n args.githubToken = value;\n break;\n case \"--github-token-command\":\n args.githubTokenCommand = value;\n break;\n case \"--host\":\n args.host = value;\n break;\n case \"--port\":\n case \"-p\":\n args.port = Number(value);\n if (!Number.isInteger(args.port) || args.port <= 0) {\n throw new Error(`Invalid port: ${value}.`);\n }\n break;\n default:\n throw new Error(`Unknown option: ${name}.`);\n }\n }\n\n return args;\n}\n\nfunction parseAuthMode(value: string): AuthMode {\n if (value === \"auto\" || value === \"copilot-token\") {\n return value;\n }\n throw new Error(`Invalid auth mode: ${value}.`);\n}\n\nfunction helpText(version: string): string {\n return `hoopilot ${version}\n\nOpenAI-compatible proxy for GitHub Copilot.\n\nUsage:\n hoopilot [serve] [options]\n hoopilot update\n npx @openhoo/hoopilot [options]\n\nCommands:\n serve Start the proxy server (default)\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-mode <mode> auto, copilot-token\n --github-token <token> GitHub CLI OAuth token for a Copilot account. PATs are rejected.\n --github-token-command <cmd> Command used to read a GitHub token. Default: gh auth token\n --copilot-token <token> Short-lived Copilot API bearer token\n --copilot-api-base-url <url> Copilot API base URL override\n --no-gh Do not try gh auth token\n --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 COPILOT_GITHUB_TOKEN\n COPILOT_API_TOKEN, GITHUB_COPILOT_API_TOKEN\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"],"mappings":"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","names":["asRecord","errorMessage","execFileSync","homedir","join","base","execFileSync"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openhoo/hoopilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"packageManager": "bun@1.3.14",
|
|
5
5
|
"description": "OpenAI-compatible local proxy for GitHub Copilot accounts.",
|
|
6
6
|
"repository": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean && tsup src/cli.ts --format esm --sourcemap",
|
|
41
|
+
"build:binaries": "bash scripts/build-binaries.sh",
|
|
41
42
|
"biome:check": "biome ci --error-on-warnings .",
|
|
42
43
|
"biome:fix": "biome check --write .",
|
|
43
44
|
"format": "biome format --write .",
|