From df78ef1608d4af0725d781fdf40c5a7e754a8e6f Mon Sep 17 00:00:00 2001 From: Josh White Date: Tue, 21 Apr 2026 18:51:38 -0400 Subject: [PATCH 1/2] Add assets config key support for UI extension points --- .../app/src/cli/models/extensions/schemas.ts | 1 + .../specifications/ui_extension.test.ts | 74 +++++++++++++++++++ .../extensions/specifications/ui_extension.ts | 7 ++ .../services/dev/extension/payload/models.ts | 2 +- 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/packages/app/src/cli/models/extensions/schemas.ts b/packages/app/src/cli/models/extensions/schemas.ts index 98943c09187..04978437b76 100644 --- a/packages/app/src/cli/models/extensions/schemas.ts +++ b/packages/app/src/cli/models/extensions/schemas.ts @@ -75,6 +75,7 @@ const NewExtensionPointSchema = zod.object({ chat: zod.string().optional(), }) .optional(), + assets: zod.string().optional(), }) export const NewExtensionPointsSchema = zod.array(NewExtensionPointSchema) diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts index be8441e3d40..1b2d15522da 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.test.ts @@ -151,6 +151,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [{namespace: 'test', key: 'test'}], default_placement_reference: undefined, @@ -219,6 +220,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [], default_placement_reference: 'PLACEMENT_REFERENCE1', @@ -283,6 +285,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [], urls: {}, @@ -347,6 +350,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [], default_placement_reference: undefined, @@ -414,6 +418,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [], default_placement_reference: undefined, @@ -483,6 +488,7 @@ describe('ui_extension', async () => { tools: undefined, instructions: undefined, intents: undefined, + assets: undefined, module: './src/ExtensionPointA.js', metafields: [], default_placement_reference: undefined, @@ -552,6 +558,7 @@ describe('ui_extension', async () => { tools: './tools.json', instructions: undefined, intents: undefined, + assets: undefined, metafields: [], default_placement_reference: undefined, capabilities: undefined, @@ -616,6 +623,72 @@ describe('ui_extension', async () => { tools: undefined, instructions: './instructions.md', intents: undefined, + assets: undefined, + metafields: [], + default_placement_reference: undefined, + capabilities: undefined, + preloads: {}, + build_manifest: { + assets: { + main: { + filepath: 'test-ui-extension.js', + module: './src/ExtensionPointA.js', + }, + }, + }, + urls: {}, + }, + ]) + }) + + test('targeting object passes through assets when configured', async () => { + const allSpecs = await loadLocalExtensionsSpecifications() + const specification = allSpecs.find((spec) => spec.identifier === 'ui_extension')! + const configuration = { + targeting: [ + { + target: 'EXTENSION::POINT::A', + module: './src/ExtensionPointA.js', + assets: './assets', + }, + ], + api_version: '2023-01' as const, + name: 'UI Extension', + description: 'This is an ordinary test extension', + type: 'ui_extension', + handle: 'test-ui-extension', + capabilities: { + block_progress: false, + network_access: false, + api_access: false, + collect_buyer_consent: { + customer_privacy: true, + sms_marketing: false, + }, + iframe: { + sources: [], + }, + }, + settings: {}, + } + + // When + const parsed = specification.parseConfigurationObject(configuration) + if (parsed.state !== 'ok') { + throw new Error("Couldn't parse configuration") + } + + const got = parsed.data + + // Then + expect(got.extension_points).toStrictEqual([ + { + target: 'EXTENSION::POINT::A', + module: './src/ExtensionPointA.js', + tools: undefined, + instructions: undefined, + intents: undefined, + assets: './assets', metafields: [], default_placement_reference: undefined, capabilities: undefined, @@ -779,6 +852,7 @@ Please check the configuration in ${uiExtension.configurationPath}`), tools: './tools.json', instructions: './instructions.md', intents: undefined, + assets: undefined, metafields: [], default_placement_reference: undefined, capabilities: undefined, diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts index 815ab533993..4a1e35ea5ac 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts @@ -74,6 +74,7 @@ export const UIExtensionSchema = BaseSchema.extend({ tools: targeting.tools, instructions: targeting.instructions, intents: targeting.intents, + assets: targeting.assets, } }) return {...config, extension_points: extensionPoints} @@ -119,6 +120,12 @@ const uiExtensionSpec = createExtensionSpecification({ groupBy: 'target', key: 'extension_points[].intents[].schema', }, + { + type: 'configKey', + anchor: 'extension_points[]', + groupBy: 'target', + key: 'extension_points[].assets', + }, ], }, }, diff --git a/packages/app/src/cli/services/dev/extension/payload/models.ts b/packages/app/src/cli/services/dev/extension/payload/models.ts index 753a6511c0b..4b73036da82 100644 --- a/packages/app/src/cli/services/dev/extension/payload/models.ts +++ b/packages/app/src/cli/services/dev/extension/payload/models.ts @@ -39,7 +39,7 @@ interface Asset { lastUpdated: number } -export interface DevNewExtensionPointSchema extends Omit { +export interface DevNewExtensionPointSchema extends Omit { assets: { [name: string]: Asset } From 8980fa8eb49b3ce402c356ba21985ee94390ef00 Mon Sep 17 00:00:00 2001 From: Elana Kopelevich Date: Fri, 24 Apr 2026 17:14:50 -0600 Subject: [PATCH 2/2] Move assets to top of inclusions --- .../cli/models/extensions/specifications/ui_extension.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts index 4a1e35ea5ac..217ceeaeec9 100644 --- a/packages/app/src/cli/models/extensions/specifications/ui_extension.ts +++ b/packages/app/src/cli/models/extensions/specifications/ui_extension.ts @@ -106,25 +106,25 @@ const uiExtensionSpec = createExtensionSpecification({ type: 'configKey', anchor: 'extension_points[]', groupBy: 'target', - key: 'extension_points[].tools', + key: 'extension_points[].assets', }, { type: 'configKey', anchor: 'extension_points[]', groupBy: 'target', - key: 'extension_points[].instructions', + key: 'extension_points[].tools', }, { type: 'configKey', anchor: 'extension_points[]', groupBy: 'target', - key: 'extension_points[].intents[].schema', + key: 'extension_points[].instructions', }, { type: 'configKey', anchor: 'extension_points[]', groupBy: 'target', - key: 'extension_points[].assets', + key: 'extension_points[].intents[].schema', }, ], },