@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 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.** Because the runtime shares this process, `env`, `telemetry`, and `workingDirectory` are rejected with this transport; set them on the host process instead.
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 session = await client.createSession({
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 session = await client.createSession({
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 session = await client.createSession({
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 session = await client.createSession({
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