11import { describe , it , expect , vi } from "vitest" ;
2-
3- // Mock types to test the safety confirmation logic in isolation
4- type SafetyCheck = {
5- id : string ;
6- code : string ;
7- message : string ;
8- } ;
9-
10- type SafetyConfirmationResponse = {
11- acknowledged : boolean ;
12- } ;
13-
14- type SafetyConfirmationHandler = (
15- checks : SafetyCheck [ ] ,
16- ) => Promise < SafetyConfirmationResponse > ;
17-
18- // Extracted logic that mirrors OpenAICUAClient.handleSafetyConfirmation
19- async function handleSafetyConfirmation (
20- pendingSafetyChecks : SafetyCheck [ ] ,
21- handler : SafetyConfirmationHandler | undefined ,
22- ) : Promise < SafetyCheck [ ] | undefined > {
23- if ( handler ) {
24- const response = await handler ( pendingSafetyChecks ) ;
25- if ( response . acknowledged ) {
26- return pendingSafetyChecks ;
27- } else {
28- return undefined ;
29- }
2+ import { OpenAICUAClient } from "../lib/v3/agent/OpenAICUAClient" ;
3+ import { GoogleCUAClient } from "../lib/v3/agent/GoogleCUAClient" ;
4+ import type {
5+ SafetyCheck ,
6+ SafetyConfirmationHandler ,
7+ } from "../lib/v3/types/public/agent" ;
8+ import type { LogLine } from "../lib/v3/types/public/logs" ;
9+
10+ type LoggerMock = ( message : LogLine ) => void ;
11+
12+ const openAISafetyInvoker = (
13+ OpenAICUAClient . prototype as unknown as {
14+ handleSafetyConfirmation : (
15+ this : OpenAICUAClient ,
16+ pendingSafetyChecks : SafetyCheck [ ] ,
17+ logger : LoggerMock ,
18+ ) => Promise < SafetyCheck [ ] | undefined > ;
19+ }
20+ ) . handleSafetyConfirmation ;
21+
22+ const googleSafetyInvoker = (
23+ GoogleCUAClient . prototype as unknown as {
24+ handleSafetyConfirmation : (
25+ this : GoogleCUAClient ,
26+ safetyDecision : unknown ,
27+ logger : LoggerMock ,
28+ ) => Promise < string | undefined > ;
3029 }
31- // Auto-acknowledge when no handler
32- return pendingSafetyChecks ;
30+ ) . handleSafetyConfirmation ;
31+
32+ function createOpenAIClient ( ) : OpenAICUAClient {
33+ return new OpenAICUAClient (
34+ "openai" ,
35+ "openai/computer-use-preview" ,
36+ "test instructions" ,
37+ { apiKey : "test" } ,
38+ ) ;
3339}
3440
35- // Extracted logic that mirrors GoogleCUAClient.handleSafetyConfirmation
36- async function handleGoogleSafetyConfirmation (
37- safetyDecision : unknown ,
38- handler : SafetyConfirmationHandler | undefined ,
39- ) : Promise < string | undefined > {
40- const safetyMessage =
41- typeof safetyDecision === "object"
42- ? JSON . stringify ( safetyDecision , null , 2 )
43- : String ( safetyDecision ) ;
44-
45- const safetyChecks : SafetyCheck [ ] = [
46- {
47- id : "google-safety-decision" ,
48- code : "safety_decision" ,
49- message : safetyMessage ,
50- } ,
51- ] ;
52-
53- if ( handler ) {
54- const response = await handler ( safetyChecks ) ;
55- if ( response . acknowledged ) {
56- return "true" ;
57- } else {
58- return undefined ;
59- }
60- }
61- // Auto-acknowledge when no handler
62- return "true" ;
41+ function createGoogleClient ( ) : GoogleCUAClient {
42+ return new GoogleCUAClient (
43+ "google" ,
44+ "google/gemini-2.5-computer-use-preview-10-2025" ,
45+ "test instructions" ,
46+ { apiKey : "test" } ,
47+ ) ;
6348}
6449
6550describe ( "Safety Confirmation Handler" , ( ) => {
@@ -73,23 +58,35 @@ describe("Safety Confirmation Handler", () => {
7358 ] ;
7459
7560 it ( "returns checks when handler acknowledges" , async ( ) => {
76- const handler = vi . fn ( ) . mockResolvedValue ( { acknowledged : true } ) ;
77- const result = await handleSafetyConfirmation ( mockChecks , handler ) ;
61+ const client = createOpenAIClient ( ) ;
62+ const handler : SafetyConfirmationHandler = vi . fn ( async ( ) => ( {
63+ acknowledged : true ,
64+ } ) ) ;
65+ client . setSafetyConfirmationHandler ( handler ) ;
66+ const logger = vi . fn < LoggerMock > ( ) ;
67+ const result = await openAISafetyInvoker . call ( client , mockChecks , logger ) ;
7868
7969 expect ( handler ) . toHaveBeenCalledWith ( mockChecks ) ;
8070 expect ( result ) . toEqual ( mockChecks ) ;
8171 } ) ;
8272
8373 it ( "returns undefined when handler rejects" , async ( ) => {
84- const handler = vi . fn ( ) . mockResolvedValue ( { acknowledged : false } ) ;
85- const result = await handleSafetyConfirmation ( mockChecks , handler ) ;
74+ const client = createOpenAIClient ( ) ;
75+ const handler : SafetyConfirmationHandler = vi . fn ( async ( ) => ( {
76+ acknowledged : false ,
77+ } ) ) ;
78+ client . setSafetyConfirmationHandler ( handler ) ;
79+ const logger = vi . fn < LoggerMock > ( ) ;
80+ const result = await openAISafetyInvoker . call ( client , mockChecks , logger ) ;
8681
8782 expect ( handler ) . toHaveBeenCalledWith ( mockChecks ) ;
8883 expect ( result ) . toBeUndefined ( ) ;
8984 } ) ;
9085
9186 it ( "auto-acknowledges when no handler is set" , async ( ) => {
92- const result = await handleSafetyConfirmation ( mockChecks , undefined ) ;
87+ const client = createOpenAIClient ( ) ;
88+ const logger = vi . fn < LoggerMock > ( ) ;
89+ const result = await openAISafetyInvoker . call ( client , mockChecks , logger ) ;
9390 expect ( result ) . toEqual ( mockChecks ) ;
9491 } ) ;
9592 } ) ;
@@ -101,10 +98,16 @@ describe("Safety Confirmation Handler", () => {
10198 } ;
10299
103100 it ( "returns 'true' when handler acknowledges" , async ( ) => {
104- const handler = vi . fn ( ) . mockResolvedValue ( { acknowledged : true } ) ;
105- const result = await handleGoogleSafetyConfirmation (
101+ const client = createGoogleClient ( ) ;
102+ const handler : SafetyConfirmationHandler = vi . fn ( async ( ) => ( {
103+ acknowledged : true ,
104+ } ) ) ;
105+ client . setSafetyConfirmationHandler ( handler ) ;
106+ const logger = vi . fn < LoggerMock > ( ) ;
107+ const result = await googleSafetyInvoker . call (
108+ client ,
106109 mockDecision ,
107- handler ,
110+ logger ,
108111 ) ;
109112
110113 expect ( handler ) . toHaveBeenCalledWith ( [
@@ -118,29 +121,44 @@ describe("Safety Confirmation Handler", () => {
118121 } ) ;
119122
120123 it ( "returns undefined when handler rejects" , async ( ) => {
121- const handler = vi . fn ( ) . mockResolvedValue ( { acknowledged : false } ) ;
122- const result = await handleGoogleSafetyConfirmation (
124+ const client = createGoogleClient ( ) ;
125+ const handler : SafetyConfirmationHandler = vi . fn ( async ( ) => ( {
126+ acknowledged : false ,
127+ } ) ) ;
128+ client . setSafetyConfirmationHandler ( handler ) ;
129+ const logger = vi . fn < LoggerMock > ( ) ;
130+ const result = await googleSafetyInvoker . call (
131+ client ,
123132 mockDecision ,
124- handler ,
133+ logger ,
125134 ) ;
126135
127136 expect ( handler ) . toHaveBeenCalled ( ) ;
128137 expect ( result ) . toBeUndefined ( ) ;
129138 } ) ;
130139
131140 it ( "auto-acknowledges when no handler is set" , async ( ) => {
132- const result = await handleGoogleSafetyConfirmation (
141+ const client = createGoogleClient ( ) ;
142+ const logger = vi . fn < LoggerMock > ( ) ;
143+ const result = await googleSafetyInvoker . call (
144+ client ,
133145 mockDecision ,
134- undefined ,
146+ logger ,
135147 ) ;
136148 expect ( result ) . toBe ( "true" ) ;
137149 } ) ;
138150
139151 it ( "handles string safety decisions" , async ( ) => {
140- const handler = vi . fn ( ) . mockResolvedValue ( { acknowledged : true } ) ;
141- const result = await handleGoogleSafetyConfirmation (
152+ const client = createGoogleClient ( ) ;
153+ const handler : SafetyConfirmationHandler = vi . fn ( async ( ) => ( {
154+ acknowledged : true ,
155+ } ) ) ;
156+ client . setSafetyConfirmationHandler ( handler ) ;
157+ const logger = vi . fn < LoggerMock > ( ) ;
158+ const result = await googleSafetyInvoker . call (
159+ client ,
142160 "Simple string decision" ,
143- handler ,
161+ logger ,
144162 ) ;
145163
146164 expect ( handler ) . toHaveBeenCalledWith ( [
0 commit comments