@@ -732,12 +732,71 @@ const makeCopilotAdapter = (options?: CopilotAdapterLiveOptions) =>
732732 toProcessError ( threadId , "Failed to start GitHub Copilot CLI client." , cause ) ,
733733 } ) ;
734734
735+ const pendingApprovals = new Map < ApprovalRequestId , PendingApproval > ( ) ;
736+ let context : CopilotSessionContext | undefined ;
737+ const onPermissionRequest = ( request : CopilotPermissionRequest ) => {
738+ if ( input . runtimeMode === "full-access" ) {
739+ return { kind : "approved" } satisfies CopilotPermissionRequestResult ;
740+ }
741+ const requestId = ApprovalRequestId . makeUnsafe (
742+ `copilot-permission:${ crypto . randomUUID ( ) } ` ,
743+ ) ;
744+ let resolve ! : ( decision : ProviderApprovalDecision ) => void ;
745+ const promise = new Promise < ProviderApprovalDecision > ( ( resolvePromise ) => {
746+ resolve = resolvePromise ;
747+ } ) ;
748+ const detail = permissionDetail ( request ) ;
749+ pendingApprovals . set ( requestId , {
750+ requestType : inferRequestType ( request ) ,
751+ ...( detail ? { detail } : { } ) ,
752+ promise,
753+ resolve,
754+ } ) ;
755+ void Effect . runPromise (
756+ emitEvent ( {
757+ ...makeBase (
758+ threadId ,
759+ context ?. turnState
760+ ? { turnId : context . turnState . turnId , requestId }
761+ : { requestId } ,
762+ ) ,
763+ type : "request.opened" ,
764+ payload : {
765+ requestType : inferRequestType ( request ) ,
766+ ...( detail ? { detail } : { } ) ,
767+ args : request ,
768+ } ,
769+ } ) ,
770+ ) ;
771+ return promise . then ( ( decision ) => {
772+ const result = mapApprovalDecisionToPermissionResult ( decision ) ;
773+ void Effect . runPromise (
774+ emitEvent ( {
775+ ...makeBase (
776+ threadId ,
777+ context ?. turnState
778+ ? { turnId : context . turnState . turnId , requestId }
779+ : { requestId } ,
780+ ) ,
781+ type : "request.resolved" ,
782+ payload : {
783+ requestType : inferRequestType ( request ) ,
784+ decision : result . kind ,
785+ resolution : result ,
786+ } ,
787+ } ) . pipe ( Effect . ensuring ( Effect . sync ( ( ) => pendingApprovals . delete ( requestId ) ) ) ) ,
788+ ) ;
789+ return result ;
790+ } ) ;
791+ } ;
792+
735793 const reasonEffort = input . modelOptions ?. copilot ?. reasoningEffort ;
736794 const sessionConfig = {
737795 ...( input . model ? { model : input . model } : { } ) ,
738796 ...( reasonEffort ? { reasoningEffort : reasonEffort } : { } ) ,
739797 workingDirectory : resolvedCwd ,
740798 streaming : true ,
799+ onPermissionRequest,
741800 ...( providerOptions . configDir ? { configDir : providerOptions . configDir } : { } ) ,
742801 } ;
743802
@@ -747,11 +806,9 @@ const makeCopilotAdapter = (options?: CopilotAdapterLiveOptions) =>
747806 resumeCursor
748807 ? client . resumeSession ( resumeCursor . sessionId , {
749808 ...sessionConfig ,
750- onPermissionRequest : ( ) => ( { kind : "approved" } ) ,
751809 } )
752810 : client . createSession ( {
753811 ...sessionConfig ,
754- onPermissionRequest : ( ) => ( { kind : "approved" } ) ,
755812 } ) ,
756813 catch : ( cause ) =>
757814 toProcessError ( threadId , "Failed to create GitHub Copilot session." , cause ) ,
@@ -778,11 +835,11 @@ const makeCopilotAdapter = (options?: CopilotAdapterLiveOptions) =>
778835 resumeCursor : makeResumeCursor ( copilotSession . sessionId ) ,
779836 } ;
780837
781- const context : CopilotSessionContext = {
838+ context = {
782839 session,
783840 client,
784841 copilotSession,
785- pendingApprovals : new Map ( ) ,
842+ pendingApprovals,
786843 pendingUserInputs : new Map ( ) ,
787844 turns : [ ] ,
788845 turnState : undefined ,
@@ -794,62 +851,6 @@ const makeCopilotAdapter = (options?: CopilotAdapterLiveOptions) =>
794851 void Effect . runPromise ( handleSessionEvent ( context , event ) ) ;
795852 } ) ;
796853
797- copilotSession . registerPermissionHandler ( ( request ) => {
798- if ( context . session . runtimeMode === "full-access" ) {
799- return { kind : "approved" } ;
800- }
801- const requestId = ApprovalRequestId . makeUnsafe (
802- `copilot-permission:${ crypto . randomUUID ( ) } ` ,
803- ) ;
804- let resolve ! : ( decision : ProviderApprovalDecision ) => void ;
805- const promise = new Promise < ProviderApprovalDecision > ( ( resolvePromise ) => {
806- resolve = resolvePromise ;
807- } ) ;
808- const detail = permissionDetail ( request ) ;
809- context . pendingApprovals . set ( requestId , {
810- requestType : inferRequestType ( request ) ,
811- ...( detail ? { detail } : { } ) ,
812- promise,
813- resolve,
814- } ) ;
815- void Effect . runPromise (
816- emitEvent ( {
817- ...makeBase (
818- threadId ,
819- context . turnState ? { turnId : context . turnState . turnId , requestId } : { requestId } ,
820- ) ,
821- type : "request.opened" ,
822- payload : {
823- requestType : inferRequestType ( request ) ,
824- ...( permissionDetail ( request ) ? { detail : permissionDetail ( request ) } : { } ) ,
825- args : request ,
826- } ,
827- } ) ,
828- ) ;
829- return promise . then ( ( decision ) => {
830- const result = mapApprovalDecisionToPermissionResult ( decision ) ;
831- void Effect . runPromise (
832- emitEvent ( {
833- ...makeBase (
834- threadId ,
835- context . turnState
836- ? { turnId : context . turnState . turnId , requestId }
837- : { requestId } ,
838- ) ,
839- type : "request.resolved" ,
840- payload : {
841- requestType : inferRequestType ( request ) ,
842- decision : result . kind ,
843- resolution : result ,
844- } ,
845- } ) . pipe (
846- Effect . ensuring ( Effect . sync ( ( ) => context . pendingApprovals . delete ( requestId ) ) ) ,
847- ) ,
848- ) ;
849- return result ;
850- } ) ;
851- } ) ;
852-
853854 copilotSession . registerUserInputHandler ( ( request ) => {
854855 const requestId = ApprovalRequestId . makeUnsafe (
855856 `copilot-user-input:${ crypto . randomUUID ( ) } ` ,
0 commit comments