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
@@ -0,0 +1,96 @@
1
+ // GitHub Copilot model availability per SKU: https://docs.github.com/en/copilot/get-started/plans#models
2
+ const ALL_SKUS = ['free', 'pro', 'pro_plus', 'business', 'enterprise'];
3
+ const PAID_SKUS = ['pro', 'pro_plus', 'business', 'enterprise'];
4
+ const PREMIUM_SKUS = ['pro_plus', 'enterprise'];
5
+ const MODEL_AVAILABILITY = {
6
+ 'claude-haiku-4.5': ALL_SKUS,
7
+ 'gpt-4.1': ALL_SKUS,
8
+ 'gpt-5-mini': ALL_SKUS,
9
+ 'raptor-mini': ['free', 'pro', 'pro_plus'],
10
+ 'claude-opus-4.1': PREMIUM_SKUS,
11
+ 'claude-opus-4.5': PAID_SKUS,
12
+ 'claude-sonnet-4': PAID_SKUS,
13
+ 'claude-sonnet-4.5': PAID_SKUS,
14
+ 'gemini-2.5-pro': PAID_SKUS,
15
+ 'gemini-3-flash': PAID_SKUS,
16
+ 'gemini-3-pro': PAID_SKUS,
17
+ 'gpt-5': PAID_SKUS,
18
+ 'gpt-5-codex': PAID_SKUS,
19
+ 'gpt-5.1': PAID_SKUS,
20
+ 'gpt-5.1-codex': PAID_SKUS,
21
+ 'gpt-5.1-codex-mini': PAID_SKUS,
22
+ 'gpt-5.1-codex-max': PAID_SKUS,
23
+ 'gpt-5.2': PAID_SKUS,
24
+ 'gpt-5.2-codex': PAID_SKUS,
25
+ 'grok-code-fast-1': PAID_SKUS,
26
+ 'o1-preview': PAID_SKUS,
27
+ 'o1-mini': PAID_SKUS,
28
+ 'o3-mini': ALL_SKUS,
29
+ 'o3': PAID_SKUS,
30
+ 'o4-mini': PAID_SKUS,
31
+ 'claude-3.7-sonnet': PAID_SKUS,
32
+ 'claude-3.7-sonnet-thought': PAID_SKUS,
33
+ };
34
+ const SKU_MAPPING = {
35
+ 'free_limited_copilot': 'free',
36
+ 'no_access': 'free',
37
+ 'copilot_pro': 'pro',
38
+ 'copilot_pro_plus': 'pro_plus',
39
+ 'copilot_business': 'business',
40
+ 'copilot_enterprise': 'enterprise',
41
+ 'free_educational_quota': 'pro',
42
+ };
43
+ const MODEL_ALIASES = {
44
+ 'claude-3.5-sonnet': 'claude-sonnet-4',
45
+ 'claude-sonnet-3.5': 'claude-sonnet-4',
46
+ 'gpt-4o': 'gpt-4.1',
47
+ 'gpt-4o-mini': 'gpt-5-mini',
48
+ 'claude-4.5-haiku': 'claude-haiku-4.5',
49
+ 'gemini-2.0-flash': 'gemini-3-flash',
50
+ 'gemini-2.0-flash-001': 'gemini-3-flash',
51
+ 'claude-opus-41': 'claude-opus-4.1',
52
+ 'oswe-vscode-prime': 'raptor-mini',
53
+ 'gemini-3-flash-preview': 'gemini-3-flash',
54
+ 'gemini-3-pro-preview': 'gemini-3-pro',
55
+ 'claude-3-7-sonnet': 'claude-3.7-sonnet',
56
+ 'claude-37-sonnet': 'claude-3.7-sonnet',
57
+ 'claude-3-7-sonnet-thought': 'claude-3.7-sonnet-thought',
58
+ 'claude-37-sonnet-thought': 'claude-3.7-sonnet-thought',
59
+ };
60
+ function normalizeModelName(model) {
61
+ const lower = model.toLowerCase();
62
+ const normalized = MODEL_ALIASES[lower] || lower;
63
+ return normalized;
64
+ }
65
+ export function isModelAvailableForSku(model, sku) {
66
+ const normalized = normalizeModelName(model.toLowerCase());
67
+ const tier = SKU_MAPPING[sku || ''] || 'free';
68
+ const allowedTiers = MODEL_AVAILABILITY[normalized];
69
+ if (!allowedTiers) {
70
+ return true;
71
+ }
72
+ const isAvailable = allowedTiers.includes(tier);
73
+ return isAvailable;
74
+ }
75
+ export function getRequiredTierForModel(model) {
76
+ const normalized = normalizeModelName(model.toLowerCase());
77
+ const allowedTiers = MODEL_AVAILABILITY[normalized];
78
+ let result;
79
+ if (!allowedTiers) {
80
+ result = 'Unknown';
81
+ }
82
+ else if (allowedTiers.includes('free')) {
83
+ result = 'Free (all tiers)';
84
+ }
85
+ else if (allowedTiers.length === 2 && allowedTiers.includes('pro_plus') && allowedTiers.includes('enterprise')) {
86
+ result = 'Pro+ or Enterprise only';
87
+ }
88
+ else if (allowedTiers.includes('pro')) {
89
+ result = 'Pro or higher';
90
+ }
91
+ else {
92
+ result = allowedTiers.join(', ');
93
+ }
94
+ return result;
95
+ }
96
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/plugin/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface CopilotQuota {
2
+ plan: string;
3
+ sku: string;
4
+ premium: {
5
+ remaining: number;
6
+ total: number;
7
+ percentRemaining: number;
8
+ };
9
+ resetDate: string | null;
10
+ }
11
+ export declare function fetchQuota(oauthToken: string): Promise<CopilotQuota | null>;
@@ -0,0 +1,42 @@
1
+ import { OPENCODE_USER_AGENT } from '../constants.js';
2
+ import { createLogger } from './logger.js';
3
+ const log = createLogger('quota');
4
+ export async function fetchQuota(oauthToken) {
5
+ try {
6
+ const url = 'https://api.github.com/copilot_internal/user';
7
+ const response = await fetch(url, {
8
+ headers: {
9
+ 'Authorization': `token ${oauthToken}`,
10
+ 'User-Agent': OPENCODE_USER_AGENT,
11
+ 'Accept': 'application/json'
12
+ },
13
+ });
14
+ if (!response.ok) {
15
+ log.warn(`[QUOTA] Failed to fetch: ${response.status} ${response.statusText}`);
16
+ return null;
17
+ }
18
+ const data = (await response.json());
19
+ const premiumInteractions = data.quota_snapshots?.premium_interactions;
20
+ if (!premiumInteractions) {
21
+ log.warn('[QUOTA] No premium interactions found in response');
22
+ }
23
+ const premiumRemaining = premiumInteractions?.remaining ?? premiumInteractions?.quota_remaining ?? 0;
24
+ const premiumTotal = premiumInteractions?.entitlement ?? 0;
25
+ const result = {
26
+ plan: data.copilot_plan || 'unknown',
27
+ sku: data.access_type_sku || 'unknown',
28
+ premium: {
29
+ remaining: premiumRemaining,
30
+ total: premiumTotal,
31
+ percentRemaining: premiumInteractions?.percent_remaining ?? 0,
32
+ },
33
+ resetDate: data.limited_user_reset_date || data.quota_reset_date || null,
34
+ };
35
+ return result;
36
+ }
37
+ catch (error) {
38
+ log.error('[QUOTA] Error fetching quota:', error);
39
+ return null;
40
+ }
41
+ }
42
+ //# sourceMappingURL=quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota.js","sourceRoot":"","sources":["../../src/plugin/quota.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AAwBlC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,8CAA8C,CAAC;QAE3D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,eAAe,EAAE,SAAS,UAAU,EAAE;gBACtC,YAAY,EAAE,mBAAmB;gBACjC,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,GAAG,CAAC,IAAI,CAAC,4BAA4B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/E,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;QAE5D,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,oBAAoB,CAAC;QAEvE,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,SAAS,IAAI,mBAAmB,EAAE,eAAe,IAAI,CAAC,CAAC;QACrG,MAAM,YAAY,GAAG,mBAAmB,EAAE,WAAW,IAAI,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAiB;YAC3B,IAAI,EAAE,IAAI,CAAC,YAAY,IAAI,SAAS;YACpC,GAAG,EAAE,IAAI,CAAC,eAAe,IAAI,SAAS;YACtC,OAAO,EAAE;gBACP,SAAS,EAAE,gBAAgB;gBAC3B,KAAK,EAAE,YAAY;gBACnB,gBAAgB,EAAE,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;aAC9D;YACD,SAAS,EAAE,IAAI,CAAC,uBAAuB,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI;SACzE,CAAC;QAEF,OAAO,MAAM,CAAC;IAEhB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAc,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { CopilotAccount } from "./accounts.js";
2
+ export declare class TokenManager {
3
+ constructor();
4
+ getToken(account: CopilotAccount): string;
5
+ }
@@ -0,0 +1,7 @@
1
+ export class TokenManager {
2
+ constructor() { }
3
+ getToken(account) {
4
+ return account.oauthToken;
5
+ }
6
+ }
7
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/plugin/token.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,YAAY;IACrB,gBAAe,CAAC;IAEhB,QAAQ,CAAC,OAAuB;QAC5B,OAAO,OAAO,CAAC,UAAU,CAAA;IAC7B,CAAC;CACJ"}
@@ -0,0 +1,41 @@
1
+ export declare const ANSI: {
2
+ readonly hide: "\u001B[?25l";
3
+ readonly show: "\u001B[?25h";
4
+ readonly up: (n?: number) => string;
5
+ readonly down: (n?: number) => string;
6
+ readonly clearLine: "\u001B[2K";
7
+ readonly clearScreen: "\u001B[2J";
8
+ readonly moveTo: (row: number, col: number) => string;
9
+ readonly cyan: "\u001B[36m";
10
+ readonly green: "\u001B[32m";
11
+ readonly red: "\u001B[31m";
12
+ readonly yellow: "\u001B[33m";
13
+ readonly dim: "\u001B[2m";
14
+ readonly bold: "\u001B[1m";
15
+ readonly reset: "\u001B[0m";
16
+ readonly inverse: "\u001B[7m";
17
+ readonly box: {
18
+ readonly topLeft: "┌";
19
+ readonly topRight: "┐";
20
+ readonly bottomLeft: "└";
21
+ readonly bottomRight: "┘";
22
+ readonly horizontal: "─";
23
+ readonly vertical: "│";
24
+ readonly cross: "┼";
25
+ readonly teeRight: "├";
26
+ readonly teeLeft: "┤";
27
+ readonly teeUp: "┴";
28
+ readonly teeDown: "┬";
29
+ readonly roundedTopLeft: "╭";
30
+ readonly roundedTopRight: "╮";
31
+ readonly roundedBottomLeft: "╰";
32
+ readonly roundedBottomRight: "╯";
33
+ };
34
+ readonly bar: {
35
+ readonly full: "█";
36
+ readonly empty: "░";
37
+ };
38
+ };
39
+ export type KeyAction = 'up' | 'down' | 'enter' | 'escape' | 'escape-start' | null;
40
+ export declare function parseKey(data: Buffer): KeyAction;
41
+ export declare function isTTY(): boolean;
@@ -0,0 +1,67 @@
1
+ export const ANSI = {
2
+ // Cursor control
3
+ hide: '\x1b[?25l',
4
+ show: '\x1b[?25h',
5
+ up: (n = 1) => `\x1b[${n}A`,
6
+ down: (n = 1) => `\x1b[${n}B`,
7
+ clearLine: '\x1b[2K',
8
+ clearScreen: '\x1b[2J',
9
+ moveTo: (row, col) => `\x1b[${row};${col}H`,
10
+ // Styles
11
+ cyan: '\x1b[36m',
12
+ green: '\x1b[32m',
13
+ red: '\x1b[31m',
14
+ yellow: '\x1b[33m',
15
+ dim: '\x1b[2m',
16
+ bold: '\x1b[1m',
17
+ reset: '\x1b[0m',
18
+ inverse: '\x1b[7m',
19
+ // Box drawing characters
20
+ box: {
21
+ topLeft: '┌',
22
+ topRight: '┐',
23
+ bottomLeft: '└',
24
+ bottomRight: '┘',
25
+ horizontal: '─',
26
+ vertical: '│',
27
+ cross: '┼',
28
+ teeRight: '├',
29
+ teeLeft: '┤',
30
+ teeUp: '┴',
31
+ teeDown: '┬',
32
+ // Rounded corners
33
+ roundedTopLeft: '╭',
34
+ roundedTopRight: '╮',
35
+ roundedBottomLeft: '╰',
36
+ roundedBottomRight: '╯',
37
+ },
38
+ // Progress bar characters
39
+ bar: {
40
+ full: '█',
41
+ empty: '░',
42
+ }
43
+ };
44
+ export function parseKey(data) {
45
+ const s = data.toString();
46
+ // COMPAT: Arrow keys differ by platform - Standard: \x1b[A/B, Application mode: \x1bOA/B
47
+ if (s === '\x1b[A' || s === '\x1bOA') {
48
+ return 'up';
49
+ }
50
+ else if (s === '\x1b[B' || s === '\x1bOB') {
51
+ return 'down';
52
+ }
53
+ else if (s === '\r' || s === '\n') {
54
+ return 'enter';
55
+ }
56
+ else if (s === '\x03') {
57
+ return 'escape';
58
+ }
59
+ else if (s === '\x1b') {
60
+ return 'escape-start';
61
+ }
62
+ return null;
63
+ }
64
+ export function isTTY() {
65
+ return Boolean(process.stdin.isTTY);
66
+ }
67
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../../src/plugin/ui/ansi.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,iBAAiB;IACjB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;IACjB,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG;IAC3B,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG;IAC7B,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,MAAM,EAAE,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG;IAE3D,SAAS;IACT,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,SAAS;IAElB,yBAAyB;IACzB,GAAG,EAAE;QACH,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,GAAG;QACb,UAAU,EAAE,GAAG;QACf,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,GAAG;QACb,KAAK,EAAE,GAAG;QACV,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,GAAG;QACZ,KAAK,EAAE,GAAG;QACV,OAAO,EAAE,GAAG;QAEZ,kBAAkB;QAClB,cAAc,EAAE,GAAG;QACnB,eAAe,EAAE,GAAG;QACpB,iBAAiB,EAAE,GAAG;QACtB,kBAAkB,EAAE,GAAG;KACxB;IAED,0BAA0B;IAC1B,GAAG,EAAE;QACH,IAAI,EAAE,GAAG;QACT,KAAK,EAAE,GAAG;KACX;CACO,CAAC;AAIX,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAE1B,yFAAyF;IACzF,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;SAAM,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;SAAM,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;SAAM,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;SAAM,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function confirm(message: string, defaultYes?: boolean): Promise<boolean>;
@@ -0,0 +1,15 @@
1
+ import { select } from './select.js';
2
+ export async function confirm(message, defaultYes = false) {
3
+ const items = defaultYes
4
+ ? [
5
+ { label: 'Yes', value: true },
6
+ { label: 'No', value: false },
7
+ ]
8
+ : [
9
+ { label: 'No', value: false },
10
+ { label: 'Yes', value: true },
11
+ ];
12
+ const result = await select(items, { message });
13
+ return result ?? false;
14
+ }
15
+ //# sourceMappingURL=confirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../../src/plugin/ui/confirm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,UAAU,GAAG,KAAK;IAC/D,MAAM,KAAK,GAAG,UAAU;QACtB,CAAC,CAAC;YACE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;YAC7B,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;SAC9B;QACH,CAAC,CAAC;YACE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;YAC7B,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;SAC9B,CAAC;IAEN,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,OAAO,MAAM,IAAI,KAAK,CAAC;AACzB,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface MenuItem<T = string> {
2
+ label: string;
3
+ value: T;
4
+ hint?: string;
5
+ disabled?: boolean;
6
+ separator?: boolean;
7
+ color?: 'red' | 'green' | 'yellow' | 'cyan';
8
+ }
9
+ export interface SelectOptions {
10
+ message: string;
11
+ subtitle?: string;
12
+ }
13
+ export declare function select<T>(items: MenuItem<T>[], options: SelectOptions): Promise<T | null>;
@@ -0,0 +1,170 @@
1
+ import { ANSI, isTTY, parseKey } from './ansi.js';
2
+ const ESCAPE_TIMEOUT_MS = 50;
3
+ function getColorCode(color) {
4
+ switch (color) {
5
+ case 'red': return ANSI.red;
6
+ case 'green': return ANSI.green;
7
+ case 'yellow': return ANSI.yellow;
8
+ case 'cyan': return ANSI.cyan;
9
+ default: return '';
10
+ }
11
+ }
12
+ export async function select(items, options) {
13
+ if (!isTTY()) {
14
+ throw new Error('Interactive select requires a TTY terminal');
15
+ }
16
+ if (items.length === 0) {
17
+ throw new Error('No menu items provided');
18
+ }
19
+ const enabledItems = items.filter(i => !i.disabled && !i.separator);
20
+ if (enabledItems.length === 0) {
21
+ throw new Error('All items disabled');
22
+ }
23
+ if (enabledItems.length === 1) {
24
+ return enabledItems[0].value;
25
+ }
26
+ const { message, subtitle } = options;
27
+ const { stdin, stdout } = process;
28
+ let cursor = items.findIndex(i => !i.disabled && !i.separator);
29
+ if (cursor === -1)
30
+ cursor = 0;
31
+ let escapeTimeout = null;
32
+ let isCleanedUp = false;
33
+ let isFirstRender = true;
34
+ const getTotalLines = () => {
35
+ const subtitleLines = subtitle ? 3 : 0;
36
+ return 1 + subtitleLines + items.length + 1 + 1;
37
+ };
38
+ const render = () => {
39
+ const totalLines = getTotalLines();
40
+ if (!isFirstRender) {
41
+ stdout.write(ANSI.up(totalLines) + '\r');
42
+ }
43
+ isFirstRender = false;
44
+ stdout.write(`${ANSI.clearLine}${ANSI.dim}┌ ${ANSI.reset}${message}\n`);
45
+ if (subtitle) {
46
+ stdout.write(`${ANSI.clearLine}${ANSI.dim}│${ANSI.reset}\n`);
47
+ stdout.write(`${ANSI.clearLine}${ANSI.cyan}◆${ANSI.reset} ${subtitle}\n`);
48
+ stdout.write(`${ANSI.clearLine}\n`);
49
+ }
50
+ for (let i = 0; i < items.length; i++) {
51
+ const item = items[i];
52
+ if (!item)
53
+ continue;
54
+ if (item.separator) {
55
+ stdout.write(`${ANSI.clearLine}${ANSI.dim}│${ANSI.reset}\n`);
56
+ continue;
57
+ }
58
+ const isSelected = i === cursor;
59
+ const colorCode = getColorCode(item.color);
60
+ let labelText;
61
+ if (item.disabled) {
62
+ labelText = `${ANSI.dim}${item.label} (unavailable)${ANSI.reset}`;
63
+ }
64
+ else if (isSelected) {
65
+ labelText = colorCode ? `${colorCode}${item.label}${ANSI.reset}` : item.label;
66
+ if (item.hint)
67
+ labelText += ` ${ANSI.dim}${item.hint}${ANSI.reset}`;
68
+ }
69
+ else {
70
+ labelText = colorCode
71
+ ? `${ANSI.dim}${colorCode}${item.label}${ANSI.reset}`
72
+ : `${ANSI.dim}${item.label}${ANSI.reset}`;
73
+ if (item.hint)
74
+ labelText += ` ${ANSI.dim}${item.hint}${ANSI.reset}`;
75
+ }
76
+ if (isSelected) {
77
+ stdout.write(`${ANSI.clearLine}${ANSI.cyan}│${ANSI.reset} ${ANSI.green}●${ANSI.reset} ${labelText}\n`);
78
+ }
79
+ else {
80
+ stdout.write(`${ANSI.clearLine}${ANSI.cyan}│${ANSI.reset} ${ANSI.dim}○${ANSI.reset} ${labelText}\n`);
81
+ }
82
+ }
83
+ stdout.write(`${ANSI.clearLine}${ANSI.cyan}│${ANSI.reset} ${ANSI.dim}↑/↓ to select • Enter: confirm${ANSI.reset}\n`);
84
+ stdout.write(`${ANSI.clearLine}${ANSI.cyan}└${ANSI.reset}\n`);
85
+ };
86
+ return new Promise((resolve) => {
87
+ const wasRaw = stdin.isRaw ?? false;
88
+ const cleanup = () => {
89
+ if (isCleanedUp)
90
+ return;
91
+ isCleanedUp = true;
92
+ if (escapeTimeout) {
93
+ clearTimeout(escapeTimeout);
94
+ escapeTimeout = null;
95
+ }
96
+ try {
97
+ stdin.removeListener('data', onKey);
98
+ stdin.setRawMode(wasRaw);
99
+ stdin.pause();
100
+ stdout.write(ANSI.show);
101
+ }
102
+ catch {
103
+ }
104
+ process.removeListener('SIGINT', onSignal);
105
+ process.removeListener('SIGTERM', onSignal);
106
+ };
107
+ const onSignal = () => {
108
+ cleanup();
109
+ resolve(null);
110
+ };
111
+ const finishWithValue = (value) => {
112
+ cleanup();
113
+ resolve(value);
114
+ };
115
+ const findNextSelectable = (from, direction) => {
116
+ if (items.length === 0)
117
+ return from;
118
+ let next = from;
119
+ do {
120
+ next = (next + direction + items.length) % items.length;
121
+ } while (items[next]?.disabled || items[next]?.separator);
122
+ return next;
123
+ };
124
+ const onKey = (data) => {
125
+ if (escapeTimeout) {
126
+ clearTimeout(escapeTimeout);
127
+ escapeTimeout = null;
128
+ }
129
+ const action = parseKey(data);
130
+ switch (action) {
131
+ case 'up':
132
+ cursor = findNextSelectable(cursor, -1);
133
+ render();
134
+ return;
135
+ case 'down':
136
+ cursor = findNextSelectable(cursor, 1);
137
+ render();
138
+ return;
139
+ case 'enter':
140
+ finishWithValue(items[cursor]?.value ?? null);
141
+ return;
142
+ case 'escape':
143
+ finishWithValue(null);
144
+ return;
145
+ case 'escape-start':
146
+ escapeTimeout = setTimeout(() => {
147
+ finishWithValue(null);
148
+ }, ESCAPE_TIMEOUT_MS);
149
+ return;
150
+ default:
151
+ return;
152
+ }
153
+ };
154
+ process.once('SIGINT', onSignal);
155
+ process.once('SIGTERM', onSignal);
156
+ try {
157
+ stdin.setRawMode(true);
158
+ }
159
+ catch {
160
+ cleanup();
161
+ resolve(null);
162
+ return;
163
+ }
164
+ stdin.resume();
165
+ stdout.write(ANSI.hide);
166
+ render();
167
+ stdin.on('data', onKey);
168
+ });
169
+ }
170
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/plugin/ui/select.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "gh-multi",
3
+ "version": "0.1.0",
4
+ "description": "Multi-account GitHub Copilot plugin for opencode - hooks into native provider",
5
+ "main": "gh-multi-dist/index.js",
6
+ "types": "gh-multi-dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./gh-multi-dist/index.d.ts",
10
+ "import": "./gh-multi-dist/index.js"
11
+ }
12
+ },
13
+ "type": "module",
14
+ "license": "MIT",
15
+ "files": [
16
+ "gh-multi-dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.build.json",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "keywords": [
26
+ "opencode",
27
+ "github-copilot",
28
+ "multi-account"
29
+ ],
30
+ "eslintConfig": {
31
+ "rules": {
32
+ "no-unused-vars": "error",
33
+ "no-unreachable": "error"
34
+ }
35
+ },
36
+ "dependencies": {
37
+ "@openauthjs/openauth": "^0.4.3",
38
+ "@opencode-ai/plugin": "^1.1.36",
39
+ "@opencode-ai/sdk": "^1.1.36",
40
+ "proper-lockfile": "^4.1.2",
41
+ "xdg-basedir": "^5.1.0",
42
+ "zod": "^3.24.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/bun": "^1.3.7",
46
+ "@types/node": "^22.0.0",
47
+ "@types/proper-lockfile": "^4.1.4",
48
+ "typescript": "^5.3.0",
49
+ "vitest": "^1.0.0",
50
+ "zod-to-json-schema": "^3.25.0"
51
+ }
52
+ }