Skip to content

Commit 8272a2a

Browse files
TypeScript SDK API review fixes (#1357)
* Phase A: property/method renames on SessionConfig/ResumeSessionConfig Mirrors C# PR #1343 Phase 4a renames: - onExitPlanMode -> onExitPlanModeRequest - onAutoModeSwitch -> onAutoModeSwitchRequest - createSessionFsHandler -> createSessionFsProvider - ResumeSessionConfig.disableResume -> suppressResumeEvent - ProviderConfig.maxInputTokens -> maxPromptTokens (drops the wire shim) - CopilotSession.getMessages() -> getEvents() - InputOptions -> UiInputOptions Wire RPC name 'session.getMessages' is unchanged (runtime contract). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase C: CopilotClientOptions / MCP / streaming shape changes - Remove autoStart and autoRestart from CopilotClientOptions. The client now always starts on first createSession/resumeSession; users can still call client.start() explicitly for eager startup. - Make MCPServerConfigBase.tools optional (undefined = all, [] = none). - Fix streaming JSDoc block comment that wasn't attached due to single-star. Mirrors C# PR #1343 Phase 4c. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase D: lifecycle event polymorphic union + Date timestamps - Split SessionLifecycleEvent into a discriminated union of SessionCreatedEvent / SessionDeletedEvent / SessionUpdatedEvent / SessionForegroundEvent / SessionBackgroundEvent. - Promote the metadata payload into a named SessionLifecycleEventMetadata interface; metadata is required on non-delete variants and absent on session.deleted. - Convert metadata.startTime and metadata.modifiedTime from string to Date, matching SessionMetadata. Parse on receipt in client.handleSessionLifecycleNotification. - Export the new variant types from index.ts. Mirrors C# PR #1343 Phase 4f + review §2.3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase E: hook input timestamps as Date - Change BaseHookInput.timestamp from number (Unix ms) to Date. - Parse incoming numeric timestamps into Date in handleHooksInvoke. - Update hooks_extended.e2e.test.ts assertion accordingly. Mirrors C# PR #1343 Phase 4g. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase F: PermissionRequestResult.feedback + use generated PermissionRequest union - Add optional feedback?: string field to PermissionRequestResult so consumers can return free-form text forwarded to the model with the decision. - Delete the hand-written narrow PermissionRequest interface in types.ts and re-export the generated discriminated union from session-events.ts instead. Handlers can now type-safely access per-kind fields (e.g. shell .commands, write .fileName / .diff, mcp .toolName / .args). Mirrors C# PR #1343 Phase 4g + review §2.9. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase G: extract SessionConfigBase Replaces the fragile Pick<SessionConfig, '...30+ keys...'> definition for ResumeSessionConfig with a shared SessionConfigBase interface. SessionConfig and ResumeSessionConfig now both extend it: - SessionConfig adds sessionId? and cloud?. - ResumeSessionConfig adds suppressResumeEvent? and continuePendingWork?. SessionConfigBase is exported from index.ts for consumers that want to build shared helpers over both shapes. Mirrors C# PR #1343 Phase 5 + review §2.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase H: defineTool({ name, ... }) single-arg form Change defineTool from defineTool(name, config) to defineTool({ name, ...config }) so the call shape matches the Tool<T> interface. name remains mandatory and is enforced by the Tool<T> type. Updates all samples, docs, tests, and the CHANGELOG snippet. Review §1.3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert "Phase H: defineTool({ name, ... }) single-arg form" This reverts commit 49da911. * Phase I: RuntimeConnection discriminated config Replaces the flat connection-related fields on CopilotClientOptions (cliPath, cliArgs, port, useStdio, cliUrl, tcpConnectionToken, isChildProcess) with a single discriminated 'connection?: RuntimeConnection' field. Construct values via factory functions: RuntimeConnection.forStdio({ path?, args? }) // default RuntimeConnection.forTcp({ port?, connectionToken?, path?, args? }) RuntimeConnection.forUri(url, { connectionToken? }) The mutually-exclusive combinations that used to be runtime errors are now caught at compile time by the discriminated union. The previous isChildProcess flag (only ever used by joinSession() in extension.ts) is dropped from the public API surface; extension.ts now uses an @internal _internalConnection hook to enter the parent-process stdio mode. Other renames in this phase: - CopilotClientOptions.copilotHome -> baseDirectory. - Internal CopilotClient.actualPort field -> runtimePort. All TS test files, scenario fixtures, samples, README, and docs updated to the new shape. Mirrors C# PR #1343 Phase 9. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase J: send / sendAndWait string overloads Both methods now accept either a MessageOptions object or just a string prompt. The string form is a shorthand for { prompt }: await session.send('Hello'); await session.sendAndWait('Hello'); Mirrors C# PR #1343 Phase 7. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase K: stripInternal, AsyncDisposable, clean stop(), drop destroy() - Enable stripInternal in tsconfig.json so @internal members no longer appear in the published .d.ts. Verified that CopilotSession constructor, the register*/clientSessionApis hooks, _handle* methods, NO_RESULT_PERMISSION_V2_ERROR, _internalConnection, and ParentProcessRuntimeConnection are all stripped from the public types. The MessageConnection import from vscode-jsonrpc no longer leaks either. - Tag NO_RESULT_PERMISSION_V2_ERROR with @internal explicitly. - Implement Symbol.asyncDispose on CopilotClient so it works inside 'await using' blocks, matching CopilotSession. - Tighten client.stop() so the Node process can exit cleanly without process.exit(): socket.destroy() in addition to socket.end(), explicit destroy() on the child process stdio streams, and cliProcess.unref(). Manually verified by running examples/basic-example.ts against a live runtime: the process exits within a few seconds of the await using block ending. - Remove the deprecated CopilotSession.destroy() alias. - Rewrite examples/basic-example.ts to import from '@github/copilot-sdk' (not '../src/index.js') and demonstrate the await using pattern with the new send/sendAndWait string overloads. Covers review §2.4, §2.5, §2.10, §3.1, §3.2, §4.1, §4.3 and the C# PR's Phase 8 docs/sample updates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase L: fix githubToken typos in scenario fixtures Twenty-one test/scenarios/**/typescript/src/index.ts files used 'githubToken: process.env.GITHUB_TOKEN' (lowercase h) instead of the correct 'gitHubToken'. They silently passed an unrecognized property and the runtime ignored the token. Fix in lock-step across all affected scenarios. The existing 'typecheck' npm script already runs 'tsc --noEmit -p tsconfig.test.json' in CI, so no further CI wiring is needed to prevent regressions: this typo would now be a compile error under the SDK's strict CopilotClientOptions shape. Other Phase L items (missing onPermissionRequest, invalid permission kinds, resumeSession scenarios without config) were either already caught by the runtime PR or do not apply to TS — no remaining work. Covers review §1.1, §2.1, §2.8, §2.11. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase L follow-up: run prettier --write over all modified files Prettier check failed on Ubuntu CI because several files modified in earlier phases didn't get re-formatted after the bulk regex rewrites. Running 'npm run format' (prettier --write) normalizes them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Phase I/E/L test failures surfaced by CI - commands/multi-client/ui_elicitation: shorthand 'copilotClientOptions: { tcpConnectionToken }' wasn't matched by the earlier batch rewrite, so client1 was still spawned in stdio mode while client2 tried to connect by URI. Switch the harness call to TCP + RuntimeConnection.forTcp({ connectionToken: tcpConnectionToken }). - session_fs.e2e.test.ts: add the missing RuntimeConnection import. - hooks_extended.e2e.test.ts: SessionStart and UserPromptSubmitted timestamp assertions still used toBeGreaterThan(0) but BaseHookInput.timestamp is now Date. Switch to toBeInstanceOf(Date). - client.test.ts: delete the two obsolete 'allows *Session without onPermissionRequest' unit tests. They asserted on the 'Client not connected' error that only occurred when autoStart was false; with Phase C removing autoStart, the client now auto-starts on the first session call and those tests would need a real spawned runtime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add E2E equivalents of removed createSession/resumeSession-without-permission tests The two client.test.ts unit tests deleted in the previous commit only asserted that createSession/resumeSession surface 'Client not connected' when called pre-start. The intent behind them was to confirm that omitting onPermissionRequest doesn't itself throw. With autoStart gone, the only meaningful version of that test is an E2E one that actually spawns a runtime. Port the equivalent C# coverage (ClientE2ETests.Should_Allow_*Session_Called_Without_PermissionHandler) to client.e2e.test.ts so we have parity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add E2E tests for createSession/resumeSession without onPermissionRequest Ports dotnet's Should_Allow_CreateSession_Called_Without_PermissionHandler (Theory: stdio + tcp) and Should_Allow_ResumeSession_Called_Without_PermissionHandler from dotnet/test/E2E/ClientE2ETests.cs into nodejs/test/e2e/session.e2e.test.ts. These exercise the contract that {onPermissionRequest} is optional on both SessionConfig and ResumeSessionConfig: when not provided, the runtime leaves permission prompts pending for the consumer to resolve via the low-level RPC. Without these tests, that contract was unprotected against regression. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Harness: preserve caller-supplied RuntimeConnection while still injecting CLI path Earlier batch rewrite of createSdkTestContext meant that whenever a test passed copilotClientOptions.connection, the spread overrode the harness's own connection variant entirely - losing the COPILOT_CLI_PATH binding. Now merge by variant kind: if the caller asks for tcp/stdio without a path, the harness fills it in from COPILOT_CLI_PATH; explicit values from the caller win. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * session_fs.e2e: fix unconverted tcpConnectionToken flat key on inner client In the 'should reject setProvider when sessions already exist' test, the first client was still using the flat tcpConnectionToken property which is no longer a valid CopilotClientOptions field. Switch to RuntimeConnection.forTcp({ connectionToken }). Verified locally: full session_fs.e2e.test.ts suite (9 tests) now passes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move hook input deserialization next to the cast that types it normalizeHookInput lived in client.ts and inspected for a 'timestamp' property by name, which felt magical (brittle against any future hook-shaped wire payload that happens to contain a numeric 'timestamp'). Move the conversion into CopilotSession._handleHooksInvoke, renamed deserializeHookInput, right next to the GenericHandler cast that says 'this unknown is now a HookInput'. That's the only call site that actually knows the payload is a hook input, so it's the correct boundary for the schema transform. This is the TS equivalent of what C# does via UnixMillisecondsDateTimeOffsetConverter (attached per-property on each HookInput.Timestamp); TS just plumbs the same conversion through the hooks dispatcher instead of a per-type JSON converter. Verified 3/3 hooks_extended.e2e tests pass locally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Phase K refinement: use unref() instead of destroy() in client.stop() destroy() on the child's stdio pipes and the TCP socket is more aggressive than needed. If the child crashes with a useful message on stderr that our existing data listener hasn't drained yet, stderr.destroy() drops it. If there's an in-flight write to stdin, destroy() raises 'error' on the stream. Same trade-off for socket.destroy() short-circuiting the graceful FIN/ACK. unref() solves the actual problem (event loop staying alive after stop()) without disrupting late output. From the Node docs: 'unref will allow the program to exit if this is the only active socket in the event system. The socket does not lose any functionality' — error events still fire, late data still drains through registered listeners. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * client.stop(): await child exit and socket close Replace the unref()-based fire-and-forget cleanup with deterministic awaiting: - Socket: end() + await 'close'. By the time stop() returns the FIN/ACK exchange has completed. - ChildProcess: kill() + await 'exit'. By the time stop() returns the child has truly exited, its stdio pipes are closed, and there are no lingering handles to keep the event loop alive. No SIGKILL escalation. If the child ignores SIGTERM, stop() blocks; callers that need a guaranteed-bounded shutdown should use forceStop() (which already sends SIGKILL). Replaces the previous unref() approach: that worked for clean exit but allowed late stderr output to surface after stop() resolved, which is exactly the timing window where consumers expect cleanup to be done. Verified locally: full client.test.ts (75 tests) passes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert incorrect feedback widening of PermissionRequestResult The previous '& { feedback?: string }' incorrectly added feedback to every variant of the union. In the runtime schema, feedback is reject-only — it appears only on PermissionDecisionReject and is already typed by the generated PermissionDecisionRequest['result'] union. No manual augmentation needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename client.on -> client.onLifecycle for cross-SDK consistency Matches the C# rename in PR #1357 Phase 4f (client.On -> client.OnLifecycle). client.onLifecycle is clearer than client.on at the call site because the two on() methods on CopilotClient and CopilotSession listen for completely different event families (lifecycle vs per-session). The receiver alone isn't always enough to disambiguate, especially in mixed code that holds both objects. session.on stays unchanged because that's where the bare 'on' verb belongs: session events are the primary stream for that object. Updates README + client_lifecycle.e2e.test.ts to the new name. Tests still pass (validated via tsc -p tsconfig.test.json). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Reformat src/types.ts after PermissionRequestResult revert Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review comments from #1357 - Add missing RuntimeConnection imports to 26 test/scenarios TypeScript fixtures. The earlier batch rewrite added the .forStdio/.forUri call sites but missed the corresponding import statement, so each scenario failed to compile until now. - nodejs/test/e2e/harness/sdkTestContext.ts: strip the 'kind' property before spreading a user-supplied RuntimeConnection back through the forStdio/forTcp factory opts. The factory opt types don't accept 'kind' so the spread was producing excess-property type errors. - nodejs/src/client.ts: rewrite the 'Path to Copilot CLI is required' error message to point at the new connection options (RuntimeConnection.forStdio({ path }), forTcp({ path }), forUri(...), or the COPILOT_CLI_PATH environment variable). The old message referenced removed cliPath / cliUrl options. - nodejs/src/client.ts: change the default logLevel from 'debug' to 'info'. 'debug' was a TS-only outlier; Python and Rust default to 'info', and the README has always claimed 'info'. Go and .NET don't pass --log-level at all when omitted (CLI defaults to info anyway), so 'info' is consistent with every other SDK's effective default. - nodejs/src/types.ts: fix MCPServerConfigBase.tools doc comment to spell the all-tools sentinel as ['*'] (the actual type is string[], so a bare '*' string can't be passed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * logLevel: don't impose any default, match C#/Go Instead of defaulting to 'info' on the SDK side, omit the --log-level flag entirely when the caller didn't set one and let the runtime use its own default. Matches dotnet/Client.cs and go/client.go, which both only pass --log-level when explicitly provided. CopilotClientOptions.logLevel JSDoc and README updated to describe this ('When omitted, the runtime uses its own default'). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename CopilotClientOptions.remote -> enableRemoteSessions for cross-SDK consistency Matches the C# API review rename in #1343 (EnableRemoteSessions on CopilotClientOptions). The wire-level RPC field stays 'remote' since that is the runtime's contract; only the SDK surface changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3c4ebf6 commit 8272a2a

70 files changed

Lines changed: 969 additions & 752 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/troubleshooting/compatibility.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The Copilot SDK communicates with the CLI via JSON-RPC protocol. Features must b
2929
| Queueing (enqueue mode) | `send({ mode: "enqueue" })` | Buffer for sequential processing (default) |
3030
| File attachments | `send({ attachments: [{ type: "file", path }] })` | Images auto-encoded and resized |
3131
| Directory attachments | `send({ attachments: [{ type: "directory", path }] })` | Attach directory context |
32-
| Get history | `getMessages()` | All session events |
32+
| Get history | `getEvents()` | All session events |
3333
| Abort | `abort()` | Cancel in-flight request |
3434
| **Tools** | | |
3535
| Register custom tools | `registerTools()` | Full JSON Schema support |
@@ -178,7 +178,7 @@ The `--share` option is not available via SDK. Workarounds:
178178
const events: SessionEvent[] = [];
179179
session.on((event) => events.push(event));
180180
// ... after conversation ...
181-
const messages = await session.getMessages();
181+
const messages = await session.getEvents();
182182
// Format as markdown yourself
183183
```
184184

nodejs/README.md

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,17 @@ new CopilotClient(options?: CopilotClientOptions)
7979

8080
**Options:**
8181

82-
- `cliPath?: string` - Path to CLI executable (default: uses COPILOT_CLI_PATH env var or bundled instance)
83-
- `cliArgs?: string[]` - Extra arguments prepended before SDK-managed flags (e.g. `["./dist-cli/index.js"]` when using `node`)
84-
- `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.
85-
- `port?: number` - Server port (default: 0 for random)
86-
- `useStdio?: boolean` - Use stdio transport instead of TCP (default: true)
87-
- `logLevel?: string` - Log level (default: "info")
88-
- `autoStart?: boolean` - Auto-start server (default: true)
82+
- `connection?: RuntimeConnection` - How to connect to the Copilot runtime. Construct via the factory functions on `RuntimeConnection`:
83+
- `RuntimeConnection.forStdio({ path?, args? })` (default) — spawn the runtime and communicate over its stdin/stdout.
84+
- `RuntimeConnection.forTcp({ port?, connectionToken?, path?, args? })` — spawn the runtime as a TCP server.
85+
- `RuntimeConnection.forUri(url, { connectionToken? })` — connect to an already-running runtime (mutually exclusive with `gitHubToken`/`useLoggedInUser`).
86+
- `cwd?: string` - Working directory for the runtime process (default: current process cwd).
87+
- `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`.
88+
- `logLevel?: string` - Log level. When omitted, the runtime uses its own default (currently `"info"`).
8989
- `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 `cliUrl`.
91-
- `copilotHome?: string` - Base directory for Copilot data (session state, config, etc.). Sets `COPILOT_HOME` on the spawned CLI process. When not set, the CLI defaults to `~/.copilot`. Useful in restricted environments where only specific directories are writable. Ignored when using `cliUrl`.
92-
- `telemetry?: TelemetryConfig` - OpenTelemetry configuration for the CLI 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 CLI's spans. Not needed for normal telemetry collection. See [Telemetry](#telemetry) below.
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+
- `telemetry?: TelemetryConfig` - OpenTelemetry configuration for the runtime process. Providing this object enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below.
92+
- `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.
9493

9594
#### Methods
9695

@@ -173,7 +172,7 @@ Request the TUI to switch to displaying the specified session. Only available in
173172
Subscribe to a specific session lifecycle event type. Returns an unsubscribe function.
174173

175174
```typescript
176-
const unsubscribe = client.on("session.foreground", (event) => {
175+
const unsubscribe = client.onLifecycle("session.foreground", (event) => {
177176
console.log(`Session ${event.sessionId} is now in foreground`);
178177
});
179178
```
@@ -183,7 +182,7 @@ const unsubscribe = client.on("session.foreground", (event) => {
183182
Subscribe to all session lifecycle events. Returns an unsubscribe function.
184183

185184
```typescript
186-
const unsubscribe = client.on((event) => {
185+
const unsubscribe = client.onLifecycle((event) => {
187186
console.log(`${event.type}: ${event.sessionId}`);
188187
});
189188
```
@@ -277,7 +276,7 @@ unsubscribe();
277276

278277
Abort the currently processing message in this session.
279278

280-
##### `getMessages(): Promise<SessionEvent[]>`
279+
##### `getEvents(): Promise<SessionEvent[]>`
281280

282281
Get all events/messages from this session.
283282

@@ -415,7 +414,7 @@ Note: `assistant.message` and `assistant.reasoning` (final events) are always se
415414
### Manual Server Control
416415

417416
```typescript
418-
const client = new CopilotClient({ autoStart: false });
417+
const client = new CopilotClient({});
419418

420419
// Start manually
421420
await client.start();
@@ -856,15 +855,15 @@ const session = await client.createSession({
856855

857856
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:
858857

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) |
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) |
863862
| `"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) |
864863
| `"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) ||
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) ||
868867

869868
### Resuming Sessions
870869

@@ -1026,7 +1025,7 @@ try {
10261025
## Requirements
10271026

10281027
- Node.js >= 18.0.0
1029-
- GitHub Copilot CLI installed and in PATH (or provide custom `cliPath`)
1028+
- GitHub Copilot CLI installed and in PATH (or provide a custom `connection`)
10301029

10311030
## License
10321031

nodejs/examples/basic-example.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*--------------------------------------------------------------------------------------------*/
44

55
import { z } from "zod";
6-
import { CopilotClient, defineTool } from "../src/index.js";
6+
import { approveAll, CopilotClient, defineTool } from "@github/copilot-sdk";
77

88
console.log("🚀 Starting Copilot SDK Example\n");
99

@@ -20,27 +20,23 @@ const lookupFactTool = defineTool("lookup_fact", {
2020
handler: ({ topic }) => facts[topic.toLowerCase()] ?? `No fact stored for ${topic}.`,
2121
});
2222

23-
// Create client - will auto-start CLI server (searches PATH for "copilot")
24-
const client = new CopilotClient({ logLevel: "info" });
25-
const session = await client.createSession({ tools: [lookupFactTool] });
23+
await using client = new CopilotClient({ logLevel: "info" });
24+
await using session = await client.createSession({
25+
onPermissionRequest: approveAll,
26+
tools: [lookupFactTool],
27+
});
2628
console.log(`✅ Session created: ${session.sessionId}\n`);
2729

28-
// Listen to events
2930
session.on((event) => {
3031
console.log(`📢 Event [${event.type}]:`, JSON.stringify(event.data, null, 2));
3132
});
3233

33-
// Send a simple message
3434
console.log("💬 Sending message...");
35-
const result1 = await session.sendAndWait({ prompt: "Tell me 2+2" });
35+
const result1 = await session.sendAndWait("Tell me 2+2");
3636
console.log("📝 Response:", result1?.data.content);
3737

38-
// Send another message that uses the tool
3938
console.log("💬 Sending follow-up message...");
40-
const result2 = await session.sendAndWait({ prompt: "Use lookup_fact to tell me about 'node'" });
39+
const result2 = await session.sendAndWait("Use lookup_fact to tell me about 'node'");
4140
console.log("📝 Response:", result2?.data.content);
4241

43-
// Clean up
44-
await session.disconnect();
45-
await client.stop();
4642
console.log("✅ Done!");

0 commit comments

Comments
 (0)