Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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