Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions packages/mock-converse-api/src/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,69 @@ describe('createMockConverseServer', () => {
expect(res.headers['content-type']).toBe('text/event-stream');
});

it('streams the Thermidor schema catalog example for its dedicated prompt', async () => {
await startServer();
const res = await makeRequest(
server,
{
method: 'POST',
path: '/rest/organizations/myorg/commerce/unstable/agentic/converse',
headers: {'Content-Type': 'application/json'},
},
JSON.stringify({message: 'Show the Thermidor catalog'})
);

const events = res.body
.split('\n\n')
.filter(Boolean)
.map(
(frame) => JSON.parse(frame.split('\n')[1].replace('data:', '')) as Record<string, unknown>
);
const activity = events.find((event) => event['type'] === 'ACTIVITY_SNAPSHOT');
const stateSnapshot = events.find((event) => event['type'] === 'STATE_SNAPSHOT');

expect(activity).toMatchObject({
type: 'ACTIVITY_SNAPSHOT',
messageId: 'commerce-catalog-example',
activityType: 'a2ui-surface',
replace: true,
content: {
a2ui_operations: [
{
version: 'v0.9',
createSurface: {
surfaceId: 'commerce-catalog-example',
catalogId: 'https://schema.thermidor.coveo.com/a2-ui/catalog.json',
},
},
{
version: 'v0.9',
updateComponents: {
components: [
{id: 'root', component: 'Column', children: ['featured-products', 'cart']},
{component: 'ProductCarousel'},
{component: 'Cart'},
],
},
},
],
},
});

const snapshot = stateSnapshot?.['snapshot'] as {
controllers: Record<string, {products?: unknown[]; items?: unknown[]}>;
};

expect(snapshot.controllers['featured-products'].products).toEqual(
expect.arrayContaining([expect.objectContaining({permanentid: 'trail-running-shoes-001'})])
);
expect(snapshot.controllers['shopping-cart'].items).toEqual(
expect.arrayContaining([
expect.objectContaining({productId: 'trail-running-shoes-001', quantity: 1}),
])
);
});

it('returns 400 for invalid JSON payload', async () => {
await startServer();
const res = await makeRequest(
Expand Down
4 changes: 4 additions & 0 deletions packages/platform-mock-api/src/converse/generate-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const PROMPT_TEMPLATE_MAP: ReadonlyArray<PromptMapping> = [
prompt: 'i like cold-water surfing. compare wetsuits for it',
templateId: 'response8',
},
{
prompt: 'show the thermidor catalog',
templateId: 'thermidor-schema-catalog',
},
];

const FALLBACK_TEMPLATE_ID: TemplateId = 'response5';
Expand Down
121 changes: 121 additions & 0 deletions packages/platform-mock-api/src/converse/templates/response9.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import {
ActivitySnapshot,
RunFinished,
RunStarted,
StateSnapshot,
TurnComplete,
TurnStarted,
textMessage,
type ConverseEvent,
} from '../events.js';

const thermidorCatalogState = {
controllers: {
'featured-products': {
products: [
{
permanentid: 'trail-running-shoes-001',
ec_name: 'Peak Trail Running Shoes',
ec_shortdesc: 'Responsive trail shoes for everyday adventures.',
ec_brand: 'Thermidor Outdoor',
ec_category: ['Footwear', 'Trail Running'],
ec_price: 129.99,
ec_promo_price: 99.99,
ec_images: ['https://images.example.com/products/trail-running-shoes-001.jpg'],
ec_in_stock: true,
ec_rating: 4.7,
clickUri: '/products/trail-running-shoes-001',
additionalFields: {},
},
{
permanentid: 'summit-pack-020',
ec_name: 'Summit Day Pack',
ec_shortdesc: 'A compact, weather-ready 20 L day pack.',
ec_brand: 'Thermidor Outdoor',
ec_category: ['Bags', 'Day Packs'],
ec_price: 89.99,
ec_images: ['https://images.example.com/products/summit-pack-020.jpg'],
ec_in_stock: true,
ec_rating: 4.4,
clickUri: '/products/summit-pack-020',
additionalFields: {},
},
],
},
'shopping-cart': {
items: [
{
productId: 'trail-running-shoes-001',
name: 'Peak Trail Running Shoes',
price: 99.99,
quantity: 1,
},
],
},
},
};

const thermidorSchemaCatalogResponseEvents: ConverseEvent[] = [
TurnStarted(),
RunStarted(),
...textMessage(
'thermidor-schema-catalog-message',
'Here are featured products and the current cart from the Thermidor catalog contract.'
),
StateSnapshot(thermidorCatalogState),
ActivitySnapshot({
messageId: 'commerce-catalog-example',
activityType: 'a2ui-surface',
replace: true,
content: {
a2ui_operations: [
{
version: 'v0.9',
createSurface: {
surfaceId: 'commerce-catalog-example',
catalogId: 'https://schema.thermidor.coveo.com/a2-ui/catalog.json',
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'commerce-catalog-example',
components: [
{
id: 'root',
component: 'Column',
children: ['featured-products', 'cart'],
},
{
id: 'featured-products',
component: 'ProductCarousel',
controllers: {
productListController: {
controllerId: 'featured-products',
controllerSchema:
'https://schema.thermidor.coveo.com/controllers/product-list.schema.json',
},
},
},
{
id: 'cart',
component: 'Cart',
controllers: {
cartController: {
controllerId: 'shopping-cart',
controllerSchema:
'https://schema.thermidor.coveo.com/controllers/cart.schema.json',
},
},
},
],
},
},
],
},
}),
RunFinished(),
TurnComplete(),
];

export {thermidorSchemaCatalogResponseEvents};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {response5Events} from './response5.js';
import {response6Events} from './response6.js';
import {response7Events} from './response7.js';
import {response8Events} from './response8.js';
import {thermidorSchemaCatalogResponseEvents} from './response9.js';

type TemplateId =
| 'response1'
Expand All @@ -16,7 +17,8 @@ type TemplateId =
| 'response5'
| 'response6'
| 'response7'
| 'response8';
| 'response8'
| 'thermidor-schema-catalog';

const templateEvents = {
response1: response1Events,
Expand All @@ -27,6 +29,7 @@ const templateEvents = {
response6: response6Events,
response7: response7Events,
response8: response8Events,
'thermidor-schema-catalog': thermidorSchemaCatalogResponseEvents,
} satisfies Record<TemplateId, ConverseEvent[]>;

const getTemplateEvents = (templateId: TemplateId): ConverseEvent[] => templateEvents[templateId];
Expand Down
42 changes: 42 additions & 0 deletions packages/thermidor-contracts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@coveo/thermidor-contracts",
"version": "0.0.1",
"description": "Generated Zod contracts for Thermidor controller and A2-UI schemas",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "git+https://github.com/coveo/ui-kit.git",
"directory": "packages/thermidor-contracts"
},
"files": [
"dist"
],
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "tsdown",
"clean": "node ../../utils/ci/rm-rf.mjs dist"
},
"dependencies": {
"zod": "catalog:"
},
"devDependencies": {
"tsdown": "0.22.0",
"typescript": "catalog:"
},
"engines": {
"node": "^22.11.0 || ^24.11.0"
}
}
Loading
Loading