@@ -286,21 +286,11 @@ const uiExtensionSpec = createExtensionSpecification({
286286 let toolsTypeDefinition = ''
287287 if ( toolsDefinition ) {
288288 try {
289- const toolsFilePath = joinPath ( extension . directory , toolsDefinition )
290- if ( await fileExists ( toolsFilePath ) ) {
291- // Read and parse the tools JSON file
292- const toolsContent = await readFile ( toolsFilePath )
293- const tools = ToolsFileSchema . safeParse ( JSON . parse ( toolsContent ) )
294- if ( tools . success ) {
295- // Generate tools type definition
296- toolsTypeDefinition = await createToolsTypeDefinition ( tools . data )
297- } else {
298- outputWarn (
299- `Invalid tools definition in "${ toolsDefinition } ": ${ tools . error . issues
300- . map ( ( issue ) => issue . message )
301- . join ( ', ' ) } `,
302- )
303- }
289+ const tools = await readAndValidateJsonAsset ( extension . directory , toolsDefinition , ToolsFileSchema )
290+ if ( tools . status === 'ok' ) {
291+ toolsTypeDefinition = await createToolsTypeDefinition ( tools . data )
292+ } else if ( tools . status === 'invalid' ) {
293+ outputWarn ( `Invalid tools definition in "${ toolsDefinition } ": ${ tools . issues } ` )
304294 }
305295 // eslint-disable-next-line no-catch-all/no-catch-all
306296 } catch ( error ) {
@@ -382,26 +372,41 @@ function addDistPathToAssets(extP: NewExtensionPointSchemaType & {build_manifest
382372 }
383373}
384374
375+ type JsonAssetResult < T > = { status : 'ok' ; data : T } | { status : 'missing' } | { status : 'invalid' ; issues : string }
376+
377+ async function readAndValidateJsonAsset < T > (
378+ extensionDirectory : string ,
379+ relativePath : string ,
380+ schema : zod . ZodType < T > ,
381+ ) : Promise < JsonAssetResult < T > > {
382+ const filePath = joinPath ( extensionDirectory , relativePath )
383+ const exists = await fileExists ( filePath )
384+ if ( ! exists ) return { status : 'missing' }
385+
386+ const content = await readFile ( filePath )
387+ const parsed = schema . safeParse ( JSON . parse ( content ) )
388+ if ( ! parsed . success ) {
389+ return {
390+ status : 'invalid' ,
391+ issues : parsed . error . issues . map ( ( issue ) => issue . message ) . join ( ', ' ) ,
392+ }
393+ }
394+
395+ return { status : 'ok' , data : parsed . data }
396+ }
397+
385398async function parseIntentTypeDefinitions (
386399 extensionDirectory : string ,
387400 intents : NonNullable < NewExtensionPointSchemaType [ 'intents' ] > ,
388401) : Promise < GeneratedIntentTypeDefinition [ ] > {
389402 const parsedIntentDefinitions = await Promise . all (
390403 intents . map ( async ( intent ) => {
391404 try {
392- const intentSchemaFilePath = joinPath ( extensionDirectory , intent . schema )
393- const schemaExists = await fileExists ( intentSchemaFilePath )
394- if ( ! schemaExists ) return null
395-
396- const intentSchemaContent = await readFile ( intentSchemaFilePath )
397- const intentSchema = IntentSchemaFileSchema . safeParse ( JSON . parse ( intentSchemaContent ) )
398-
399- if ( ! intentSchema . success ) {
400- outputWarn (
401- `Invalid intent schema in "${ intent . schema } ": ${ intentSchema . error . issues
402- . map ( ( issue ) => issue . message )
403- . join ( ', ' ) } `,
404- )
405+ const intentSchema = await readAndValidateJsonAsset ( extensionDirectory , intent . schema , IntentSchemaFileSchema )
406+ if ( intentSchema . status === 'missing' ) return null
407+
408+ if ( intentSchema . status === 'invalid' ) {
409+ outputWarn ( `Invalid intent schema in "${ intent . schema } ": ${ intentSchema . issues } ` )
405410 return null
406411 }
407412
0 commit comments