@github/copilot-language-server 1.528.0 → 1.529.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/dist/main.js +66 -66
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/client.js +276 -53
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/copilotRequestHandler.js +9 -0
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/extension.js +21 -6
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/factory.js +123 -0
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/ffiRuntimeHost.js +285 -0
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/generated/rpc.js +587 -46
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/index.js +11 -2
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/session.js +643 -14
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/sessionFsProvider.js +43 -0
- package/dist/node_modules/@github/copilot-sdk/dist/cjs/types.js +30 -3
- package/dist/node_modules/@github/copilot-sdk/package.json +3 -2
- package/dist/node_modules/vscode-jsonrpc/lib/common/connection.js +5 -3
- package/dist/node_modules/vscode-jsonrpc/package.json +1 -1
- package/package.json +14 -14
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var client_exports = {};
|
|
20
30
|
__export(client_exports, {
|
|
@@ -246,6 +256,7 @@ class TeardownResilientStreamMessageWriter extends import_node.StreamMessageWrit
|
|
|
246
256
|
class CopilotClient {
|
|
247
257
|
cliStartTimeout = null;
|
|
248
258
|
cliProcess = null;
|
|
259
|
+
ffiHost = null;
|
|
249
260
|
connection = null;
|
|
250
261
|
messageWriter = null;
|
|
251
262
|
socket = null;
|
|
@@ -322,6 +333,29 @@ class CopilotClient {
|
|
|
322
333
|
`);
|
|
323
334
|
}
|
|
324
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Environment variable that overrides the transport when the caller does not set
|
|
338
|
+
* {@link CopilotClientOptions.connection}. Accepts `"inprocess"` or `"stdio"`
|
|
339
|
+
* (case-insensitive); unset preserves the default stdio transport. Any other value
|
|
340
|
+
* is an error.
|
|
341
|
+
*/
|
|
342
|
+
static DEFAULT_CONNECTION_ENV_VAR = "COPILOT_SDK_DEFAULT_CONNECTION";
|
|
343
|
+
/**
|
|
344
|
+
* Resolves the default {@link RuntimeConnection} for the no-connection case,
|
|
345
|
+
* honoring {@link CopilotClient.DEFAULT_CONNECTION_ENV_VAR}.
|
|
346
|
+
*/
|
|
347
|
+
static resolveDefaultConnection() {
|
|
348
|
+
const value = process.env[CopilotClient.DEFAULT_CONNECTION_ENV_VAR];
|
|
349
|
+
if (!value || value.toLowerCase() === "stdio") {
|
|
350
|
+
return { kind: "stdio" };
|
|
351
|
+
}
|
|
352
|
+
if (value.toLowerCase() === "inprocess") {
|
|
353
|
+
return { kind: "inprocess" };
|
|
354
|
+
}
|
|
355
|
+
throw new Error(
|
|
356
|
+
`Invalid ${CopilotClient.DEFAULT_CONNECTION_ENV_VAR} value '${value}'. Expected 'inprocess', 'stdio', or unset.`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
325
359
|
/**
|
|
326
360
|
* Creates a new CopilotClient instance.
|
|
327
361
|
*
|
|
@@ -350,12 +384,32 @@ class CopilotClient {
|
|
|
350
384
|
* ```
|
|
351
385
|
*/
|
|
352
386
|
constructor(options = {}) {
|
|
353
|
-
const conn = options._internalConnection ?? options.connection ??
|
|
387
|
+
const conn = options._internalConnection ?? options.connection ?? CopilotClient.resolveDefaultConnection();
|
|
354
388
|
if (conn.kind === "uri" && (options.gitHubToken !== void 0 || options.useLoggedInUser !== void 0)) {
|
|
355
389
|
throw new Error(
|
|
356
390
|
"gitHubToken and useLoggedInUser cannot be used with RuntimeConnection.forUri (external server manages its own auth)"
|
|
357
391
|
);
|
|
358
392
|
}
|
|
393
|
+
if (conn.kind === "inprocess" && options.workingDirectory !== void 0) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
"workingDirectory is not supported with RuntimeConnection.forInProcess(): the in-process transport hosts the runtime in this process, so honoring it would require mutating the shared process-global cwd. Change the host process's working directory before constructing the client instead."
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
if (conn.kind === "inprocess" && options.env !== void 0) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
"env is not supported with RuntimeConnection.forInProcess(): the in-process transport loads the native runtime into the shared host process, whose single environment block cannot carry per-client values. Set the variables on the host process environment instead."
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
if (conn.kind === "inprocess" && options.telemetry !== void 0) {
|
|
404
|
+
throw new Error(
|
|
405
|
+
"telemetry is not supported with RuntimeConnection.forInProcess(): telemetry configuration is lowered to environment variables read by native runtime code running in the shared host process, so per-client telemetry cannot be honored in-process. Configure telemetry via the host process environment, or use a child-process transport."
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
if ((conn.kind === "stdio" || conn.kind === "tcp") && conn.env !== void 0 && options.env !== void 0) {
|
|
409
|
+
throw new Error(
|
|
410
|
+
"Set environment variables via either the client-level env option or the connection's env (RuntimeConnection.forStdio/forTcp), not both. Prefer the connection-level env for child-process transports."
|
|
411
|
+
);
|
|
412
|
+
}
|
|
359
413
|
if (conn.kind === "tcp" && conn.connectionToken !== void 0) {
|
|
360
414
|
if (typeof conn.connectionToken !== "string" || conn.connectionToken.length === 0) {
|
|
361
415
|
throw new Error("connectionToken must be a non-empty string");
|
|
@@ -384,7 +438,8 @@ class CopilotClient {
|
|
|
384
438
|
this.requestHandler = options.requestHandler ?? null;
|
|
385
439
|
this.onGitHubTelemetry = options.onGitHubTelemetry;
|
|
386
440
|
this.setupClientGlobalHandlers();
|
|
387
|
-
const
|
|
441
|
+
const connEnv = conn.kind === "stdio" || conn.kind === "tcp" ? conn.env : void 0;
|
|
442
|
+
const effectiveEnv = connEnv ?? options.env ?? process.env;
|
|
388
443
|
this.resolvedEnv = effectiveEnv;
|
|
389
444
|
this.resolvedCliPath = conn.kind === "stdio" || conn.kind === "tcp" ? conn.path ?? effectiveEnv.COPILOT_CLI_PATH ?? getBundledCliPath() : void 0;
|
|
390
445
|
const connArgs = conn.kind === "stdio" || conn.kind === "tcp" ? conn.args ?? [] : [];
|
|
@@ -511,7 +566,9 @@ class CopilotClient {
|
|
|
511
566
|
}
|
|
512
567
|
this.state = "connecting";
|
|
513
568
|
try {
|
|
514
|
-
if (
|
|
569
|
+
if (this.connectionConfig.kind === "inprocess") {
|
|
570
|
+
await this.startInProcessFfi();
|
|
571
|
+
} else if (!this.isExternalServer) {
|
|
515
572
|
await this.startCLIServer();
|
|
516
573
|
}
|
|
517
574
|
await this.connectToServer();
|
|
@@ -560,6 +617,9 @@ class CopilotClient {
|
|
|
560
617
|
async stop() {
|
|
561
618
|
const errors = [];
|
|
562
619
|
const activeSessions = [...this.sessions.values()];
|
|
620
|
+
if (this.connectionConfig.kind === "inprocess") {
|
|
621
|
+
await Promise.allSettled(activeSessions.map((session) => session.abort()));
|
|
622
|
+
}
|
|
563
623
|
for (const session of activeSessions) {
|
|
564
624
|
const sessionId = session.sessionId;
|
|
565
625
|
let lastError = null;
|
|
@@ -588,7 +648,7 @@ class CopilotClient {
|
|
|
588
648
|
session._markDisconnected();
|
|
589
649
|
}
|
|
590
650
|
this.sessions.clear();
|
|
591
|
-
if (this.connection && this.cliProcess && !this.isExternalServer) {
|
|
651
|
+
if (this.connection && (this.cliProcess || this.ffiHost) && !this.isExternalServer) {
|
|
592
652
|
const runtimeShutdownStart = Date.now();
|
|
593
653
|
const shutdownPromise = this.rpc.runtime.shutdown();
|
|
594
654
|
void shutdownPromise.catch(() => void 0);
|
|
@@ -673,6 +733,19 @@ class CopilotClient {
|
|
|
673
733
|
);
|
|
674
734
|
}
|
|
675
735
|
}
|
|
736
|
+
if (this.ffiHost) {
|
|
737
|
+
const host = this.ffiHost;
|
|
738
|
+
this.ffiHost = null;
|
|
739
|
+
try {
|
|
740
|
+
host.dispose();
|
|
741
|
+
} catch (error) {
|
|
742
|
+
errors.push(
|
|
743
|
+
new Error(
|
|
744
|
+
`Failed to dispose in-process runtime host: ${error instanceof Error ? error.message : String(error)}`
|
|
745
|
+
)
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
676
749
|
if (this.cliStartTimeout) {
|
|
677
750
|
clearTimeout(this.cliStartTimeout);
|
|
678
751
|
this.cliStartTimeout = null;
|
|
@@ -757,6 +830,13 @@ class CopilotClient {
|
|
|
757
830
|
}
|
|
758
831
|
this.cliProcess = null;
|
|
759
832
|
}
|
|
833
|
+
if (this.ffiHost) {
|
|
834
|
+
try {
|
|
835
|
+
this.ffiHost.dispose();
|
|
836
|
+
} catch {
|
|
837
|
+
}
|
|
838
|
+
this.ffiHost = null;
|
|
839
|
+
}
|
|
760
840
|
if (this.cliStartTimeout) {
|
|
761
841
|
clearTimeout(this.cliStartTimeout);
|
|
762
842
|
this.cliStartTimeout = null;
|
|
@@ -834,11 +914,16 @@ class CopilotClient {
|
|
|
834
914
|
enableHostGitOperations: false,
|
|
835
915
|
enableSessionStore: false,
|
|
836
916
|
enableSkills: false,
|
|
837
|
-
memory: { enabled: false }
|
|
917
|
+
memory: { enabled: false },
|
|
918
|
+
customAgentsLocalOnly: true
|
|
838
919
|
};
|
|
839
920
|
}
|
|
840
921
|
return {};
|
|
841
922
|
}
|
|
923
|
+
/** Mode-specific default for enableExperimentalMode. */
|
|
924
|
+
experimentalModeForMode(supplied) {
|
|
925
|
+
return this.options.mode === "empty" ? supplied ?? false : supplied;
|
|
926
|
+
}
|
|
842
927
|
/**
|
|
843
928
|
* Returns the systemMessage config to use, adjusted for the current mode.
|
|
844
929
|
* In empty mode we ensure the environment_context section is removed
|
|
@@ -919,7 +1004,9 @@ class CopilotClient {
|
|
|
919
1004
|
if (!this.connection) {
|
|
920
1005
|
await this.start();
|
|
921
1006
|
}
|
|
922
|
-
|
|
1007
|
+
const modeDefaults = this.configDefaultsForMode();
|
|
1008
|
+
config = { ...modeDefaults, ...config };
|
|
1009
|
+
config.customAgentsLocalOnly ??= modeDefaults.customAgentsLocalOnly;
|
|
923
1010
|
config.systemMessage = this.getSystemMessageConfigForMode(config.systemMessage);
|
|
924
1011
|
const callerSessionId = config.sessionId;
|
|
925
1012
|
const useServerGeneratedId = config.cloud != null && callerSessionId == null;
|
|
@@ -938,7 +1025,10 @@ class CopilotClient {
|
|
|
938
1025
|
this.connection,
|
|
939
1026
|
void 0,
|
|
940
1027
|
this.onGetTraceContext,
|
|
941
|
-
{
|
|
1028
|
+
{
|
|
1029
|
+
mcpAuthHandler: config.onMcpAuthRequest,
|
|
1030
|
+
managedSettingsEnabled: config.enableManagedSettings
|
|
1031
|
+
}
|
|
942
1032
|
);
|
|
943
1033
|
s.registerTools(config.tools);
|
|
944
1034
|
s.registerCanvases(config.canvases);
|
|
@@ -987,6 +1077,7 @@ class CopilotClient {
|
|
|
987
1077
|
clientName: config.clientName,
|
|
988
1078
|
reasoningEffort: config.reasoningEffort,
|
|
989
1079
|
reasoningSummary: config.reasoningSummary,
|
|
1080
|
+
isExperimentalMode: this.experimentalModeForMode(config.enableExperimentalMode),
|
|
990
1081
|
contextTier: config.contextTier,
|
|
991
1082
|
tools: config.tools?.map((tool) => ({
|
|
992
1083
|
name: tool.name,
|
|
@@ -994,13 +1085,16 @@ class CopilotClient {
|
|
|
994
1085
|
parameters: toJsonSchema(tool.parameters),
|
|
995
1086
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
996
1087
|
skipPermission: tool.skipPermission,
|
|
997
|
-
defer: tool.defer
|
|
1088
|
+
defer: tool.defer,
|
|
1089
|
+
metadata: tool.metadata
|
|
998
1090
|
})),
|
|
1091
|
+
toolSearch: config.toolSearch,
|
|
999
1092
|
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
1000
1093
|
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
1001
1094
|
requestExtensions: config.requestExtensions,
|
|
1002
1095
|
extensionSdkPath: config.extensionSdkPath,
|
|
1003
1096
|
extensionInfo: config.extensionInfo,
|
|
1097
|
+
canvasProvider: config.canvasProvider,
|
|
1004
1098
|
commands: config.commands?.map((cmd) => ({
|
|
1005
1099
|
name: cmd.name,
|
|
1006
1100
|
description: cmd.description
|
|
@@ -1023,10 +1117,12 @@ class CopilotClient {
|
|
|
1023
1117
|
requestUserInput: !!config.onUserInputRequest,
|
|
1024
1118
|
requestElicitation: !!config.onElicitationRequest,
|
|
1025
1119
|
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
1120
|
+
...config.githubMcpToolConfig != null ? { githubMcpToolConfig: config.githubMcpToolConfig } : {},
|
|
1026
1121
|
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
1027
1122
|
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
1028
1123
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
1029
1124
|
workingDirectory: config.workingDirectory,
|
|
1125
|
+
additionalDirectories: config.additionalDirectories,
|
|
1030
1126
|
streaming: config.streaming,
|
|
1031
1127
|
includeSubAgentStreamingEvents: config.includeSubAgentStreamingEvents ?? true,
|
|
1032
1128
|
...this.onGitHubTelemetry != null ? { enableGitHubTelemetryForwarding: true } : {},
|
|
@@ -1034,6 +1130,7 @@ class CopilotClient {
|
|
|
1034
1130
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1035
1131
|
envValueMode: "direct",
|
|
1036
1132
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1133
|
+
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
|
1037
1134
|
defaultAgent: config.defaultAgent,
|
|
1038
1135
|
agent: config.agent,
|
|
1039
1136
|
configDir: config.configDirectory,
|
|
@@ -1050,12 +1147,14 @@ class CopilotClient {
|
|
|
1050
1147
|
pluginDirectories: config.pluginDirectories,
|
|
1051
1148
|
instructionDirectories: config.instructionDirectories,
|
|
1052
1149
|
disabledSkills: config.disabledSkills,
|
|
1150
|
+
disabledMcpServers: config.disabledMcpServers,
|
|
1053
1151
|
infiniteSessions: config.infiniteSessions,
|
|
1054
1152
|
memory: config.memory,
|
|
1055
1153
|
gitHubToken: config.gitHubToken,
|
|
1056
1154
|
remoteSession: config.remoteSession,
|
|
1057
1155
|
cloud: config.cloud,
|
|
1058
|
-
expAssignments: config.expAssignments
|
|
1156
|
+
expAssignments: config.expAssignments,
|
|
1157
|
+
enableManagedSettings: config.enableManagedSettings
|
|
1059
1158
|
});
|
|
1060
1159
|
const {
|
|
1061
1160
|
sessionId: returnedSessionId,
|
|
@@ -1116,6 +1215,13 @@ class CopilotClient {
|
|
|
1116
1215
|
* ```
|
|
1117
1216
|
*/
|
|
1118
1217
|
async resumeSession(sessionId, config) {
|
|
1218
|
+
return this.resumeSessionInternal(sessionId, config);
|
|
1219
|
+
}
|
|
1220
|
+
/** @internal */
|
|
1221
|
+
async resumeSessionForExtension(sessionId, config, factories) {
|
|
1222
|
+
return this.resumeSessionInternal(sessionId, config, factories);
|
|
1223
|
+
}
|
|
1224
|
+
async resumeSessionInternal(sessionId, config, factories) {
|
|
1119
1225
|
if (!this.connection) {
|
|
1120
1226
|
await this.start();
|
|
1121
1227
|
}
|
|
@@ -1124,11 +1230,15 @@ class CopilotClient {
|
|
|
1124
1230
|
this.connection,
|
|
1125
1231
|
void 0,
|
|
1126
1232
|
this.onGetTraceContext,
|
|
1127
|
-
{
|
|
1233
|
+
{
|
|
1234
|
+
mcpAuthHandler: config.onMcpAuthRequest,
|
|
1235
|
+
managedSettingsEnabled: config.enableManagedSettings
|
|
1236
|
+
}
|
|
1128
1237
|
);
|
|
1129
1238
|
session.registerTools(config.tools);
|
|
1130
1239
|
session.registerCanvases(config.canvases);
|
|
1131
1240
|
session.registerCommands(config.commands);
|
|
1241
|
+
session.registerFactories(factories);
|
|
1132
1242
|
const {
|
|
1133
1243
|
wireProvider: bearerWireProvider,
|
|
1134
1244
|
wireProviders: bearerWireProviders,
|
|
@@ -1153,7 +1263,9 @@ class CopilotClient {
|
|
|
1153
1263
|
if (config.hooks) {
|
|
1154
1264
|
session.registerHooks(config.hooks);
|
|
1155
1265
|
}
|
|
1156
|
-
|
|
1266
|
+
const modeDefaults = this.configDefaultsForMode();
|
|
1267
|
+
config = { ...modeDefaults, ...config };
|
|
1268
|
+
config.customAgentsLocalOnly ??= modeDefaults.customAgentsLocalOnly;
|
|
1157
1269
|
config.systemMessage = this.getSystemMessageConfigForMode(config.systemMessage);
|
|
1158
1270
|
const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
|
|
1159
1271
|
config.systemMessage
|
|
@@ -1175,6 +1287,7 @@ class CopilotClient {
|
|
|
1175
1287
|
model: config.model,
|
|
1176
1288
|
reasoningEffort: config.reasoningEffort,
|
|
1177
1289
|
reasoningSummary: config.reasoningSummary,
|
|
1290
|
+
isExperimentalMode: this.experimentalModeForMode(config.enableExperimentalMode),
|
|
1178
1291
|
contextTier: config.contextTier,
|
|
1179
1292
|
systemMessage: wireSystemMessage,
|
|
1180
1293
|
availableTools: toolFilterOptions.availableTools,
|
|
@@ -1190,13 +1303,17 @@ class CopilotClient {
|
|
|
1190
1303
|
parameters: toJsonSchema(tool.parameters),
|
|
1191
1304
|
overridesBuiltInTool: tool.overridesBuiltInTool,
|
|
1192
1305
|
skipPermission: tool.skipPermission,
|
|
1193
|
-
defer: tool.defer
|
|
1306
|
+
defer: tool.defer,
|
|
1307
|
+
metadata: tool.metadata
|
|
1194
1308
|
})),
|
|
1309
|
+
toolSearch: config.toolSearch,
|
|
1195
1310
|
canvases: config.canvases?.map((canvas) => canvas.declaration),
|
|
1311
|
+
factories: factories?.map((factory) => factory.meta),
|
|
1196
1312
|
requestCanvasRenderer: config.requestCanvasRenderer,
|
|
1197
1313
|
requestExtensions: config.requestExtensions,
|
|
1198
1314
|
extensionSdkPath: config.extensionSdkPath,
|
|
1199
1315
|
extensionInfo: config.extensionInfo,
|
|
1316
|
+
canvasProvider: config.canvasProvider,
|
|
1200
1317
|
commands: config.commands?.map((cmd) => ({
|
|
1201
1318
|
name: cmd.name,
|
|
1202
1319
|
description: cmd.description
|
|
@@ -1211,10 +1328,12 @@ class CopilotClient {
|
|
|
1211
1328
|
requestUserInput: !!config.onUserInputRequest,
|
|
1212
1329
|
requestElicitation: !!config.onElicitationRequest,
|
|
1213
1330
|
...config.enableMcpApps ? { requestMcpApps: true } : {},
|
|
1331
|
+
...config.githubMcpToolConfig != null ? { githubMcpToolConfig: config.githubMcpToolConfig } : {},
|
|
1214
1332
|
requestExitPlanMode: !!config.onExitPlanModeRequest,
|
|
1215
1333
|
requestAutoModeSwitch: !!config.onAutoModeSwitchRequest,
|
|
1216
1334
|
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
1217
1335
|
workingDirectory: config.workingDirectory,
|
|
1336
|
+
additionalDirectories: config.additionalDirectories,
|
|
1218
1337
|
configDir: config.configDirectory,
|
|
1219
1338
|
enableConfigDiscovery: config.enableConfigDiscovery,
|
|
1220
1339
|
skipEmbeddingRetrieval: config.skipEmbeddingRetrieval,
|
|
@@ -1232,12 +1351,14 @@ class CopilotClient {
|
|
|
1232
1351
|
mcpOAuthTokenStorage: config.mcpOAuthTokenStorage,
|
|
1233
1352
|
envValueMode: "direct",
|
|
1234
1353
|
customAgents: toWireCustomAgents(config.customAgents),
|
|
1354
|
+
customAgentsLocalOnly: config.customAgentsLocalOnly,
|
|
1235
1355
|
defaultAgent: config.defaultAgent,
|
|
1236
1356
|
agent: config.agent,
|
|
1237
1357
|
skillDirectories: config.skillDirectories,
|
|
1238
1358
|
pluginDirectories: config.pluginDirectories,
|
|
1239
1359
|
instructionDirectories: config.instructionDirectories,
|
|
1240
1360
|
disabledSkills: config.disabledSkills,
|
|
1361
|
+
disabledMcpServers: config.disabledMcpServers,
|
|
1241
1362
|
infiniteSessions: config.infiniteSessions,
|
|
1242
1363
|
memory: config.memory,
|
|
1243
1364
|
disableResume: config.suppressResumeEvent,
|
|
@@ -1245,7 +1366,8 @@ class CopilotClient {
|
|
|
1245
1366
|
gitHubToken: config.gitHubToken,
|
|
1246
1367
|
remoteSession: config.remoteSession,
|
|
1247
1368
|
openCanvases: config.openCanvases,
|
|
1248
|
-
expAssignments: config.expAssignments
|
|
1369
|
+
expAssignments: config.expAssignments,
|
|
1370
|
+
enableManagedSettings: config.enableManagedSettings
|
|
1249
1371
|
});
|
|
1250
1372
|
const { workspacePath, capabilities, openCanvases } = response;
|
|
1251
1373
|
session["_workspacePath"] = workspacePath;
|
|
@@ -1371,9 +1493,11 @@ class CopilotClient {
|
|
|
1371
1493
|
const raceAgainstExit = (p) => this.processExitPromise ? Promise.race([p, this.processExitPromise]) : p;
|
|
1372
1494
|
let serverVersion;
|
|
1373
1495
|
try {
|
|
1374
|
-
const
|
|
1375
|
-
|
|
1376
|
-
|
|
1496
|
+
const connectParams = { token: this.effectiveConnectionToken };
|
|
1497
|
+
if (this.onGitHubTelemetry != null) {
|
|
1498
|
+
connectParams.enableGitHubTelemetryForwarding = true;
|
|
1499
|
+
}
|
|
1500
|
+
const result = await raceAgainstExit(this.internalRpc.connect(connectParams));
|
|
1377
1501
|
serverVersion = result.protocolVersion;
|
|
1378
1502
|
} catch (err) {
|
|
1379
1503
|
if (err instanceof import_node.ResponseError && (err.code === import_node.ErrorCodes.MethodNotFound || err.message === "Unhandled method connect")) {
|
|
@@ -1592,6 +1716,41 @@ class CopilotClient {
|
|
|
1592
1716
|
this.sessionLifecycleHandlers.delete(wildcardHandler);
|
|
1593
1717
|
};
|
|
1594
1718
|
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Builds the environment for the spawned runtime child process (stdio/TCP): applies
|
|
1721
|
+
* the auth token, connection token, `COPILOT_HOME`, keychain setting, and telemetry
|
|
1722
|
+
* variables on top of the effective env. Not used by the in-process (FFI) transport,
|
|
1723
|
+
* whose worker inherits the host process's ambient environment
|
|
1724
|
+
* (see {@link CopilotClient.startInProcessFfi}).
|
|
1725
|
+
*/
|
|
1726
|
+
buildRuntimeEnv() {
|
|
1727
|
+
const env = { ...this.resolvedEnv };
|
|
1728
|
+
delete env.NODE_DEBUG;
|
|
1729
|
+
if (this.options.gitHubToken) {
|
|
1730
|
+
env.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
|
|
1731
|
+
}
|
|
1732
|
+
if (this.effectiveConnectionToken) {
|
|
1733
|
+
env.COPILOT_CONNECTION_TOKEN = this.effectiveConnectionToken;
|
|
1734
|
+
}
|
|
1735
|
+
if (this.options.baseDirectory) {
|
|
1736
|
+
env.COPILOT_HOME = this.options.baseDirectory;
|
|
1737
|
+
}
|
|
1738
|
+
if (this.options.mode === "empty") {
|
|
1739
|
+
env.COPILOT_DISABLE_KEYTAR = "1";
|
|
1740
|
+
}
|
|
1741
|
+
if (this.options.telemetry) {
|
|
1742
|
+
const t = this.options.telemetry;
|
|
1743
|
+
env.COPILOT_OTEL_ENABLED = "true";
|
|
1744
|
+
if (t.otlpEndpoint !== void 0) env.OTEL_EXPORTER_OTLP_ENDPOINT = t.otlpEndpoint;
|
|
1745
|
+
if (t.otlpProtocol !== void 0) env.OTEL_EXPORTER_OTLP_PROTOCOL = t.otlpProtocol;
|
|
1746
|
+
if (t.filePath !== void 0) env.COPILOT_OTEL_FILE_EXPORTER_PATH = t.filePath;
|
|
1747
|
+
if (t.exporterType !== void 0) env.COPILOT_OTEL_EXPORTER_TYPE = t.exporterType;
|
|
1748
|
+
if (t.sourceName !== void 0) env.COPILOT_OTEL_SOURCE_NAME = t.sourceName;
|
|
1749
|
+
if (t.captureContent !== void 0)
|
|
1750
|
+
env.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = String(t.captureContent);
|
|
1751
|
+
}
|
|
1752
|
+
return env;
|
|
1753
|
+
}
|
|
1595
1754
|
/**
|
|
1596
1755
|
* Start the CLI server process
|
|
1597
1756
|
*/
|
|
@@ -1625,43 +1784,12 @@ class CopilotClient {
|
|
|
1625
1784
|
if (this.options.enableRemoteSessions) {
|
|
1626
1785
|
args.push("--remote");
|
|
1627
1786
|
}
|
|
1628
|
-
const envWithoutNodeDebug =
|
|
1629
|
-
delete envWithoutNodeDebug.NODE_DEBUG;
|
|
1630
|
-
if (this.options.gitHubToken) {
|
|
1631
|
-
envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
|
|
1632
|
-
}
|
|
1633
|
-
if (this.effectiveConnectionToken) {
|
|
1634
|
-
envWithoutNodeDebug.COPILOT_CONNECTION_TOKEN = this.effectiveConnectionToken;
|
|
1635
|
-
}
|
|
1636
|
-
if (this.options.baseDirectory) {
|
|
1637
|
-
envWithoutNodeDebug.COPILOT_HOME = this.options.baseDirectory;
|
|
1638
|
-
}
|
|
1639
|
-
if (this.options.mode === "empty") {
|
|
1640
|
-
envWithoutNodeDebug.COPILOT_DISABLE_KEYTAR = "1";
|
|
1641
|
-
}
|
|
1787
|
+
const envWithoutNodeDebug = this.buildRuntimeEnv();
|
|
1642
1788
|
if (!this.resolvedCliPath) {
|
|
1643
1789
|
throw new Error(
|
|
1644
1790
|
"Path to Copilot CLI is required. Please supply it via `RuntimeConnection.forStdio({ path })` or `RuntimeConnection.forTcp({ path })`, set the COPILOT_CLI_PATH environment variable, or use `RuntimeConnection.forUri(...)` to connect to an already-running runtime."
|
|
1645
1791
|
);
|
|
1646
1792
|
}
|
|
1647
|
-
if (this.options.telemetry) {
|
|
1648
|
-
const t = this.options.telemetry;
|
|
1649
|
-
envWithoutNodeDebug.COPILOT_OTEL_ENABLED = "true";
|
|
1650
|
-
if (t.otlpEndpoint !== void 0)
|
|
1651
|
-
envWithoutNodeDebug.OTEL_EXPORTER_OTLP_ENDPOINT = t.otlpEndpoint;
|
|
1652
|
-
if (t.otlpProtocol !== void 0)
|
|
1653
|
-
envWithoutNodeDebug.OTEL_EXPORTER_OTLP_PROTOCOL = t.otlpProtocol;
|
|
1654
|
-
if (t.filePath !== void 0)
|
|
1655
|
-
envWithoutNodeDebug.COPILOT_OTEL_FILE_EXPORTER_PATH = t.filePath;
|
|
1656
|
-
if (t.exporterType !== void 0)
|
|
1657
|
-
envWithoutNodeDebug.COPILOT_OTEL_EXPORTER_TYPE = t.exporterType;
|
|
1658
|
-
if (t.sourceName !== void 0)
|
|
1659
|
-
envWithoutNodeDebug.COPILOT_OTEL_SOURCE_NAME = t.sourceName;
|
|
1660
|
-
if (t.captureContent !== void 0)
|
|
1661
|
-
envWithoutNodeDebug.OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT = String(
|
|
1662
|
-
t.captureContent
|
|
1663
|
-
);
|
|
1664
|
-
}
|
|
1665
1793
|
if (!(0, import_node_fs.existsSync)(this.resolvedCliPath)) {
|
|
1666
1794
|
throw new Error(
|
|
1667
1795
|
`Copilot CLI not found at ${this.resolvedCliPath}. Ensure @github/copilot is installed.`
|
|
@@ -1780,11 +1908,103 @@ stderr: ${stderrOutput}`
|
|
|
1780
1908
|
return this.connectToParentProcessViaStdio();
|
|
1781
1909
|
case "stdio":
|
|
1782
1910
|
return this.connectToChildProcessViaStdio();
|
|
1911
|
+
case "inprocess":
|
|
1912
|
+
return this.connectViaFfi();
|
|
1783
1913
|
case "tcp":
|
|
1784
1914
|
case "uri":
|
|
1785
1915
|
return this.connectViaTcp();
|
|
1786
1916
|
}
|
|
1787
1917
|
}
|
|
1918
|
+
/** Starts the in-process FFI runtime with SDK-managed typed options. */
|
|
1919
|
+
async startInProcessFfi() {
|
|
1920
|
+
const entrypoint = this.resolveCliPathForFfi();
|
|
1921
|
+
const { FfiRuntimeHost } = await import("./ffiRuntimeHost.js");
|
|
1922
|
+
const environment = {};
|
|
1923
|
+
if (this.options.gitHubToken) {
|
|
1924
|
+
environment.COPILOT_SDK_AUTH_TOKEN = this.options.gitHubToken;
|
|
1925
|
+
}
|
|
1926
|
+
if (this.options.baseDirectory) {
|
|
1927
|
+
environment.COPILOT_HOME = this.options.baseDirectory;
|
|
1928
|
+
}
|
|
1929
|
+
if (this.options.mode === "empty") {
|
|
1930
|
+
environment.COPILOT_DISABLE_KEYTAR = "1";
|
|
1931
|
+
}
|
|
1932
|
+
const args = [];
|
|
1933
|
+
if (this.options.logLevel) {
|
|
1934
|
+
args.push("--log-level", this.options.logLevel);
|
|
1935
|
+
}
|
|
1936
|
+
if (this.options.gitHubToken) {
|
|
1937
|
+
args.push("--auth-token-env", "COPILOT_SDK_AUTH_TOKEN");
|
|
1938
|
+
}
|
|
1939
|
+
if (!this.options.useLoggedInUser) {
|
|
1940
|
+
args.push("--no-auto-login");
|
|
1941
|
+
}
|
|
1942
|
+
if (this.options.sessionIdleTimeoutSeconds > 0) {
|
|
1943
|
+
args.push("--session-idle-timeout", this.options.sessionIdleTimeoutSeconds.toString());
|
|
1944
|
+
}
|
|
1945
|
+
if (this.options.enableRemoteSessions) {
|
|
1946
|
+
args.push("--remote");
|
|
1947
|
+
}
|
|
1948
|
+
const host = FfiRuntimeHost.create(
|
|
1949
|
+
entrypoint,
|
|
1950
|
+
CopilotClient.getNapiPrebuildsFolder(entrypoint),
|
|
1951
|
+
environment,
|
|
1952
|
+
args
|
|
1953
|
+
);
|
|
1954
|
+
this.ffiHost = host;
|
|
1955
|
+
await host.start();
|
|
1956
|
+
}
|
|
1957
|
+
/**
|
|
1958
|
+
* Connect to the in-process FFI runtime host over its receive/send streams,
|
|
1959
|
+
* reusing the same `vscode-jsonrpc` framing as the stdio transport.
|
|
1960
|
+
*/
|
|
1961
|
+
async connectViaFfi() {
|
|
1962
|
+
if (!this.ffiHost) {
|
|
1963
|
+
throw new Error("In-process FFI runtime host not started");
|
|
1964
|
+
}
|
|
1965
|
+
this.messageWriter = new TeardownResilientStreamMessageWriter(this.ffiHost.sendStream);
|
|
1966
|
+
this.connection = (0, import_node.createMessageConnection)(
|
|
1967
|
+
new import_node.StreamMessageReader(this.ffiHost.receiveStream),
|
|
1968
|
+
this.messageWriter
|
|
1969
|
+
);
|
|
1970
|
+
this.attachConnectionHandlers();
|
|
1971
|
+
this.connection.listen();
|
|
1972
|
+
}
|
|
1973
|
+
/**
|
|
1974
|
+
* Resolves the CLI entrypoint used for in-process FFI hosting: `COPILOT_CLI_PATH`
|
|
1975
|
+
* when set, otherwise the bundled platform-package entrypoint.
|
|
1976
|
+
*/
|
|
1977
|
+
resolveCliPathForFfi() {
|
|
1978
|
+
return this.resolvedEnv.COPILOT_CLI_PATH ?? getBundledCliPath();
|
|
1979
|
+
}
|
|
1980
|
+
/**
|
|
1981
|
+
* Returns the napi prebuilds folder name for the current host — the
|
|
1982
|
+
* `<node-platform>-<arch>` convention (e.g. `win32-x64`, `darwin-arm64`,
|
|
1983
|
+
* `linux-x64`, `linuxmusl-x64`) under which the runtime ships
|
|
1984
|
+
* `prebuilds/<folder>/runtime.node`.
|
|
1985
|
+
*/
|
|
1986
|
+
static getNapiPrebuildsFolder(entrypoint) {
|
|
1987
|
+
const arch = process.arch;
|
|
1988
|
+
if (arch !== "x64" && arch !== "arm64") {
|
|
1989
|
+
throw new Error(`Unsupported architecture '${arch}' for in-process FFI hosting.`);
|
|
1990
|
+
}
|
|
1991
|
+
let platform = process.platform;
|
|
1992
|
+
if (platform === "linux" && CopilotClient.isMusl(entrypoint)) {
|
|
1993
|
+
platform = "linuxmusl";
|
|
1994
|
+
}
|
|
1995
|
+
return `${platform}-${arch}`;
|
|
1996
|
+
}
|
|
1997
|
+
static isMusl(entrypoint) {
|
|
1998
|
+
if (entrypoint.includes(`copilot-linuxmusl-${process.arch}`)) {
|
|
1999
|
+
return true;
|
|
2000
|
+
}
|
|
2001
|
+
if (entrypoint.includes(`copilot-linux-${process.arch}`)) {
|
|
2002
|
+
return false;
|
|
2003
|
+
}
|
|
2004
|
+
const report = process.report?.getReport();
|
|
2005
|
+
const header = report && "header" in report ? report.header : void 0;
|
|
2006
|
+
return header !== void 0 && header.glibcVersionRuntime === void 0;
|
|
2007
|
+
}
|
|
1788
2008
|
/**
|
|
1789
2009
|
* Connect to child via stdio pipes
|
|
1790
2010
|
*/
|
|
@@ -1879,10 +2099,6 @@ stderr: ${stderrOutput}`
|
|
|
1879
2099
|
"autoModeSwitch.request",
|
|
1880
2100
|
async (params) => await this.handleAutoModeSwitchRequest(params)
|
|
1881
2101
|
);
|
|
1882
|
-
this.connection.onRequest(
|
|
1883
|
-
"hooks.invoke",
|
|
1884
|
-
async (params) => await this.handleHooksInvoke(params)
|
|
1885
|
-
);
|
|
1886
2102
|
this.connection.onRequest(
|
|
1887
2103
|
"systemMessage.transform",
|
|
1888
2104
|
async (params) => await this.handleSystemMessageTransform(params)
|
|
@@ -1894,6 +2110,12 @@ stderr: ${stderrOutput}`
|
|
|
1894
2110
|
return session.clientSessionApis;
|
|
1895
2111
|
});
|
|
1896
2112
|
(0, import_rpc.registerClientGlobalApiHandlers)(this.connection, this.clientGlobalHandlers);
|
|
2113
|
+
this.connection.onRequest(
|
|
2114
|
+
"hooks.invoke",
|
|
2115
|
+
async (params) => {
|
|
2116
|
+
return await this.handleHooksInvoke(params);
|
|
2117
|
+
}
|
|
2118
|
+
);
|
|
1897
2119
|
this.connection.onClose(() => {
|
|
1898
2120
|
this.state = "disconnected";
|
|
1899
2121
|
});
|
|
@@ -1906,8 +2128,9 @@ stderr: ${stderrOutput}`
|
|
|
1906
2128
|
return;
|
|
1907
2129
|
}
|
|
1908
2130
|
const session = this.sessions.get(notification.sessionId);
|
|
2131
|
+
const event = notification.event;
|
|
1909
2132
|
if (session) {
|
|
1910
|
-
session._dispatchEvent(
|
|
2133
|
+
session._dispatchEvent(event);
|
|
1911
2134
|
}
|
|
1912
2135
|
}
|
|
1913
2136
|
handleSessionLifecycleNotification(notification) {
|
|
@@ -180,6 +180,9 @@ class CopilotRequestHandler {
|
|
|
180
180
|
const ctx = {
|
|
181
181
|
requestId: exchange.requestId,
|
|
182
182
|
sessionId: exchange.sessionId,
|
|
183
|
+
agentId: exchange.agentId,
|
|
184
|
+
parentAgentId: exchange.parentAgentId,
|
|
185
|
+
interactionType: exchange.interactionType,
|
|
183
186
|
transport: exchange.transport,
|
|
184
187
|
url: exchange.url,
|
|
185
188
|
headers: exchange.headers,
|
|
@@ -305,6 +308,9 @@ function routeChunk(exchange, params) {
|
|
|
305
308
|
class CopilotRequestExchange {
|
|
306
309
|
requestId;
|
|
307
310
|
sessionId;
|
|
311
|
+
agentId;
|
|
312
|
+
parentAgentId;
|
|
313
|
+
interactionType;
|
|
308
314
|
method = "GET";
|
|
309
315
|
url = "";
|
|
310
316
|
headers = {};
|
|
@@ -324,6 +330,9 @@ class CopilotRequestExchange {
|
|
|
324
330
|
/** Fill in the request context once the matching start frame arrives. */
|
|
325
331
|
setContext(params) {
|
|
326
332
|
this.sessionId = params.sessionId;
|
|
333
|
+
this.agentId = params.agentId;
|
|
334
|
+
this.parentAgentId = params.parentAgentId;
|
|
335
|
+
this.interactionType = params.interactionType;
|
|
327
336
|
this.method = params.method;
|
|
328
337
|
this.url = params.url;
|
|
329
338
|
this.headers = params.headers;
|