diff --git a/CHANGELOG.md b/CHANGELOG.md index ac5712aa5..8bb74e3e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ See [GitHub Releases](https://github.com/github/copilot-sdk/releases) for the fu SDK applications written against the v3 API now also work when connected to a v2 CLI server, with no code changes required. The SDK detects the server's protocol version and automatically adapts v2 `tool.call` and `permission.request` messages into the same user-facing handlers used by v3. ([#706](https://github.com/github/copilot-sdk/pull/706)) ```ts +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); + const session = await client.createSession({ tools: [myTool], // unchanged — works with v2 and v3 servers onPermissionRequest: approveAll, @@ -84,7 +88,9 @@ if result.Kind == copilot.PermissionKindApproved { /* ... */ } Applications can now override built-in tools such as `grep`, `edit_file`, or `read_file`. To do this, register a custom tool with the same name and set the override flag. Without the flag, the runtime will return an error if the name clashes with a built-in. ([#636](https://github.com/github/copilot-sdk/pull/636)) ```ts -import { defineTool } from "@github/copilot-sdk"; +import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ tools: [defineTool("grep", { diff --git a/docs/auth/byok.md b/docs/auth/byok.md index 8d9650280..51e858eab 100644 --- a/docs/auth/byok.md +++ b/docs/auth/byok.md @@ -63,7 +63,7 @@ asyncio.run(main()) Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const FOUNDRY_MODEL_URL = "https://your-resource.openai.azure.com/openai/v1/"; @@ -76,6 +76,7 @@ const session = await client.createSession({ wireApi: "responses", // Use "completions" for older models apiKey: process.env.FOUNDRY_API_KEY, }, + onPermissionRequest: approveAll }); session.on("assistant.message", (event) => { @@ -454,15 +455,21 @@ Some Copilot features may behave differently with BYOK: When using BYOK, the `model` parameter is **required**: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); + // ❌ Error: Model required with custom provider const session = await client.createSession({ provider: { type: "openai", baseUrl: "..." }, + onPermissionRequest: approveAll, }); // ✅ Correct: Model specified const session = await client.createSession({ model: "gpt-4", // Required! provider: { type: "openai", baseUrl: "..." }, + onPermissionRequest: approveAll, }); ``` @@ -472,7 +479,7 @@ For Azure OpenAI endpoints (`*.openai.azure.com`), use the correct type: ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ @@ -481,6 +488,7 @@ const session = await client.createSession({ type: "azure", baseUrl: "https://my-resource.openai.azure.com", }, + onPermissionRequest: approveAll }); ``` @@ -503,7 +511,7 @@ However, if your Azure AI Foundry deployment provides an OpenAI-compatible endpo ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ @@ -512,6 +520,7 @@ const session = await client.createSession({ type: "openai", baseUrl: "https://your-resource.openai.azure.com/openai/v1/", }, + onPermissionRequest: approveAll }); ``` diff --git a/docs/features/custom-agents.md b/docs/features/custom-agents.md index 47712d9cf..aee06d5cb 100644 --- a/docs/features/custom-agents.md +++ b/docs/features/custom-agents.md @@ -31,7 +31,7 @@ Pass `customAgents` when creating a session. Each agent needs at minimum a `name Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); @@ -54,7 +54,7 @@ const session = await client.createSession({ prompt: "You are a code editor. Make minimal, surgical changes to files as requested.", }, ], - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -236,6 +236,9 @@ This is equivalent to calling `session.rpc.agent.select()` after creation, but a ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ customAgents: [ { @@ -248,6 +251,7 @@ const session = await client.createSession({ }, ], agent: "researcher", // Pre-select the researcher agent + onPermissionRequest: approveAll, }); ``` @@ -618,6 +622,9 @@ session.on((event) => { Use the `tools` property to restrict which tools an agent can access. This is essential for security and for keeping agents focused: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ customAgents: [ { @@ -639,6 +646,7 @@ const session = await client.createSession({ prompt: "You handle complex multi-step tasks using any available tools.", }, ], + onPermissionRequest: approveAll, }); ``` @@ -649,6 +657,9 @@ const session = await client.createSession({ Each custom agent can have its own MCP (Model Context Protocol) servers, giving it access to specialized data sources: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ customAgents: [ { @@ -663,6 +674,7 @@ const session = await client.createSession({ }, }, ], + onPermissionRequest: approveAll, }); ``` diff --git a/docs/features/hooks.md b/docs/features/hooks.md index 1a01c5f1a..5af4e60f5 100644 --- a/docs/features/hooks.md +++ b/docs/features/hooks.md @@ -38,7 +38,7 @@ Pass a `hooks` object when you create (or resume) a session. Every example below Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); @@ -50,7 +50,7 @@ const session = await client.createSession({ onPostToolUse: async (input, invocation) => { /* ... */ }, // ... add only the hooks you need }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -209,6 +209,9 @@ Use `onPreToolUse` to build a permission layer that decides which tools the agen Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const READ_ONLY_TOOLS = ["read_file", "glob", "grep", "view"]; const session = await client.createSession({ @@ -224,7 +227,7 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -383,6 +386,9 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Restrict file access to specific directories ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const ALLOWED_DIRS = ["/home/user/projects", "/tmp"]; const session = await client.createSession({ @@ -403,13 +409,16 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` ### Ask the user before destructive operations ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const DESTRUCTIVE_TOOLS = ["delete_file", "shell", "bash"]; const session = await client.createSession({ @@ -421,7 +430,7 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -439,6 +448,8 @@ Combine `onPreToolUse`, `onPostToolUse`, and the session lifecycle hooks to buil Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + interface AuditEntry { timestamp: number; sessionId: string; @@ -451,6 +462,7 @@ interface AuditEntry { const auditLog: AuditEntry[] = []; +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async (input, invocation) => { @@ -505,7 +517,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -584,6 +596,9 @@ session = await client.create_session( ### Redact secrets from tool results ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const SECRET_PATTERNS = [ /(?:api[_-]?key|token|secret|password)\s*[:=]\s*["']?[\w\-\.]+["']?/gi, ]; @@ -603,7 +618,7 @@ const session = await client.createSession({ : null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -620,7 +635,9 @@ Hooks fire in your application's process, so you can trigger any side-effect — ```typescript import notifier from "node-notifier"; // npm install node-notifier +import { CopilotClient, approveAll } from "@github/copilot-sdk"; +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionEnd: async (input, invocation) => { @@ -638,7 +655,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -681,7 +698,9 @@ session = await client.create_session( ```typescript import { exec } from "node:child_process"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPostToolUse: async (input) => { @@ -694,13 +713,16 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` ### Post to Slack on errors ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL!; const session = await client.createSession({ @@ -718,7 +740,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -731,6 +753,9 @@ Use `onSessionStart` and `onUserPromptSubmitted` to automatically inject context ### Inject project metadata at session start ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async (input) => { @@ -746,13 +771,16 @@ const session = await client.createSession({ }; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` ### Expand shorthand commands in prompts ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const SHORTCUTS: Record = { "/fix": "Find and fix all errors in the current file", "/test": "Write comprehensive unit tests for this code", @@ -772,7 +800,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -785,6 +813,9 @@ The `onErrorOccurred` hook gives you a chance to react to failures — whether t ### Retry transient model errors ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onErrorOccurred: async (input) => { @@ -798,13 +829,16 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` ### Friendly error messages ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const FRIENDLY_MESSAGES: Record = { model_call: "The AI model is temporarily unavailable. Please try again.", tool_execution: "A tool encountered an error. Check inputs and try again.", @@ -819,7 +853,7 @@ const session = await client.createSession({ }; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -833,6 +867,9 @@ Track how long sessions run, how many tools are invoked, and why sessions end Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const metrics = new Map(); const session = await client.createSession({ @@ -867,7 +904,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -925,6 +962,9 @@ session = await client.create_session( Hooks compose naturally. A single `hooks` object can handle permissions **and** auditing **and** notifications — each hook does its own job. ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async (input) => { @@ -951,7 +991,7 @@ const session = await client.createSession({ return null; }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` diff --git a/docs/features/image-input.md b/docs/features/image-input.md index acec80d4a..093f62f89 100644 --- a/docs/features/image-input.md +++ b/docs/features/image-input.md @@ -41,14 +41,14 @@ Attach an image file to any message using the file attachment type. The path mus Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); await session.send({ @@ -227,14 +227,14 @@ When you already have image data in memory (e.g., a screenshot captured by your Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); const base64ImageData = "..."; // your base64-encoded image diff --git a/docs/features/mcp.md b/docs/features/mcp.md index 62465c0bd..e91184a74 100644 --- a/docs/features/mcp.md +++ b/docs/features/mcp.md @@ -28,7 +28,7 @@ The SDK supports two types of MCP servers: ### Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ @@ -52,6 +52,7 @@ const session = await client.createSession({ tools: ["*"], }, }, + onPermissionRequest: approveAll }); ``` @@ -162,7 +163,7 @@ await using var session = await client.CreateSessionAsync(new SessionConfig Here's a complete working example using the official [`@modelcontextprotocol/server-filesystem`](https://www.npmjs.com/package/@modelcontextprotocol/server-filesystem) MCP server: ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; async function main() { const client = new CopilotClient(); @@ -177,6 +178,7 @@ async function main() { tools: ["*"], }, }, + onPermissionRequest: approveAll }); console.log("Session created:", session.sessionId); diff --git a/docs/features/session-persistence.md b/docs/features/session-persistence.md index 3b0e9f69b..dc1fc5062 100644 --- a/docs/features/session-persistence.md +++ b/docs/features/session-persistence.md @@ -26,7 +26,7 @@ The key to resumable sessions is providing your own `session_id`. Without one, t ### TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); @@ -34,6 +34,7 @@ const client = new CopilotClient(); const session = await client.createSession({ sessionId: "user-123-task-456", model: "gpt-5.2-codex", + onPermissionRequest: approveAll }); // Do some work... @@ -134,10 +135,10 @@ flowchart LR subgraph Day1["Day 1"] A1[Client A:
createSession] --> A2[Work...] end - + A2 --> S[(💾 Storage:
~/.copilot/session-state/)] S --> B1 - + subgraph Day2["Day 2"] B1[Client B:
resumeSession] --> B2[Continue] end @@ -265,6 +266,9 @@ const session = await client.resumeSession("user-123-task-456", { When using your own API keys, you must re-provide the provider configuration when resuming. API keys are never persisted to disk for security reasons. ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); // Original session with BYOK const session = await client.createSession({ sessionId: "user-123-task-456", @@ -275,6 +279,7 @@ const session = await client.createSession({ apiKey: process.env.AZURE_OPENAI_KEY, deploymentId: "my-gpt-deployment", }, + onPermissionRequest: approveAll, }); // When resuming, you MUST re-provide the provider config @@ -376,7 +381,7 @@ const repoSessions = await client.listSessions({ repository: "owner/repo" }); async function cleanupExpiredSessions(maxAgeMs: number) { const sessions = await client.listSessions(); const now = Date.now(); - + for (const session of sessions) { const age = now - new Date(session.createdAt).getTime(); if (age > maxAgeMs) { @@ -398,7 +403,7 @@ When a task completes, disconnect from the session explicitly rather than waitin try { // Do work... await session.sendAndWait({ prompt: "Complete the task" }); - + // Task complete — release in-memory resources (session can be resumed later) await session.disconnect(); } catch (error) { @@ -495,11 +500,11 @@ async function resumeSessionWithAuth( ): Promise { // Parse user from session ID const [sessionUserId] = sessionId.split("-"); - + if (sessionUserId !== currentUserId) { throw new Error("Access denied: session belongs to another user"); } - + return client.resumeSession(sessionId); } ``` @@ -533,10 +538,10 @@ flowchart LR subgraph Before["Container A"] CLI1[CLI + Session X] end - + CLI1 --> |persist| Azure[(☁️ Azure File Share)] Azure --> |restore| CLI2 - + subgraph After["Container B (restart)"] CLI2[CLI + Session X] end @@ -549,6 +554,9 @@ flowchart LR For workflows that might exceed context limits, enable infinite sessions with automatic compaction: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ sessionId: "long-workflow-123", infiniteSessions: { @@ -556,6 +564,7 @@ const session = await client.createSession({ backgroundCompactionThreshold: 0.80, // Start compaction at 80% context bufferExhaustionThreshold: 0.95, // Block at 95% if needed }, + onPermissionRequest: approveAll, }); ``` @@ -586,11 +595,11 @@ async function withSessionLock( ): Promise { const lockKey = `session-lock:${sessionId}`; const acquired = await redis.set(lockKey, "locked", "NX", "EX", 300); - + if (!acquired) { throw new Error("Session is in use by another client"); } - + try { return await fn(); } finally { diff --git a/docs/features/skills.md b/docs/features/skills.md index 466c637ff..8f2fd5895 100644 --- a/docs/features/skills.md +++ b/docs/features/skills.md @@ -20,7 +20,7 @@ Specify directories containing skills when creating a session: Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ @@ -29,7 +29,7 @@ const session = await client.createSession({ "./skills/code-review", "./skills/documentation", ], - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); // Copilot now has access to skills in those directories @@ -148,9 +148,13 @@ Disable specific skills while keeping others active: Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ skillDirectories: ["./skills"], disabledSkills: ["experimental-feature", "deprecated-tool"], + onPermissionRequest: approveAll, }); ``` @@ -319,6 +323,9 @@ The markdown body contains the instructions that are injected into the session c Skills work alongside custom agents: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ skillDirectories: ["./skills/security"], customAgents: [{ @@ -326,7 +333,7 @@ const session = await client.createSession({ description: "Security-focused code reviewer", prompt: "Focus on OWASP Top 10 vulnerabilities", }], - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` @@ -335,6 +342,9 @@ const session = await client.createSession({ Skills can complement MCP server capabilities: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ skillDirectories: ["./skills/database"], mcpServers: { @@ -345,7 +355,7 @@ const session = await client.createSession({ tools: ["*"], }, }, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); ``` diff --git a/docs/features/steering-and-queueing.md b/docs/features/steering-and-queueing.md index 7da349e1c..c68e5692a 100644 --- a/docs/features/steering-and-queueing.md +++ b/docs/features/steering-and-queueing.md @@ -41,14 +41,14 @@ Steering sends a message that is injected directly into the agent's current turn Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); // Start a long-running task @@ -195,14 +195,14 @@ Queueing buffers messages to be processed sequentially after the current turn fi Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); await client.start(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); // Send an initial task @@ -404,9 +404,12 @@ You can use both patterns together in a single session. Steering affects the cur Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); // Start a task diff --git a/docs/getting-started.md b/docs/getting-started.md index 6c0aee72e..9a25fafcf 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -102,10 +102,10 @@ Create a new file and add the following code. This is the simplest way to use th Create `index.ts`: ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); -const session = await client.createSession({ model: "gpt-4.1" }); +const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: "What is 2 + 2?" }); console.log(response?.data.content); @@ -243,12 +243,13 @@ Right now, you wait for the complete response before seeing anything. Let's make Update `index.ts`: ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4.1", streaming: true, + onPermissionRequest: approveAll }); // Listen for response chunks @@ -595,7 +596,7 @@ Now for the powerful part. Let's give Copilot the ability to call your code by d Update `index.ts`: ```typescript -import { CopilotClient, defineTool } from "@github/copilot-sdk"; +import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk"; // Define a tool that Copilot can call const getWeather = defineTool("get_weather", { @@ -622,6 +623,7 @@ const session = await client.createSession({ model: "gpt-4.1", streaming: true, tools: [getWeather], + onPermissionRequest: approveAll }); session.on("assistant.message_delta", (event) => { @@ -845,7 +847,7 @@ Let's put it all together into a useful interactive assistant: Node.js / TypeScript ```typescript -import { CopilotClient, defineTool } from "@github/copilot-sdk"; +import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk"; import * as readline from "readline"; const getWeather = defineTool("get_weather", { @@ -870,6 +872,7 @@ const session = await client.createSession({ model: "gpt-4.1", streaming: true, tools: [getWeather], + onPermissionRequest: approveAll }); session.on("assistant.message_delta", (event) => { @@ -1204,6 +1207,9 @@ Now that you've got the basics, here are more powerful features to explore: MCP (Model Context Protocol) servers provide pre-built tools. Connect to GitHub's MCP server to give Copilot access to repositories, issues, and pull requests: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ mcpServers: { github: { @@ -1211,6 +1217,7 @@ const session = await client.createSession({ url: "https://api.githubcopilot.com/mcp/", }, }, + onPermissionRequest: approveAll, }); ``` @@ -1221,6 +1228,9 @@ const session = await client.createSession({ Define specialized AI personas for specific tasks: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ customAgents: [{ name: "pr-reviewer", @@ -1228,6 +1238,7 @@ const session = await client.createSession({ description: "Reviews pull requests for best practices", prompt: "You are an expert code reviewer. Focus on security, performance, and maintainability.", }], + onPermissionRequest: approveAll, }); ``` @@ -1238,10 +1249,14 @@ const session = await client.createSession({ Control the AI's behavior and personality: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ systemMessage: { content: "You are a helpful assistant for our engineering team. Always be concise.", }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/error-handling.md b/docs/hooks/error-handling.md index a67906ac9..3418ae0e7 100644 --- a/docs/hooks/error-handling.md +++ b/docs/hooks/error-handling.md @@ -128,6 +128,9 @@ Return `null` or `undefined` to use default error handling. Otherwise, return an Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onErrorOccurred: async (input, invocation) => { @@ -137,6 +140,7 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` @@ -255,6 +259,9 @@ var session = await client.CreateSessionAsync(new SessionConfig ```typescript import { captureException } from "@sentry/node"; // or your monitoring service +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { @@ -270,16 +277,20 @@ const session = await client.createSession({ cwd: input.cwd, }, }); - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### User-Friendly Error Messages ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const ERROR_MESSAGES: Record = { "model_call": "There was an issue communicating with the AI model. Please try again.", "tool_execution": "A tool failed to execute. Please check your inputs and try again.", @@ -291,22 +302,26 @@ const session = await client.createSession({ hooks: { onErrorOccurred: async (input) => { const friendlyMessage = ERROR_MESSAGES[input.errorContext]; - + if (friendlyMessage) { return { userNotification: friendlyMessage, }; } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Suppress Non-Critical Errors ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onErrorOccurred: async (input) => { @@ -318,12 +333,16 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Add Recovery Context ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onErrorOccurred: async (input) => { @@ -337,7 +356,7 @@ The tool failed. Here are some recovery suggestions: `.trim(), }; } - + if (input.errorContext === "model_call" && input.error.includes("rate")) { return { errorHandling: "retry", @@ -345,55 +364,63 @@ The tool failed. Here are some recovery suggestions: userNotification: "Rate limit hit. Retrying...", }; } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Track Error Patterns ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + interface ErrorStats { count: number; lastOccurred: number; contexts: string[]; } +const client = new CopilotClient(); const errorStats = new Map(); const session = await client.createSession({ hooks: { onErrorOccurred: async (input, invocation) => { const key = `${input.errorContext}:${input.error.substring(0, 50)}`; - + const existing = errorStats.get(key) || { count: 0, lastOccurred: 0, contexts: [], }; - + existing.count++; existing.lastOccurred = input.timestamp; existing.contexts.push(invocation.sessionId); - + errorStats.set(key, existing); - + // Alert if error is recurring if (existing.count >= 5) { console.warn(`Recurring error detected: ${key} (${existing.count} times)`); } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Alert on Critical Errors ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const CRITICAL_CONTEXTS = ["system", "model_call"]; const session = await client.createSession({ @@ -408,16 +435,20 @@ const session = await client.createSession({ timestamp: new Date(input.timestamp).toISOString(), }); } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Combine with Other Hooks for Context ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const sessionContext = new Map(); const session = await client.createSession({ @@ -428,17 +459,17 @@ const session = await client.createSession({ sessionContext.set(invocation.sessionId, ctx); return { permissionDecision: "allow" }; }, - + onUserPromptSubmitted: async (input, invocation) => { const ctx = sessionContext.get(invocation.sessionId) || {}; ctx.lastPrompt = input.prompt.substring(0, 100); sessionContext.set(invocation.sessionId, ctx); return null; }, - + onErrorOccurred: async (input, invocation) => { const ctx = sessionContext.get(invocation.sessionId); - + console.error(`Error in session ${invocation.sessionId}:`); console.error(` Error: ${input.error}`); console.error(` Context: ${input.errorContext}`); @@ -448,10 +479,11 @@ const session = await client.createSession({ if (ctx?.lastPrompt) { console.error(` Last prompt: ${ctx.lastPrompt}...`); } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/index.md b/docs/hooks/index.md index d83b11b2f..9434b3d94 100644 --- a/docs/hooks/index.md +++ b/docs/hooks/index.md @@ -25,7 +25,7 @@ Hooks allow you to intercept and customize the behavior of Copilot sessions at k Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); @@ -44,6 +44,7 @@ const session = await client.createSession({ return { additionalContext: "User prefers concise answers." }; }, }, + onPermissionRequest: approveAll }); ``` @@ -170,6 +171,9 @@ This allows hooks to maintain state or perform session-specific logic. ### Logging All Tool Calls ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPreToolUse: async (input) => { @@ -181,12 +185,16 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Blocking Dangerous Tools ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const BLOCKED_TOOLS = ["shell", "bash", "exec"]; const session = await client.createSession({ @@ -201,12 +209,16 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` ### Adding User Context ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async () => { @@ -216,6 +228,7 @@ const session = await client.createSession({ }; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/post-tool-use.md b/docs/hooks/post-tool-use.md index 029e9eb2f..51cc6521f 100644 --- a/docs/hooks/post-tool-use.md +++ b/docs/hooks/post-tool-use.md @@ -127,6 +127,9 @@ Return `null` or `undefined` to pass through the result unchanged. Otherwise, re Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPostToolUse: async (input, invocation) => { @@ -136,6 +139,7 @@ const session = await client.createSession({ return null; // Pass through unchanged }, }, + onPermissionRequest: approveAll, }); ``` @@ -253,6 +257,9 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Redact Sensitive Data ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const SENSITIVE_PATTERNS = [ /api[_-]?key["\s:=]+["']?[\w-]+["']?/gi, /password["\s:=]+["']?[\w-]+["']?/gi, @@ -267,7 +274,7 @@ const session = await client.createSession({ for (const pattern of SENSITIVE_PATTERNS) { redacted = redacted.replace(pattern, "[REDACTED]"); } - + if (redacted !== input.toolResult) { return { modifiedResult: redacted }; } @@ -275,19 +282,23 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Truncate Large Results ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const MAX_RESULT_LENGTH = 10000; const session = await client.createSession({ hooks: { onPostToolUse: async (input) => { const resultStr = JSON.stringify(input.toolResult); - + if (resultStr.length > MAX_RESULT_LENGTH) { return { modifiedResult: { @@ -301,12 +312,16 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Add Context Based on Results ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPostToolUse: async (input) => { @@ -316,23 +331,27 @@ const session = await client.createSession({ additionalContext: "Tip: If the file doesn't exist, consider creating it or checking the path.", }; } - + // If shell command failed, add debugging hint if (input.toolName === "shell" && input.toolResult?.exitCode !== 0) { return { additionalContext: "The command failed. Check if required dependencies are installed.", }; } - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Filter Error Stack Traces ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPostToolUse: async (input) => { @@ -349,12 +368,15 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Audit Trail for Compliance ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + interface AuditEntry { timestamp: number; sessionId: string; @@ -364,6 +386,7 @@ interface AuditEntry { success: boolean; } +const client = new CopilotClient(); const auditLog: AuditEntry[] = []; const session = await client.createSession({ @@ -377,19 +400,23 @@ const session = await client.createSession({ result: input.toolResult, success: !input.toolResult?.error, }); - + // Optionally persist to database/file await saveAuditLog(auditLog); - + return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Suppress Noisy Results ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const NOISY_TOOLS = ["list_directory", "search_codebase"]; const session = await client.createSession({ @@ -397,10 +424,10 @@ const session = await client.createSession({ onPostToolUse: async (input) => { if (NOISY_TOOLS.includes(input.toolName)) { // Summarize instead of showing full result - const items = Array.isArray(input.toolResult) - ? input.toolResult + const items = Array.isArray(input.toolResult) + ? input.toolResult : input.toolResult?.items || []; - + return { modifiedResult: { summary: `Found ${items.length} items`, @@ -411,6 +438,7 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/pre-tool-use.md b/docs/hooks/pre-tool-use.md index e1bb97495..ab0587bfe 100644 --- a/docs/hooks/pre-tool-use.md +++ b/docs/hooks/pre-tool-use.md @@ -136,6 +136,9 @@ Return `null` or `undefined` to allow the tool to execute with no changes. Other Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPreToolUse: async (input, invocation) => { @@ -144,6 +147,7 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` @@ -264,6 +268,9 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Block Specific Tools ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const BLOCKED_TOOLS = ["shell", "bash", "write_file", "delete_file"]; const session = await client.createSession({ @@ -278,12 +285,16 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` ### Modify Tool Arguments ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPreToolUse: async (input) => { @@ -301,12 +312,16 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` ### Restrict File Access to Specific Directories ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const ALLOWED_DIRECTORIES = ["/home/user/projects", "/tmp"]; const session = await client.createSession({ @@ -314,10 +329,10 @@ const session = await client.createSession({ onPreToolUse: async (input) => { if (input.toolName === "read_file" || input.toolName === "write_file") { const args = input.toolArgs as { path: string }; - const isAllowed = ALLOWED_DIRECTORIES.some(dir => + const isAllowed = ALLOWED_DIRECTORIES.some(dir => args.path.startsWith(dir) ); - + if (!isAllowed) { return { permissionDecision: "deny", @@ -328,12 +343,16 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` ### Suppress Verbose Tool Output ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const VERBOSE_TOOLS = ["list_directory", "search_files"]; const session = await client.createSession({ @@ -345,12 +364,16 @@ const session = await client.createSession({ }; }, }, + onPermissionRequest: approveAll, }); ``` ### Add Context Based on Tool ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onPreToolUse: async (input) => { @@ -363,6 +386,7 @@ const session = await client.createSession({ return { permissionDecision: "allow" }; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/session-lifecycle.md b/docs/hooks/session-lifecycle.md index 4efd33ccc..006583406 100644 --- a/docs/hooks/session-lifecycle.md +++ b/docs/hooks/session-lifecycle.md @@ -127,13 +127,16 @@ public delegate Task SessionStartHandler( Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async (input, invocation) => { console.log(`Session ${invocation.sessionId} started (${input.source})`); - + const projectInfo = await detectProjectType(input.cwd); - + return { additionalContext: ` This is a ${projectInfo.type} project. @@ -143,6 +146,7 @@ Package manager: ${projectInfo.packageManager} }; }, }, + onPermissionRequest: approveAll, }); ``` @@ -156,9 +160,9 @@ from copilot import PermissionHandler async def on_session_start(input_data, invocation): print(f"Session {invocation['session_id']} started ({input_data['source']})") - + project_info = await detect_project_type(input_data["cwd"]) - + return { "additionalContext": f""" This is a {project_info['type']} project. @@ -175,13 +179,16 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap #### Handle Session Resume ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async (input, invocation) => { if (input.source === "resume") { // Load previous session state const previousState = await loadSessionState(invocation.sessionId); - + return { additionalContext: ` Session resumed. Previous context: @@ -193,19 +200,23 @@ Session resumed. Previous context: return null; }, }, + onPermissionRequest: approveAll, }); ``` #### Load User Preferences ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionStart: async () => { const preferences = await loadUserPreferences(); - + const contextParts = []; - + if (preferences.language) { contextParts.push(`Preferred language: ${preferences.language}`); } @@ -215,12 +226,13 @@ const session = await client.createSession({ if (preferences.verbosity === "concise") { contextParts.push("Keep responses brief and to the point."); } - + return { additionalContext: contextParts.join("\n"), }; }, }, + onPermissionRequest: approveAll, }); ``` @@ -340,6 +352,9 @@ public delegate Task SessionEndHandler( Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const sessionStartTimes = new Map(); const session = await client.createSession({ @@ -351,17 +366,18 @@ const session = await client.createSession({ onSessionEnd: async (input, invocation) => { const startTime = sessionStartTimes.get(invocation.sessionId); const duration = startTime ? input.timestamp - startTime : 0; - + await recordMetrics({ sessionId: invocation.sessionId, duration, endReason: input.reason, }); - + sessionStartTimes.delete(invocation.sessionId); return null; }, }, + onPermissionRequest: approveAll, }); ``` @@ -382,13 +398,13 @@ async def on_session_start(input_data, invocation): async def on_session_end(input_data, invocation): start_time = session_start_times.get(invocation["session_id"]) duration = input_data["timestamp"] - start_time if start_time else 0 - + await record_metrics({ "session_id": invocation["session_id"], "duration": duration, "end_reason": input_data["reason"], }) - + session_start_times.pop(invocation["session_id"], None) return None @@ -403,6 +419,9 @@ session = await client.create_session(on_permission_request=PermissionHandler.ap #### Clean Up Resources ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const sessionResources = new Map(); const session = await client.createSession({ @@ -413,7 +432,7 @@ const session = await client.createSession({ }, onSessionEnd: async (input, invocation) => { const resources = sessionResources.get(invocation.sessionId); - + if (resources) { // Clean up temp files for (const file of resources.tempFiles) { @@ -421,17 +440,21 @@ const session = await client.createSession({ } sessionResources.delete(invocation.sessionId); } - + console.log(`Session ${invocation.sessionId} ended: ${input.reason}`); return null; }, }, + onPermissionRequest: approveAll, }); ``` #### Save Session State for Resume ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onSessionEnd: async (input, invocation) => { @@ -446,21 +469,25 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll }); ``` #### Log Session Summary ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const sessionData: Record = {}; const session = await client.createSession({ hooks: { onSessionStart: async (input, invocation) => { - sessionData[invocation.sessionId] = { - prompts: 0, - tools: 0, - startTime: input.timestamp + sessionData[invocation.sessionId] = { + prompts: 0, + tools: 0, + startTime: input.timestamp }; return null; }, @@ -482,11 +509,12 @@ Session Summary: Tool calls: ${data.tools} End reason: ${input.reason} `.trim()); - + delete sessionData[invocation.sessionId]; return null; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/hooks/user-prompt-submitted.md b/docs/hooks/user-prompt-submitted.md index 2aca7f1ce..502d6616f 100644 --- a/docs/hooks/user-prompt-submitted.md +++ b/docs/hooks/user-prompt-submitted.md @@ -125,6 +125,9 @@ Return `null` or `undefined` to use the prompt unchanged. Otherwise, return an o Node.js / TypeScript ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onUserPromptSubmitted: async (input, invocation) => { @@ -132,6 +135,7 @@ const session = await client.createSession({ return null; // Pass through unchanged }, }, + onPermissionRequest: approveAll, }); ``` @@ -239,11 +243,14 @@ var session = await client.CreateSessionAsync(new SessionConfig ### Add Project Context ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onUserPromptSubmitted: async (input) => { const projectInfo = await getProjectInfo(); - + return { additionalContext: ` Project: ${projectInfo.name} @@ -253,12 +260,16 @@ Framework: ${projectInfo.framework} }; }, }, + onPermissionRequest: approveAll, }); ``` ### Expand Shorthand Commands ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const SHORTCUTS: Record = { "/fix": "Please fix the errors in the code", "/explain": "Please explain this code in detail", @@ -280,12 +291,16 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Content Filtering ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const BLOCKED_PATTERNS = [ /password\s*[:=]/i, /api[_-]?key\s*[:=]/i, @@ -307,12 +322,16 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Enforce Prompt Length Limits ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const MAX_PROMPT_LENGTH = 10000; const session = await client.createSession({ @@ -328,46 +347,54 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Add User Preferences ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + interface UserPreferences { codeStyle: "concise" | "verbose"; preferredLanguage: string; experienceLevel: "beginner" | "intermediate" | "expert"; } +const client = new CopilotClient(); const session = await client.createSession({ hooks: { onUserPromptSubmitted: async (input) => { const prefs: UserPreferences = await loadUserPreferences(); - + const contextParts = []; - + if (prefs.codeStyle === "concise") { contextParts.push("User prefers concise code with minimal comments."); } else { contextParts.push("User prefers verbose code with detailed comments."); } - + if (prefs.experienceLevel === "beginner") { contextParts.push("Explain concepts in simple terms."); } - + return { additionalContext: contextParts.join(" "), }; }, }, + onPermissionRequest: approveAll, }); ``` ### Rate Limiting ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const promptTimestamps: number[] = []; const RATE_LIMIT = 10; // prompts const RATE_WINDOW = 60000; // 1 minute @@ -376,29 +403,33 @@ const session = await client.createSession({ hooks: { onUserPromptSubmitted: async (input) => { const now = Date.now(); - + // Remove timestamps outside the window while (promptTimestamps.length > 0 && promptTimestamps[0] < now - RATE_WINDOW) { promptTimestamps.shift(); } - + if (promptTimestamps.length >= RATE_LIMIT) { return { reject: true, rejectReason: `Rate limit exceeded. Please wait before sending more prompts.`, }; } - + promptTimestamps.push(now); return null; }, }, + onPermissionRequest: approveAll, }); ``` ### Prompt Templates ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const TEMPLATES: Record string> = { "bug:": (desc) => `I found a bug: ${desc} @@ -429,6 +460,7 @@ const session = await client.createSession({ return null; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/docs/integrations/microsoft-agent-framework.md b/docs/integrations/microsoft-agent-framework.md index 8e794759b..87fd24a09 100644 --- a/docs/integrations/microsoft-agent-framework.md +++ b/docs/integrations/microsoft-agent-framework.md @@ -159,8 +159,9 @@ You can also use Copilot SDK's native tool definition alongside MAF tools: Node.js / TypeScript (standalone SDK) ```typescript -import { CopilotClient, DefineTool } from "@github/copilot-sdk"; +import { CopilotClient, DefineTool, approveAll } from "@github/copilot-sdk"; +const client = new CopilotClient(); const getWeather = DefineTool({ name: "GetWeather", description: "Get the current weather for a given location.", @@ -168,11 +169,10 @@ const getWeather = DefineTool({ execute: async ({ location }) => `The weather in ${location} is sunny, 25°C.`, }); -const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4.1", tools: [getWeather], - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); await session.sendAndWait({ prompt: "What's the weather like in Seattle?" }); @@ -351,13 +351,13 @@ You can also stream directly through the Copilot SDK without MAF: Node.js / TypeScript (standalone SDK) ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4.1", streaming: true, - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); session.on("assistant.message_delta", (event) => { @@ -401,12 +401,12 @@ Use the MAF wrapper when you need to compose Copilot with other providers in orc ```typescript // Standalone SDK — full control, simpler setup -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4.1", - onPermissionRequest: async () => ({ kind: "approved" }), + onPermissionRequest: approveAll, }); const response = await session.sendAndWait({ prompt: "Explain this code" }); ``` diff --git a/docs/setup/azure-managed-identity.md b/docs/setup/azure-managed-identity.md index 40d87c5ba..c3d1821c1 100644 --- a/docs/setup/azure-managed-identity.md +++ b/docs/setup/azure-managed-identity.md @@ -124,7 +124,7 @@ class ManagedIdentityCopilotAgent: ```typescript import { DefaultAzureCredential } from "@azure/identity"; -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const credential = new DefaultAzureCredential(); const tokenResponse = await credential.getToken( @@ -141,6 +141,7 @@ const session = await client.createSession({ bearerToken: tokenResponse.token, wireApi: "responses", }, + onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: "Hello!" }); diff --git a/docs/setup/backend-services.md b/docs/setup/backend-services.md index 735adf4ff..b235019c7 100644 --- a/docs/setup/backend-services.md +++ b/docs/setup/backend-services.md @@ -90,7 +90,7 @@ Restart=always Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient({ cliUrl: "localhost:4321", @@ -99,6 +99,7 @@ const client = new CopilotClient({ const session = await client.createSession({ sessionId: `user-${userId}-${Date.now()}`, model: "gpt-4.1", + onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: req.body.message }); @@ -254,6 +255,9 @@ copilot --headless --port 4321 Pass individual user tokens when creating sessions. See [GitHub OAuth](./github-oauth.md) for the full flow. ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); // Your API receives user tokens from your auth layer app.post("/chat", authMiddleware, async (req, res) => { const client = new CopilotClient({ @@ -265,6 +269,7 @@ app.post("/chat", authMiddleware, async (req, res) => { const session = await client.createSession({ sessionId: `user-${req.user.id}-chat`, model: "gpt-4.1", + onPermissionRequest: approveAll, }); const response = await session.sendAndWait({ @@ -280,6 +285,8 @@ app.post("/chat", authMiddleware, async (req, res) => { Use your own API keys for the model provider. See [BYOK](../auth/byok.md) for details. ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + const client = new CopilotClient({ cliUrl: "localhost:4321", }); @@ -291,6 +298,7 @@ const session = await client.createSession({ baseUrl: "https://api.openai.com/v1", apiKey: process.env.OPENAI_API_KEY, }, + onPermissionRequest: approveAll, }); ``` @@ -316,7 +324,7 @@ flowchart TB ```typescript import express from "express"; -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const app = express(); app.use(express.json()); @@ -337,6 +345,7 @@ app.post("/api/chat", async (req, res) => { session = await client.createSession({ sessionId, model: "gpt-4.1", + onPermissionRequest: approveAll }); } @@ -353,7 +362,7 @@ app.listen(3000); ### Background Worker ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient({ cliUrl: process.env.CLI_URL || "localhost:4321", @@ -364,6 +373,7 @@ async function processJob(job: Job) { const session = await client.createSession({ sessionId: `job-${job.id}`, model: "gpt-4.1", + onPermissionRequest: approveAll }); const response = await session.sendAndWait({ diff --git a/docs/setup/bundled-cli.md b/docs/setup/bundled-cli.md index cdfe6df81..427177255 100644 --- a/docs/setup/bundled-cli.md +++ b/docs/setup/bundled-cli.md @@ -64,7 +64,7 @@ npm install @github/copilot Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; import path from "path"; const client = new CopilotClient({ @@ -72,7 +72,7 @@ const client = new CopilotClient({ cliPath: path.join(__dirname, "vendor", "copilot"), }); -const session = await client.createSession({ model: "gpt-4.1" }); +const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: "Hello!" }); console.log(response?.data.content); @@ -217,6 +217,8 @@ const client = new CopilotClient({ If you manage your own model provider keys, users don't need GitHub accounts at all: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + const client = new CopilotClient({ cliPath: path.join(__dirname, "vendor", "copilot"), }); @@ -228,6 +230,7 @@ const session = await client.createSession({ baseUrl: "https://api.openai.com/v1", apiKey: process.env.OPENAI_API_KEY, }, + onPermissionRequest: approveAll, }); ``` @@ -238,6 +241,8 @@ See the **[BYOK guide](../auth/byok.md)** for full details. Bundled apps typically want named sessions so users can resume conversations: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + const client = new CopilotClient({ cliPath: path.join(__dirname, "vendor", "copilot"), }); @@ -247,6 +252,7 @@ const sessionId = `project-${projectName}`; const session = await client.createSession({ sessionId, model: "gpt-4.1", + onPermissionRequest: approveAll, }); // User closes app... diff --git a/docs/setup/github-oauth.md b/docs/setup/github-oauth.md index 81d2b25a2..1db796ec7 100644 --- a/docs/setup/github-oauth.md +++ b/docs/setup/github-oauth.md @@ -119,7 +119,7 @@ Create a SDK client for each authenticated user, passing their token: Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; // Create a client for an authenticated user function createClientForUser(userToken: string): CopilotClient { @@ -134,6 +134,7 @@ const client = createClientForUser("gho_user_access_token"); const session = await client.createSession({ sessionId: `user-${userId}-session`, model: "gpt-4.1", + onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: "Hello!" }); diff --git a/docs/setup/local-cli.md b/docs/setup/local-cli.md index bb95a4d38..97ba8c700 100644 --- a/docs/setup/local-cli.md +++ b/docs/setup/local-cli.md @@ -34,10 +34,10 @@ The default configuration requires no options at all: Node.js / TypeScript ```typescript -import { CopilotClient } from "@github/copilot-sdk"; +import { CopilotClient, approveAll } from "@github/copilot-sdk"; const client = new CopilotClient(); -const session = await client.createSession({ model: "gpt-4.1" }); +const session = await client.createSession({ model: "gpt-4.1", onPermissionRequest: approveAll }); const response = await session.sendAndWait({ prompt: "Hello!" }); console.log(response?.data.content); @@ -192,10 +192,14 @@ The SDK picks these up automatically — no code changes needed. With the local CLI, sessions default to ephemeral. To create resumable sessions, provide your own session ID: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); // Create a named session const session = await client.createSession({ sessionId: "my-project-analysis", model: "gpt-4.1", + onPermissionRequest: approveAll, }); // Later, resume it diff --git a/docs/setup/scaling.md b/docs/setup/scaling.md index 325d9244d..0fbb544d6 100644 --- a/docs/setup/scaling.md +++ b/docs/setup/scaling.md @@ -279,6 +279,8 @@ flowchart TB ```typescript // Route sessions to CLI servers +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + class CLILoadBalancer { private servers: string[]; private currentIndex = 0; @@ -310,6 +312,8 @@ class CLILoadBalancer { } } +const client = new CopilotClient(); + const lb = new CLILoadBalancer([ "cli-1:4321", "cli-2:4321", @@ -323,6 +327,7 @@ app.post("/chat", async (req, res) => { const session = await client.createSession({ sessionId: `user-${req.user.id}-chat`, model: "gpt-4.1", + onPermissionRequest: approveAll, }); const response = await session.sendAndWait({ prompt: req.body.message }); @@ -379,6 +384,10 @@ flowchart TB **Session lifecycle management** is key to vertical scaling: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); + // Limit concurrent active sessions class SessionManager { private activeSessions = new Map(); @@ -403,6 +412,7 @@ class SessionManager { const session = await client.createSession({ sessionId, model: "gpt-4.1", + onPermissionRequest: approveAll, }); this.activeSessions.set(sessionId, session); @@ -446,9 +456,13 @@ flowchart LR For stateless API endpoints where each request is independent: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); app.post("/api/analyze", async (req, res) => { const session = await client.createSession({ model: "gpt-4.1", + onPermissionRequest: approveAll, }); try { @@ -467,6 +481,9 @@ app.post("/api/analyze", async (req, res) => { For conversational interfaces or long-running workflows: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); // Create a resumable session app.post("/api/chat/start", async (req, res) => { const sessionId = `user-${req.user.id}-${Date.now()}`; @@ -478,6 +495,7 @@ app.post("/api/chat/start", async (req, res) => { enabled: true, backgroundCompactionThreshold: 0.80, }, + onPermissionRequest: approveAll, }); res.json({ sessionId }); diff --git a/docs/troubleshooting/compatibility.md b/docs/troubleshooting/compatibility.md index 1a322b88c..3dfc38e28 100644 --- a/docs/troubleshooting/compatibility.md +++ b/docs/troubleshooting/compatibility.md @@ -189,6 +189,9 @@ The SDK uses a **deny-by-default** permission model. All permission requests (fi Instead of `--allow-all-paths` or `--yolo`, use the permission handler: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ onPermissionRequest: approveAll, }); @@ -213,12 +216,16 @@ Instead of `/compact`, configure automatic compaction or trigger it manually: ```typescript // Automatic compaction via config +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ infiniteSessions: { enabled: true, backgroundCompactionThreshold: 0.80, // Start background compaction at 80% context utilization bufferExhaustionThreshold: 0.95, // Block and compact at 95% context utilization }, + onPermissionRequest: approveAll, }); // Manual compaction (experimental) diff --git a/docs/troubleshooting/debugging.md b/docs/troubleshooting/debugging.md index 146d3fd5a..ec877709c 100644 --- a/docs/troubleshooting/debugging.md +++ b/docs/troubleshooting/debugging.md @@ -393,10 +393,14 @@ const client = new CopilotClient({ 1. **Verify tool registration:** ```typescript + import { CopilotClient, approveAll } from "@github/copilot-sdk"; + + const client = new CopilotClient(); const session = await client.createSession({ tools: [myTool], + onPermissionRequest: approveAll, }); - + // Check registered tools console.log("Registered tools:", session.getTools?.()); ``` @@ -424,7 +428,7 @@ const client = new CopilotClient({ handler: async (args) => { // Must return something JSON-serializable return { success: true, data: "result" }; - + // Don't return undefined or non-serializable objects } ``` diff --git a/nodejs/README.md b/nodejs/README.md index e9d23c529..df2435531 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -60,6 +60,9 @@ await client.stop(); Sessions also support `Symbol.asyncDispose` for use with [`await using`](https://github.com/tc39/proposal-explicit-resource-management) (TypeScript 5.2+/Node.js 18.0+): ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); await using session = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll }); // session is automatically disconnected when leaving scope ``` @@ -338,9 +341,13 @@ await session.send({ prompt: "What does the most recent jpg in this directory po Enable streaming to receive assistant response chunks as they're generated: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", streaming: true, + onPermissionRequest: approveAll, }); // Wait for completion using typed event handlers @@ -408,7 +415,7 @@ You can let the CLI call back into your process when the model needs capabilitie ```ts import { z } from "zod"; -import { CopilotClient, defineTool } from "@github/copilot-sdk"; +import { CopilotClient, defineTool, approveAll } from "@github/copilot-sdk"; const session = await client.createSession({ model: "gpt-5", @@ -424,6 +431,7 @@ const session = await client.createSession({ }, }), ], + onPermissionRequest: approveAll }); ``` @@ -460,6 +468,9 @@ defineTool("safe_lookup", { Control the system prompt using `systemMessage` in session config: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", systemMessage: { @@ -470,6 +481,7 @@ const session = await client.createSession({ `, }, + onPermissionRequest: approveAll, }); ``` @@ -478,12 +490,16 @@ The SDK auto-injects environment context, tool instructions, and security guardr For full control (removes all guardrails), use `mode: "replace"`: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", systemMessage: { mode: "replace", content: "You are a helpful assistant.", }, + onPermissionRequest: approveAll, }); ``` @@ -492,8 +508,12 @@ const session = await client.createSession({ By default, sessions use **infinite sessions** which automatically manage context window limits through background compaction and persist state to a workspace directory. ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); + // Default: infinite sessions enabled with default thresholds -const session = await client.createSession({ model: "gpt-5" }); +const session = await client.createSession({ model: "gpt-5",onPermissionRequest: approveAll, }); // Access the workspace path for checkpoints and files console.log(session.workspacePath); @@ -507,12 +527,14 @@ const session = await client.createSession({ backgroundCompactionThreshold: 0.80, // Start compacting at 80% context usage bufferExhaustionThreshold: 0.95, // Block at 95% until compaction completes }, + onPermissionRequest: approveAll, }); // Disable infinite sessions const session = await client.createSession({ model: "gpt-5", infiniteSessions: { enabled: false }, + onPermissionRequest: approveAll }); ``` @@ -524,8 +546,11 @@ When enabled, sessions emit compaction events: ### Multiple Sessions ```typescript -const session1 = await client.createSession({ model: "gpt-5" }); -const session2 = await client.createSession({ model: "claude-sonnet-4.5" }); +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); +const session1 = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll, }); +const session2 = await client.createSession({ model: "claude-sonnet-4.5", onPermissionRequest: approveAll, }); // Both sessions are independent await session1.sendAndWait({ prompt: "Hello from session 1" }); @@ -535,9 +560,13 @@ await session2.sendAndWait({ prompt: "Hello from session 2" }); ### Custom Session IDs ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ sessionId: "my-custom-session-id", model: "gpt-5", + onPermissionRequest: approveAll, }); ``` @@ -572,6 +601,9 @@ The SDK supports custom OpenAI-compatible API providers (BYOK - Bring Your Own K **Example with Ollama:** ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "deepseek-coder-v2:16b", // Required when using custom provider provider: { @@ -579,6 +611,7 @@ const session = await client.createSession({ baseUrl: "http://localhost:11434/v1", // Ollama endpoint // apiKey not required for Ollama }, + onPermissionRequest: approveAll, }); await session.sendAndWait({ prompt: "Hello!" }); @@ -587,6 +620,9 @@ await session.sendAndWait({ prompt: "Hello!" }); **Example with custom OpenAI-compatible API:** ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4", provider: { @@ -594,12 +630,16 @@ const session = await client.createSession({ baseUrl: "https://my-api.example.com/v1", apiKey: process.env.MY_API_KEY, }, + onPermissionRequest: approveAll, }); ``` **Example with Azure OpenAI:** ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-4", provider: { @@ -610,6 +650,7 @@ const session = await client.createSession({ apiVersion: "2024-10-21", }, }, + onPermissionRequest: approveAll, }); ``` @@ -674,6 +715,7 @@ Use the built-in `approveAll` helper to allow every tool call without any checks ```typescript import { CopilotClient, approveAll } from "@github/copilot-sdk"; +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", onPermissionRequest: approveAll, @@ -685,8 +727,9 @@ const session = await client.createSession({ Provide your own function to inspect each request and apply custom logic: ```typescript -import type { PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk"; +import type { CopilotClient, PermissionRequest, PermissionRequestResult } from "@github/copilot-sdk"; +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", onPermissionRequest: (request: PermissionRequest, invocation): PermissionRequestResult => { @@ -711,7 +754,7 @@ const session = await client.createSession({ } return { kind: "approved" }; - }, + } }); ``` @@ -730,6 +773,9 @@ const session = await client.createSession({ Pass `onPermissionRequest` when resuming a session too — it is required: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.resumeSession("session-id", { onPermissionRequest: approveAll, }); @@ -744,6 +790,9 @@ To let a specific custom tool bypass the permission prompt entirely, set `skipPe Enable the agent to ask questions to the user using the `ask_user` tool by providing an `onUserInputRequest` handler: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", onUserInputRequest: async (request, invocation) => { @@ -762,6 +811,7 @@ const session = await client.createSession({ wasFreeform: true, // Whether the answer was freeform (not from choices) }; }, + onPermissionRequest: approveAll, }); ``` @@ -770,6 +820,9 @@ const session = await client.createSession({ Hook into session lifecycle events by providing handlers in the `hooks` configuration: ```typescript +import { CopilotClient, approveAll } from "@github/copilot-sdk"; + +const client = new CopilotClient(); const session = await client.createSession({ model: "gpt-5", hooks: { @@ -822,6 +875,7 @@ const session = await client.createSession({ }; }, }, + onPermissionRequest: approveAll, }); ``` diff --git a/nodejs/examples/basic-example.ts b/nodejs/examples/basic-example.ts index c20a85af0..dc4d002c3 100644 --- a/nodejs/examples/basic-example.ts +++ b/nodejs/examples/basic-example.ts @@ -3,7 +3,7 @@ *--------------------------------------------------------------------------------------------*/ import { z } from "zod"; -import { CopilotClient, defineTool } from "../src/index.js"; +import { CopilotClient, defineTool, approveAll } from "../src/index.js"; console.log("🚀 Starting Copilot SDK Example\n"); @@ -22,7 +22,7 @@ const lookupFactTool = defineTool("lookup_fact", { // Create client - will auto-start CLI server (searches PATH for "copilot") const client = new CopilotClient({ logLevel: "info" }); -const session = await client.createSession({ tools: [lookupFactTool] }); +const session = await client.createSession({ tools: [lookupFactTool], onPermissionRequest: approveAll }); console.log(`✅ Session created: ${session.sessionId}\n`); // Listen to events