@github/copilot-sdk 0.1.15 → 0.1.16
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 +361 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,361 @@
|
|
|
1
|
-
|
|
1
|
+
# Copilot SDK for Node.js/TypeScript
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC.
|
|
4
|
+
|
|
5
|
+
> **Note:** This SDK is in technical preview and may change in breaking ways.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @github/copilot-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { CopilotClient } from "@github/copilot-sdk";
|
|
17
|
+
|
|
18
|
+
// Create and start client
|
|
19
|
+
const client = new CopilotClient();
|
|
20
|
+
await client.start();
|
|
21
|
+
|
|
22
|
+
// Create a session
|
|
23
|
+
const session = await client.createSession({
|
|
24
|
+
model: "gpt-5",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Wait for response using session.idle event
|
|
28
|
+
const done = new Promise<void>((resolve) => {
|
|
29
|
+
session.on((event) => {
|
|
30
|
+
if (event.type === "assistant.message") {
|
|
31
|
+
console.log(event.data.content);
|
|
32
|
+
} else if (event.type === "session.idle") {
|
|
33
|
+
resolve();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Send a message and wait for completion
|
|
39
|
+
await session.send({ prompt: "What is 2+2?" });
|
|
40
|
+
await done;
|
|
41
|
+
|
|
42
|
+
// Clean up
|
|
43
|
+
await session.destroy();
|
|
44
|
+
await client.stop();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API Reference
|
|
48
|
+
|
|
49
|
+
### CopilotClient
|
|
50
|
+
|
|
51
|
+
#### Constructor
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
new CopilotClient(options?: CopilotClientOptions)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Options:**
|
|
58
|
+
|
|
59
|
+
- `cliPath?: string` - Path to CLI executable (default: "copilot" from PATH)
|
|
60
|
+
- `cliArgs?: string[]` - Extra arguments prepended before SDK-managed flags (e.g. `["./dist-cli/index.js"]` when using `node`)
|
|
61
|
+
- `cliUrl?: string` - URL of existing CLI server to connect to (e.g., `"localhost:8080"`, `"http://127.0.0.1:9000"`, or just `"8080"`). When provided, the client will not spawn a CLI process.
|
|
62
|
+
- `port?: number` - Server port (default: 0 for random)
|
|
63
|
+
- `useStdio?: boolean` - Use stdio transport instead of TCP (default: true)
|
|
64
|
+
- `logLevel?: string` - Log level (default: "info")
|
|
65
|
+
- `autoStart?: boolean` - Auto-start server (default: true)
|
|
66
|
+
- `autoRestart?: boolean` - Auto-restart on crash (default: true)
|
|
67
|
+
|
|
68
|
+
#### Methods
|
|
69
|
+
|
|
70
|
+
##### `start(): Promise<void>`
|
|
71
|
+
|
|
72
|
+
Start the CLI server and establish connection.
|
|
73
|
+
|
|
74
|
+
##### `stop(): Promise<Error[]>`
|
|
75
|
+
|
|
76
|
+
Stop the server and close all sessions. Returns a list of any errors encountered during cleanup.
|
|
77
|
+
|
|
78
|
+
##### `forceStop(): Promise<void>`
|
|
79
|
+
|
|
80
|
+
Force stop the CLI server without graceful cleanup. Use when `stop()` takes too long.
|
|
81
|
+
|
|
82
|
+
##### `createSession(config?: SessionConfig): Promise<CopilotSession>`
|
|
83
|
+
|
|
84
|
+
Create a new conversation session.
|
|
85
|
+
|
|
86
|
+
**Config:**
|
|
87
|
+
|
|
88
|
+
- `sessionId?: string` - Custom session ID
|
|
89
|
+
- `model?: string` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.)
|
|
90
|
+
- `tools?: Tool[]` - Custom tools exposed to the CLI
|
|
91
|
+
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
|
|
92
|
+
|
|
93
|
+
##### `resumeSession(sessionId: string, config?: ResumeSessionConfig): Promise<CopilotSession>`
|
|
94
|
+
|
|
95
|
+
Resume an existing session.
|
|
96
|
+
|
|
97
|
+
##### `ping(message?: string): Promise<{ message: string; timestamp: number }>`
|
|
98
|
+
|
|
99
|
+
Ping the server to check connectivity.
|
|
100
|
+
|
|
101
|
+
##### `getState(): ConnectionState`
|
|
102
|
+
|
|
103
|
+
Get current connection state.
|
|
104
|
+
|
|
105
|
+
##### `listSessions(): Promise<SessionMetadata[]>`
|
|
106
|
+
|
|
107
|
+
List all available sessions.
|
|
108
|
+
|
|
109
|
+
##### `deleteSession(sessionId: string): Promise<void>`
|
|
110
|
+
|
|
111
|
+
Delete a session and its data from disk.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### CopilotSession
|
|
116
|
+
|
|
117
|
+
Represents a single conversation session.
|
|
118
|
+
|
|
119
|
+
#### Methods
|
|
120
|
+
|
|
121
|
+
##### `send(options: MessageOptions): Promise<string>`
|
|
122
|
+
|
|
123
|
+
Send a message to the session. Returns immediately after the message is queued; use event handlers or `sendAndWait()` to wait for completion.
|
|
124
|
+
|
|
125
|
+
**Options:**
|
|
126
|
+
|
|
127
|
+
- `prompt: string` - The message/prompt to send
|
|
128
|
+
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
129
|
+
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
130
|
+
|
|
131
|
+
Returns the message ID.
|
|
132
|
+
|
|
133
|
+
##### `sendAndWait(options: MessageOptions, timeout?: number): Promise<AssistantMessageEvent | undefined>`
|
|
134
|
+
|
|
135
|
+
Send a message and wait until the session becomes idle.
|
|
136
|
+
|
|
137
|
+
**Options:**
|
|
138
|
+
|
|
139
|
+
- `prompt: string` - The message/prompt to send
|
|
140
|
+
- `attachments?: Array<{type, path, displayName}>` - File attachments
|
|
141
|
+
- `mode?: "enqueue" | "immediate"` - Delivery mode
|
|
142
|
+
- `timeout?: number` - Optional timeout in milliseconds
|
|
143
|
+
|
|
144
|
+
Returns the final assistant message event, or undefined if none was received.
|
|
145
|
+
|
|
146
|
+
##### `on(handler: SessionEventHandler): () => void`
|
|
147
|
+
|
|
148
|
+
Subscribe to session events. Returns an unsubscribe function.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const unsubscribe = session.on((event) => {
|
|
152
|
+
console.log(event);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Later...
|
|
156
|
+
unsubscribe();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
##### `abort(): Promise<void>`
|
|
160
|
+
|
|
161
|
+
Abort the currently processing message in this session.
|
|
162
|
+
|
|
163
|
+
##### `getMessages(): Promise<SessionEvent[]>`
|
|
164
|
+
|
|
165
|
+
Get all events/messages from this session.
|
|
166
|
+
|
|
167
|
+
##### `destroy(): Promise<void>`
|
|
168
|
+
|
|
169
|
+
Destroy the session and free resources.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Event Types
|
|
174
|
+
|
|
175
|
+
Sessions emit various events during processing:
|
|
176
|
+
|
|
177
|
+
- `user.message` - User message added
|
|
178
|
+
- `assistant.message` - Assistant response
|
|
179
|
+
- `assistant.message_delta` - Streaming response chunk
|
|
180
|
+
- `tool.execution_start` - Tool execution started
|
|
181
|
+
- `tool.execution_end` - Tool execution completed
|
|
182
|
+
- And more...
|
|
183
|
+
|
|
184
|
+
See `SessionEvent` type in the source for full details.
|
|
185
|
+
|
|
186
|
+
## Streaming
|
|
187
|
+
|
|
188
|
+
Enable streaming to receive assistant response chunks as they're generated:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const session = await client.createSession({
|
|
192
|
+
model: "gpt-5",
|
|
193
|
+
streaming: true,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Wait for completion using session.idle event
|
|
197
|
+
const done = new Promise<void>((resolve) => {
|
|
198
|
+
session.on((event) => {
|
|
199
|
+
if (event.type === "assistant.message_delta") {
|
|
200
|
+
// Streaming message chunk - print incrementally
|
|
201
|
+
process.stdout.write(event.data.deltaContent);
|
|
202
|
+
} else if (event.type === "assistant.reasoning_delta") {
|
|
203
|
+
// Streaming reasoning chunk (if model supports reasoning)
|
|
204
|
+
process.stdout.write(event.data.deltaContent);
|
|
205
|
+
} else if (event.type === "assistant.message") {
|
|
206
|
+
// Final message - complete content
|
|
207
|
+
console.log("\n--- Final message ---");
|
|
208
|
+
console.log(event.data.content);
|
|
209
|
+
} else if (event.type === "assistant.reasoning") {
|
|
210
|
+
// Final reasoning content (if model supports reasoning)
|
|
211
|
+
console.log("--- Reasoning ---");
|
|
212
|
+
console.log(event.data.content);
|
|
213
|
+
} else if (event.type === "session.idle") {
|
|
214
|
+
// Session finished processing
|
|
215
|
+
resolve();
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
await session.send({ prompt: "Tell me a short story" });
|
|
221
|
+
await done; // Wait for streaming to complete
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
When `streaming: true`:
|
|
225
|
+
|
|
226
|
+
- `assistant.message_delta` events are sent with `deltaContent` containing incremental text
|
|
227
|
+
- `assistant.reasoning_delta` events are sent with `deltaContent` for reasoning/chain-of-thought (model-dependent)
|
|
228
|
+
- Accumulate `deltaContent` values to build the full response progressively
|
|
229
|
+
- The final `assistant.message` and `assistant.reasoning` events contain the complete content
|
|
230
|
+
|
|
231
|
+
Note: `assistant.message` and `assistant.reasoning` (final events) are always sent regardless of streaming setting.
|
|
232
|
+
|
|
233
|
+
## Advanced Usage
|
|
234
|
+
|
|
235
|
+
### Manual Server Control
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
const client = new CopilotClient({ autoStart: false });
|
|
239
|
+
|
|
240
|
+
// Start manually
|
|
241
|
+
await client.start();
|
|
242
|
+
|
|
243
|
+
// Use client...
|
|
244
|
+
|
|
245
|
+
// Stop manually
|
|
246
|
+
await client.stop();
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Tools
|
|
250
|
+
|
|
251
|
+
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:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import { z } from "zod";
|
|
255
|
+
import { CopilotClient, defineTool } from "@github/copilot-sdk";
|
|
256
|
+
|
|
257
|
+
const session = await client.createSession({
|
|
258
|
+
model: "gpt-5",
|
|
259
|
+
tools: [
|
|
260
|
+
defineTool("lookup_issue", {
|
|
261
|
+
description: "Fetch issue details from our tracker",
|
|
262
|
+
parameters: z.object({
|
|
263
|
+
id: z.string().describe("Issue identifier"),
|
|
264
|
+
}),
|
|
265
|
+
handler: async ({ id }) => {
|
|
266
|
+
const issue = await fetchIssue(id);
|
|
267
|
+
return issue;
|
|
268
|
+
},
|
|
269
|
+
}),
|
|
270
|
+
],
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
When Copilot invokes `lookup_issue`, the client automatically runs your handler and responds to the CLI. Handlers can return any JSON-serializable value (automatically wrapped), a simple string, or a `ToolResultObject` for full control over result metadata. Raw JSON schemas are also supported if Zod isn't desired.
|
|
275
|
+
|
|
276
|
+
### System Message Customization
|
|
277
|
+
|
|
278
|
+
Control the system prompt using `systemMessage` in session config:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const session = await client.createSession({
|
|
282
|
+
model: "gpt-5",
|
|
283
|
+
systemMessage: {
|
|
284
|
+
content: `
|
|
285
|
+
<workflow_rules>
|
|
286
|
+
- Always check for security vulnerabilities
|
|
287
|
+
- Suggest performance improvements when applicable
|
|
288
|
+
</workflow_rules>
|
|
289
|
+
`,
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
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"`.
|
|
295
|
+
|
|
296
|
+
For full control (removes all guardrails), use `mode: "replace"`:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const session = await client.createSession({
|
|
300
|
+
model: "gpt-5",
|
|
301
|
+
systemMessage: {
|
|
302
|
+
mode: "replace",
|
|
303
|
+
content: "You are a helpful assistant.",
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Multiple Sessions
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const session1 = await client.createSession({ model: "gpt-5" });
|
|
312
|
+
const session2 = await client.createSession({ model: "claude-sonnet-4.5" });
|
|
313
|
+
|
|
314
|
+
// Both sessions are independent
|
|
315
|
+
await session1.sendAndWait({ prompt: "Hello from session 1" });
|
|
316
|
+
await session2.sendAndWait({ prompt: "Hello from session 2" });
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Custom Session IDs
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
const session = await client.createSession({
|
|
323
|
+
sessionId: "my-custom-session-id",
|
|
324
|
+
model: "gpt-5",
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### File Attachments
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
await session.send({
|
|
332
|
+
prompt: "Analyze this file",
|
|
333
|
+
attachments: [
|
|
334
|
+
{
|
|
335
|
+
type: "file",
|
|
336
|
+
path: "/path/to/file.js",
|
|
337
|
+
displayName: "My File",
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Error Handling
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
try {
|
|
347
|
+
const session = await client.createSession();
|
|
348
|
+
await session.send({ prompt: "Hello" });
|
|
349
|
+
} catch (error) {
|
|
350
|
+
console.error("Error:", error.message);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Requirements
|
|
355
|
+
|
|
356
|
+
- Node.js >= 18.0.0
|
|
357
|
+
- GitHub Copilot CLI installed and in PATH (or provide custom `cliPath`)
|
|
358
|
+
|
|
359
|
+
## License
|
|
360
|
+
|
|
361
|
+
MIT
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/github/copilot-sdk.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.16",
|
|
8
8
|
"description": "TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC",
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"types": "./dist/index.d.ts",
|