opencode-gemini-cli-oauth 1.0.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 +256 -0
- package/dist/auth/account-manager.d.ts +50 -0
- package/dist/auth/account-manager.d.ts.map +1 -0
- package/dist/auth/account-manager.js +142 -0
- package/dist/auth/account-manager.js.map +1 -0
- package/dist/auth/oauth.d.ts +40 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +126 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/request-interceptor.d.ts +18 -0
- package/dist/auth/request-interceptor.d.ts.map +1 -0
- package/dist/auth/request-interceptor.js +94 -0
- package/dist/auth/request-interceptor.js.map +1 -0
- package/dist/constants.d.ts +55 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +61 -0
- package/dist/constants.js.map +1 -0
- package/dist/index-minimal.d.ts +2 -0
- package/dist/index-minimal.d.ts.map +1 -0
- package/dist/index-minimal.js +2 -0
- package/dist/index-minimal.js.map +1 -0
- package/dist/index-simple.d.ts +5 -0
- package/dist/index-simple.d.ts.map +1 -0
- package/dist/index-simple.js +5 -0
- package/dist/index-simple.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-minimal.d.ts +21 -0
- package/dist/plugin-minimal.d.ts.map +1 -0
- package/dist/plugin-minimal.js +27 -0
- package/dist/plugin-minimal.js.map +1 -0
- package/dist/plugin-simple.d.ts +28 -0
- package/dist/plugin-simple.d.ts.map +1 -0
- package/dist/plugin-simple.js +117 -0
- package/dist/plugin-simple.js.map +1 -0
- package/dist/plugin.d.ts +46 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +66 -0
- package/dist/plugin.js.map +1 -0
- package/dist/storage/storage.d.ts +56 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +138 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import { RATE_LIMIT_RETRY_DELAY_MS } from '../constants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Check if request is for Gemini API
|
|
9
|
+
*/
|
|
10
|
+
function isGeminiAPIRequest(input) {
|
|
11
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
12
|
+
return url.includes('generativelanguage.googleapis.com');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse retry-after header from rate limit response
|
|
16
|
+
*/
|
|
17
|
+
function parseRetryAfter(response) {
|
|
18
|
+
const retryAfter = response.headers.get('retry-after');
|
|
19
|
+
if (retryAfter) {
|
|
20
|
+
const seconds = parseInt(retryAfter, 10);
|
|
21
|
+
if (!isNaN(seconds)) {
|
|
22
|
+
return seconds;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Default to 60 seconds if not specified
|
|
26
|
+
return 60;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create authenticated fetch function with OAuth token injection
|
|
30
|
+
*/
|
|
31
|
+
export function createAuthenticatedFetch(accountManager) {
|
|
32
|
+
return async function authenticatedFetch(input, init) {
|
|
33
|
+
// Pass through non-Gemini API requests
|
|
34
|
+
if (!isGeminiAPIRequest(input)) {
|
|
35
|
+
return fetch(input, init);
|
|
36
|
+
}
|
|
37
|
+
// Get current access token
|
|
38
|
+
const accessToken = await accountManager.getCurrentAccessToken();
|
|
39
|
+
// Inject Authorization header
|
|
40
|
+
const headers = new Headers(init?.headers);
|
|
41
|
+
headers.set('Authorization', `Bearer ${accessToken}`);
|
|
42
|
+
// Remove API key from URL if present (OAuth doesn't need it)
|
|
43
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
44
|
+
const urlObj = new URL(url);
|
|
45
|
+
urlObj.searchParams.delete('key');
|
|
46
|
+
// Make request
|
|
47
|
+
const response = await fetch(urlObj.toString(), {
|
|
48
|
+
...init,
|
|
49
|
+
headers,
|
|
50
|
+
});
|
|
51
|
+
// Handle rate limiting (429)
|
|
52
|
+
if (response.status === 429) {
|
|
53
|
+
const currentAccount = await accountManager.getCurrentAccount();
|
|
54
|
+
if (currentAccount) {
|
|
55
|
+
const retryAfterSeconds = parseRetryAfter(response);
|
|
56
|
+
console.warn(`⚠️ Rate limit hit for ${currentAccount.email}. Retry after ${retryAfterSeconds}s`);
|
|
57
|
+
// Mark account as rate limited
|
|
58
|
+
await accountManager.markAccountRateLimited(currentAccount.email, retryAfterSeconds);
|
|
59
|
+
// Try to get next available account
|
|
60
|
+
const nextAccount = await accountManager.getNextAvailableAccount();
|
|
61
|
+
if (nextAccount) {
|
|
62
|
+
console.log(`🔄 Switching to account: ${nextAccount.email}`);
|
|
63
|
+
// Retry request with new account
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, RATE_LIMIT_RETRY_DELAY_MS));
|
|
65
|
+
return authenticatedFetch(input, init);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.error('❌ All accounts are rate limited. Please wait or add more accounts.');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Increment request count
|
|
73
|
+
await accountManager.incrementRequestCount();
|
|
74
|
+
return response;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create request interceptor for OpenCode plugin
|
|
79
|
+
*/
|
|
80
|
+
export async function createRequestInterceptor() {
|
|
81
|
+
// Lazy load to avoid constructor issues
|
|
82
|
+
const { AccountManager: AM } = await import('./account-manager.js');
|
|
83
|
+
const accountManager = new AM();
|
|
84
|
+
// Initialize account pool from Gemini CLI credentials
|
|
85
|
+
await accountManager.initialize();
|
|
86
|
+
// Get pool stats
|
|
87
|
+
const stats = await accountManager.getPoolStats();
|
|
88
|
+
console.log(`🔐 Gemini CLI OAuth: ${stats.availableAccounts}/${stats.totalAccounts} accounts available`);
|
|
89
|
+
return {
|
|
90
|
+
fetch: createAuthenticatedFetch(accountManager),
|
|
91
|
+
accountManager,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=request-interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-interceptor.js","sourceRoot":"","sources":["../../src/auth/request-interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* OAuth2 Client credentials from Gemini CLI
|
|
8
|
+
* Source: @google/gemini-cli-core/dist/src/code_assist/oauth2.js
|
|
9
|
+
*
|
|
10
|
+
* These credentials are safe to embed as this is an "installed application"
|
|
11
|
+
* per Google OAuth2 guidelines: https://developers.google.com/identity/protocols/oauth2#installed
|
|
12
|
+
*/
|
|
13
|
+
export declare const OAUTH_CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
|
|
14
|
+
export declare const OAUTH_CLIENT_SECRET = "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";
|
|
15
|
+
/**
|
|
16
|
+
* OAuth scopes required for Gemini API access
|
|
17
|
+
*/
|
|
18
|
+
export declare const OAUTH_SCOPES: string[];
|
|
19
|
+
/**
|
|
20
|
+
* Gemini CLI storage directory
|
|
21
|
+
*/
|
|
22
|
+
export declare const GEMINI_DIR: string;
|
|
23
|
+
/**
|
|
24
|
+
* OAuth credentials file path (compatible with Gemini CLI)
|
|
25
|
+
*/
|
|
26
|
+
export declare const OAUTH_CREDS_PATH: string;
|
|
27
|
+
/**
|
|
28
|
+
* Google accounts file path (for multi-account support)
|
|
29
|
+
*/
|
|
30
|
+
export declare const GOOGLE_ACCOUNTS_PATH: string;
|
|
31
|
+
/**
|
|
32
|
+
* Plugin storage directory
|
|
33
|
+
*/
|
|
34
|
+
export declare const PLUGIN_STORAGE_DIR: string;
|
|
35
|
+
/**
|
|
36
|
+
* Account pool storage file
|
|
37
|
+
*/
|
|
38
|
+
export declare const ACCOUNT_POOL_PATH: string;
|
|
39
|
+
/**
|
|
40
|
+
* Generative Language API endpoint
|
|
41
|
+
*/
|
|
42
|
+
export declare const GEMINI_API_BASE = "https://generativelanguage.googleapis.com";
|
|
43
|
+
/**
|
|
44
|
+
* Token expiry buffer (refresh 5 minutes before expiry)
|
|
45
|
+
*/
|
|
46
|
+
export declare const TOKEN_EXPIRY_BUFFER_MS: number;
|
|
47
|
+
/**
|
|
48
|
+
* Rate limit retry delay (milliseconds)
|
|
49
|
+
*/
|
|
50
|
+
export declare const RATE_LIMIT_RETRY_DELAY_MS = 2000;
|
|
51
|
+
/**
|
|
52
|
+
* Maximum retry attempts for token refresh
|
|
53
|
+
*/
|
|
54
|
+
export declare const MAX_REFRESH_RETRIES = 3;
|
|
55
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,6EAA6E,CAAC;AAC1G,eAAO,MAAM,mBAAmB,wCAAwC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,YAAY,UAIxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,QAAqC,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAA4C,CAAC;AAE1E;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAgD,CAAC;AAElF;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAqD,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,eAAe,8CAA8C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,sBAAsB,QAAgB,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
/**
|
|
9
|
+
* OAuth2 Client credentials from Gemini CLI
|
|
10
|
+
* Source: @google/gemini-cli-core/dist/src/code_assist/oauth2.js
|
|
11
|
+
*
|
|
12
|
+
* These credentials are safe to embed as this is an "installed application"
|
|
13
|
+
* per Google OAuth2 guidelines: https://developers.google.com/identity/protocols/oauth2#installed
|
|
14
|
+
*/
|
|
15
|
+
export const OAUTH_CLIENT_ID = '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
|
|
16
|
+
export const OAUTH_CLIENT_SECRET = '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';
|
|
17
|
+
/**
|
|
18
|
+
* OAuth scopes required for Gemini API access
|
|
19
|
+
*/
|
|
20
|
+
export const OAUTH_SCOPES = [
|
|
21
|
+
'https://www.googleapis.com/auth/cloud-platform',
|
|
22
|
+
'https://www.googleapis.com/auth/userinfo.email',
|
|
23
|
+
'https://www.googleapis.com/auth/userinfo.profile',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Gemini CLI storage directory
|
|
27
|
+
*/
|
|
28
|
+
export const GEMINI_DIR = path.join(os.homedir(), '.gemini');
|
|
29
|
+
/**
|
|
30
|
+
* OAuth credentials file path (compatible with Gemini CLI)
|
|
31
|
+
*/
|
|
32
|
+
export const OAUTH_CREDS_PATH = path.join(GEMINI_DIR, 'oauth_creds.json');
|
|
33
|
+
/**
|
|
34
|
+
* Google accounts file path (for multi-account support)
|
|
35
|
+
*/
|
|
36
|
+
export const GOOGLE_ACCOUNTS_PATH = path.join(GEMINI_DIR, 'google_accounts.json');
|
|
37
|
+
/**
|
|
38
|
+
* Plugin storage directory
|
|
39
|
+
*/
|
|
40
|
+
export const PLUGIN_STORAGE_DIR = path.join(GEMINI_DIR, 'opencode-plugin');
|
|
41
|
+
/**
|
|
42
|
+
* Account pool storage file
|
|
43
|
+
*/
|
|
44
|
+
export const ACCOUNT_POOL_PATH = path.join(PLUGIN_STORAGE_DIR, 'account_pool.json');
|
|
45
|
+
/**
|
|
46
|
+
* Generative Language API endpoint
|
|
47
|
+
*/
|
|
48
|
+
export const GEMINI_API_BASE = 'https://generativelanguage.googleapis.com';
|
|
49
|
+
/**
|
|
50
|
+
* Token expiry buffer (refresh 5 minutes before expiry)
|
|
51
|
+
*/
|
|
52
|
+
export const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000;
|
|
53
|
+
/**
|
|
54
|
+
* Rate limit retry delay (milliseconds)
|
|
55
|
+
*/
|
|
56
|
+
export const RATE_LIMIT_RETRY_DELAY_MS = 2000;
|
|
57
|
+
/**
|
|
58
|
+
* Maximum retry attempts for token refresh
|
|
59
|
+
*/
|
|
60
|
+
export const MAX_REFRESH_RETRIES = 3;
|
|
61
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,0EAA0E,CAAC;AAC1G,MAAM,CAAC,MAAM,mBAAmB,GAAG,qCAAqC,CAAC;AAEzE;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gDAAgD;IAChD,gDAAgD;IAChD,kDAAkD;CACnD,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAE7D;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAE1E;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAE3E;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAEpF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,2CAA2C,CAAC;AAE3E;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-minimal.d.ts","sourceRoot":"","sources":["../src/index-minimal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-minimal.js","sourceRoot":"","sources":["../src/index-minimal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-simple.d.ts","sourceRoot":"","sources":["../src/index-simple.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-simple.js","sourceRoot":"","sources":["../src/index-simple.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* OpenCode Gemini CLI OAuth Plugin
|
|
8
|
+
*
|
|
9
|
+
* Main entry point for the plugin
|
|
10
|
+
*/
|
|
11
|
+
export { default as GeminiCLIOAuthPlugin, metadata } from './plugin.js';
|
|
12
|
+
export type { OAuthCredentials, GoogleAccount, AccountPoolEntry, AccountPool, PluginConfig, } from './types.js';
|
|
13
|
+
export { OAuthManager } from './auth/oauth.js';
|
|
14
|
+
export { AccountManager } from './auth/account-manager.js';
|
|
15
|
+
export { StorageManager } from './storage/storage.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAGH,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGxE,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* OpenCode Gemini CLI OAuth Plugin
|
|
8
|
+
*
|
|
9
|
+
* Main entry point for the plugin
|
|
10
|
+
*/
|
|
11
|
+
// Named export for OpenCode (following Antigravity pattern)
|
|
12
|
+
export { default as GeminiCLIOAuthPlugin, metadata } from './plugin.js';
|
|
13
|
+
// Export utilities for advanced usage
|
|
14
|
+
export { OAuthManager } from './auth/oauth.js';
|
|
15
|
+
export { AccountManager } from './auth/account-manager.js';
|
|
16
|
+
export { StorageManager } from './storage/storage.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,4DAA4D;AAC5D,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAWxE,sCAAsC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal test - just to see if plugin structure is correct
|
|
3
|
+
*/
|
|
4
|
+
export declare const GeminiCLIOAuthPlugin: ({ client, directory }: any) => Promise<{
|
|
5
|
+
auth: {
|
|
6
|
+
provider: string;
|
|
7
|
+
loader: (getAuth: any, provider: string) => Promise<{
|
|
8
|
+
apiKey?: undefined;
|
|
9
|
+
fetch?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
apiKey: string;
|
|
12
|
+
fetch: typeof fetch;
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
15
|
+
}>;
|
|
16
|
+
export declare const metadata: {
|
|
17
|
+
name: string;
|
|
18
|
+
version: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=plugin-minimal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-minimal.d.ts","sourceRoot":"","sources":["../src/plugin-minimal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,oBAAoB,GAAU,uBAAuB,GAAG;;;0BAMvC,GAAG,YAAY,MAAM;;;;;;;;EAclD,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;CAIpB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal test - just to see if plugin structure is correct
|
|
3
|
+
*/
|
|
4
|
+
export const GeminiCLIOAuthPlugin = async ({ client, directory }) => {
|
|
5
|
+
console.log('🚀 Minimal Gemini CLI OAuth plugin loading...');
|
|
6
|
+
return {
|
|
7
|
+
auth: {
|
|
8
|
+
provider: 'gemini-cli-oauth',
|
|
9
|
+
loader: async (getAuth, provider) => {
|
|
10
|
+
if (provider !== 'gemini-cli-oauth') {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
console.log(`🔐 Provider: ${provider}`);
|
|
14
|
+
return {
|
|
15
|
+
apiKey: '',
|
|
16
|
+
fetch: fetch, // Just use native fetch for now to test structure
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export const metadata = {
|
|
23
|
+
name: 'opencode-gemini-cli-oauth',
|
|
24
|
+
version: '1.0.2-minimal',
|
|
25
|
+
description: 'Minimal test',
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=plugin-minimal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-minimal.js","sourceRoot":"","sources":["../src/plugin-minimal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAO,EAAE,EAAE;IACvE,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,OAAO;QACL,IAAI,EAAE;YACJ,QAAQ,EAAE,kBAAkB;YAC5B,MAAM,EAAE,KAAK,EAAE,OAAY,EAAE,QAAgB,EAAE,EAAE;gBAC/C,IAAI,QAAQ,KAAK,kBAAkB,EAAE,CAAC;oBACpC,OAAO,EAAE,CAAC;gBACZ,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,EAAE,CAAC,CAAC;gBAExC,OAAO;oBACL,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE,KAAK,EAAE,kDAAkD;iBACjE,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,eAAe;IACxB,WAAW,EAAE,cAAc;CAC5B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Simplified OpenCode Plugin for Gemini CLI OAuth (No Classes)
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* OpenCode plugin export (following Antigravity pattern)
|
|
10
|
+
*/
|
|
11
|
+
export declare const GeminiCLIOAuthPlugin: ({ client, directory }: any) => Promise<{
|
|
12
|
+
auth: {
|
|
13
|
+
provider: string;
|
|
14
|
+
loader: (getAuth: any, provider: string) => Promise<{
|
|
15
|
+
apiKey?: undefined;
|
|
16
|
+
fetch?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
}>;
|
|
23
|
+
export declare const metadata: {
|
|
24
|
+
name: string;
|
|
25
|
+
version: string;
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=plugin-simple.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-simple.d.ts","sourceRoot":"","sources":["../src/plugin-simple.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4EH;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAU,uBAAuB,GAAG;;;0BAcvC,GAAG,YAAY,MAAM;;;;;yBAWtB,WAAW,GAAG,GAAG,SAAS,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;;;EAyBrF,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;CAIpB,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* Simplified OpenCode Plugin for Gemini CLI OAuth (No Classes)
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import { OAuth2Client } from 'google-auth-library';
|
|
12
|
+
const OAUTH_CLIENT_ID = '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
|
|
13
|
+
const OAUTH_CLIENT_SECRET = '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';
|
|
14
|
+
const OAUTH_CREDS_PATH = path.join(os.homedir(), '.gemini/oauth_creds.json');
|
|
15
|
+
/**
|
|
16
|
+
* Get OAuth access token from Gemini CLI credentials
|
|
17
|
+
*/
|
|
18
|
+
async function getAccessToken() {
|
|
19
|
+
try {
|
|
20
|
+
const data = await fs.readFile(OAUTH_CREDS_PATH, 'utf-8');
|
|
21
|
+
const credentials = JSON.parse(data);
|
|
22
|
+
// Check if token needs refresh
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
const expiryTime = credentials.expiry_date || 0;
|
|
25
|
+
const needsRefresh = expiryTime - now < 5 * 60 * 1000; // 5 min buffer
|
|
26
|
+
if (needsRefresh && credentials.refresh_token) {
|
|
27
|
+
// Refresh token
|
|
28
|
+
const client = new OAuth2Client(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET);
|
|
29
|
+
client.setCredentials({ refresh_token: credentials.refresh_token });
|
|
30
|
+
const { credentials: refreshed } = await client.refreshAccessToken();
|
|
31
|
+
if (refreshed.access_token) {
|
|
32
|
+
// Update stored credentials
|
|
33
|
+
credentials.access_token = refreshed.access_token;
|
|
34
|
+
credentials.expiry_date = refreshed.expiry_date || Date.now() + 3600 * 1000;
|
|
35
|
+
await fs.writeFile(OAUTH_CREDS_PATH, JSON.stringify(credentials, null, 2), 'utf-8');
|
|
36
|
+
return refreshed.access_token;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return credentials.access_token;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(`Failed to get OAuth token: ${error instanceof Error ? error.message : String(error)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create authenticated fetch with OAuth token injection
|
|
47
|
+
*/
|
|
48
|
+
function createAuthFetch() {
|
|
49
|
+
return async function (input, init) {
|
|
50
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
51
|
+
// Only intercept Gemini API requests
|
|
52
|
+
if (!url.includes('generativelanguage.googleapis.com')) {
|
|
53
|
+
return fetch(input, init);
|
|
54
|
+
}
|
|
55
|
+
// Get OAuth token
|
|
56
|
+
const token = await getAccessToken();
|
|
57
|
+
// Inject Authorization header
|
|
58
|
+
const headers = new Headers(init?.headers);
|
|
59
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
60
|
+
// Remove API key from URL if present
|
|
61
|
+
const urlObj = new URL(url);
|
|
62
|
+
urlObj.searchParams.delete('key');
|
|
63
|
+
return fetch(urlObj.toString(), { ...init, headers });
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* OpenCode plugin export (following Antigravity pattern)
|
|
68
|
+
*/
|
|
69
|
+
export const GeminiCLIOAuthPlugin = async ({ client, directory }) => {
|
|
70
|
+
console.log('🚀 Loading Gemini CLI OAuth plugin...');
|
|
71
|
+
// Verify credentials exist
|
|
72
|
+
try {
|
|
73
|
+
await fs.access(OAUTH_CREDS_PATH);
|
|
74
|
+
console.log('✅ OAuth credentials found');
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.warn('⚠️ No OAuth credentials. Run: gemini auth login');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
auth: {
|
|
81
|
+
provider: 'gemini-cli-oauth',
|
|
82
|
+
loader: async (getAuth, provider) => {
|
|
83
|
+
// Only intercept for our provider
|
|
84
|
+
if (provider !== 'gemini-cli-oauth') {
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
console.log(`🔐 Gemini CLI OAuth: Active for provider ${provider}`);
|
|
88
|
+
// Return object with apiKey and fetch function (Antigravity pattern)
|
|
89
|
+
return {
|
|
90
|
+
apiKey: '',
|
|
91
|
+
async fetch(input, init) {
|
|
92
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
93
|
+
// Pass through non-Gemini API requests
|
|
94
|
+
if (!url.includes('generativelanguage.googleapis.com')) {
|
|
95
|
+
return fetch(input, init);
|
|
96
|
+
}
|
|
97
|
+
// Get OAuth token
|
|
98
|
+
const token = await getAccessToken();
|
|
99
|
+
// Inject Authorization header
|
|
100
|
+
const headers = new Headers(init?.headers);
|
|
101
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
102
|
+
// Remove API key from URL if present
|
|
103
|
+
const urlObj = new URL(url);
|
|
104
|
+
urlObj.searchParams.delete('key');
|
|
105
|
+
return fetch(urlObj.toString(), { ...init, headers });
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
export const metadata = {
|
|
113
|
+
name: 'opencode-gemini-cli-oauth',
|
|
114
|
+
version: '1.0.1-simplified',
|
|
115
|
+
description: 'Simplified Gemini CLI OAuth plugin',
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=plugin-simple.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-simple.js","sourceRoot":"","sources":["../src/plugin-simple.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* OpenCode Plugin for Gemini CLI OAuth Authentication
|
|
7
|
+
*
|
|
8
|
+
* This plugin enables OpenCode to use Google account OAuth credentials
|
|
9
|
+
* from Gemini CLI, allowing access to Gemini models without API keys.
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Reuses Gemini CLI OAuth credentials (~/.gemini/oauth_creds.json)
|
|
13
|
+
* - Multi-account support with automatic rotation
|
|
14
|
+
* - Automatic token refresh
|
|
15
|
+
* - Rate limit handling with account switching
|
|
16
|
+
* - Compatible with existing Antigravity plugin
|
|
17
|
+
*/
|
|
18
|
+
import type { PluginContext, AuthLoader } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* OpenCode plugin export
|
|
21
|
+
*/
|
|
22
|
+
export default function GeminiCLIOAuthPlugin({ client, directory }: PluginContext): Promise<{
|
|
23
|
+
auth: {
|
|
24
|
+
/**
|
|
25
|
+
* Auth provider for "gemini-cli-oauth" provider
|
|
26
|
+
*/
|
|
27
|
+
provider: string;
|
|
28
|
+
/**
|
|
29
|
+
* Auth loader - returns fetch function with OAuth token injection
|
|
30
|
+
*/
|
|
31
|
+
loader: AuthLoader;
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Plugin metadata
|
|
36
|
+
*/
|
|
37
|
+
export declare const metadata: {
|
|
38
|
+
name: string;
|
|
39
|
+
version: string;
|
|
40
|
+
description: string;
|
|
41
|
+
author: string;
|
|
42
|
+
compatibleWith: {
|
|
43
|
+
opencode: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5D;;GAEG;AACH,wBAA8B,oBAAoB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,aAAa;;QAUjF;;WAEG;;QAGH;;WAEG;gBAiBG,UAAU;;GAGrB;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;;;;CAQpB,CAAC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Yusuf
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*
|
|
6
|
+
* OpenCode Plugin for Gemini CLI OAuth Authentication
|
|
7
|
+
*
|
|
8
|
+
* This plugin enables OpenCode to use Google account OAuth credentials
|
|
9
|
+
* from Gemini CLI, allowing access to Gemini models without API keys.
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Reuses Gemini CLI OAuth credentials (~/.gemini/oauth_creds.json)
|
|
13
|
+
* - Multi-account support with automatic rotation
|
|
14
|
+
* - Automatic token refresh
|
|
15
|
+
* - Rate limit handling with account switching
|
|
16
|
+
* - Compatible with existing Antigravity plugin
|
|
17
|
+
*/
|
|
18
|
+
import { createRequestInterceptor } from './auth/request-interceptor.js';
|
|
19
|
+
/**
|
|
20
|
+
* OpenCode plugin export
|
|
21
|
+
*/
|
|
22
|
+
export default async function GeminiCLIOAuthPlugin({ client, directory }) {
|
|
23
|
+
console.log('🚀 Loading Gemini CLI OAuth plugin...');
|
|
24
|
+
// Create request interceptor with OAuth token injection
|
|
25
|
+
const interceptor = await createRequestInterceptor();
|
|
26
|
+
console.log('✅ Gemini CLI OAuth plugin loaded successfully');
|
|
27
|
+
return {
|
|
28
|
+
auth: {
|
|
29
|
+
/**
|
|
30
|
+
* Auth provider for "gemini-cli-oauth" provider
|
|
31
|
+
*/
|
|
32
|
+
provider: 'gemini-cli-oauth',
|
|
33
|
+
/**
|
|
34
|
+
* Auth loader - returns fetch function with OAuth token injection
|
|
35
|
+
*/
|
|
36
|
+
loader: (async (getAuth, provider) => {
|
|
37
|
+
// Only intercept requests for "gemini-cli-oauth" provider
|
|
38
|
+
if (provider !== 'gemini-cli-oauth') {
|
|
39
|
+
return {
|
|
40
|
+
apiKey: '',
|
|
41
|
+
fetch: fetch,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
// Dummy API key (OAuth doesn't need it)
|
|
46
|
+
apiKey: 'gemini-cli-oauth',
|
|
47
|
+
// Custom fetch with OAuth token injection
|
|
48
|
+
fetch: interceptor.fetch,
|
|
49
|
+
};
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Plugin metadata
|
|
56
|
+
*/
|
|
57
|
+
export const metadata = {
|
|
58
|
+
name: 'opencode-gemini-cli-oauth',
|
|
59
|
+
version: '1.0.0',
|
|
60
|
+
description: 'Use Gemini CLI OAuth credentials in OpenCode',
|
|
61
|
+
author: 'Yusuf',
|
|
62
|
+
compatibleWith: {
|
|
63
|
+
opencode: '^1.0.0',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE;;GAEG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,oBAAoB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAiB;IACrF,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,wDAAwD;IACxD,MAAM,WAAW,GAAG,MAAM,wBAAwB,EAAE,CAAC;IAErD,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,OAAO;QACL,IAAI,EAAE;YACJ;;eAEG;YACH,QAAQ,EAAE,kBAAkB;YAE5B;;eAEG;YACH,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;gBACnC,0DAA0D;gBAC1D,IAAI,QAAQ,KAAK,kBAAkB,EAAE,CAAC;oBACpC,OAAO;wBACL,MAAM,EAAE,EAAE;wBACV,KAAK,EAAE,KAAK;qBACb,CAAC;gBACJ,CAAC;gBAED,OAAO;oBACL,wCAAwC;oBACxC,MAAM,EAAE,kBAAkB;oBAE1B,0CAA0C;oBAC1C,KAAK,EAAE,WAAW,CAAC,KAAK;iBACzB,CAAC;YACJ,CAAC,CAAe;SACjB;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,8CAA8C;IAC3D,MAAM,EAAE,OAAO;IACf,cAAc,EAAE;QACd,QAAQ,EAAE,QAAQ;KACnB;CACF,CAAC"}
|