@github/copilot-sdk 1.0.0-beta.1 → 1.0.0-beta.11
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 +61 -48
- package/dist/canvas.d.ts +126 -0
- package/dist/canvas.js +49 -0
- package/dist/cjs/canvas.js +75 -0
- package/dist/cjs/client.js +540 -299
- package/dist/cjs/extension.js +12 -3
- package/dist/cjs/generated/rpc.js +1332 -15
- package/dist/cjs/index.js +22 -7
- package/dist/cjs/session.js +179 -93
- package/dist/cjs/sessionFsProvider.js +34 -0
- package/dist/cjs/toolSet.js +107 -0
- package/dist/cjs/types.js +38 -4
- package/dist/client.d.ts +63 -73
- package/dist/client.js +541 -300
- package/dist/extension.d.ts +4 -2
- package/dist/extension.js +13 -3
- package/dist/generated/rpc.d.ts +10205 -994
- package/dist/generated/rpc.js +1332 -15
- package/dist/generated/session-events.d.ts +2061 -194
- package/dist/index.d.ts +6 -2
- package/dist/index.js +15 -2
- package/dist/session.d.ts +19 -186
- package/dist/session.js +179 -92
- package/dist/sessionFsProvider.d.ts +29 -2
- package/dist/sessionFsProvider.js +34 -0
- package/dist/toolSet.d.ts +75 -0
- package/dist/toolSet.js +82 -0
- package/dist/types.d.ts +753 -123
- package/dist/types.js +36 -3
- package/docs/agent-author.md +31 -7
- package/docs/examples.md +29 -19
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript SDK for programmatic control of GitHub Copilot CLI via JSON-RPC.
|
|
4
4
|
|
|
5
|
-
> **Note:** This SDK is in public preview and may change in breaking ways.
|
|
6
|
-
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
@@ -32,13 +30,13 @@ import { CopilotClient, approveAll } from "@github/copilot-sdk";
|
|
|
32
30
|
const client = new CopilotClient();
|
|
33
31
|
await client.start();
|
|
34
32
|
|
|
35
|
-
// Create a session (onPermissionRequest is
|
|
33
|
+
// Create a session (onPermissionRequest is optional; approveAll allows every tool)
|
|
36
34
|
const session = await client.createSession({
|
|
37
35
|
model: "gpt-5",
|
|
38
36
|
onPermissionRequest: approveAll,
|
|
39
37
|
});
|
|
40
38
|
|
|
41
|
-
// Wait for response using typed event handlers
|
|
39
|
+
// Wait for the response using typed event handlers
|
|
42
40
|
const done = new Promise<void>((resolve) => {
|
|
43
41
|
session.on("assistant.message", (event) => {
|
|
44
42
|
console.log(event.data.content);
|
|
@@ -57,7 +55,7 @@ await session.disconnect();
|
|
|
57
55
|
await client.stop();
|
|
58
56
|
```
|
|
59
57
|
|
|
60
|
-
Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2
|
|
58
|
+
Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2+ / Node.js 20+):
|
|
61
59
|
|
|
62
60
|
```typescript
|
|
63
61
|
await using session = await client.createSession({
|
|
@@ -79,18 +77,23 @@ new CopilotClient(options?: CopilotClientOptions)
|
|
|
79
77
|
|
|
80
78
|
**Options:**
|
|
81
79
|
|
|
82
|
-
- `
|
|
83
|
-
- `
|
|
84
|
-
- `
|
|
85
|
-
- `
|
|
86
|
-
- `
|
|
87
|
-
- `
|
|
88
|
-
- `
|
|
80
|
+
- `connection?: RuntimeConnection` - How to connect to the Copilot runtime. Construct via the factory functions on `RuntimeConnection`:
|
|
81
|
+
- `RuntimeConnection.forStdio({ path?, args? })` (default) — spawn the runtime and communicate over its stdin/stdout.
|
|
82
|
+
- `RuntimeConnection.forTcp({ port?, connectionToken?, path?, args? })` — spawn the runtime as a TCP server.
|
|
83
|
+
- `RuntimeConnection.forUri(url, { connectionToken? })` — connect to an already-running runtime (mutually exclusive with `gitHubToken`/`useLoggedInUser`). There is no top-level `cliUrl` shortcut; use this factory for URL-based connections.
|
|
84
|
+
- `mode?: "empty" | "copilot-cli"` - Defaulting strategy. Use `"empty"` for multi-user server mode; defaults to `"copilot-cli"`.
|
|
85
|
+
- `workingDirectory?: string` - Working directory for the runtime process (default: current process cwd).
|
|
86
|
+
- `baseDirectory?: string` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned runtime. When not set, the runtime defaults to `~/.copilot`. Ignored when connecting via `RuntimeConnection.forUri`.
|
|
87
|
+
- `logLevel?: "none" | "error" | "warning" | "info" | "debug" | "all"` - Log level. When omitted, the runtime uses its own default (currently `"info"`).
|
|
88
|
+
- `env?: Record<string, string | undefined>` - Environment variables for the runtime process. When omitted, inherits `process.env`.
|
|
89
89
|
- `gitHubToken?: string` - GitHub token for authentication. When provided, takes priority over other auth methods.
|
|
90
|
-
- `useLoggedInUser?: boolean` - Whether to use logged-in user for authentication (default: true, but false when `gitHubToken` is provided). Cannot be used with `
|
|
91
|
-
- `
|
|
92
|
-
- `telemetry?: TelemetryConfig` - OpenTelemetry configuration for the
|
|
93
|
-
- `onGetTraceContext?: TraceContextProvider` - Advanced: callback for linking your application's own OpenTelemetry spans into the same distributed trace as the
|
|
90
|
+
- `useLoggedInUser?: boolean` - Whether to use logged-in user for authentication (default: true, but false when `gitHubToken` is provided). Cannot be used with `RuntimeConnection.forUri`.
|
|
91
|
+
- `onListModels?: () => Promise<ModelInfo[]> | ModelInfo[]` - Optional model-list provider, useful when using a custom provider.
|
|
92
|
+
- `telemetry?: TelemetryConfig` - OpenTelemetry configuration for the runtime process. Providing this object enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below.
|
|
93
|
+
- `onGetTraceContext?: TraceContextProvider` - Advanced: callback for linking your application's own OpenTelemetry spans into the same distributed trace as the runtime's spans. Not needed for normal telemetry collection. See [Telemetry](#telemetry) below.
|
|
94
|
+
- `sessionFs?: SessionFsConfig` - Custom session filesystem provider.
|
|
95
|
+
- `sessionIdleTimeoutSeconds?: number` - Server-wide idle timeout for sessions in seconds. Ignored when connecting via `RuntimeConnection.forUri`.
|
|
96
|
+
- `enableRemoteSessions?: boolean` - Enable Mission Control remote session support. Ignored when connecting via `RuntimeConnection.forUri`.
|
|
94
97
|
|
|
95
98
|
#### Methods
|
|
96
99
|
|
|
@@ -115,11 +118,11 @@ Create a new conversation session.
|
|
|
115
118
|
- `sessionId?: string` - Custom session ID.
|
|
116
119
|
- `model?: string` - Model to use ("gpt-5", "claude-sonnet-4.5", etc.). **Required when using custom provider.**
|
|
117
120
|
- `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
|
|
121
|
+
- `tools?: Tool[]` - Custom tools exposed to the CLI. Tools without `handler` are declaration-only and must be resolved via pending tool-call RPCs.
|
|
119
122
|
- `systemMessage?: SystemMessageConfig` - System message customization (see below)
|
|
120
123
|
- `infiniteSessions?: InfiniteSessionConfig` - Configure automatic context compaction (see below)
|
|
121
124
|
- `provider?: ProviderConfig` - Custom API provider configuration (BYOK - Bring Your Own Key). See [Custom Providers](#custom-providers) section.
|
|
122
|
-
- `onPermissionRequest
|
|
125
|
+
- `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
126
|
- `onUserInputRequest?: UserInputHandler` - Handler for user input requests from the agent. Enables the `ask_user` tool. See [User Input Requests](#user-input-requests) section.
|
|
124
127
|
- `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
128
|
- `hooks?: SessionHooks` - Hook handlers for session lifecycle events. See [Session Hooks](#session-hooks) section.
|
|
@@ -128,14 +131,10 @@ Create a new conversation session.
|
|
|
128
131
|
|
|
129
132
|
Resume an existing session. Returns the session with `workspacePath` populated if infinite sessions were enabled.
|
|
130
133
|
|
|
131
|
-
##### `ping(message?: string): Promise<{ message: string; timestamp:
|
|
134
|
+
##### `ping(message?: string): Promise<{ message: string; timestamp: string }>`
|
|
132
135
|
|
|
133
136
|
Ping the server to check connectivity.
|
|
134
137
|
|
|
135
|
-
##### `getState(): ConnectionState`
|
|
136
|
-
|
|
137
|
-
Get current connection state.
|
|
138
|
-
|
|
139
138
|
##### `listSessions(filter?: SessionListFilter): Promise<SessionMetadata[]>`
|
|
140
139
|
|
|
141
140
|
List all available sessions. Optionally filter by working directory context.
|
|
@@ -168,22 +167,22 @@ Get the ID of the session currently displayed in the TUI. Only available when co
|
|
|
168
167
|
|
|
169
168
|
Request the TUI to switch to displaying the specified session. Only available in TUI+server mode.
|
|
170
169
|
|
|
171
|
-
##### `
|
|
170
|
+
##### `onLifecycle(eventType: SessionLifecycleEventType, handler): () => void`
|
|
172
171
|
|
|
173
172
|
Subscribe to a specific session lifecycle event type. Returns an unsubscribe function.
|
|
174
173
|
|
|
175
174
|
```typescript
|
|
176
|
-
const unsubscribe = client.
|
|
175
|
+
const unsubscribe = client.onLifecycle("session.foreground", (event) => {
|
|
177
176
|
console.log(`Session ${event.sessionId} is now in foreground`);
|
|
178
177
|
});
|
|
179
178
|
```
|
|
180
179
|
|
|
181
|
-
##### `
|
|
180
|
+
##### `onLifecycle(handler: SessionLifecycleHandler): () => void`
|
|
182
181
|
|
|
183
182
|
Subscribe to all session lifecycle events. Returns an unsubscribe function.
|
|
184
183
|
|
|
185
184
|
```typescript
|
|
186
|
-
const unsubscribe = client.
|
|
185
|
+
const unsubscribe = client.onLifecycle((event) => {
|
|
187
186
|
console.log(`${event.type}: ${event.sessionId}`);
|
|
188
187
|
});
|
|
189
188
|
```
|
|
@@ -277,7 +276,7 @@ unsubscribe();
|
|
|
277
276
|
|
|
278
277
|
Abort the currently processing message in this session.
|
|
279
278
|
|
|
280
|
-
##### `
|
|
279
|
+
##### `getEvents(): Promise<SessionEvent[]>`
|
|
281
280
|
|
|
282
281
|
Get all events/messages from this session.
|
|
283
282
|
|
|
@@ -415,7 +414,7 @@ Note: `assistant.message` and `assistant.reasoning` (final events) are always se
|
|
|
415
414
|
### Manual Server Control
|
|
416
415
|
|
|
417
416
|
```typescript
|
|
418
|
-
const client = new CopilotClient({
|
|
417
|
+
const client = new CopilotClient({});
|
|
419
418
|
|
|
420
419
|
// Start manually
|
|
421
420
|
await client.start();
|
|
@@ -574,8 +573,8 @@ The SDK auto-injects environment context, tool instructions, and security guardr
|
|
|
574
573
|
Use `mode: "customize"` to selectively override individual sections of the prompt while preserving the rest:
|
|
575
574
|
|
|
576
575
|
```typescript
|
|
577
|
-
import {
|
|
578
|
-
import type { SectionOverride,
|
|
576
|
+
import { SYSTEM_MESSAGE_SECTIONS } from "@github/copilot-sdk";
|
|
577
|
+
import type { SectionOverride, SystemMessageSection } from "@github/copilot-sdk";
|
|
579
578
|
|
|
580
579
|
const session = await client.createSession({
|
|
581
580
|
model: "gpt-5",
|
|
@@ -598,7 +597,7 @@ const session = await client.createSession({
|
|
|
598
597
|
});
|
|
599
598
|
```
|
|
600
599
|
|
|
601
|
-
Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `last_instructions`. Use the `
|
|
600
|
+
Available section IDs: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, `runtime_instructions`, `last_instructions`. Use the `SYSTEM_MESSAGE_SECTIONS` constant for descriptions of each section.
|
|
602
601
|
|
|
603
602
|
Each section override supports four actions:
|
|
604
603
|
|
|
@@ -802,7 +801,7 @@ Inbound trace context from the CLI is available on the `ToolInvocation` object p
|
|
|
802
801
|
|
|
803
802
|
## Permission Handling
|
|
804
803
|
|
|
805
|
-
An `onPermissionRequest` handler is
|
|
804
|
+
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
805
|
|
|
807
806
|
### Approve All (simplest)
|
|
808
807
|
|
|
@@ -843,29 +842,32 @@ const session = await client.createSession({
|
|
|
843
842
|
// request.fullCommandText — full shell command (for shell)
|
|
844
843
|
|
|
845
844
|
if (request.kind === "shell") {
|
|
846
|
-
// Deny shell commands
|
|
847
|
-
return { kind: "
|
|
845
|
+
// Deny shell commands, optionally telling the model why
|
|
846
|
+
return { kind: "reject", feedback: "Shell commands are not allowed." };
|
|
848
847
|
}
|
|
849
848
|
|
|
850
|
-
return { kind: "
|
|
849
|
+
return { kind: "approve-once" };
|
|
851
850
|
},
|
|
852
851
|
});
|
|
853
852
|
```
|
|
854
853
|
|
|
855
854
|
### Permission Result Kinds
|
|
856
855
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
|
860
|
-
|
|
|
861
|
-
| `"
|
|
862
|
-
| `"
|
|
863
|
-
| `"
|
|
864
|
-
| `"
|
|
856
|
+
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:
|
|
857
|
+
|
|
858
|
+
| Kind | Meaning | Extra fields |
|
|
859
|
+
| ------------------------ | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
860
|
+
| `"approve-once"` | Allow this single request | — |
|
|
861
|
+
| `"approve-for-session"` | Allow this request and remember the approval for the rest of the session | `approval?` (rule to remember), `domain?` (for URL approvals) |
|
|
862
|
+
| `"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) |
|
|
863
|
+
| `"approve-permanently"` | Allow this request and persist the approval across sessions (currently used for URL domains) | `domain` (URL domain to approve) |
|
|
864
|
+
| `"reject"` | Deny the request | `feedback?` (optional string surfaced to the agent) |
|
|
865
|
+
| `"user-not-available"` | Deny the request because no user is available to confirm it | — |
|
|
866
|
+
| `"no-result"` | Leave the request unanswered (only valid with protocol v1; rejected by protocol v2 servers) | — |
|
|
865
867
|
|
|
866
868
|
### Resuming Sessions
|
|
867
869
|
|
|
868
|
-
|
|
870
|
+
You may pass `onPermissionRequest` when resuming a session too:
|
|
869
871
|
|
|
870
872
|
```typescript
|
|
871
873
|
const session = await client.resumeSession("session-id", {
|
|
@@ -959,7 +961,7 @@ const session = await client.createSession({
|
|
|
959
961
|
};
|
|
960
962
|
},
|
|
961
963
|
|
|
962
|
-
// Called after each tool execution
|
|
964
|
+
// Called after each successful tool execution
|
|
963
965
|
onPostToolUse: async (input, invocation) => {
|
|
964
966
|
console.log(`Tool ${input.toolName} completed`);
|
|
965
967
|
// Optionally modify the result or add context
|
|
@@ -968,6 +970,16 @@ const session = await client.createSession({
|
|
|
968
970
|
};
|
|
969
971
|
},
|
|
970
972
|
|
|
973
|
+
// Called after a tool execution whose result was "failure".
|
|
974
|
+
// onPostToolUse does NOT fire for failed tool calls — register this
|
|
975
|
+
// hook to observe them. Input includes `error` (the failure message
|
|
976
|
+
// extracted from the tool's result), not the full result object.
|
|
977
|
+
onPostToolUseFailure: async (input, invocation) => {
|
|
978
|
+
console.log(`Tool ${input.toolName} failed: ${input.error}`);
|
|
979
|
+
// Optionally append hidden guidance to the model.
|
|
980
|
+
return { additionalContext: "Suggest checking inputs and retrying." };
|
|
981
|
+
},
|
|
982
|
+
|
|
971
983
|
// Called when user submits a prompt
|
|
972
984
|
onUserPromptSubmitted: async (input, invocation) => {
|
|
973
985
|
console.log(`User prompt: ${input.prompt}`);
|
|
@@ -1003,7 +1015,8 @@ const session = await client.createSession({
|
|
|
1003
1015
|
**Available hooks:**
|
|
1004
1016
|
|
|
1005
1017
|
- `onPreToolUse` - Intercept tool calls before execution. Can allow/deny or modify arguments.
|
|
1006
|
-
- `onPostToolUse` - Process tool results after execution. Can modify results or add context.
|
|
1018
|
+
- `onPostToolUse` - Process tool results after **successful** execution. Can modify results or add context.
|
|
1019
|
+
- `onPostToolUseFailure` - Observe and append hidden guidance to the model after tool executions whose result was `"failure"`. Register this in addition to `onPostToolUse` to see failed tool calls.
|
|
1007
1020
|
- `onUserPromptSubmitted` - Intercept user prompts. Can modify the prompt before processing.
|
|
1008
1021
|
- `onSessionStart` - Run logic when a session starts or resumes.
|
|
1009
1022
|
- `onSessionEnd` - Cleanup or logging when session ends.
|
|
@@ -1023,7 +1036,7 @@ try {
|
|
|
1023
1036
|
## Requirements
|
|
1024
1037
|
|
|
1025
1038
|
- Node.js >= 18.0.0
|
|
1026
|
-
- GitHub Copilot CLI installed and in PATH (or provide custom `
|
|
1039
|
+
- GitHub Copilot CLI installed and in PATH (or provide a custom `connection`)
|
|
1027
1040
|
|
|
1028
1041
|
## License
|
|
1029
1042
|
|
package/dist/canvas.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { CanvasJsonSchema, CanvasProviderCloseRequest, CanvasProviderInvokeActionRequest, CanvasProviderOpenRequest, CanvasProviderOpenResult } from "./generated/rpc.js";
|
|
2
|
+
export type { CanvasJsonSchema, CanvasHostContext, CanvasHostContextCapabilities, } from "./generated/rpc.js";
|
|
3
|
+
/**
|
|
4
|
+
* Extension-owned canvases declared via
|
|
5
|
+
* `joinSession({ canvases: [createCanvas({...})] })`.
|
|
6
|
+
*
|
|
7
|
+
* The runtime sends provider callbacks as `canvas.open`, `canvas.close`, and
|
|
8
|
+
* `canvas.action.invoke` JSON-RPC requests via the codegen client session API
|
|
9
|
+
* pipeline. The SDK routes those requests by `canvasId` to the in-process
|
|
10
|
+
* handlers bound by `createCanvas`. Re-opening with an existing `instanceId`
|
|
11
|
+
* is how the host focuses an existing panel; reload is a renderer-only concern.
|
|
12
|
+
*
|
|
13
|
+
* @experimental Canvas types are part of an experimental wire-protocol surface
|
|
14
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* A single agent-callable action contributed by a canvas. The metadata
|
|
18
|
+
* (`name`, `description`, `inputSchema`) is serialized over the wire on
|
|
19
|
+
* `session.create` / `session.resume`; the `handler` closure is stripped
|
|
20
|
+
* before the declaration is sent and dispatched in-process by the SDK.
|
|
21
|
+
*
|
|
22
|
+
* Names MUST NOT start with `canvas.` — that prefix is reserved for
|
|
23
|
+
* lifecycle verbs.
|
|
24
|
+
*
|
|
25
|
+
* @experimental This type is part of an experimental wire-protocol surface
|
|
26
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
27
|
+
*/
|
|
28
|
+
export interface CanvasAction {
|
|
29
|
+
/** Action identifier, unique within the canvas. */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Description shown to the model when picking an action. */
|
|
32
|
+
description?: string;
|
|
33
|
+
/** Optional JSON Schema for the action's `input` payload. */
|
|
34
|
+
inputSchema?: CanvasJsonSchema;
|
|
35
|
+
/** Required per-action dispatch handler. */
|
|
36
|
+
handler: (ctx: CanvasProviderInvokeActionRequest) => Promise<unknown> | unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Declarative metadata for a single canvas, serialized over the wire on
|
|
40
|
+
* `session.create` / `session.resume`.
|
|
41
|
+
*
|
|
42
|
+
* @experimental This type is part of an experimental wire-protocol surface
|
|
43
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
44
|
+
*/
|
|
45
|
+
export interface CanvasDeclaration {
|
|
46
|
+
/** Canvas id, unique within the declaring connection. */
|
|
47
|
+
id: string;
|
|
48
|
+
/** Human-readable label shown in discovery and host UI chrome. */
|
|
49
|
+
displayName: string;
|
|
50
|
+
/** Short, single-sentence description shown to the agent in canvas catalogs. */
|
|
51
|
+
description: string;
|
|
52
|
+
/** Optional JSON Schema for the `input` payload accepted by `canvas.open`. */
|
|
53
|
+
inputSchema?: CanvasJsonSchema;
|
|
54
|
+
/** Agent-invocable actions exposed via `invoke_canvas_action`. */
|
|
55
|
+
actions?: Omit<CanvasAction, "handler">[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Structured error returned from canvas handlers.
|
|
59
|
+
*
|
|
60
|
+
* @experimental This class is part of an experimental wire-protocol surface
|
|
61
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
62
|
+
*/
|
|
63
|
+
export declare class CanvasError extends Error {
|
|
64
|
+
readonly code: string;
|
|
65
|
+
constructor(code: string, message: string);
|
|
66
|
+
/** Default error when an action is declared but no `handler` is wired. */
|
|
67
|
+
static noHandler(): CanvasError;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Options accepted by {@link createCanvas}. Combines the declarative
|
|
71
|
+
* {@link CanvasDeclaration} fields with the in-process handler closures.
|
|
72
|
+
*
|
|
73
|
+
* @experimental This interface is part of an experimental wire-protocol surface
|
|
74
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
75
|
+
*/
|
|
76
|
+
export interface CanvasOptions {
|
|
77
|
+
/** @see CanvasDeclaration.id */
|
|
78
|
+
id: string;
|
|
79
|
+
/** @see CanvasDeclaration.displayName */
|
|
80
|
+
displayName: string;
|
|
81
|
+
/** @see CanvasDeclaration.description */
|
|
82
|
+
description: string;
|
|
83
|
+
/** @see CanvasDeclaration.inputSchema */
|
|
84
|
+
inputSchema?: CanvasJsonSchema;
|
|
85
|
+
/**
|
|
86
|
+
* Agent-invocable actions exposed via `invoke_canvas_action`. Each action
|
|
87
|
+
* carries its own required `handler`; the action's wire metadata
|
|
88
|
+
* (`name`, `description`, `inputSchema`) is what reaches the runtime.
|
|
89
|
+
*/
|
|
90
|
+
actions?: CanvasAction[];
|
|
91
|
+
/** Required. Open a new canvas instance. */
|
|
92
|
+
open: (ctx: CanvasProviderOpenRequest) => Promise<CanvasProviderOpenResult> | CanvasProviderOpenResult;
|
|
93
|
+
/**
|
|
94
|
+
* Optional. Notified when a canvas instance is closed by the user, the
|
|
95
|
+
* agent, or the host. Fire-and-forget: the return value is ignored and
|
|
96
|
+
* errors are logged but not surfaced to the runtime.
|
|
97
|
+
*/
|
|
98
|
+
onClose?: (ctx: CanvasProviderCloseRequest) => Promise<void> | void;
|
|
99
|
+
}
|
|
100
|
+
/** A registered canvas: declarative metadata + in-process handler closures.
|
|
101
|
+
*
|
|
102
|
+
* Node intentionally uses a per-canvas factory pattern (mirroring
|
|
103
|
+
* {@link https://github.com/github/copilot-sdk | `DefineTool`}'s co-location
|
|
104
|
+
* ergonomics) where other SDKs (Rust, Python, Go, .NET) expose a single
|
|
105
|
+
* `CanvasHandler` per session that switches on `canvasId`. Both shapes target
|
|
106
|
+
* the same JSON-RPC wire protocol; the divergence is API ergonomics only.
|
|
107
|
+
*
|
|
108
|
+
* @experimental This class is part of an experimental wire-protocol surface
|
|
109
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
110
|
+
*/
|
|
111
|
+
export declare class Canvas {
|
|
112
|
+
readonly declaration: CanvasDeclaration;
|
|
113
|
+
readonly open: NonNullable<CanvasOptions["open"]>;
|
|
114
|
+
readonly onClose?: CanvasOptions["onClose"];
|
|
115
|
+
}
|
|
116
|
+
/** Create a canvas declaration with bound in-process handlers.
|
|
117
|
+
*
|
|
118
|
+
* Node intentionally uses this per-canvas factory pattern (mirroring
|
|
119
|
+
* `DefineTool`'s co-location ergonomics) where other SDKs (Rust, Python, Go,
|
|
120
|
+
* .NET) expose a single `CanvasHandler` per session that switches on
|
|
121
|
+
* `canvasId`. Both shapes target the same JSON-RPC wire protocol.
|
|
122
|
+
*
|
|
123
|
+
* @experimental This function is part of an experimental wire-protocol surface
|
|
124
|
+
* and may change or be removed in future SDK or CLI releases.
|
|
125
|
+
*/
|
|
126
|
+
export declare function createCanvas(options: CanvasOptions): Canvas;
|
package/dist/canvas.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class CanvasError extends Error {
|
|
2
|
+
constructor(code, message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.code = code;
|
|
5
|
+
this.name = "CanvasError";
|
|
6
|
+
}
|
|
7
|
+
/** Default error when an action is declared but no `handler` is wired. */
|
|
8
|
+
static noHandler() {
|
|
9
|
+
return new CanvasError(
|
|
10
|
+
"canvas_action_no_handler",
|
|
11
|
+
"No handler implemented for this canvas action"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
class Canvas {
|
|
16
|
+
declaration;
|
|
17
|
+
open;
|
|
18
|
+
onClose;
|
|
19
|
+
/** @internal */
|
|
20
|
+
actionHandlers;
|
|
21
|
+
/** @internal */
|
|
22
|
+
constructor(options) {
|
|
23
|
+
const actionHandlers = /* @__PURE__ */ new Map();
|
|
24
|
+
const wireActions = options.actions?.map(
|
|
25
|
+
({ handler, ...wire }) => {
|
|
26
|
+
actionHandlers.set(wire.name, handler);
|
|
27
|
+
return wire;
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
this.declaration = {
|
|
31
|
+
id: options.id,
|
|
32
|
+
displayName: options.displayName,
|
|
33
|
+
description: options.description,
|
|
34
|
+
inputSchema: options.inputSchema,
|
|
35
|
+
actions: wireActions
|
|
36
|
+
};
|
|
37
|
+
this.open = options.open;
|
|
38
|
+
this.onClose = options.onClose;
|
|
39
|
+
this.actionHandlers = actionHandlers;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function createCanvas(options) {
|
|
43
|
+
return new Canvas(options);
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
Canvas,
|
|
47
|
+
CanvasError,
|
|
48
|
+
createCanvas
|
|
49
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var canvas_exports = {};
|
|
20
|
+
__export(canvas_exports, {
|
|
21
|
+
Canvas: () => Canvas,
|
|
22
|
+
CanvasError: () => CanvasError,
|
|
23
|
+
createCanvas: () => createCanvas
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(canvas_exports);
|
|
26
|
+
class CanvasError extends Error {
|
|
27
|
+
constructor(code, message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.name = "CanvasError";
|
|
31
|
+
}
|
|
32
|
+
/** Default error when an action is declared but no `handler` is wired. */
|
|
33
|
+
static noHandler() {
|
|
34
|
+
return new CanvasError(
|
|
35
|
+
"canvas_action_no_handler",
|
|
36
|
+
"No handler implemented for this canvas action"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
class Canvas {
|
|
41
|
+
declaration;
|
|
42
|
+
open;
|
|
43
|
+
onClose;
|
|
44
|
+
/** @internal */
|
|
45
|
+
actionHandlers;
|
|
46
|
+
/** @internal */
|
|
47
|
+
constructor(options) {
|
|
48
|
+
const actionHandlers = /* @__PURE__ */ new Map();
|
|
49
|
+
const wireActions = options.actions?.map(
|
|
50
|
+
({ handler, ...wire }) => {
|
|
51
|
+
actionHandlers.set(wire.name, handler);
|
|
52
|
+
return wire;
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
this.declaration = {
|
|
56
|
+
id: options.id,
|
|
57
|
+
displayName: options.displayName,
|
|
58
|
+
description: options.description,
|
|
59
|
+
inputSchema: options.inputSchema,
|
|
60
|
+
actions: wireActions
|
|
61
|
+
};
|
|
62
|
+
this.open = options.open;
|
|
63
|
+
this.onClose = options.onClose;
|
|
64
|
+
this.actionHandlers = actionHandlers;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function createCanvas(options) {
|
|
68
|
+
return new Canvas(options);
|
|
69
|
+
}
|
|
70
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
71
|
+
0 && (module.exports = {
|
|
72
|
+
Canvas,
|
|
73
|
+
CanvasError,
|
|
74
|
+
createCanvas
|
|
75
|
+
});
|