Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/auth/byok.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const session = await client.createSession({
wireApi: "responses", // Use "completions" for older models
apiKey: process.env.FOUNDRY_API_KEY,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

session.on("assistant.message", (event) => {
Expand Down Expand Up @@ -350,12 +351,14 @@ When using BYOK, the `model` parameter is **required**:
// ❌ Error: Model required with custom provider
const session = await client.createSession({
provider: { type: "openai", baseUrl: "..." },
onPermissionRequest: async () => ({ kind: "approved" }),
});

// ✅ Correct: Model specified
const session = await client.createSession({
model: "gpt-4", // Required!
provider: { type: "openai", baseUrl: "..." },
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down
1 change: 1 addition & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ const session = await client.createSession({
backgroundCompactionThreshold: 0.80, // Start background compaction at 80% context utilization
bufferExhaustionThreshold: 0.95, // Block and compact at 95% context utilization
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down
3 changes: 2 additions & 1 deletion docs/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,9 @@ const client = new CopilotClient({
```typescript
const session = await client.createSession({
tools: [myTool],
onPermissionRequest: async () => ({ kind: "approved" }),
});

// Check registered tools
console.log("Registered tools:", session.getTools?.());
```
Expand Down
10 changes: 8 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Before you begin, make sure you have:

- **GitHub Copilot CLI** installed and authenticated ([Installation guide](https://docs.github.com/en/copilot/how-tos/set-up/install-copilot-cli))
- Your preferred language runtime:
- **Node.js** 18+ or **Python** 3.8+ or **Go** 1.21+ or **.NET** 8.0+
- **Node.js** 22.13.0+ / 23.5.0+ / 24+ or **Python** 3.8+ or **Go** 1.21+ or **.NET** 8.0+

Verify the CLI is working:

Expand Down Expand Up @@ -105,7 +105,7 @@ Create `index.ts`:
import { CopilotClient } 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: async () => ({ kind: "approved" }) });

const response = await session.sendAndWait({ prompt: "What is 2 + 2?" });
console.log(response?.data.content);
Expand Down Expand Up @@ -248,6 +248,7 @@ const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
onPermissionRequest: async () => ({ kind: "approved" }),
});

// Listen for response chunks
Expand Down Expand Up @@ -624,6 +625,7 @@ const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
onPermissionRequest: async () => ({ kind: "approved" }),
});

session.on("assistant.message_delta", (event) => {
Expand Down Expand Up @@ -876,6 +878,7 @@ const session = await client.createSession({
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
onPermissionRequest: async () => ({ kind: "approved" }),
});

session.on("assistant.message_delta", (event) => {
Expand Down Expand Up @@ -1221,6 +1224,7 @@ const session = await client.createSession({
url: "https://api.githubcopilot.com/mcp/",
},
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand All @@ -1238,6 +1242,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: async () => ({ kind: "approved" }),
});
```

Expand All @@ -1250,6 +1255,7 @@ const session = await client.createSession({
systemMessage: {
content: "You are a helpful assistant for our engineering team. Always be concise.",
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down
31 changes: 18 additions & 13 deletions docs/guides/session-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const client = new CopilotClient();
const session = await client.createSession({
sessionId: "user-123-task-456",
model: "gpt-5.2-codex",
onPermissionRequest: async () => ({ kind: "approved" }),
});

// Do some work...
Expand Down Expand Up @@ -111,10 +112,10 @@ flowchart LR
subgraph Day1["Day 1"]
A1[Client A:<br/>createSession] --> A2[Work...]
end

A2 --> S[(💾 Storage:<br/>~/.copilot/session-state/)]
S --> B1

subgraph Day2["Day 2"]
B1[Client B:<br/>resumeSession] --> B2[Continue]
end
Expand All @@ -124,7 +125,7 @@ flowchart LR

```typescript
// Resume from a different client instance (or after restart)
const session = await client.resumeSession("user-123-task-456");
const session = await client.resumeSession("user-123-task-456", { onPermissionRequest: async () => ({ kind: "approved" }) });

// Continue where you left off
await session.sendAndWait({ prompt: "What did we discuss earlier?" });
Expand Down Expand Up @@ -192,6 +193,7 @@ When resuming a session, you can optionally reconfigure many settings. This is u
const session = await client.resumeSession("user-123-task-456", {
model: "claude-sonnet-4", // Switch to a different model
reasoningEffort: "high", // Increase reasoning effort
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand All @@ -210,6 +212,7 @@ const session = await client.createSession({
apiKey: process.env.AZURE_OPENAI_KEY,
deploymentId: "my-gpt-deployment",
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

// When resuming, you MUST re-provide the provider config
Expand All @@ -220,6 +223,7 @@ const resumed = await client.resumeSession("user-123-task-456", {
apiKey: process.env.AZURE_OPENAI_KEY, // Required again
deploymentId: "my-gpt-deployment",
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down Expand Up @@ -311,7 +315,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) {
Expand All @@ -333,7 +337,7 @@ When a task completes, destroy the session explicitly rather than waiting for ti
try {
// Do work...
await session.sendAndWait({ prompt: "Complete the task" });

// Task complete - clean up
await session.destroy();
} catch (error) {
Expand Down Expand Up @@ -408,12 +412,12 @@ async function resumeSessionWithAuth(
): Promise<Session> {
// 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);

return client.resumeSession(sessionId, { onPermissionRequest: async () => ({ kind: "approved" }) });
}
```

Expand Down Expand Up @@ -446,10 +450,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
Expand All @@ -469,6 +473,7 @@ const session = await client.createSession({
backgroundCompactionThreshold: 0.80, // Start compaction at 80% context
bufferExhaustionThreshold: 0.95, // Block at 95% if needed
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down Expand Up @@ -499,11 +504,11 @@ async function withSessionLock<T>(
): Promise<T> {
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 {
Expand All @@ -513,7 +518,7 @@ async function withSessionLock<T>(

// Usage
await withSessionLock("user-123-task-456", async () => {
const session = await client.resumeSession("user-123-task-456");
const session = await client.resumeSession("user-123-task-456", { onPermissionRequest: async () => ({ kind: "approved" }) });
await session.sendAndWait({ prompt: "Continue the task" });
});
```
Expand Down
1 change: 1 addition & 0 deletions docs/guides/setup/azure-managed-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ const session = await client.createSession({
bearerToken: tokenResponse.token,
wireApi: "responses",
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({ prompt: "Hello!" });
Expand Down
7 changes: 6 additions & 1 deletion docs/guides/setup/backend-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ const client = new CopilotClient({
const session = await client.createSession({
sessionId: `user-${userId}-${Date.now()}`,
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({ prompt: req.body.message });
Expand Down Expand Up @@ -213,6 +214,7 @@ app.post("/chat", authMiddleware, async (req, res) => {
const session = await client.createSession({
sessionId: `user-${req.user.id}-chat`,
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({
Expand All @@ -239,6 +241,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down Expand Up @@ -280,11 +283,12 @@ app.post("/api/chat", async (req, res) => {
// Create or resume session
let session;
try {
session = await client.resumeSession(sessionId);
session = await client.resumeSession(sessionId, { onPermissionRequest: async () => ({ kind: "approved" }) });
} catch {
session = await client.createSession({
sessionId,
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});
}

Expand Down Expand Up @@ -312,6 +316,7 @@ async function processJob(job: Job) {
const session = await client.createSession({
sessionId: `job-${job.id}`,
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({
Expand Down
6 changes: 4 additions & 2 deletions docs/guides/setup/bundled-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: async () => ({ kind: "approved" }) });
const response = await session.sendAndWait({ prompt: "Hello!" });
console.log(response?.data.content);

Expand Down Expand Up @@ -200,6 +200,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand All @@ -219,11 +220,12 @@ const sessionId = `project-${projectName}`;
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});

// User closes app...
// Later, resume where they left off
const resumed = await client.resumeSession(sessionId);
const resumed = await client.resumeSession(sessionId, { onPermissionRequest: async () => ({ kind: "approved" }) });
```

Session state persists at `~/.copilot/session-state/{sessionId}/`.
Expand Down
5 changes: 5 additions & 0 deletions docs/guides/setup/byok.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({ prompt: "Hello!" });
Expand Down Expand Up @@ -255,6 +256,7 @@ app.post("/chat", authMiddleware, async (req, res) => {
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY, // Your key, your billing
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({ prompt: req.body.message });
Expand Down Expand Up @@ -303,6 +305,7 @@ async function createSessionForCustomer(customerId: string) {
baseUrl: config.baseUrl,
apiKey: config.apiKey,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
}
```
Expand All @@ -321,6 +324,7 @@ const session = await client.createSession({
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
onPermissionRequest: async () => ({ kind: "approved" }),
});

// Resume later — must re-provide provider config
Expand All @@ -330,6 +334,7 @@ const resumed = await client.resumeSession("task-123", {
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY, // Required again
},
onPermissionRequest: async () => ({ kind: "approved" }),
});
```

Expand Down
1 change: 1 addition & 0 deletions docs/guides/setup/github-oauth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: async () => ({ kind: "approved" }),
});

const response = await session.sendAndWait({ prompt: "Hello!" });
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/setup/local-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The default configuration requires no options at all:
import { CopilotClient } 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: async () => ({ kind: "approved" }) });

const response = await session.sendAndWait({ prompt: "Hello!" });
console.log(response?.data.content);
Expand Down Expand Up @@ -173,10 +173,11 @@ With the local CLI, sessions default to ephemeral. To create resumable sessions,
const session = await client.createSession({
sessionId: "my-project-analysis",
model: "gpt-4.1",
onPermissionRequest: async () => ({ kind: "approved" }),
});

// Later, resume it
const resumed = await client.resumeSession("my-project-analysis");
const resumed = await client.resumeSession("my-project-analysis", { onPermissionRequest: async () => ({ kind: "approved" }) });
```

Session state is stored locally at `~/.copilot/session-state/{sessionId}/`.
Expand Down
Loading
Loading