@github/copilot-sdk 0.1.33-unstable.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +194 -6
- package/dist/cjs/client.js +1317 -0
- package/dist/cjs/extension.js +45 -0
- package/dist/cjs/generated/rpc.js +123 -0
- package/dist/cjs/generated/session-events.js +16 -0
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/sdkProtocolVersion.js +33 -0
- package/dist/cjs/session.js +616 -0
- package/dist/cjs/telemetry.js +35 -0
- package/dist/cjs/types.js +49 -0
- package/dist/client.d.ts +2 -4
- package/dist/client.js +204 -88
- package/dist/extension.d.ts +6 -7
- package/dist/extension.js +5 -1
- package/dist/generated/rpc.d.ts +540 -1
- package/dist/generated/rpc.js +41 -2
- package/dist/generated/session-events.d.ts +731 -25
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/session.d.ts +35 -5
- package/dist/session.js +74 -9
- package/dist/telemetry.d.ts +14 -0
- package/dist/telemetry.js +11 -0
- package/dist/types.d.ts +153 -6
- package/dist/types.js +15 -0
- package/docs/agent-author.md +0 -2
- package/docs/examples.md +2 -15
- package/docs/extensions.md +0 -2
- package/package.json +19 -7
package/README.md
CHANGED
|
@@ -26,15 +26,16 @@ npm start
|
|
|
26
26
|
## Quick Start
|
|
27
27
|
|
|
28
28
|
```typescript
|
|
29
|
-
import { CopilotClient } from "@github/copilot-sdk";
|
|
29
|
+
import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
30
30
|
|
|
31
31
|
// Create and start client
|
|
32
32
|
const client = new CopilotClient();
|
|
33
33
|
await client.start();
|
|
34
34
|
|
|
35
|
-
// Create a session
|
|
35
|
+
// Create a session (onPermissionRequest is required)
|
|
36
36
|
const session = await client.createSession({
|
|
37
37
|
model: "gpt-5",
|
|
38
|
+
onPermissionRequest: approveAll,
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
// Wait for response using typed event handlers
|
|
@@ -59,7 +60,7 @@ await client.stop();
|
|
|
59
60
|
Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2+/Node.js 18.0+):
|
|
60
61
|
|
|
61
62
|
```typescript
|
|
62
|
-
await using session = await client.createSession({ model: "gpt-5" });
|
|
63
|
+
await using session = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll });
|
|
63
64
|
// session is automatically disconnected when leaving scope
|
|
64
65
|
```
|
|
65
66
|
|
|
@@ -82,9 +83,10 @@ new CopilotClient(options?: CopilotClientOptions)
|
|
|
82
83
|
- `useStdio?: boolean` - Use stdio transport instead of TCP (default: true)
|
|
83
84
|
- `logLevel?: string` - Log level (default: "info")
|
|
84
85
|
- `autoStart?: boolean` - Auto-start server (default: true)
|
|
85
|
-
- `autoRestart?: boolean` - Auto-restart on crash (default: true)
|
|
86
86
|
- `githubToken?: string` - GitHub token for authentication. When provided, takes priority over other auth methods.
|
|
87
87
|
- `useLoggedInUser?: boolean` - Whether to use logged-in user for authentication (default: true, but false when `githubToken` is provided). Cannot be used with `cliUrl`.
|
|
88
|
+
- `telemetry?: TelemetryConfig` - OpenTelemetry configuration for the CLI process. Providing this object enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below.
|
|
89
|
+
- `onGetTraceContext?: TraceContextProvider` - Advanced: callback for linking your application's own OpenTelemetry spans into the same distributed trace as the CLI's spans. Not needed for normal telemetry collection. See [Telemetry](#telemetry) below.
|
|
88
90
|
|
|
89
91
|
#### Methods
|
|
90
92
|
|
|
@@ -113,6 +115,7 @@ Create a new conversation session.
|
|
|
113
115
|
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
|
|
114
116
|
- `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
|
|
115
117
|
- `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
|
|
118
|
+
- `onPermissionRequest: PermissionHandler` - **Required.** Handler called before each tool execution to approve or deny it. Use `approveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section.
|
|
116
119
|
- `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
|
|
117
120
|
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
|
|
118
121
|
|
|
@@ -297,9 +300,10 @@ See `SessionEvent` type in the source for full details.
|
|
|
297
300
|
|
|
298
301
|
## Image Support
|
|
299
302
|
|
|
300
|
-
The SDK supports image attachments via the `attachments` parameter. You can attach images by providing their file path:
|
|
303
|
+
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:
|
|
301
304
|
|
|
302
305
|
```typescript
|
|
306
|
+
// File attachment — runtime reads from disk
|
|
303
307
|
await session.send({
|
|
304
308
|
prompt: "What's in this image?",
|
|
305
309
|
attachments: [
|
|
@@ -309,6 +313,18 @@ await session.send({
|
|
|
309
313
|
},
|
|
310
314
|
],
|
|
311
315
|
});
|
|
316
|
+
|
|
317
|
+
// Blob attachment — provide base64 data directly
|
|
318
|
+
await session.send({
|
|
319
|
+
prompt: "What's in this image?",
|
|
320
|
+
attachments: [
|
|
321
|
+
{
|
|
322
|
+
type: "blob",
|
|
323
|
+
data: base64ImageData,
|
|
324
|
+
mimeType: "image/png",
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
});
|
|
312
328
|
```
|
|
313
329
|
|
|
314
330
|
Supported image formats include JPG, PNG, GIF, and other common image types. The agent's `view` tool can also read images directly from the filesystem, so you can also ask questions like:
|
|
@@ -426,6 +442,19 @@ defineTool("edit_file", {
|
|
|
426
442
|
})
|
|
427
443
|
```
|
|
428
444
|
|
|
445
|
+
#### Skipping Permission Prompts
|
|
446
|
+
|
|
447
|
+
Set `skipPermission: true` on a tool definition to allow it to execute without triggering a permission prompt:
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
defineTool("safe_lookup", {
|
|
451
|
+
description: "A read-only lookup that needs no confirmation",
|
|
452
|
+
parameters: z.object({ id: z.string() }),
|
|
453
|
+
skipPermission: true,
|
|
454
|
+
handler: async ({ id }) => { /* your logic */ },
|
|
455
|
+
})
|
|
456
|
+
```
|
|
457
|
+
|
|
429
458
|
### System Message Customization
|
|
430
459
|
|
|
431
460
|
Control the system prompt using `systemMessage` in session config:
|
|
@@ -444,7 +473,45 @@ const session = await client.createSession({
|
|
|
444
473
|
});
|
|
445
474
|
```
|
|
446
475
|
|
|
447
|
-
The SDK auto-injects environment context, tool instructions, and security guardrails. The default CLI persona is preserved, and your `content` is appended after SDK-managed sections. To change the persona or fully redefine the prompt, use `mode: "replace"`.
|
|
476
|
+
The SDK auto-injects environment context, tool instructions, and security guardrails. The default CLI persona is preserved, and your `content` is appended after SDK-managed sections. To change the persona or fully redefine the prompt, use `mode: "replace"` or `mode: "customize"`.
|
|
477
|
+
|
|
478
|
+
#### Customize Mode
|
|
479
|
+
|
|
480
|
+
Use `mode: "customize"` to selectively override individual sections of the prompt while preserving the rest:
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
import { SYSTEM_PROMPT_SECTIONS } from "@github/copilot-sdk";
|
|
484
|
+
import type { SectionOverride, SystemPromptSection } from "@github/copilot-sdk";
|
|
485
|
+
|
|
486
|
+
const session = await client.createSession({
|
|
487
|
+
model: "gpt-5",
|
|
488
|
+
systemMessage: {
|
|
489
|
+
mode: "customize",
|
|
490
|
+
sections: {
|
|
491
|
+
// Replace the tone/style section
|
|
492
|
+
tone: { action: "replace", content: "Respond in a warm, professional tone. Be thorough in explanations." },
|
|
493
|
+
// Remove coding-specific rules
|
|
494
|
+
code_change_rules: { action: "remove" },
|
|
495
|
+
// Append to existing guidelines
|
|
496
|
+
guidelines: { action: "append", content: "\n* Always cite data sources" },
|
|
497
|
+
},
|
|
498
|
+
// Additional instructions appended after all sections
|
|
499
|
+
content: "Focus on financial analysis and reporting.",
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `last_instructions`. Use the `SYSTEM_PROMPT_SECTIONS` constant for descriptions of each section.
|
|
505
|
+
|
|
506
|
+
Each section override supports four actions:
|
|
507
|
+
- **`replace`** — Replace the section content entirely
|
|
508
|
+
- **`remove`** — Remove the section from the prompt
|
|
509
|
+
- **`append`** — Add content after the existing section
|
|
510
|
+
- **`prepend`** — Add content before the existing section
|
|
511
|
+
|
|
512
|
+
Unknown section IDs are handled gracefully: content from `replace`/`append`/`prepend` overrides is appended to additional instructions, and `remove` overrides are silently ignored.
|
|
513
|
+
|
|
514
|
+
#### Replace Mode
|
|
448
515
|
|
|
449
516
|
For full control (removes all guardrails), use `mode: "replace"`:
|
|
450
517
|
|
|
@@ -589,6 +656,127 @@ const session = await client.createSession({
|
|
|
589
656
|
> - For Azure OpenAI endpoints (`*.openai.azure.com`), you **must** use `type: "azure"`, not `type: "openai"`.
|
|
590
657
|
> - The `baseUrl` should be just the host (e.g., `https://my-resource.openai.azure.com`). Do **not** include `/openai/v1` in the URL - the SDK handles path construction automatically.
|
|
591
658
|
|
|
659
|
+
## Telemetry
|
|
660
|
+
|
|
661
|
+
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:
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
const client = new CopilotClient({
|
|
665
|
+
telemetry: {
|
|
666
|
+
otlpEndpoint: "http://localhost:4318",
|
|
667
|
+
},
|
|
668
|
+
});
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
With just this configuration, the CLI emits spans for every session, message, and tool call to your collector. No additional dependencies or setup required.
|
|
672
|
+
|
|
673
|
+
**TelemetryConfig options:**
|
|
674
|
+
|
|
675
|
+
- `otlpEndpoint?: string` - OTLP HTTP endpoint URL
|
|
676
|
+
- `filePath?: string` - File path for JSON-lines trace output
|
|
677
|
+
- `exporterType?: string` - `"otlp-http"` or `"file"`
|
|
678
|
+
- `sourceName?: string` - Instrumentation scope name
|
|
679
|
+
- `captureContent?: boolean` - Whether to capture message content
|
|
680
|
+
|
|
681
|
+
### Advanced: Trace Context Propagation
|
|
682
|
+
|
|
683
|
+
> **You don't need this for normal telemetry collection.** The `telemetry` config above is sufficient to get full traces from the CLI.
|
|
684
|
+
|
|
685
|
+
`onGetTraceContext` is only needed if your application creates its own OpenTelemetry spans and you want them to appear in the **same distributed trace** as the CLI's spans — for example, to nest a "handle tool call" span inside the CLI's "execute tool" span, or to show the SDK call as a child of your application's request-handling span.
|
|
686
|
+
|
|
687
|
+
If you're already using `@opentelemetry/api` in your app and want this linkage, provide a callback:
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
import { propagation, context } from "@opentelemetry/api";
|
|
691
|
+
|
|
692
|
+
const client = new CopilotClient({
|
|
693
|
+
telemetry: { otlpEndpoint: "http://localhost:4318" },
|
|
694
|
+
onGetTraceContext: () => {
|
|
695
|
+
const carrier: Record<string, string> = {};
|
|
696
|
+
propagation.inject(context.active(), carrier);
|
|
697
|
+
return carrier;
|
|
698
|
+
},
|
|
699
|
+
});
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
Inbound trace context from the CLI is available on the `ToolInvocation` object passed to tool handlers as `traceparent` and `tracestate` fields. See the [OpenTelemetry guide](../docs/observability/opentelemetry.md) for a full wire-up example.
|
|
703
|
+
|
|
704
|
+
## Permission Handling
|
|
705
|
+
|
|
706
|
+
An `onPermissionRequest` handler is **required** whenever you create or resume a session. The handler is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and must return a decision.
|
|
707
|
+
|
|
708
|
+
### Approve All (simplest)
|
|
709
|
+
|
|
710
|
+
Use the built-in `approveAll` helper to allow every tool call without any checks:
|
|
711
|
+
|
|
712
|
+
```typescript
|
|
713
|
+
import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
714
|
+
|
|
715
|
+
const session = await client.createSession({
|
|
716
|
+
model: "gpt-5",
|
|
717
|
+
onPermissionRequest: approveAll,
|
|
718
|
+
});
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
### Custom Permission Handler
|
|
722
|
+
|
|
723
|
+
Provide your own function to inspect each request and apply custom logic:
|
|
724
|
+
|
|
725
|
+
```typescript
|
|
726
|
+
import type { PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk";
|
|
727
|
+
|
|
728
|
+
const session = await client.createSession({
|
|
729
|
+
model: "gpt-5",
|
|
730
|
+
onPermissionRequest: (request: PermissionRequest, invocation): PermissionRequestResult => {
|
|
731
|
+
// request.kind — what type of operation is being requested:
|
|
732
|
+
// "shell" — executing a shell command
|
|
733
|
+
// "write" — writing or editing a file
|
|
734
|
+
// "read" — reading a file
|
|
735
|
+
// "mcp" — calling an MCP tool
|
|
736
|
+
// "custom-tool" — calling one of your registered tools
|
|
737
|
+
// "url" — fetching a URL
|
|
738
|
+
// "memory" — storing or retrieving persistent session memory
|
|
739
|
+
// "hook" — invoking a server-side hook or integration
|
|
740
|
+
// (additional kinds may be added; include a default case in handlers)
|
|
741
|
+
// request.toolCallId — the tool call that triggered this request
|
|
742
|
+
// request.toolName — name of the tool (for custom-tool / mcp)
|
|
743
|
+
// request.fileName — file being written (for write)
|
|
744
|
+
// request.fullCommandText — full shell command (for shell)
|
|
745
|
+
|
|
746
|
+
if (request.kind === "shell") {
|
|
747
|
+
// Deny shell commands
|
|
748
|
+
return { kind: "denied-interactively-by-user" };
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return { kind: "approved" };
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### Permission Result Kinds
|
|
757
|
+
|
|
758
|
+
| Kind | Meaning |
|
|
759
|
+
|------|---------|
|
|
760
|
+
| `"approved"` | Allow the tool to run |
|
|
761
|
+
| `"denied-interactively-by-user"` | User explicitly denied the request |
|
|
762
|
+
| `"denied-no-approval-rule-and-could-not-request-from-user"` | No approval rule matched and user could not be asked |
|
|
763
|
+
| `"denied-by-rules"` | Denied by a policy rule |
|
|
764
|
+
| `"denied-by-content-exclusion-policy"` | Denied due to a content exclusion policy |
|
|
765
|
+
| `"no-result"` | Leave the request unanswered (only valid with protocol v1; rejected by protocol v2 servers) |
|
|
766
|
+
### Resuming Sessions
|
|
767
|
+
|
|
768
|
+
Pass `onPermissionRequest` when resuming a session too — it is required:
|
|
769
|
+
|
|
770
|
+
```typescript
|
|
771
|
+
const session = await client.resumeSession("session-id", {
|
|
772
|
+
onPermissionRequest: approveAll,
|
|
773
|
+
});
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Per-Tool Skip Permission
|
|
777
|
+
|
|
778
|
+
To let a specific custom tool bypass the permission prompt entirely, set `skipPermission: true` on the tool definition. See [Skipping Permission Prompts](#skipping-permission-prompts) under Tools.
|
|
779
|
+
|
|
592
780
|
## User Input Requests
|
|
593
781
|
|
|
594
782
|
Enable the agent to ask questions to the user using the `ask_user` tool by providing an `onUserInputRequest` handler:
|