@@ -33,6 +33,8 @@ const useChatSocket = (isEmpty?: boolean) => {
3333 const latestAgentMessageIndex = useRef < number > ( - 1 ) ;
3434 const trustedRef = useRef < Record < string , boolean > > ( { } ) ;
3535 const trustedRepoPrefixesRef = useRef < string [ ] > ( [ ...initiallyTrustedRepos ] ) ;
36+ // trustedOpenAPIRef contains a mapping of OpenAPI run tools to OpenAPI operation names that have been trusted.
37+ const trustedOpenAPIRef = useRef < Record < string , Record < string , boolean > > > ( { } ) ;
3638
3739 // update the refs as the state changes
3840 useEffect ( ( ) => {
@@ -201,7 +203,9 @@ const useChatSocket = (isEmpty?: boolean) => {
201203 }
202204
203205 let confirmMessage = `Proceed with calling the ${ frame . tool . name } tool?` ;
204- if ( frame . displayText ) {
206+ if ( frame . tool . instructions ?. startsWith ( '#!sys.openapi' ) ) {
207+ confirmMessage = `Proceed with running the following API operation (or allow all runs of this operation)?` ;
208+ } else if ( frame . displayText ) {
205209 const tool = frame . tool ?. name ?. replace ( 'sys.' , '' ) ;
206210 confirmMessage = frame . tool ?. source ?. repo
207211 ? `Proceed with running the following (or allow all calls from the **${ trimRepo ( frame . tool ?. source . repo ! . Root ) } ** repo)?`
@@ -278,6 +282,28 @@ const useChatSocket = (isEmpty?: boolean) => {
278282 const alreadyAllowed = ( frame : CallFrame ) : boolean => {
279283 if ( ! frame . tool ) return false ;
280284
285+ if ( frame . tool . instructions ?. startsWith ( '#!sys.openapi' ) ) {
286+ // If the tool is an OpenAPI tool to list operations or get the schema for an operation, allow it.
287+ const instructions = frame . tool . instructions . split ( ' ' ) ;
288+ if (
289+ instructions . length > 2 &&
290+ ( instructions [ 1 ] == 'list' || instructions [ 1 ] == 'get-schema' )
291+ ) {
292+ return true ;
293+ }
294+
295+ // If the tool is an OpenAPI tool to run an operation, check if it has been trusted.
296+ if ( ! frame . tool . name ) {
297+ return false ;
298+ }
299+
300+ const operation = JSON . parse ( frame . input as string ) [ 'operation' ] ;
301+ return (
302+ trustedOpenAPIRef . current [ frame . tool . name ] &&
303+ trustedOpenAPIRef . current [ frame . tool . name ] [ operation ]
304+ ) ;
305+ }
306+
281307 // Check if the tool has already been allowed
282308 if ( frame . tool . name && trustedRef . current [ frame . tool . name ] ) return true ;
283309
@@ -304,6 +330,22 @@ const useChatSocket = (isEmpty?: boolean) => {
304330 const addTrustedFor = ( frame : CallFrame ) => {
305331 if ( ! frame . tool ) return ( ) => { } ;
306332
333+ if (
334+ frame . tool . instructions &&
335+ frame . tool . name &&
336+ frame . tool . instructions . startsWith ( '#!sys.openapi' )
337+ ) {
338+ return ( ) => {
339+ const toolName = frame . tool ?. name ?? '' ; // Not possible for this to be null, but I have to satisfy the type checker.
340+ const operation = JSON . parse ( frame . input as string ) [ 'operation' ] ;
341+
342+ if ( ! trustedOpenAPIRef . current [ toolName ] ) {
343+ trustedOpenAPIRef . current [ toolName ] = { } ;
344+ }
345+ trustedOpenAPIRef . current [ toolName ] [ operation ] = true ;
346+ } ;
347+ }
348+
307349 return frame . tool . source ?. repo
308350 ? ( ) => {
309351 const repo = frame . tool ! . source ?. repo ! . Root ;
0 commit comments