gh-multi 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/README.md +70 -0
- package/gh-multi-dist/constants.d.ts +14 -0
- package/gh-multi-dist/constants.js +16 -0
- package/gh-multi-dist/constants.js.map +1 -0
- package/gh-multi-dist/index.d.ts +4 -0
- package/gh-multi-dist/index.js +110 -0
- package/gh-multi-dist/index.js.map +1 -0
- package/gh-multi-dist/plugin/accounts.d.ts +62 -0
- package/gh-multi-dist/plugin/accounts.js +703 -0
- package/gh-multi-dist/plugin/accounts.js.map +1 -0
- package/gh-multi-dist/plugin/cli.d.ts +19 -0
- package/gh-multi-dist/plugin/cli.js +409 -0
- package/gh-multi-dist/plugin/cli.js.map +1 -0
- package/gh-multi-dist/plugin/config/index.d.ts +2 -0
- package/gh-multi-dist/plugin/config/index.js +3 -0
- package/gh-multi-dist/plugin/config/index.js.map +1 -0
- package/gh-multi-dist/plugin/config/loader.d.ts +3 -0
- package/gh-multi-dist/plugin/config/loader.js +78 -0
- package/gh-multi-dist/plugin/config/loader.js.map +1 -0
- package/gh-multi-dist/plugin/config/schema.d.ts +28 -0
- package/gh-multi-dist/plugin/config/schema.js +10 -0
- package/gh-multi-dist/plugin/config/schema.js.map +1 -0
- package/gh-multi-dist/plugin/device_flow.d.ts +18 -0
- package/gh-multi-dist/plugin/device_flow.js +78 -0
- package/gh-multi-dist/plugin/device_flow.js.map +1 -0
- package/gh-multi-dist/plugin/fetch.d.ts +3 -0
- package/gh-multi-dist/plugin/fetch.js +156 -0
- package/gh-multi-dist/plugin/fetch.js.map +1 -0
- package/gh-multi-dist/plugin/index.d.ts +5 -0
- package/gh-multi-dist/plugin/index.js +6 -0
- package/gh-multi-dist/plugin/index.js.map +1 -0
- package/gh-multi-dist/plugin/logger.d.ts +43 -0
- package/gh-multi-dist/plugin/logger.js +169 -0
- package/gh-multi-dist/plugin/logger.js.map +1 -0
- package/gh-multi-dist/plugin/models.d.ts +2 -0
- package/gh-multi-dist/plugin/models.js +96 -0
- package/gh-multi-dist/plugin/models.js.map +1 -0
- package/gh-multi-dist/plugin/quota.d.ts +11 -0
- package/gh-multi-dist/plugin/quota.js +42 -0
- package/gh-multi-dist/plugin/quota.js.map +1 -0
- package/gh-multi-dist/plugin/token.d.ts +5 -0
- package/gh-multi-dist/plugin/token.js +7 -0
- package/gh-multi-dist/plugin/token.js.map +1 -0
- package/gh-multi-dist/plugin/ui/ansi.d.ts +41 -0
- package/gh-multi-dist/plugin/ui/ansi.js +67 -0
- package/gh-multi-dist/plugin/ui/ansi.js.map +1 -0
- package/gh-multi-dist/plugin/ui/confirm.d.ts +1 -0
- package/gh-multi-dist/plugin/ui/confirm.js +15 -0
- package/gh-multi-dist/plugin/ui/confirm.js.map +1 -0
- package/gh-multi-dist/plugin/ui/select.d.ts +13 -0
- package/gh-multi-dist/plugin/ui/select.js +170 -0
- package/gh-multi-dist/plugin/ui/select.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# gh-multi
|
|
2
|
+
|
|
3
|
+
Multi-account GitHub Copilot plugin for OpenCode that hooks into the native provider or runs standalone.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
This plugin intercepts GitHub Copilot API requests and distributes them across multiple GitHub accounts. It automatically rotates credentials using round-robin or sticky strategies to maximize quota usage. This prevents rate limiting and extends coding sessions when single-account quotas are exhausted.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Node.js 18+
|
|
12
|
+
- OpenCode
|
|
13
|
+
- Multiple GitHub accounts with Copilot access
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
1. Navigate to the plugin directory:
|
|
18
|
+
```bash
|
|
19
|
+
cd ~/.config/opencode/gh-multi
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. Install dependencies:
|
|
23
|
+
```bash
|
|
24
|
+
npm install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
3. Build the plugin:
|
|
28
|
+
```bash
|
|
29
|
+
npm run build
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
The configuration file is located at `~/.config/opencode/copilot.json`.
|
|
35
|
+
|
|
36
|
+
**Example:**
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"logging": {
|
|
41
|
+
"enabled": true,
|
|
42
|
+
"level": "info"
|
|
43
|
+
},
|
|
44
|
+
"rotation_strategy": "round-robin"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
1. Run the OpenCode authentication command:
|
|
51
|
+
```bash
|
|
52
|
+
opencode auth login
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. Select **GitHub Copilot Multi-Account** from the provider list.
|
|
56
|
+
|
|
57
|
+
3. Follow the CLI prompts to authenticate each GitHub account via device flow.
|
|
58
|
+
|
|
59
|
+
4. Once authenticated, the plugin will automatically manage credential rotation during chat sessions.
|
|
60
|
+
|
|
61
|
+
## Logging
|
|
62
|
+
|
|
63
|
+
Logs are written to the `gh-multi_logs` directory within the plugin folder.
|
|
64
|
+
|
|
65
|
+
- **Location**: `~/.config/opencode/gh-multi/gh-multi_logs/gh-multi-{timestamp}.log`
|
|
66
|
+
- **Debug Mode**: Set `"level": "debug"` in `copilot.json` or use the environment variable `GH_MULTI_DEBUG=1`.
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
Proprietary
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const GITHUB_CLIENT_ID = "Ov23li8tweQw6odWQebz";
|
|
2
|
+
export declare const GITHUB_SCOPES = "read:user";
|
|
3
|
+
export declare const GITHUB_AUTH_URL = "https://github.com/login/device/code";
|
|
4
|
+
export declare const GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
5
|
+
export declare const USER_AGENT = "opencode-copilot-auth/0.1.0";
|
|
6
|
+
export declare const OPENCODE_USER_AGENT: string;
|
|
7
|
+
export declare const MAX_HEALTH = 100;
|
|
8
|
+
export declare const INITIAL_HEALTH = 100;
|
|
9
|
+
export declare const MIN_HEALTH_THRESHOLD = 20;
|
|
10
|
+
export declare const DEFAULT_RATE_LIMIT_COOLDOWN: number;
|
|
11
|
+
export declare const MAX_FAILURES_BEFORE_SUSPEND = 10;
|
|
12
|
+
export declare const SESSION_CLEANUP_INTERVAL_MS: number;
|
|
13
|
+
export declare const QUOTA_SYNC_INTERVAL_MS: number;
|
|
14
|
+
export declare const SYNC_EVERY_N_REQUESTS = 10;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const GITHUB_CLIENT_ID = "Ov23li8tweQw6odWQebz";
|
|
2
|
+
export const GITHUB_SCOPES = "read:user";
|
|
3
|
+
export const GITHUB_AUTH_URL = "https://github.com/login/device/code";
|
|
4
|
+
export const GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
5
|
+
export const USER_AGENT = "opencode-copilot-auth/0.1.0";
|
|
6
|
+
const VERSION = process.env.npm_package_version || "0.1.0";
|
|
7
|
+
export const OPENCODE_USER_AGENT = `opencode/${VERSION}`;
|
|
8
|
+
export const MAX_HEALTH = 100;
|
|
9
|
+
export const INITIAL_HEALTH = 100;
|
|
10
|
+
export const MIN_HEALTH_THRESHOLD = 20;
|
|
11
|
+
export const DEFAULT_RATE_LIMIT_COOLDOWN = 5 * 60 * 1000;
|
|
12
|
+
export const MAX_FAILURES_BEFORE_SUSPEND = 10;
|
|
13
|
+
export const SESSION_CLEANUP_INTERVAL_MS = 5 * 60 * 1000;
|
|
14
|
+
export const QUOTA_SYNC_INTERVAL_MS = 2 * 60 * 1000;
|
|
15
|
+
export const SYNC_EVERY_N_REQUESTS = 10;
|
|
16
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,MAAM,CAAC,MAAM,eAAe,GAAG,sCAAsC,CAAC;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,6CAA6C,CAAC;AAE9E,MAAM,CAAC,MAAM,UAAU,GAAG,6BAA6B,CAAC;AAExD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,OAAO,EAAE,CAAC;AAEzD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAC9B,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACzD,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { CopilotAccountManager } from "./plugin/accounts.js";
|
|
2
|
+
import { TokenManager } from "./plugin/token.js";
|
|
3
|
+
import { createMultiAccountFetch } from "./plugin/fetch.js";
|
|
4
|
+
import { loadConfig } from "./plugin/config/loader.js";
|
|
5
|
+
import { CopilotCLI } from "./plugin/cli.js";
|
|
6
|
+
import { log } from "./plugin/logger.js";
|
|
7
|
+
let accountManager = null;
|
|
8
|
+
let tokenManager = null;
|
|
9
|
+
let customFetch = null;
|
|
10
|
+
let config = null;
|
|
11
|
+
let initPromise = null;
|
|
12
|
+
async function ensureInitialized(input) {
|
|
13
|
+
if (initPromise)
|
|
14
|
+
return initPromise;
|
|
15
|
+
initPromise = (async () => {
|
|
16
|
+
config = await loadConfig();
|
|
17
|
+
log.initialize(input, config.logging);
|
|
18
|
+
log.info("init", "GH-MULTI COPILOT INITIALIZING");
|
|
19
|
+
accountManager = new CopilotAccountManager(config);
|
|
20
|
+
// Optimization: loadAccounts only performs local disk reads.
|
|
21
|
+
// Network sync is fired in background (fire-and-forget) within loadAccounts.
|
|
22
|
+
await accountManager.loadAccounts();
|
|
23
|
+
tokenManager = new TokenManager();
|
|
24
|
+
customFetch = createMultiAccountFetch(accountManager, tokenManager);
|
|
25
|
+
const shutdown = async () => {
|
|
26
|
+
if (accountManager)
|
|
27
|
+
await accountManager.shutdown();
|
|
28
|
+
};
|
|
29
|
+
process.on('SIGINT', shutdown);
|
|
30
|
+
process.on('SIGTERM', shutdown);
|
|
31
|
+
log.info("init", "GH-MULTI COPILOT READY");
|
|
32
|
+
})();
|
|
33
|
+
return initPromise;
|
|
34
|
+
}
|
|
35
|
+
export const nativeHook = async (input) => {
|
|
36
|
+
await ensureInitialized(input);
|
|
37
|
+
return {
|
|
38
|
+
auth: {
|
|
39
|
+
provider: "github-copilot",
|
|
40
|
+
loader: async (getAuth) => {
|
|
41
|
+
const auth = await getAuth();
|
|
42
|
+
log.info("GH_MULTI", "[LOADER:github-copilot] Injecting multi-account fetch");
|
|
43
|
+
const result = typeof auth === 'string' ? { token: auth } : { ...auth };
|
|
44
|
+
return {
|
|
45
|
+
...result,
|
|
46
|
+
fetch: customFetch
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"chat.headers": async (input, output) => {
|
|
51
|
+
if (input.model.providerID === "github-copilot") {
|
|
52
|
+
log.info("GH_MULTI", "[HEADERS:github-copilot] Injecting session ID", {
|
|
53
|
+
sessionID: input.sessionID
|
|
54
|
+
});
|
|
55
|
+
output.headers["x-session-id"] = input.sessionID;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export const multiHook = async (input) => {
|
|
61
|
+
await ensureInitialized(input);
|
|
62
|
+
return {
|
|
63
|
+
auth: {
|
|
64
|
+
provider: "gh-multi",
|
|
65
|
+
methods: [
|
|
66
|
+
{
|
|
67
|
+
type: "api",
|
|
68
|
+
label: "GitHub Copilot Multi-Account",
|
|
69
|
+
authorize: async () => {
|
|
70
|
+
log.info("auth", "Starting gh-multi authorization flow");
|
|
71
|
+
const cli = new CopilotCLI(accountManager);
|
|
72
|
+
await cli.showMenu();
|
|
73
|
+
const accounts = accountManager.listAccounts();
|
|
74
|
+
if (accounts.length === 0) {
|
|
75
|
+
return {
|
|
76
|
+
type: "failed",
|
|
77
|
+
message: "No accounts configured. Please add an account."
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
log.info("auth", `Authorization complete. ${accounts.length} account(s) configured.`);
|
|
81
|
+
return {
|
|
82
|
+
type: "success",
|
|
83
|
+
key: "gh-multi-managed",
|
|
84
|
+
provider: "gh-multi"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
loader: async (getAuth) => {
|
|
90
|
+
const auth = await getAuth();
|
|
91
|
+
log.info("GH_MULTI", "[LOADER:gh-multi] Injecting multi-account fetch");
|
|
92
|
+
return {
|
|
93
|
+
...auth,
|
|
94
|
+
fetch: customFetch,
|
|
95
|
+
baseURL: "https://api.githubcopilot.com"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"chat.headers": async (input, output) => {
|
|
100
|
+
if (input.model.providerID === "gh-multi") {
|
|
101
|
+
log.info("GH_MULTI", "[HEADERS:gh-multi] Injecting session ID", {
|
|
102
|
+
sessionID: input.sessionID
|
|
103
|
+
});
|
|
104
|
+
output.headers["x-session-id"] = input.sessionID;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
export default nativeHook;
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { CopilotConfig } from "./config/index.js";
|
|
2
|
+
export interface CopilotAccount {
|
|
3
|
+
username: string;
|
|
4
|
+
oauthToken: string;
|
|
5
|
+
addedAt: number;
|
|
6
|
+
status: "active" | "rate_limited" | "suspended" | "quota_exhausted";
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
health_score: number;
|
|
9
|
+
last_error_at?: number;
|
|
10
|
+
rateLimitedUntil?: number;
|
|
11
|
+
failureCount?: number;
|
|
12
|
+
lastUsed?: number;
|
|
13
|
+
sku?: string;
|
|
14
|
+
quotaResetDate?: string;
|
|
15
|
+
lastQuotaSync?: number;
|
|
16
|
+
premiumRemaining?: number;
|
|
17
|
+
premiumTotal?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class CopilotAccountManager {
|
|
20
|
+
private accounts;
|
|
21
|
+
private config;
|
|
22
|
+
private sessionIdToUsername;
|
|
23
|
+
private sessionCleanupInterval;
|
|
24
|
+
private dataDir?;
|
|
25
|
+
private saveTimeout;
|
|
26
|
+
private quotaSyncInterval;
|
|
27
|
+
private requestCount;
|
|
28
|
+
constructor(config: CopilotConfig, dataDir?: string);
|
|
29
|
+
shutdown(): Promise<void>;
|
|
30
|
+
private startQuotaSync;
|
|
31
|
+
stopQuotaSync(): void;
|
|
32
|
+
private startSessionCleanup;
|
|
33
|
+
stopSessionCleanup(): void;
|
|
34
|
+
private cleanupStaleSessions;
|
|
35
|
+
private syncAllQuotas;
|
|
36
|
+
private syncQuotaForAccount;
|
|
37
|
+
hasAccounts(): boolean;
|
|
38
|
+
hasHealthyAccounts(): boolean;
|
|
39
|
+
loadAccounts(): Promise<void>;
|
|
40
|
+
addAccount(oauthToken: string): Promise<CopilotAccount>;
|
|
41
|
+
refreshAccountInfo(username: string): Promise<CopilotAccount | null>;
|
|
42
|
+
private requestSave;
|
|
43
|
+
private saveAccounts;
|
|
44
|
+
getCurrentOrNext(sessionId?: string, model?: string): Promise<CopilotAccount | null>;
|
|
45
|
+
private selectAccountByQuota;
|
|
46
|
+
private selectNextAccount;
|
|
47
|
+
markQuotaExhausted(account: CopilotAccount): void;
|
|
48
|
+
markRateLimited(account: CopilotAccount, cooldownMs: number): Promise<void>;
|
|
49
|
+
markSuccess(account: CopilotAccount, _duration?: number): void;
|
|
50
|
+
markFailed(account: CopilotAccount, error?: Error, statusCode?: number): void;
|
|
51
|
+
listAccounts(): CopilotAccount[];
|
|
52
|
+
updateAccount(username: string, updates: Partial<CopilotAccount>): Promise<void>;
|
|
53
|
+
toggleAccount(username: string, enabled: boolean): Promise<void>;
|
|
54
|
+
updateAccountQuota(username: string, quota: {
|
|
55
|
+
premium: {
|
|
56
|
+
remaining: number;
|
|
57
|
+
total: number;
|
|
58
|
+
};
|
|
59
|
+
resetDate?: string | null;
|
|
60
|
+
}): void;
|
|
61
|
+
removeAccount(username: string): Promise<void>;
|
|
62
|
+
}
|