opencode-copilot-multi-fix 1.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 +172 -0
- package/bin/cli.js +26 -0
- package/dist/commands/multi-copilot.d.ts +18 -0
- package/dist/commands/multi-copilot.d.ts.map +1 -0
- package/dist/commands/multi-copilot.js +403 -0
- package/dist/commands/multi-copilot.js.map +1 -0
- package/dist/config/writer.d.ts +22 -0
- package/dist/config/writer.d.ts.map +1 -0
- package/dist/config/writer.js +143 -0
- package/dist/config/writer.js.map +1 -0
- package/dist/discovery/accounts.d.ts +24 -0
- package/dist/discovery/accounts.d.ts.map +1 -0
- package/dist/discovery/accounts.js +128 -0
- package/dist/discovery/accounts.js.map +1 -0
- package/dist/discovery/models.d.ts +32 -0
- package/dist/discovery/models.d.ts.map +1 -0
- package/dist/discovery/models.js +124 -0
- package/dist/discovery/models.js.map +1 -0
- package/dist/discovery/username.d.ts +8 -0
- package/dist/discovery/username.d.ts.map +1 -0
- package/dist/discovery/username.js +47 -0
- package/dist/discovery/username.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +16 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +174 -0
- package/dist/provider.js.map +1 -0
- package/dist/storage/auth.d.ts +21 -0
- package/dist/storage/auth.d.ts.map +1 -0
- package/dist/storage/auth.js +130 -0
- package/dist/storage/auth.js.map +1 -0
- package/dist/storage/pool.d.ts +29 -0
- package/dist/storage/pool.d.ts.map +1 -0
- package/dist/storage/pool.js +152 -0
- package/dist/storage/pool.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errors.d.ts +28 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +52 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/jsonc.d.ts +20 -0
- package/dist/utils/jsonc.d.ts.map +1 -0
- package/dist/utils/jsonc.js +91 -0
- package/dist/utils/jsonc.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +53 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +71 -0
- package/scripts/postinstall.js +86 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config writer - writes models to opencode.json
|
|
3
|
+
*/
|
|
4
|
+
import type { Account } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Write models for all accounts to opencode.json
|
|
7
|
+
*
|
|
8
|
+
* Format: provider "copilot-multi" with models like "username:model-id"
|
|
9
|
+
*/
|
|
10
|
+
export declare function writeModelsToConfig(accounts: Account[]): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Remove copilot-multi provider from config
|
|
13
|
+
* (for cleanup/uninstall)
|
|
14
|
+
*/
|
|
15
|
+
export declare function removeProviderFromConfig(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Ensure plugin is registered in opencode.json(c)
|
|
18
|
+
*
|
|
19
|
+
* @returns true if plugin was newly added, false if already present
|
|
20
|
+
*/
|
|
21
|
+
export declare function ensurePluginInstalled(): Promise<boolean>;
|
|
22
|
+
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/config/writer.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,aAAa,CAAC;AAmE3D;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC5E;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ9D;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAwC9D"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config writer - writes models to opencode.json
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import os from 'os';
|
|
7
|
+
import { logger } from '../utils/logger.js';
|
|
8
|
+
import { buildModelConfig } from '../discovery/models.js';
|
|
9
|
+
import { parseJSONC } from '../utils/jsonc.js';
|
|
10
|
+
import { PLUGIN_CONSTANTS } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Get path to global opencode.json(c)
|
|
13
|
+
* Checks for both .jsonc and .json variants
|
|
14
|
+
*/
|
|
15
|
+
function getGlobalConfigPath() {
|
|
16
|
+
const homeDir = os.homedir();
|
|
17
|
+
const configDir = path.join(homeDir, '.config', 'opencode');
|
|
18
|
+
// Prefer .jsonc if it exists
|
|
19
|
+
const jsoncPath = path.join(configDir, 'opencode.jsonc');
|
|
20
|
+
if (fs.existsSync(jsoncPath)) {
|
|
21
|
+
return jsoncPath;
|
|
22
|
+
}
|
|
23
|
+
// Fall back to .json
|
|
24
|
+
return path.join(configDir, 'opencode.json');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read current opencode.json(c) config
|
|
28
|
+
*/
|
|
29
|
+
async function readConfig() {
|
|
30
|
+
const configPath = getGlobalConfigPath();
|
|
31
|
+
try {
|
|
32
|
+
if (!fs.existsSync(configPath)) {
|
|
33
|
+
logger.debug('Config file not found, will create new one');
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
37
|
+
// Use JSONC parser if file is .jsonc
|
|
38
|
+
if (configPath.endsWith('.jsonc')) {
|
|
39
|
+
return parseJSONC(content);
|
|
40
|
+
}
|
|
41
|
+
return JSON.parse(content);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logger.error('Failed to read config', {
|
|
45
|
+
error: error instanceof Error ? error.message : String(error)
|
|
46
|
+
});
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Write config to opencode.json
|
|
52
|
+
*/
|
|
53
|
+
async function writeConfig(config) {
|
|
54
|
+
const configPath = getGlobalConfigPath();
|
|
55
|
+
const configDir = path.dirname(configPath);
|
|
56
|
+
// Ensure directory exists
|
|
57
|
+
if (!fs.existsSync(configDir)) {
|
|
58
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
// Write with pretty formatting
|
|
61
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
62
|
+
logger.info('Config written', { path: configPath });
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Write models for all accounts to opencode.json
|
|
66
|
+
*
|
|
67
|
+
* Format: provider "copilot-multi" with models like "username:model-id"
|
|
68
|
+
*/
|
|
69
|
+
export async function writeModelsToConfig(accounts) {
|
|
70
|
+
logger.info(`Writing models for ${accounts.length} accounts to config...`);
|
|
71
|
+
const config = await readConfig();
|
|
72
|
+
// Initialize provider section
|
|
73
|
+
config.provider = config.provider || {};
|
|
74
|
+
// Create/update copilot-multi provider
|
|
75
|
+
config.provider[PLUGIN_CONSTANTS.PROVIDER_NAME] = {
|
|
76
|
+
models: {}
|
|
77
|
+
};
|
|
78
|
+
const providerConfig = config.provider[PLUGIN_CONSTANTS.PROVIDER_NAME];
|
|
79
|
+
// Add models for each account
|
|
80
|
+
for (const account of accounts) {
|
|
81
|
+
for (const modelId of account.models) {
|
|
82
|
+
// Model ID format: "username:model"
|
|
83
|
+
const fullModelId = `${account.username}:${modelId}`;
|
|
84
|
+
providerConfig.models[fullModelId] = buildModelConfig(modelId, account.displayName);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await writeConfig(config);
|
|
88
|
+
const totalModels = Object.keys(providerConfig.models).length;
|
|
89
|
+
logger.info(`Wrote ${totalModels} models to config`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Remove copilot-multi provider from config
|
|
93
|
+
* (for cleanup/uninstall)
|
|
94
|
+
*/
|
|
95
|
+
export async function removeProviderFromConfig() {
|
|
96
|
+
const config = await readConfig();
|
|
97
|
+
if (config.provider && config.provider[PLUGIN_CONSTANTS.PROVIDER_NAME]) {
|
|
98
|
+
delete config.provider[PLUGIN_CONSTANTS.PROVIDER_NAME];
|
|
99
|
+
await writeConfig(config);
|
|
100
|
+
logger.info('Provider removed from config');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Ensure plugin is registered in opencode.json(c)
|
|
105
|
+
*
|
|
106
|
+
* @returns true if plugin was newly added, false if already present
|
|
107
|
+
*/
|
|
108
|
+
export async function ensurePluginInstalled() {
|
|
109
|
+
const configPath = getGlobalConfigPath();
|
|
110
|
+
try {
|
|
111
|
+
// Read config
|
|
112
|
+
let config = {};
|
|
113
|
+
if (fs.existsSync(configPath)) {
|
|
114
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
115
|
+
config = configPath.endsWith('.jsonc') ? parseJSONC(content) : JSON.parse(content);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
logger.debug('Config file not found, will create new one');
|
|
119
|
+
}
|
|
120
|
+
// Initialize plugin array if needed
|
|
121
|
+
if (!config.plugin) {
|
|
122
|
+
config.plugin = [];
|
|
123
|
+
}
|
|
124
|
+
// Check if already installed
|
|
125
|
+
if (config.plugin.includes(PLUGIN_CONSTANTS.PACKAGE_NAME)) {
|
|
126
|
+
logger.debug('Plugin already in config');
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// Add plugin
|
|
130
|
+
config.plugin.push(PLUGIN_CONSTANTS.PACKAGE_NAME);
|
|
131
|
+
// Write back
|
|
132
|
+
await writeConfig(config);
|
|
133
|
+
logger.info('Plugin added to config');
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
logger.error('Failed to ensure plugin installed', {
|
|
138
|
+
error: error instanceof Error ? error.message : String(error)
|
|
139
|
+
});
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/config/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account discovery and management
|
|
3
|
+
* Non-blocking - called lazily, not at init
|
|
4
|
+
*/
|
|
5
|
+
import type { Account } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Detect and add new account from OpenCode's github-copilot auth
|
|
8
|
+
* This is called lazily (on first request or explicit sync)
|
|
9
|
+
*
|
|
10
|
+
* @returns The new account if added, null if already exists or no auth
|
|
11
|
+
*/
|
|
12
|
+
export declare function detectAndAddNewAccount(): Promise<Account | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Sync all accounts - update auth if changed, clean if removed
|
|
15
|
+
* Called periodically or on demand
|
|
16
|
+
*
|
|
17
|
+
* This function:
|
|
18
|
+
* 1. Checks if github-copilot auth still exists
|
|
19
|
+
* 2. If no auth, clears all accounts (user logged out)
|
|
20
|
+
* 3. If auth exists but token changed, adds new account
|
|
21
|
+
* 4. Updates config with current accounts
|
|
22
|
+
*/
|
|
23
|
+
export declare function syncAccounts(): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=accounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/discovery/accounts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,KAAK,EAAE,OAAO,EAAa,MAAM,aAAa,CAAC;AAyBtD;;;;;GAKG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA0CtE;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAiDlD"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account discovery and management
|
|
3
|
+
* Non-blocking - called lazily, not at init
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { getGitHubCopilotAuth, generateAccountId } from '../storage/auth.js';
|
|
7
|
+
import { getAccountPool, addAccountToPool, saveAccountPool } from '../storage/pool.js';
|
|
8
|
+
import { fetchGitHubUsername } from './username.js';
|
|
9
|
+
import { DEFAULT_COPILOT_MODELS } from './models.js';
|
|
10
|
+
import { writeModelsToConfig } from '../config/writer.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create a new account object
|
|
13
|
+
*/
|
|
14
|
+
function createAccount(username, auth) {
|
|
15
|
+
return {
|
|
16
|
+
id: generateAccountId(auth.refresh),
|
|
17
|
+
username,
|
|
18
|
+
displayName: username, // Can be customized later
|
|
19
|
+
auth,
|
|
20
|
+
models: [...DEFAULT_COPILOT_MODELS],
|
|
21
|
+
addedAt: Date.now(),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Check if account already exists in pool (by refresh token)
|
|
26
|
+
*/
|
|
27
|
+
async function accountExistsInPool(auth) {
|
|
28
|
+
const pool = await getAccountPool();
|
|
29
|
+
const id = generateAccountId(auth.refresh);
|
|
30
|
+
return pool.accounts.some(a => a.id === id);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Detect and add new account from OpenCode's github-copilot auth
|
|
34
|
+
* This is called lazily (on first request or explicit sync)
|
|
35
|
+
*
|
|
36
|
+
* @returns The new account if added, null if already exists or no auth
|
|
37
|
+
*/
|
|
38
|
+
export async function detectAndAddNewAccount() {
|
|
39
|
+
logger.info('Checking for new GitHub Copilot account...');
|
|
40
|
+
// Get current auth from OpenCode
|
|
41
|
+
const currentAuth = await getGitHubCopilotAuth();
|
|
42
|
+
if (!currentAuth) {
|
|
43
|
+
logger.info('No GitHub Copilot auth found in OpenCode');
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
// Check if already in pool
|
|
47
|
+
const exists = await accountExistsInPool(currentAuth);
|
|
48
|
+
if (exists) {
|
|
49
|
+
logger.debug('Account already in pool');
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// New account! Fetch username
|
|
53
|
+
logger.info('New account detected, fetching username...');
|
|
54
|
+
try {
|
|
55
|
+
const username = await fetchGitHubUsername(currentAuth.access);
|
|
56
|
+
// Create and add account
|
|
57
|
+
const newAccount = createAccount(username, currentAuth);
|
|
58
|
+
await addAccountToPool(newAccount);
|
|
59
|
+
// Update config with new models
|
|
60
|
+
const pool = await getAccountPool();
|
|
61
|
+
await writeModelsToConfig(pool.accounts);
|
|
62
|
+
logger.info(`New account added: ${username}`);
|
|
63
|
+
return newAccount;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error('Failed to add new account', {
|
|
67
|
+
error: error instanceof Error ? error.message : String(error)
|
|
68
|
+
});
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Sync all accounts - update auth if changed, clean if removed
|
|
74
|
+
* Called periodically or on demand
|
|
75
|
+
*
|
|
76
|
+
* This function:
|
|
77
|
+
* 1. Checks if github-copilot auth still exists
|
|
78
|
+
* 2. If no auth, clears all accounts (user logged out)
|
|
79
|
+
* 3. If auth exists but token changed, adds new account
|
|
80
|
+
* 4. Updates config with current accounts
|
|
81
|
+
*/
|
|
82
|
+
export async function syncAccounts() {
|
|
83
|
+
logger.info('Syncing accounts...');
|
|
84
|
+
// Check if github-copilot auth still exists
|
|
85
|
+
const currentAuth = await getGitHubCopilotAuth();
|
|
86
|
+
const pool = await getAccountPool();
|
|
87
|
+
if (!currentAuth) {
|
|
88
|
+
// No github-copilot auth found - user logged out from GitHub Copilot
|
|
89
|
+
if (pool.accounts.length > 0) {
|
|
90
|
+
logger.info('GitHub Copilot auth removed, clearing all accounts from pool');
|
|
91
|
+
pool.accounts = [];
|
|
92
|
+
pool.lastUpdated = Date.now();
|
|
93
|
+
await saveAccountPool(pool);
|
|
94
|
+
await writeModelsToConfig([]);
|
|
95
|
+
logger.info('All accounts cleared due to logout');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
logger.debug('No auth and no accounts - nothing to sync');
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Auth exists - check if it matches any account in pool
|
|
103
|
+
const currentId = generateAccountId(currentAuth.refresh);
|
|
104
|
+
const accountExists = pool.accounts.some(a => a.id === currentId);
|
|
105
|
+
if (!accountExists) {
|
|
106
|
+
// New account detected (token changed)
|
|
107
|
+
logger.info('Token changed or new account, detecting...');
|
|
108
|
+
await detectAndAddNewAccount();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Same account - update auth if needed
|
|
112
|
+
const account = pool.accounts.find(a => a.id === currentId);
|
|
113
|
+
if (account) {
|
|
114
|
+
// Update tokens in case they changed (e.g., refresh)
|
|
115
|
+
if (account.auth.access !== currentAuth.access ||
|
|
116
|
+
account.auth.refresh !== currentAuth.refresh) {
|
|
117
|
+
logger.debug('Updating tokens for existing account');
|
|
118
|
+
account.auth = currentAuth;
|
|
119
|
+
await saveAccountPool(pool);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Update config with current accounts
|
|
124
|
+
const updatedPool = await getAccountPool();
|
|
125
|
+
await writeModelsToConfig(updatedPool.accounts);
|
|
126
|
+
logger.info(`Sync complete. ${updatedPool.accounts.length} accounts in pool.`);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/discovery/accounts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model definitions for GitHub Copilot
|
|
3
|
+
* Based on observed models available via GitHub Copilot
|
|
4
|
+
*/
|
|
5
|
+
import type { ModelConfig } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Default models available through GitHub Copilot
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_COPILOT_MODELS: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Get display name for a model
|
|
12
|
+
*/
|
|
13
|
+
export declare function getModelDisplayName(modelId: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get limits for a model
|
|
16
|
+
*/
|
|
17
|
+
export declare function getModelLimits(modelId: string): {
|
|
18
|
+
context: number;
|
|
19
|
+
output: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Get modalities for a model
|
|
23
|
+
*/
|
|
24
|
+
export declare function getModelModalities(modelId: string): {
|
|
25
|
+
input: string[];
|
|
26
|
+
output: string[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Build full model config for opencode.json
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildModelConfig(modelId: string, displayPrefix: string): ModelConfig;
|
|
32
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/discovery/models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,sBAAsB,UAgBlC,CAAC;AA6EF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAEnF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAEzF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,WAAW,CAMpF"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model definitions for GitHub Copilot
|
|
3
|
+
* Based on observed models available via GitHub Copilot
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Default models available through GitHub Copilot
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_COPILOT_MODELS = [
|
|
9
|
+
'claude-sonnet-4',
|
|
10
|
+
'claude-sonnet-4.5',
|
|
11
|
+
'claude-haiku-4.5',
|
|
12
|
+
'claude-opus-4',
|
|
13
|
+
'claude-opus-4.5',
|
|
14
|
+
'gpt-4o',
|
|
15
|
+
'gpt-4o-mini',
|
|
16
|
+
'gpt-4-turbo',
|
|
17
|
+
'gpt-5',
|
|
18
|
+
'o1',
|
|
19
|
+
'o1-mini',
|
|
20
|
+
'o3-mini',
|
|
21
|
+
'gemini-2.5-pro',
|
|
22
|
+
'gemini-3-flash-preview',
|
|
23
|
+
'gemini-3-pro-preview',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Model display names
|
|
27
|
+
*/
|
|
28
|
+
const MODEL_DISPLAY_NAMES = {
|
|
29
|
+
'claude-sonnet-4': 'Claude Sonnet 4',
|
|
30
|
+
'claude-sonnet-4.5': 'Claude Sonnet 4.5',
|
|
31
|
+
'claude-haiku-4.5': 'Claude Haiku 4.5',
|
|
32
|
+
'claude-opus-4': 'Claude Opus 4',
|
|
33
|
+
'claude-opus-4.5': 'Claude Opus 4.5',
|
|
34
|
+
'gpt-4o': 'GPT-4o',
|
|
35
|
+
'gpt-4o-mini': 'GPT-4o Mini',
|
|
36
|
+
'gpt-4-turbo': 'GPT-4 Turbo',
|
|
37
|
+
'gpt-5': 'GPT-5',
|
|
38
|
+
'o1': 'OpenAI o1',
|
|
39
|
+
'o1-mini': 'OpenAI o1-mini',
|
|
40
|
+
'o3-mini': 'OpenAI o3-mini',
|
|
41
|
+
'gemini-2.5-pro': 'Gemini 2.5 Pro',
|
|
42
|
+
'gemini-3-flash-preview': 'Gemini 3 Flash',
|
|
43
|
+
'gemini-3-pro-preview': 'Gemini 3 Pro',
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Model limits configuration
|
|
47
|
+
*/
|
|
48
|
+
const MODEL_LIMITS = {
|
|
49
|
+
// Claude models
|
|
50
|
+
'claude-sonnet-4': { context: 200000, output: 64000 },
|
|
51
|
+
'claude-sonnet-4.5': { context: 200000, output: 64000 },
|
|
52
|
+
'claude-haiku-4.5': { context: 200000, output: 64000 },
|
|
53
|
+
'claude-opus-4': { context: 200000, output: 64000 },
|
|
54
|
+
'claude-opus-4.5': { context: 200000, output: 64000 },
|
|
55
|
+
// OpenAI models
|
|
56
|
+
'gpt-4o': { context: 128000, output: 16000 },
|
|
57
|
+
'gpt-4o-mini': { context: 128000, output: 16000 },
|
|
58
|
+
'gpt-4-turbo': { context: 128000, output: 16000 },
|
|
59
|
+
'gpt-5': { context: 128000, output: 32000 },
|
|
60
|
+
'o1': { context: 200000, output: 100000 },
|
|
61
|
+
'o1-mini': { context: 128000, output: 65536 },
|
|
62
|
+
'o3-mini': { context: 200000, output: 100000 },
|
|
63
|
+
// Gemini models
|
|
64
|
+
'gemini-2.5-pro': { context: 1048576, output: 65536 },
|
|
65
|
+
'gemini-3-flash-preview': { context: 1048576, output: 65536 },
|
|
66
|
+
'gemini-3-pro-preview': { context: 1048576, output: 65536 },
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Model modalities
|
|
70
|
+
*/
|
|
71
|
+
const MODEL_MODALITIES = {
|
|
72
|
+
// Claude - supports images
|
|
73
|
+
'claude-sonnet-4': { input: ['text', 'image'], output: ['text'] },
|
|
74
|
+
'claude-sonnet-4.5': { input: ['text', 'image'], output: ['text'] },
|
|
75
|
+
'claude-haiku-4.5': { input: ['text', 'image'], output: ['text'] },
|
|
76
|
+
'claude-opus-4': { input: ['text', 'image'], output: ['text'] },
|
|
77
|
+
'claude-opus-4.5': { input: ['text', 'image'], output: ['text'] },
|
|
78
|
+
// OpenAI - supports images
|
|
79
|
+
'gpt-4o': { input: ['text', 'image'], output: ['text'] },
|
|
80
|
+
'gpt-4o-mini': { input: ['text', 'image'], output: ['text'] },
|
|
81
|
+
'gpt-4-turbo': { input: ['text', 'image'], output: ['text'] },
|
|
82
|
+
'gpt-5': { input: ['text', 'image'], output: ['text'] },
|
|
83
|
+
'o1': { input: ['text', 'image'], output: ['text'] },
|
|
84
|
+
'o1-mini': { input: ['text'], output: ['text'] },
|
|
85
|
+
'o3-mini': { input: ['text'], output: ['text'] },
|
|
86
|
+
// Gemini - supports images and PDF
|
|
87
|
+
'gemini-2.5-pro': { input: ['text', 'image', 'pdf'], output: ['text'] },
|
|
88
|
+
'gemini-3-flash-preview': { input: ['text', 'image', 'pdf'], output: ['text'] },
|
|
89
|
+
'gemini-3-pro-preview': { input: ['text', 'image', 'pdf'], output: ['text'] },
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Default values for unknown models
|
|
93
|
+
*/
|
|
94
|
+
const DEFAULT_LIMITS = { context: 128000, output: 16000 };
|
|
95
|
+
const DEFAULT_MODALITIES = { input: ['text'], output: ['text'] };
|
|
96
|
+
/**
|
|
97
|
+
* Get display name for a model
|
|
98
|
+
*/
|
|
99
|
+
export function getModelDisplayName(modelId) {
|
|
100
|
+
return MODEL_DISPLAY_NAMES[modelId] || modelId;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get limits for a model
|
|
104
|
+
*/
|
|
105
|
+
export function getModelLimits(modelId) {
|
|
106
|
+
return MODEL_LIMITS[modelId] || DEFAULT_LIMITS;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get modalities for a model
|
|
110
|
+
*/
|
|
111
|
+
export function getModelModalities(modelId) {
|
|
112
|
+
return MODEL_MODALITIES[modelId] || DEFAULT_MODALITIES;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build full model config for opencode.json
|
|
116
|
+
*/
|
|
117
|
+
export function buildModelConfig(modelId, displayPrefix) {
|
|
118
|
+
return {
|
|
119
|
+
name: `${displayPrefix}: ${getModelDisplayName(modelId)}`,
|
|
120
|
+
limit: getModelLimits(modelId),
|
|
121
|
+
modalities: getModelModalities(modelId),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/discovery/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"username.d.ts","sourceRoot":"","sources":["../../src/discovery/username.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA6C9E"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account discovery - fetch GitHub username from API
|
|
3
|
+
*/
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
import { GitHubAPIError } from '../utils/errors.js';
|
|
6
|
+
const GITHUB_API_TIMEOUT = 5000; // 5 seconds
|
|
7
|
+
const GITHUB_API_URL = 'https://api.github.com/user';
|
|
8
|
+
/**
|
|
9
|
+
* Fetch GitHub username using the access token
|
|
10
|
+
*/
|
|
11
|
+
export async function fetchGitHubUsername(accessToken) {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
const timeout = setTimeout(() => controller.abort(), GITHUB_API_TIMEOUT);
|
|
14
|
+
try {
|
|
15
|
+
logger.debug('Fetching GitHub username from API...');
|
|
16
|
+
const response = await fetch(GITHUB_API_URL, {
|
|
17
|
+
headers: {
|
|
18
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
19
|
+
'Accept': 'application/json',
|
|
20
|
+
'User-Agent': 'opencode-copilot-multi',
|
|
21
|
+
},
|
|
22
|
+
signal: controller.signal,
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new GitHubAPIError(`API returned status ${response.status}`, response.status);
|
|
26
|
+
}
|
|
27
|
+
const data = await response.json();
|
|
28
|
+
if (!data.login) {
|
|
29
|
+
throw new GitHubAPIError('API response missing login field');
|
|
30
|
+
}
|
|
31
|
+
logger.debug(`Fetched username: ${data.login}`);
|
|
32
|
+
return data.login;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof GitHubAPIError) {
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
// Timeout or network error
|
|
39
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
40
|
+
logger.error('Failed to fetch GitHub username', { error: message });
|
|
41
|
+
throw new GitHubAPIError(message);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
clearTimeout(timeout);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=username.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"username.js","sourceRoot":"","sources":["../../src/discovery/username.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,YAAY;AAC7C,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAErD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,WAAmB;IAC3D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAEzE,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE;YAC3C,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,WAAW,EAAE;gBACxC,QAAQ,EAAE,kBAAkB;gBAC5B,YAAY,EAAE,wBAAwB;aACvC;YACD,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,cAAc,CACtB,uBAAuB,QAAQ,CAAC,MAAM,EAAE,EACxC,QAAQ,CAAC,MAAM,CAChB,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAuC,CAAC;QAExE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,cAAc,CAAC,kCAAkC,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC;IAEpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;YACpC,MAAM,KAAK,CAAC;QACd,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACpE,MAAM,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;IAEpC,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode GitHub Copilot Multi-Account Plugin
|
|
3
|
+
*
|
|
4
|
+
* Enables using multiple GitHub Copilot accounts simultaneously.
|
|
5
|
+
* Each account's models appear in the model selector with format:
|
|
6
|
+
* copilot-multi/username:model-name
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* - Single auth hook for provider "copilot-multi"
|
|
10
|
+
* - Custom fetch routes requests based on model ID
|
|
11
|
+
* - Account pool stored separately from OpenCode auth
|
|
12
|
+
* - Lazy loading - no blocking init
|
|
13
|
+
*
|
|
14
|
+
* Management:
|
|
15
|
+
* - Use CLI tool: opencode-copilot-multi list|remove|clear
|
|
16
|
+
*
|
|
17
|
+
* @author Valerio Fantozzi
|
|
18
|
+
* @license MIT
|
|
19
|
+
*/
|
|
20
|
+
import type { Plugin } from './types.js';
|
|
21
|
+
/**
|
|
22
|
+
* Plugin entry point
|
|
23
|
+
*
|
|
24
|
+
* IMPORTANT: This function must return quickly!
|
|
25
|
+
* - No blocking HTTP calls
|
|
26
|
+
* - No heavy I/O operations
|
|
27
|
+
* - Defer everything to lazy loading
|
|
28
|
+
*/
|
|
29
|
+
export declare const plugin: Plugin;
|
|
30
|
+
export default plugin;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,MAsDpB,CAAC;AAGF,eAAe,MAAM,CAAC"}
|