@ai-ide-bridge/copilot 1.0.5 → 1.1.1

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @ai-ide-bridge/copilot@1.0.5 build /home/runner/work/llm-bridge/llm-bridge/packages/copilot
2
+ > @ai-ide-bridge/copilot@1.1.1 build /home/runner/work/llm-bridge/llm-bridge/packages/copilot
3
3
  > tsc
4
4
 
package/dist/auth.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { CopilotConfig } from './types.js';
2
2
  export declare function validateToken(token: string): Promise<boolean>;
3
- export declare function getToken(config: CopilotConfig): string | null;
4
- export declare function refreshOAuthToken(_refreshToken: string, _clientId: string, _clientSecret: string): Promise<{
3
+ export declare function getToken(config: CopilotConfig): Promise<string | null>;
4
+ export declare function refreshOAuthToken(refreshToken: string, clientId: string, _clientSecret: string): Promise<{
5
5
  accessToken: string;
6
6
  refreshToken: string;
7
7
  } | null>;
package/dist/auth.js CHANGED
@@ -14,11 +14,45 @@ export async function validateToken(token) {
14
14
  return false;
15
15
  }
16
16
  }
17
- export function getToken(config) {
18
- return config.COPILOT_TOKEN ?? config.COPILOT_OAUTH_TOKEN ?? null;
17
+ export async function getToken(config) {
18
+ if (config.COPILOT_TOKEN)
19
+ return config.COPILOT_TOKEN;
20
+ try {
21
+ const { createTokenStore } = await import('@ai-ide-bridge/oauth');
22
+ const store = createTokenStore();
23
+ const token = await store.get('copilot');
24
+ if (token && Date.now() < token.expiresAt) {
25
+ return token.accessToken;
26
+ }
27
+ }
28
+ catch {
29
+ // OAuth package may not be available
30
+ }
31
+ return config.COPILOT_OAUTH_TOKEN ?? null;
19
32
  }
20
- // OAuth placeholder wired up when OAuth Phase 2 is implemented
21
- export async function refreshOAuthToken(_refreshToken, _clientId, _clientSecret) {
22
- // TODO: Implement GitHub OAuth with PKCE flow
23
- return null;
33
+ export async function refreshOAuthToken(refreshToken, clientId, _clientSecret) {
34
+ try {
35
+ const params = new URLSearchParams({
36
+ grant_type: 'refresh_token',
37
+ refresh_token: refreshToken,
38
+ client_id: clientId,
39
+ });
40
+ const response = await fetch('https://github.com/login/oauth/access_token', {
41
+ method: 'POST',
42
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
43
+ body: params.toString(),
44
+ });
45
+ if (!response.ok)
46
+ return null;
47
+ const data = (await response.json());
48
+ if (!data.access_token)
49
+ return null;
50
+ return {
51
+ accessToken: data.access_token,
52
+ refreshToken: data.refresh_token ?? refreshToken,
53
+ };
54
+ }
55
+ catch {
56
+ return null;
57
+ }
24
58
  }
package/dist/plugin.js CHANGED
@@ -5,13 +5,13 @@ export class CopilotBridgePlugin {
5
5
  name = 'copilot';
6
6
  version = '2.0.0';
7
7
  async authenticate(config) {
8
- const token = getToken(config);
8
+ const token = await getToken(config);
9
9
  if (!token)
10
10
  return false;
11
11
  return validateToken(token);
12
12
  }
13
13
  async listModels(config) {
14
- const token = getToken(config);
14
+ const token = await getToken(config);
15
15
  if (!token)
16
16
  throw new Error('Missing COPILOT_TOKEN');
17
17
  return COPILOT_MODELS.map((m) => ({
@@ -21,7 +21,7 @@ export class CopilotBridgePlugin {
21
21
  }));
22
22
  }
23
23
  async createSession(config, model) {
24
- const token = getToken(config);
24
+ const token = await getToken(config);
25
25
  if (!token)
26
26
  throw new Error('Missing COPILOT_TOKEN');
27
27
  return new CopilotBridgeSession(token, model);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ide-bridge/copilot",
3
- "version": "1.0.5",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,7 +12,8 @@
12
12
  "dev": "tsc --watch"
13
13
  },
14
14
  "dependencies": {
15
- "@ai-ide-bridge/core": "workspace:*"
15
+ "@ai-ide-bridge/core": "workspace:*",
16
+ "@ai-ide-bridge/oauth": "workspace:*"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@types/node": "^22.15.0",
package/src/auth.ts CHANGED
@@ -17,16 +17,51 @@ export async function validateToken(token: string): Promise<boolean> {
17
17
  }
18
18
  }
19
19
 
20
- export function getToken(config: CopilotConfig): string | null {
21
- return config.COPILOT_TOKEN ?? config.COPILOT_OAUTH_TOKEN ?? null;
20
+ export async function getToken(config: CopilotConfig): Promise<string | null> {
21
+ if (config.COPILOT_TOKEN) return config.COPILOT_TOKEN;
22
+
23
+ try {
24
+ const { createTokenStore } = await import('@ai-ide-bridge/oauth');
25
+ const store = createTokenStore();
26
+ const token = await store.get('copilot');
27
+ if (token && Date.now() < token.expiresAt) {
28
+ return token.accessToken;
29
+ }
30
+ } catch {
31
+ // OAuth package may not be available
32
+ }
33
+
34
+ return config.COPILOT_OAUTH_TOKEN ?? null;
22
35
  }
23
36
 
24
- // OAuth placeholder — wired up when OAuth Phase 2 is implemented
25
37
  export async function refreshOAuthToken(
26
- _refreshToken: string,
27
- _clientId: string,
38
+ refreshToken: string,
39
+ clientId: string,
28
40
  _clientSecret: string,
29
41
  ): Promise<{ accessToken: string; refreshToken: string } | null> {
30
- // TODO: Implement GitHub OAuth with PKCE flow
31
- return null;
42
+ try {
43
+ const params = new URLSearchParams({
44
+ grant_type: 'refresh_token',
45
+ refresh_token: refreshToken,
46
+ client_id: clientId,
47
+ });
48
+
49
+ const response = await fetch('https://github.com/login/oauth/access_token', {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
52
+ body: params.toString(),
53
+ });
54
+
55
+ if (!response.ok) return null;
56
+
57
+ const data = (await response.json()) as Record<string, unknown>;
58
+ if (!data.access_token) return null;
59
+
60
+ return {
61
+ accessToken: data.access_token as string,
62
+ refreshToken: (data.refresh_token as string) ?? refreshToken,
63
+ };
64
+ } catch {
65
+ return null;
66
+ }
32
67
  }
package/src/plugin.ts CHANGED
@@ -8,13 +8,13 @@ export class CopilotBridgePlugin implements BridgePlugin {
8
8
  version = '2.0.0';
9
9
 
10
10
  async authenticate(config: Record<string, string>): Promise<boolean> {
11
- const token = getToken(config as CopilotConfig);
11
+ const token = await getToken(config as CopilotConfig);
12
12
  if (!token) return false;
13
13
  return validateToken(token);
14
14
  }
15
15
 
16
16
  async listModels(config: Record<string, string>): Promise<ModelInfo[]> {
17
- const token = getToken(config as CopilotConfig);
17
+ const token = await getToken(config as CopilotConfig);
18
18
  if (!token) throw new Error('Missing COPILOT_TOKEN');
19
19
  return COPILOT_MODELS.map((m) => ({
20
20
  id: m.id,
@@ -24,7 +24,7 @@ export class CopilotBridgePlugin implements BridgePlugin {
24
24
  }
25
25
 
26
26
  async createSession(config: Record<string, string>, model: string): Promise<BridgeSession> {
27
- const token = getToken(config as CopilotConfig);
27
+ const token = await getToken(config as CopilotConfig);
28
28
  if (!token) throw new Error('Missing COPILOT_TOKEN');
29
29
  return new CopilotBridgeSession(token, model);
30
30
  }
package/test/auth.test.ts CHANGED
@@ -2,23 +2,23 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
2
  import { getToken, validateToken } from '../src/auth.js';
3
3
 
4
4
  describe('getToken', () => {
5
- it('returns COPILOT_TOKEN when present', () => {
6
- const result = getToken({ COPILOT_TOKEN: 'test-token' });
5
+ it('returns COPILOT_TOKEN when present', async () => {
6
+ const result = await getToken({ COPILOT_TOKEN: 'test-token' });
7
7
  expect(result).toBe('test-token');
8
8
  });
9
9
 
10
- it('returns COPILOT_OAUTH_TOKEN when COPILOT_TOKEN is missing', () => {
11
- const result = getToken({ COPILOT_OAUTH_TOKEN: 'oauth-token' });
10
+ it('returns COPILOT_OAUTH_TOKEN when COPILOT_TOKEN is missing', async () => {
11
+ const result = await getToken({ COPILOT_OAUTH_TOKEN: 'oauth-token' });
12
12
  expect(result).toBe('oauth-token');
13
13
  });
14
14
 
15
- it('returns null when no token is present', () => {
16
- const result = getToken({});
15
+ it('returns null when no token is present', async () => {
16
+ const result = await getToken({});
17
17
  expect(result).toBeNull();
18
18
  });
19
19
 
20
- it('prefers COPILOT_TOKEN over COPILOT_OAUTH_TOKEN', () => {
21
- const result = getToken({
20
+ it('prefers COPILOT_TOKEN over COPILOT_OAUTH_TOKEN', async () => {
21
+ const result = await getToken({
22
22
  COPILOT_TOKEN: 'primary-token',
23
23
  COPILOT_OAUTH_TOKEN: 'fallback-token',
24
24
  });