@@ -282,21 +282,11 @@ const uiExtensionSpec = createExtensionSpecification({
282282 let toolsTypeDefinition = ''
283283 if ( toolsDefinition ) {
284284 try {
285- const toolsFilePath = joinPath ( extension . directory , toolsDefinition )
286- if ( await fileExists ( toolsFilePath ) ) {
287- // Read and parse the tools JSON file
288- const toolsContent = await readFile ( toolsFilePath )
289- const tools = ToolsFileSchema . safeParse ( JSON . parse ( toolsContent ) )
290- if ( tools . success ) {
291- // Generate tools type definition
292- toolsTypeDefinition = await createToolsTypeDefinition ( tools . data )
293- } else {
294- outputWarn (
295- `Invalid tools definition in "${ toolsDefinition } ": ${ tools . error . issues
296- . map ( ( issue ) => issue . message )
297- . join ( ', ' ) } `,
298- )
299- }
285+ const tools = await readAndValidateJsonAsset ( extension . directory , toolsDefinition , ToolsFileSchema )
286+ if ( tools . status === 'ok' ) {
287+ toolsTypeDefinition = await createToolsTypeDefinition ( tools . data )
288+ } else if ( tools . status === 'invalid' ) {
289+ outputWarn ( `Invalid tools definition in "${ toolsDefinition } ": ${ tools . issues } ` )
300290 }
301291 // eslint-disable-next-line no-catch-all/no-catch-all
302292 } catch ( error ) {
@@ -378,26 +368,41 @@ function addDistPathToAssets(extP: NewExtensionPointSchemaType & {build_manifest
378368 }
379369}
380370
371+ type JsonAssetResult < T > = { status : 'ok' ; data : T } | { status : 'missing' } | { status : 'invalid' ; issues : string }
372+
373+ async function readAndValidateJsonAsset < T > (
374+ extensionDirectory : string ,
375+ relativePath : string ,
376+ schema : zod . ZodType < T > ,
377+ ) : Promise < JsonAssetResult < T > > {
378+ const filePath = joinPath ( extensionDirectory , relativePath )
379+ const exists = await fileExists ( filePath )
380+ if ( ! exists ) return { status : 'missing' }
381+
382+ const content = await readFile ( filePath )
383+ const parsed = schema . safeParse ( JSON . parse ( content ) )
384+ if ( ! parsed . success ) {
385+ return {
386+ status : 'invalid' ,
387+ issues : parsed . error . issues . map ( ( issue ) => issue . message ) . join ( ', ' ) ,
388+ }
389+ }
390+
391+ return { status : 'ok' , data : parsed . data }
392+ }
393+
381394async function parseIntentTypeDefinitions (
382395 extensionDirectory : string ,
383396 intents : NonNullable < NewExtensionPointSchemaType [ 'intents' ] > ,
384397) : Promise < GeneratedIntentTypeDefinition [ ] > {
385398 const parsedIntentDefinitions = await Promise . all (
386399 intents . map ( async ( intent ) => {
387400 try {
388- const intentSchemaFilePath = joinPath ( extensionDirectory , intent . schema )
389- const schemaExists = await fileExists ( intentSchemaFilePath )
390- if ( ! schemaExists ) return null
391-
392- const intentSchemaContent = await readFile ( intentSchemaFilePath )
393- const intentSchema = IntentSchemaFileSchema . safeParse ( JSON . parse ( intentSchemaContent ) )
394-
395- if ( ! intentSchema . success ) {
396- outputWarn (
397- `Invalid intent schema in "${ intent . schema } ": ${ intentSchema . error . issues
398- . map ( ( issue ) => issue . message )
399- . join ( ', ' ) } `,
400- )
401+ const intentSchema = await readAndValidateJsonAsset ( extensionDirectory , intent . schema , IntentSchemaFileSchema )
402+ if ( intentSchema . status === 'missing' ) return null
403+
404+ if ( intentSchema . status === 'invalid' ) {
405+ outputWarn ( `Invalid intent schema in "${ intent . schema } ": ${ intentSchema . issues } ` )
401406 return null
402407 }
403408
0 commit comments