1- import { describe , expect , it , vi } from "vitest" ;
1+ import { beforeEach , describe , expect , it , vi } from "vitest" ;
22
33const mocks = vi . hoisted ( ( ) => ( {
44 inspectProviderToolSchemasWithPlugin : vi . fn ( ) ,
@@ -21,7 +21,25 @@ vi.mock("./logger.js", () => ({
2121const { logProviderToolSchemaDiagnostics, normalizeProviderToolSchemas } =
2222 await import ( "./tool-schema-runtime.js" ) ;
2323
24+ function createHostileThrownValue ( ) {
25+ return new Proxy ( ( ) => undefined , {
26+ get ( target , property , receiver ) {
27+ if ( property === Symbol . toStringTag ) {
28+ throw new Error ( "tag exploded" ) ;
29+ }
30+ return Reflect . get ( target , property , receiver ) ;
31+ } ,
32+ } ) as unknown as Error ;
33+ }
34+
2435describe ( "tool schema runtime diagnostics" , ( ) => {
36+ beforeEach ( ( ) => {
37+ mocks . log . info . mockReset ( ) ;
38+ mocks . log . warn . mockReset ( ) ;
39+ mocks . inspectProviderToolSchemasWithPlugin . mockReset ( ) ;
40+ mocks . normalizeProviderToolSchemasWithPlugin . mockReset ( ) ;
41+ } ) ;
42+
2543 it ( "stays quiet when a provider reports no diagnostics" , ( ) => {
2644 mocks . inspectProviderToolSchemasWithPlugin . mockReturnValueOnce ( [ ] ) ;
2745
@@ -57,6 +75,68 @@ describe("tool schema runtime diagnostics", () => {
5775 ) ;
5876 } ) ;
5977
78+ it ( "keeps the current runtime tools when provider schema normalization throws" , ( ) => {
79+ const tools = [ { name : "alpha" } ] as never ;
80+ mocks . normalizeProviderToolSchemasWithPlugin . mockImplementationOnce ( ( ) => {
81+ throw new Error ( "bad\nnormalizer" ) ;
82+ } ) ;
83+
84+ expect (
85+ normalizeProviderToolSchemas ( {
86+ provider : "fuzz-provider\nWARN forged" ,
87+ tools,
88+ hookFailureMode : "warn" ,
89+ } ) ,
90+ ) . toBe ( tools ) ;
91+
92+ expect ( mocks . log . warn ) . toHaveBeenCalledWith (
93+ "provider tool schema normalizeToolSchemas hook failed for fuzz-providerWARN forged; keeping current runtime tools: badnormalizer" ,
94+ {
95+ provider : "fuzz-providerWARN forged" ,
96+ hookName : "normalizeToolSchemas" ,
97+ toolCount : 1 ,
98+ } ,
99+ ) ;
100+ } ) ;
101+
102+ it ( "does not crash warn-mode normalization for hostile thrown values" , ( ) => {
103+ const tools = [ { name : "alpha" } ] as never ;
104+ mocks . normalizeProviderToolSchemasWithPlugin . mockImplementationOnce ( ( ) => {
105+ throw createHostileThrownValue ( ) ;
106+ } ) ;
107+
108+ expect (
109+ normalizeProviderToolSchemas ( {
110+ provider : "example" ,
111+ tools,
112+ hookFailureMode : "warn" ,
113+ } ) ,
114+ ) . toBe ( tools ) ;
115+
116+ expect ( mocks . log . warn ) . toHaveBeenCalledWith (
117+ "provider tool schema normalizeToolSchemas hook failed for example; keeping current runtime tools: [object Function]" ,
118+ {
119+ provider : "example" ,
120+ hookName : "normalizeToolSchemas" ,
121+ toolCount : 1 ,
122+ } ,
123+ ) ;
124+ } ) ;
125+
126+ it ( "keeps doctor-style schema normalization strict by default" , ( ) => {
127+ mocks . normalizeProviderToolSchemasWithPlugin . mockImplementationOnce ( ( ) => {
128+ throw new Error ( "bad normalizer" ) ;
129+ } ) ;
130+
131+ expect ( ( ) =>
132+ normalizeProviderToolSchemas ( {
133+ provider : "example" ,
134+ tools : [ { name : "alpha" } ] as never ,
135+ } ) ,
136+ ) . toThrow ( "bad normalizer" ) ;
137+ expect ( mocks . log . warn ) . not . toHaveBeenCalled ( ) ;
138+ } ) ;
139+
60140 it ( "logs one summarized warning for provider tool schema diagnostics" , ( ) => {
61141 mocks . inspectProviderToolSchemasWithPlugin . mockReturnValueOnce ( [
62142 { toolName : "alpha" , toolIndex : 0 , violations : [ "one" , "two" ] } ,
@@ -84,4 +164,39 @@ describe("tool schema runtime diagnostics", () => {
84164 } ,
85165 ) ;
86166 } ) ;
167+
168+ it ( "does not crash runtime diagnostics when provider schema inspection throws" , ( ) => {
169+ mocks . inspectProviderToolSchemasWithPlugin . mockImplementationOnce ( ( ) => {
170+ throw new Error ( "bad inspector" ) ;
171+ } ) ;
172+
173+ logProviderToolSchemaDiagnostics ( {
174+ provider : "example" ,
175+ tools : [ { name : "alpha" } ] as never ,
176+ hookFailureMode : "warn" ,
177+ } ) ;
178+
179+ expect ( mocks . log . warn ) . toHaveBeenCalledWith (
180+ "provider tool schema inspectToolSchemas hook failed for example; keeping current runtime tools: bad inspector" ,
181+ {
182+ provider : "example" ,
183+ hookName : "inspectToolSchemas" ,
184+ toolCount : 1 ,
185+ } ,
186+ ) ;
187+ } ) ;
188+
189+ it ( "keeps doctor-style schema inspection strict by default" , ( ) => {
190+ mocks . inspectProviderToolSchemasWithPlugin . mockImplementationOnce ( ( ) => {
191+ throw new Error ( "bad inspector" ) ;
192+ } ) ;
193+
194+ expect ( ( ) =>
195+ logProviderToolSchemaDiagnostics ( {
196+ provider : "example" ,
197+ tools : [ { name : "alpha" } ] as never ,
198+ } ) ,
199+ ) . toThrow ( "bad inspector" ) ;
200+ expect ( mocks . log . warn ) . not . toHaveBeenCalled ( ) ;
201+ } ) ;
87202} ) ;
0 commit comments