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.
Files changed (53) hide show
  1. package/README.md +70 -0
  2. package/gh-multi-dist/constants.d.ts +14 -0
  3. package/gh-multi-dist/constants.js +16 -0
  4. package/gh-multi-dist/constants.js.map +1 -0
  5. package/gh-multi-dist/index.d.ts +4 -0
  6. package/gh-multi-dist/index.js +110 -0
  7. package/gh-multi-dist/index.js.map +1 -0
  8. package/gh-multi-dist/plugin/accounts.d.ts +62 -0
  9. package/gh-multi-dist/plugin/accounts.js +703 -0
  10. package/gh-multi-dist/plugin/accounts.js.map +1 -0
  11. package/gh-multi-dist/plugin/cli.d.ts +19 -0
  12. package/gh-multi-dist/plugin/cli.js +409 -0
  13. package/gh-multi-dist/plugin/cli.js.map +1 -0
  14. package/gh-multi-dist/plugin/config/index.d.ts +2 -0
  15. package/gh-multi-dist/plugin/config/index.js +3 -0
  16. package/gh-multi-dist/plugin/config/index.js.map +1 -0
  17. package/gh-multi-dist/plugin/config/loader.d.ts +3 -0
  18. package/gh-multi-dist/plugin/config/loader.js +78 -0
  19. package/gh-multi-dist/plugin/config/loader.js.map +1 -0
  20. package/gh-multi-dist/plugin/config/schema.d.ts +28 -0
  21. package/gh-multi-dist/plugin/config/schema.js +10 -0
  22. package/gh-multi-dist/plugin/config/schema.js.map +1 -0
  23. package/gh-multi-dist/plugin/device_flow.d.ts +18 -0
  24. package/gh-multi-dist/plugin/device_flow.js +78 -0
  25. package/gh-multi-dist/plugin/device_flow.js.map +1 -0
  26. package/gh-multi-dist/plugin/fetch.d.ts +3 -0
  27. package/gh-multi-dist/plugin/fetch.js +156 -0
  28. package/gh-multi-dist/plugin/fetch.js.map +1 -0
  29. package/gh-multi-dist/plugin/index.d.ts +5 -0
  30. package/gh-multi-dist/plugin/index.js +6 -0
  31. package/gh-multi-dist/plugin/index.js.map +1 -0
  32. package/gh-multi-dist/plugin/logger.d.ts +43 -0
  33. package/gh-multi-dist/plugin/logger.js +169 -0
  34. package/gh-multi-dist/plugin/logger.js.map +1 -0
  35. package/gh-multi-dist/plugin/models.d.ts +2 -0
  36. package/gh-multi-dist/plugin/models.js +96 -0
  37. package/gh-multi-dist/plugin/models.js.map +1 -0
  38. package/gh-multi-dist/plugin/quota.d.ts +11 -0
  39. package/gh-multi-dist/plugin/quota.js +42 -0
  40. package/gh-multi-dist/plugin/quota.js.map +1 -0
  41. package/gh-multi-dist/plugin/token.d.ts +5 -0
  42. package/gh-multi-dist/plugin/token.js +7 -0
  43. package/gh-multi-dist/plugin/token.js.map +1 -0
  44. package/gh-multi-dist/plugin/ui/ansi.d.ts +41 -0
  45. package/gh-multi-dist/plugin/ui/ansi.js +67 -0
  46. package/gh-multi-dist/plugin/ui/ansi.js.map +1 -0
  47. package/gh-multi-dist/plugin/ui/confirm.d.ts +1 -0
  48. package/gh-multi-dist/plugin/ui/confirm.js +15 -0
  49. package/gh-multi-dist/plugin/ui/confirm.js.map +1 -0
  50. package/gh-multi-dist/plugin/ui/select.d.ts +13 -0
  51. package/gh-multi-dist/plugin/ui/select.js +170 -0
  52. package/gh-multi-dist/plugin/ui/select.js.map +1 -0
  53. 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,4 @@
1
+ import { Plugin } from "@opencode-ai/plugin";
2
+ export declare const nativeHook: Plugin;
3
+ export declare const multiHook: Plugin;
4
+ export default nativeHook;
@@ -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
+ }