@openhoo/hoopilot 0.9.2 → 0.10.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 +36 -4
- package/dist/cli.js +40 -11
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,17 +58,17 @@ Run Hoopilot as a long-lived service from the published multi-arch image on the
|
|
|
58
58
|
# 1. Sign in once; the OAuth credential is written to the persisted /data volume.
|
|
59
59
|
docker run --rm -it -v hoopilot-data:/data ghcr.io/openhoo/hoopilot login
|
|
60
60
|
|
|
61
|
-
# 2. Run the proxy
|
|
61
|
+
# 2. Run the proxy on localhost.
|
|
62
62
|
docker run -d --name hoopilot --restart unless-stopped \
|
|
63
|
-
-p 4141:4141
|
|
63
|
+
-p 127.0.0.1:4141:4141 \
|
|
64
64
|
-v hoopilot-data:/data ghcr.io/openhoo/hoopilot
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
Tags follow the release version (e.g. `ghcr.io/openhoo/hoopilot:0.8`, `:0.8.3`) plus `:latest`. The image listens on `0.0.0.0:4141`, runs as a non-root user, and stores its OAuth credential at `/data/auth.json` (override with `HOOPILOT_AUTH_FILE`). A `docker-compose.yml` is provided in the repository:
|
|
67
|
+
Tags follow the release version (e.g. `ghcr.io/openhoo/hoopilot:0.8`, `:0.8.3`) plus `:latest`. The image listens on `0.0.0.0:4141`, runs as a non-root user, and stores its OAuth credential at `/data/auth.json` (override with `HOOPILOT_AUTH_FILE`). The Docker image allows unauthenticated local clients by default; set `HOOPILOT_API_KEY` if you publish the port beyond localhost. A `docker-compose.yml` is provided in the repository:
|
|
68
68
|
|
|
69
69
|
```sh
|
|
70
70
|
docker compose run --rm hoopilot login # one-time GitHub OAuth
|
|
71
|
-
|
|
71
|
+
docker compose up -d
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
## Update
|
|
@@ -91,6 +91,37 @@ npx @openhoo/hoopilot login
|
|
|
91
91
|
|
|
92
92
|
The login command prints a one-time code, opens `https://github.com/login/device` best-effort, verifies that the returned OAuth token can reach the Copilot API, and stores it in Hoopilot's auth file. Re-run `npx @openhoo/hoopilot login` after upgrading Hoopilot if Copilot reports a supported model as unavailable; older stored tokens can have a reduced model set.
|
|
93
93
|
|
|
94
|
+
Add `--print-key` to print the received OAuth token after verification. Login status stays on stderr, so stdout contains only the token. To append the token to a `.env` file, use one of these copyable examples.
|
|
95
|
+
|
|
96
|
+
Local CLI, sh:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
hoopilot login --print-key | sed 's/^/COPILOT_OAUTH_TOKEN=/' >> .env
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Local CLI, PowerShell:
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
hoopilot login --print-key |
|
|
106
|
+
ForEach-Object { "COPILOT_OAUTH_TOKEN=$_" } |
|
|
107
|
+
Add-Content -Encoding utf8 .env
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Docker, sh:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
docker run --rm -v hoopilot-data:/data ghcr.io/openhoo/hoopilot login --print-key \
|
|
114
|
+
| sed 's/^/COPILOT_OAUTH_TOKEN=/' >> .env
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Docker, PowerShell:
|
|
118
|
+
|
|
119
|
+
```powershell
|
|
120
|
+
docker run --rm -v hoopilot-data:/data ghcr.io/openhoo/hoopilot login --print-key |
|
|
121
|
+
ForEach-Object { "COPILOT_OAUTH_TOKEN=$_" } |
|
|
122
|
+
Add-Content -Encoding utf8 .env
|
|
123
|
+
```
|
|
124
|
+
|
|
94
125
|
Then start the proxy:
|
|
95
126
|
|
|
96
127
|
```powershell
|
|
@@ -280,6 +311,7 @@ Options:
|
|
|
280
311
|
--api-key-file <path> Read the local API key from a file instead of argv
|
|
281
312
|
--auth-file <path> OAuth credential store path
|
|
282
313
|
--copilot-api-base-url <url> Copilot API base URL override
|
|
314
|
+
--print-key Login: print the received OAuth token to stdout
|
|
283
315
|
--log-level <level> trace, debug, info, warn, error, fatal, or silent
|
|
284
316
|
--log-format <format> json or pretty. Default: pretty
|
|
285
317
|
--no-update-check Do not check GitHub for a newer release
|
package/dist/cli.js
CHANGED
|
@@ -3473,7 +3473,7 @@ async function main2(argv = Bun.argv.slice(2)) {
|
|
|
3473
3473
|
if (await printMetaOption(args2)) {
|
|
3474
3474
|
return;
|
|
3475
3475
|
}
|
|
3476
|
-
args2.logger = commandLogger(args2, "login");
|
|
3476
|
+
args2.logger = commandLogger(args2, "login", args2.printToken ? process.stderr : void 0);
|
|
3477
3477
|
await runLogin(args2);
|
|
3478
3478
|
return;
|
|
3479
3479
|
}
|
|
@@ -3556,6 +3556,10 @@ function parseArgs(argv) {
|
|
|
3556
3556
|
args.noUpdateCheck = true;
|
|
3557
3557
|
continue;
|
|
3558
3558
|
}
|
|
3559
|
+
if (arg === "--print-key" || arg === "--print-token") {
|
|
3560
|
+
args.printToken = true;
|
|
3561
|
+
continue;
|
|
3562
|
+
}
|
|
3559
3563
|
if (!arg.startsWith("-")) {
|
|
3560
3564
|
throw new Error(`Unknown argument: ${arg}.`);
|
|
3561
3565
|
}
|
|
@@ -3629,14 +3633,16 @@ function readApiKeyFile(path) {
|
|
|
3629
3633
|
}
|
|
3630
3634
|
async function runLogin(options = {}) {
|
|
3631
3635
|
const logger = options.logger?.child({ component: "auth" }) ?? noopLogger;
|
|
3636
|
+
const status = loginStatusLogger(Boolean(options.printToken));
|
|
3632
3637
|
logger.debug({ event: "auth.login.started" }, "starting github copilot browser login");
|
|
3633
|
-
|
|
3634
|
-
const
|
|
3638
|
+
status.info("Starting GitHub Copilot browser login...");
|
|
3639
|
+
const deviceLogin = options.deviceLogin ?? githubCopilotDeviceLogin;
|
|
3640
|
+
const login = await deviceLogin({
|
|
3635
3641
|
env: options.env,
|
|
3636
|
-
logger:
|
|
3642
|
+
logger: status,
|
|
3637
3643
|
openBrowser: openBrowserBestEffort
|
|
3638
3644
|
});
|
|
3639
|
-
|
|
3645
|
+
status.info("Checking GitHub Copilot access...");
|
|
3640
3646
|
const access = await verifyCopilotOAuthToken(login.token, options);
|
|
3641
3647
|
logger.debug(
|
|
3642
3648
|
{ apiBaseUrl: access.apiBaseUrl, event: "auth.login.verified" },
|
|
@@ -3653,8 +3659,11 @@ async function runLogin(options = {}) {
|
|
|
3653
3659
|
path
|
|
3654
3660
|
);
|
|
3655
3661
|
logger.debug({ authStorePath: path, event: "auth.login.stored" }, "copilot credential stored");
|
|
3656
|
-
|
|
3657
|
-
|
|
3662
|
+
status.info(`Copilot OAuth credential stored at ${path}`);
|
|
3663
|
+
status.info("Copilot authentication ready.");
|
|
3664
|
+
if (options.printToken) {
|
|
3665
|
+
console.log(login.token);
|
|
3666
|
+
}
|
|
3658
3667
|
}
|
|
3659
3668
|
async function runModels(options = {}) {
|
|
3660
3669
|
const logger = options.logger?.child({ component: "models" }) ?? noopLogger;
|
|
@@ -3790,15 +3799,17 @@ async function verifyCopilotOAuthToken(token, options = {}) {
|
|
|
3790
3799
|
token
|
|
3791
3800
|
};
|
|
3792
3801
|
}
|
|
3793
|
-
function openBrowserBestEffort(url) {
|
|
3802
|
+
function openBrowserBestEffort(url, spawnOpener = spawn) {
|
|
3794
3803
|
const platform = process.platform;
|
|
3795
3804
|
const command = platform === "win32" ? "cmd" : platform === "darwin" ? "open" : "xdg-open";
|
|
3796
3805
|
const args = platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
3797
3806
|
try {
|
|
3798
|
-
const child =
|
|
3807
|
+
const child = spawnOpener(command, args, {
|
|
3799
3808
|
detached: true,
|
|
3800
3809
|
stdio: "ignore"
|
|
3801
3810
|
});
|
|
3811
|
+
child.on("error", () => {
|
|
3812
|
+
});
|
|
3802
3813
|
child.unref();
|
|
3803
3814
|
} catch {
|
|
3804
3815
|
}
|
|
@@ -3821,13 +3832,28 @@ function modelIdsFromResponse(body) {
|
|
|
3821
3832
|
function withRuntimeEnv(args) {
|
|
3822
3833
|
return { ...args, env: process.env };
|
|
3823
3834
|
}
|
|
3824
|
-
function commandLogger(args, command) {
|
|
3835
|
+
function commandLogger(args, command, stream) {
|
|
3825
3836
|
return createHoopilotLogger({
|
|
3826
3837
|
env: args.env,
|
|
3827
3838
|
format: args.logFormat,
|
|
3828
|
-
level: args.logLevel
|
|
3839
|
+
level: args.logLevel,
|
|
3840
|
+
stream
|
|
3829
3841
|
}).child({ command, component: "cli" });
|
|
3830
3842
|
}
|
|
3843
|
+
function loginStatusLogger(writeSecretsToStdout) {
|
|
3844
|
+
if (writeSecretsToStdout) {
|
|
3845
|
+
return {
|
|
3846
|
+
error: (message) => console.error(message),
|
|
3847
|
+
info: (message) => console.error(message),
|
|
3848
|
+
warn: (message) => console.error(message)
|
|
3849
|
+
};
|
|
3850
|
+
}
|
|
3851
|
+
return {
|
|
3852
|
+
error: (message) => console.error(message),
|
|
3853
|
+
info: (message) => console.log(message),
|
|
3854
|
+
warn: (message) => console.warn(message)
|
|
3855
|
+
};
|
|
3856
|
+
}
|
|
3831
3857
|
function helpText(version) {
|
|
3832
3858
|
return `hoopilot ${version}
|
|
3833
3859
|
|
|
@@ -3861,6 +3887,7 @@ Options:
|
|
|
3861
3887
|
--api-key-file <path> Read the local API key from a file instead of argv
|
|
3862
3888
|
--auth-file <path> OAuth credential store path
|
|
3863
3889
|
--copilot-api-base-url <url> Copilot API base URL override
|
|
3890
|
+
--print-key Login: print the received OAuth token to stdout
|
|
3864
3891
|
--log-level <level> trace, debug, info, warn, error, fatal, or silent
|
|
3865
3892
|
--log-format <format> json or pretty. Default: pretty
|
|
3866
3893
|
--stream-mode <mode> auto, live, or buffer. Auto buffers Windows standalone streams.
|
|
@@ -3891,7 +3918,9 @@ if (import.meta.main) {
|
|
|
3891
3918
|
}
|
|
3892
3919
|
export {
|
|
3893
3920
|
main2 as main,
|
|
3921
|
+
openBrowserBestEffort,
|
|
3894
3922
|
parseArgs,
|
|
3923
|
+
runLogin,
|
|
3895
3924
|
runModels,
|
|
3896
3925
|
runUsage,
|
|
3897
3926
|
verifyCopilotOAuthToken
|