Skip to content

Commit d00eabd

Browse files
docs-botgithub-actions[bot]sunbryeCopilot
authored
Sync Copilot SDK docs (auto-generated) (#63408)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: sunbrye <sunbrye@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 860ffa15-aef4-4655-a9cb-f4e04cc36886
1 parent 31140e8 commit d00eabd

22 files changed

Lines changed: 713 additions & 18 deletions
5 Bytes
Loading
3 Bytes
Loading
22.8 KB
Loading

‎content/copilot/how-tos/copilot-sdk/auth/authenticate.md‎

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,133 @@ const client = new CopilotClient({
215215

216216
For more information, see [AUTOTITLE](/copilot/how-tos/copilot-sdk/setup/github-oauth).
217217

218+
## Rotating session-scoped GitHub tokens
219+
220+
For multi-user services and integrations, set a token provider on each session instead of storing one long-lived token. The runtime calls the provider for the effective GitHub host and identifies the request as `initial` or `refresh`. The session ID is absent only when a cloud session has not received its ID yet.
221+
222+
Return a tagged token result or an explicit cancellation. Every token result must include `expiresIn`: the positive number of seconds remaining when the callback completes. Production GitHub tokens typically last eight hours, so `8 * 60 * 60` is a common value. Do not set both the static per-session token and the provider.
223+
224+
{% codetabs %}
225+
{% codetab typescript %}
226+
227+
<!-- docs-validate: skip -->
228+
229+
```typescript
230+
const session = await client.createSession({
231+
gitHubTokenProvider: async ({ host, sessionId, reason }) => {
232+
const token = await acquireGitHubToken({ host, sessionId, reason });
233+
return {
234+
kind: "token",
235+
accessToken: token.value,
236+
expiresIn: token.secondsRemaining,
237+
};
238+
},
239+
});
240+
```
241+
242+
{% endcodetab %}
243+
{% codetab python %}
244+
245+
<!-- docs-validate: skip -->
246+
247+
```python
248+
async def provide_github_token(args):
249+
token = await acquire_github_token(
250+
host=args["host"],
251+
session_id=args["session_id"],
252+
reason=args["reason"],
253+
)
254+
return {
255+
"kind": "token",
256+
"accessToken": token.value,
257+
"expiresIn": token.seconds_remaining,
258+
}
259+
260+
261+
session = await client.create_session(github_token_provider=provide_github_token)
262+
```
263+
264+
{% endcodetab %}
265+
{% codetab go %}
266+
267+
<!-- docs-validate: skip -->
268+
269+
```golang
270+
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
271+
GitHubTokenProvider: func(args copilot.GitHubTokenProviderArgs) (*copilot.GitHubTokenProviderResult, error) {
272+
token, secondsRemaining, err := acquireGitHubToken(args.Host, args.SessionID, args.Reason)
273+
if err != nil {
274+
return nil, err
275+
}
276+
return copilot.GitHubTokenResult(&copilot.GitHubToken{
277+
AccessToken: token,
278+
ExpiresIn: secondsRemaining,
279+
}), nil
280+
},
281+
})
282+
```
283+
284+
{% endcodetab %}
285+
{% codetab dotnet %}
286+
287+
<!-- docs-validate: skip -->
288+
289+
```csharp
290+
await using var session = await client.CreateSessionAsync(new SessionConfig
291+
{
292+
GitHubTokenProvider = async args =>
293+
{
294+
var token = await AcquireGitHubTokenAsync(args.Host, args.SessionId, args.Reason);
295+
return GitHubTokenProviderResult.FromToken(new GitHubToken
296+
{
297+
AccessToken = token.Value,
298+
ExpiresIn = token.SecondsRemaining,
299+
});
300+
},
301+
});
302+
```
303+
304+
{% endcodetab %}
305+
{% codetab java %}
306+
307+
<!-- docs-validate: skip -->
308+
309+
```java
310+
var session = client.createSession(new SessionConfig()
311+
.setGitHubTokenProvider(args ->
312+
acquireGitHubToken(args.host(), args.sessionId(), args.reason())
313+
.thenApply(token -> GitHubTokenProviderResult.token(
314+
token.value(), token.secondsRemaining())))
315+
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
316+
).get();
317+
```
318+
319+
{% endcodetab %}
320+
{% codetab rust %}
321+
322+
<!-- docs-validate: skip -->
323+
324+
```rust
325+
let provider = Arc::new(|args: GitHubTokenProviderArgs| async move {
326+
let token = acquire_github_token(&args.host, args.session_id.as_ref(), args.reason).await?;
327+
Ok(GitHubTokenProviderResult::Token(GitHubToken::new(
328+
token.value,
329+
token.seconds_remaining,
330+
)))
331+
});
332+
333+
let session = client
334+
.create_session(SessionConfig::default().with_github_token_provider(provider))
335+
.await?;
336+
```
337+
338+
{% endcodetab %}
339+
{% endcodetabs %}
340+
341+
The runtime performs the `initial` acquisition as part of session creation or resume. A cancelled acquisition, provider error, invalid response, or token without a stable account identity rejects the create or resume operation. The runtime does not fall back to ambient authentication.
342+
343+
After the session is established, the runtime performs async preflight before each credential-consuming operation. It requests a `refresh` when the current token has one hour or less remaining. Idle sessions are not refreshed until their next credential-consuming operation. The runtime does not use background timers, rejection-driven replay, 401/403 challenge propagation, or upscope for this callback.
344+
218345
## Environment variables
219346

220347
For automation, CI/CD pipelines, and server-to-server scenarios, you can authenticate using environment variables.

‎content/copilot/how-tos/copilot-sdk/auth/byok.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ Anthropic models always use the Anthropic Messages API regardless of this settin
234234

235235
**Azure (`type: "azure"`)**
236236
* Use for native Azure OpenAI endpoints
237-
* `baseUrl` should be just the host (e.g., `https://my-resource.openai.azure.com`)
238-
* Do NOT include `/openai/v1` in the URL—the SDK handles path construction
237+
* `baseUrl` / `base_url` accepts a resource host or a full project URL, such as `https://<host>/api/projects/hosted-agents-ncus`, with or without a trailing slash.
238+
* The runtime preserves the project prefix when constructing Azure API paths. For `wireApi: "responses"` with `azure.apiVersion` omitted, the project URL above produces `https://<host>/api/projects/hosted-agents-ncus/openai/v1/responses`. Project URLs require an updated Copilot CLI runtime.
239239

240240
**Anthropic (`type: "anthropic"`)**
241241
* For direct Anthropic API access
@@ -260,7 +260,7 @@ Use `type: "azure"` for endpoints at `*.openai.azure.com`:
260260
```typescript
261261
provider: {
262262
type: "azure",
263-
baseUrl: "https://my-resource.openai.azure.com", // Just the host
263+
baseUrl: "https://my-resource.openai.azure.com", // Resource host or full project URL
264264
apiKey: process.env.AZURE_OPENAI_KEY,
265265
azure: {
266266
apiVersion: "2024-10-21",
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
title: Client info
3+
shortTitle: Client info
4+
intro: >-
5+
Client info identifies the application using the Copilot SDK and, when
6+
applicable, a specific integration within it. An integration is an
7+
identifiable sub-part of the application through which the SDK is used, such
8+
as an extension or plugin. Set the optional `clientInfo` client option to
9+
attribute runtime telemetry for that connection to your application instead of
10+
the runtime's own build.
11+
versions:
12+
fpt: '*'
13+
ghec: '*'
14+
contentType: how-tos
15+
---
16+
17+
<!-- markdownlint-disable GHD046 GHD005 -->
18+
<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->
19+
20+
## When to set client info
21+
22+
Set client info when your SDK application represents a distinct product, service, or integration whose runtime activity should be attributed consistently.
23+
24+
Leave client info unset for scripts, one-off tools, and jobs that do not represent a distinct application. The runtime then keeps its default attribution.
25+
26+
Client info has four optional string fields. Set the fields you know and omit the rest. The SDK includes client info in the `server.connect` handshake only when at least one field has a non-empty value.
27+
28+
| Field | Example | Meaning |
29+
|---|---|---|
30+
| `applicationName` | `"vscode"` | Name of the application using the SDK |
31+
| `applicationVersion` | `"1.124.2"` | Version of the application using the SDK |
32+
| `integrationName` | `"copilot-chat"` | Name of the extension, plugin, or other application sub-part using the SDK |
33+
| `integrationVersion` | `"0.54.0"` | Version of that extension, plugin, or application sub-part |
34+
35+
For a standalone application without a distinct integration, set only the application fields. For example, a developer portal could set `applicationName` to `"acme-developer-portal"` and `applicationVersion` to `"2.4.0"`, leaving both integration fields unset.
36+
37+
The SDK sends client info once when it establishes the connection. The identity applies for the lifetime of that connection.
38+
39+
## Configure client info
40+
41+
Pass client info when you create the client:
42+
43+
{% codetabs %}
44+
{% codetab typescript %}
45+
46+
```typescript
47+
import { CopilotClient } from "@github/copilot-sdk";
48+
49+
const client = new CopilotClient({
50+
clientInfo: {
51+
applicationName: "vscode",
52+
applicationVersion: "1.124.2",
53+
integrationName: "copilot-chat",
54+
integrationVersion: "0.54.0",
55+
},
56+
});
57+
58+
await client.start();
59+
```
60+
61+
{% endcodetab %}
62+
{% codetab python %}
63+
64+
<!-- docs-validate: wrap-async -->
65+
66+
```python
67+
from copilot import CopilotClient
68+
69+
client = CopilotClient(
70+
client_info={
71+
"application_name": "vscode",
72+
"application_version": "1.124.2",
73+
"integration_name": "copilot-chat",
74+
"integration_version": "0.54.0",
75+
},
76+
)
77+
await client.start()
78+
```
79+
80+
{% endcodetab %}
81+
{% codetab go %}
82+
83+
```golang
84+
client := copilot.NewClient(&copilot.ClientOptions{
85+
ClientInfo: &copilot.ClientInfo{
86+
ApplicationName: "vscode",
87+
ApplicationVersion: "1.124.2",
88+
IntegrationName: "copilot-chat",
89+
IntegrationVersion: "0.54.0",
90+
},
91+
})
92+
if err := client.Start(ctx); err != nil {
93+
return err
94+
}
95+
```
96+
97+
{% endcodetab %}
98+
{% codetab dotnet %}
99+
100+
```csharp
101+
using GitHub.Copilot;
102+
103+
await using var client = new CopilotClient(new CopilotClientOptions
104+
{
105+
ClientInfo = new CopilotClientInfo
106+
{
107+
ApplicationName = "vscode",
108+
ApplicationVersion = "1.124.2",
109+
IntegrationName = "copilot-chat",
110+
IntegrationVersion = "0.54.0",
111+
},
112+
});
113+
114+
await client.StartAsync();
115+
```
116+
117+
{% endcodetab %}
118+
{% codetab java %}
119+
120+
```java
121+
var options = new CopilotClientOptions()
122+
.setClientInfo(new ClientInfo()
123+
.setApplicationName("vscode")
124+
.setApplicationVersion("1.124.2")
125+
.setIntegrationName("copilot-chat")
126+
.setIntegrationVersion("0.54.0"));
127+
128+
var client = new CopilotClient(options);
129+
client.start().get();
130+
```
131+
132+
{% endcodetab %}
133+
{% codetab rust %}
134+
135+
```rust
136+
use github_copilot_sdk::{Client, ClientInfo, ClientOptions};
137+
138+
let client = Client::start(
139+
ClientOptions::new().with_client_info(
140+
ClientInfo::new()
141+
.with_application_name("vscode")
142+
.with_application_version("1.124.2")
143+
.with_integration_name("copilot-chat")
144+
.with_integration_version("0.54.0"),
145+
),
146+
)
147+
.await?;
148+
```
149+
150+
{% endcodetab %}
151+
{% endcodetabs %}
152+
153+
## Notes
154+
155+
* Client info is advisory. The runtime can ignore values that do not match the expected format, such as an invalid version string.
156+
* Setting client info changes how the runtime attributes its telemetry. It does not change what the runtime records.
157+
* If every field is unset or empty, the SDK omits client info from the handshake and the runtime keeps its default attribution.

‎content/copilot/how-tos/copilot-sdk/features/hooks.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ A hook is a callback you register once when creating a session. The SDK invokes
2626

2727
| Hook | When it fires | What you can do |
2828
| ------------------------------------------------------------------- | ----------------------------------- | ------------------------------------------ |
29-
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-start) | Session begins (new or resumed) | Inject context, load preferences |
29+
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-start-hook) | Session begins (new or resumed) | Inject context, load preferences |
3030
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/user-prompt-submitted) | User sends a message | Rewrite prompts, add context, filter input |
3131
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/user-prompt-transformed) | Runtime builds the model prompt | Inspect or replace model-facing content |
3232
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/pre-tool-use) | Before a tool executes | Allow / deny / modify the call |
3333
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/post-tool-use) | After a tool returns (success only) | Transform results, redact secrets, audit |
3434
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/post-tool-use#failure-variant) | After a tool returns a failure | Inject retry guidance, log failures |
35-
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-end) | Session ends | Clean up, record metrics |
35+
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/session-lifecycle#session-end-hook) | Session ends | Clean up, record metrics |
3636
| [AUTOTITLE](/copilot/how-tos/copilot-sdk/hooks/error-handling) | An error is raised | Custom logging, retry logic, alerts |
3737

3838
All hooks are **optional**—register only the ones you need. Returning `null` (or the language equivalent) from any hook tells the SDK to continue with default behavior.

‎content/copilot/how-tos/copilot-sdk/features/index.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ contentType: how-tos
1313
children:
1414
- /agent-loop
1515
- /citations
16+
- /client-info
1617
- /cloud-sessions
1718
- /context-management
1819
- /custom-agents

‎content/copilot/how-tos/copilot-sdk/features/plugin-directories.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,34 @@ let client = Client::start(
160160

161161
> The example above uses an stdio runtime connection — the default when the SDK bundles the CLI. If you connect to an external runtime via a URL (`forUri` / `ForUri`), pass `--plugin-dir` to the long-running CLI server when you start it; the SDK does not forward `--plugin-dir` to runtimes it didn't spawn.
162162
163+
## Per-session plugin directories
164+
165+
`--plugin-dir` is a launch argument, so it fixes one plugin set for the CLI process and every session created against it. When sessions need different plugin sets, or when the SDK is connected to a runtime it did not spawn, pass the directories on the session config instead. They travel in the `session.create` and `session.resume` payloads over JSON-RPC rather than as process arguments, so they reach an external runtime the same way the startup option does.
166+
167+
```typescript
168+
import { CopilotClient } from "@github/copilot-sdk";
169+
170+
const client = new CopilotClient();
171+
await client.start();
172+
173+
const session = await client.createSession({
174+
pluginDirectories: ["./plugins/code-reviewer"],
175+
});
176+
```
177+
178+
Relative paths resolve against `workingDirectory`, or the runtime working directory when that is unset, so absolute paths are recommended. Entries that do not resolve are logged and skipped rather than failing session creation. The option is an explicit opt-in, which means plugin agents and rules load even when `enableConfigDiscovery` is false. Assets loaded this way sit between project sources and personal or home sources in the session-wide precedence order.
179+
180+
The equivalent option in each SDK is:
181+
182+
| SDK | Session option |
183+
|---|---|
184+
| Node.js / TypeScript | `pluginDirectories: string[]` |
185+
| Python | `plugin_directories=[...]` |
186+
| Go | `PluginDirectories: []string{...}` |
187+
| .NET | `PluginDirectories = [...]` |
188+
| Java | `.setPluginDirectories(List.of(...))` |
189+
| Rust | `.with_plugin_directories([...])` |
190+
163191
## Trusted host-bundled plugin directories
164192

165193
Applications that ship their own trusted plugins can register them as a client startup option. The SDK sends the complete ordered set after connecting and verifying the protocol, before `start` returns or any session can be created. Paths must be absolute; leaving the option unset or empty makes no RPC call.

0 commit comments

Comments
 (0)