@github/copilot-sdk 1.0.0-beta.4 → 1.0.0-beta.5
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 +20 -17
- package/dist/cjs/client.js +32 -35
- package/dist/cjs/generated/rpc.js +1137 -12
- package/dist/cjs/session.js +5 -3
- package/dist/cjs/sessionFsProvider.js +34 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.js +32 -35
- package/dist/generated/rpc.d.ts +8635 -1224
- package/dist/generated/rpc.js +1137 -12
- package/dist/generated/session-events.d.ts +1111 -105
- package/dist/index.d.ts +2 -1
- package/dist/session.d.ts +2 -2
- package/dist/session.js +5 -3
- package/dist/sessionFsProvider.d.ts +28 -1
- package/dist/sessionFsProvider.js +34 -0
- package/dist/types.d.ts +68 -9
- package/docs/examples.md +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
|
32
32
|
const client = new CopilotClient();
|
|
33
33
|
await client.start();
|
|
34
34
|
|
|
35
|
-
// Create a session (onPermissionRequest is
|
|
35
|
+
// Create a session (onPermissionRequest is optional; approveAll allows every tool)
|
|
36
36
|
const session = await client.createSession({
|
|
37
37
|
model: "gpt-5",
|
|
38
38
|
onPermissionRequest: approveAll,
|
|
@@ -115,11 +115,11 @@ Create a new conversation session.
|
|
|
115
115
|
- `sessionId?: string` - Custom session ID.
|
|
116
116
|
- `model?: string` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.). **Required when using custom provider.**
|
|
117
117
|
- `reasoningEffort?: "low" | "medium" | "high" | "xhigh"` - Reasoning effort level for models that support it. Use `listModels()` to check which models support this option.
|
|
118
|
-
- `tools?: Tool[]` - Custom tools exposed to the CLI
|
|
118
|
+
- `tools?: Tool[]` - Custom tools exposed to the CLI. Tools without `handler` are declaration-only and must be resolved via pending tool-call RPCs.
|
|
119
119
|
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
|
|
120
120
|
- `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
|
|
121
121
|
- `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
|
|
122
|
-
- `onPermissionRequest
|
|
122
|
+
- `onPermissionRequest?: PermissionHandler` - Optional handler called before each tool execution to approve or deny it. When omitted, permission requests are emitted as events and left pending for manual resolution. Use `approveAll` to allow everything, or provide a custom function for fine-grained control. See [Permission Handling](#permission-handling) section.
|
|
123
123
|
- `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
|
|
124
124
|
- `onElicitationRequest?: ElicitationHandler` - Handler for elicitation requests dispatched by the server. Enables this client to present form-based UI dialogs on behalf of the agent or other session participants. See [Elicitation Requests](#elicitation-requests) section.
|
|
125
125
|
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
|
|
@@ -128,7 +128,7 @@ Create a new conversation session.
|
|
|
128
128
|
|
|
129
129
|
Resume an existing session. Returns the session with `workspacePath` populated if infinite sessions were enabled.
|
|
130
130
|
|
|
131
|
-
##### `ping(message?: string): Promise<{ message: string; timestamp:
|
|
131
|
+
##### `ping(message?: string): Promise<{ message: string; timestamp: string }>`
|
|
132
132
|
|
|
133
133
|
Ping the server to check connectivity.
|
|
134
134
|
|
|
@@ -802,7 +802,7 @@ Inbound trace context from the CLI is available on the `ToolInvocation` object p
|
|
|
802
802
|
|
|
803
803
|
## Permission Handling
|
|
804
804
|
|
|
805
|
-
An `onPermissionRequest` handler is
|
|
805
|
+
An `onPermissionRequest` handler is optional when you create or resume a session. When provided, it is called before the agent executes each tool (file writes, shell commands, custom tools, etc.) and returns a decision. When omitted, permission requests are emitted as events and left pending for the consumer to resolve with the pending permission RPC.
|
|
806
806
|
|
|
807
807
|
### Approve All (simplest)
|
|
808
808
|
|
|
@@ -843,29 +843,32 @@ const session = await client.createSession({
|
|
|
843
843
|
// request.fullCommandText — full shell command (for shell)
|
|
844
844
|
|
|
845
845
|
if (request.kind === "shell") {
|
|
846
|
-
// Deny shell commands
|
|
847
|
-
return { kind: "
|
|
846
|
+
// Deny shell commands, optionally telling the model why
|
|
847
|
+
return { kind: "reject", feedback: "Shell commands are not allowed." };
|
|
848
848
|
}
|
|
849
849
|
|
|
850
|
-
return { kind: "
|
|
850
|
+
return { kind: "approve-once" };
|
|
851
851
|
},
|
|
852
852
|
});
|
|
853
853
|
```
|
|
854
854
|
|
|
855
855
|
### Permission Result Kinds
|
|
856
856
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
|
860
|
-
|
|
|
861
|
-
| `"
|
|
862
|
-
| `"
|
|
863
|
-
| `"
|
|
864
|
-
| `"
|
|
857
|
+
The handler must return one of the `PermissionDecision` shapes (or `{ kind: "no-result" }`). Approval scopes are present-tense — they describe the decision to apply, not the outcome reported back on session events:
|
|
858
|
+
|
|
859
|
+
| Kind | Meaning | Extra fields |
|
|
860
|
+
| ------------------------ | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
861
|
+
| `"approve-once"` | Allow this single request | — |
|
|
862
|
+
| `"approve-for-session"` | Allow this request and remember the approval for the rest of the session | `approval?` (rule to remember), `domain?` (for URL approvals) |
|
|
863
|
+
| `"approve-for-location"` | Allow this request and persist the approval for this project location (git root or cwd) | `approval` (rule to persist), `locationKey` (location to persist under) |
|
|
864
|
+
| `"approve-permanently"` | Allow this request and persist the approval across sessions (currently used for URL domains) | `domain` (URL domain to approve) |
|
|
865
|
+
| `"reject"` | Deny the request | `feedback?` (optional string surfaced to the agent) |
|
|
866
|
+
| `"user-not-available"` | Deny the request because no user is available to confirm it | — |
|
|
867
|
+
| `"no-result"` | Leave the request unanswered (only valid with protocol v1; rejected by protocol v2 servers) | — |
|
|
865
868
|
|
|
866
869
|
### Resuming Sessions
|
|
867
870
|
|
|
868
|
-
|
|
871
|
+
You may pass `onPermissionRequest` when resuming a session too:
|
|
869
872
|
|
|
870
873
|
```typescript
|
|
871
874
|
const session = await client.resumeSession("session-id", {
|
package/dist/cjs/client.js
CHANGED
|
@@ -272,6 +272,23 @@ class CopilotClient {
|
|
|
272
272
|
throw new Error("sessionFs.conventions must be either 'windows' or 'posix'");
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
+
setupSessionFs(session, config) {
|
|
276
|
+
if (!this.sessionFsConfig) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (!config.createSessionFsHandler) {
|
|
280
|
+
throw new Error(
|
|
281
|
+
"createSessionFsHandler is required in session config when sessionFs is enabled in client options."
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
const provider = config.createSessionFsHandler(session);
|
|
285
|
+
if (this.sessionFsConfig.capabilities?.sqlite && !provider.sqlite) {
|
|
286
|
+
throw new Error(
|
|
287
|
+
"SessionFsConfig declares capabilities.sqlite but the provider does not implement sqlite."
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(provider);
|
|
291
|
+
}
|
|
275
292
|
/**
|
|
276
293
|
* Starts the CLI server and establishes a connection.
|
|
277
294
|
*
|
|
@@ -305,7 +322,8 @@ class CopilotClient {
|
|
|
305
322
|
await this.connection.sendRequest("sessionFs.setProvider", {
|
|
306
323
|
initialCwd: this.sessionFsConfig.initialCwd,
|
|
307
324
|
sessionStatePath: this.sessionFsConfig.sessionStatePath,
|
|
308
|
-
conventions: this.sessionFsConfig.conventions
|
|
325
|
+
conventions: this.sessionFsConfig.conventions,
|
|
326
|
+
capabilities: this.sessionFsConfig.capabilities
|
|
309
327
|
});
|
|
310
328
|
}
|
|
311
329
|
this.state = "connected";
|
|
@@ -502,11 +520,6 @@ class CopilotClient {
|
|
|
502
520
|
* ```
|
|
503
521
|
*/
|
|
504
522
|
async createSession(config) {
|
|
505
|
-
if (!config?.onPermissionRequest) {
|
|
506
|
-
throw new Error(
|
|
507
|
-
"An onPermissionRequest handler is required when creating a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
523
|
if (!this.connection) {
|
|
511
524
|
if (this.options.autoStart) {
|
|
512
525
|
await this.start();
|
|
@@ -549,17 +562,7 @@ class CopilotClient {
|
|
|
549
562
|
session.on(config.onEvent);
|
|
550
563
|
}
|
|
551
564
|
this.sessions.set(sessionId, session);
|
|
552
|
-
|
|
553
|
-
if (config.createSessionFsHandler) {
|
|
554
|
-
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(
|
|
555
|
-
config.createSessionFsHandler(session)
|
|
556
|
-
);
|
|
557
|
-
} else {
|
|
558
|
-
throw new Error(
|
|
559
|
-
"createSessionFsHandler is required in session config when sessionFs is enabled in client options."
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
565
|
+
this.setupSessionFs(session, config);
|
|
563
566
|
try {
|
|
564
567
|
const response = await this.connection.sendRequest("session.create", {
|
|
565
568
|
...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
|
|
@@ -604,7 +607,9 @@ class CopilotClient {
|
|
|
604
607
|
instructionDirectories: config.instructionDirectories,
|
|
605
608
|
disabledSkills: config.disabledSkills,
|
|
606
609
|
infiniteSessions: config.infiniteSessions,
|
|
607
|
-
gitHubToken: config.gitHubToken
|
|
610
|
+
gitHubToken: config.gitHubToken,
|
|
611
|
+
remoteSession: config.remoteSession,
|
|
612
|
+
cloud: config.cloud
|
|
608
613
|
});
|
|
609
614
|
const { workspacePath, capabilities } = response;
|
|
610
615
|
session["_workspacePath"] = workspacePath;
|
|
@@ -640,11 +645,6 @@ class CopilotClient {
|
|
|
640
645
|
* ```
|
|
641
646
|
*/
|
|
642
647
|
async resumeSession(sessionId, config) {
|
|
643
|
-
if (!config?.onPermissionRequest) {
|
|
644
|
-
throw new Error(
|
|
645
|
-
"An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
|
|
646
|
-
);
|
|
647
|
-
}
|
|
648
648
|
if (!this.connection) {
|
|
649
649
|
if (this.options.autoStart) {
|
|
650
650
|
await this.start();
|
|
@@ -686,17 +686,7 @@ class CopilotClient {
|
|
|
686
686
|
session.on(config.onEvent);
|
|
687
687
|
}
|
|
688
688
|
this.sessions.set(sessionId, session);
|
|
689
|
-
|
|
690
|
-
if (config.createSessionFsHandler) {
|
|
691
|
-
session.clientSessionApis.sessionFs = (0, import_sessionFsProvider.createSessionFsAdapter)(
|
|
692
|
-
config.createSessionFsHandler(session)
|
|
693
|
-
);
|
|
694
|
-
} else {
|
|
695
|
-
throw new Error(
|
|
696
|
-
"createSessionFsHandler is required in session config when sessionFs is enabled in client options."
|
|
697
|
-
);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
689
|
+
this.setupSessionFs(session, config);
|
|
700
690
|
try {
|
|
701
691
|
const response = await this.connection.sendRequest("session.resume", {
|
|
702
692
|
...await (0, import_telemetry.getTraceContext)(this.onGetTraceContext),
|
|
@@ -743,7 +733,8 @@ class CopilotClient {
|
|
|
743
733
|
infiniteSessions: config.infiniteSessions,
|
|
744
734
|
disableResume: config.disableResume,
|
|
745
735
|
continuePendingWork: config.continuePendingWork,
|
|
746
|
-
gitHubToken: config.gitHubToken
|
|
736
|
+
gitHubToken: config.gitHubToken,
|
|
737
|
+
remoteSession: config.remoteSession
|
|
747
738
|
});
|
|
748
739
|
const { workspacePath, capabilities } = response;
|
|
749
740
|
session["_workspacePath"] = workspacePath;
|
|
@@ -1314,7 +1305,12 @@ stderr: ${stderrOutput}`
|
|
|
1314
1305
|
}
|
|
1315
1306
|
return new Promise((resolve, reject) => {
|
|
1316
1307
|
this.socket = new import_node_net.Socket();
|
|
1308
|
+
const connectionTimeout = setTimeout(() => {
|
|
1309
|
+
this.socket?.destroy();
|
|
1310
|
+
reject(new Error("Timeout connecting to CLI server"));
|
|
1311
|
+
}, 1e4);
|
|
1317
1312
|
this.socket.connect(this.actualPort, this.actualHost, () => {
|
|
1313
|
+
clearTimeout(connectionTimeout);
|
|
1318
1314
|
this.connection = (0, import_node.createMessageConnection)(
|
|
1319
1315
|
new import_node.StreamMessageReader(this.socket),
|
|
1320
1316
|
new import_node.StreamMessageWriter(this.socket)
|
|
@@ -1324,6 +1320,7 @@ stderr: ${stderrOutput}`
|
|
|
1324
1320
|
resolve();
|
|
1325
1321
|
});
|
|
1326
1322
|
this.socket.on("error", (error) => {
|
|
1323
|
+
clearTimeout(connectionTimeout);
|
|
1327
1324
|
reject(new Error(`Failed to connect to CLI server: ${error.message}`));
|
|
1328
1325
|
});
|
|
1329
1326
|
});
|