Skip to content

Commit 85185fd

Browse files
committed
Merge remote-tracking branch 'origin/main' into inline-data-attachments
# Conflicts: # python/copilot/__init__.py
2 parents eea6ea5 + f2d21a0 commit 85185fd

164 files changed

Lines changed: 3932 additions & 747 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/agents/docs-maintenance.agent.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ Every major SDK feature should be documented. Core features include:
122122
- Client initialization and configuration
123123
- Connection modes (stdio vs TCP)
124124
- Authentication options
125-
- Auto-start and auto-restart behavior
126125

127126
**Session Management:**
128127
- Creating sessions
@@ -342,7 +341,7 @@ cat nodejs/src/types.ts | grep -A 10 "export interface ExportSessionOptions"
342341
```
343342

344343
**Must match:**
345-
- `CopilotClient` constructor options: `cliPath`, `cliUrl`, `useStdio`, `port`, `logLevel`, `autoStart`, `autoRestart`, `env`, `githubToken`, `useLoggedInUser`
344+
- `CopilotClient` constructor options: `cliPath`, `cliUrl`, `useStdio`, `port`, `logLevel`, `autoStart`, `env`, `githubToken`, `useLoggedInUser`
346345
- `createSession()` config: `model`, `tools`, `hooks`, `systemMessage`, `mcpServers`, `availableTools`, `excludedTools`, `streaming`, `reasoningEffort`, `provider`, `infiniteSessions`, `customAgents`, `workingDirectory`
347346
- `CopilotSession` methods: `send()`, `sendAndWait()`, `getMessages()`, `disconnect()`, `abort()`, `on()`, `once()`, `off()`
348347
- Hook names: `onPreToolUse`, `onPostToolUse`, `onUserPromptSubmitted`, `onSessionStart`, `onSessionEnd`, `onErrorOccurred`
@@ -360,7 +359,7 @@ cat python/copilot/types.py | grep -A 15 "class SessionHooks"
360359
```
361360

362361
**Must match (snake_case):**
363-
- `CopilotClient` options: `cli_path`, `cli_url`, `use_stdio`, `port`, `log_level`, `auto_start`, `auto_restart`, `env`, `github_token`, `use_logged_in_user`
362+
- `CopilotClient` options: `cli_path`, `cli_url`, `use_stdio`, `port`, `log_level`, `auto_start`, `env`, `github_token`, `use_logged_in_user`
364363
- `create_session()` config keys: `model`, `tools`, `hooks`, `system_message`, `mcp_servers`, `available_tools`, `excluded_tools`, `streaming`, `reasoning_effort`, `provider`, `infinite_sessions`, `custom_agents`, `working_directory`
365364
- `CopilotSession` methods: `send()`, `send_and_wait()`, `get_messages()`, `disconnect()`, `abort()`, `export_session()`
366365
- Hook names: `on_pre_tool_use`, `on_post_tool_use`, `on_user_prompt_submitted`, `on_session_start`, `on_session_end`, `on_error_occurred`
@@ -378,7 +377,7 @@ cat go/types.go | grep -A 15 "type SessionHooks struct"
378377
```
379378

380379
**Must match (PascalCase for exported):**
381-
- `ClientOptions` fields: `CLIPath`, `CLIUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `AutoRestart`, `Env`, `GithubToken`, `UseLoggedInUser`
380+
- `ClientOptions` fields: `CLIPath`, `CLIUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Env`, `GithubToken`, `UseLoggedInUser`
382381
- `SessionConfig` fields: `Model`, `Tools`, `Hooks`, `SystemMessage`, `MCPServers`, `AvailableTools`, `ExcludedTools`, `Streaming`, `ReasoningEffort`, `Provider`, `InfiniteSessions`, `CustomAgents`, `WorkingDirectory`
383382
- `Session` methods: `Send()`, `SendAndWait()`, `GetMessages()`, `Disconnect()`, `Abort()`, `ExportSession()`
384383
- Hook fields: `OnPreToolUse`, `OnPostToolUse`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`
@@ -396,7 +395,7 @@ cat dotnet/src/Types.cs | grep -A 15 "public class SessionHooks"
396395
```
397396

398397
**Must match (PascalCase):**
399-
- `CopilotClientOptions` properties: `CliPath`, `CliUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `AutoRestart`, `Environment`, `GithubToken`, `UseLoggedInUser`
398+
- `CopilotClientOptions` properties: `CliPath`, `CliUrl`, `UseStdio`, `Port`, `LogLevel`, `AutoStart`, `Environment`, `GithubToken`, `UseLoggedInUser`
400399
- `SessionConfig` properties: `Model`, `Tools`, `Hooks`, `SystemMessage`, `McpServers`, `AvailableTools`, `ExcludedTools`, `Streaming`, `ReasoningEffort`, `Provider`, `InfiniteSessions`, `CustomAgents`, `WorkingDirectory`
401400
- `CopilotSession` methods: `SendAsync()`, `SendAndWaitAsync()`, `GetMessagesAsync()`, `DisposeAsync()`, `AbortAsync()`, `ExportSessionAsync()`
402401
- Hook properties: `OnPreToolUse`, `OnPostToolUse`, `OnUserPromptSubmitted`, `OnSessionStart`, `OnSessionEnd`, `OnErrorOccurred`

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- Python: `cd python && uv pip install -e ".[dev]"``uv run pytest` (E2E tests use the test harness)
2626
- Go: `cd go && go test ./...`
2727
- .NET: `cd dotnet && dotnet test test/GitHub.Copilot.SDK.Test.csproj`
28+
- **.NET testing note:** Never add `InternalsVisibleTo` to any project file when writing tests. Tests must only access public APIs.
2829

2930
## Testing & E2E tips ⚙️
3031

docs/getting-started.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,119 @@ await using var session = await client.CreateSessionAsync(new()
13951395

13961396
---
13971397

1398+
## Telemetry & Observability
1399+
1400+
The Copilot SDK supports [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. Provide a `telemetry` configuration to the client to enable trace export from the CLI process and automatic [W3C Trace Context](https://www.w3.org/TR/trace-context/) propagation between the SDK and CLI.
1401+
1402+
### Enabling Telemetry
1403+
1404+
Pass a `telemetry` (or `Telemetry`) config when creating the client. This is the opt-in — no separate "enabled" flag is needed.
1405+
1406+
<details open>
1407+
<summary><strong>Node.js / TypeScript</strong></summary>
1408+
1409+
<!-- docs-validate: skip -->
1410+
```typescript
1411+
import { CopilotClient } from "@github/copilot-sdk";
1412+
1413+
const client = new CopilotClient({
1414+
telemetry: {
1415+
otlpEndpoint: "http://localhost:4318",
1416+
},
1417+
});
1418+
```
1419+
1420+
Optional peer dependency: `@opentelemetry/api`
1421+
1422+
</details>
1423+
1424+
<details>
1425+
<summary><strong>Python</strong></summary>
1426+
1427+
<!-- docs-validate: skip -->
1428+
```python
1429+
from copilot import CopilotClient, SubprocessConfig
1430+
1431+
client = CopilotClient(SubprocessConfig(
1432+
telemetry={
1433+
"otlp_endpoint": "http://localhost:4318",
1434+
},
1435+
))
1436+
```
1437+
1438+
Install with telemetry extras: `pip install copilot-sdk[telemetry]` (provides `opentelemetry-api`)
1439+
1440+
</details>
1441+
1442+
<details>
1443+
<summary><strong>Go</strong></summary>
1444+
1445+
<!-- docs-validate: skip -->
1446+
```go
1447+
client, err := copilot.NewClient(copilot.ClientOptions{
1448+
Telemetry: &copilot.TelemetryConfig{
1449+
OTLPEndpoint: "http://localhost:4318",
1450+
},
1451+
})
1452+
```
1453+
1454+
Dependency: `go.opentelemetry.io/otel`
1455+
1456+
</details>
1457+
1458+
<details>
1459+
<summary><strong>.NET</strong></summary>
1460+
1461+
<!-- docs-validate: skip -->
1462+
```csharp
1463+
var client = new CopilotClient(new CopilotClientOptions
1464+
{
1465+
Telemetry = new TelemetryConfig
1466+
{
1467+
OtlpEndpoint = "http://localhost:4318",
1468+
},
1469+
});
1470+
```
1471+
1472+
No extra dependencies — uses built-in `System.Diagnostics.Activity`.
1473+
1474+
</details>
1475+
1476+
### TelemetryConfig Options
1477+
1478+
| Option | Node.js | Python | Go | .NET | Description |
1479+
|---|---|---|---|---|---|
1480+
| OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | OTLP HTTP endpoint URL |
1481+
| File path | `filePath` | `file_path` | `FilePath` | `FilePath` | File path for JSON-lines trace output |
1482+
| Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `"otlp-http"` or `"file"` |
1483+
| Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | Instrumentation scope name |
1484+
| Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | Whether to capture message content |
1485+
1486+
### File Export
1487+
1488+
To write traces to a local file instead of an OTLP endpoint:
1489+
1490+
<!-- docs-validate: skip -->
1491+
```typescript
1492+
const client = new CopilotClient({
1493+
telemetry: {
1494+
filePath: "./traces.jsonl",
1495+
exporterType: "file",
1496+
},
1497+
});
1498+
```
1499+
1500+
### Trace Context Propagation
1501+
1502+
Trace context is propagated automatically — no manual instrumentation is needed:
1503+
1504+
- **SDK → CLI**: `traceparent` and `tracestate` headers from the current span/activity are included in `session.create`, `session.resume`, and `session.send` RPC calls.
1505+
- **CLI → SDK**: When the CLI invokes tool handlers, the trace context from the CLI's span is propagated so your tool code runs under the correct parent span.
1506+
1507+
📖 **[OpenTelemetry Instrumentation Guide →](./observability/opentelemetry.md)** — detailed GenAI semantic conventions, event-to-attribute mapping, and complete examples.
1508+
1509+
---
1510+
13981511
## Learn More
13991512

14001513
- [Authentication Guide](./auth/index.md) - GitHub OAuth, environment variables, and BYOK
@@ -1406,6 +1519,7 @@ await using var session = await client.CreateSessionAsync(new()
14061519
- [Using MCP Servers](./features/mcp.md) - Integrate external tools via Model Context Protocol
14071520
- [GitHub MCP Server Documentation](https://github.com/github/github-mcp-server)
14081521
- [MCP Servers Directory](https://github.com/modelcontextprotocol/servers) - Explore more MCP servers
1522+
- [OpenTelemetry Instrumentation](./observability/opentelemetry.md) - Add tracing to your SDK usage
14091523

14101524
---
14111525

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Detailed API reference for each session hook.
6767

6868
### [Observability](./observability/opentelemetry.md)
6969

70-
- [OpenTelemetry Instrumentation](./observability/opentelemetry.md)add tracing to your SDK usage
70+
- [OpenTelemetry Instrumentation](./observability/opentelemetry.md)built-in TelemetryConfig, trace context propagation, and application-level tracing
7171

7272
### [Integrations](./integrations/microsoft-agent-framework.md)
7373

docs/observability/opentelemetry.md

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,158 @@
11
# OpenTelemetry Instrumentation for Copilot SDK
22

3-
This guide shows how to add OpenTelemetry tracing to your Copilot SDK applications using GenAI semantic conventions.
3+
This guide shows how to add OpenTelemetry tracing to your Copilot SDK applications.
4+
5+
## Built-in Telemetry Support
6+
7+
The SDK has built-in support for configuring OpenTelemetry on the CLI process and propagating W3C Trace Context between the SDK and CLI. Provide a `TelemetryConfig` when creating the client to opt in:
8+
9+
<details open>
10+
<summary><strong>Node.js / TypeScript</strong></summary>
11+
12+
<!-- docs-validate: skip -->
13+
```typescript
14+
import { CopilotClient } from "@github/copilot-sdk";
15+
16+
const client = new CopilotClient({
17+
telemetry: {
18+
otlpEndpoint: "http://localhost:4318",
19+
},
20+
});
21+
```
22+
23+
</details>
24+
25+
<details>
26+
<summary><strong>Python</strong></summary>
27+
28+
<!-- docs-validate: skip -->
29+
```python
30+
from copilot import CopilotClient, SubprocessConfig
31+
32+
client = CopilotClient(SubprocessConfig(
33+
telemetry={
34+
"otlp_endpoint": "http://localhost:4318",
35+
},
36+
))
37+
```
38+
39+
</details>
40+
41+
<details>
42+
<summary><strong>Go</strong></summary>
43+
44+
<!-- docs-validate: skip -->
45+
```go
46+
client, err := copilot.NewClient(copilot.ClientOptions{
47+
Telemetry: &copilot.TelemetryConfig{
48+
OTLPEndpoint: "http://localhost:4318",
49+
},
50+
})
51+
```
52+
53+
</details>
54+
55+
<details>
56+
<summary><strong>.NET</strong></summary>
57+
58+
<!-- docs-validate: skip -->
59+
```csharp
60+
var client = new CopilotClient(new CopilotClientOptions
61+
{
62+
Telemetry = new TelemetryConfig
63+
{
64+
OtlpEndpoint = "http://localhost:4318",
65+
},
66+
});
67+
```
68+
69+
</details>
70+
71+
### TelemetryConfig Options
72+
73+
| Option | Node.js | Python | Go | .NET | Description |
74+
|---|---|---|---|---|---|
75+
| OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | OTLP HTTP endpoint URL |
76+
| File path | `filePath` | `file_path` | `FilePath` | `FilePath` | File path for JSON-lines trace output |
77+
| Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `"otlp-http"` or `"file"` |
78+
| Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | Instrumentation scope name |
79+
| Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | Whether to capture message content |
80+
81+
### Trace Context Propagation
82+
83+
> **Most users don't need this.** The `TelemetryConfig` above is all you need to collect traces from the CLI. The trace context propagation described in this section is an **advanced feature** for applications that create their own OpenTelemetry spans and want them to appear in the **same distributed trace** as the CLI's spans.
84+
85+
The SDK can propagate W3C Trace Context (`traceparent`/`tracestate`) on JSON-RPC payloads so that your application's spans and the CLI's spans are linked in one distributed trace. This is useful when, for example, you want to see a "handle tool call" span in your app nested inside the CLI's "execute tool" span, or show the SDK call as a child of your request-handling span.
86+
87+
#### SDK → CLI (outbound)
88+
89+
For **Node.js**, provide an `onGetTraceContext` callback on the client options. This is only needed if your application already uses `@opentelemetry/api` and you want to link your spans with the CLI's spans. The SDK calls this callback before `session.create`, `session.resume`, and `session.send` RPCs:
90+
91+
<!-- docs-validate: skip -->
92+
```typescript
93+
import { CopilotClient } from "@github/copilot-sdk";
94+
import { propagation, context } from "@opentelemetry/api";
95+
96+
const client = new CopilotClient({
97+
telemetry: { otlpEndpoint: "http://localhost:4318" },
98+
onGetTraceContext: () => {
99+
const carrier: Record<string, string> = {};
100+
propagation.inject(context.active(), carrier);
101+
return carrier; // { traceparent: "00-...", tracestate: "..." }
102+
},
103+
});
104+
```
105+
106+
For **Python**, **Go**, and **.NET**, trace context injection is automatic when the respective OpenTelemetry/Activity API is configured — no callback is needed.
107+
108+
#### CLI → SDK (inbound)
109+
110+
When the CLI invokes a tool handler, the `traceparent` and `tracestate` from the CLI's span are available in all languages:
111+
112+
- **Go**: The `ToolInvocation.TraceContext` field is a `context.Context` with the trace already restored — use it directly as the parent for your spans.
113+
- **Python**: Trace context is automatically restored around the handler via `trace_context()` — child spans are parented to the CLI's span automatically.
114+
- **.NET**: Trace context is automatically restored via `RestoreTraceContext()` — child `Activity` instances are parented to the CLI's span automatically.
115+
- **Node.js**: Since the SDK has no OpenTelemetry dependency, `traceparent` and `tracestate` are passed as raw strings on the `ToolInvocation` object. Restore the context manually if needed:
116+
117+
<!-- docs-validate: skip -->
118+
```typescript
119+
import { propagation, context, trace } from "@opentelemetry/api";
120+
121+
session.registerTool(myTool, async (args, invocation) => {
122+
// Restore the CLI's trace context as the active context
123+
const carrier = {
124+
traceparent: invocation.traceparent,
125+
tracestate: invocation.tracestate,
126+
};
127+
const parentCtx = propagation.extract(context.active(), carrier);
128+
129+
// Create a child span under the CLI's span
130+
const tracer = trace.getTracer("my-app");
131+
return context.with(parentCtx, () =>
132+
tracer.startActiveSpan("my-tool", async (span) => {
133+
try {
134+
const result = await doWork(args);
135+
return result;
136+
} finally {
137+
span.end();
138+
}
139+
})
140+
);
141+
});
142+
```
143+
144+
### Per-Language Dependencies
145+
146+
| Language | Dependency | Notes |
147+
|---|---|---|
148+
| Node.js || No dependency; provide `onGetTraceContext` callback for outbound propagation |
149+
| Python | `opentelemetry-api` | Install with `pip install copilot-sdk[telemetry]` |
150+
| Go | `go.opentelemetry.io/otel` | Required dependency |
151+
| .NET || Uses built-in `System.Diagnostics.Activity` |
152+
153+
## Application-Level Instrumentation
154+
155+
The rest of this guide shows how to add your own OpenTelemetry spans around SDK operations using GenAI semantic conventions. This is complementary to the built-in `TelemetryConfig` above — you can use both together.
4156

5157
## Overview
6158

docs/setup/local-cli.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ const client = new CopilotClient({
171171

172172
// Set working directory
173173
cwd: "/path/to/project",
174-
175-
// Auto-restart CLI if it crashes (default: true)
176-
autoRestart: true,
177174
});
178175
```
179176

docs/troubleshooting/debugging.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,7 @@ var client = new CopilotClient(new CopilotClientOptions
297297
copilot --server --stdio
298298
```
299299

300-
2. Enable auto-restart (enabled by default):
301-
```typescript
302-
const client = new CopilotClient({
303-
autoRestart: true,
304-
});
305-
```
306-
307-
3. Check for port conflicts if using TCP mode:
300+
2. Check for port conflicts if using TCP mode:
308301
```typescript
309302
const client = new CopilotClient({
310303
useStdio: false,

0 commit comments

Comments
 (0)