Skip to content

Commit 07bdcd1

Browse files
fix: add onPermissionRequest handlers to E2E tests for default-deny behavior
Tests that use built-in tools (file reads, shell commands, MCP) now need an onPermissionRequest handler to approve tool execution, since the SDK now sends requestPermission=true by default. - Node.js: hooks.test.ts, tools.test.ts, session.test.ts, mcp_and_agents.test.ts - Python: test_hooks.py, test_tools.py, test_mcp_and_agents.py + fix chat.py formatting - Go: mcp_and_agents_test.go - .NET: HooksTests.cs, ToolsTests.cs, McpAndAgentsTests.cs, SessionTests.cs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent ca0e7f7 commit 07bdcd1

13 files changed

Lines changed: 61 additions & 14 deletions

File tree

dotnet/test/HooksTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public async Task Should_Invoke_PreToolUse_Hook_When_Model_Runs_A_Tool()
1717
CopilotSession? session = null;
1818
session = await Client.CreateSessionAsync(new SessionConfig
1919
{
20+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
2021
Hooks = new SessionHooks
2122
{
2223
OnPreToolUse = (input, invocation) =>
@@ -52,6 +53,7 @@ public async Task Should_Invoke_PostToolUse_Hook_After_Model_Runs_A_Tool()
5253
CopilotSession? session = null;
5354
session = await Client.CreateSessionAsync(new SessionConfig
5455
{
56+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
5557
Hooks = new SessionHooks
5658
{
5759
OnPostToolUse = (input, invocation) =>
@@ -89,6 +91,7 @@ public async Task Should_Invoke_Both_PreToolUse_And_PostToolUse_Hooks_For_Single
8991

9092
var session = await Client.CreateSessionAsync(new SessionConfig
9193
{
94+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
9295
Hooks = new SessionHooks
9396
{
9497
OnPreToolUse = (input, invocation) =>
@@ -130,6 +133,7 @@ public async Task Should_Deny_Tool_Execution_When_PreToolUse_Returns_Deny()
130133

131134
var session = await Client.CreateSessionAsync(new SessionConfig
132135
{
136+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
133137
Hooks = new SessionHooks
134138
{
135139
OnPreToolUse = (input, invocation) =>

dotnet/test/McpAndAgentsTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ public async Task Should_Pass_Literal_Env_Values_To_Mcp_Server_Subprocess()
279279

280280
var session = await Client.CreateSessionAsync(new SessionConfig
281281
{
282-
McpServers = mcpServers
282+
McpServers = mcpServers,
283+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
283284
});
284285

285286
Assert.Matches(@"^[a-f0-9-]+$", session.SessionId);

dotnet/test/SessionTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,10 @@ public async Task Should_Receive_Session_Events()
333333
[Fact]
334334
public async Task Send_Returns_Immediately_While_Events_Stream_In_Background()
335335
{
336-
var session = await Client.CreateSessionAsync();
336+
var session = await Client.CreateSessionAsync(new SessionConfig
337+
{
338+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
339+
});
337340
var events = new List<string>();
338341

339342
session.On(evt => events.Add(evt.Type));

dotnet/test/ToolsTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ await File.WriteAllTextAsync(
2121
Path.Combine(Ctx.WorkDir, "README.md"),
2222
"# ELIZA, the only chatbot you'll ever need");
2323

24-
var session = await Client.CreateSessionAsync();
24+
var session = await Client.CreateSessionAsync(new SessionConfig
25+
{
26+
OnPermissionRequest = (request, invocation) => Task.FromResult(new PermissionRequestResult { Kind = "approved" }),
27+
});
2528

2629
await session.SendAsync(new MessageOptions
2730
{

go/internal/e2e/mcp_and_agents_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ func TestMCPServers(t *testing.T) {
127127

128128
session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{
129129
MCPServers: mcpServers,
130+
OnPermissionRequest: func(request copilot.PermissionRequest, invocation copilot.PermissionInvocation) (copilot.PermissionRequestResult, error) {
131+
return copilot.PermissionRequestResult{Kind: "approved"}, nil
132+
},
130133
})
131134
if err != nil {
132135
t.Fatalf("Failed to create session: %v", err)

nodejs/test/e2e/hooks.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ describe("Session hooks", async () => {
2020
const preToolUseInputs: PreToolUseHookInput[] = [];
2121

2222
const session = await client.createSession({
23+
onPermissionRequest: async () => ({ kind: "approved" as const }),
2324
hooks: {
2425
onPreToolUse: async (input, invocation) => {
2526
preToolUseInputs.push(input);
@@ -50,6 +51,7 @@ describe("Session hooks", async () => {
5051
const postToolUseInputs: PostToolUseHookInput[] = [];
5152

5253
const session = await client.createSession({
54+
onPermissionRequest: async () => ({ kind: "approved" as const }),
5355
hooks: {
5456
onPostToolUse: async (input, invocation) => {
5557
postToolUseInputs.push(input);
@@ -81,6 +83,7 @@ describe("Session hooks", async () => {
8183
const postToolUseInputs: PostToolUseHookInput[] = [];
8284

8385
const session = await client.createSession({
86+
onPermissionRequest: async () => ({ kind: "approved" as const }),
8487
hooks: {
8588
onPreToolUse: async (input) => {
8689
preToolUseInputs.push(input);

nodejs/test/e2e/mcp_and_agents.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ describe("MCP Servers and Custom Agents", async () => {
108108

109109
const session = await client.createSession({
110110
mcpServers,
111+
onPermissionRequest: async () => ({ kind: "approved" as const }),
111112
});
112113

113114
expect(session.sessionId).toBeDefined();

nodejs/test/e2e/session.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@ describe("Send Blocking Behavior", async () => {
366366
const { copilotClient: client } = await createSdkTestContext();
367367

368368
it("send returns immediately while events stream in background", async () => {
369-
const session = await client.createSession();
369+
const session = await client.createSession({
370+
onPermissionRequest: async () => ({ kind: "approved" as const }),
371+
});
370372

371373
const events: string[] = [];
372374
session.on((event) => {

nodejs/test/e2e/tools.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ describe("Custom tools", async () => {
1515
it("invokes built-in tools", async () => {
1616
await writeFile(join(workDir, "README.md"), "# ELIZA, the only chatbot you'll ever need");
1717

18-
const session = await client.createSession();
18+
const session = await client.createSession({
19+
onPermissionRequest: async () => ({ kind: "approved" as const }),
20+
});
1921
const assistantMessage = await session.sendAndWait({
2022
prompt: "What's the first line of README.md in this directory?",
2123
});

python/e2e/test_hooks.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ async def on_pre_tool_use(input_data, invocation):
2121
# Allow the tool to run
2222
return {"permissionDecision": "allow"}
2323

24-
session = await ctx.client.create_session({"hooks": {"on_pre_tool_use": on_pre_tool_use}})
24+
session = await ctx.client.create_session(
25+
{
26+
"hooks": {"on_pre_tool_use": on_pre_tool_use},
27+
"on_permission_request": lambda _req, _inv: {"kind": "approved"},
28+
}
29+
)
2530

2631
# Create a file for the model to read
2732
write_file(ctx.work_dir, "hello.txt", "Hello from the test!")
@@ -49,7 +54,12 @@ async def on_post_tool_use(input_data, invocation):
4954
assert invocation["session_id"] == session.session_id
5055
return None
5156

52-
session = await ctx.client.create_session({"hooks": {"on_post_tool_use": on_post_tool_use}})
57+
session = await ctx.client.create_session(
58+
{
59+
"hooks": {"on_post_tool_use": on_post_tool_use},
60+
"on_permission_request": lambda _req, _inv: {"kind": "approved"},
61+
}
62+
)
5363

5464
# Create a file for the model to read
5565
write_file(ctx.work_dir, "world.txt", "World from the test!")
@@ -87,7 +97,8 @@ async def on_post_tool_use(input_data, invocation):
8797
"hooks": {
8898
"on_pre_tool_use": on_pre_tool_use,
8999
"on_post_tool_use": on_post_tool_use,
90-
}
100+
},
101+
"on_permission_request": lambda _req, _inv: {"kind": "approved"},
91102
}
92103
)
93104

@@ -118,7 +129,12 @@ async def on_pre_tool_use(input_data, invocation):
118129
# Deny all tool calls
119130
return {"permissionDecision": "deny"}
120131

121-
session = await ctx.client.create_session({"hooks": {"on_pre_tool_use": on_pre_tool_use}})
132+
session = await ctx.client.create_session(
133+
{
134+
"hooks": {"on_pre_tool_use": on_pre_tool_use},
135+
"on_permission_request": lambda _req, _inv: {"kind": "approved"},
136+
}
137+
)
122138

123139
# Create a file
124140
original_content = "Original content that should not be modified"

0 commit comments

Comments
 (0)