@@ -243,11 +243,16 @@ function toClaudeCodeName(name: string): string {
243243function fromClaudeCodeName ( name : string , tools : Context [ "tools" ] | undefined ) : string {
244244 if ( tools && tools . length > 0 ) {
245245 const lowerName = normalizeLowercaseStringOrEmpty ( name ) ;
246- const matchedTool = tools . find (
247- ( tool ) => normalizeLowercaseStringOrEmpty ( tool . name ) === lowerName ,
248- ) ;
249- if ( matchedTool ) {
250- return matchedTool . name ;
246+ for ( const tool of tools ) {
247+ let toolName : unknown ;
248+ try {
249+ toolName = tool . name ;
250+ } catch {
251+ continue ;
252+ }
253+ if ( typeof toolName === "string" && normalizeLowercaseStringOrEmpty ( toolName ) === lowerName ) {
254+ return toolName ;
255+ }
251256 }
252257 }
253258 return name ;
@@ -474,6 +479,31 @@ function ensureNonEmptyAnthropicMessages(messages: Array<Record<string, unknown>
474479 : [ { role : "user" , content : EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT } ] ;
475480}
476481
482+ type AnthropicToolCandidate = NonNullable < Context [ "tools" ] > [ number ] ;
483+ type AnthropicToolFieldRead = { readable : true ; value : unknown } | { readable : false } ;
484+
485+ function readAnthropicToolField (
486+ tool : AnthropicToolCandidate ,
487+ field : "name" | "description" | "parameters" ,
488+ ) : AnthropicToolFieldRead {
489+ try {
490+ return { readable : true , value : ( tool as unknown as Record < string , unknown > ) [ field ] } ;
491+ } catch {
492+ return { readable : false } ;
493+ }
494+ }
495+
496+ function readAnthropicSchemaField (
497+ schema : Record < string , unknown > ,
498+ field : "properties" | "required" ,
499+ ) : AnthropicToolFieldRead {
500+ try {
501+ return { readable : true , value : schema [ field ] } ;
502+ } catch {
503+ return { readable : false } ;
504+ }
505+ }
506+
477507function convertAnthropicTools ( tools : Context [ "tools" ] , isOAuthToken : boolean ) {
478508 if ( ! tools ) {
479509 return [ ] ;
@@ -490,20 +520,43 @@ function convertAnthropicTools(tools: Context["tools"], isOAuthToken: boolean) {
490520 for ( const tool of tools ) {
491521 // Main quarantine happens when plugin tools materialize; this keeps Anthropic
492522 // safe for direct/custom tool arrays that bypass the plugin registry.
523+ const nameRead = readAnthropicToolField ( tool , "name" ) ;
524+ const parametersRead = readAnthropicToolField ( tool , "parameters" ) ;
525+ if ( ! nameRead . readable || ! parametersRead . readable ) {
526+ continue ;
527+ }
528+ const rawParameters = parametersRead . value ;
493529 const parameters =
494- tool . parameters && typeof tool . parameters === "object" && ! Array . isArray ( tool . parameters )
495- ? ( tool . parameters as Record < string , unknown > )
530+ rawParameters && typeof rawParameters === "object" && ! Array . isArray ( rawParameters )
531+ ? ( rawParameters as Record < string , unknown > )
496532 : undefined ;
497- if ( ! parameters ) {
533+ if ( typeof nameRead . value !== "string" || ! parameters ) {
534+ continue ;
535+ }
536+ const propertiesRead = readAnthropicSchemaField ( parameters , "properties" ) ;
537+ const requiredRead = readAnthropicSchemaField ( parameters , "required" ) ;
538+ const descriptionRead = readAnthropicToolField ( tool , "description" ) ;
539+ if ( ! propertiesRead . readable || ! requiredRead . readable ) {
540+ continue ;
541+ }
542+ const properties = propertiesRead . value ;
543+ const required = requiredRead . value ;
544+ if (
545+ ( properties !== undefined && properties !== null && typeof properties !== "object" ) ||
546+ ( required !== undefined && required !== null && ! Array . isArray ( required ) )
547+ ) {
498548 continue ;
499549 }
500550 converted . push ( {
501- name : isOAuthToken ? toClaudeCodeName ( tool . name ) : tool . name ,
502- description : tool . description ,
551+ name : isOAuthToken ? toClaudeCodeName ( nameRead . value ) : nameRead . value ,
552+ description :
553+ descriptionRead . readable && typeof descriptionRead . value === "string"
554+ ? descriptionRead . value
555+ : undefined ,
503556 input_schema : {
504557 type : "object" ,
505- properties : parameters . properties || { } ,
506- required : parameters . required || [ ] ,
558+ properties : properties ?? { } ,
559+ required : required ?? [ ] ,
507560 } ,
508561 } ) ;
509562 }
0 commit comments