@@ -363,4 +363,115 @@ void testShouldDenyToolOperationsWhenHandlerExplicitlyDeniesAfterResume(TestInfo
363363 session2 .close ();
364364 }
365365 }
366+
367+ /**
368+ * Verifies that a permission handler returning {@code noResult} is handled
369+ * correctly — the handler is called, and the session can be aborted afterward.
370+ *
371+ * @see Snapshot: permissions/should_deny_permission_with_noresult_kind
372+ */
373+ @ Test
374+ void testShouldDenyPermissionWithNoResultKind () throws Exception {
375+ ctx .configureForTest ("permissions" , "should_deny_permission_with_noresult_kind" );
376+
377+ var permissionCalled = new CompletableFuture <Boolean >();
378+
379+ try (CopilotClient client = ctx .createClient ()) {
380+ CopilotSession session = client
381+ .createSession (new SessionConfig ().setOnPermissionRequest ((request , invocation ) -> {
382+ permissionCalled .complete (true );
383+ return CompletableFuture .completedFuture (
384+ new PermissionRequestResult ().setKind (PermissionRequestResultKind .NO_RESULT ));
385+ })).get ();
386+
387+ session .send (new MessageOptions ().setPrompt ("Run 'node --version'" ));
388+
389+ assertTrue (permissionCalled .get (30 , TimeUnit .SECONDS ),
390+ "Expected the no-result permission handler to be called." );
391+
392+ session .abort ().get (10 , TimeUnit .SECONDS );
393+ session .close ();
394+ }
395+ }
396+
397+ /**
398+ * Verifies that the runtime short-circuits the permission handler when
399+ * {@code session.permissions.setApproveAll(true)} has been called.
400+ *
401+ * @see Snapshot:
402+ * permissions/should_short_circuit_permission_handler_when_set_approve_all_enabled
403+ */
404+ @ Test
405+ void testShouldShortCircuitPermissionHandlerWhenSetApproveAllEnabled () throws Exception {
406+ ctx .configureForTest ("permissions" , "should_short_circuit_permission_handler_when_set_approve_all_enabled" );
407+
408+ var handlerCallCount = new int []{0 };
409+
410+ try (CopilotClient client = ctx .createClient ()) {
411+ CopilotSession session = client
412+ .createSession (new SessionConfig ().setOnPermissionRequest ((request , invocation ) -> {
413+ handlerCallCount [0 ]++;
414+ return CompletableFuture .completedFuture (
415+ new PermissionRequestResult ().setKind (PermissionRequestResultKind .APPROVED ));
416+ })).get ();
417+
418+ // Set approve-all so the runtime short-circuits
419+ var setResult = session .getRpc ().permissions
420+ .setApproveAll (new com .github .copilot .sdk .generated .rpc .SessionPermissionsSetApproveAllParams (
421+ session .getSessionId (), true ))
422+ .get (10 , TimeUnit .SECONDS );
423+ assertTrue (setResult .success (), "setApproveAll should succeed" );
424+
425+ AssistantMessageEvent response = session
426+ .sendAndWait (new MessageOptions ().setPrompt ("Run 'echo test' and tell me what happens" ))
427+ .get (60 , TimeUnit .SECONDS );
428+ assertNotNull (response );
429+
430+ // Handler should not have been called since runtime approves all
431+ assertEquals (0 , handlerCallCount [0 ],
432+ "Permission handler should not be called when setApproveAll is enabled" );
433+
434+ session .close ();
435+ }
436+ }
437+
438+ /**
439+ * Verifies that the SDK correctly waits for a slow permission handler before
440+ * completing tool execution.
441+ *
442+ * @see Snapshot: permissions/should_wait_for_slow_permission_handler
443+ */
444+ @ Test
445+ void testShouldWaitForSlowPermissionHandler () throws Exception {
446+ ctx .configureForTest ("permissions" , "should_wait_for_slow_permission_handler" );
447+
448+ var handlerEntered = new CompletableFuture <Void >();
449+ var releaseHandler = new CompletableFuture <Void >();
450+
451+ try (CopilotClient client = ctx .createClient ()) {
452+ CopilotSession session = client
453+ .createSession (new SessionConfig ().setOnPermissionRequest ((request , invocation ) -> {
454+ handlerEntered .complete (null );
455+ return releaseHandler .thenApply (
456+ v -> new PermissionRequestResult ().setKind (PermissionRequestResultKind .APPROVED ));
457+ })).get ();
458+
459+ // Capture the sendAndWait future before awaiting it so we can interact with the
460+ // handler
461+ CompletableFuture <AssistantMessageEvent > responseFuture = session
462+ .sendAndWait (new MessageOptions ().setPrompt ("Run 'echo slow_handler_test'" ));
463+
464+ // Wait for permission handler to be entered
465+ handlerEntered .get (30 , TimeUnit .SECONDS );
466+
467+ // Release the handler
468+ releaseHandler .complete (null );
469+
470+ // Session should complete successfully
471+ AssistantMessageEvent message = responseFuture .get (60 , TimeUnit .SECONDS );
472+ assertNotNull (message );
473+
474+ session .close ();
475+ }
476+ }
366477}
0 commit comments