opencode-gemini-business 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/CHANGELOG.md +58 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/README.ru.md +311 -0
- package/bin/cli.js +18 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +306 -0
- package/dist/index.js.map +1 -0
- package/dist/src/account-manager.d.ts +58 -0
- package/dist/src/account-manager.d.ts.map +1 -0
- package/dist/src/account-manager.js +190 -0
- package/dist/src/account-manager.js.map +1 -0
- package/dist/src/gemini-business-api.d.ts +67 -0
- package/dist/src/gemini-business-api.d.ts.map +1 -0
- package/dist/src/gemini-business-api.js +302 -0
- package/dist/src/gemini-business-api.js.map +1 -0
- package/dist/src/types.d.ts +104 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +66 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI entry point for opencode-gemini-business
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import('../dist/index.js')
|
|
8
|
+
.then(module => {
|
|
9
|
+
if (module.cli) {
|
|
10
|
+
return module.cli();
|
|
11
|
+
} else {
|
|
12
|
+
throw new Error('CLI function not found in module exports');
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
.catch(error => {
|
|
16
|
+
console.error('Failed to load CLI:', error);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenCode Gemini Business Plugin
|
|
4
|
+
* Multi-account Gemini Business pool with automatic rotation
|
|
5
|
+
*
|
|
6
|
+
* Follows OpenCode plugin patterns from:
|
|
7
|
+
* - opencode-gemini-auth
|
|
8
|
+
* - opencode-openai-codex-auth
|
|
9
|
+
* - opencode-antigravity-auth
|
|
10
|
+
*/
|
|
11
|
+
import { AccountManager } from './src/account-manager.js';
|
|
12
|
+
import { GeminiBusinessAPI } from './src/gemini-business-api.js';
|
|
13
|
+
/**
|
|
14
|
+
* OpenCode Plugin Entry Point
|
|
15
|
+
*
|
|
16
|
+
* This plugin doesn't use traditional OAuth - it uses cookie-based auth
|
|
17
|
+
* with Gemini Business accounts configured via CLI.
|
|
18
|
+
*/
|
|
19
|
+
export declare const GeminiBusinessPlugin: (ctx: any) => Promise<{
|
|
20
|
+
auth: {
|
|
21
|
+
provider: string;
|
|
22
|
+
/**
|
|
23
|
+
* Loader function - called by OpenCode to initialize the provider
|
|
24
|
+
*/
|
|
25
|
+
loader(getAuth: any, provider: any): Promise<{
|
|
26
|
+
accountCount?: undefined;
|
|
27
|
+
strategy?: undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Custom fetch implementation for Gemini Business API
|
|
30
|
+
*
|
|
31
|
+
* This intercepts all OpenCode API calls and routes them through
|
|
32
|
+
* the Gemini Business API with account rotation.
|
|
33
|
+
*/
|
|
34
|
+
fetch?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
accountCount: number;
|
|
37
|
+
strategy: "round-robin" | "least-used" | "random";
|
|
38
|
+
/**
|
|
39
|
+
* Custom fetch implementation for Gemini Business API
|
|
40
|
+
*
|
|
41
|
+
* This intercepts all OpenCode API calls and routes them through
|
|
42
|
+
* the Gemini Business API with account rotation.
|
|
43
|
+
*/
|
|
44
|
+
fetch(input: any, options: any): Promise<any>;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Authentication methods
|
|
48
|
+
*
|
|
49
|
+
* For Gemini Business, we don't support OAuth - accounts are configured
|
|
50
|
+
* via CLI with cookie extraction from browser.
|
|
51
|
+
*/
|
|
52
|
+
methods: {
|
|
53
|
+
type: "cookie";
|
|
54
|
+
label: string;
|
|
55
|
+
authorize: () => Promise<{
|
|
56
|
+
type: "instructions";
|
|
57
|
+
instructions: string;
|
|
58
|
+
}>;
|
|
59
|
+
}[];
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
62
|
+
export default GeminiBusinessPlugin;
|
|
63
|
+
export { AccountManager, GeminiBusinessAPI };
|
|
64
|
+
/**
|
|
65
|
+
* CLI entry point - handles account management commands
|
|
66
|
+
*/
|
|
67
|
+
declare function cli(): Promise<void>;
|
|
68
|
+
export { cli };
|
|
69
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAOjE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAU,KAAK,GAAG;;;QAK7C;;WAEG;wBACmB,GAAG,YAAY,GAAG;;;YA0BpC;;;;;eAKG;;;;;YALH;;;;;eAKG;yBACgB,GAAG,WAAW,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;;QAsDvD;;;;;WAKG;;;;;;;;;;EAyBR,CAAC;AAGF,eAAe,oBAAoB,CAAC;AAGpC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC;AAM7C;;GAEG;AACH,iBAAe,GAAG,kBAkCjB;AAsJD,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenCode Gemini Business Plugin
|
|
4
|
+
* Multi-account Gemini Business pool with automatic rotation
|
|
5
|
+
*
|
|
6
|
+
* Follows OpenCode plugin patterns from:
|
|
7
|
+
* - opencode-gemini-auth
|
|
8
|
+
* - opencode-openai-codex-auth
|
|
9
|
+
* - opencode-antigravity-auth
|
|
10
|
+
*/
|
|
11
|
+
import { AccountManager } from './src/account-manager.js';
|
|
12
|
+
import { GeminiBusinessAPI } from './src/gemini-business-api.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// OpenCode Plugin Export
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* OpenCode Plugin Entry Point
|
|
18
|
+
*
|
|
19
|
+
* This plugin doesn't use traditional OAuth - it uses cookie-based auth
|
|
20
|
+
* with Gemini Business accounts configured via CLI.
|
|
21
|
+
*/
|
|
22
|
+
export const GeminiBusinessPlugin = async (ctx) => {
|
|
23
|
+
return {
|
|
24
|
+
auth: {
|
|
25
|
+
provider: 'gemini-business',
|
|
26
|
+
/**
|
|
27
|
+
* Loader function - called by OpenCode to initialize the provider
|
|
28
|
+
*/
|
|
29
|
+
async loader(getAuth, provider) {
|
|
30
|
+
const accountManager = new AccountManager();
|
|
31
|
+
await accountManager.loadAccounts();
|
|
32
|
+
const accounts = accountManager.getAccounts();
|
|
33
|
+
if (accounts.length === 0) {
|
|
34
|
+
console.error('\n❌ No Gemini Business accounts configured!\n' +
|
|
35
|
+
'\nTo add an account, run:\n' +
|
|
36
|
+
' opencode-gemini-business add-account\n' +
|
|
37
|
+
'\nFor help, run:\n' +
|
|
38
|
+
' opencode-gemini-business help\n');
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
console.log(`\n✅ Gemini Business: Loaded ${accounts.length} account(s)\n` +
|
|
42
|
+
` Strategy: ${accountManager.getConfig().rotation_strategy}\n`);
|
|
43
|
+
return {
|
|
44
|
+
// Return empty config - we handle everything in custom fetch
|
|
45
|
+
accountCount: accounts.length,
|
|
46
|
+
strategy: accountManager.getConfig().rotation_strategy,
|
|
47
|
+
/**
|
|
48
|
+
* Custom fetch implementation for Gemini Business API
|
|
49
|
+
*
|
|
50
|
+
* This intercepts all OpenCode API calls and routes them through
|
|
51
|
+
* the Gemini Business API with account rotation.
|
|
52
|
+
*/
|
|
53
|
+
async fetch(input, options) {
|
|
54
|
+
try {
|
|
55
|
+
// Get next available account based on rotation strategy
|
|
56
|
+
const account = accountManager.getNextAccount();
|
|
57
|
+
if (!account) {
|
|
58
|
+
throw new Error('No available accounts');
|
|
59
|
+
}
|
|
60
|
+
// Create API client for this account
|
|
61
|
+
const api = new GeminiBusinessAPI(account);
|
|
62
|
+
// Refresh session if needed
|
|
63
|
+
if (api.needsSessionRefresh()) {
|
|
64
|
+
console.log(` ⟳ Refreshing session for: ${account.name}`);
|
|
65
|
+
await api.refreshSession();
|
|
66
|
+
await accountManager.updateSession(account.id, account.session_id, 50 * 60 * 1000 // 50 minutes
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
// Parse request body
|
|
70
|
+
const requestBody = options?.body ? JSON.parse(options.body) : {};
|
|
71
|
+
// Make API call
|
|
72
|
+
const response = await api.chatCompletion(requestBody);
|
|
73
|
+
// Success! Reset error count
|
|
74
|
+
accountManager.resetAccountErrors(account.id);
|
|
75
|
+
// Convert to Response object for OpenCode
|
|
76
|
+
return new Response(JSON.stringify(response), {
|
|
77
|
+
status: 200,
|
|
78
|
+
headers: {
|
|
79
|
+
'Content-Type': 'application/json',
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
85
|
+
// Mark account error
|
|
86
|
+
const account = accountManager.getNextAccount();
|
|
87
|
+
if (account) {
|
|
88
|
+
accountManager.markAccountError(account.id, errorMessage);
|
|
89
|
+
}
|
|
90
|
+
// Rethrow for OpenCode to handle
|
|
91
|
+
throw new Error(`Gemini Business API Error: ${errorMessage}`);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
/**
|
|
97
|
+
* Authentication methods
|
|
98
|
+
*
|
|
99
|
+
* For Gemini Business, we don't support OAuth - accounts are configured
|
|
100
|
+
* via CLI with cookie extraction from browser.
|
|
101
|
+
*/
|
|
102
|
+
methods: [
|
|
103
|
+
{
|
|
104
|
+
type: 'cookie',
|
|
105
|
+
label: 'Gemini Business Cookie Auth',
|
|
106
|
+
authorize: async () => ({
|
|
107
|
+
type: 'instructions',
|
|
108
|
+
instructions: '📋 To configure Gemini Business accounts:\n\n' +
|
|
109
|
+
'1. Login to https://business.gemini.google\n' +
|
|
110
|
+
'2. Open DevTools (F12) → Network tab\n' +
|
|
111
|
+
'3. Make any API request (refresh page or send a prompt)\n' +
|
|
112
|
+
'4. Find request headers and copy:\n' +
|
|
113
|
+
' • team_id (from X-Goog-Team-Id header)\n' +
|
|
114
|
+
' • __Secure-c_ses cookie\n' +
|
|
115
|
+
' • __Host-c_oses cookie\n' +
|
|
116
|
+
' • csesidx value\n\n' +
|
|
117
|
+
'5. Run: opencode-gemini-business add-account\n' +
|
|
118
|
+
' Or use environment variables (see docs)\n\n' +
|
|
119
|
+
'For more help: opencode-gemini-business help',
|
|
120
|
+
}),
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
// Export as default for CommonJS compatibility
|
|
127
|
+
export default GeminiBusinessPlugin;
|
|
128
|
+
// Export legacy functions for backward compatibility (if needed)
|
|
129
|
+
export { AccountManager, GeminiBusinessAPI };
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// CLI Commands
|
|
132
|
+
// ============================================================================
|
|
133
|
+
/**
|
|
134
|
+
* CLI entry point - handles account management commands
|
|
135
|
+
*/
|
|
136
|
+
async function cli() {
|
|
137
|
+
const args = process.argv.slice(2);
|
|
138
|
+
const command = args[0];
|
|
139
|
+
const accountManager = new AccountManager();
|
|
140
|
+
try {
|
|
141
|
+
await accountManager.loadAccounts();
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Config file might not exist yet - that's ok
|
|
145
|
+
}
|
|
146
|
+
switch (command) {
|
|
147
|
+
case 'add-account':
|
|
148
|
+
await addAccountCommand(accountManager, args.slice(1));
|
|
149
|
+
break;
|
|
150
|
+
case 'list-accounts':
|
|
151
|
+
await listAccountsCommand(accountManager);
|
|
152
|
+
break;
|
|
153
|
+
case 'remove-account':
|
|
154
|
+
await removeAccountCommand(accountManager, args[1]);
|
|
155
|
+
break;
|
|
156
|
+
case 'test-account':
|
|
157
|
+
await testAccountCommand(accountManager, args[1]);
|
|
158
|
+
break;
|
|
159
|
+
case 'help':
|
|
160
|
+
default:
|
|
161
|
+
printHelp();
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Add account command
|
|
167
|
+
*/
|
|
168
|
+
async function addAccountCommand(manager, args) {
|
|
169
|
+
console.log('Add Gemini Business Account');
|
|
170
|
+
console.log('----------------------------');
|
|
171
|
+
// Read from command line args or env vars
|
|
172
|
+
const account = {
|
|
173
|
+
name: args[0] || process.env.GEMINI_ACCOUNT_NAME || `account-${Date.now()}`,
|
|
174
|
+
team_id: args[1] || process.env.GEMINI_TEAM_ID || '',
|
|
175
|
+
cookies: {
|
|
176
|
+
secure_c_ses: args[2] || process.env.GEMINI_SECURE_C_SES || '',
|
|
177
|
+
host_c_oses: args[3] || process.env.GEMINI_HOST_C_OSES || '',
|
|
178
|
+
},
|
|
179
|
+
csesidx: args[4] || process.env.GEMINI_CSESIDX || '',
|
|
180
|
+
user_agent: args[5] || process.env.GEMINI_USER_AGENT,
|
|
181
|
+
enabled: true,
|
|
182
|
+
};
|
|
183
|
+
// Validate required fields
|
|
184
|
+
if (!account.team_id || !account.cookies.secure_c_ses || !account.cookies.host_c_oses || !account.csesidx) {
|
|
185
|
+
console.error('Error: Missing required fields!');
|
|
186
|
+
console.error('\nUsage:');
|
|
187
|
+
console.error(' opencode-gemini-business add-account <name> <team_id> <secure_c_ses> <host_c_oses> <csesidx> [user_agent]');
|
|
188
|
+
console.error('\nOr set environment variables:');
|
|
189
|
+
console.error(' GEMINI_ACCOUNT_NAME, GEMINI_TEAM_ID, GEMINI_SECURE_C_SES, GEMINI_HOST_C_OSES, GEMINI_CSESIDX, GEMINI_USER_AGENT');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
const id = await manager.addAccount(account);
|
|
193
|
+
console.log(`✅ Account added successfully! ID: ${id}`);
|
|
194
|
+
console.log(` Name: ${account.name}`);
|
|
195
|
+
console.log(` Team ID: ${account.team_id}`);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* List accounts command
|
|
199
|
+
*/
|
|
200
|
+
async function listAccountsCommand(manager) {
|
|
201
|
+
const accounts = manager.getAccounts();
|
|
202
|
+
if (accounts.length === 0) {
|
|
203
|
+
console.log('No accounts configured.');
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
console.log(`Found ${accounts.length} account(s):\n`);
|
|
207
|
+
accounts.forEach((account, index) => {
|
|
208
|
+
console.log(`[${index + 1}] ${account.name} (${account.id})`);
|
|
209
|
+
console.log(` Team ID: ${account.team_id}`);
|
|
210
|
+
console.log(` Status: ${account.enabled ? '✅ Enabled' : '❌ Disabled'}`);
|
|
211
|
+
console.log(` Errors: ${account.error_count || 0}`);
|
|
212
|
+
if (account.last_error) {
|
|
213
|
+
console.log(` Last Error: ${account.last_error}`);
|
|
214
|
+
}
|
|
215
|
+
if (account.last_used) {
|
|
216
|
+
const lastUsed = new Date(account.last_used);
|
|
217
|
+
console.log(` Last Used: ${lastUsed.toISOString()}`);
|
|
218
|
+
}
|
|
219
|
+
console.log('');
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Remove account command
|
|
224
|
+
*/
|
|
225
|
+
async function removeAccountCommand(manager, accountId) {
|
|
226
|
+
if (!accountId) {
|
|
227
|
+
console.error('Error: Account ID required');
|
|
228
|
+
console.error('Usage: opencode-gemini-business remove-account <account_id>');
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
const removed = await manager.removeAccount(accountId);
|
|
232
|
+
if (removed) {
|
|
233
|
+
console.log(`✅ Account ${accountId} removed successfully`);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
console.error(`❌ Account ${accountId} not found`);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Test account command
|
|
242
|
+
*/
|
|
243
|
+
async function testAccountCommand(manager, accountId) {
|
|
244
|
+
if (!accountId) {
|
|
245
|
+
console.error('Error: Account ID required');
|
|
246
|
+
console.error('Usage: opencode-gemini-business test-account <account_id>');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
const accounts = manager.getAccounts();
|
|
250
|
+
const account = accounts.find(acc => acc.id === accountId);
|
|
251
|
+
if (!account) {
|
|
252
|
+
console.error(`❌ Account ${accountId} not found`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
console.log(`Testing account: ${account.name} (${account.id})`);
|
|
256
|
+
console.log('Please wait...\n');
|
|
257
|
+
const api = new GeminiBusinessAPI(account);
|
|
258
|
+
const result = await api.testAccount();
|
|
259
|
+
if (result.success) {
|
|
260
|
+
console.log('✅ Account test successful!');
|
|
261
|
+
console.log(' XSRF Token: OK');
|
|
262
|
+
console.log(' Session: OK');
|
|
263
|
+
console.log(' Authentication: OK');
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
console.log('❌ Account test failed!');
|
|
267
|
+
console.log(` Error: ${result.error}`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Print help
|
|
273
|
+
*/
|
|
274
|
+
function printHelp() {
|
|
275
|
+
console.log('OpenCode Gemini Business Plugin');
|
|
276
|
+
console.log('================================\n');
|
|
277
|
+
console.log('Multi-account Gemini Business pool with automatic rotation\n');
|
|
278
|
+
console.log('Commands:');
|
|
279
|
+
console.log(' add-account <name> <team_id> <secure_c_ses> <host_c_oses> <csesidx> [user_agent]');
|
|
280
|
+
console.log(' Add a new Gemini Business account\n');
|
|
281
|
+
console.log(' list-accounts');
|
|
282
|
+
console.log(' List all configured accounts\n');
|
|
283
|
+
console.log(' remove-account <account_id>');
|
|
284
|
+
console.log(' Remove an account\n');
|
|
285
|
+
console.log(' test-account <account_id>');
|
|
286
|
+
console.log(' Test account credentials\n');
|
|
287
|
+
console.log(' help');
|
|
288
|
+
console.log(' Show this help message\n');
|
|
289
|
+
console.log('Environment Variables:');
|
|
290
|
+
console.log(' GEMINI_ACCOUNT_NAME - Account name');
|
|
291
|
+
console.log(' GEMINI_TEAM_ID - Team ID');
|
|
292
|
+
console.log(' GEMINI_SECURE_C_SES - __Secure-c_ses cookie');
|
|
293
|
+
console.log(' GEMINI_HOST_C_OSES - __Host-c_oses cookie');
|
|
294
|
+
console.log(' GEMINI_CSESIDX - csesidx value');
|
|
295
|
+
console.log(' GEMINI_USER_AGENT - Custom user agent (optional)\n');
|
|
296
|
+
}
|
|
297
|
+
// Export CLI function
|
|
298
|
+
export { cli };
|
|
299
|
+
// Run CLI if executed directly
|
|
300
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
301
|
+
cli().catch(error => {
|
|
302
|
+
console.error('Error:', error.message);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Manager for multi-account rotation
|
|
3
|
+
*/
|
|
4
|
+
import { GeminiBusinessAccount, PoolConfig } from './types.js';
|
|
5
|
+
export declare class AccountManager {
|
|
6
|
+
private config;
|
|
7
|
+
private currentIndex;
|
|
8
|
+
constructor(config?: Partial<PoolConfig>);
|
|
9
|
+
/**
|
|
10
|
+
* Load accounts from config file
|
|
11
|
+
*/
|
|
12
|
+
loadAccounts(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Save accounts to config file
|
|
15
|
+
*/
|
|
16
|
+
saveAccounts(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Add a new account
|
|
19
|
+
*/
|
|
20
|
+
addAccount(account: Omit<GeminiBusinessAccount, 'id'>): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Remove an account
|
|
23
|
+
*/
|
|
24
|
+
removeAccount(id: string): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Get next available account based on rotation strategy
|
|
27
|
+
*/
|
|
28
|
+
getNextAccount(): GeminiBusinessAccount | null;
|
|
29
|
+
/**
|
|
30
|
+
* Mark account as failed
|
|
31
|
+
*/
|
|
32
|
+
markAccountError(accountId: string, error: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Reset account errors (e.g., after successful request)
|
|
35
|
+
*/
|
|
36
|
+
resetAccountErrors(accountId: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Check if session needs refresh
|
|
39
|
+
*/
|
|
40
|
+
needsSessionRefresh(account: GeminiBusinessAccount): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Update account session
|
|
43
|
+
*/
|
|
44
|
+
updateSession(accountId: string, sessionId: string, expiresIn: number): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Update XSRF token
|
|
47
|
+
*/
|
|
48
|
+
updateXSRFToken(accountId: string, token: string, expiresIn: number): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Get all accounts
|
|
51
|
+
*/
|
|
52
|
+
getAccounts(): GeminiBusinessAccount[];
|
|
53
|
+
/**
|
|
54
|
+
* Get config
|
|
55
|
+
*/
|
|
56
|
+
getConfig(): PoolConfig;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=account-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-manager.d.ts","sourceRoot":"","sources":["../../src/account-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAS/D,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAa;gBAErB,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;IAYxC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBnC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAWnC;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAc7E;;OAEG;IACG,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASjD;;OAEG;IACH,cAAc,IAAI,qBAAqB,GAAG,IAAI;IAqC9C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAcxD;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQ3C;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO;IAS5D;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3F;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASzF;;OAEG;IACH,WAAW,IAAI,qBAAqB,EAAE;IAItC;;OAEG;IACH,SAAS,IAAI,UAAU;CAGxB"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Manager for multi-account rotation
|
|
3
|
+
*/
|
|
4
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
const CONFIG_DIR = join(homedir(), '.config', 'opencode');
|
|
9
|
+
const ACCOUNTS_FILE = join(CONFIG_DIR, 'gemini-business-accounts.json');
|
|
10
|
+
export class AccountManager {
|
|
11
|
+
config;
|
|
12
|
+
currentIndex = 0;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = {
|
|
15
|
+
accounts: [],
|
|
16
|
+
rotation_strategy: 'round-robin',
|
|
17
|
+
max_retries: 3,
|
|
18
|
+
retry_delay: 1000,
|
|
19
|
+
session_refresh_threshold: 300, // 5 minutes
|
|
20
|
+
error_threshold: 3,
|
|
21
|
+
...config,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load accounts from config file
|
|
26
|
+
*/
|
|
27
|
+
async loadAccounts() {
|
|
28
|
+
if (!existsSync(ACCOUNTS_FILE)) {
|
|
29
|
+
console.warn(`No accounts file found at ${ACCOUNTS_FILE}`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const data = await readFile(ACCOUNTS_FILE, 'utf-8');
|
|
34
|
+
const saved = JSON.parse(data);
|
|
35
|
+
this.config.accounts = saved.accounts || [];
|
|
36
|
+
// Merge other config options if they exist
|
|
37
|
+
if (saved.rotation_strategy)
|
|
38
|
+
this.config.rotation_strategy = saved.rotation_strategy;
|
|
39
|
+
if (saved.max_retries !== undefined)
|
|
40
|
+
this.config.max_retries = saved.max_retries;
|
|
41
|
+
console.log(`Loaded ${this.config.accounts.length} accounts`);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error('Failed to load accounts:', error);
|
|
45
|
+
throw new Error(`Failed to load accounts: ${error}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Save accounts to config file
|
|
50
|
+
*/
|
|
51
|
+
async saveAccounts() {
|
|
52
|
+
try {
|
|
53
|
+
const data = JSON.stringify(this.config, null, 2);
|
|
54
|
+
await writeFile(ACCOUNTS_FILE, data, 'utf-8');
|
|
55
|
+
console.log(`Saved ${this.config.accounts.length} accounts to ${ACCOUNTS_FILE}`);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error('Failed to save accounts:', error);
|
|
59
|
+
throw new Error(`Failed to save accounts: ${error}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Add a new account
|
|
64
|
+
*/
|
|
65
|
+
async addAccount(account) {
|
|
66
|
+
const id = `account-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
67
|
+
const newAccount = {
|
|
68
|
+
...account,
|
|
69
|
+
id,
|
|
70
|
+
enabled: true,
|
|
71
|
+
error_count: 0,
|
|
72
|
+
};
|
|
73
|
+
this.config.accounts.push(newAccount);
|
|
74
|
+
await this.saveAccounts();
|
|
75
|
+
return id;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Remove an account
|
|
79
|
+
*/
|
|
80
|
+
async removeAccount(id) {
|
|
81
|
+
const index = this.config.accounts.findIndex(acc => acc.id === id);
|
|
82
|
+
if (index === -1)
|
|
83
|
+
return false;
|
|
84
|
+
this.config.accounts.splice(index, 1);
|
|
85
|
+
await this.saveAccounts();
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get next available account based on rotation strategy
|
|
90
|
+
*/
|
|
91
|
+
getNextAccount() {
|
|
92
|
+
const enabledAccounts = this.config.accounts.filter(acc => acc.enabled);
|
|
93
|
+
if (enabledAccounts.length === 0) {
|
|
94
|
+
console.error('No enabled accounts available');
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let account;
|
|
98
|
+
switch (this.config.rotation_strategy) {
|
|
99
|
+
case 'round-robin':
|
|
100
|
+
account = enabledAccounts[this.currentIndex % enabledAccounts.length];
|
|
101
|
+
this.currentIndex++;
|
|
102
|
+
break;
|
|
103
|
+
case 'least-used':
|
|
104
|
+
account = enabledAccounts.reduce((least, current) => {
|
|
105
|
+
const leastUsed = least.last_used || 0;
|
|
106
|
+
const currentUsed = current.last_used || 0;
|
|
107
|
+
return currentUsed < leastUsed ? current : least;
|
|
108
|
+
});
|
|
109
|
+
break;
|
|
110
|
+
case 'random':
|
|
111
|
+
account = enabledAccounts[Math.floor(Math.random() * enabledAccounts.length)];
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
account = enabledAccounts[0];
|
|
115
|
+
}
|
|
116
|
+
// Update last used timestamp
|
|
117
|
+
account.last_used = Date.now();
|
|
118
|
+
return account;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Mark account as failed
|
|
122
|
+
*/
|
|
123
|
+
markAccountError(accountId, error) {
|
|
124
|
+
const account = this.config.accounts.find(acc => acc.id === accountId);
|
|
125
|
+
if (!account)
|
|
126
|
+
return;
|
|
127
|
+
account.error_count = (account.error_count || 0) + 1;
|
|
128
|
+
account.last_error = error;
|
|
129
|
+
// Disable account if error threshold reached
|
|
130
|
+
if (account.error_count >= this.config.error_threshold) {
|
|
131
|
+
account.enabled = false;
|
|
132
|
+
console.warn(`Account ${account.name} (${accountId}) disabled after ${account.error_count} errors`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Reset account errors (e.g., after successful request)
|
|
137
|
+
*/
|
|
138
|
+
resetAccountErrors(accountId) {
|
|
139
|
+
const account = this.config.accounts.find(acc => acc.id === accountId);
|
|
140
|
+
if (!account)
|
|
141
|
+
return;
|
|
142
|
+
account.error_count = 0;
|
|
143
|
+
account.last_error = undefined;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if session needs refresh
|
|
147
|
+
*/
|
|
148
|
+
needsSessionRefresh(account) {
|
|
149
|
+
if (!account.session_id || !account.session_expires)
|
|
150
|
+
return true;
|
|
151
|
+
const now = Date.now();
|
|
152
|
+
const expiresIn = account.session_expires - now;
|
|
153
|
+
return expiresIn < this.config.session_refresh_threshold * 1000;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Update account session
|
|
157
|
+
*/
|
|
158
|
+
async updateSession(accountId, sessionId, expiresIn) {
|
|
159
|
+
const account = this.config.accounts.find(acc => acc.id === accountId);
|
|
160
|
+
if (!account)
|
|
161
|
+
return;
|
|
162
|
+
account.session_id = sessionId;
|
|
163
|
+
account.session_expires = Date.now() + expiresIn;
|
|
164
|
+
await this.saveAccounts();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Update XSRF token
|
|
168
|
+
*/
|
|
169
|
+
async updateXSRFToken(accountId, token, expiresIn) {
|
|
170
|
+
const account = this.config.accounts.find(acc => acc.id === accountId);
|
|
171
|
+
if (!account)
|
|
172
|
+
return;
|
|
173
|
+
account.xsrf_token = token;
|
|
174
|
+
account.xsrf_expires = Date.now() + expiresIn;
|
|
175
|
+
await this.saveAccounts();
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all accounts
|
|
179
|
+
*/
|
|
180
|
+
getAccounts() {
|
|
181
|
+
return this.config.accounts;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get config
|
|
185
|
+
*/
|
|
186
|
+
getConfig() {
|
|
187
|
+
return this.config;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=account-manager.js.map
|