@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.
Files changed (2) hide show
  1. package/README.md +361 -1
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1 +1,361 @@
1
- Coming soon
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.15",
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",