@theia/ai-copilot 1.77.0-next.99 → 1.78.0-next.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/lib/browser/copilot-auth-dialog-messages.js +7 -10
- package/lib/browser/copilot-auth-dialog-messages.js.map +1 -1
- package/lib/browser/copilot-auth-dialog.d.ts +2 -2
- package/lib/browser/copilot-auth-dialog.d.ts.map +1 -1
- package/lib/browser/copilot-auth-dialog.js +43 -55
- package/lib/browser/copilot-auth-dialog.js.map +1 -1
- package/lib/browser/copilot-command-contribution.d.ts +2 -2
- package/lib/browser/copilot-command-contribution.d.ts.map +1 -1
- package/lib/browser/copilot-command-contribution.js +35 -46
- package/lib/browser/copilot-command-contribution.js.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.d.ts +1 -1
- package/lib/browser/copilot-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/copilot-frontend-application-contribution.js +61 -71
- package/lib/browser/copilot-frontend-application-contribution.js.map +1 -1
- package/lib/browser/copilot-frontend-module.js +31 -33
- package/lib/browser/copilot-frontend-module.js.map +1 -1
- package/lib/browser/copilot-status-bar-contribution.d.ts +1 -1
- package/lib/browser/copilot-status-bar-contribution.d.ts.map +1 -1
- package/lib/browser/copilot-status-bar-contribution.js +30 -40
- package/lib/browser/copilot-status-bar-contribution.js.map +1 -1
- package/lib/browser/index.d.ts +5 -5
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +5 -8
- package/lib/browser/index.js.map +1 -1
- package/lib/common/copilot-auth-service.js +3 -6
- package/lib/common/copilot-auth-service.js.map +1 -1
- package/lib/common/copilot-language-models-manager.js +3 -6
- package/lib/common/copilot-language-models-manager.js.map +1 -1
- package/lib/common/copilot-preferences.js +20 -23
- package/lib/common/copilot-preferences.js.map +1 -1
- package/lib/common/index.d.ts +3 -3
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -6
- package/lib/common/index.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.d.ts +4 -4
- package/lib/node/copilot-auth-service-impl.d.ts.map +1 -1
- package/lib/node/copilot-auth-service-impl.js +21 -31
- package/lib/node/copilot-auth-service-impl.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.spec.js +17 -19
- package/lib/node/copilot-auth-service-impl.spec.js.map +1 -1
- package/lib/node/copilot-backend-module.js +26 -28
- package/lib/node/copilot-backend-module.js.map +1 -1
- package/lib/node/copilot-cli-auth-provider.d.ts +4 -4
- package/lib/node/copilot-cli-auth-provider.d.ts.map +1 -1
- package/lib/node/copilot-cli-auth-provider.js +43 -53
- package/lib/node/copilot-cli-auth-provider.js.map +1 -1
- package/lib/node/copilot-cli-auth-provider.spec.js +60 -63
- package/lib/node/copilot-cli-auth-provider.spec.js.map +1 -1
- package/lib/node/copilot-cli-locator.js +34 -38
- package/lib/node/copilot-cli-locator.js.map +1 -1
- package/lib/node/copilot-cli-locator.spec.js +90 -93
- package/lib/node/copilot-cli-locator.spec.js.map +1 -1
- package/lib/node/copilot-credential-store.js +12 -17
- package/lib/node/copilot-credential-store.js.map +1 -1
- package/lib/node/copilot-credential-store.spec.js +16 -18
- package/lib/node/copilot-credential-store.spec.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.d.ts +3 -3
- package/lib/node/copilot-language-models-manager-impl.d.ts.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.js +31 -44
- package/lib/node/copilot-language-models-manager-impl.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.spec.js +29 -31
- package/lib/node/copilot-language-models-manager-impl.spec.js.map +1 -1
- package/lib/node/copilot-runtime-env.js +2 -5
- package/lib/node/copilot-runtime-env.js.map +1 -1
- package/lib/node/copilot-sdk-client-provider.d.ts +4 -4
- package/lib/node/copilot-sdk-client-provider.d.ts.map +1 -1
- package/lib/node/copilot-sdk-client-provider.js +35 -46
- package/lib/node/copilot-sdk-client-provider.js.map +1 -1
- package/lib/node/copilot-sdk-client-provider.spec.js +43 -46
- package/lib/node/copilot-sdk-client-provider.spec.js.map +1 -1
- package/lib/node/copilot-sdk-language-model.d.ts +1 -1
- package/lib/node/copilot-sdk-language-model.d.ts.map +1 -1
- package/lib/node/copilot-sdk-language-model.js +9 -15
- package/lib/node/copilot-sdk-language-model.js.map +1 -1
- package/lib/node/copilot-sdk-language-model.spec.js +54 -56
- package/lib/node/copilot-sdk-language-model.spec.js.map +1 -1
- package/lib/node/copilot-sdk-loader.d.ts +2 -2
- package/lib/node/copilot-sdk-loader.d.ts.map +1 -1
- package/lib/node/copilot-sdk-loader.js +19 -24
- package/lib/node/copilot-sdk-loader.js.map +1 -1
- package/lib/node/copilot-sdk-loader.spec.js +22 -24
- package/lib/node/copilot-sdk-loader.spec.js.map +1 -1
- package/lib/node/copilot-sdk-mappers.d.ts +1 -1
- package/lib/node/copilot-sdk-mappers.d.ts.map +1 -1
- package/lib/node/copilot-sdk-mappers.js +11 -16
- package/lib/node/copilot-sdk-mappers.js.map +1 -1
- package/lib/node/copilot-sdk-mappers.spec.js +45 -47
- package/lib/node/copilot-sdk-mappers.spec.js.map +1 -1
- package/lib/node/copilot-sdk-types.js +1 -2
- package/lib/node/copilot-sdk-types.js.map +1 -1
- package/lib/node/index.d.ts +11 -11
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +11 -14
- package/lib/node/index.js.map +1 -1
- package/lib/package.spec.d.ts +1 -0
- package/lib/package.spec.js +1 -1
- package/lib/package.spec.js.map +1 -1
- package/package.json +16 -5
- package/src/browser/copilot-auth-dialog.tsx +2 -2
- package/src/browser/copilot-command-contribution.ts +3 -3
- package/src/browser/copilot-frontend-application-contribution.ts +3 -3
- package/src/browser/copilot-frontend-module.ts +7 -7
- package/src/browser/copilot-status-bar-contribution.ts +3 -3
- package/src/browser/index.ts +5 -5
- package/src/common/index.ts +3 -3
- package/src/node/copilot-auth-service-impl.spec.ts +2 -2
- package/src/node/copilot-auth-service-impl.ts +4 -4
- package/src/node/copilot-backend-module.ts +8 -8
- package/src/node/copilot-cli-auth-provider.spec.ts +2 -2
- package/src/node/copilot-cli-auth-provider.ts +5 -5
- package/src/node/copilot-cli-locator.spec.ts +1 -1
- package/src/node/copilot-cli-locator.ts +2 -2
- package/src/node/copilot-credential-store.spec.ts +1 -1
- package/src/node/copilot-language-models-manager-impl.spec.ts +2 -2
- package/src/node/copilot-language-models-manager-impl.ts +4 -4
- package/src/node/copilot-sdk-client-provider.spec.ts +3 -3
- package/src/node/copilot-sdk-client-provider.ts +6 -6
- package/src/node/copilot-sdk-language-model.spec.ts +2 -2
- package/src/node/copilot-sdk-language-model.ts +2 -2
- package/src/node/copilot-sdk-loader.spec.ts +1 -1
- package/src/node/copilot-sdk-loader.ts +3 -3
- package/src/node/copilot-sdk-mappers.spec.ts +2 -2
- package/src/node/copilot-sdk-mappers.ts +1 -1
- package/src/node/index.ts +11 -11
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// *****************************************************************************
|
|
3
2
|
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
4
3
|
//
|
|
@@ -14,21 +13,19 @@
|
|
|
14
13
|
//
|
|
15
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
15
|
// *****************************************************************************
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const core_1 = require("@theia/core");
|
|
27
|
-
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
16
|
+
import { __decorate } from "tslib";
|
|
17
|
+
import { execFile } from 'child_process';
|
|
18
|
+
import { constants, promises as fs } from 'fs';
|
|
19
|
+
import { createRequire } from 'module';
|
|
20
|
+
import { delimiter, dirname, join } from 'path';
|
|
21
|
+
import { promisify } from 'util';
|
|
22
|
+
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
|
23
|
+
import { ILogger, nls } from '@theia/core';
|
|
24
|
+
const execFileAsync = promisify(execFile);
|
|
28
25
|
/**
|
|
29
26
|
* Environment variable that points at the Copilot CLI, honored by the Copilot SDK as well.
|
|
30
27
|
*/
|
|
31
|
-
|
|
28
|
+
export const COPILOT_CLI_PATH_ENV = 'COPILOT_CLI_PATH';
|
|
32
29
|
/**
|
|
33
30
|
* Time after which looking up the global npm installation directory is given up on.
|
|
34
31
|
*/
|
|
@@ -81,7 +78,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
81
78
|
if (this.configuredPath) {
|
|
82
79
|
const configured = await this.resolveConfiguredPath(this.configuredPath);
|
|
83
80
|
if (!configured) {
|
|
84
|
-
throw new Error(
|
|
81
|
+
throw new Error(nls.localize('theia/ai/copilot/cliNotFoundAt', 'The configured GitHub Copilot CLI does not exist or is not executable: {0}', this.configuredPath));
|
|
85
82
|
}
|
|
86
83
|
return configured;
|
|
87
84
|
}
|
|
@@ -109,7 +106,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
109
106
|
}
|
|
110
107
|
}
|
|
111
108
|
this.logger.warn(`Copilot: no Copilot CLI found, searched:\n${attempted.join('\n')}`);
|
|
112
|
-
throw new Error(
|
|
109
|
+
throw new Error(nls.localize('theia/ai/copilot/cliNotFound', 'Could not find the GitHub Copilot CLI on the machine running the backend. Install it with '
|
|
113
110
|
+ '`npm install -g @github/copilot`, or set the `ai-features.copilot.executablePath` preference to the location of '
|
|
114
111
|
+ 'its executable. {0} locations were searched, see the backend log for the full list.', attempted.length));
|
|
115
112
|
}
|
|
@@ -122,12 +119,12 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
122
119
|
* for as long as a Node.js is on the `PATH` of the backend, which is nothing to rely on.
|
|
123
120
|
*/
|
|
124
121
|
async resolveConfiguredPath(configured) {
|
|
125
|
-
const candidates = [configured, ...this.getCliFileNames().map(name =>
|
|
122
|
+
const candidates = [configured, ...this.getCliFileNames().map(name => join(configured, name))];
|
|
126
123
|
for (const candidate of candidates) {
|
|
127
124
|
if (!await this.isExecutable(candidate)) {
|
|
128
125
|
continue;
|
|
129
126
|
}
|
|
130
|
-
const target = await
|
|
127
|
+
const target = await fs.realpath(candidate).catch(() => candidate);
|
|
131
128
|
for (const mapped of this.toCandidatesOnPath(target)) {
|
|
132
129
|
if (await this.isExecutable(mapped)) {
|
|
133
130
|
return mapped;
|
|
@@ -149,7 +146,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
149
146
|
* turned into an error, so that the remaining sources still get their chance.
|
|
150
147
|
*/
|
|
151
148
|
async environmentCandidates() {
|
|
152
|
-
const configured = process.env[
|
|
149
|
+
const configured = process.env[COPILOT_CLI_PATH_ENV]?.trim();
|
|
153
150
|
if (!configured) {
|
|
154
151
|
return [];
|
|
155
152
|
}
|
|
@@ -159,7 +156,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
159
156
|
}
|
|
160
157
|
// A launcher that could not be followed is dropped rather than kept as a candidate, because it
|
|
161
158
|
// would be spawned and cannot work. Everything else is kept, so that the error names it.
|
|
162
|
-
this.logger.warn(`Copilot: ${
|
|
159
|
+
this.logger.warn(`Copilot: ${COPILOT_CLI_PATH_ENV} does not point at a usable Copilot CLI: ${configured}`);
|
|
163
160
|
return this.isLauncher(configured) ? [] : [configured];
|
|
164
161
|
}
|
|
165
162
|
/**
|
|
@@ -169,9 +166,9 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
169
166
|
* package is found whether the installation hoisted it or nested it below the SDK.
|
|
170
167
|
*/
|
|
171
168
|
async bundledCandidates() {
|
|
172
|
-
const candidates = [...this.resolvedCandidates(
|
|
169
|
+
const candidates = [...this.resolvedCandidates(import.meta.filename)];
|
|
173
170
|
try {
|
|
174
|
-
const resolver = (
|
|
171
|
+
const resolver = createRequire(import.meta.filename);
|
|
175
172
|
candidates.push(...this.resolvedCandidates(resolver.resolve('@github/copilot-sdk')));
|
|
176
173
|
for (const base of resolver.resolve.paths('@github/copilot') ?? []) {
|
|
177
174
|
candidates.push(...this.toPlatformPackageCandidates(base));
|
|
@@ -194,7 +191,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
194
191
|
const candidates = [];
|
|
195
192
|
for (const packageName of this.getCliPlatformPackageNames()) {
|
|
196
193
|
try {
|
|
197
|
-
candidates.push(
|
|
194
|
+
candidates.push(join(dirname(createRequire(anchor).resolve(packageName)), this.getBinaryName()));
|
|
198
195
|
}
|
|
199
196
|
catch (error) {
|
|
200
197
|
// No such package below this anchor.
|
|
@@ -211,14 +208,14 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
211
208
|
*/
|
|
212
209
|
async pathCandidates() {
|
|
213
210
|
const candidates = [];
|
|
214
|
-
for (const entry of (process.env.PATH ?? '').split(
|
|
211
|
+
for (const entry of (process.env.PATH ?? '').split(delimiter)) {
|
|
215
212
|
if (!entry) {
|
|
216
213
|
continue;
|
|
217
214
|
}
|
|
218
215
|
for (const name of this.getCliFileNames()) {
|
|
219
|
-
const candidate =
|
|
216
|
+
const candidate = join(entry, name);
|
|
220
217
|
try {
|
|
221
|
-
candidates.push(...this.toCandidatesOnPath(await
|
|
218
|
+
candidates.push(...this.toCandidatesOnPath(await fs.realpath(candidate)));
|
|
222
219
|
}
|
|
223
220
|
catch (error) {
|
|
224
221
|
// No CLI of this name in this entry of the PATH.
|
|
@@ -236,12 +233,12 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
236
233
|
if (this.isJsEntryPoint(target)) {
|
|
237
234
|
// `<node_modules>/@github/copilot/npm-loader.js`, so resolve from the launcher itself and
|
|
238
235
|
// fall back to `<node_modules>`, which is where a hoisting installation puts the package.
|
|
239
|
-
return [...this.resolvedCandidates(target), ...this.moduleDirectoryCandidates(
|
|
236
|
+
return [...this.resolvedCandidates(target), ...this.moduleDirectoryCandidates(dirname(dirname(dirname(target))))];
|
|
240
237
|
}
|
|
241
238
|
if (this.isShim(target)) {
|
|
242
239
|
// `<npm prefix>/copilot.cmd` on Windows, which is not a link to the entry point but a batch
|
|
243
240
|
// file next to the module directory the installation wrote.
|
|
244
|
-
return this.moduleDirectoryCandidates(
|
|
241
|
+
return this.moduleDirectoryCandidates(join(dirname(target), 'node_modules'));
|
|
245
242
|
}
|
|
246
243
|
return [target];
|
|
247
244
|
}
|
|
@@ -276,7 +273,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
276
273
|
return [];
|
|
277
274
|
}
|
|
278
275
|
return [
|
|
279
|
-
...this.resolvedCandidates(
|
|
276
|
+
...this.resolvedCandidates(join(modules, '@github', 'copilot', 'npm-loader.js')),
|
|
280
277
|
...this.toPlatformPackageCandidates(modules)
|
|
281
278
|
];
|
|
282
279
|
}
|
|
@@ -287,7 +284,7 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
287
284
|
if (!base) {
|
|
288
285
|
return [];
|
|
289
286
|
}
|
|
290
|
-
return this.getCliPlatformPackageNames().map(packageName =>
|
|
287
|
+
return this.getCliPlatformPackageNames().map(packageName => join(base, ...packageName.split('/'), this.getBinaryName()));
|
|
291
288
|
}
|
|
292
289
|
/**
|
|
293
290
|
* The platform-specific packages that can carry the CLI for this host.
|
|
@@ -323,12 +320,12 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
323
320
|
}
|
|
324
321
|
async isExecutable(path) {
|
|
325
322
|
try {
|
|
326
|
-
const stats = await
|
|
323
|
+
const stats = await fs.stat(path);
|
|
327
324
|
if (!stats.isFile()) {
|
|
328
325
|
return false;
|
|
329
326
|
}
|
|
330
327
|
// The executable bit is not modelled on Windows, where every file passes this check.
|
|
331
|
-
await
|
|
328
|
+
await fs.access(path, constants.X_OK);
|
|
332
329
|
return true;
|
|
333
330
|
}
|
|
334
331
|
catch (error) {
|
|
@@ -336,13 +333,12 @@ let CopilotCliLocator = class CopilotCliLocator {
|
|
|
336
333
|
}
|
|
337
334
|
}
|
|
338
335
|
};
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
(
|
|
342
|
-
(0, inversify_1.named)('ai-copilot:CopilotCliLocator'),
|
|
343
|
-
tslib_1.__metadata("design:type", Object)
|
|
336
|
+
__decorate([
|
|
337
|
+
inject(ILogger),
|
|
338
|
+
named('ai-copilot:CopilotCliLocator')
|
|
344
339
|
], CopilotCliLocator.prototype, "logger", void 0);
|
|
345
|
-
|
|
346
|
-
|
|
340
|
+
CopilotCliLocator = __decorate([
|
|
341
|
+
injectable()
|
|
347
342
|
], CopilotCliLocator);
|
|
343
|
+
export { CopilotCliLocator };
|
|
348
344
|
//# sourceMappingURL=copilot-cli-locator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copilot-cli-locator.js","sourceRoot":"","sources":["../../src/node/copilot-cli-locator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"copilot-cli-locator.js","sourceRoot":"","sources":["../../src/node/copilot-cli-locator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// *****************************************************************************
|
|
3
2
|
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
4
3
|
//
|
|
@@ -14,19 +13,17 @@
|
|
|
14
13
|
//
|
|
15
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
15
|
// *****************************************************************************
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const copilot_cli_locator_1 = require("./copilot-cli-locator");
|
|
25
|
-
class TestableCopilotCliLocator extends copilot_cli_locator_1.CopilotCliLocator {
|
|
16
|
+
import { expect } from 'chai';
|
|
17
|
+
import { promises as fs } from 'fs';
|
|
18
|
+
import * as os from 'os';
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
|
21
|
+
import { CopilotCliLocator, COPILOT_CLI_PATH_ENV } from './copilot-cli-locator.js';
|
|
22
|
+
class TestableCopilotCliLocator extends CopilotCliLocator {
|
|
26
23
|
constructor() {
|
|
27
24
|
super();
|
|
28
25
|
// The logger is injected in production, and read-only for everyone else.
|
|
29
|
-
Object.assign(this, { logger: new
|
|
26
|
+
Object.assign(this, { logger: new MockLogger() });
|
|
30
27
|
}
|
|
31
28
|
callToPlatformPackageCandidates(base) {
|
|
32
29
|
return this.toPlatformPackageCandidates(base);
|
|
@@ -60,14 +57,14 @@ const BINARY_NAME = names.callGetBinaryName();
|
|
|
60
57
|
* resolution of Node.js, while the temporary directory is a symlink on macOS.
|
|
61
58
|
*/
|
|
62
59
|
async function createTempDirectory(prefix) {
|
|
63
|
-
return
|
|
60
|
+
return fs.realpath(await fs.mkdtemp(join(os.tmpdir(), prefix)));
|
|
64
61
|
}
|
|
65
62
|
/**
|
|
66
63
|
* Creates a file that passes the executable check of the locator.
|
|
67
64
|
*/
|
|
68
65
|
async function writeExecutable(path) {
|
|
69
|
-
await
|
|
70
|
-
await
|
|
66
|
+
await fs.mkdir(join(path, '..'), { recursive: true });
|
|
67
|
+
await fs.writeFile(path, '', { mode: 0o755 });
|
|
71
68
|
return path;
|
|
72
69
|
}
|
|
73
70
|
/**
|
|
@@ -75,14 +72,14 @@ async function writeExecutable(path) {
|
|
|
75
72
|
* by GitHub do: `@github/copilot-win32-x64` exports `./copilot.exe`, the others `./copilot`.
|
|
76
73
|
*/
|
|
77
74
|
async function installPlatformPackage(at, packageName = PLATFORM_PACKAGE, binaryName = BINARY_NAME) {
|
|
78
|
-
const directory =
|
|
79
|
-
await
|
|
80
|
-
await
|
|
75
|
+
const directory = join(at, ...packageName.split('/'));
|
|
76
|
+
await fs.mkdir(directory, { recursive: true });
|
|
77
|
+
await fs.writeFile(join(directory, 'package.json'), JSON.stringify({
|
|
81
78
|
name: packageName,
|
|
82
79
|
version: '1.0.0',
|
|
83
80
|
exports: { '.': `./${binaryName}` }
|
|
84
81
|
}));
|
|
85
|
-
return writeExecutable(
|
|
82
|
+
return writeExecutable(join(directory, binaryName));
|
|
86
83
|
}
|
|
87
84
|
/** A locator that looks for what a Windows host has, so that the lookup can be tested from anywhere. */
|
|
88
85
|
class WindowsLikeCopilotCliLocator extends TestableCopilotCliLocator {
|
|
@@ -98,11 +95,11 @@ class WindowsLikeCopilotCliLocator extends TestableCopilotCliLocator {
|
|
|
98
95
|
describe('CopilotCliLocator - candidates', () => {
|
|
99
96
|
const locator = new TestableCopilotCliLocator();
|
|
100
97
|
it('should look for the executable of the platform package below a module directory', () => {
|
|
101
|
-
const candidates = locator.callToPlatformPackageCandidates(
|
|
102
|
-
|
|
98
|
+
const candidates = locator.callToPlatformPackageCandidates(join('/app', 'node_modules'));
|
|
99
|
+
expect(candidates).to.not.be.empty;
|
|
103
100
|
for (const candidate of candidates) {
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
expect(candidate).to.contain(join('node_modules', '@github', 'copilot-'));
|
|
102
|
+
expect(candidate.endsWith(locator.callGetBinaryName())).to.be.true;
|
|
106
103
|
}
|
|
107
104
|
});
|
|
108
105
|
it('should consider the glibc and the musl build on Linux', function () {
|
|
@@ -110,45 +107,45 @@ describe('CopilotCliLocator - candidates', () => {
|
|
|
110
107
|
this.skip();
|
|
111
108
|
}
|
|
112
109
|
const candidates = locator.callToPlatformPackageCandidates('/app/node_modules');
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
expect(candidates).to.have.lengthOf(2);
|
|
111
|
+
expect(candidates.some(candidate => candidate.includes('copilot-linux-'))).to.be.true;
|
|
112
|
+
expect(candidates.some(candidate => candidate.includes('copilot-linuxmusl-'))).to.be.true;
|
|
116
113
|
});
|
|
117
114
|
it('should return nothing for an empty module directory', () => {
|
|
118
|
-
|
|
115
|
+
expect(locator.callToPlatformPackageCandidates('')).to.be.empty;
|
|
119
116
|
});
|
|
120
117
|
it('should map the JavaScript launcher of a global installation to the platform package', () => {
|
|
121
|
-
const launcher =
|
|
118
|
+
const launcher = join('/usr', 'lib', 'node_modules', '@github', 'copilot', 'npm-loader.js');
|
|
122
119
|
const candidates = locator.callToCandidatesOnPath(launcher);
|
|
123
|
-
|
|
120
|
+
expect(candidates).to.not.be.empty;
|
|
124
121
|
for (const candidate of candidates) {
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
expect(candidate).to.contain(join('/usr', 'lib', 'node_modules', '@github', 'copilot-'));
|
|
123
|
+
expect(candidate).to.not.contain('npm-loader.js');
|
|
127
124
|
}
|
|
128
125
|
});
|
|
129
126
|
it('should map the shim of a global installation to the platform package next to it', () => {
|
|
130
127
|
// What a global npm installation on Windows puts into its prefix, instead of a link.
|
|
131
|
-
const candidates = locator.callToCandidatesOnPath(
|
|
132
|
-
|
|
128
|
+
const candidates = locator.callToCandidatesOnPath(join('/prefix', 'copilot.cmd'));
|
|
129
|
+
expect(candidates).to.not.be.empty;
|
|
133
130
|
for (const candidate of candidates) {
|
|
134
|
-
|
|
131
|
+
expect(candidate).to.contain(join('/prefix', 'node_modules', '@github', 'copilot-'));
|
|
135
132
|
}
|
|
136
133
|
});
|
|
137
134
|
it('should take a native executable on the PATH as it is', () => {
|
|
138
|
-
const executable =
|
|
139
|
-
|
|
135
|
+
const executable = join('/opt', 'copilot', 'copilot');
|
|
136
|
+
expect(locator.callToCandidatesOnPath(executable)).to.deep.equal([executable]);
|
|
140
137
|
});
|
|
141
138
|
it('should look for the shim of a global installation on Windows, which has no other entry', function () {
|
|
142
139
|
if (process.platform !== 'win32') {
|
|
143
140
|
this.skip();
|
|
144
141
|
}
|
|
145
|
-
|
|
142
|
+
expect(locator.callGetCliFileNames()).to.deep.equal(['copilot.exe', 'copilot.cmd']);
|
|
146
143
|
});
|
|
147
144
|
it('should look for the executable only where an installation links to it', function () {
|
|
148
145
|
if (process.platform === 'win32') {
|
|
149
146
|
this.skip();
|
|
150
147
|
}
|
|
151
|
-
|
|
148
|
+
expect(locator.callGetCliFileNames()).to.deep.equal(['copilot']);
|
|
152
149
|
});
|
|
153
150
|
});
|
|
154
151
|
describe('CopilotCliLocator - installed platform package', () => {
|
|
@@ -157,43 +154,43 @@ describe('CopilotCliLocator - installed platform package', () => {
|
|
|
157
154
|
const locator = new TestableCopilotCliLocator();
|
|
158
155
|
beforeEach(async () => {
|
|
159
156
|
root = await createTempDirectory('theia-copilot-install-');
|
|
160
|
-
modules =
|
|
161
|
-
await
|
|
157
|
+
modules = join(root, 'node_modules');
|
|
158
|
+
await fs.mkdir(join(modules, '@github', 'copilot'), { recursive: true });
|
|
162
159
|
// The launcher of the CLI is executable, and linked to from the global binary directory.
|
|
163
|
-
await writeExecutable(
|
|
160
|
+
await writeExecutable(join(modules, '@github', 'copilot', 'npm-loader.js'));
|
|
164
161
|
});
|
|
165
162
|
afterEach(async () => {
|
|
166
|
-
await
|
|
163
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
167
164
|
});
|
|
168
165
|
it('should find a package that the installation hoisted next to the launcher', async () => {
|
|
169
166
|
const executable = await installPlatformPackage(modules);
|
|
170
|
-
const launcher =
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
const launcher = join(modules, '@github', 'copilot', 'npm-loader.js');
|
|
168
|
+
expect(locator.callResolvedCandidates(launcher)).to.contain(executable);
|
|
169
|
+
expect(locator.callToCandidatesOnPath(launcher)).to.contain(executable);
|
|
173
170
|
});
|
|
174
171
|
it('should find a package that a global installation nested below the launcher', async () => {
|
|
175
|
-
const executable = await installPlatformPackage(
|
|
176
|
-
const launcher =
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
const executable = await installPlatformPackage(join(modules, '@github', 'copilot', 'node_modules'));
|
|
173
|
+
const launcher = join(modules, '@github', 'copilot', 'npm-loader.js');
|
|
174
|
+
expect(locator.callResolvedCandidates(launcher)).to.contain(executable);
|
|
175
|
+
expect(locator.callToCandidatesOnPath(launcher)).to.contain(executable);
|
|
179
176
|
});
|
|
180
177
|
it('should return nothing when no platform package is installed', () => {
|
|
181
|
-
|
|
178
|
+
expect(locator.callResolvedCandidates(join(modules, '@github', 'copilot', 'npm-loader.js'))).to.be.empty;
|
|
182
179
|
});
|
|
183
180
|
it('should find the package of a global installation from the shim next to its module directory', async () => {
|
|
184
|
-
const executable = await installPlatformPackage(
|
|
185
|
-
|
|
181
|
+
const executable = await installPlatformPackage(join(modules, '@github', 'copilot', 'node_modules'));
|
|
182
|
+
expect(locator.callToCandidatesOnPath(join(root, 'copilot.cmd'))).to.contain(executable);
|
|
186
183
|
});
|
|
187
184
|
it('should reject a configured shim that leads nowhere, since it cannot be spawned', async () => {
|
|
188
|
-
const shim = await writeExecutable(
|
|
185
|
+
const shim = await writeExecutable(join(root, 'copilot.cmd'));
|
|
189
186
|
const configured = new TestableCopilotCliLocator();
|
|
190
187
|
configured.setConfiguredPath(shim);
|
|
191
188
|
try {
|
|
192
189
|
await configured.resolve();
|
|
193
|
-
|
|
190
|
+
expect.fail('should have rejected');
|
|
194
191
|
}
|
|
195
192
|
catch (error) {
|
|
196
|
-
|
|
193
|
+
expect(String(error)).to.contain(shim);
|
|
197
194
|
}
|
|
198
195
|
});
|
|
199
196
|
it('should follow a configured launcher to the executable it would start', async function () {
|
|
@@ -201,54 +198,54 @@ describe('CopilotCliLocator - installed platform package', () => {
|
|
|
201
198
|
// A global installation writes a shim rather than a link there.
|
|
202
199
|
this.skip();
|
|
203
200
|
}
|
|
204
|
-
const executable = await installPlatformPackage(
|
|
205
|
-
const launcher =
|
|
206
|
-
await
|
|
207
|
-
await
|
|
201
|
+
const executable = await installPlatformPackage(join(modules, '@github', 'copilot', 'node_modules'));
|
|
202
|
+
const launcher = join(root, 'bin', 'copilot');
|
|
203
|
+
await fs.mkdir(join(root, 'bin'), { recursive: true });
|
|
204
|
+
await fs.symlink(join(modules, '@github', 'copilot', 'npm-loader.js'), launcher);
|
|
208
205
|
const configured = new TestableCopilotCliLocator();
|
|
209
206
|
configured.setConfiguredPath(launcher);
|
|
210
|
-
|
|
207
|
+
expect(await configured.resolve()).to.equal(executable);
|
|
211
208
|
});
|
|
212
209
|
});
|
|
213
210
|
describe('CopilotCliLocator - environment', () => {
|
|
214
211
|
const locator = new TestableCopilotCliLocator();
|
|
215
|
-
const previous = process.env[
|
|
212
|
+
const previous = process.env[COPILOT_CLI_PATH_ENV];
|
|
216
213
|
let root;
|
|
217
214
|
beforeEach(async () => {
|
|
218
215
|
root = await createTempDirectory('theia-copilot-env-');
|
|
219
216
|
});
|
|
220
217
|
afterEach(async () => {
|
|
221
218
|
if (previous === undefined) {
|
|
222
|
-
delete process.env[
|
|
219
|
+
delete process.env[COPILOT_CLI_PATH_ENV];
|
|
223
220
|
}
|
|
224
221
|
else {
|
|
225
|
-
process.env[
|
|
222
|
+
process.env[COPILOT_CLI_PATH_ENV] = previous;
|
|
226
223
|
}
|
|
227
|
-
await
|
|
224
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
228
225
|
});
|
|
229
226
|
it('should honor the location given in the environment', async () => {
|
|
230
|
-
process.env[
|
|
231
|
-
|
|
227
|
+
process.env[COPILOT_CLI_PATH_ENV] = '/opt/copilot/copilot';
|
|
228
|
+
expect(await locator.callEnvironmentCandidates()).to.deep.equal(['/opt/copilot/copilot']);
|
|
232
229
|
});
|
|
233
230
|
it('should ignore a blank value', async () => {
|
|
234
|
-
process.env[
|
|
235
|
-
|
|
231
|
+
process.env[COPILOT_CLI_PATH_ENV] = ' ';
|
|
232
|
+
expect(await locator.callEnvironmentCandidates()).to.be.empty;
|
|
236
233
|
});
|
|
237
234
|
it('should follow a launcher given in the environment, the way a configured one is followed', async () => {
|
|
238
|
-
const modules =
|
|
235
|
+
const modules = join(root, 'node_modules');
|
|
239
236
|
const executable = await installPlatformPackage(modules);
|
|
240
|
-
const launcher = await writeExecutable(
|
|
241
|
-
process.env[
|
|
242
|
-
|
|
237
|
+
const launcher = await writeExecutable(join(modules, '@github', 'copilot', 'npm-loader.js'));
|
|
238
|
+
process.env[COPILOT_CLI_PATH_ENV] = launcher;
|
|
239
|
+
expect(await locator.callEnvironmentCandidates()).to.deep.equal([executable]);
|
|
243
240
|
});
|
|
244
241
|
it('should accept the directory holding the executable', async () => {
|
|
245
|
-
const executable = await writeExecutable(
|
|
246
|
-
process.env[
|
|
247
|
-
|
|
242
|
+
const executable = await writeExecutable(join(root, 'bin', BINARY_NAME));
|
|
243
|
+
process.env[COPILOT_CLI_PATH_ENV] = join(root, 'bin');
|
|
244
|
+
expect(await locator.callEnvironmentCandidates()).to.deep.equal([executable]);
|
|
248
245
|
});
|
|
249
246
|
it('should drop a launcher that leads nowhere instead of offering it for spawning', async () => {
|
|
250
|
-
process.env[
|
|
251
|
-
|
|
247
|
+
process.env[COPILOT_CLI_PATH_ENV] = await writeExecutable(join(root, 'copilot.cmd'));
|
|
248
|
+
expect(await locator.callEnvironmentCandidates()).to.be.empty;
|
|
252
249
|
});
|
|
253
250
|
});
|
|
254
251
|
describe('CopilotCliLocator - configured path', () => {
|
|
@@ -256,39 +253,39 @@ describe('CopilotCliLocator - configured path', () => {
|
|
|
256
253
|
let executable;
|
|
257
254
|
beforeEach(async () => {
|
|
258
255
|
home = await createTempDirectory('theia-copilot-locator-');
|
|
259
|
-
executable = await writeExecutable(
|
|
256
|
+
executable = await writeExecutable(join(home, 'bin', process.platform === 'win32' ? 'copilot.exe' : 'copilot'));
|
|
260
257
|
});
|
|
261
258
|
afterEach(async () => {
|
|
262
|
-
await
|
|
259
|
+
await fs.rm(home, { recursive: true, force: true });
|
|
263
260
|
});
|
|
264
261
|
it('should use the configured executable', async () => {
|
|
265
262
|
const locator = new TestableCopilotCliLocator();
|
|
266
263
|
locator.setConfiguredPath(executable);
|
|
267
|
-
|
|
264
|
+
expect(await locator.resolve()).to.equal(executable);
|
|
268
265
|
});
|
|
269
266
|
it('should accept the directory holding the executable', async () => {
|
|
270
267
|
const locator = new TestableCopilotCliLocator();
|
|
271
|
-
locator.setConfiguredPath(
|
|
272
|
-
|
|
268
|
+
locator.setConfiguredPath(join(home, 'bin'));
|
|
269
|
+
expect(await locator.resolve()).to.equal(executable);
|
|
273
270
|
});
|
|
274
271
|
it('should report a configured location that does not exist', async () => {
|
|
275
272
|
const locator = new TestableCopilotCliLocator();
|
|
276
|
-
const missing =
|
|
273
|
+
const missing = join(home, 'nowhere', 'copilot');
|
|
277
274
|
locator.setConfiguredPath(missing);
|
|
278
275
|
try {
|
|
279
276
|
await locator.resolve();
|
|
280
|
-
|
|
277
|
+
expect.fail('should have rejected');
|
|
281
278
|
}
|
|
282
279
|
catch (error) {
|
|
283
|
-
|
|
280
|
+
expect(String(error)).to.contain(missing);
|
|
284
281
|
}
|
|
285
282
|
});
|
|
286
283
|
it('should search again after the configured location changed', async () => {
|
|
287
284
|
const locator = new TestableCopilotCliLocator();
|
|
288
|
-
locator.setConfiguredPath(
|
|
285
|
+
locator.setConfiguredPath(join(home, 'nowhere', 'copilot'));
|
|
289
286
|
await locator.resolve().catch(() => { });
|
|
290
287
|
locator.setConfiguredPath(executable);
|
|
291
|
-
|
|
288
|
+
expect(await locator.resolve()).to.equal(executable);
|
|
292
289
|
});
|
|
293
290
|
});
|
|
294
291
|
describe('CopilotCliLocator - a Windows host', () => {
|
|
@@ -298,27 +295,27 @@ describe('CopilotCliLocator - a Windows host', () => {
|
|
|
298
295
|
root = await createTempDirectory('theia-copilot-windows-');
|
|
299
296
|
});
|
|
300
297
|
afterEach(async () => {
|
|
301
|
-
await
|
|
298
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
302
299
|
});
|
|
303
300
|
/**
|
|
304
301
|
* Writes what a global npm installation leaves on Windows: a `copilot.cmd` shim in the prefix, and
|
|
305
302
|
* the platform package nested below the launcher, exporting its executable under the `.exe` name.
|
|
306
303
|
*/
|
|
307
304
|
async function installGlobally() {
|
|
308
|
-
const modules =
|
|
309
|
-
await writeExecutable(
|
|
310
|
-
const executable = await installPlatformPackage(
|
|
311
|
-
return { shim: await writeExecutable(
|
|
305
|
+
const modules = join(root, 'node_modules');
|
|
306
|
+
await writeExecutable(join(modules, '@github', 'copilot', 'npm-loader.js'));
|
|
307
|
+
const executable = await installPlatformPackage(join(modules, '@github', 'copilot', 'node_modules'), WindowsLikeCopilotCliLocator.PACKAGE, WindowsLikeCopilotCliLocator.BINARY);
|
|
308
|
+
return { shim: await writeExecutable(join(root, 'copilot.cmd')), executable };
|
|
312
309
|
}
|
|
313
310
|
it('should follow the shim of a global installation to the executable', async () => {
|
|
314
311
|
const { shim, executable } = await installGlobally();
|
|
315
|
-
|
|
312
|
+
expect(locator.callToCandidatesOnPath(shim)).to.contain(executable);
|
|
316
313
|
});
|
|
317
314
|
it('should follow a configured shim to the executable, which is what can be spawned', async () => {
|
|
318
315
|
const { shim, executable } = await installGlobally();
|
|
319
316
|
locator.setConfiguredPath(shim);
|
|
320
317
|
try {
|
|
321
|
-
|
|
318
|
+
expect(await locator.resolve()).to.equal(executable);
|
|
322
319
|
}
|
|
323
320
|
finally {
|
|
324
321
|
locator.setConfiguredPath(undefined);
|