@github/copilot-sdk 1.0.29-preview.1 → 1.0.29-preview.10
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 +658 -11
- package/dist/cjs/cliVersion.js +1 -1
- package/dist/cjs/client.js +138 -39
- package/dist/cjs/copilotRequestHandler.js +17 -7
- package/dist/cjs/generated/rpc.js +321 -6
- package/dist/cjs/session.js +59 -1
- package/dist/cjs/types.js +3 -5
- package/dist/cliVersion.d.ts +1 -1
- package/dist/cliVersion.js +1 -1
- package/dist/client.d.ts +8 -7
- package/dist/client.js +140 -41
- package/dist/copilotRequestHandler.js +17 -7
- package/dist/generated/lifecycle-diagnostics.d.ts +4 -0
- package/dist/generated/rpc.d.ts +670 -14
- package/dist/generated/rpc.js +321 -6
- package/dist/generated/session-events.d.ts +48 -2
- package/dist/index.d.ts +1 -1
- package/dist/session.d.ts +11 -3
- package/dist/session.js +59 -1
- package/dist/types.d.ts +50 -16
- package/dist/types.js +3 -5
- package/docs/agent-author.md +53 -5
- package/docs/examples.md +21 -16
- package/docs/workflows.md +2 -3
- package/package.json +17 -14
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ By default the callback authenticates only requests made for sessions this clien
|
|
|
64
64
|
`startAhpHost()` requires `authentication`: `github`, or direct-only `none` / `custom`
|
|
65
65
|
(`requireIdentity` and a validator returning `{identity,expiresAt}` or `null`):
|
|
66
66
|
|
|
67
|
+
<!-- docs-validate: strict -->
|
|
67
68
|
```typescript
|
|
68
69
|
import { CopilotClient } from "@github/copilot-sdk";
|
|
69
70
|
|
|
@@ -134,6 +135,7 @@ by the SDK. Published sessions remain discoverable after hosting stops.
|
|
|
134
135
|
|
|
135
136
|
Supply `createSession` to materialize fresh AHP sessions in your application:
|
|
136
137
|
|
|
138
|
+
<!-- docs-validate: strict -->
|
|
137
139
|
```typescript
|
|
138
140
|
import { approveAll, CopilotClient, defineTool } from "@github/copilot-sdk";
|
|
139
141
|
|
|
@@ -218,6 +220,7 @@ npm start
|
|
|
218
220
|
|
|
219
221
|
## Quick Start
|
|
220
222
|
|
|
223
|
+
<!-- docs-validate: strict -->
|
|
221
224
|
```typescript
|
|
222
225
|
import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
223
226
|
|
|
@@ -252,7 +255,10 @@ await client.stop();
|
|
|
252
255
|
|
|
253
256
|
Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2+ / Node.js 20+):
|
|
254
257
|
|
|
258
|
+
<!-- docs-validate: strict -->
|
|
255
259
|
```typescript
|
|
260
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
261
|
+
|
|
256
262
|
await using session = await client.createSession({
|
|
257
263
|
model: "gpt-5",
|
|
258
264
|
onPermissionRequest: approveAll,
|
|
@@ -282,7 +288,7 @@ new CopilotClient(options?: CopilotClientOptions)
|
|
|
282
288
|
- `RuntimeConnection.forStdio({ path?, args?, env? })` (default) — spawn the runtime and communicate over its stdin/stdout.
|
|
283
289
|
- `RuntimeConnection.forTcp({ port?, connectionToken?, path?, args?, env? })` — spawn the runtime as a TCP server.
|
|
284
290
|
- `RuntimeConnection.forUri(url, { connectionToken? })` — connect to an already-running runtime (mutually exclusive with `gitHubToken`/`useLoggedInUser`). There is no top-level `cliUrl` shortcut; use this factory for URL-based connections.
|
|
285
|
-
- `RuntimeConnection.forInProcess()` — host the runtime in-process over its native C ABI (FFI). **Experimental.**
|
|
291
|
+
- `RuntimeConnection.forInProcess()` — host the runtime in-process over its native C ABI (FFI). **Experimental.** Client-level `env`, `telemetry`, and `workingDirectory` are rejected; use supported typed options and configure working directories per session.
|
|
286
292
|
- The child-process transports (`forStdio`/`forTcp`) also accept a per-connection `env`. Set it there or via the top-level `env` option — not both (setting both throws).
|
|
287
293
|
- Managed child-process connections materialize the bundled `copilot-runtime` and adjacent `runtime.node`, then launch the wrapper by default. An explicit connection `path` or `COPILOT_CLI_PATH` overrides the bundled runtime.
|
|
288
294
|
- `mode?: "empty" | "copilot-cli"` - Defaulting strategy. Use `"empty"` for multi-user server mode; defaults to `"copilot-cli"`.
|
|
@@ -417,6 +423,20 @@ Create a new conversation session.
|
|
|
417
423
|
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
|
|
418
424
|
- `skillProvider?: SkillProvider` - **Experimental.** Serves skills from host storage instead of skill directories. Not persisted; pass it again on resume. See [Skill providers](#skill-providers-experimental).
|
|
419
425
|
|
|
426
|
+
<!-- docs-validate: strict -->
|
|
427
|
+
<!-- docs-validate: hidden -->
|
|
428
|
+
```typescript
|
|
429
|
+
declare function acquireTokenForHost(host: string): Promise<string>;
|
|
430
|
+
|
|
431
|
+
const session = await client.createSession({
|
|
432
|
+
gitHubTokenProvider: async ({ host }) => ({
|
|
433
|
+
kind: "token",
|
|
434
|
+
accessToken: await acquireTokenForHost(host),
|
|
435
|
+
expiresIn: 8 * 60 * 60,
|
|
436
|
+
}),
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
<!-- /docs-validate: hidden -->
|
|
420
440
|
```typescript
|
|
421
441
|
const session = await client.createSession({
|
|
422
442
|
gitHubTokenProvider: async ({ host }) => ({
|
|
@@ -465,6 +485,8 @@ List all available sessions. Optionally filter by working directory context.
|
|
|
465
485
|
- `summary?: string` - Optional session summary
|
|
466
486
|
- `isRemote: boolean` - Whether the session is remote
|
|
467
487
|
- `context?: SessionContext` - Working directory context from session creation
|
|
488
|
+
- `clientName?: string` - Client that created the session (for example `github/cli`)
|
|
489
|
+
- `lastClientName?: string` - Client that most recently ran the session: the client that created it, or a client that resumed it and then ran it. Resuming a session only to observe it does not change it. Omitted when unknown, such as for sessions persisted before this field existed.
|
|
468
490
|
|
|
469
491
|
**SessionContext:**
|
|
470
492
|
|
|
@@ -489,6 +511,7 @@ Request the TUI to switch to displaying the specified session. Only available in
|
|
|
489
511
|
|
|
490
512
|
Subscribe to a specific session lifecycle event type. Returns an unsubscribe function.
|
|
491
513
|
|
|
514
|
+
<!-- docs-validate: strict -->
|
|
492
515
|
```typescript
|
|
493
516
|
const unsubscribe = client.onLifecycle("session.foreground", (event) => {
|
|
494
517
|
console.log(`Session ${event.sessionId} is now in foreground`);
|
|
@@ -499,6 +522,7 @@ const unsubscribe = client.onLifecycle("session.foreground", (event) => {
|
|
|
499
522
|
|
|
500
523
|
Subscribe to all session lifecycle events. Returns an unsubscribe function.
|
|
501
524
|
|
|
525
|
+
<!-- docs-validate: strict -->
|
|
502
526
|
```typescript
|
|
503
527
|
const unsubscribe = client.onLifecycle((event) => {
|
|
504
528
|
console.log(`${event.type}: ${event.sessionId}`);
|
|
@@ -546,12 +570,32 @@ Returns the message ID.
|
|
|
546
570
|
|
|
547
571
|
Use `source: "system"` for automated messages from your application:
|
|
548
572
|
|
|
573
|
+
<!-- docs-validate: strict -->
|
|
574
|
+
<!-- docs-validate: hidden -->
|
|
575
|
+
```typescript
|
|
576
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
577
|
+
|
|
578
|
+
declare const session: CopilotSession;
|
|
579
|
+
|
|
580
|
+
await session.send({ prompt: "Context updated", source: "system" });
|
|
581
|
+
```
|
|
582
|
+
<!-- /docs-validate: hidden -->
|
|
549
583
|
```typescript
|
|
550
584
|
await session.send({ prompt: "Context updated", source: "system" });
|
|
551
585
|
```
|
|
552
586
|
|
|
553
587
|
For a message from another agent, use its trusted sender ID:
|
|
554
588
|
|
|
589
|
+
<!-- docs-validate: strict -->
|
|
590
|
+
<!-- docs-validate: hidden -->
|
|
591
|
+
```typescript
|
|
592
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
593
|
+
|
|
594
|
+
declare const session: CopilotSession;
|
|
595
|
+
|
|
596
|
+
await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
|
|
597
|
+
```
|
|
598
|
+
<!-- /docs-validate: hidden -->
|
|
555
599
|
```typescript
|
|
556
600
|
await session.send({ prompt: "Review complete", source: "agent-reviewer-id" });
|
|
557
601
|
```
|
|
@@ -584,6 +628,23 @@ Pass a raw JSON Schema or a Zod schema as `responseSchema` to `send` or
|
|
|
584
628
|
`sendAndWait`. As with custom tool parameters, the SDK converts Zod schemas to
|
|
585
629
|
JSON Schema before sending them:
|
|
586
630
|
|
|
631
|
+
<!-- docs-validate: strict -->
|
|
632
|
+
<!-- docs-validate: hidden -->
|
|
633
|
+
```typescript
|
|
634
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
635
|
+
|
|
636
|
+
declare const session: CopilotSession;
|
|
637
|
+
|
|
638
|
+
import { z } from "zod";
|
|
639
|
+
|
|
640
|
+
const answerSchema = z.object({ answer: z.number().int() });
|
|
641
|
+
const message = await session.sendAndWait({
|
|
642
|
+
prompt: "What is 19 + 23?",
|
|
643
|
+
responseSchema: answerSchema,
|
|
644
|
+
});
|
|
645
|
+
console.log(message?.data.content); // JSON text
|
|
646
|
+
```
|
|
647
|
+
<!-- /docs-validate: hidden -->
|
|
587
648
|
```typescript
|
|
588
649
|
import { z } from "zod";
|
|
589
650
|
|
|
@@ -597,6 +658,20 @@ console.log(message?.data.content); // JSON text
|
|
|
597
658
|
|
|
598
659
|
For a typed result, pass the Zod schema as the **second argument** instead:
|
|
599
660
|
|
|
661
|
+
<!-- docs-validate: strict -->
|
|
662
|
+
<!-- docs-validate: hidden -->
|
|
663
|
+
```typescript
|
|
664
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
665
|
+
|
|
666
|
+
declare const session: CopilotSession;
|
|
667
|
+
import { z } from "zod";
|
|
668
|
+
|
|
669
|
+
const answerSchema = z.object({ answer: z.number().int() });
|
|
670
|
+
|
|
671
|
+
const answer = await session.sendAndWait("What is 19 + 23?", answerSchema);
|
|
672
|
+
console.log(answer.answer); // number; TResult is inferred from answerSchema
|
|
673
|
+
```
|
|
674
|
+
<!-- /docs-validate: hidden -->
|
|
600
675
|
```typescript
|
|
601
676
|
const answer = await session.sendAndWait("What is 19 + 23?", answerSchema);
|
|
602
677
|
console.log(answer.answer); // number; TResult is inferred from answerSchema
|
|
@@ -616,6 +691,10 @@ sends do not inherit it. Ordinary immediate steering inherits the active schema
|
|
|
616
691
|
and originating message ID, even when it arrives too late for the current model
|
|
617
692
|
request and is promoted into a follow-up run. Specifying a schema with
|
|
618
693
|
`mode: "immediate"` is rejected, even while idle.
|
|
694
|
+
Provider schema restrictions still apply, and schemas are not rewritten. Strict
|
|
695
|
+
OpenAI output needs an object root with every property listed in `required`.
|
|
696
|
+
Zod leaves `.optional()` properties out of `required`, so use `.nullable()` for a
|
|
697
|
+
field the model may leave empty.
|
|
619
698
|
The generated `session.rpc.send` and `session.rpc.sendMessages` wrappers expose
|
|
620
699
|
the full `responseFormat` contract when you need to set its name, description,
|
|
621
700
|
or strict option rather than using the convenience defaults (`name: "response"`,
|
|
@@ -665,6 +744,28 @@ native `output_config.format` endpoint.
|
|
|
665
744
|
|
|
666
745
|
Subscribe to a specific event type. The handler receives properly typed events.
|
|
667
746
|
|
|
747
|
+
<!-- docs-validate: strict -->
|
|
748
|
+
<!-- docs-validate: hidden -->
|
|
749
|
+
```typescript
|
|
750
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
751
|
+
|
|
752
|
+
declare const session: CopilotSession;
|
|
753
|
+
|
|
754
|
+
// Listen for specific event types with full type inference
|
|
755
|
+
session.on("assistant.message", (event) => {
|
|
756
|
+
console.log(event.data.content); // TypeScript knows about event.data.content
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
session.on("session.idle", () => {
|
|
760
|
+
console.log("Session is idle");
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// Listen to streaming events
|
|
764
|
+
session.on("assistant.message_delta", (event) => {
|
|
765
|
+
process.stdout.write(event.data.deltaContent);
|
|
766
|
+
});
|
|
767
|
+
```
|
|
768
|
+
<!-- /docs-validate: hidden -->
|
|
668
769
|
```typescript
|
|
669
770
|
// Listen for specific event types with full type inference
|
|
670
771
|
session.on("assistant.message", (event) => {
|
|
@@ -685,6 +786,22 @@ session.on("assistant.message_delta", (event) => {
|
|
|
685
786
|
|
|
686
787
|
Subscribe to all session events. Returns an unsubscribe function.
|
|
687
788
|
|
|
789
|
+
<!-- docs-validate: strict -->
|
|
790
|
+
<!-- docs-validate: hidden -->
|
|
791
|
+
```typescript
|
|
792
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
793
|
+
|
|
794
|
+
declare const session: CopilotSession;
|
|
795
|
+
|
|
796
|
+
const unsubscribe = session.on((event) => {
|
|
797
|
+
// Handle any event type
|
|
798
|
+
console.log(event.type, event);
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
// Later...
|
|
802
|
+
unsubscribe();
|
|
803
|
+
```
|
|
804
|
+
<!-- /docs-validate: hidden -->
|
|
688
805
|
```typescript
|
|
689
806
|
const unsubscribe = session.on((event) => {
|
|
690
807
|
// Handle any event type
|
|
@@ -712,6 +829,19 @@ The runtime does not apply the preference immediately. It records the request an
|
|
|
712
829
|
|
|
713
830
|
Watch for the outcome through the `session.model_change` event on success or the ephemeral `session.auto_tier_switch_failed` event on failure. A failed activation leaves the incumbent effective tier unchanged. Read the authoritative state at any time with `session.rpc.model.getCurrent()`.
|
|
714
831
|
|
|
832
|
+
<!-- docs-validate: strict -->
|
|
833
|
+
<!-- docs-validate: hidden -->
|
|
834
|
+
```typescript
|
|
835
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
836
|
+
|
|
837
|
+
declare const session: CopilotSession;
|
|
838
|
+
|
|
839
|
+
const result = await session.setAutoTier("intelligence");
|
|
840
|
+
if (result.status === "pending") {
|
|
841
|
+
// Accepted, but not yet in effect.
|
|
842
|
+
}
|
|
843
|
+
```
|
|
844
|
+
<!-- /docs-validate: hidden -->
|
|
715
845
|
```typescript
|
|
716
846
|
const result = await session.setAutoTier("intelligence");
|
|
717
847
|
if (result.status === "pending") {
|
|
@@ -725,6 +855,23 @@ See [Auto tier persistence](../docs/features/session-persistence.md#auto-tier-pe
|
|
|
725
855
|
|
|
726
856
|
Read the current model's reasoning-summary presentation policy without changing session state. Call `session.rpc.model.list()` first to load the model catalog; otherwise the result may have `ready: false`. The request and result types are exported from `@github/copilot-sdk`.
|
|
727
857
|
|
|
858
|
+
<!-- docs-validate: strict -->
|
|
859
|
+
<!-- docs-validate: hidden -->
|
|
860
|
+
```typescript
|
|
861
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
862
|
+
|
|
863
|
+
declare const session: CopilotSession;
|
|
864
|
+
|
|
865
|
+
import type {
|
|
866
|
+
ModelGetReasoningSummariesRequest,
|
|
867
|
+
ModelGetReasoningSummariesResult,
|
|
868
|
+
} from "@github/copilot-sdk";
|
|
869
|
+
|
|
870
|
+
const presentation: ModelGetReasoningSummariesRequest = { summariesVisible: false };
|
|
871
|
+
const policy: ModelGetReasoningSummariesResult =
|
|
872
|
+
await session.rpc.model.getReasoningSummaries(presentation);
|
|
873
|
+
```
|
|
874
|
+
<!-- /docs-validate: hidden -->
|
|
728
875
|
```typescript
|
|
729
876
|
import type {
|
|
730
877
|
ModelGetReasoningSummariesRequest,
|
|
@@ -744,6 +891,26 @@ Replace the tools this client supplies to the session, together with the handler
|
|
|
744
891
|
|
|
745
892
|
Once the runtime accepts the replacement, every tool call this session dispatches uses the new handlers; calls already running finish on their original handlers. If the runtime rejects it, the promise rejects and the previous tools and handlers stay in place. Concurrent calls are applied one at a time, in call order.
|
|
746
893
|
|
|
894
|
+
<!-- docs-validate: strict -->
|
|
895
|
+
<!-- docs-validate: hidden -->
|
|
896
|
+
```typescript
|
|
897
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
898
|
+
|
|
899
|
+
declare const session: CopilotSession;
|
|
900
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
901
|
+
import { z } from "zod";
|
|
902
|
+
|
|
903
|
+
declare function searchIssues(query: string): Promise<string>;
|
|
904
|
+
|
|
905
|
+
await session.setTools([
|
|
906
|
+
defineTool("search_issues", {
|
|
907
|
+
description: "Search the issues shown on the current page",
|
|
908
|
+
parameters: z.object({ query: z.string() }),
|
|
909
|
+
handler: async ({ query }) => searchIssues(query),
|
|
910
|
+
}),
|
|
911
|
+
]);
|
|
912
|
+
```
|
|
913
|
+
<!-- /docs-validate: hidden -->
|
|
747
914
|
```typescript
|
|
748
915
|
await session.setTools([
|
|
749
916
|
defineTool("search_issues", {
|
|
@@ -772,6 +939,18 @@ Disconnect the session and free resources. Session data on disk is preserved for
|
|
|
772
939
|
|
|
773
940
|
Host capabilities reported when the session was created or resumed. Use this to check feature support before calling capability-gated APIs.
|
|
774
941
|
|
|
942
|
+
<!-- docs-validate: strict -->
|
|
943
|
+
<!-- docs-validate: hidden -->
|
|
944
|
+
```typescript
|
|
945
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
946
|
+
|
|
947
|
+
declare const session: CopilotSession;
|
|
948
|
+
|
|
949
|
+
if (session.capabilities.ui?.elicitation) {
|
|
950
|
+
const ok = await session.ui.confirm("Deploy?");
|
|
951
|
+
}
|
|
952
|
+
```
|
|
953
|
+
<!-- /docs-validate: hidden -->
|
|
775
954
|
```typescript
|
|
776
955
|
if (session.capabilities.ui?.elicitation) {
|
|
777
956
|
const ok = await session.ui.confirm("Deploy?");
|
|
@@ -784,10 +963,6 @@ Capabilities may update during the session. For example, when another client joi
|
|
|
784
963
|
|
|
785
964
|
Interactive UI methods for showing dialogs to the user. Only available when the CLI host supports elicitation (`session.capabilities.ui?.elicitation === true`). See [UI Elicitation](#ui-elicitation) for full details.
|
|
786
965
|
|
|
787
|
-
##### `destroy(): Promise<void>` _(deprecated)_
|
|
788
|
-
|
|
789
|
-
Deprecated — use `disconnect()` instead.
|
|
790
|
-
|
|
791
966
|
---
|
|
792
967
|
|
|
793
968
|
## Event Types
|
|
@@ -809,6 +984,38 @@ See `SessionEvent` type in the source for full details.
|
|
|
809
984
|
|
|
810
985
|
The SDK supports image attachments via the `attachments` parameter. You can attach images by providing their file path, or by passing base64-encoded data directly using a blob attachment:
|
|
811
986
|
|
|
987
|
+
<!-- docs-validate: strict -->
|
|
988
|
+
<!-- docs-validate: hidden -->
|
|
989
|
+
```typescript
|
|
990
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
991
|
+
|
|
992
|
+
declare const session: CopilotSession;
|
|
993
|
+
declare const base64ImageData: string;
|
|
994
|
+
|
|
995
|
+
// File attachment — runtime reads from disk
|
|
996
|
+
await session.send({
|
|
997
|
+
prompt: "What's in this image?",
|
|
998
|
+
attachments: [
|
|
999
|
+
{
|
|
1000
|
+
type: "file",
|
|
1001
|
+
path: "/path/to/image.jpg",
|
|
1002
|
+
},
|
|
1003
|
+
],
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
// Blob attachment — provide base64 data directly
|
|
1007
|
+
await session.send({
|
|
1008
|
+
prompt: "What's in this image?",
|
|
1009
|
+
attachments: [
|
|
1010
|
+
{
|
|
1011
|
+
type: "blob",
|
|
1012
|
+
data: base64ImageData,
|
|
1013
|
+
mimeType: "image/png",
|
|
1014
|
+
},
|
|
1015
|
+
],
|
|
1016
|
+
});
|
|
1017
|
+
```
|
|
1018
|
+
<!-- /docs-validate: hidden -->
|
|
812
1019
|
```typescript
|
|
813
1020
|
// File attachment — runtime reads from disk
|
|
814
1021
|
await session.send({
|
|
@@ -836,6 +1043,16 @@ await session.send({
|
|
|
836
1043
|
|
|
837
1044
|
Supported image formats are PNG, JPEG, WebP, and GIF. Images in other formats, such as BMP or TIFF, are not sent to the model. The agent's `view` tool can also read images directly from the filesystem, so you can also ask questions like:
|
|
838
1045
|
|
|
1046
|
+
<!-- docs-validate: strict -->
|
|
1047
|
+
<!-- docs-validate: hidden -->
|
|
1048
|
+
```typescript
|
|
1049
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
1050
|
+
|
|
1051
|
+
declare const session: CopilotSession;
|
|
1052
|
+
|
|
1053
|
+
await session.send({ prompt: "What does the most recent jpg in this directory portray?" });
|
|
1054
|
+
```
|
|
1055
|
+
<!-- /docs-validate: hidden -->
|
|
839
1056
|
```typescript
|
|
840
1057
|
await session.send({ prompt: "What does the most recent jpg in this directory portray?" });
|
|
841
1058
|
```
|
|
@@ -844,6 +1061,51 @@ await session.send({ prompt: "What does the most recent jpg in this directory po
|
|
|
844
1061
|
|
|
845
1062
|
Enable streaming to receive assistant response chunks as they're generated:
|
|
846
1063
|
|
|
1064
|
+
<!-- docs-validate: strict -->
|
|
1065
|
+
<!-- docs-validate: hidden -->
|
|
1066
|
+
```typescript
|
|
1067
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1068
|
+
|
|
1069
|
+
const session = await client.createSession({
|
|
1070
|
+
model: "gpt-5",
|
|
1071
|
+
streaming: true,
|
|
1072
|
+
onPermissionRequest: approveAll,
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
// Wait for completion using typed event handlers
|
|
1076
|
+
const done = new Promise<void>((resolve) => {
|
|
1077
|
+
session.on("assistant.message_delta", (event) => {
|
|
1078
|
+
// Streaming message chunk - print incrementally
|
|
1079
|
+
process.stdout.write(event.data.deltaContent);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
session.on("assistant.reasoning_delta", (event) => {
|
|
1083
|
+
// Streaming reasoning chunk (if model supports reasoning)
|
|
1084
|
+
process.stdout.write(event.data.deltaContent);
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
session.on("assistant.message", (event) => {
|
|
1088
|
+
// Final message - complete content
|
|
1089
|
+
console.log("\n--- Final message ---");
|
|
1090
|
+
console.log(event.data.content);
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
session.on("assistant.reasoning", (event) => {
|
|
1094
|
+
// Final reasoning content (if model supports reasoning)
|
|
1095
|
+
console.log("--- Reasoning ---");
|
|
1096
|
+
console.log(event.data.content);
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
session.on("session.idle", () => {
|
|
1100
|
+
// Session finished processing
|
|
1101
|
+
resolve();
|
|
1102
|
+
});
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
await session.send({ prompt: "Tell me a short story" });
|
|
1106
|
+
await done; // Wait for streaming to complete
|
|
1107
|
+
```
|
|
1108
|
+
<!-- /docs-validate: hidden -->
|
|
847
1109
|
```typescript
|
|
848
1110
|
const session = await client.createSession({
|
|
849
1111
|
model: "gpt-5",
|
|
@@ -897,7 +1159,10 @@ Note: `assistant.message` and `assistant.reasoning` (final events) are always se
|
|
|
897
1159
|
|
|
898
1160
|
### Manual Server Control
|
|
899
1161
|
|
|
1162
|
+
<!-- docs-validate: strict -->
|
|
900
1163
|
```typescript
|
|
1164
|
+
import { CopilotClient } from "@github/copilot-sdk";
|
|
1165
|
+
|
|
901
1166
|
const client = new CopilotClient({});
|
|
902
1167
|
|
|
903
1168
|
// Start manually
|
|
@@ -913,6 +1178,31 @@ await client.stop();
|
|
|
913
1178
|
|
|
914
1179
|
You can let the CLI call back into your process when the model needs capabilities you own. Use `defineTool` with Zod schemas for type-safe tool definitions:
|
|
915
1180
|
|
|
1181
|
+
<!-- docs-validate: strict -->
|
|
1182
|
+
<!-- docs-validate: hidden -->
|
|
1183
|
+
```ts
|
|
1184
|
+
import { z } from "zod";
|
|
1185
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
1186
|
+
|
|
1187
|
+
declare function fetchIssue(id: string): Promise<string>;
|
|
1188
|
+
|
|
1189
|
+
const session = await client.createSession({
|
|
1190
|
+
model: "gpt-5",
|
|
1191
|
+
tools: [
|
|
1192
|
+
defineTool("lookup_issue", {
|
|
1193
|
+
description: "Fetch issue details from our tracker",
|
|
1194
|
+
parameters: z.object({
|
|
1195
|
+
id: z.string().describe("Issue identifier"),
|
|
1196
|
+
}),
|
|
1197
|
+
handler: async ({ id }) => {
|
|
1198
|
+
const issue = await fetchIssue(id);
|
|
1199
|
+
return issue;
|
|
1200
|
+
},
|
|
1201
|
+
}),
|
|
1202
|
+
],
|
|
1203
|
+
});
|
|
1204
|
+
```
|
|
1205
|
+
<!-- /docs-validate: hidden -->
|
|
916
1206
|
```ts
|
|
917
1207
|
import { z } from "zod";
|
|
918
1208
|
import { CopilotClient, defineTool } from "@github/copilot-sdk";
|
|
@@ -940,6 +1230,22 @@ When Copilot invokes `lookup_issue`, the client automatically runs your handler
|
|
|
940
1230
|
|
|
941
1231
|
If you register a tool with the same name as a built-in CLI tool (e.g. `edit_file`, `read_file`), the SDK will throw an error unless you explicitly opt in by setting `overridesBuiltInTool: true`. This flag signals that you intend to replace the built-in tool with your custom implementation.
|
|
942
1232
|
|
|
1233
|
+
<!-- docs-validate: strict -->
|
|
1234
|
+
<!-- docs-validate: hidden -->
|
|
1235
|
+
```ts
|
|
1236
|
+
import { z } from "zod";
|
|
1237
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
1238
|
+
|
|
1239
|
+
defineTool("edit_file", {
|
|
1240
|
+
description: "Custom file editor with project-specific validation",
|
|
1241
|
+
parameters: z.object({ path: z.string(), content: z.string() }),
|
|
1242
|
+
overridesBuiltInTool: true,
|
|
1243
|
+
handler: async ({ path, content }) => {
|
|
1244
|
+
/* your logic */
|
|
1245
|
+
},
|
|
1246
|
+
});
|
|
1247
|
+
```
|
|
1248
|
+
<!-- /docs-validate: hidden -->
|
|
943
1249
|
```ts
|
|
944
1250
|
defineTool("edit_file", {
|
|
945
1251
|
description: "Custom file editor with project-specific validation",
|
|
@@ -956,6 +1262,19 @@ An `apply_patch` override can declare a string schema. The model sees a required
|
|
|
956
1262
|
dispatching to any SDK. Both a Zod-inferred Node handler and
|
|
957
1263
|
`invocation.arguments` receive the patch text as a string:
|
|
958
1264
|
|
|
1265
|
+
<!-- docs-validate: strict -->
|
|
1266
|
+
<!-- docs-validate: hidden -->
|
|
1267
|
+
```ts
|
|
1268
|
+
import { z } from "zod";
|
|
1269
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
1270
|
+
|
|
1271
|
+
defineTool("apply_patch", {
|
|
1272
|
+
parameters: z.string(),
|
|
1273
|
+
overridesBuiltInTool: true,
|
|
1274
|
+
handler: (patch) => patch.trim(),
|
|
1275
|
+
});
|
|
1276
|
+
```
|
|
1277
|
+
<!-- /docs-validate: hidden -->
|
|
959
1278
|
```ts
|
|
960
1279
|
defineTool("apply_patch", {
|
|
961
1280
|
parameters: z.string(),
|
|
@@ -971,6 +1290,22 @@ use an object schema if references are needed.
|
|
|
971
1290
|
|
|
972
1291
|
Set `skipPermission: true` on a tool definition to allow it to execute without triggering a permission prompt:
|
|
973
1292
|
|
|
1293
|
+
<!-- docs-validate: strict -->
|
|
1294
|
+
<!-- docs-validate: hidden -->
|
|
1295
|
+
```ts
|
|
1296
|
+
import { z } from "zod";
|
|
1297
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
1298
|
+
|
|
1299
|
+
defineTool("safe_lookup", {
|
|
1300
|
+
description: "A read-only lookup that needs no confirmation",
|
|
1301
|
+
parameters: z.object({ id: z.string() }),
|
|
1302
|
+
skipPermission: true,
|
|
1303
|
+
handler: async ({ id }) => {
|
|
1304
|
+
/* your logic */
|
|
1305
|
+
},
|
|
1306
|
+
});
|
|
1307
|
+
```
|
|
1308
|
+
<!-- /docs-validate: hidden -->
|
|
974
1309
|
```ts
|
|
975
1310
|
defineTool("safe_lookup", {
|
|
976
1311
|
description: "A read-only lookup that needs no confirmation",
|
|
@@ -986,6 +1321,22 @@ defineTool("safe_lookup", {
|
|
|
986
1321
|
|
|
987
1322
|
Set `defer` to control whether a tool may be loaded lazily via tool search rather than always pre-loaded. Use `"auto"` to allow the tool to be deferred and surfaced through tool search, or `"never"` to force it to always be pre-loaded. Defaults to `"auto"`.
|
|
988
1323
|
|
|
1324
|
+
<!-- docs-validate: strict -->
|
|
1325
|
+
<!-- docs-validate: hidden -->
|
|
1326
|
+
```ts
|
|
1327
|
+
import { z } from "zod";
|
|
1328
|
+
import { defineTool } from "@github/copilot-sdk";
|
|
1329
|
+
|
|
1330
|
+
defineTool("lookup_issue", {
|
|
1331
|
+
description: "Fetch issue details",
|
|
1332
|
+
parameters: z.object({ id: z.string() }),
|
|
1333
|
+
defer: "auto",
|
|
1334
|
+
handler: async ({ id }) => {
|
|
1335
|
+
/* your logic */
|
|
1336
|
+
},
|
|
1337
|
+
});
|
|
1338
|
+
```
|
|
1339
|
+
<!-- /docs-validate: hidden -->
|
|
989
1340
|
```ts
|
|
990
1341
|
defineTool("lookup_issue", {
|
|
991
1342
|
description: "Fetch issue details",
|
|
@@ -1001,6 +1352,26 @@ defineTool("lookup_issue", {
|
|
|
1001
1352
|
|
|
1002
1353
|
Register slash commands so that users of the CLI's TUI can invoke custom actions via `/commandName`. Each command has a `name`, optional `description`, and a `handler` called when the user executes it.
|
|
1003
1354
|
|
|
1355
|
+
<!-- docs-validate: strict -->
|
|
1356
|
+
<!-- docs-validate: hidden -->
|
|
1357
|
+
```ts
|
|
1358
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1359
|
+
|
|
1360
|
+
const session = await client.createSession({
|
|
1361
|
+
onPermissionRequest: approveAll,
|
|
1362
|
+
commands: [
|
|
1363
|
+
{
|
|
1364
|
+
name: "deploy",
|
|
1365
|
+
description: "Deploy the app to production",
|
|
1366
|
+
handler: async ({ commandName, args }) => {
|
|
1367
|
+
console.log(`Deploying with args: ${args}`);
|
|
1368
|
+
// Do work here — any thrown error is reported back to the CLI
|
|
1369
|
+
},
|
|
1370
|
+
},
|
|
1371
|
+
],
|
|
1372
|
+
});
|
|
1373
|
+
```
|
|
1374
|
+
<!-- /docs-validate: hidden -->
|
|
1004
1375
|
```ts
|
|
1005
1376
|
const session = await client.createSession({
|
|
1006
1377
|
onPermissionRequest: approveAll,
|
|
@@ -1027,6 +1398,44 @@ When the session has elicitation support — either from the CLI's TUI or from a
|
|
|
1027
1398
|
|
|
1028
1399
|
> **Capability check:** Elicitation is only available when at least one connected participant advertises support. Always check `session.capabilities.ui?.elicitation` before calling UI methods — this property updates automatically as participants join and leave.
|
|
1029
1400
|
|
|
1401
|
+
<!-- docs-validate: strict -->
|
|
1402
|
+
<!-- docs-validate: hidden -->
|
|
1403
|
+
```ts
|
|
1404
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1405
|
+
|
|
1406
|
+
const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
1407
|
+
|
|
1408
|
+
if (session.capabilities.ui?.elicitation) {
|
|
1409
|
+
// Confirm dialog — returns boolean
|
|
1410
|
+
const ok = await session.ui.confirm("Deploy to production?");
|
|
1411
|
+
|
|
1412
|
+
// Selection dialog — returns selected value or null
|
|
1413
|
+
const env = await session.ui.select("Pick environment", ["production", "staging", "dev"]);
|
|
1414
|
+
|
|
1415
|
+
// Text input — returns string or null
|
|
1416
|
+
const name = await session.ui.input("Project name:", {
|
|
1417
|
+
title: "Name",
|
|
1418
|
+
minLength: 1,
|
|
1419
|
+
maxLength: 50,
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
// Generic elicitation with full schema control
|
|
1423
|
+
const result = await session.ui.elicitation({
|
|
1424
|
+
message: "Configure deployment",
|
|
1425
|
+
requestedSchema: {
|
|
1426
|
+
type: "object",
|
|
1427
|
+
properties: {
|
|
1428
|
+
region: { type: "string", enum: ["us-east", "eu-west"] },
|
|
1429
|
+
dryRun: { type: "boolean", default: true },
|
|
1430
|
+
},
|
|
1431
|
+
required: ["region"],
|
|
1432
|
+
},
|
|
1433
|
+
});
|
|
1434
|
+
// result.action: "accept" | "decline" | "cancel"
|
|
1435
|
+
// result.content: { region: "us-east", dryRun: true } (when accepted)
|
|
1436
|
+
}
|
|
1437
|
+
```
|
|
1438
|
+
<!-- /docs-validate: hidden -->
|
|
1030
1439
|
```ts
|
|
1031
1440
|
const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
1032
1441
|
|
|
@@ -1067,6 +1476,7 @@ All UI methods throw if elicitation is not supported by the host.
|
|
|
1067
1476
|
|
|
1068
1477
|
Control the system prompt using `systemMessage` in session config:
|
|
1069
1478
|
|
|
1479
|
+
<!-- docs-validate: strict -->
|
|
1070
1480
|
```typescript
|
|
1071
1481
|
const session = await client.createSession({
|
|
1072
1482
|
model: "gpt-5",
|
|
@@ -1087,6 +1497,7 @@ The SDK auto-injects environment context, tool instructions, and security guardr
|
|
|
1087
1497
|
|
|
1088
1498
|
Use `mode: "customize"` to selectively override individual sections of the prompt while preserving the rest:
|
|
1089
1499
|
|
|
1500
|
+
<!-- docs-validate: strict -->
|
|
1090
1501
|
```typescript
|
|
1091
1502
|
import { SYSTEM_MESSAGE_SECTIONS } from "@github/copilot-sdk";
|
|
1092
1503
|
import type { SectionOverride, SystemMessageSection } from "@github/copilot-sdk";
|
|
@@ -1134,6 +1545,7 @@ Unknown section IDs are handled gracefully: content from `replace`/`append`/`pre
|
|
|
1134
1545
|
|
|
1135
1546
|
For full control (removes all guardrails), use `mode: "replace"`:
|
|
1136
1547
|
|
|
1548
|
+
<!-- docs-validate: strict -->
|
|
1137
1549
|
```typescript
|
|
1138
1550
|
const session = await client.createSession({
|
|
1139
1551
|
model: "gpt-5",
|
|
@@ -1148,6 +1560,8 @@ const session = await client.createSession({
|
|
|
1148
1560
|
|
|
1149
1561
|
By default, sessions use **infinite sessions** which automatically manage context window limits through background compaction and persist state to a workspace directory.
|
|
1150
1562
|
|
|
1563
|
+
<!-- docs-validate: strict -->
|
|
1564
|
+
<!-- docs-validate: hidden -->
|
|
1151
1565
|
```typescript
|
|
1152
1566
|
// Default: infinite sessions enabled with default thresholds
|
|
1153
1567
|
const session = await client.createSession({ model: "gpt-5" });
|
|
@@ -1157,7 +1571,7 @@ console.log(session.workspacePath);
|
|
|
1157
1571
|
// => ~/.copilot/session-state/{sessionId}/
|
|
1158
1572
|
|
|
1159
1573
|
// Custom thresholds
|
|
1160
|
-
const
|
|
1574
|
+
const tuned = await client.createSession({
|
|
1161
1575
|
model: "gpt-5",
|
|
1162
1576
|
infiniteSessions: {
|
|
1163
1577
|
enabled: true,
|
|
@@ -1167,7 +1581,32 @@ const session = await client.createSession({
|
|
|
1167
1581
|
});
|
|
1168
1582
|
|
|
1169
1583
|
// Disable infinite sessions
|
|
1170
|
-
const
|
|
1584
|
+
const disabled = await client.createSession({
|
|
1585
|
+
model: "gpt-5",
|
|
1586
|
+
infiniteSessions: { enabled: false },
|
|
1587
|
+
});
|
|
1588
|
+
```
|
|
1589
|
+
<!-- /docs-validate: hidden -->
|
|
1590
|
+
```typescript
|
|
1591
|
+
// Default: infinite sessions enabled with default thresholds
|
|
1592
|
+
const session = await client.createSession({ model: "gpt-5" });
|
|
1593
|
+
|
|
1594
|
+
// Access the workspace path for checkpoints and files
|
|
1595
|
+
console.log(session.workspacePath);
|
|
1596
|
+
// => ~/.copilot/session-state/{sessionId}/
|
|
1597
|
+
|
|
1598
|
+
// Custom thresholds
|
|
1599
|
+
const tuned = await client.createSession({
|
|
1600
|
+
model: "gpt-5",
|
|
1601
|
+
infiniteSessions: {
|
|
1602
|
+
enabled: true,
|
|
1603
|
+
backgroundCompactionThreshold: 0.8, // Start compacting at 80% context usage
|
|
1604
|
+
bufferExhaustionThreshold: 0.95, // Block at 95% until compaction completes
|
|
1605
|
+
},
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
// Disable infinite sessions
|
|
1609
|
+
const disabled = await client.createSession({
|
|
1171
1610
|
model: "gpt-5",
|
|
1172
1611
|
infiniteSessions: { enabled: false },
|
|
1173
1612
|
});
|
|
@@ -1187,15 +1626,31 @@ SDK leaves `memory` unset so the runtime applies its own default, while `"empty"
|
|
|
1187
1626
|
defaults `memory` to disabled unless you set it explicitly.
|
|
1188
1627
|
For more background, see [About GitHub Copilot Memory](https://docs.github.com/en/copilot/concepts/agents/copilot-memory).
|
|
1189
1628
|
|
|
1629
|
+
<!-- docs-validate: strict -->
|
|
1630
|
+
<!-- docs-validate: hidden -->
|
|
1190
1631
|
```typescript
|
|
1191
1632
|
// Enable memory for a session
|
|
1192
|
-
const
|
|
1633
|
+
const enabled = await client.createSession({
|
|
1193
1634
|
model: "gpt-5",
|
|
1194
1635
|
memory: { enabled: true },
|
|
1195
1636
|
});
|
|
1196
1637
|
|
|
1197
1638
|
// Disable memory for a session
|
|
1198
|
-
const
|
|
1639
|
+
const disabled = await client.createSession({
|
|
1640
|
+
model: "gpt-5",
|
|
1641
|
+
memory: { enabled: false },
|
|
1642
|
+
});
|
|
1643
|
+
```
|
|
1644
|
+
<!-- /docs-validate: hidden -->
|
|
1645
|
+
```typescript
|
|
1646
|
+
// Enable memory for a session
|
|
1647
|
+
const enabled = await client.createSession({
|
|
1648
|
+
model: "gpt-5",
|
|
1649
|
+
memory: { enabled: true },
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1652
|
+
// Disable memory for a session
|
|
1653
|
+
const disabled = await client.createSession({
|
|
1199
1654
|
model: "gpt-5",
|
|
1200
1655
|
memory: { enabled: false },
|
|
1201
1656
|
});
|
|
@@ -1207,6 +1662,29 @@ A skill provider serves skills from your own storage, such as a database, instea
|
|
|
1207
1662
|
files on disk. Provider skills join the session's skill catalog and load on demand through the
|
|
1208
1663
|
`skill` tool, just like file-based skills.
|
|
1209
1664
|
|
|
1665
|
+
<!-- docs-validate: strict -->
|
|
1666
|
+
<!-- docs-validate: hidden -->
|
|
1667
|
+
```typescript
|
|
1668
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1669
|
+
import type { SkillProvider } from "@github/copilot-sdk";
|
|
1670
|
+
|
|
1671
|
+
declare const db: {
|
|
1672
|
+
findSkill(name: string, options: { signal: AbortSignal }): Promise<{ markdown: string } | undefined>;
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
const skillProvider: SkillProvider = {
|
|
1676
|
+
listSkills: async () => [
|
|
1677
|
+
{ name: "release-notes", description: "Writes release notes in the team's format." },
|
|
1678
|
+
],
|
|
1679
|
+
readSkill: async (name, { signal }) => (await db.findSkill(name, { signal }))?.markdown ?? null,
|
|
1680
|
+
};
|
|
1681
|
+
|
|
1682
|
+
const session = await client.createSession({
|
|
1683
|
+
onPermissionRequest: approveAll,
|
|
1684
|
+
skillProvider,
|
|
1685
|
+
});
|
|
1686
|
+
```
|
|
1687
|
+
<!-- /docs-validate: hidden -->
|
|
1210
1688
|
```typescript
|
|
1211
1689
|
import type { SkillProvider } from "@github/copilot-sdk";
|
|
1212
1690
|
|
|
@@ -1260,6 +1738,7 @@ See [Supporting files](../docs/features/skills.md#supporting-files-experimental)
|
|
|
1260
1738
|
|
|
1261
1739
|
### Multiple Sessions
|
|
1262
1740
|
|
|
1741
|
+
<!-- docs-validate: strict -->
|
|
1263
1742
|
```typescript
|
|
1264
1743
|
const session1 = await client.createSession({ model: "gpt-5" });
|
|
1265
1744
|
const session2 = await client.createSession({ model: "claude-sonnet-4.5" });
|
|
@@ -1271,6 +1750,7 @@ await session2.sendAndWait({ prompt: "Hello from session 2" });
|
|
|
1271
1750
|
|
|
1272
1751
|
### Custom Session IDs
|
|
1273
1752
|
|
|
1753
|
+
<!-- docs-validate: strict -->
|
|
1274
1754
|
```typescript
|
|
1275
1755
|
const session = await client.createSession({
|
|
1276
1756
|
sessionId: "my-custom-session-id",
|
|
@@ -1280,6 +1760,25 @@ const session = await client.createSession({
|
|
|
1280
1760
|
|
|
1281
1761
|
### File Attachments
|
|
1282
1762
|
|
|
1763
|
+
<!-- docs-validate: strict -->
|
|
1764
|
+
<!-- docs-validate: hidden -->
|
|
1765
|
+
```typescript
|
|
1766
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1767
|
+
|
|
1768
|
+
const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
1769
|
+
|
|
1770
|
+
await session.send({
|
|
1771
|
+
prompt: "Analyze this file",
|
|
1772
|
+
attachments: [
|
|
1773
|
+
{
|
|
1774
|
+
type: "file",
|
|
1775
|
+
path: "/path/to/file.js",
|
|
1776
|
+
displayName: "My File",
|
|
1777
|
+
},
|
|
1778
|
+
],
|
|
1779
|
+
});
|
|
1780
|
+
```
|
|
1781
|
+
<!-- /docs-validate: hidden -->
|
|
1283
1782
|
```typescript
|
|
1284
1783
|
await session.send({
|
|
1285
1784
|
prompt: "Analyze this file",
|
|
@@ -1308,6 +1807,7 @@ The SDK supports custom OpenAI-compatible API providers (BYOK - Bring Your Own K
|
|
|
1308
1807
|
|
|
1309
1808
|
**Example with Ollama:**
|
|
1310
1809
|
|
|
1810
|
+
<!-- docs-validate: strict -->
|
|
1311
1811
|
```typescript
|
|
1312
1812
|
const session = await client.createSession({
|
|
1313
1813
|
model: "deepseek-coder-v2:16b", // Required when using custom provider
|
|
@@ -1323,6 +1823,7 @@ await session.sendAndWait({ prompt: "Hello!" });
|
|
|
1323
1823
|
|
|
1324
1824
|
**Example with custom OpenAI-compatible API:**
|
|
1325
1825
|
|
|
1826
|
+
<!-- docs-validate: strict -->
|
|
1326
1827
|
```typescript
|
|
1327
1828
|
const session = await client.createSession({
|
|
1328
1829
|
model: "gpt-4",
|
|
@@ -1336,6 +1837,7 @@ const session = await client.createSession({
|
|
|
1336
1837
|
|
|
1337
1838
|
**Example with Azure OpenAI:**
|
|
1338
1839
|
|
|
1840
|
+
<!-- docs-validate: strict -->
|
|
1339
1841
|
```typescript
|
|
1340
1842
|
const session = await client.createSession({
|
|
1341
1843
|
model: "gpt-4",
|
|
@@ -1360,7 +1862,10 @@ const session = await client.createSession({
|
|
|
1360
1862
|
|
|
1361
1863
|
The SDK supports OpenTelemetry for distributed tracing. Provide a `telemetry` config to enable trace export from the CLI process — this is all most users need:
|
|
1362
1864
|
|
|
1865
|
+
<!-- docs-validate: strict -->
|
|
1363
1866
|
```typescript
|
|
1867
|
+
import { CopilotClient } from "@github/copilot-sdk";
|
|
1868
|
+
|
|
1364
1869
|
const client = new CopilotClient({
|
|
1365
1870
|
telemetry: {
|
|
1366
1871
|
otlpEndpoint: "http://localhost:4318",
|
|
@@ -1412,6 +1917,17 @@ Callbacks receive optional derived prompt context as `invocation.promptRequest`.
|
|
|
1412
1917
|
|
|
1413
1918
|
Use the built-in `approveAll` helper when managed settings are disabled:
|
|
1414
1919
|
|
|
1920
|
+
<!-- docs-validate: strict -->
|
|
1921
|
+
<!-- docs-validate: hidden -->
|
|
1922
|
+
```typescript
|
|
1923
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
1924
|
+
|
|
1925
|
+
const session = await client.createSession({
|
|
1926
|
+
model: "gpt-5",
|
|
1927
|
+
onPermissionRequest: approveAll,
|
|
1928
|
+
});
|
|
1929
|
+
```
|
|
1930
|
+
<!-- /docs-validate: hidden -->
|
|
1415
1931
|
```typescript
|
|
1416
1932
|
import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
1417
1933
|
|
|
@@ -1427,6 +1943,7 @@ When `enableManagedSettings` is true for the session, `approveAll` throws. Use a
|
|
|
1427
1943
|
|
|
1428
1944
|
Provide your own function to inspect each request and apply custom logic. Check `managedApprovalRequired` before any automatic approval:
|
|
1429
1945
|
|
|
1946
|
+
<!-- docs-validate: strict -->
|
|
1430
1947
|
```typescript
|
|
1431
1948
|
import type { PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk";
|
|
1432
1949
|
|
|
@@ -1500,6 +2017,26 @@ Recheck requires session opt-in through `enableManagedSettings: true`.
|
|
|
1500
2017
|
Treat helper text as untrusted plain text, keep `diagnostic` secondary,
|
|
1501
2018
|
and sanitize `helpLink` before navigation.
|
|
1502
2019
|
|
|
2020
|
+
<!-- docs-validate: strict -->
|
|
2021
|
+
<!-- docs-validate: hidden -->
|
|
2022
|
+
```typescript
|
|
2023
|
+
import type { CopilotSession } from "@github/copilot-sdk";
|
|
2024
|
+
|
|
2025
|
+
declare const session: CopilotSession;
|
|
2026
|
+
|
|
2027
|
+
const snapshot = await session.rpc.managedSettings.get();
|
|
2028
|
+
|
|
2029
|
+
if (snapshot.policyHelperFailure) {
|
|
2030
|
+
console.warn(snapshot.policyHelperFailure.message);
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
if (snapshot.policyHelperCapabilities?.recheck === true) {
|
|
2034
|
+
const refreshed = await session.rpc.managedSettings.recheckPolicyHelper();
|
|
2035
|
+
// Only a current capable snapshot without policyHelperFailure establishes recovery.
|
|
2036
|
+
console.log(refreshed.policyHelperFailure ?? "Policy Helper recovered");
|
|
2037
|
+
}
|
|
2038
|
+
```
|
|
2039
|
+
<!-- /docs-validate: hidden -->
|
|
1503
2040
|
```typescript
|
|
1504
2041
|
const snapshot = await session.rpc.managedSettings.get();
|
|
1505
2042
|
|
|
@@ -1538,6 +2075,16 @@ The handler must return one of the `PermissionDecision` shapes (or `{ kind: "no-
|
|
|
1538
2075
|
|
|
1539
2076
|
You may pass `onPermissionRequest` when resuming a session too:
|
|
1540
2077
|
|
|
2078
|
+
<!-- docs-validate: strict -->
|
|
2079
|
+
<!-- docs-validate: hidden -->
|
|
2080
|
+
```typescript
|
|
2081
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
2082
|
+
|
|
2083
|
+
const session = await client.resumeSession("session-id", {
|
|
2084
|
+
onPermissionRequest: approveAll,
|
|
2085
|
+
});
|
|
2086
|
+
```
|
|
2087
|
+
<!-- /docs-validate: hidden -->
|
|
1541
2088
|
```typescript
|
|
1542
2089
|
const session = await client.resumeSession("session-id", {
|
|
1543
2090
|
onPermissionRequest: approveAll,
|
|
@@ -1552,6 +2099,7 @@ To let a specific custom tool bypass the permission prompt entirely, set `skipPe
|
|
|
1552
2099
|
|
|
1553
2100
|
Enable the legacy question-and-answer `ask_user` tool by providing an `onUserInputRequest` handler:
|
|
1554
2101
|
|
|
2102
|
+
<!-- docs-validate: strict -->
|
|
1555
2103
|
```typescript
|
|
1556
2104
|
const session = await client.createSession({
|
|
1557
2105
|
model: "gpt-5",
|
|
@@ -1559,6 +2107,7 @@ const session = await client.createSession({
|
|
|
1559
2107
|
// request.question - The question to ask
|
|
1560
2108
|
// request.choices - Optional array of choices for multiple choice
|
|
1561
2109
|
// request.allowFreeform - Whether freeform input is allowed (default: true)
|
|
2110
|
+
// request.requestId - Runtime ID of the pending request (absent on older runtimes)
|
|
1562
2111
|
|
|
1563
2112
|
console.log(`Agent asks: ${request.question}`);
|
|
1564
2113
|
if (request.choices) {
|
|
@@ -1578,7 +2127,10 @@ const session = await client.createSession({
|
|
|
1578
2127
|
|
|
1579
2128
|
Register an `onElicitationRequest` handler to let your client act as an elicitation provider — presenting form-based UI dialogs on behalf of the agent. When provided, the server notifies your client whenever a tool or MCP server needs structured user input.
|
|
1580
2129
|
|
|
2130
|
+
<!-- docs-validate: strict -->
|
|
1581
2131
|
```typescript
|
|
2132
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
2133
|
+
|
|
1582
2134
|
const session = await client.createSession({
|
|
1583
2135
|
model: "gpt-5",
|
|
1584
2136
|
onPermissionRequest: approveAll,
|
|
@@ -1619,6 +2171,100 @@ In multi-client scenarios:
|
|
|
1619
2171
|
|
|
1620
2172
|
Hook into session lifecycle events by providing handlers in the `hooks` configuration:
|
|
1621
2173
|
|
|
2174
|
+
<!-- docs-validate: strict -->
|
|
2175
|
+
<!-- docs-validate: hidden -->
|
|
2176
|
+
```typescript
|
|
2177
|
+
declare function needsMoreWork(): boolean;
|
|
2178
|
+
|
|
2179
|
+
const session = await client.createSession({
|
|
2180
|
+
model: "gpt-5",
|
|
2181
|
+
hooks: {
|
|
2182
|
+
// Called before each tool execution
|
|
2183
|
+
onPreToolUse: async (input, invocation) => {
|
|
2184
|
+
console.log(`About to run tool: ${input.toolName}`);
|
|
2185
|
+
// Return permission decision and optionally modify args
|
|
2186
|
+
return {
|
|
2187
|
+
permissionDecision: "allow", // "allow", "deny", or "ask"
|
|
2188
|
+
modifiedArgs: input.toolArgs, // Optionally modify tool arguments
|
|
2189
|
+
additionalContext: "Extra context for the model",
|
|
2190
|
+
};
|
|
2191
|
+
},
|
|
2192
|
+
|
|
2193
|
+
// Called after each successful tool execution
|
|
2194
|
+
onPostToolUse: async (input, invocation) => {
|
|
2195
|
+
console.log(`Tool ${input.toolName} completed`);
|
|
2196
|
+
// Optionally modify the result or add context
|
|
2197
|
+
return {
|
|
2198
|
+
additionalContext: "Post-execution notes",
|
|
2199
|
+
};
|
|
2200
|
+
},
|
|
2201
|
+
|
|
2202
|
+
// Called after a tool execution whose result was "failure".
|
|
2203
|
+
// onPostToolUse does NOT fire for failed tool calls — register this
|
|
2204
|
+
// hook to observe them. Input includes `error` (the failure message
|
|
2205
|
+
// extracted from the tool's result), not the full result object.
|
|
2206
|
+
onPostToolUseFailure: async (input, invocation) => {
|
|
2207
|
+
console.log(`Tool ${input.toolName} failed: ${input.error}`);
|
|
2208
|
+
// Optionally append hidden guidance to the model.
|
|
2209
|
+
return { additionalContext: "Suggest checking inputs and retrying." };
|
|
2210
|
+
},
|
|
2211
|
+
|
|
2212
|
+
// Called when user submits a prompt
|
|
2213
|
+
onUserPromptSubmitted: async (input, invocation) => {
|
|
2214
|
+
console.log(`User prompt: ${input.prompt}`);
|
|
2215
|
+
return {
|
|
2216
|
+
modifiedPrompt: input.prompt, // Optionally modify the prompt
|
|
2217
|
+
};
|
|
2218
|
+
},
|
|
2219
|
+
|
|
2220
|
+
// Called when session starts
|
|
2221
|
+
onSessionStart: async (input, invocation) => {
|
|
2222
|
+
console.log(`Session started from: ${input.source}`); // "startup", "resume", "new"
|
|
2223
|
+
return {
|
|
2224
|
+
additionalContext: "Session initialization context",
|
|
2225
|
+
};
|
|
2226
|
+
},
|
|
2227
|
+
|
|
2228
|
+
// Called when session ends
|
|
2229
|
+
onSessionEnd: async (input, invocation) => {
|
|
2230
|
+
console.log(`Session ended: ${input.reason}`);
|
|
2231
|
+
},
|
|
2232
|
+
|
|
2233
|
+
// Called when an error occurs
|
|
2234
|
+
onErrorOccurred: async (input, invocation) => {
|
|
2235
|
+
console.error(`Error in ${input.errorContext}: ${input.error}`);
|
|
2236
|
+
return {
|
|
2237
|
+
errorHandling: "retry", // "retry", "skip", or "abort"
|
|
2238
|
+
};
|
|
2239
|
+
},
|
|
2240
|
+
|
|
2241
|
+
// Called when the top-level agent naturally stops
|
|
2242
|
+
onAgentStop: async (input, invocation) => {
|
|
2243
|
+
if (!input.stopHookActive && needsMoreWork()) {
|
|
2244
|
+
return {
|
|
2245
|
+
decision: "block",
|
|
2246
|
+
reason: "Run the final validation and fix any failures.",
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
},
|
|
2250
|
+
|
|
2251
|
+
// Called before a sub-agent's first turn (the input identifies the parent session)
|
|
2252
|
+
onSubagentStart: (input, invocation) => {
|
|
2253
|
+
console.log(`Starting ${input.agentDisplayName ?? input.agentName}`);
|
|
2254
|
+
return { additionalContext: "Check the requested file before reporting back." };
|
|
2255
|
+
},
|
|
2256
|
+
|
|
2257
|
+
// Called when a sub-agent completes a turn
|
|
2258
|
+
onSubagentStop: (input, invocation) => {
|
|
2259
|
+
console.log(`${input.agentName} replied: ${input.response}`);
|
|
2260
|
+
// Return { decision: "block", reason: "Continue checking the file." }
|
|
2261
|
+
// to request another child turn instead.
|
|
2262
|
+
return { modifiedResponse: `Reviewed: ${input.response}` };
|
|
2263
|
+
},
|
|
2264
|
+
},
|
|
2265
|
+
});
|
|
2266
|
+
```
|
|
2267
|
+
<!-- /docs-validate: hidden -->
|
|
1622
2268
|
```typescript
|
|
1623
2269
|
const session = await client.createSession({
|
|
1624
2270
|
model: "gpt-5",
|
|
@@ -1724,12 +2370,13 @@ const session = await client.createSession({
|
|
|
1724
2370
|
|
|
1725
2371
|
## Error Handling
|
|
1726
2372
|
|
|
2373
|
+
<!-- docs-validate: strict -->
|
|
1727
2374
|
```typescript
|
|
1728
2375
|
try {
|
|
1729
|
-
const session = await client.createSession();
|
|
2376
|
+
const session = await client.createSession({});
|
|
1730
2377
|
await session.send({ prompt: "Hello" });
|
|
1731
2378
|
} catch (error) {
|
|
1732
|
-
console.error("Error:", error.message);
|
|
2379
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1733
2380
|
}
|
|
1734
2381
|
```
|
|
1735
2382
|
|