@github/copilot-sdk 0.1.19 → 0.1.20
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 +218 -30
- package/dist/client.d.ts +2 -0
- package/dist/client.js +72 -2
- package/dist/index.d.ts +1 -1
- package/dist/session.d.ts +61 -2
- package/dist/session.js +106 -29
- package/dist/types.d.ts +254 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,14 +24,13 @@ const session = await client.createSession({
|
|
|
24
24
|
model: "gpt-5",
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
// Wait for response using
|
|
27
|
+
// Wait for response using typed event handlers
|
|
28
28
|
const done = new Promise<void>((resolve) => {
|
|
29
|
-
session.on((event) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
29
|
+
session.on("assistant.message", (event) => {
|
|
30
|
+
console.log(event.data.content);
|
|
31
|
+
});
|
|
32
|
+
session.on("session.idle", () => {
|
|
33
|
+
resolve();
|
|
35
34
|
});
|
|
36
35
|
});
|
|
37
36
|
|
|
@@ -64,6 +63,8 @@ new CopilotClient(options?: CopilotClientOptions)
|
|
|
64
63
|
- `logLevel?: string` - Log level (default: "info")
|
|
65
64
|
- `autoStart?: boolean` - Auto-start server (default: true)
|
|
66
65
|
- `autoRestart?: boolean` - Auto-restart on crash (default: true)
|
|
66
|
+
- `githubToken?: string` - GitHub token for authentication. When provided, takes priority over other auth methods.
|
|
67
|
+
- `useLoggedInUser?: boolean` - Whether to use logged-in user for authentication (default: true, but false when `githubToken` is provided). Cannot be used with `cliUrl`.
|
|
67
68
|
|
|
68
69
|
#### Methods
|
|
69
70
|
|
|
@@ -86,10 +87,13 @@ Create a new conversation session.
|
|
|
86
87
|
**Config:**
|
|
87
88
|
|
|
88
89
|
- `sessionId?: string` - Custom session ID
|
|
89
|
-
- `model?: string` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.)
|
|
90
|
+
- `model?: string` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.). **Required when using custom provider.**
|
|
90
91
|
- `tools?: Tool[]` - Custom tools exposed to the CLI
|
|
91
92
|
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
|
|
92
93
|
- `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
|
|
94
|
+
- `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
|
|
95
|
+
- `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
|
|
96
|
+
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
|
|
93
97
|
|
|
94
98
|
##### `resumeSession(sessionId: string, config?: ResumeSessionConfig): Promise<CopilotSession>`
|
|
95
99
|
|
|
@@ -154,13 +158,34 @@ Send a message and wait until the session becomes idle.
|
|
|
154
158
|
|
|
155
159
|
Returns the final assistant message event, or undefined if none was received.
|
|
156
160
|
|
|
161
|
+
##### `on(eventType: string, handler: TypedSessionEventHandler): () => void`
|
|
162
|
+
|
|
163
|
+
Subscribe to a specific event type. The handler receives properly typed events.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Listen for specific event types with full type inference
|
|
167
|
+
session.on("assistant.message", (event) => {
|
|
168
|
+
console.log(event.data.content); // TypeScript knows about event.data.content
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
session.on("session.idle", () => {
|
|
172
|
+
console.log("Session is idle");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Listen to streaming events
|
|
176
|
+
session.on("assistant.message_delta", (event) => {
|
|
177
|
+
process.stdout.write(event.data.deltaContent);
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
157
181
|
##### `on(handler: SessionEventHandler): () => void`
|
|
158
182
|
|
|
159
|
-
Subscribe to session events. Returns an unsubscribe function.
|
|
183
|
+
Subscribe to all session events. Returns an unsubscribe function.
|
|
160
184
|
|
|
161
185
|
```typescript
|
|
162
186
|
const unsubscribe = session.on((event) => {
|
|
163
|
-
|
|
187
|
+
// Handle any event type
|
|
188
|
+
console.log(event.type, event);
|
|
164
189
|
});
|
|
165
190
|
|
|
166
191
|
// Later...
|
|
@@ -226,27 +251,33 @@ const session = await client.createSession({
|
|
|
226
251
|
streaming: true,
|
|
227
252
|
});
|
|
228
253
|
|
|
229
|
-
// Wait for completion using
|
|
254
|
+
// Wait for completion using typed event handlers
|
|
230
255
|
const done = new Promise<void>((resolve) => {
|
|
231
|
-
session.on((event) => {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
256
|
+
session.on("assistant.message_delta", (event) => {
|
|
257
|
+
// Streaming message chunk - print incrementally
|
|
258
|
+
process.stdout.write(event.data.deltaContent);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
session.on("assistant.reasoning_delta", (event) => {
|
|
262
|
+
// Streaming reasoning chunk (if model supports reasoning)
|
|
263
|
+
process.stdout.write(event.data.deltaContent);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
session.on("assistant.message", (event) => {
|
|
267
|
+
// Final message - complete content
|
|
268
|
+
console.log("\n--- Final message ---");
|
|
269
|
+
console.log(event.data.content);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
session.on("assistant.reasoning", (event) => {
|
|
273
|
+
// Final reasoning content (if model supports reasoning)
|
|
274
|
+
console.log("--- Reasoning ---");
|
|
275
|
+
console.log(event.data.content);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
session.on("session.idle", () => {
|
|
279
|
+
// Session finished processing
|
|
280
|
+
resolve();
|
|
250
281
|
});
|
|
251
282
|
});
|
|
252
283
|
|
|
@@ -407,6 +438,163 @@ await session.send({
|
|
|
407
438
|
});
|
|
408
439
|
```
|
|
409
440
|
|
|
441
|
+
### Custom Providers
|
|
442
|
+
|
|
443
|
+
The SDK supports custom OpenAI-compatible API providers (BYOK - Bring Your Own Key), including local providers like Ollama. When using a custom provider, you must specify the `model` explicitly.
|
|
444
|
+
|
|
445
|
+
**ProviderConfig:**
|
|
446
|
+
|
|
447
|
+
- `type?: "openai" | "azure" | "anthropic"` - Provider type (default: "openai")
|
|
448
|
+
- `baseUrl: string` - API endpoint URL (required)
|
|
449
|
+
- `apiKey?: string` - API key (optional for local providers like Ollama)
|
|
450
|
+
- `bearerToken?: string` - Bearer token for authentication (takes precedence over apiKey)
|
|
451
|
+
- `wireApi?: "completions" | "responses"` - API format for OpenAI/Azure (default: "completions")
|
|
452
|
+
- `azure?.apiVersion?: string` - Azure API version (default: "2024-10-21")
|
|
453
|
+
|
|
454
|
+
**Example with Ollama:**
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
const session = await client.createSession({
|
|
458
|
+
model: "deepseek-coder-v2:16b", // Required when using custom provider
|
|
459
|
+
provider: {
|
|
460
|
+
type: "openai",
|
|
461
|
+
baseUrl: "http://localhost:11434/v1", // Ollama endpoint
|
|
462
|
+
// apiKey not required for Ollama
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
await session.sendAndWait({ prompt: "Hello!" });
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Example with custom OpenAI-compatible API:**
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
const session = await client.createSession({
|
|
473
|
+
model: "gpt-4",
|
|
474
|
+
provider: {
|
|
475
|
+
type: "openai",
|
|
476
|
+
baseUrl: "https://my-api.example.com/v1",
|
|
477
|
+
apiKey: process.env.MY_API_KEY,
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Example with Azure OpenAI:**
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
const session = await client.createSession({
|
|
486
|
+
model: "gpt-4",
|
|
487
|
+
provider: {
|
|
488
|
+
type: "azure", // Must be "azure" for Azure endpoints, NOT "openai"
|
|
489
|
+
baseUrl: "https://my-resource.openai.azure.com", // Just the host, no path
|
|
490
|
+
apiKey: process.env.AZURE_OPENAI_KEY,
|
|
491
|
+
azure: {
|
|
492
|
+
apiVersion: "2024-10-21",
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
});
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
> **Important notes:**
|
|
499
|
+
> - When using a custom provider, the `model` parameter is **required**. The SDK will throw an error if no model is specified.
|
|
500
|
+
> - For Azure OpenAI endpoints (`*.openai.azure.com`), you **must** use `type: "azure"`, not `type: "openai"`.
|
|
501
|
+
> - 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.
|
|
502
|
+
|
|
503
|
+
## User Input Requests
|
|
504
|
+
|
|
505
|
+
Enable the agent to ask questions to the user using the `ask_user` tool by providing an `onUserInputRequest` handler:
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
const session = await client.createSession({
|
|
509
|
+
model: "gpt-5",
|
|
510
|
+
onUserInputRequest: async (request, invocation) => {
|
|
511
|
+
// request.question - The question to ask
|
|
512
|
+
// request.choices - Optional array of choices for multiple choice
|
|
513
|
+
// request.allowFreeform - Whether freeform input is allowed (default: true)
|
|
514
|
+
|
|
515
|
+
console.log(`Agent asks: ${request.question}`);
|
|
516
|
+
if (request.choices) {
|
|
517
|
+
console.log(`Choices: ${request.choices.join(", ")}`);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Return the user's response
|
|
521
|
+
return {
|
|
522
|
+
answer: "User's answer here",
|
|
523
|
+
wasFreeform: true, // Whether the answer was freeform (not from choices)
|
|
524
|
+
};
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## Session Hooks
|
|
530
|
+
|
|
531
|
+
Hook into session lifecycle events by providing handlers in the `hooks` configuration:
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
const session = await client.createSession({
|
|
535
|
+
model: "gpt-5",
|
|
536
|
+
hooks: {
|
|
537
|
+
// Called before each tool execution
|
|
538
|
+
onPreToolUse: async (input, invocation) => {
|
|
539
|
+
console.log(`About to run tool: ${input.toolName}`);
|
|
540
|
+
// Return permission decision and optionally modify args
|
|
541
|
+
return {
|
|
542
|
+
permissionDecision: "allow", // "allow", "deny", or "ask"
|
|
543
|
+
modifiedArgs: input.toolArgs, // Optionally modify tool arguments
|
|
544
|
+
additionalContext: "Extra context for the model",
|
|
545
|
+
};
|
|
546
|
+
},
|
|
547
|
+
|
|
548
|
+
// Called after each tool execution
|
|
549
|
+
onPostToolUse: async (input, invocation) => {
|
|
550
|
+
console.log(`Tool ${input.toolName} completed`);
|
|
551
|
+
// Optionally modify the result or add context
|
|
552
|
+
return {
|
|
553
|
+
additionalContext: "Post-execution notes",
|
|
554
|
+
};
|
|
555
|
+
},
|
|
556
|
+
|
|
557
|
+
// Called when user submits a prompt
|
|
558
|
+
onUserPromptSubmitted: async (input, invocation) => {
|
|
559
|
+
console.log(`User prompt: ${input.prompt}`);
|
|
560
|
+
return {
|
|
561
|
+
modifiedPrompt: input.prompt, // Optionally modify the prompt
|
|
562
|
+
};
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
// Called when session starts
|
|
566
|
+
onSessionStart: async (input, invocation) => {
|
|
567
|
+
console.log(`Session started from: ${input.source}`); // "startup", "resume", "new"
|
|
568
|
+
return {
|
|
569
|
+
additionalContext: "Session initialization context",
|
|
570
|
+
};
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
// Called when session ends
|
|
574
|
+
onSessionEnd: async (input, invocation) => {
|
|
575
|
+
console.log(`Session ended: ${input.reason}`);
|
|
576
|
+
},
|
|
577
|
+
|
|
578
|
+
// Called when an error occurs
|
|
579
|
+
onErrorOccurred: async (input, invocation) => {
|
|
580
|
+
console.error(`Error in ${input.errorContext}: ${input.error}`);
|
|
581
|
+
return {
|
|
582
|
+
errorHandling: "retry", // "retry", "skip", or "abort"
|
|
583
|
+
};
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
**Available hooks:**
|
|
590
|
+
|
|
591
|
+
- `onPreToolUse` - Intercept tool calls before execution. Can allow/deny or modify arguments.
|
|
592
|
+
- `onPostToolUse` - Process tool results after execution. Can modify results or add context.
|
|
593
|
+
- `onUserPromptSubmitted` - Intercept user prompts. Can modify the prompt before processing.
|
|
594
|
+
- `onSessionStart` - Run logic when a session starts or resumes.
|
|
595
|
+
- `onSessionEnd` - Cleanup or logging when session ends.
|
|
596
|
+
- `onErrorOccurred` - Handle errors with retry/skip/abort strategies.
|
|
597
|
+
|
|
410
598
|
## Error Handling
|
|
411
599
|
|
|
412
600
|
```typescript
|
package/dist/client.d.ts
CHANGED
|
@@ -309,6 +309,8 @@ export declare class CopilotClient {
|
|
|
309
309
|
private handleToolCallRequest;
|
|
310
310
|
private executeToolCall;
|
|
311
311
|
private handlePermissionRequest;
|
|
312
|
+
private handleUserInputRequest;
|
|
313
|
+
private handleHooksInvoke;
|
|
312
314
|
private normalizeToolResult;
|
|
313
315
|
private isToolResultObject;
|
|
314
316
|
private buildUnsupportedToolResult;
|
package/dist/client.js
CHANGED
|
@@ -53,6 +53,11 @@ class CopilotClient {
|
|
|
53
53
|
if (options.cliUrl && (options.useStdio === true || options.cliPath)) {
|
|
54
54
|
throw new Error("cliUrl is mutually exclusive with useStdio and cliPath");
|
|
55
55
|
}
|
|
56
|
+
if (options.cliUrl && (options.githubToken || options.useLoggedInUser !== void 0)) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"githubToken and useLoggedInUser cannot be used with cliUrl (external server manages its own auth)"
|
|
59
|
+
);
|
|
60
|
+
}
|
|
56
61
|
if (options.cliUrl) {
|
|
57
62
|
const { host, port } = this.parseCliUrl(options.cliUrl);
|
|
58
63
|
this.actualHost = host;
|
|
@@ -70,7 +75,10 @@ class CopilotClient {
|
|
|
70
75
|
logLevel: options.logLevel || "debug",
|
|
71
76
|
autoStart: options.autoStart ?? true,
|
|
72
77
|
autoRestart: options.autoRestart ?? true,
|
|
73
|
-
env: options.env ?? process.env
|
|
78
|
+
env: options.env ?? process.env,
|
|
79
|
+
githubToken: options.githubToken,
|
|
80
|
+
// Default useLoggedInUser to false when githubToken is provided, otherwise true
|
|
81
|
+
useLoggedInUser: options.useLoggedInUser ?? (options.githubToken ? false : true)
|
|
74
82
|
};
|
|
75
83
|
}
|
|
76
84
|
/**
|
|
@@ -317,6 +325,9 @@ class CopilotClient {
|
|
|
317
325
|
excludedTools: config.excludedTools,
|
|
318
326
|
provider: config.provider,
|
|
319
327
|
requestPermission: !!config.onPermissionRequest,
|
|
328
|
+
requestUserInput: !!config.onUserInputRequest,
|
|
329
|
+
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
330
|
+
workingDirectory: config.workingDirectory,
|
|
320
331
|
streaming: config.streaming,
|
|
321
332
|
mcpServers: config.mcpServers,
|
|
322
333
|
customAgents: config.customAgents,
|
|
@@ -331,6 +342,12 @@ class CopilotClient {
|
|
|
331
342
|
if (config.onPermissionRequest) {
|
|
332
343
|
session.registerPermissionHandler(config.onPermissionRequest);
|
|
333
344
|
}
|
|
345
|
+
if (config.onUserInputRequest) {
|
|
346
|
+
session.registerUserInputHandler(config.onUserInputRequest);
|
|
347
|
+
}
|
|
348
|
+
if (config.hooks) {
|
|
349
|
+
session.registerHooks(config.hooks);
|
|
350
|
+
}
|
|
334
351
|
this.sessions.set(sessionId, session);
|
|
335
352
|
return session;
|
|
336
353
|
}
|
|
@@ -374,11 +391,15 @@ class CopilotClient {
|
|
|
374
391
|
})),
|
|
375
392
|
provider: config.provider,
|
|
376
393
|
requestPermission: !!config.onPermissionRequest,
|
|
394
|
+
requestUserInput: !!config.onUserInputRequest,
|
|
395
|
+
hooks: !!(config.hooks && Object.values(config.hooks).some(Boolean)),
|
|
396
|
+
workingDirectory: config.workingDirectory,
|
|
377
397
|
streaming: config.streaming,
|
|
378
398
|
mcpServers: config.mcpServers,
|
|
379
399
|
customAgents: config.customAgents,
|
|
380
400
|
skillDirectories: config.skillDirectories,
|
|
381
|
-
disabledSkills: config.disabledSkills
|
|
401
|
+
disabledSkills: config.disabledSkills,
|
|
402
|
+
disableResume: config.disableResume
|
|
382
403
|
});
|
|
383
404
|
const { sessionId: resumedSessionId, workspacePath } = response;
|
|
384
405
|
const session = new CopilotSession(resumedSessionId, this.connection, workspacePath);
|
|
@@ -386,6 +407,12 @@ class CopilotClient {
|
|
|
386
407
|
if (config.onPermissionRequest) {
|
|
387
408
|
session.registerPermissionHandler(config.onPermissionRequest);
|
|
388
409
|
}
|
|
410
|
+
if (config.onUserInputRequest) {
|
|
411
|
+
session.registerUserInputHandler(config.onUserInputRequest);
|
|
412
|
+
}
|
|
413
|
+
if (config.hooks) {
|
|
414
|
+
session.registerHooks(config.hooks);
|
|
415
|
+
}
|
|
389
416
|
this.sessions.set(resumedSessionId, session);
|
|
390
417
|
return session;
|
|
391
418
|
}
|
|
@@ -572,8 +599,17 @@ class CopilotClient {
|
|
|
572
599
|
} else if (this.options.port > 0) {
|
|
573
600
|
args.push("--port", this.options.port.toString());
|
|
574
601
|
}
|
|
602
|
+
if (this.options.githubToken) {
|
|
603
|
+
args.push("--auth-token-env", "COPILOT_SDK_AUTH_TOKEN");
|
|
604
|
+
}
|
|
605
|
+
if (!this.options.useLoggedInUser) {
|
|
606
|
+
args.push("--no-auto-login");
|
|
607
|
+
}
|
|
575
608
|
const envWithoutNodeDebug = { ...this.options.env };
|
|
576
609
|
delete envWithoutNodeDebug.NODE_DEBUG;
|
|
610
|
+
if (this.options.githubToken) {
|
|
611
|
+
envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.githubToken;
|
|
612
|
+
}
|
|
577
613
|
const isJsFile = this.options.cliPath.endsWith(".js");
|
|
578
614
|
const isAbsolutePath = this.options.cliPath.startsWith("/") || /^[a-zA-Z]:/.test(this.options.cliPath);
|
|
579
615
|
let command;
|
|
@@ -707,6 +743,14 @@ class CopilotClient {
|
|
|
707
743
|
"permission.request",
|
|
708
744
|
async (params) => await this.handlePermissionRequest(params)
|
|
709
745
|
);
|
|
746
|
+
this.connection.onRequest(
|
|
747
|
+
"userInput.request",
|
|
748
|
+
async (params) => await this.handleUserInputRequest(params)
|
|
749
|
+
);
|
|
750
|
+
this.connection.onRequest(
|
|
751
|
+
"hooks.invoke",
|
|
752
|
+
async (params) => await this.handleHooksInvoke(params)
|
|
753
|
+
);
|
|
710
754
|
this.connection.onClose(() => {
|
|
711
755
|
if (this.state === "connected" && this.options.autoRestart) {
|
|
712
756
|
void this.reconnect();
|
|
@@ -780,6 +824,32 @@ class CopilotClient {
|
|
|
780
824
|
};
|
|
781
825
|
}
|
|
782
826
|
}
|
|
827
|
+
async handleUserInputRequest(params) {
|
|
828
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
|
|
829
|
+
throw new Error("Invalid user input request payload");
|
|
830
|
+
}
|
|
831
|
+
const session = this.sessions.get(params.sessionId);
|
|
832
|
+
if (!session) {
|
|
833
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
834
|
+
}
|
|
835
|
+
const result = await session._handleUserInputRequest({
|
|
836
|
+
question: params.question,
|
|
837
|
+
choices: params.choices,
|
|
838
|
+
allowFreeform: params.allowFreeform
|
|
839
|
+
});
|
|
840
|
+
return result;
|
|
841
|
+
}
|
|
842
|
+
async handleHooksInvoke(params) {
|
|
843
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
|
|
844
|
+
throw new Error("Invalid hooks invoke payload");
|
|
845
|
+
}
|
|
846
|
+
const session = this.sessions.get(params.sessionId);
|
|
847
|
+
if (!session) {
|
|
848
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
849
|
+
}
|
|
850
|
+
const output = await session._handleHooksInvoke(params.hookType, params.input);
|
|
851
|
+
return { output };
|
|
852
|
+
}
|
|
783
853
|
normalizeToolResult(result) {
|
|
784
854
|
if (result === void 0 || result === null) {
|
|
785
855
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
export { CopilotClient } from "./client.js";
|
|
7
7
|
export { CopilotSession, type AssistantMessageEvent } from "./session.js";
|
|
8
8
|
export { defineTool } from "./types.js";
|
|
9
|
-
export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SessionConfig, SessionEvent, SessionEventHandler, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation, ToolResultObject, ZodSchema, } from "./types.js";
|
|
9
|
+
export type { ConnectionState, CopilotClientOptions, CustomAgentConfig, GetAuthStatusResponse, GetStatusResponse, InfiniteSessionConfig, MCPLocalServerConfig, MCPRemoteServerConfig, MCPServerConfig, MessageOptions, ModelBilling, ModelCapabilities, ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest, PermissionRequestResult, ResumeSessionConfig, SessionConfig, SessionEvent, SessionEventHandler, SessionEventPayload, SessionEventType, SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig, SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation, ToolResultObject, TypedSessionEventHandler, ZodSchema, } from "./types.js";
|
package/dist/session.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module session
|
|
4
4
|
*/
|
|
5
5
|
import type { MessageConnection } from "vscode-jsonrpc/node";
|
|
6
|
-
import type { MessageOptions, PermissionHandler, PermissionRequestResult, SessionEvent, SessionEventHandler, Tool, ToolHandler } from "./types.js";
|
|
6
|
+
import type { MessageOptions, PermissionHandler, PermissionRequestResult, SessionEvent, SessionEventHandler, SessionEventType, SessionHooks, Tool, ToolHandler, TypedSessionEventHandler, UserInputHandler, UserInputResponse } from "./types.js";
|
|
7
7
|
/** Assistant message event - the final response from the assistant. */
|
|
8
8
|
export type AssistantMessageEvent = Extract<SessionEvent, {
|
|
9
9
|
type: "assistant.message";
|
|
@@ -38,8 +38,11 @@ export declare class CopilotSession {
|
|
|
38
38
|
private connection;
|
|
39
39
|
private readonly _workspacePath?;
|
|
40
40
|
private eventHandlers;
|
|
41
|
+
private typedEventHandlers;
|
|
41
42
|
private toolHandlers;
|
|
42
43
|
private permissionHandler?;
|
|
44
|
+
private userInputHandler?;
|
|
45
|
+
private hooks?;
|
|
43
46
|
/**
|
|
44
47
|
* Creates a new CopilotSession instance.
|
|
45
48
|
*
|
|
@@ -104,7 +107,26 @@ export declare class CopilotSession {
|
|
|
104
107
|
* Events include assistant messages, tool executions, errors, and session state changes.
|
|
105
108
|
* Multiple handlers can be registered and will all receive events.
|
|
106
109
|
*
|
|
107
|
-
* @param
|
|
110
|
+
* @param eventType - The specific event type to listen for (e.g., "assistant.message", "session.idle")
|
|
111
|
+
* @param handler - A callback function that receives events of the specified type
|
|
112
|
+
* @returns A function that, when called, unsubscribes the handler
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // Listen for a specific event type
|
|
117
|
+
* const unsubscribe = session.on("assistant.message", (event) => {
|
|
118
|
+
* console.log("Assistant:", event.data.content);
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* // Later, to stop receiving events:
|
|
122
|
+
* unsubscribe();
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
on<K extends SessionEventType>(eventType: K, handler: TypedSessionEventHandler<K>): () => void;
|
|
126
|
+
/**
|
|
127
|
+
* Subscribes to all events from this session.
|
|
128
|
+
*
|
|
129
|
+
* @param handler - A callback function that receives all session events
|
|
108
130
|
* @returns A function that, when called, unsubscribes the handler
|
|
109
131
|
*
|
|
110
132
|
* @example
|
|
@@ -160,6 +182,26 @@ export declare class CopilotSession {
|
|
|
160
182
|
* @internal This method is typically called internally when creating a session.
|
|
161
183
|
*/
|
|
162
184
|
registerPermissionHandler(handler?: PermissionHandler): void;
|
|
185
|
+
/**
|
|
186
|
+
* Registers a user input handler for ask_user requests.
|
|
187
|
+
*
|
|
188
|
+
* When the agent needs input from the user (via ask_user tool),
|
|
189
|
+
* this handler is called to provide the response.
|
|
190
|
+
*
|
|
191
|
+
* @param handler - The user input handler function, or undefined to remove the handler
|
|
192
|
+
* @internal This method is typically called internally when creating a session.
|
|
193
|
+
*/
|
|
194
|
+
registerUserInputHandler(handler?: UserInputHandler): void;
|
|
195
|
+
/**
|
|
196
|
+
* Registers hook handlers for session lifecycle events.
|
|
197
|
+
*
|
|
198
|
+
* Hooks allow custom logic to be executed at various points during
|
|
199
|
+
* the session lifecycle (before/after tool use, session start/end, etc.).
|
|
200
|
+
*
|
|
201
|
+
* @param hooks - The hook handlers object, or undefined to remove all hooks
|
|
202
|
+
* @internal This method is typically called internally when creating a session.
|
|
203
|
+
*/
|
|
204
|
+
registerHooks(hooks?: SessionHooks): void;
|
|
163
205
|
/**
|
|
164
206
|
* Handles a permission request from the Copilot CLI.
|
|
165
207
|
*
|
|
@@ -168,6 +210,23 @@ export declare class CopilotSession {
|
|
|
168
210
|
* @internal This method is for internal use by the SDK.
|
|
169
211
|
*/
|
|
170
212
|
_handlePermissionRequest(request: unknown): Promise<PermissionRequestResult>;
|
|
213
|
+
/**
|
|
214
|
+
* Handles a user input request from the Copilot CLI.
|
|
215
|
+
*
|
|
216
|
+
* @param request - The user input request data from the CLI
|
|
217
|
+
* @returns A promise that resolves with the user's response
|
|
218
|
+
* @internal This method is for internal use by the SDK.
|
|
219
|
+
*/
|
|
220
|
+
_handleUserInputRequest(request: unknown): Promise<UserInputResponse>;
|
|
221
|
+
/**
|
|
222
|
+
* Handles a hooks invocation from the Copilot CLI.
|
|
223
|
+
*
|
|
224
|
+
* @param hookType - The type of hook being invoked
|
|
225
|
+
* @param input - The input data for the hook
|
|
226
|
+
* @returns A promise that resolves with the hook output, or undefined
|
|
227
|
+
* @internal This method is for internal use by the SDK.
|
|
228
|
+
*/
|
|
229
|
+
_handleHooksInvoke(hookType: string, input: unknown): Promise<unknown>;
|
|
171
230
|
/**
|
|
172
231
|
* Retrieves all events and messages from this session's history.
|
|
173
232
|
*
|
package/dist/session.js
CHANGED
|
@@ -13,8 +13,11 @@ class CopilotSession {
|
|
|
13
13
|
this._workspacePath = _workspacePath;
|
|
14
14
|
}
|
|
15
15
|
eventHandlers = /* @__PURE__ */ new Set();
|
|
16
|
+
typedEventHandlers = /* @__PURE__ */ new Map();
|
|
16
17
|
toolHandlers = /* @__PURE__ */ new Map();
|
|
17
18
|
permissionHandler;
|
|
19
|
+
userInputHandler;
|
|
20
|
+
hooks;
|
|
18
21
|
/**
|
|
19
22
|
* Path to the session workspace directory when infinite sessions are enabled.
|
|
20
23
|
* Contains checkpoints/, plan.md, and files/ subdirectories.
|
|
@@ -111,36 +114,25 @@ class CopilotSession {
|
|
|
111
114
|
unsubscribe();
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
* console.error("Error:", event.data.message);
|
|
132
|
-
* break;
|
|
133
|
-
* }
|
|
134
|
-
* });
|
|
135
|
-
*
|
|
136
|
-
* // Later, to stop receiving events:
|
|
137
|
-
* unsubscribe();
|
|
138
|
-
* ```
|
|
139
|
-
*/
|
|
140
|
-
on(handler) {
|
|
141
|
-
this.eventHandlers.add(handler);
|
|
117
|
+
on(eventTypeOrHandler, handler) {
|
|
118
|
+
if (typeof eventTypeOrHandler === "string" && handler) {
|
|
119
|
+
const eventType = eventTypeOrHandler;
|
|
120
|
+
if (!this.typedEventHandlers.has(eventType)) {
|
|
121
|
+
this.typedEventHandlers.set(eventType, /* @__PURE__ */ new Set());
|
|
122
|
+
}
|
|
123
|
+
const storedHandler = handler;
|
|
124
|
+
this.typedEventHandlers.get(eventType).add(storedHandler);
|
|
125
|
+
return () => {
|
|
126
|
+
const handlers = this.typedEventHandlers.get(eventType);
|
|
127
|
+
if (handlers) {
|
|
128
|
+
handlers.delete(storedHandler);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const wildcardHandler = eventTypeOrHandler;
|
|
133
|
+
this.eventHandlers.add(wildcardHandler);
|
|
142
134
|
return () => {
|
|
143
|
-
this.eventHandlers.delete(
|
|
135
|
+
this.eventHandlers.delete(wildcardHandler);
|
|
144
136
|
};
|
|
145
137
|
}
|
|
146
138
|
/**
|
|
@@ -150,6 +142,15 @@ class CopilotSession {
|
|
|
150
142
|
* @internal This method is for internal use by the SDK.
|
|
151
143
|
*/
|
|
152
144
|
_dispatchEvent(event) {
|
|
145
|
+
const typedHandlers = this.typedEventHandlers.get(event.type);
|
|
146
|
+
if (typedHandlers) {
|
|
147
|
+
for (const handler of typedHandlers) {
|
|
148
|
+
try {
|
|
149
|
+
handler(event);
|
|
150
|
+
} catch (_error) {
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
153
154
|
for (const handler of this.eventHandlers) {
|
|
154
155
|
try {
|
|
155
156
|
handler(event);
|
|
@@ -197,6 +198,30 @@ class CopilotSession {
|
|
|
197
198
|
registerPermissionHandler(handler) {
|
|
198
199
|
this.permissionHandler = handler;
|
|
199
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Registers a user input handler for ask_user requests.
|
|
203
|
+
*
|
|
204
|
+
* When the agent needs input from the user (via ask_user tool),
|
|
205
|
+
* this handler is called to provide the response.
|
|
206
|
+
*
|
|
207
|
+
* @param handler - The user input handler function, or undefined to remove the handler
|
|
208
|
+
* @internal This method is typically called internally when creating a session.
|
|
209
|
+
*/
|
|
210
|
+
registerUserInputHandler(handler) {
|
|
211
|
+
this.userInputHandler = handler;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Registers hook handlers for session lifecycle events.
|
|
215
|
+
*
|
|
216
|
+
* Hooks allow custom logic to be executed at various points during
|
|
217
|
+
* the session lifecycle (before/after tool use, session start/end, etc.).
|
|
218
|
+
*
|
|
219
|
+
* @param hooks - The hook handlers object, or undefined to remove all hooks
|
|
220
|
+
* @internal This method is typically called internally when creating a session.
|
|
221
|
+
*/
|
|
222
|
+
registerHooks(hooks) {
|
|
223
|
+
this.hooks = hooks;
|
|
224
|
+
}
|
|
200
225
|
/**
|
|
201
226
|
* Handles a permission request from the Copilot CLI.
|
|
202
227
|
*
|
|
@@ -217,6 +242,57 @@ class CopilotSession {
|
|
|
217
242
|
return { kind: "denied-no-approval-rule-and-could-not-request-from-user" };
|
|
218
243
|
}
|
|
219
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Handles a user input request from the Copilot CLI.
|
|
247
|
+
*
|
|
248
|
+
* @param request - The user input request data from the CLI
|
|
249
|
+
* @returns A promise that resolves with the user's response
|
|
250
|
+
* @internal This method is for internal use by the SDK.
|
|
251
|
+
*/
|
|
252
|
+
async _handleUserInputRequest(request) {
|
|
253
|
+
if (!this.userInputHandler) {
|
|
254
|
+
throw new Error("User input requested but no handler registered");
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const result = await this.userInputHandler(request, {
|
|
258
|
+
sessionId: this.sessionId
|
|
259
|
+
});
|
|
260
|
+
return result;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Handles a hooks invocation from the Copilot CLI.
|
|
267
|
+
*
|
|
268
|
+
* @param hookType - The type of hook being invoked
|
|
269
|
+
* @param input - The input data for the hook
|
|
270
|
+
* @returns A promise that resolves with the hook output, or undefined
|
|
271
|
+
* @internal This method is for internal use by the SDK.
|
|
272
|
+
*/
|
|
273
|
+
async _handleHooksInvoke(hookType, input) {
|
|
274
|
+
if (!this.hooks) {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
const handlerMap = {
|
|
278
|
+
preToolUse: this.hooks.onPreToolUse,
|
|
279
|
+
postToolUse: this.hooks.onPostToolUse,
|
|
280
|
+
userPromptSubmitted: this.hooks.onUserPromptSubmitted,
|
|
281
|
+
sessionStart: this.hooks.onSessionStart,
|
|
282
|
+
sessionEnd: this.hooks.onSessionEnd,
|
|
283
|
+
errorOccurred: this.hooks.onErrorOccurred
|
|
284
|
+
};
|
|
285
|
+
const handler = handlerMap[hookType];
|
|
286
|
+
if (!handler) {
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
const result = await handler(input, { sessionId: this.sessionId });
|
|
291
|
+
return result;
|
|
292
|
+
} catch (_error) {
|
|
293
|
+
return void 0;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
220
296
|
/**
|
|
221
297
|
* Retrieves all events and messages from this session's history.
|
|
222
298
|
*
|
|
@@ -263,6 +339,7 @@ class CopilotSession {
|
|
|
263
339
|
sessionId: this.sessionId
|
|
264
340
|
});
|
|
265
341
|
this.eventHandlers.clear();
|
|
342
|
+
this.typedEventHandlers.clear();
|
|
266
343
|
this.toolHandlers.clear();
|
|
267
344
|
this.permissionHandler = void 0;
|
|
268
345
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -58,6 +58,19 @@ export interface CopilotClientOptions {
|
|
|
58
58
|
* Environment variables to pass to the CLI process. If not set, inherits process.env.
|
|
59
59
|
*/
|
|
60
60
|
env?: Record<string, string | undefined>;
|
|
61
|
+
/**
|
|
62
|
+
* GitHub token to use for authentication.
|
|
63
|
+
* When provided, the token is passed to the CLI server via environment variable.
|
|
64
|
+
* This takes priority over other authentication methods.
|
|
65
|
+
*/
|
|
66
|
+
githubToken?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Whether to use the logged-in user for authentication.
|
|
69
|
+
* When true, the CLI server will attempt to use stored OAuth tokens or gh CLI auth.
|
|
70
|
+
* When false, only explicit tokens (githubToken or environment variables) are used.
|
|
71
|
+
* @default true (but defaults to false when githubToken is provided)
|
|
72
|
+
*/
|
|
73
|
+
useLoggedInUser?: boolean;
|
|
61
74
|
}
|
|
62
75
|
/**
|
|
63
76
|
* Configuration for creating a session
|
|
@@ -166,6 +179,209 @@ export interface PermissionRequestResult {
|
|
|
166
179
|
export type PermissionHandler = (request: PermissionRequest, invocation: {
|
|
167
180
|
sessionId: string;
|
|
168
181
|
}) => Promise<PermissionRequestResult> | PermissionRequestResult;
|
|
182
|
+
/**
|
|
183
|
+
* Request for user input from the agent (enables ask_user tool)
|
|
184
|
+
*/
|
|
185
|
+
export interface UserInputRequest {
|
|
186
|
+
/**
|
|
187
|
+
* The question to ask the user
|
|
188
|
+
*/
|
|
189
|
+
question: string;
|
|
190
|
+
/**
|
|
191
|
+
* Optional choices for multiple choice questions
|
|
192
|
+
*/
|
|
193
|
+
choices?: string[];
|
|
194
|
+
/**
|
|
195
|
+
* Whether to allow freeform text input in addition to choices
|
|
196
|
+
* @default true
|
|
197
|
+
*/
|
|
198
|
+
allowFreeform?: boolean;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Response to a user input request
|
|
202
|
+
*/
|
|
203
|
+
export interface UserInputResponse {
|
|
204
|
+
/**
|
|
205
|
+
* The user's answer
|
|
206
|
+
*/
|
|
207
|
+
answer: string;
|
|
208
|
+
/**
|
|
209
|
+
* Whether the answer was freeform (not from choices)
|
|
210
|
+
*/
|
|
211
|
+
wasFreeform: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Handler for user input requests from the agent
|
|
215
|
+
*/
|
|
216
|
+
export type UserInputHandler = (request: UserInputRequest, invocation: {
|
|
217
|
+
sessionId: string;
|
|
218
|
+
}) => Promise<UserInputResponse> | UserInputResponse;
|
|
219
|
+
/**
|
|
220
|
+
* Base interface for all hook inputs
|
|
221
|
+
*/
|
|
222
|
+
export interface BaseHookInput {
|
|
223
|
+
timestamp: number;
|
|
224
|
+
cwd: string;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Input for pre-tool-use hook
|
|
228
|
+
*/
|
|
229
|
+
export interface PreToolUseHookInput extends BaseHookInput {
|
|
230
|
+
toolName: string;
|
|
231
|
+
toolArgs: unknown;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Output for pre-tool-use hook
|
|
235
|
+
*/
|
|
236
|
+
export interface PreToolUseHookOutput {
|
|
237
|
+
permissionDecision?: "allow" | "deny" | "ask";
|
|
238
|
+
permissionDecisionReason?: string;
|
|
239
|
+
modifiedArgs?: unknown;
|
|
240
|
+
additionalContext?: string;
|
|
241
|
+
suppressOutput?: boolean;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Handler for pre-tool-use hook
|
|
245
|
+
*/
|
|
246
|
+
export type PreToolUseHandler = (input: PreToolUseHookInput, invocation: {
|
|
247
|
+
sessionId: string;
|
|
248
|
+
}) => Promise<PreToolUseHookOutput | void> | PreToolUseHookOutput | void;
|
|
249
|
+
/**
|
|
250
|
+
* Input for post-tool-use hook
|
|
251
|
+
*/
|
|
252
|
+
export interface PostToolUseHookInput extends BaseHookInput {
|
|
253
|
+
toolName: string;
|
|
254
|
+
toolArgs: unknown;
|
|
255
|
+
toolResult: ToolResultObject;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Output for post-tool-use hook
|
|
259
|
+
*/
|
|
260
|
+
export interface PostToolUseHookOutput {
|
|
261
|
+
modifiedResult?: ToolResultObject;
|
|
262
|
+
additionalContext?: string;
|
|
263
|
+
suppressOutput?: boolean;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Handler for post-tool-use hook
|
|
267
|
+
*/
|
|
268
|
+
export type PostToolUseHandler = (input: PostToolUseHookInput, invocation: {
|
|
269
|
+
sessionId: string;
|
|
270
|
+
}) => Promise<PostToolUseHookOutput | void> | PostToolUseHookOutput | void;
|
|
271
|
+
/**
|
|
272
|
+
* Input for user-prompt-submitted hook
|
|
273
|
+
*/
|
|
274
|
+
export interface UserPromptSubmittedHookInput extends BaseHookInput {
|
|
275
|
+
prompt: string;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Output for user-prompt-submitted hook
|
|
279
|
+
*/
|
|
280
|
+
export interface UserPromptSubmittedHookOutput {
|
|
281
|
+
modifiedPrompt?: string;
|
|
282
|
+
additionalContext?: string;
|
|
283
|
+
suppressOutput?: boolean;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Handler for user-prompt-submitted hook
|
|
287
|
+
*/
|
|
288
|
+
export type UserPromptSubmittedHandler = (input: UserPromptSubmittedHookInput, invocation: {
|
|
289
|
+
sessionId: string;
|
|
290
|
+
}) => Promise<UserPromptSubmittedHookOutput | void> | UserPromptSubmittedHookOutput | void;
|
|
291
|
+
/**
|
|
292
|
+
* Input for session-start hook
|
|
293
|
+
*/
|
|
294
|
+
export interface SessionStartHookInput extends BaseHookInput {
|
|
295
|
+
source: "startup" | "resume" | "new";
|
|
296
|
+
initialPrompt?: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Output for session-start hook
|
|
300
|
+
*/
|
|
301
|
+
export interface SessionStartHookOutput {
|
|
302
|
+
additionalContext?: string;
|
|
303
|
+
modifiedConfig?: Record<string, unknown>;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Handler for session-start hook
|
|
307
|
+
*/
|
|
308
|
+
export type SessionStartHandler = (input: SessionStartHookInput, invocation: {
|
|
309
|
+
sessionId: string;
|
|
310
|
+
}) => Promise<SessionStartHookOutput | void> | SessionStartHookOutput | void;
|
|
311
|
+
/**
|
|
312
|
+
* Input for session-end hook
|
|
313
|
+
*/
|
|
314
|
+
export interface SessionEndHookInput extends BaseHookInput {
|
|
315
|
+
reason: "complete" | "error" | "abort" | "timeout" | "user_exit";
|
|
316
|
+
finalMessage?: string;
|
|
317
|
+
error?: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Output for session-end hook
|
|
321
|
+
*/
|
|
322
|
+
export interface SessionEndHookOutput {
|
|
323
|
+
suppressOutput?: boolean;
|
|
324
|
+
cleanupActions?: string[];
|
|
325
|
+
sessionSummary?: string;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Handler for session-end hook
|
|
329
|
+
*/
|
|
330
|
+
export type SessionEndHandler = (input: SessionEndHookInput, invocation: {
|
|
331
|
+
sessionId: string;
|
|
332
|
+
}) => Promise<SessionEndHookOutput | void> | SessionEndHookOutput | void;
|
|
333
|
+
/**
|
|
334
|
+
* Input for error-occurred hook
|
|
335
|
+
*/
|
|
336
|
+
export interface ErrorOccurredHookInput extends BaseHookInput {
|
|
337
|
+
error: string;
|
|
338
|
+
errorContext: "model_call" | "tool_execution" | "system" | "user_input";
|
|
339
|
+
recoverable: boolean;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Output for error-occurred hook
|
|
343
|
+
*/
|
|
344
|
+
export interface ErrorOccurredHookOutput {
|
|
345
|
+
suppressOutput?: boolean;
|
|
346
|
+
errorHandling?: "retry" | "skip" | "abort";
|
|
347
|
+
retryCount?: number;
|
|
348
|
+
userNotification?: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Handler for error-occurred hook
|
|
352
|
+
*/
|
|
353
|
+
export type ErrorOccurredHandler = (input: ErrorOccurredHookInput, invocation: {
|
|
354
|
+
sessionId: string;
|
|
355
|
+
}) => Promise<ErrorOccurredHookOutput | void> | ErrorOccurredHookOutput | void;
|
|
356
|
+
/**
|
|
357
|
+
* Configuration for session hooks
|
|
358
|
+
*/
|
|
359
|
+
export interface SessionHooks {
|
|
360
|
+
/**
|
|
361
|
+
* Called before a tool is executed
|
|
362
|
+
*/
|
|
363
|
+
onPreToolUse?: PreToolUseHandler;
|
|
364
|
+
/**
|
|
365
|
+
* Called after a tool is executed
|
|
366
|
+
*/
|
|
367
|
+
onPostToolUse?: PostToolUseHandler;
|
|
368
|
+
/**
|
|
369
|
+
* Called when the user submits a prompt
|
|
370
|
+
*/
|
|
371
|
+
onUserPromptSubmitted?: UserPromptSubmittedHandler;
|
|
372
|
+
/**
|
|
373
|
+
* Called when a session starts
|
|
374
|
+
*/
|
|
375
|
+
onSessionStart?: SessionStartHandler;
|
|
376
|
+
/**
|
|
377
|
+
* Called when a session ends
|
|
378
|
+
*/
|
|
379
|
+
onSessionEnd?: SessionEndHandler;
|
|
380
|
+
/**
|
|
381
|
+
* Called when an error occurs
|
|
382
|
+
*/
|
|
383
|
+
onErrorOccurred?: ErrorOccurredHandler;
|
|
384
|
+
}
|
|
169
385
|
/**
|
|
170
386
|
* Base interface for MCP server configuration.
|
|
171
387
|
*/
|
|
@@ -318,6 +534,21 @@ export interface SessionConfig {
|
|
|
318
534
|
* When provided, the server will call this handler to request permission for operations.
|
|
319
535
|
*/
|
|
320
536
|
onPermissionRequest?: PermissionHandler;
|
|
537
|
+
/**
|
|
538
|
+
* Handler for user input requests from the agent.
|
|
539
|
+
* When provided, enables the ask_user tool allowing the agent to ask questions.
|
|
540
|
+
*/
|
|
541
|
+
onUserInputRequest?: UserInputHandler;
|
|
542
|
+
/**
|
|
543
|
+
* Hook handlers for intercepting session lifecycle events.
|
|
544
|
+
* When provided, enables hooks callback allowing custom logic at various points.
|
|
545
|
+
*/
|
|
546
|
+
hooks?: SessionHooks;
|
|
547
|
+
/**
|
|
548
|
+
* Working directory for the session.
|
|
549
|
+
* Tool operations will be relative to this directory.
|
|
550
|
+
*/
|
|
551
|
+
workingDirectory?: string;
|
|
321
552
|
streaming?: boolean;
|
|
322
553
|
/**
|
|
323
554
|
* MCP server configurations for the session.
|
|
@@ -346,7 +577,14 @@ export interface SessionConfig {
|
|
|
346
577
|
/**
|
|
347
578
|
* Configuration for resuming a session
|
|
348
579
|
*/
|
|
349
|
-
export type ResumeSessionConfig = Pick<SessionConfig, "tools" | "provider" | "streaming" | "onPermissionRequest" | "mcpServers" | "customAgents" | "skillDirectories" | "disabledSkills"
|
|
580
|
+
export type ResumeSessionConfig = Pick<SessionConfig, "tools" | "provider" | "streaming" | "onPermissionRequest" | "onUserInputRequest" | "hooks" | "workingDirectory" | "mcpServers" | "customAgents" | "skillDirectories" | "disabledSkills"> & {
|
|
581
|
+
/**
|
|
582
|
+
* When true, skips emitting the session.resume event.
|
|
583
|
+
* Useful for reconnecting to a session without triggering resume-related side effects.
|
|
584
|
+
* @default false
|
|
585
|
+
*/
|
|
586
|
+
disableResume?: boolean;
|
|
587
|
+
};
|
|
350
588
|
/**
|
|
351
589
|
* Configuration for a custom API provider.
|
|
352
590
|
*/
|
|
@@ -407,7 +645,21 @@ export interface MessageOptions {
|
|
|
407
645
|
mode?: "enqueue" | "immediate";
|
|
408
646
|
}
|
|
409
647
|
/**
|
|
410
|
-
*
|
|
648
|
+
* All possible event type strings from SessionEvent
|
|
649
|
+
*/
|
|
650
|
+
export type SessionEventType = SessionEvent["type"];
|
|
651
|
+
/**
|
|
652
|
+
* Extract the specific event payload for a given event type
|
|
653
|
+
*/
|
|
654
|
+
export type SessionEventPayload<T extends SessionEventType> = Extract<SessionEvent, {
|
|
655
|
+
type: T;
|
|
656
|
+
}>;
|
|
657
|
+
/**
|
|
658
|
+
* Event handler for a specific event type
|
|
659
|
+
*/
|
|
660
|
+
export type TypedSessionEventHandler<T extends SessionEventType> = (event: SessionEventPayload<T>) => void;
|
|
661
|
+
/**
|
|
662
|
+
* Event handler callback type (for all events)
|
|
411
663
|
*/
|
|
412
664
|
export type SessionEventHandler = (event: SessionEvent) => void;
|
|
413
665
|
/**
|
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.20",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"author": "GitHub",
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@github/copilot": "^0.0.
|
|
43
|
+
"@github/copilot": "^0.0.399",
|
|
44
44
|
"vscode-jsonrpc": "^8.2.1",
|
|
45
45
|
"zod": "^4.3.5"
|
|
46
46
|
},
|