@theia/ai-copilot 1.76.0-next.4 → 1.76.0-next.42
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 +87 -14
- package/lib/browser/copilot-auth-dialog.d.ts.map +1 -1
- package/lib/browser/copilot-auth-dialog.js +19 -11
- package/lib/browser/copilot-auth-dialog.js.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.d.ts +21 -1
- package/lib/browser/copilot-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.js +129 -26
- package/lib/browser/copilot-frontend-application-contribution.js.map +1 -1
- package/lib/common/copilot-auth-service.d.ts +27 -24
- package/lib/common/copilot-auth-service.d.ts.map +1 -1
- package/lib/common/copilot-language-models-manager.d.ts +6 -22
- package/lib/common/copilot-language-models-manager.d.ts.map +1 -1
- package/lib/common/copilot-language-models-manager.js +1 -13
- package/lib/common/copilot-language-models-manager.js.map +1 -1
- package/lib/common/copilot-preferences.d.ts +1 -0
- package/lib/common/copilot-preferences.d.ts.map +1 -1
- package/lib/common/copilot-preferences.js +24 -6
- package/lib/common/copilot-preferences.js.map +1 -1
- package/lib/common/index.d.ts +0 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +0 -1
- package/lib/common/index.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.d.ts +25 -16
- package/lib/node/copilot-auth-service-impl.d.ts.map +1 -1
- package/lib/node/copilot-auth-service-impl.js +67 -183
- package/lib/node/copilot-auth-service-impl.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.spec.js +104 -168
- package/lib/node/copilot-auth-service-impl.spec.js.map +1 -1
- package/lib/node/copilot-backend-module.d.ts.map +1 -1
- package/lib/node/copilot-backend-module.js +10 -2
- package/lib/node/copilot-backend-module.js.map +1 -1
- package/lib/node/copilot-cli-auth-provider.d.ts +146 -0
- package/lib/node/copilot-cli-auth-provider.d.ts.map +1 -0
- package/lib/node/copilot-cli-auth-provider.js +430 -0
- package/lib/node/copilot-cli-auth-provider.js.map +1 -0
- package/lib/node/copilot-cli-auth-provider.spec.d.ts +2 -0
- package/lib/node/copilot-cli-auth-provider.spec.d.ts.map +1 -0
- package/lib/node/copilot-cli-auth-provider.spec.js +249 -0
- package/lib/node/copilot-cli-auth-provider.spec.js.map +1 -0
- package/lib/node/copilot-cli-locator.d.ts +120 -0
- package/lib/node/copilot-cli-locator.d.ts.map +1 -0
- package/lib/node/copilot-cli-locator.js +348 -0
- package/lib/node/copilot-cli-locator.js.map +1 -0
- package/lib/node/copilot-cli-locator.spec.d.ts +2 -0
- package/lib/node/copilot-cli-locator.spec.d.ts.map +1 -0
- package/lib/node/copilot-cli-locator.spec.js +327 -0
- package/lib/node/copilot-cli-locator.spec.js.map +1 -0
- package/lib/node/copilot-credential-store.d.ts +45 -0
- package/lib/node/copilot-credential-store.d.ts.map +1 -0
- package/lib/node/copilot-credential-store.js +96 -0
- package/lib/node/copilot-credential-store.js.map +1 -0
- package/lib/node/copilot-credential-store.spec.d.ts +2 -0
- package/lib/node/copilot-credential-store.spec.d.ts.map +1 -0
- package/lib/node/copilot-credential-store.spec.js +93 -0
- package/lib/node/copilot-credential-store.spec.js.map +1 -0
- package/lib/node/copilot-language-models-manager-impl.d.ts +44 -20
- package/lib/node/copilot-language-models-manager-impl.d.ts.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.js +112 -65
- package/lib/node/copilot-language-models-manager-impl.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.spec.d.ts +2 -0
- package/lib/node/copilot-language-models-manager-impl.spec.d.ts.map +1 -0
- package/lib/node/copilot-language-models-manager-impl.spec.js +162 -0
- package/lib/node/copilot-language-models-manager-impl.spec.js.map +1 -0
- package/lib/node/copilot-runtime-env.d.ts +20 -0
- package/lib/node/copilot-runtime-env.d.ts.map +1 -0
- package/lib/node/copilot-runtime-env.js +49 -0
- package/lib/node/copilot-runtime-env.js.map +1 -0
- package/lib/node/copilot-sdk-client-provider.d.ts +103 -0
- package/lib/node/copilot-sdk-client-provider.d.ts.map +1 -0
- package/lib/node/copilot-sdk-client-provider.js +247 -0
- package/lib/node/copilot-sdk-client-provider.js.map +1 -0
- package/lib/node/copilot-sdk-client-provider.spec.d.ts +2 -0
- package/lib/node/copilot-sdk-client-provider.spec.d.ts.map +1 -0
- package/lib/node/copilot-sdk-client-provider.spec.js +215 -0
- package/lib/node/copilot-sdk-client-provider.spec.js.map +1 -0
- package/lib/node/copilot-sdk-language-model.d.ts +85 -0
- package/lib/node/copilot-sdk-language-model.d.ts.map +1 -0
- package/lib/node/copilot-sdk-language-model.js +301 -0
- package/lib/node/copilot-sdk-language-model.js.map +1 -0
- package/lib/node/copilot-sdk-language-model.spec.d.ts +2 -0
- package/lib/node/copilot-sdk-language-model.spec.d.ts.map +1 -0
- package/lib/node/copilot-sdk-language-model.spec.js +315 -0
- package/lib/node/copilot-sdk-language-model.spec.js.map +1 -0
- package/lib/node/copilot-sdk-loader.d.ts +57 -0
- package/lib/node/copilot-sdk-loader.d.ts.map +1 -0
- package/lib/node/copilot-sdk-loader.js +133 -0
- package/lib/node/copilot-sdk-loader.js.map +1 -0
- package/lib/node/copilot-sdk-loader.spec.d.ts +2 -0
- package/lib/node/copilot-sdk-loader.spec.d.ts.map +1 -0
- package/lib/node/copilot-sdk-loader.spec.js +113 -0
- package/lib/node/copilot-sdk-loader.spec.js.map +1 -0
- package/lib/node/copilot-sdk-mappers.d.ts +54 -0
- package/lib/node/copilot-sdk-mappers.d.ts.map +1 -0
- package/lib/node/copilot-sdk-mappers.js +158 -0
- package/lib/node/copilot-sdk-mappers.js.map +1 -0
- package/lib/node/copilot-sdk-mappers.spec.d.ts +2 -0
- package/lib/node/copilot-sdk-mappers.spec.d.ts.map +1 -0
- package/lib/node/copilot-sdk-mappers.spec.js +168 -0
- package/lib/node/copilot-sdk-mappers.spec.js.map +1 -0
- package/lib/node/copilot-sdk-types.d.ts +208 -0
- package/lib/node/copilot-sdk-types.d.ts.map +1 -0
- package/lib/{common/copilot-oauth-config.js → node/copilot-sdk-types.js} +2 -13
- package/lib/node/copilot-sdk-types.js.map +1 -0
- package/lib/node/index.d.ts +9 -1
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +9 -1
- package/lib/node/index.js.map +1 -1
- package/package.json +4 -6
- package/src/browser/copilot-auth-dialog.tsx +20 -16
- package/src/browser/copilot-frontend-application-contribution.ts +144 -31
- package/src/common/copilot-auth-service.ts +28 -24
- package/src/common/copilot-language-models-manager.ts +6 -29
- package/src/common/copilot-preferences.ts +24 -5
- package/src/common/index.ts +0 -1
- package/src/node/copilot-auth-service-impl.spec.ts +122 -207
- package/src/node/copilot-auth-service-impl.ts +63 -218
- package/src/node/copilot-backend-module.ts +11 -2
- package/src/node/copilot-cli-auth-provider.spec.ts +315 -0
- package/src/node/copilot-cli-auth-provider.ts +444 -0
- package/src/node/copilot-cli-locator.spec.ts +386 -0
- package/src/node/copilot-cli-locator.ts +363 -0
- package/src/node/copilot-credential-store.spec.ts +106 -0
- package/src/node/copilot-credential-store.ts +99 -0
- package/src/node/copilot-language-models-manager-impl.spec.ts +188 -0
- package/src/node/copilot-language-models-manager-impl.ts +131 -84
- package/src/node/copilot-runtime-env.ts +46 -0
- package/src/node/copilot-sdk-client-provider.spec.ts +253 -0
- package/src/node/copilot-sdk-client-provider.ts +241 -0
- package/src/node/copilot-sdk-language-model.spec.ts +377 -0
- package/src/node/copilot-sdk-language-model.ts +330 -0
- package/src/node/copilot-sdk-loader.spec.ts +126 -0
- package/src/node/copilot-sdk-loader.ts +142 -0
- package/src/node/copilot-sdk-mappers.spec.ts +190 -0
- package/src/node/copilot-sdk-mappers.ts +172 -0
- package/src/node/copilot-sdk-types.ts +290 -0
- package/src/node/index.ts +9 -1
- package/lib/common/copilot-oauth-config.d.ts +0 -33
- package/lib/common/copilot-oauth-config.d.ts.map +0 -1
- package/lib/common/copilot-oauth-config.js.map +0 -1
- package/lib/node/copilot-language-model.d.ts +0 -34
- package/lib/node/copilot-language-model.d.ts.map +0 -1
- package/lib/node/copilot-language-model.js +0 -236
- package/lib/node/copilot-language-model.js.map +0 -1
- package/lib/node/copilot-language-model.spec.d.ts +0 -2
- package/lib/node/copilot-language-model.spec.d.ts.map +0 -1
- package/lib/node/copilot-language-model.spec.js +0 -89
- package/lib/node/copilot-language-model.spec.js.map +0 -1
- package/src/common/copilot-oauth-config.ts +0 -55
- package/src/node/copilot-language-model.spec.ts +0 -106
- package/src/node/copilot-language-model.ts +0 -273
|
@@ -19,223 +19,107 @@ exports.CopilotAuthServiceImpl = void 0;
|
|
|
19
19
|
const tslib_1 = require("tslib");
|
|
20
20
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
21
|
const core_1 = require("@theia/core");
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const COPILOT_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
|
|
22
|
+
const copilot_cli_auth_provider_1 = require("./copilot-cli-auth-provider");
|
|
23
|
+
const copilot_cli_locator_1 = require("./copilot-cli-locator");
|
|
24
|
+
const copilot_credential_store_1 = require("./copilot-credential-store");
|
|
26
25
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Backend implementation of the GitHub Copilot OAuth Device Flow authentication service.
|
|
33
|
-
* Handles device code generation, token polling, and credential storage.
|
|
26
|
+
* Backend implementation of the GitHub Copilot authentication service.
|
|
27
|
+
*
|
|
28
|
+
* All Copilot requests are served by the official Copilot CLI, which owns its credentials, so this
|
|
29
|
+
* service only drives the sign-in of the CLI and reports its state, see {@link CopilotCliAuthProvider}.
|
|
34
30
|
*/
|
|
35
31
|
let CopilotAuthServiceImpl = class CopilotAuthServiceImpl {
|
|
36
32
|
constructor() {
|
|
33
|
+
this.migrationRequired = false;
|
|
37
34
|
this.onAuthStateChangedEmitter = new core_1.Emitter();
|
|
38
35
|
this.onAuthStateChanged = this.onAuthStateChangedEmitter.event;
|
|
39
36
|
}
|
|
37
|
+
init() {
|
|
38
|
+
// The previous integration signed in with an OAuth application of its own and stored a token
|
|
39
|
+
// that is of no use here. Remove it instead of leaving it on the machine of the user.
|
|
40
|
+
this.legacyCleanup = this.credentialStore.deleteLegacy().then(async (removed) => {
|
|
41
|
+
this.migrationRequired = removed;
|
|
42
|
+
if (removed) {
|
|
43
|
+
this.logger.info('Copilot: discarded the sign-in of the previous integration, a new sign-in is required.');
|
|
44
|
+
this.updateAuthState(await this.computeAuthState());
|
|
45
|
+
}
|
|
46
|
+
}, error => this.logger.warn('Copilot: failed to clean up the previous sign-in:', error));
|
|
47
|
+
}
|
|
40
48
|
setClient(client) {
|
|
41
49
|
this.client = client;
|
|
42
50
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const domain = enterpriseUrl
|
|
46
|
-
.replace(/^https?:\/\//, '')
|
|
47
|
-
.replace(/\/$/, '');
|
|
48
|
-
return {
|
|
49
|
-
deviceCodeUrl: `https://${domain}/login/device/code`,
|
|
50
|
-
accessTokenUrl: `https://${domain}/login/oauth/access_token`
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
deviceCodeUrl: 'https://github.com/login/device/code',
|
|
55
|
-
accessTokenUrl: 'https://github.com/login/oauth/access_token'
|
|
56
|
-
};
|
|
51
|
+
async setExecutablePath(path) {
|
|
52
|
+
this.cliLocator.setConfiguredPath(path);
|
|
57
53
|
}
|
|
58
|
-
async
|
|
59
|
-
|
|
60
|
-
const response = await fetch(endpoints.deviceCodeUrl, {
|
|
61
|
-
method: 'POST',
|
|
62
|
-
headers: {
|
|
63
|
-
'Accept': 'application/json',
|
|
64
|
-
'Content-Type': 'application/json',
|
|
65
|
-
'User-Agent': this.oauthConfig.userAgent
|
|
66
|
-
},
|
|
67
|
-
body: JSON.stringify({
|
|
68
|
-
client_id: this.oauthConfig.clientId,
|
|
69
|
-
scope: COPILOT_SCOPE
|
|
70
|
-
})
|
|
71
|
-
});
|
|
72
|
-
if (!response.ok) {
|
|
73
|
-
const errorText = await response.text();
|
|
74
|
-
throw new Error(`Failed to initiate device authorization: ${response.status} - ${errorText}`);
|
|
75
|
-
}
|
|
76
|
-
const data = await response.json();
|
|
77
|
-
return data;
|
|
54
|
+
async startSignIn(enterpriseUrl) {
|
|
55
|
+
return this.cliAuthProvider.startLogin(enterpriseUrl);
|
|
78
56
|
}
|
|
79
|
-
async
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await this.
|
|
84
|
-
attempts++;
|
|
85
|
-
const response = await fetch(endpoints.accessTokenUrl, {
|
|
86
|
-
method: 'POST',
|
|
87
|
-
headers: {
|
|
88
|
-
'Accept': 'application/json',
|
|
89
|
-
'Content-Type': 'application/json',
|
|
90
|
-
'User-Agent': this.oauthConfig.userAgent
|
|
91
|
-
},
|
|
92
|
-
body: JSON.stringify({
|
|
93
|
-
client_id: this.oauthConfig.clientId,
|
|
94
|
-
device_code: deviceCode,
|
|
95
|
-
grant_type: COPILOT_GRANT_TYPE
|
|
96
|
-
})
|
|
97
|
-
});
|
|
98
|
-
if (!response.ok) {
|
|
99
|
-
this.logger.error(`Token request failed: ${response.status}`);
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
const data = await response.json();
|
|
103
|
-
if (data.access_token) {
|
|
104
|
-
// Get user info for account label
|
|
105
|
-
const accountLabel = await this.fetchAccountLabel(data.access_token, enterpriseUrl);
|
|
106
|
-
// Store credentials
|
|
107
|
-
const credentials = {
|
|
108
|
-
accessToken: data.access_token,
|
|
109
|
-
accountLabel,
|
|
110
|
-
enterpriseUrl
|
|
111
|
-
};
|
|
112
|
-
await this.keyStoreService.setPassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount, JSON.stringify(credentials));
|
|
113
|
-
// Update cached state and notify
|
|
114
|
-
const newState = {
|
|
115
|
-
isAuthenticated: true,
|
|
116
|
-
accountLabel,
|
|
117
|
-
enterpriseUrl
|
|
118
|
-
};
|
|
119
|
-
this.updateAuthState(newState);
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
if (data.error === 'authorization_pending') {
|
|
123
|
-
// User hasn't authorized yet, continue polling
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (data.error === 'slow_down') {
|
|
127
|
-
// Increase polling interval
|
|
128
|
-
interval += 5;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (data.error === 'expired_token' || data.error === 'access_denied') {
|
|
132
|
-
this.logger.error(`Authorization failed: ${data.error} - ${data.error_description}`);
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
if (data.error) {
|
|
136
|
-
this.logger.error(`Unexpected error: ${data.error} - ${data.error_description}`);
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
57
|
+
async waitForSignIn() {
|
|
58
|
+
const success = await this.cliAuthProvider.waitForLogin();
|
|
59
|
+
if (success) {
|
|
60
|
+
this.cachedState = undefined;
|
|
61
|
+
this.updateAuthState(await this.cliAuthProvider.getAuthState());
|
|
139
62
|
}
|
|
140
|
-
return
|
|
63
|
+
return success;
|
|
141
64
|
}
|
|
142
|
-
async
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'Authorization': `Bearer ${accessToken}`,
|
|
150
|
-
'User-Agent': this.oauthConfig.userAgent,
|
|
151
|
-
'Accept': 'application/vnd.github.v3+json'
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
if (response.ok) {
|
|
155
|
-
const userData = await response.json();
|
|
156
|
-
return userData.login;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
this.logger.warn('Failed to fetch GitHub user info:', error);
|
|
161
|
-
}
|
|
162
|
-
return undefined;
|
|
65
|
+
async cancelSignIn() {
|
|
66
|
+
await this.cliAuthProvider.cancelLogin();
|
|
67
|
+
}
|
|
68
|
+
async signOut() {
|
|
69
|
+
await this.cliAuthProvider.signOut();
|
|
70
|
+
this.cachedState = undefined;
|
|
71
|
+
this.updateAuthState(await this.getAuthState());
|
|
163
72
|
}
|
|
164
73
|
async getAuthState() {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const credentials = JSON.parse(stored);
|
|
172
|
-
// Tokens from the current OAuth App start with 'gho_'; other prefixes (e.g. 'ghu_') indicate a token from the previous GitHub App (Iv-prefixed client ID).
|
|
173
|
-
if (!credentials.accessToken.startsWith('gho_')) {
|
|
174
|
-
this.logger.info('Copilot: clearing outdated GitHub App token. Please sign in again.');
|
|
175
|
-
await this.keyStoreService.deletePassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
176
|
-
this.cachedState = { isAuthenticated: false, migrationRequired: true };
|
|
177
|
-
return this.cachedState;
|
|
178
|
-
}
|
|
179
|
-
this.cachedState = {
|
|
180
|
-
isAuthenticated: true,
|
|
181
|
-
accountLabel: credentials.accountLabel,
|
|
182
|
-
enterpriseUrl: credentials.enterpriseUrl
|
|
183
|
-
};
|
|
184
|
-
return this.cachedState;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
this.logger.warn('Failed to retrieve Copilot credentials:', error);
|
|
74
|
+
// Awaited so that a state requested early cannot be cached without the migration flag, which
|
|
75
|
+
// is the only thing that tells the user why they were signed out. The frontend evaluates it
|
|
76
|
+
// once at startup, so losing it there means losing it altogether.
|
|
77
|
+
await this.legacyCleanup;
|
|
78
|
+
if (!this.cachedState) {
|
|
79
|
+
this.cachedState = await this.computeAuthState();
|
|
189
80
|
}
|
|
190
|
-
this.cachedState = { isAuthenticated: false };
|
|
191
81
|
return this.cachedState;
|
|
192
82
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
this.logger.warn('Failed to retrieve Copilot access token:', error);
|
|
203
|
-
}
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
206
|
-
async signOut() {
|
|
207
|
-
try {
|
|
208
|
-
await this.keyStoreService.deletePassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
this.logger.warn('Failed to delete Copilot credentials:', error);
|
|
212
|
-
}
|
|
213
|
-
const newState = { isAuthenticated: false };
|
|
214
|
-
this.updateAuthState(newState);
|
|
83
|
+
/**
|
|
84
|
+
* The state as it currently is, with the request for a new sign-in attached when the credentials
|
|
85
|
+
* of the previous integration had to be discarded and none have been established since.
|
|
86
|
+
*
|
|
87
|
+
* Does not await the cleanup, so that it can be used from it.
|
|
88
|
+
*/
|
|
89
|
+
async computeAuthState() {
|
|
90
|
+
const state = await this.cliAuthProvider.getAuthState();
|
|
91
|
+
return state.isAuthenticated || !this.migrationRequired ? state : { ...state, migrationRequired: true };
|
|
215
92
|
}
|
|
216
93
|
updateAuthState(state) {
|
|
217
94
|
this.cachedState = state;
|
|
218
95
|
this.onAuthStateChangedEmitter.fire(state);
|
|
219
96
|
this.client?.onAuthStateChanged(state);
|
|
220
97
|
}
|
|
221
|
-
delay(ms) {
|
|
222
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
223
|
-
}
|
|
224
98
|
};
|
|
225
99
|
exports.CopilotAuthServiceImpl = CopilotAuthServiceImpl;
|
|
226
100
|
tslib_1.__decorate([
|
|
227
|
-
(0, inversify_1.inject)(
|
|
228
|
-
tslib_1.__metadata("design:type",
|
|
229
|
-
], CopilotAuthServiceImpl.prototype, "
|
|
101
|
+
(0, inversify_1.inject)(copilot_cli_auth_provider_1.CopilotCliAuthProvider),
|
|
102
|
+
tslib_1.__metadata("design:type", copilot_cli_auth_provider_1.CopilotCliAuthProvider)
|
|
103
|
+
], CopilotAuthServiceImpl.prototype, "cliAuthProvider", void 0);
|
|
104
|
+
tslib_1.__decorate([
|
|
105
|
+
(0, inversify_1.inject)(copilot_credential_store_1.CopilotCredentialStore),
|
|
106
|
+
tslib_1.__metadata("design:type", copilot_credential_store_1.CopilotCredentialStore)
|
|
107
|
+
], CopilotAuthServiceImpl.prototype, "credentialStore", void 0);
|
|
108
|
+
tslib_1.__decorate([
|
|
109
|
+
(0, inversify_1.inject)(copilot_cli_locator_1.CopilotCliLocator),
|
|
110
|
+
tslib_1.__metadata("design:type", copilot_cli_locator_1.CopilotCliLocator)
|
|
111
|
+
], CopilotAuthServiceImpl.prototype, "cliLocator", void 0);
|
|
230
112
|
tslib_1.__decorate([
|
|
231
113
|
(0, inversify_1.inject)(core_1.ILogger),
|
|
232
114
|
(0, inversify_1.named)('ai-copilot:CopilotAuthServiceImpl'),
|
|
233
115
|
tslib_1.__metadata("design:type", Object)
|
|
234
116
|
], CopilotAuthServiceImpl.prototype, "logger", void 0);
|
|
235
117
|
tslib_1.__decorate([
|
|
236
|
-
(0, inversify_1.
|
|
237
|
-
tslib_1.__metadata("design:type",
|
|
238
|
-
|
|
118
|
+
(0, inversify_1.postConstruct)(),
|
|
119
|
+
tslib_1.__metadata("design:type", Function),
|
|
120
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
121
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
122
|
+
], CopilotAuthServiceImpl.prototype, "init", null);
|
|
239
123
|
exports.CopilotAuthServiceImpl = CopilotAuthServiceImpl = tslib_1.__decorate([
|
|
240
124
|
(0, inversify_1.injectable)()
|
|
241
125
|
], CopilotAuthServiceImpl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copilot-auth-service-impl.js","sourceRoot":"","sources":["../../src/node/copilot-auth-service-impl.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,
|
|
1
|
+
{"version":3,"file":"copilot-auth-service-impl.js","sourceRoot":"","sources":["../../src/node/copilot-auth-service-impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// *****************************************************************************
|
|
3
|
-
// Copyright (C) 2026 EclipseSource and others.
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
4
4
|
//
|
|
5
5
|
// This program and the accompanying materials are made available under the
|
|
6
6
|
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
@@ -16,183 +16,119 @@
|
|
|
16
16
|
// *****************************************************************************
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
const chai_1 = require("chai");
|
|
19
|
-
const sinon = require("sinon");
|
|
20
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
|
-
const key_store_1 = require("@theia/core/lib/common/key-store");
|
|
22
|
-
const copilot_oauth_config_1 = require("../common/copilot-oauth-config");
|
|
23
|
-
const copilot_auth_service_impl_1 = require("./copilot-auth-service-impl");
|
|
24
|
-
const logger_1 = require("@theia/core/lib/common/logger");
|
|
25
19
|
const mock_logger_1 = require("@theia/core/lib/common/test/mock-logger");
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
findPassword: sinon.stub().resolves(undefined),
|
|
38
|
-
findCredentials: sinon.stub().resolves([]),
|
|
39
|
-
keys: sinon.stub().resolves([])
|
|
20
|
+
const copilot_auth_service_impl_1 = require("./copilot-auth-service-impl");
|
|
21
|
+
class TestableCopilotAuthServiceImpl extends copilot_auth_service_impl_1.CopilotAuthServiceImpl {
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
this.stubs = {
|
|
25
|
+
legacyRemoved: false,
|
|
26
|
+
legacyDelay: 0,
|
|
27
|
+
authState: { isAuthenticated: false },
|
|
28
|
+
authStateCalls: 0,
|
|
29
|
+
configuredPath: undefined,
|
|
30
|
+
deleted: 0
|
|
40
31
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
const token = await authService.getAccessToken();
|
|
63
|
-
(0, chai_1.expect)(token).to.equal(oauthToken);
|
|
64
|
-
});
|
|
65
|
-
it('should return undefined when stored data is malformed', async () => {
|
|
66
|
-
getPasswordStub.resolves('not-valid-json');
|
|
67
|
-
const token = await authService.getAccessToken();
|
|
68
|
-
(0, chai_1.expect)(token).to.be.undefined;
|
|
32
|
+
const stubs = this.stubs;
|
|
33
|
+
Object.assign(this, {
|
|
34
|
+
logger: new mock_logger_1.MockLogger(),
|
|
35
|
+
credentialStore: {
|
|
36
|
+
deleteLegacy: async () => {
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, stubs.legacyDelay));
|
|
38
|
+
return stubs.legacyRemoved;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
cliLocator: { setConfiguredPath: (path) => { stubs.configuredPath = path; } },
|
|
42
|
+
cliAuthProvider: {
|
|
43
|
+
getAuthState: async () => {
|
|
44
|
+
stubs.authStateCalls++;
|
|
45
|
+
return stubs.authState;
|
|
46
|
+
},
|
|
47
|
+
signOut: async () => {
|
|
48
|
+
stubs.deleted++;
|
|
49
|
+
stubs.authState = { isAuthenticated: false };
|
|
50
|
+
},
|
|
51
|
+
waitForLogin: async () => true
|
|
52
|
+
}
|
|
69
53
|
});
|
|
54
|
+
}
|
|
55
|
+
/** Runs what `@postConstruct` runs in production. */
|
|
56
|
+
start() {
|
|
57
|
+
this.init();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
describe('CopilotAuthServiceImpl - migration of the previous sign-in', () => {
|
|
61
|
+
it('should report that a new sign-in is required, even when asked before the cleanup finished', async () => {
|
|
62
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
63
|
+
service.stubs.legacyRemoved = true;
|
|
64
|
+
// The frontend evaluates the flag once at startup, so a state cached without it loses it.
|
|
65
|
+
service.stubs.legacyDelay = 20;
|
|
66
|
+
service.start();
|
|
67
|
+
(0, chai_1.expect)(await service.getAuthState()).to.deep.include({ isAuthenticated: false, migrationRequired: true });
|
|
70
68
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(0, chai_1.expect)(state.isAuthenticated).to.be.false;
|
|
76
|
-
(0, chai_1.expect)(state.accountLabel).to.be.undefined;
|
|
77
|
-
});
|
|
78
|
-
it('should return authenticated with account label when credentials exist', async () => {
|
|
79
|
-
getPasswordStub.resolves(JSON.stringify({
|
|
80
|
-
accessToken: 'gho_test',
|
|
81
|
-
accountLabel: 'testuser',
|
|
82
|
-
enterpriseUrl: undefined
|
|
83
|
-
}));
|
|
84
|
-
const state = await authService.getAuthState();
|
|
85
|
-
(0, chai_1.expect)(state.isAuthenticated).to.be.true;
|
|
86
|
-
(0, chai_1.expect)(state.accountLabel).to.equal('testuser');
|
|
87
|
-
});
|
|
88
|
-
it('should return enterprise URL when stored', async () => {
|
|
89
|
-
getPasswordStub.resolves(JSON.stringify({
|
|
90
|
-
accessToken: 'gho_test',
|
|
91
|
-
accountLabel: 'testuser',
|
|
92
|
-
enterpriseUrl: 'github.mycompany.com'
|
|
93
|
-
}));
|
|
94
|
-
const state = await authService.getAuthState();
|
|
95
|
-
(0, chai_1.expect)(state.isAuthenticated).to.be.true;
|
|
96
|
-
(0, chai_1.expect)(state.enterpriseUrl).to.equal('github.mycompany.com');
|
|
97
|
-
});
|
|
98
|
-
it('should clear outdated non-gho_ token and flag migration', async () => {
|
|
99
|
-
getPasswordStub.resolves(JSON.stringify({
|
|
100
|
-
accessToken: 'ghu_old_token',
|
|
101
|
-
accountLabel: 'testuser'
|
|
102
|
-
}));
|
|
103
|
-
const state = await authService.getAuthState();
|
|
104
|
-
(0, chai_1.expect)(state.isAuthenticated).to.be.false;
|
|
105
|
-
(0, chai_1.expect)(state.migrationRequired).to.be.true;
|
|
106
|
-
(0, chai_1.expect)(keyStoreService.deletePassword.calledOnce).to.be.true;
|
|
107
|
-
});
|
|
108
|
-
it('should cache the auth state after first retrieval', async () => {
|
|
109
|
-
getPasswordStub.resolves(JSON.stringify({
|
|
110
|
-
accessToken: 'gho_test',
|
|
111
|
-
accountLabel: 'testuser'
|
|
112
|
-
}));
|
|
113
|
-
const state1 = await authService.getAuthState();
|
|
114
|
-
const state2 = await authService.getAuthState();
|
|
115
|
-
(0, chai_1.expect)(state1).to.equal(state2);
|
|
116
|
-
(0, chai_1.expect)(getPasswordStub.calledOnce).to.be.true;
|
|
117
|
-
});
|
|
69
|
+
it('should not claim a migration when there was nothing to discard', async () => {
|
|
70
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
71
|
+
service.start();
|
|
72
|
+
(0, chai_1.expect)(await service.getAuthState()).to.not.have.property('migrationRequired');
|
|
118
73
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
(0, chai_1.expect)(stateAfter.isAuthenticated).to.be.false;
|
|
132
|
-
});
|
|
133
|
-
it('should fire auth state changed event on sign out', async () => {
|
|
134
|
-
const stateChanges = [];
|
|
135
|
-
authService.onAuthStateChanged(state => stateChanges.push(state));
|
|
136
|
-
await authService.signOut();
|
|
137
|
-
(0, chai_1.expect)(stateChanges).to.have.lengthOf(1);
|
|
138
|
-
(0, chai_1.expect)(stateChanges[0].isAuthenticated).to.be.false;
|
|
139
|
-
});
|
|
140
|
-
it('should delete credentials from keystore on sign out', async () => {
|
|
141
|
-
await authService.signOut();
|
|
142
|
-
(0, chai_1.expect)(keyStoreService.deletePassword.calledOnce).to.be.true;
|
|
143
|
-
});
|
|
144
|
-
it('should notify client on sign out', async () => {
|
|
145
|
-
const client = { onAuthStateChanged: sinon.stub() };
|
|
146
|
-
authService.setClient(client);
|
|
147
|
-
await authService.signOut();
|
|
148
|
-
(0, chai_1.expect)(client.onAuthStateChanged.calledOnce).to.be.true;
|
|
149
|
-
(0, chai_1.expect)(client.onAuthStateChanged.firstCall.args[0].isAuthenticated).to.be.false;
|
|
150
|
-
});
|
|
74
|
+
it('should not claim a migration for a user who is signed in', async () => {
|
|
75
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
76
|
+
service.stubs.legacyRemoved = true;
|
|
77
|
+
service.stubs.authState = { isAuthenticated: true, accountLabel: 'octocat' };
|
|
78
|
+
service.start();
|
|
79
|
+
(0, chai_1.expect)(await service.getAuthState()).to.not.have.property('migrationRequired');
|
|
80
|
+
});
|
|
81
|
+
it('should survive a keychain that cannot be read', async () => {
|
|
82
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
83
|
+
Object.assign(service, { credentialStore: { deleteLegacy: async () => { throw new Error('keychain unavailable'); } } });
|
|
84
|
+
service.start();
|
|
85
|
+
(0, chai_1.expect)(await service.getAuthState()).to.deep.equal({ isAuthenticated: false });
|
|
151
86
|
});
|
|
152
87
|
});
|
|
153
|
-
describe('CopilotAuthServiceImpl
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
let authService;
|
|
161
|
-
let getPasswordStub;
|
|
162
|
-
let deletePasswordStub;
|
|
163
|
-
beforeEach(() => {
|
|
164
|
-
const container = new inversify_1.Container();
|
|
165
|
-
container.bind(logger_1.ILogger).to(mock_logger_1.MockLogger).inSingletonScope();
|
|
166
|
-
getPasswordStub = sinon.stub().resolves(undefined);
|
|
167
|
-
deletePasswordStub = sinon.stub().resolves(true);
|
|
168
|
-
const keyStoreService = {
|
|
169
|
-
setPassword: sinon.stub().resolves(),
|
|
170
|
-
getPassword: getPasswordStub,
|
|
171
|
-
deletePassword: deletePasswordStub,
|
|
172
|
-
findPassword: sinon.stub().resolves(undefined),
|
|
173
|
-
findCredentials: sinon.stub().resolves([]),
|
|
174
|
-
keys: sinon.stub().resolves([])
|
|
175
|
-
};
|
|
176
|
-
container.bind(key_store_1.KeyStoreService).toConstantValue(keyStoreService);
|
|
177
|
-
container.bind(copilot_oauth_config_1.CopilotOAuthConfig).toConstantValue(customConfig);
|
|
178
|
-
container.bind(copilot_auth_service_impl_1.CopilotAuthServiceImpl).toSelf().inSingletonScope();
|
|
179
|
-
authService = container.get(copilot_auth_service_impl_1.CopilotAuthServiceImpl);
|
|
88
|
+
describe('CopilotAuthServiceImpl - state', () => {
|
|
89
|
+
it('should ask the provider once and serve the cached state afterwards', async () => {
|
|
90
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
91
|
+
service.start();
|
|
92
|
+
await service.getAuthState();
|
|
93
|
+
await service.getAuthState();
|
|
94
|
+
(0, chai_1.expect)(service.stubs.authStateCalls).to.equal(1);
|
|
180
95
|
});
|
|
181
|
-
|
|
182
|
-
|
|
96
|
+
it('should report the new state after a sign-in', async () => {
|
|
97
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
98
|
+
service.start();
|
|
99
|
+
await service.getAuthState();
|
|
100
|
+
service.stubs.authState = { isAuthenticated: true, accountLabel: 'octocat' };
|
|
101
|
+
const reported = [];
|
|
102
|
+
service.onAuthStateChanged(state => reported.push(state));
|
|
103
|
+
(0, chai_1.expect)(await service.waitForSignIn()).to.be.true;
|
|
104
|
+
(0, chai_1.expect)(reported).to.deep.equal([{ isAuthenticated: true, accountLabel: 'octocat' }]);
|
|
105
|
+
(0, chai_1.expect)(await service.getAuthState()).to.deep.equal({ isAuthenticated: true, accountLabel: 'octocat' });
|
|
183
106
|
});
|
|
184
|
-
it('should
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
(
|
|
191
|
-
|
|
107
|
+
it('should report the new state after signing out', async () => {
|
|
108
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
109
|
+
service.stubs.authState = { isAuthenticated: true, accountLabel: 'octocat' };
|
|
110
|
+
service.start();
|
|
111
|
+
await service.getAuthState();
|
|
112
|
+
const reported = [];
|
|
113
|
+
service.onAuthStateChanged(state => reported.push(state));
|
|
114
|
+
await service.signOut();
|
|
115
|
+
(0, chai_1.expect)(service.stubs.deleted).to.equal(1);
|
|
116
|
+
(0, chai_1.expect)(reported).to.deep.equal([{ isAuthenticated: false }]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('CopilotAuthServiceImpl - executable path', () => {
|
|
120
|
+
it('should hand the configured location to the lookup, which cannot read preferences itself', async () => {
|
|
121
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
122
|
+
service.start();
|
|
123
|
+
await service.setExecutablePath('/opt/copilot/copilot');
|
|
124
|
+
(0, chai_1.expect)(service.stubs.configuredPath).to.equal('/opt/copilot/copilot');
|
|
192
125
|
});
|
|
193
|
-
it('should
|
|
194
|
-
|
|
195
|
-
|
|
126
|
+
it('should hand on that nothing is configured, so that the CLI is searched for', async () => {
|
|
127
|
+
const service = new TestableCopilotAuthServiceImpl();
|
|
128
|
+
service.start();
|
|
129
|
+
await service.setExecutablePath('/opt/copilot/copilot');
|
|
130
|
+
await service.setExecutablePath(undefined);
|
|
131
|
+
(0, chai_1.expect)(service.stubs.configuredPath).to.be.undefined;
|
|
196
132
|
});
|
|
197
133
|
});
|
|
198
134
|
//# sourceMappingURL=copilot-auth-service-impl.spec.js.map
|