@github/copilot-sdk 1.0.3 → 1.0.4
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 +6 -2
- package/dist/cjs/client.js +133 -24
- package/dist/cjs/copilotRequestHandler.js +629 -0
- package/dist/cjs/generated/rpc.js +58 -3
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/session.js +80 -9
- package/dist/cjs/types.js +13 -1
- package/dist/client.d.ts +5 -33
- package/dist/client.js +134 -24
- package/dist/copilotRequestHandler.d.ts +82 -0
- package/dist/copilotRequestHandler.js +601 -0
- package/dist/generated/rpc.d.ts +872 -570
- package/dist/generated/rpc.js +57 -3
- package/dist/generated/session-events.d.ts +271 -14
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -0
- package/dist/session.d.ts +2 -0
- package/dist/session.js +80 -9
- package/dist/types.d.ts +124 -2
- package/dist/types.js +14 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -618,14 +618,17 @@ const session = await client.createSession({
|
|
|
618
618
|
});
|
|
619
619
|
```
|
|
620
620
|
|
|
621
|
-
Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `runtime_instructions`, `last_instructions`. Use the `SYSTEM_MESSAGE_SECTIONS` constant for descriptions of each section.
|
|
621
|
+
Available section IDs: `preamble`, `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `runtime_instructions`, `last_instructions`. Use the `SYSTEM_MESSAGE_SECTIONS` constant for descriptions of each section.
|
|
622
622
|
|
|
623
|
-
|
|
623
|
+
`identity` and `tool_instructions` are section _groups_ that target a collection of related sub-sections as a unit. Use `preamble` to target just the identity preamble without affecting its sibling sub-sections.
|
|
624
|
+
|
|
625
|
+
Each section override supports five actions:
|
|
624
626
|
|
|
625
627
|
- **`replace`** — Replace the section content entirely
|
|
626
628
|
- **`remove`** — Remove the section from the prompt
|
|
627
629
|
- **`append`** — Add content after the existing section
|
|
628
630
|
- **`prepend`** — Add content before the existing section
|
|
631
|
+
- **`preserve`** — No-op that opts an individually-addressable section out of a group-level `remove`
|
|
629
632
|
|
|
630
633
|
Unknown section IDs are handled gracefully: content from `replace`/`append`/`prepend` overrides is appended to additional instructions, and `remove` overrides are silently ignored.
|
|
631
634
|
|
|
@@ -684,6 +687,7 @@ information across turns. Provide a `memory` configuration on session create or
|
|
|
684
687
|
when omitted, the runtime default applies. In the default `"copilot-cli"` client mode the
|
|
685
688
|
SDK leaves `memory` unset so the runtime applies its own default, while `"empty"` mode
|
|
686
689
|
defaults `memory` to disabled unless you set it explicitly.
|
|
690
|
+
For more background, see [About GitHub Copilot Memory](https://docs.github.com/en/copilot/concepts/agents/copilot-memory).
|
|
687
691
|
|
|
688
692
|
```typescript
|
|
689
693
|
// Enable memory for a session
|
package/dist/cjs/client.js
CHANGED
|
@@ -33,6 +33,7 @@ var import_rpc = require("./generated/rpc.js");
|
|
|
33
33
|
var import_sdkProtocolVersion = require("./sdkProtocolVersion.js");
|
|
34
34
|
var import_session = require("./session.js");
|
|
35
35
|
var import_sessionFsProvider = require("./sessionFsProvider.js");
|
|
36
|
+
var import_copilotRequestHandler = require("./copilotRequestHandler.js");
|
|
36
37
|
var import_telemetry = require("./telemetry.js");
|
|
37
38
|
var import_toolSet = require("./toolSet.js");
|
|
38
39
|
var import_types = require("./types.js");
|
|
@@ -93,6 +94,32 @@ function toJsonSchema(parameters) {
|
|
|
93
94
|
}
|
|
94
95
|
return parameters;
|
|
95
96
|
}
|
|
97
|
+
const DEFAULT_PROVIDER_NAME = "default";
|
|
98
|
+
function extractBearerTokenProviders(provider, providers) {
|
|
99
|
+
const callbacks = /* @__PURE__ */ new Map();
|
|
100
|
+
let wireProvider = provider;
|
|
101
|
+
if (provider?.getBearerToken) {
|
|
102
|
+
const { getBearerToken, ...rest } = provider;
|
|
103
|
+
callbacks.set(DEFAULT_PROVIDER_NAME, getBearerToken);
|
|
104
|
+
wireProvider = {
|
|
105
|
+
...rest,
|
|
106
|
+
hasBearerTokenProvider: true
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
let wireProviders = providers;
|
|
110
|
+
if (providers?.some((p) => p.getBearerToken)) {
|
|
111
|
+
wireProviders = providers.map((p) => {
|
|
112
|
+
if (!p.getBearerToken) return p;
|
|
113
|
+
const { getBearerToken, ...rest } = p;
|
|
114
|
+
callbacks.set(p.name, getBearerToken);
|
|
115
|
+
return {
|
|
116
|
+
...rest,
|
|
117
|
+
hasBearerTokenProvider: true
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return { wireProvider, wireProviders, callbacks };
|
|
122
|
+
}
|
|
96
123
|
function toWireMcpServers(mcpServers) {
|
|
97
124
|
if (!mcpServers) return void 0;
|
|
98
125
|
return Object.fromEntries(
|
|
@@ -204,10 +231,23 @@ function getBundledCliPath() {
|
|
|
204
231
|
`Could not find a @github/copilot platform package (tried ${packageNames.join(", ")}). Searched ${searchPaths.length} paths. Ensure @github/copilot is installed, or pass cliPath/cliUrl to CopilotClient.`
|
|
205
232
|
);
|
|
206
233
|
}
|
|
234
|
+
class TeardownResilientStreamMessageWriter extends import_node.StreamMessageWriter {
|
|
235
|
+
suppressWriteErrors = false;
|
|
236
|
+
async write(msg) {
|
|
237
|
+
try {
|
|
238
|
+
await super.write(msg);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
if (!this.suppressWriteErrors) {
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
207
246
|
class CopilotClient {
|
|
208
247
|
cliStartTimeout = null;
|
|
209
248
|
cliProcess = null;
|
|
210
249
|
connection = null;
|
|
250
|
+
messageWriter = null;
|
|
211
251
|
socket = null;
|
|
212
252
|
runtimePort = null;
|
|
213
253
|
actualHost = "localhost";
|
|
@@ -239,6 +279,8 @@ class CopilotClient {
|
|
|
239
279
|
negotiatedProtocolVersion = null;
|
|
240
280
|
/** Connection-level session filesystem config, set via constructor option. */
|
|
241
281
|
sessionFsConfig = null;
|
|
282
|
+
requestHandler = null;
|
|
283
|
+
llmInferenceHandlers = {};
|
|
242
284
|
/**
|
|
243
285
|
* Typed server-scoped RPC methods.
|
|
244
286
|
* @throws Error if the client is not connected
|
|
@@ -269,6 +311,13 @@ class CopilotClient {
|
|
|
269
311
|
const level = this.options.logLevel?.toLowerCase();
|
|
270
312
|
if (level === "debug" || level === "all") {
|
|
271
313
|
process.stderr.write(`[copilot-sdk] ${message}. Elapsed=${Date.now() - startMs}ms
|
|
314
|
+
`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
logDebug(message) {
|
|
318
|
+
const level = this.options.logLevel?.toLowerCase();
|
|
319
|
+
if (level === "debug" || level === "all") {
|
|
320
|
+
process.stderr.write(`[copilot-sdk] ${message}
|
|
272
321
|
`);
|
|
273
322
|
}
|
|
274
323
|
}
|
|
@@ -331,6 +380,8 @@ class CopilotClient {
|
|
|
331
380
|
this.onListModels = options.onListModels;
|
|
332
381
|
this.onGetTraceContext = options.onGetTraceContext;
|
|
333
382
|
this.sessionFsConfig = options.sessionFs ?? null;
|
|
383
|
+
this.requestHandler = options.requestHandler ?? null;
|
|
384
|
+
this.setupLlmInference();
|
|
334
385
|
const effectiveEnv = options.env ?? process.env;
|
|
335
386
|
this.resolvedEnv = effectiveEnv;
|
|
336
387
|
this.resolvedCliPath = conn.kind === "stdio" || conn.kind === "tcp" ? conn.path ?? effectiveEnv.COPILOT_CLI_PATH ?? getBundledCliPath() : void 0;
|
|
@@ -410,6 +461,20 @@ class CopilotClient {
|
|
|
410
461
|
}
|
|
411
462
|
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(provider);
|
|
412
463
|
}
|
|
464
|
+
setupLlmInference() {
|
|
465
|
+
if (!this.requestHandler) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
this.llmInferenceHandlers = {
|
|
469
|
+
llmInference: (0, import_copilotRequestHandler.createCopilotRequestAdapter)(this.requestHandler, () => {
|
|
470
|
+
if (!this.connection) {
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
this._rpc ??= (0, import_rpc.createServerRpc)(this.connection);
|
|
474
|
+
return this._rpc;
|
|
475
|
+
})
|
|
476
|
+
};
|
|
477
|
+
}
|
|
413
478
|
/**
|
|
414
479
|
* Starts the CLI server and establishes a connection.
|
|
415
480
|
*
|
|
@@ -447,6 +512,9 @@ class CopilotClient {
|
|
|
447
512
|
capabilities: this.sessionFsConfig.capabilities
|
|
448
513
|
});
|
|
449
514
|
}
|
|
515
|
+
if (this.requestHandler) {
|
|
516
|
+
await this.connection.sendRequest("llmInference.setProvider", {});
|
|
517
|
+
}
|
|
450
518
|
this.state = "connected";
|
|
451
519
|
} catch (error) {
|
|
452
520
|
this.state = "error";
|
|
@@ -479,7 +547,8 @@ class CopilotClient {
|
|
|
479
547
|
*/
|
|
480
548
|
async stop() {
|
|
481
549
|
const errors = [];
|
|
482
|
-
|
|
550
|
+
const activeSessions = [...this.sessions.values()];
|
|
551
|
+
for (const session of activeSessions) {
|
|
483
552
|
const sessionId = session.sessionId;
|
|
484
553
|
let lastError = null;
|
|
485
554
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
@@ -503,8 +572,10 @@ class CopilotClient {
|
|
|
503
572
|
);
|
|
504
573
|
}
|
|
505
574
|
}
|
|
575
|
+
for (const session of activeSessions) {
|
|
576
|
+
session._markDisconnected();
|
|
577
|
+
}
|
|
506
578
|
this.sessions.clear();
|
|
507
|
-
let runtimeShutdownCompleted = false;
|
|
508
579
|
if (this.connection && this.cliProcess && !this.isExternalServer) {
|
|
509
580
|
const runtimeShutdownStart = Date.now();
|
|
510
581
|
const shutdownPromise = this.rpc.runtime.shutdown();
|
|
@@ -515,7 +586,6 @@ class CopilotClient {
|
|
|
515
586
|
RUNTIME_SHUTDOWN_TIMEOUT_MS,
|
|
516
587
|
`runtime.shutdown timed out after ${RUNTIME_SHUTDOWN_TIMEOUT_MS}ms`
|
|
517
588
|
);
|
|
518
|
-
runtimeShutdownCompleted = true;
|
|
519
589
|
this.logDebugTiming(
|
|
520
590
|
"CopilotClient.stop runtime shutdown complete",
|
|
521
591
|
runtimeShutdownStart
|
|
@@ -532,6 +602,9 @@ class CopilotClient {
|
|
|
532
602
|
);
|
|
533
603
|
}
|
|
534
604
|
}
|
|
605
|
+
if (this.messageWriter) {
|
|
606
|
+
this.messageWriter.suppressWriteErrors = true;
|
|
607
|
+
}
|
|
535
608
|
if (this.connection) {
|
|
536
609
|
try {
|
|
537
610
|
this.connection.dispose();
|
|
@@ -543,6 +616,7 @@ class CopilotClient {
|
|
|
543
616
|
);
|
|
544
617
|
}
|
|
545
618
|
this.connection = null;
|
|
619
|
+
this.messageWriter = null;
|
|
546
620
|
this._rpc = null;
|
|
547
621
|
this._internalRpc = null;
|
|
548
622
|
}
|
|
@@ -570,16 +644,13 @@ class CopilotClient {
|
|
|
570
644
|
this.cliProcess = null;
|
|
571
645
|
try {
|
|
572
646
|
if (child.exitCode == null && child.signalCode == null) {
|
|
573
|
-
|
|
574
|
-
if (!
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
)
|
|
581
|
-
);
|
|
582
|
-
}
|
|
647
|
+
child.kill();
|
|
648
|
+
if (!await waitForChildExit(child, RUNTIME_SHUTDOWN_TIMEOUT_MS)) {
|
|
649
|
+
errors.push(
|
|
650
|
+
new Error(
|
|
651
|
+
`Timed out waiting for CLI process to exit after kill: ${RUNTIME_SHUTDOWN_TIMEOUT_MS}ms`
|
|
652
|
+
)
|
|
653
|
+
);
|
|
583
654
|
}
|
|
584
655
|
}
|
|
585
656
|
} catch (error) {
|
|
@@ -642,13 +713,20 @@ class CopilotClient {
|
|
|
642
713
|
*/
|
|
643
714
|
async forceStop() {
|
|
644
715
|
this.forceStopping = true;
|
|
716
|
+
for (const session of this.sessions.values()) {
|
|
717
|
+
session._markDisconnected();
|
|
718
|
+
}
|
|
645
719
|
this.sessions.clear();
|
|
720
|
+
if (this.messageWriter) {
|
|
721
|
+
this.messageWriter.suppressWriteErrors = true;
|
|
722
|
+
}
|
|
646
723
|
if (this.connection) {
|
|
647
724
|
try {
|
|
648
725
|
this.connection.dispose();
|
|
649
726
|
} catch {
|
|
650
727
|
}
|
|
651
728
|
this.connection = null;
|
|
729
|
+
this.messageWriter = null;
|
|
652
730
|
this._rpc = null;
|
|
653
731
|
this._internalRpc = null;
|
|
654
732
|
}
|
|
@@ -834,6 +912,11 @@ class CopilotClient {
|
|
|
834
912
|
const callerSessionId = config.sessionId;
|
|
835
913
|
const useServerGeneratedId = config.cloud != null && callerSessionId == null;
|
|
836
914
|
const localSessionId = useServerGeneratedId ? void 0 : callerSessionId ?? (0, import_node_crypto.randomUUID)();
|
|
915
|
+
const {
|
|
916
|
+
wireProvider: bearerWireProvider,
|
|
917
|
+
wireProviders: bearerWireProviders,
|
|
918
|
+
callbacks: bearerTokenCallbacks
|
|
919
|
+
} = extractBearerTokenProviders(config.provider, config.providers);
|
|
837
920
|
const { wirePayload: wireSystemMessage, transformCallbacks } = extractTransformCallbacks(
|
|
838
921
|
config.systemMessage
|
|
839
922
|
);
|
|
@@ -847,6 +930,9 @@ class CopilotClient {
|
|
|
847
930
|
s.registerTools(config.tools);
|
|
848
931
|
s.registerCanvases(config.canvases);
|
|
849
932
|
s.registerCommands(config.commands);
|
|
933
|
+
if (bearerTokenCallbacks.size > 0) {
|
|
934
|
+
s.registerBearerTokenProviders(bearerTokenCallbacks);
|
|
935
|
+
}
|
|
850
936
|
s.registerPermissionHandler(config.onPermissionRequest);
|
|
851
937
|
if (config.onUserInputRequest) {
|
|
852
938
|
s.registerUserInputHandler(config.onUserInputRequest);
|
|
@@ -910,8 +996,9 @@ class CopilotClient {
|
|
|
910
996
|
availableTools: toolFilterOptions.availableTools,
|
|
911
997
|
excludedTools: toolFilterOptions.excludedTools,
|
|
912
998
|
toolFilterPrecedence: toolFilterOptions.toolFilterPrecedence,
|
|
913
|
-
provider:
|
|
914
|
-
|
|
999
|
+
provider: bearerWireProvider,
|
|
1000
|
+
capi: config.capi,
|
|
1001
|
+
providers: bearerWireProviders,
|
|
915
1002
|
models: config.models,
|
|
916
1003
|
enableSessionTelemetry: config.enableSessionTelemetry,
|
|
917
1004
|
modelCapabilities: config.modelCapabilities,
|
|
@@ -950,7 +1037,8 @@ class CopilotClient {
|
|
|
950
1037
|
memory: config.memory,
|
|
951
1038
|
gitHubToken: config.gitHubToken,
|
|
952
1039
|
remoteSession: config.remoteSession,
|
|
953
|
-
cloud: config.cloud
|
|
1040
|
+
cloud: config.cloud,
|
|
1041
|
+
expAssignments: config.expAssignments
|
|
954
1042
|
});
|
|
955
1043
|
const {
|
|
956
1044
|
sessionId: returnedSessionId,
|
|
@@ -1017,6 +1105,14 @@ class CopilotClient {
|
|
|
1017
1105
|
session.registerTools(config.tools);
|
|
1018
1106
|
session.registerCanvases(config.canvases);
|
|
1019
1107
|
session.registerCommands(config.commands);
|
|
1108
|
+
const {
|
|
1109
|
+
wireProvider: bearerWireProvider,
|
|
1110
|
+
wireProviders: bearerWireProviders,
|
|
1111
|
+
callbacks: bearerTokenCallbacks
|
|
1112
|
+
} = extractBearerTokenProviders(config.provider, config.providers);
|
|
1113
|
+
if (bearerTokenCallbacks.size > 0) {
|
|
1114
|
+
session.registerBearerTokenProviders(bearerTokenCallbacks);
|
|
1115
|
+
}
|
|
1020
1116
|
session.registerPermissionHandler(config.onPermissionRequest);
|
|
1021
1117
|
if (config.onUserInputRequest) {
|
|
1022
1118
|
session.registerUserInputHandler(config.onUserInputRequest);
|
|
@@ -1078,8 +1174,9 @@ class CopilotClient {
|
|
|
1078
1174
|
name: cmd.name,
|
|
1079
1175
|
description: cmd.description
|
|
1080
1176
|
})),
|
|
1081
|
-
provider:
|
|
1082
|
-
|
|
1177
|
+
provider: bearerWireProvider,
|
|
1178
|
+
capi: config.capi,
|
|
1179
|
+
providers: bearerWireProviders,
|
|
1083
1180
|
models: config.models,
|
|
1084
1181
|
modelCapabilities: config.modelCapabilities,
|
|
1085
1182
|
largeOutput: toWireLargeOutput(config.largeOutput),
|
|
@@ -1119,7 +1216,8 @@ class CopilotClient {
|
|
|
1119
1216
|
continuePendingWork: config.continuePendingWork,
|
|
1120
1217
|
gitHubToken: config.gitHubToken,
|
|
1121
1218
|
remoteSession: config.remoteSession,
|
|
1122
|
-
openCanvases: config.openCanvases
|
|
1219
|
+
openCanvases: config.openCanvases,
|
|
1220
|
+
expAssignments: config.expAssignments
|
|
1123
1221
|
});
|
|
1124
1222
|
const { workspacePath, capabilities, openCanvases } = response;
|
|
1125
1223
|
session["_workspacePath"] = workspacePath;
|
|
@@ -1661,13 +1759,21 @@ stderr: ${stderrOutput}`
|
|
|
1661
1759
|
throw new Error("CLI process not started");
|
|
1662
1760
|
}
|
|
1663
1761
|
this.cliProcess.stdin?.on("error", (err) => {
|
|
1664
|
-
if (
|
|
1665
|
-
|
|
1762
|
+
if (this.forceStopping) {
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
this.state = "error";
|
|
1766
|
+
const reason = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
1767
|
+
this.logDebug(`stdin pipe error: ${reason}`);
|
|
1768
|
+
try {
|
|
1769
|
+
this.connection?.dispose();
|
|
1770
|
+
} catch {
|
|
1666
1771
|
}
|
|
1667
1772
|
});
|
|
1773
|
+
this.messageWriter = new TeardownResilientStreamMessageWriter(this.cliProcess.stdin);
|
|
1668
1774
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1669
1775
|
new import_node.StreamMessageReader(this.cliProcess.stdout),
|
|
1670
|
-
|
|
1776
|
+
this.messageWriter
|
|
1671
1777
|
);
|
|
1672
1778
|
this.attachConnectionHandlers();
|
|
1673
1779
|
this.connection.listen();
|
|
@@ -1679,9 +1785,10 @@ stderr: ${stderrOutput}`
|
|
|
1679
1785
|
if (this.cliProcess) {
|
|
1680
1786
|
throw new Error("CLI child process was unexpectedly started in parent process mode");
|
|
1681
1787
|
}
|
|
1788
|
+
this.messageWriter = new TeardownResilientStreamMessageWriter(process.stdout);
|
|
1682
1789
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1683
1790
|
new import_node.StreamMessageReader(process.stdin),
|
|
1684
|
-
|
|
1791
|
+
this.messageWriter
|
|
1685
1792
|
);
|
|
1686
1793
|
this.attachConnectionHandlers();
|
|
1687
1794
|
this.connection.listen();
|
|
@@ -1701,9 +1808,10 @@ stderr: ${stderrOutput}`
|
|
|
1701
1808
|
}, 1e4);
|
|
1702
1809
|
this.socket.connect(this.runtimePort, this.actualHost, () => {
|
|
1703
1810
|
clearTimeout(connectionTimeout);
|
|
1811
|
+
this.messageWriter = new TeardownResilientStreamMessageWriter(this.socket);
|
|
1704
1812
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1705
1813
|
new import_node.StreamMessageReader(this.socket),
|
|
1706
|
-
|
|
1814
|
+
this.messageWriter
|
|
1707
1815
|
);
|
|
1708
1816
|
this.attachConnectionHandlers();
|
|
1709
1817
|
this.connection.listen();
|
|
@@ -1751,6 +1859,7 @@ stderr: ${stderrOutput}`
|
|
|
1751
1859
|
if (!session) throw new Error(`No session found for sessionId: ${sessionId}`);
|
|
1752
1860
|
return session.clientSessionApis;
|
|
1753
1861
|
});
|
|
1862
|
+
(0, import_rpc.registerClientGlobalApiHandlers)(this.connection, this.llmInferenceHandlers);
|
|
1754
1863
|
this.connection.onClose(() => {
|
|
1755
1864
|
this.state = "disconnected";
|
|
1756
1865
|
});
|