geminimock 0.1.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/LICENSE +21 -0
- package/README.md +66 -0
- package/dist/auth/credential-store.d.ts +17 -0
- package/dist/auth/credential-store.js +44 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/oauth-flow.d.ts +26 -0
- package/dist/auth/oauth-flow.js +87 -0
- package/dist/auth/oauth-flow.js.map +1 -0
- package/dist/auth/oauth-service.d.ts +18 -0
- package/dist/auth/oauth-service.js +287 -0
- package/dist/auth/oauth-service.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +76 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/env.d.ts +11 -0
- package/dist/config/env.js +28 -0
- package/dist/config/env.js.map +1 -0
- package/dist/gemini/code-assist-client.d.ts +17 -0
- package/dist/gemini/code-assist-client.js +179 -0
- package/dist/gemini/code-assist-client.js.map +1 -0
- package/dist/gemini/model-catalog-service.d.ts +8 -0
- package/dist/gemini/model-catalog-service.js +31 -0
- package/dist/gemini/model-catalog-service.js.map +1 -0
- package/dist/gemini/types.d.ts +82 -0
- package/dist/gemini/types.js +2 -0
- package/dist/gemini/types.js.map +1 -0
- package/dist/openai/chat-service.d.ts +12 -0
- package/dist/openai/chat-service.js +82 -0
- package/dist/openai/chat-service.js.map +1 -0
- package/dist/openai/mapper.d.ts +7 -0
- package/dist/openai/mapper.js +86 -0
- package/dist/openai/mapper.js.map +1 -0
- package/dist/openai/model-resolver.d.ts +2 -0
- package/dist/openai/model-resolver.js +52 -0
- package/dist/openai/model-resolver.js.map +1 -0
- package/dist/openai/models-response.d.ts +10 -0
- package/dist/openai/models-response.js +12 -0
- package/dist/openai/models-response.js.map +1 -0
- package/dist/openai/types.d.ts +56 -0
- package/dist/openai/types.js +19 -0
- package/dist/openai/types.js.map +1 -0
- package/dist/server/app.d.ts +17 -0
- package/dist/server/app.js +91 -0
- package/dist/server/app.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 soomin lee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# GeminiMock
|
|
2
|
+
|
|
3
|
+
OpenAI-compatible chat API server backed by Gemini Code Assist OAuth.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
- global: `npm i -g geminimock`
|
|
8
|
+
- one-off: `npx geminimock models list`
|
|
9
|
+
|
|
10
|
+
Installed CLI command:
|
|
11
|
+
|
|
12
|
+
- `geminimock auth login`
|
|
13
|
+
- `geminimock auth logout`
|
|
14
|
+
- `geminimock models list`
|
|
15
|
+
- `geminimock serve`
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
- `bun run auth:login`
|
|
20
|
+
- `bun run auth:logout`
|
|
21
|
+
- `bun run models:list`
|
|
22
|
+
- `bun run dev`
|
|
23
|
+
- `bun run start`
|
|
24
|
+
- `bun run test`
|
|
25
|
+
- `bun run lint`
|
|
26
|
+
- `bun run typecheck`
|
|
27
|
+
- `bun run build`
|
|
28
|
+
|
|
29
|
+
## Environment
|
|
30
|
+
|
|
31
|
+
- `GEMINI_CLI_API_HOST` default: `127.0.0.1`
|
|
32
|
+
- `GEMINI_CLI_API_PORT` default: `8080`
|
|
33
|
+
- `GEMINI_CLI_MODEL` default: `gemini-2.5-pro`
|
|
34
|
+
- `CODE_ASSIST_ENDPOINT` default: `https://cloudcode-pa.googleapis.com`
|
|
35
|
+
- `CODE_ASSIST_API_VERSION` default: `v1internal`
|
|
36
|
+
- `GEMINI_CLI_API_OAUTH_PATH` default: `~/.geminimock/oauth_creds.json`
|
|
37
|
+
- `GEMINI_CLI_OAUTH_FALLBACK_PATH` default: `~/.gemini/oauth_creds.json`
|
|
38
|
+
- `GEMINI_CLI_OAUTH_CLIENT_ID` required for fresh OAuth login
|
|
39
|
+
- `GEMINI_CLI_OAUTH_CLIENT_SECRET` required for fresh OAuth login
|
|
40
|
+
- `GOOGLE_CLOUD_PROJECT` optional
|
|
41
|
+
- `GOOGLE_CLOUD_PROJECT_ID` optional
|
|
42
|
+
|
|
43
|
+
## OAuth Login
|
|
44
|
+
|
|
45
|
+
1. Run `bun run auth:login`
|
|
46
|
+
2. Browser opens automatically and listens on a local callback URL
|
|
47
|
+
3. If browser callback is not available, paste either authorization code or full callback URL
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
- `GET /health`
|
|
52
|
+
- `GET /v1/auth/status`
|
|
53
|
+
- `GET /v1/models`
|
|
54
|
+
- `POST /v1/chat/completions`
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
curl -sS -X POST http://127.0.0.1:8080/v1/chat/completions \
|
|
60
|
+
-H 'content-type: application/json' \
|
|
61
|
+
-d '{"model":"gemini-2.5-flash","messages":[{"role":"user","content":"Hello"}]}'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
curl -sS http://127.0.0.1:8080/v1/models
|
|
66
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const credentialSchema: z.ZodObject<{
|
|
3
|
+
access_token: z.ZodString;
|
|
4
|
+
refresh_token: z.ZodOptional<z.ZodString>;
|
|
5
|
+
expiry_date: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
token_type: z.ZodOptional<z.ZodString>;
|
|
7
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export type StoredCredentials = z.infer<typeof credentialSchema>;
|
|
10
|
+
export declare function createCredentialStore(path: string, fallbackPath?: string): {
|
|
11
|
+
path: string;
|
|
12
|
+
load(): Promise<StoredCredentials | null>;
|
|
13
|
+
save(credentials: StoredCredentials): Promise<void>;
|
|
14
|
+
clear(): Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export type CredentialStore = ReturnType<typeof createCredentialStore>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const credentialSchema = z.object({
|
|
5
|
+
access_token: z.string(),
|
|
6
|
+
refresh_token: z.string().optional(),
|
|
7
|
+
expiry_date: z.number().optional(),
|
|
8
|
+
token_type: z.string().optional(),
|
|
9
|
+
scope: z.string().optional()
|
|
10
|
+
});
|
|
11
|
+
async function readCredentialFile(path) {
|
|
12
|
+
try {
|
|
13
|
+
const raw = await readFile(path, "utf8");
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
return credentialSchema.parse(parsed);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function createCredentialStore(path, fallbackPath) {
|
|
22
|
+
return {
|
|
23
|
+
path,
|
|
24
|
+
async load() {
|
|
25
|
+
const primary = await readCredentialFile(path);
|
|
26
|
+
if (primary) {
|
|
27
|
+
return primary;
|
|
28
|
+
}
|
|
29
|
+
if (!fallbackPath) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return readCredentialFile(fallbackPath);
|
|
33
|
+
},
|
|
34
|
+
async save(credentials) {
|
|
35
|
+
const data = credentialSchema.parse(credentials);
|
|
36
|
+
await mkdir(dirname(path), { recursive: true });
|
|
37
|
+
await writeFile(path, JSON.stringify(data, null, 2), { mode: 0o600, encoding: "utf8" });
|
|
38
|
+
},
|
|
39
|
+
async clear() {
|
|
40
|
+
await rm(path, { force: true });
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=credential-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAIH,KAAK,UAAU,kBAAkB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,OAAO,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,YAAqB;IACvE,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,IAAI;YACR,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,kBAAkB,CAAC,YAAY,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,WAA8B;YACvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACjD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { OAuth2Client, type Credentials } from "google-auth-library";
|
|
2
|
+
export declare const GEMINI_CLI_OAUTH_CLIENT_ID: string;
|
|
3
|
+
export declare const GEMINI_CLI_OAUTH_CLIENT_SECRET: string;
|
|
4
|
+
export declare const GEMINI_CLI_OAUTH_REDIRECT_URI = "https://codeassist.google.com/authcode";
|
|
5
|
+
export declare const GEMINI_CLI_OAUTH_SCOPE: readonly ["https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"];
|
|
6
|
+
export type ManualOAuthRequest = {
|
|
7
|
+
authUrl: string;
|
|
8
|
+
codeVerifier: string;
|
|
9
|
+
state: string;
|
|
10
|
+
redirectUri: string;
|
|
11
|
+
};
|
|
12
|
+
export type WebOAuthRequest = {
|
|
13
|
+
authUrl: string;
|
|
14
|
+
state: string;
|
|
15
|
+
redirectUri: string;
|
|
16
|
+
};
|
|
17
|
+
export type ParsedOAuthInput = {
|
|
18
|
+
code: string;
|
|
19
|
+
state?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function createOAuthClient(): OAuth2Client;
|
|
22
|
+
export declare function buildManualOAuthRequest(): Promise<ManualOAuthRequest>;
|
|
23
|
+
export declare function buildWebOAuthRequest(port: number): WebOAuthRequest;
|
|
24
|
+
export declare function parseOAuthInput(input: string): ParsedOAuthInput;
|
|
25
|
+
export declare function exchangeManualCode(request: ManualOAuthRequest, code: string): Promise<Credentials>;
|
|
26
|
+
export declare function exchangeWebCode(request: WebOAuthRequest, code: string): Promise<Credentials>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { CodeChallengeMethod, OAuth2Client } from "google-auth-library";
|
|
3
|
+
export const GEMINI_CLI_OAUTH_CLIENT_ID = process.env.GEMINI_CLI_OAUTH_CLIENT_ID ?? "replace-with-google-oauth-client-id";
|
|
4
|
+
export const GEMINI_CLI_OAUTH_CLIENT_SECRET = process.env.GEMINI_CLI_OAUTH_CLIENT_SECRET ?? "replace-with-google-oauth-client-secret";
|
|
5
|
+
export const GEMINI_CLI_OAUTH_REDIRECT_URI = "https://codeassist.google.com/authcode";
|
|
6
|
+
export const GEMINI_CLI_OAUTH_SCOPE = [
|
|
7
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
8
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
9
|
+
"https://www.googleapis.com/auth/userinfo.profile"
|
|
10
|
+
];
|
|
11
|
+
export function createOAuthClient() {
|
|
12
|
+
return new OAuth2Client({
|
|
13
|
+
clientId: GEMINI_CLI_OAUTH_CLIENT_ID,
|
|
14
|
+
clientSecret: GEMINI_CLI_OAUTH_CLIENT_SECRET
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export async function buildManualOAuthRequest() {
|
|
18
|
+
const client = createOAuthClient();
|
|
19
|
+
const verifier = await client.generateCodeVerifierAsync();
|
|
20
|
+
const state = randomBytes(32).toString("hex");
|
|
21
|
+
const authUrl = client.generateAuthUrl({
|
|
22
|
+
redirect_uri: GEMINI_CLI_OAUTH_REDIRECT_URI,
|
|
23
|
+
access_type: "offline",
|
|
24
|
+
prompt: "consent",
|
|
25
|
+
scope: [...GEMINI_CLI_OAUTH_SCOPE],
|
|
26
|
+
code_challenge_method: CodeChallengeMethod.S256,
|
|
27
|
+
code_challenge: verifier.codeChallenge,
|
|
28
|
+
state
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
authUrl,
|
|
32
|
+
codeVerifier: verifier.codeVerifier,
|
|
33
|
+
state,
|
|
34
|
+
redirectUri: GEMINI_CLI_OAUTH_REDIRECT_URI
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function buildWebOAuthRequest(port) {
|
|
38
|
+
const client = createOAuthClient();
|
|
39
|
+
const state = randomBytes(32).toString("hex");
|
|
40
|
+
const redirectUri = `http://127.0.0.1:${port}/oauth2callback`;
|
|
41
|
+
const authUrl = client.generateAuthUrl({
|
|
42
|
+
redirect_uri: redirectUri,
|
|
43
|
+
access_type: "offline",
|
|
44
|
+
prompt: "consent",
|
|
45
|
+
scope: [...GEMINI_CLI_OAUTH_SCOPE],
|
|
46
|
+
state
|
|
47
|
+
});
|
|
48
|
+
return { authUrl, state, redirectUri };
|
|
49
|
+
}
|
|
50
|
+
export function parseOAuthInput(input) {
|
|
51
|
+
const value = input.trim();
|
|
52
|
+
if (!value) {
|
|
53
|
+
throw new Error("Authorization code is required");
|
|
54
|
+
}
|
|
55
|
+
if (value.startsWith("http://") || value.startsWith("https://")) {
|
|
56
|
+
const url = new URL(value);
|
|
57
|
+
const code = url.searchParams.get("code");
|
|
58
|
+
const state = url.searchParams.get("state") ?? undefined;
|
|
59
|
+
if (!code) {
|
|
60
|
+
throw new Error("Callback URL does not include code parameter");
|
|
61
|
+
}
|
|
62
|
+
return { code, state };
|
|
63
|
+
}
|
|
64
|
+
return { code: value };
|
|
65
|
+
}
|
|
66
|
+
export async function exchangeManualCode(request, code) {
|
|
67
|
+
const parsed = parseOAuthInput(code);
|
|
68
|
+
if (parsed.state && parsed.state !== request.state) {
|
|
69
|
+
throw new Error("OAuth state mismatch");
|
|
70
|
+
}
|
|
71
|
+
const client = createOAuthClient();
|
|
72
|
+
const tokenResponse = await client.getToken({
|
|
73
|
+
code: parsed.code,
|
|
74
|
+
codeVerifier: request.codeVerifier,
|
|
75
|
+
redirect_uri: request.redirectUri
|
|
76
|
+
});
|
|
77
|
+
return tokenResponse.tokens;
|
|
78
|
+
}
|
|
79
|
+
export async function exchangeWebCode(request, code) {
|
|
80
|
+
const client = createOAuthClient();
|
|
81
|
+
const tokenResponse = await client.getToken({
|
|
82
|
+
code,
|
|
83
|
+
redirect_uri: request.redirectUri
|
|
84
|
+
});
|
|
85
|
+
return tokenResponse.tokens;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=oauth-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-flow.js","sourceRoot":"","sources":["../../src/auth/oauth-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OAuth2Client } from "google-auth-library";
|
|
2
|
+
import type { CredentialStore } from "./credential-store.js";
|
|
3
|
+
export type OAuthServiceIO = {
|
|
4
|
+
write(message: string): void;
|
|
5
|
+
readCode(prompt: string): Promise<string>;
|
|
6
|
+
};
|
|
7
|
+
export declare class OAuthService {
|
|
8
|
+
private readonly store;
|
|
9
|
+
constructor(store: CredentialStore);
|
|
10
|
+
login(io?: OAuthServiceIO): Promise<{
|
|
11
|
+
email?: string;
|
|
12
|
+
}>;
|
|
13
|
+
private loginWithWebCallback;
|
|
14
|
+
private loginManual;
|
|
15
|
+
logout(): Promise<void>;
|
|
16
|
+
getClient(): Promise<OAuth2Client>;
|
|
17
|
+
getAccessToken(): Promise<string>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import net from "node:net";
|
|
4
|
+
import { createInterface } from "node:readline/promises";
|
|
5
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
6
|
+
import { buildManualOAuthRequest, buildWebOAuthRequest, createOAuthClient, exchangeManualCode, exchangeWebCode, GEMINI_CLI_OAUTH_SCOPE, parseOAuthInput } from "./oauth-flow.js";
|
|
7
|
+
const OAUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
8
|
+
function defaultIO() {
|
|
9
|
+
return {
|
|
10
|
+
write(message) {
|
|
11
|
+
output.write(message);
|
|
12
|
+
},
|
|
13
|
+
async readCode(prompt) {
|
|
14
|
+
const rl = createInterface({ input, output });
|
|
15
|
+
const code = await rl.question(prompt);
|
|
16
|
+
rl.close();
|
|
17
|
+
return code;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function normalizeCredentials(credentials) {
|
|
22
|
+
return {
|
|
23
|
+
access_token: credentials.access_token,
|
|
24
|
+
refresh_token: credentials.refresh_token ?? undefined,
|
|
25
|
+
expiry_date: credentials.expiry_date ?? undefined,
|
|
26
|
+
token_type: credentials.token_type ?? undefined,
|
|
27
|
+
scope: credentials.scope ?? GEMINI_CLI_OAUTH_SCOPE.join(" ")
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function fetchUserEmail(client) {
|
|
31
|
+
const token = await client.getAccessToken();
|
|
32
|
+
if (!token.token) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const response = await fetch("https://www.googleapis.com/oauth2/v2/userinfo", {
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${token.token}`
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const data = (await response.json());
|
|
44
|
+
return data.email;
|
|
45
|
+
}
|
|
46
|
+
async function getAvailablePort() {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const server = net.createServer();
|
|
49
|
+
server.listen(0, "127.0.0.1", () => {
|
|
50
|
+
const address = server.address();
|
|
51
|
+
server.close(() => {
|
|
52
|
+
if (address && typeof address === "object") {
|
|
53
|
+
resolve(address.port);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
reject(new Error("Unable to allocate callback port"));
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
server.on("error", reject);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function openExternalUrl(url) {
|
|
63
|
+
const platform = process.platform;
|
|
64
|
+
const command = platform === "darwin"
|
|
65
|
+
? { cmd: "open", args: [url] }
|
|
66
|
+
: platform === "win32"
|
|
67
|
+
? { cmd: "cmd", args: ["/c", "start", "", url] }
|
|
68
|
+
: { cmd: "xdg-open", args: [url] };
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
const child = spawn(command.cmd, command.args, {
|
|
71
|
+
stdio: "ignore",
|
|
72
|
+
detached: true
|
|
73
|
+
});
|
|
74
|
+
child.on("error", () => resolve(false));
|
|
75
|
+
child.unref();
|
|
76
|
+
resolve(true);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async function startCallbackListener(port, timeoutMs) {
|
|
80
|
+
let timer;
|
|
81
|
+
let settled = false;
|
|
82
|
+
let resolveWait;
|
|
83
|
+
let rejectWait;
|
|
84
|
+
const waitPromise = new Promise((resolve, reject) => {
|
|
85
|
+
resolveWait = resolve;
|
|
86
|
+
rejectWait = reject;
|
|
87
|
+
});
|
|
88
|
+
const server = createServer((req, res) => {
|
|
89
|
+
try {
|
|
90
|
+
if (!req.url) {
|
|
91
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
92
|
+
res.end("Invalid request");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const parsed = new URL(req.url, `http://127.0.0.1:${port}`);
|
|
96
|
+
if (parsed.pathname !== "/oauth2callback") {
|
|
97
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
98
|
+
res.end("Not found");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const code = parsed.searchParams.get("code");
|
|
102
|
+
const state = parsed.searchParams.get("state") ?? undefined;
|
|
103
|
+
const error = parsed.searchParams.get("error");
|
|
104
|
+
if (error) {
|
|
105
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
106
|
+
res.end("OAuth failed");
|
|
107
|
+
if (!settled) {
|
|
108
|
+
settled = true;
|
|
109
|
+
rejectWait(new Error(`OAuth error: ${error}`));
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!code) {
|
|
114
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
115
|
+
res.end("Missing code");
|
|
116
|
+
if (!settled) {
|
|
117
|
+
settled = true;
|
|
118
|
+
rejectWait(new Error("OAuth callback missing code"));
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
123
|
+
res.end("<html><body><h1>Login complete</h1><p>You can close this tab.</p></body></html>");
|
|
124
|
+
if (!settled) {
|
|
125
|
+
settled = true;
|
|
126
|
+
resolveWait({ code, state });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (!settled) {
|
|
131
|
+
settled = true;
|
|
132
|
+
rejectWait(error instanceof Error ? error : new Error(String(error)));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
setImmediate(() => {
|
|
137
|
+
server.close();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
await new Promise((resolve, reject) => {
|
|
142
|
+
server.once("error", reject);
|
|
143
|
+
server.listen(port, process.env.OAUTH_CALLBACK_HOST ?? "127.0.0.1", () => {
|
|
144
|
+
server.off("error", reject);
|
|
145
|
+
resolve();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
timer = setTimeout(() => {
|
|
149
|
+
if (!settled) {
|
|
150
|
+
settled = true;
|
|
151
|
+
rejectWait(new Error("Timed out waiting for OAuth callback"));
|
|
152
|
+
server.close();
|
|
153
|
+
}
|
|
154
|
+
}, timeoutMs);
|
|
155
|
+
return {
|
|
156
|
+
waitForCallback: () => waitPromise,
|
|
157
|
+
close: () => new Promise((resolve) => {
|
|
158
|
+
if (timer) {
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
}
|
|
161
|
+
server.close(() => resolve());
|
|
162
|
+
})
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async function persistCredentials(store, tokens) {
|
|
166
|
+
const existing = await store.load();
|
|
167
|
+
const normalized = normalizeCredentials({
|
|
168
|
+
access_token: tokens.access_token,
|
|
169
|
+
refresh_token: tokens.refresh_token ?? existing?.refresh_token,
|
|
170
|
+
expiry_date: tokens.expiry_date ?? existing?.expiry_date,
|
|
171
|
+
token_type: tokens.token_type,
|
|
172
|
+
scope: tokens.scope
|
|
173
|
+
});
|
|
174
|
+
await store.save(normalized);
|
|
175
|
+
return normalized;
|
|
176
|
+
}
|
|
177
|
+
export class OAuthService {
|
|
178
|
+
store;
|
|
179
|
+
constructor(store) {
|
|
180
|
+
this.store = store;
|
|
181
|
+
}
|
|
182
|
+
async login(io = defaultIO()) {
|
|
183
|
+
try {
|
|
184
|
+
const result = await this.loginWithWebCallback(io);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
189
|
+
io.write(`Automatic callback login failed: ${message}\n`);
|
|
190
|
+
io.write("Falling back to manual authorization code flow.\n\n");
|
|
191
|
+
return this.loginManual(io);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async loginWithWebCallback(io) {
|
|
195
|
+
const port = await getAvailablePort();
|
|
196
|
+
const request = buildWebOAuthRequest(port);
|
|
197
|
+
const listener = await startCallbackListener(port, OAUTH_TIMEOUT_MS);
|
|
198
|
+
try {
|
|
199
|
+
const opened = await openExternalUrl(request.authUrl);
|
|
200
|
+
if (!opened) {
|
|
201
|
+
io.write("Could not open browser automatically. Open this URL manually:\n");
|
|
202
|
+
}
|
|
203
|
+
io.write(`${request.authUrl}\n\n`);
|
|
204
|
+
io.write("Waiting for OAuth callback...\n");
|
|
205
|
+
const callback = await listener.waitForCallback();
|
|
206
|
+
if (callback.state && callback.state !== request.state) {
|
|
207
|
+
throw new Error("OAuth state mismatch");
|
|
208
|
+
}
|
|
209
|
+
const tokens = await exchangeWebCode(request, callback.code);
|
|
210
|
+
if (!tokens.access_token) {
|
|
211
|
+
throw new Error("OAuth login did not return access_token");
|
|
212
|
+
}
|
|
213
|
+
const stored = await persistCredentials(this.store, {
|
|
214
|
+
access_token: tokens.access_token,
|
|
215
|
+
refresh_token: tokens.refresh_token ?? undefined,
|
|
216
|
+
expiry_date: tokens.expiry_date ?? undefined,
|
|
217
|
+
token_type: tokens.token_type ?? undefined,
|
|
218
|
+
scope: tokens.scope ?? undefined
|
|
219
|
+
});
|
|
220
|
+
const client = createOAuthClient();
|
|
221
|
+
client.setCredentials(stored);
|
|
222
|
+
const email = await fetchUserEmail(client);
|
|
223
|
+
return { email };
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
await listener.close();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async loginManual(io) {
|
|
230
|
+
const request = await buildManualOAuthRequest();
|
|
231
|
+
io.write(`Open this URL and complete login:\n\n${request.authUrl}\n\n`);
|
|
232
|
+
const rawInput = await io.readCode("Paste the authorization code (or callback URL): ");
|
|
233
|
+
const parsed = parseOAuthInput(rawInput);
|
|
234
|
+
if (parsed.state && parsed.state !== request.state) {
|
|
235
|
+
throw new Error("OAuth state mismatch");
|
|
236
|
+
}
|
|
237
|
+
const tokens = await exchangeManualCode(request, parsed.code);
|
|
238
|
+
if (!tokens.access_token) {
|
|
239
|
+
throw new Error("OAuth login did not return access_token");
|
|
240
|
+
}
|
|
241
|
+
const stored = await persistCredentials(this.store, {
|
|
242
|
+
access_token: tokens.access_token,
|
|
243
|
+
refresh_token: tokens.refresh_token ?? undefined,
|
|
244
|
+
expiry_date: tokens.expiry_date ?? undefined,
|
|
245
|
+
token_type: tokens.token_type ?? undefined,
|
|
246
|
+
scope: tokens.scope ?? undefined
|
|
247
|
+
});
|
|
248
|
+
const client = createOAuthClient();
|
|
249
|
+
client.setCredentials(stored);
|
|
250
|
+
const email = await fetchUserEmail(client);
|
|
251
|
+
return { email };
|
|
252
|
+
}
|
|
253
|
+
async logout() {
|
|
254
|
+
await this.store.clear();
|
|
255
|
+
}
|
|
256
|
+
async getClient() {
|
|
257
|
+
const credentials = await this.store.load();
|
|
258
|
+
if (!credentials) {
|
|
259
|
+
throw new Error("OAuth credentials not found. Run auth login first.");
|
|
260
|
+
}
|
|
261
|
+
const client = createOAuthClient();
|
|
262
|
+
client.setCredentials(normalizeCredentials(credentials));
|
|
263
|
+
const token = await client.getAccessToken();
|
|
264
|
+
if (!token.token) {
|
|
265
|
+
throw new Error("Failed to obtain access token from stored credentials.");
|
|
266
|
+
}
|
|
267
|
+
const merged = normalizeCredentials({
|
|
268
|
+
access_token: token.token,
|
|
269
|
+
refresh_token: client.credentials.refresh_token ?? credentials.refresh_token,
|
|
270
|
+
expiry_date: client.credentials.expiry_date ?? undefined,
|
|
271
|
+
token_type: client.credentials.token_type ?? undefined,
|
|
272
|
+
scope: client.credentials.scope ?? undefined
|
|
273
|
+
});
|
|
274
|
+
await this.store.save(merged);
|
|
275
|
+
client.setCredentials(merged);
|
|
276
|
+
return client;
|
|
277
|
+
}
|
|
278
|
+
async getAccessToken() {
|
|
279
|
+
const client = await this.getClient();
|
|
280
|
+
const token = await client.getAccessToken();
|
|
281
|
+
if (!token.token) {
|
|
282
|
+
throw new Error("Access token is empty");
|
|
283
|
+
}
|
|
284
|
+
return token.token;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=oauth-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-service.js","sourceRoot":"","sources":["../../src/auth/oauth-service.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED