create-auto-app 0.8.5 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/templates/shopping-app/.context/schema.graphql +4 -4
- package/templates/shopping-app/.context/schema.json +54 -62
- package/templates/shopping-app/.context/server/server/package.json +1 -2
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/accepts-items-and-adds-to-their-cart/decide.specs.ts +0 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/accepts-items-and-adds-to-their-cart/events.ts +0 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/creates-a-chat-session/react.specs.ts +0 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/enters-shopping-criteria-into-assistant/decide.specs.ts +0 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/enters-shopping-criteria-into-assistant/events.ts +0 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/selects-items-relevant-to-the-shopping-criteria/decide.ts +1 -1
- package/templates/shopping-app/.context/server/server/src/domain/flows/seasonal-assistant/selects-items-relevant-to-the-shopping-criteria/handle.ts +2 -2
- package/templates/shopping-app/auto.config.ts +19 -11
- package/templates/shopping-app/example-integrations/ai-chat-completion/package.json +1 -2
- package/templates/shopping-app/example-integrations/cart/package.json +1 -2
- package/templates/shopping-app/example-integrations/cart-api/package.json +1 -2
- package/templates/shopping-app/example-integrations/product-catalogue/package.json +1 -2
- package/templates/shopping-app/example-integrations/product-catalogue-api/package.json +1 -2
- package/templates/shopping-app/flows/shopping-assistant.flow.ts +80 -97
- package/templates/shopping-app/package.json +2 -2
- package/templates/shopping-app/server/scripts/generate-schema.ts +1 -1
- package/templates/shopping-app/server/src/integrations/product-catalogue/product-catalogue-integration.ts +8 -29
- package/templates/shopping-app/tsconfig.json +3 -1
- package/templates/shopping-app/turbo.json +19 -0
- package/templates/shopping-app/client/postcss.config.js +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-auto-app",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "Create Auto Engineer apps with no configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=18.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
|
-
"copy-templates": "rm -rf templates/shopping-app && rsync -
|
|
42
|
+
"copy-templates": "rm -rf templates/shopping-app && rsync -a --exclude='node_modules' --exclude='.turbo' --exclude='dist' --exclude='build' --exclude='**/*.js' --exclude='**/*.js.map' ../../examples/shopping-app/ templates/shopping-app/",
|
|
43
43
|
"build": "npm run copy-templates && tsc && chmod +x dist/index.js",
|
|
44
44
|
"type-check": "tsc --noEmit",
|
|
45
45
|
"lint": "eslint 'src/**/*.ts' --max-warnings 0 --config ../../eslint.config.ts --ignore-pattern 'templates/**'",
|
|
@@ -30,9 +30,9 @@ type MutationError {
|
|
|
30
30
|
message: String
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
input
|
|
33
|
+
input AddItemsToCartInput {
|
|
34
34
|
sessionId: String!
|
|
35
|
-
|
|
35
|
+
items: String!
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
input EnterShoppingCriteriaInput {
|
|
@@ -40,7 +40,7 @@ input EnterShoppingCriteriaInput {
|
|
|
40
40
|
criteria: String!
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
input
|
|
43
|
+
input SuggestShoppingItemsInput {
|
|
44
44
|
sessionId: String!
|
|
45
|
-
|
|
45
|
+
prompt: String!
|
|
46
46
|
}
|
|
@@ -9,15 +9,17 @@
|
|
|
9
9
|
"type": "command",
|
|
10
10
|
"client": {
|
|
11
11
|
"description": "",
|
|
12
|
-
"specs":
|
|
13
|
-
"Assistant Chat Interface",
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
"specs": {
|
|
13
|
+
"name": "Assistant Chat Interface",
|
|
14
|
+
"rules": [
|
|
15
|
+
"allow shopper to describe their shopping needs in natural language",
|
|
16
|
+
"provide a text input for entering criteria",
|
|
17
|
+
"show examples of what to include (age, interests, budget)",
|
|
18
|
+
"show a button to submit the criteria",
|
|
19
|
+
"generate a persisted session id for a visit",
|
|
20
|
+
"show the header on top of the page"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
21
23
|
},
|
|
22
24
|
"request": "mutation EnterShoppingCriteria($input: EnterShoppingCriteriaInput!) {\n enterShoppingCriteria(input: $input) {\n success\n error {\n type\n message\n }\n }\n}",
|
|
23
25
|
"server": {
|
|
@@ -54,8 +56,7 @@
|
|
|
54
56
|
"eventRef": "ShoppingCriteriaEntered",
|
|
55
57
|
"exampleData": {
|
|
56
58
|
"sessionId": "shopper-123",
|
|
57
|
-
"criteria": "I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering."
|
|
58
|
-
"timestamp": "2025-09-04T21:20:20.309Z"
|
|
59
|
+
"criteria": "I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering."
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
]
|
|
@@ -83,8 +84,7 @@
|
|
|
83
84
|
"eventRef": "ShoppingCriteriaEntered",
|
|
84
85
|
"exampleData": {
|
|
85
86
|
"sessionId": "session-abc",
|
|
86
|
-
"criteria": "I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering."
|
|
87
|
-
"timestamp": "2025-09-04T21:20:20.309Z"
|
|
87
|
+
"criteria": "I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering."
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
],
|
|
@@ -108,8 +108,7 @@
|
|
|
108
108
|
"name": "selects items relevant to the shopping criteria",
|
|
109
109
|
"type": "command",
|
|
110
110
|
"client": {
|
|
111
|
-
"description": ""
|
|
112
|
-
"specs": []
|
|
111
|
+
"description": ""
|
|
113
112
|
},
|
|
114
113
|
"server": {
|
|
115
114
|
"description": "",
|
|
@@ -135,7 +134,7 @@
|
|
|
135
134
|
},
|
|
136
135
|
"origin": {
|
|
137
136
|
"type": "integration",
|
|
138
|
-
"systems": ["
|
|
137
|
+
"systems": ["ProductCatalog"]
|
|
139
138
|
}
|
|
140
139
|
}
|
|
141
140
|
},
|
|
@@ -160,6 +159,7 @@
|
|
|
160
159
|
"description": "Product catalog with matching items generates suggestions",
|
|
161
160
|
"given": [
|
|
162
161
|
{
|
|
162
|
+
"stateRef": "Products",
|
|
163
163
|
"exampleData": {
|
|
164
164
|
"products": [
|
|
165
165
|
{
|
|
@@ -195,8 +195,7 @@
|
|
|
195
195
|
"imageUrl": "https://example.com/mtg-starter.jpg"
|
|
196
196
|
}
|
|
197
197
|
]
|
|
198
|
-
}
|
|
199
|
-
"stateRef": "Products"
|
|
198
|
+
}
|
|
200
199
|
}
|
|
201
200
|
],
|
|
202
201
|
"when": {
|
|
@@ -252,13 +251,15 @@
|
|
|
252
251
|
"type": "query",
|
|
253
252
|
"client": {
|
|
254
253
|
"description": "",
|
|
255
|
-
"specs":
|
|
256
|
-
"Suggested Items Screen",
|
|
257
|
-
"
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
"specs": {
|
|
255
|
+
"name": "Suggested Items Screen",
|
|
256
|
+
"rules": [
|
|
257
|
+
"display all suggested items with names and reasons",
|
|
258
|
+
"show quantity selectors for each item",
|
|
259
|
+
"have an \"Add to Cart\" button for selected items",
|
|
260
|
+
"allow removing items from the suggestions"
|
|
261
|
+
]
|
|
262
|
+
}
|
|
262
263
|
},
|
|
263
264
|
"request": "query GetSuggestedItems($sessionId: ID!) {\n suggestedItems(sessionId: $sessionId) {\n items {\n productId\n name\n quantity\n reason\n }\n }\n}",
|
|
264
265
|
"server": {
|
|
@@ -362,12 +363,14 @@
|
|
|
362
363
|
"type": "command",
|
|
363
364
|
"client": {
|
|
364
365
|
"description": "",
|
|
365
|
-
"specs":
|
|
366
|
-
"Suggested Items Screen",
|
|
367
|
-
"
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
366
|
+
"specs": {
|
|
367
|
+
"name": "Suggested Items Screen",
|
|
368
|
+
"rules": [
|
|
369
|
+
"allow selecting specific items to add",
|
|
370
|
+
"update quantities before adding to cart",
|
|
371
|
+
"provide feedback when items are added"
|
|
372
|
+
]
|
|
373
|
+
}
|
|
371
374
|
},
|
|
372
375
|
"server": {
|
|
373
376
|
"description": "",
|
|
@@ -437,8 +440,7 @@
|
|
|
437
440
|
"productId": "prod-mtg-starter",
|
|
438
441
|
"quantity": 1
|
|
439
442
|
}
|
|
440
|
-
]
|
|
441
|
-
"timestamp": "2025-09-04T21:20:20.310Z"
|
|
443
|
+
]
|
|
442
444
|
}
|
|
443
445
|
}
|
|
444
446
|
]
|
|
@@ -569,20 +571,6 @@
|
|
|
569
571
|
"version": 1
|
|
570
572
|
}
|
|
571
573
|
},
|
|
572
|
-
{
|
|
573
|
-
"type": "state",
|
|
574
|
-
"name": "Products",
|
|
575
|
-
"fields": [
|
|
576
|
-
{
|
|
577
|
-
"name": "products",
|
|
578
|
-
"type": "Array<{ productId: string; name: string; category: string; price: number; tags: Array<string>; imageUrl: string }>",
|
|
579
|
-
"required": true
|
|
580
|
-
}
|
|
581
|
-
],
|
|
582
|
-
"metadata": {
|
|
583
|
-
"version": 1
|
|
584
|
-
}
|
|
585
|
-
},
|
|
586
574
|
{
|
|
587
575
|
"type": "command",
|
|
588
576
|
"name": "EnterShoppingCriteria",
|
|
@@ -615,11 +603,6 @@
|
|
|
615
603
|
"name": "criteria",
|
|
616
604
|
"type": "string",
|
|
617
605
|
"required": true
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
"name": "timestamp",
|
|
621
|
-
"type": "Date",
|
|
622
|
-
"required": true
|
|
623
606
|
}
|
|
624
607
|
],
|
|
625
608
|
"source": "internal",
|
|
@@ -646,6 +629,20 @@
|
|
|
646
629
|
"version": 1
|
|
647
630
|
}
|
|
648
631
|
},
|
|
632
|
+
{
|
|
633
|
+
"type": "state",
|
|
634
|
+
"name": "Products",
|
|
635
|
+
"fields": [
|
|
636
|
+
{
|
|
637
|
+
"name": "products",
|
|
638
|
+
"type": "Array<{ productId: string; name: string; category: string; price: number; tags: Array<string>; imageUrl: string }>",
|
|
639
|
+
"required": true
|
|
640
|
+
}
|
|
641
|
+
],
|
|
642
|
+
"metadata": {
|
|
643
|
+
"version": 1
|
|
644
|
+
}
|
|
645
|
+
},
|
|
649
646
|
{
|
|
650
647
|
"type": "event",
|
|
651
648
|
"name": "ShoppingItemsSuggested",
|
|
@@ -717,11 +714,6 @@
|
|
|
717
714
|
"name": "items",
|
|
718
715
|
"type": "Array<{ productId: string; quantity: number }>",
|
|
719
716
|
"required": true
|
|
720
|
-
},
|
|
721
|
-
{
|
|
722
|
-
"name": "timestamp",
|
|
723
|
-
"type": "Date",
|
|
724
|
-
"required": true
|
|
725
717
|
}
|
|
726
718
|
],
|
|
727
719
|
"source": "internal",
|
|
@@ -737,13 +729,13 @@
|
|
|
737
729
|
"source": "@auto-engineer/ai-integration"
|
|
738
730
|
},
|
|
739
731
|
{
|
|
740
|
-
"name": "
|
|
741
|
-
"description": "
|
|
742
|
-
"source": "@auto-engineer/
|
|
732
|
+
"name": "ProductCatalog",
|
|
733
|
+
"description": "ProductCatalog integration",
|
|
734
|
+
"source": "@auto-engineer/productcatalog-integration"
|
|
743
735
|
},
|
|
744
736
|
{
|
|
745
|
-
"name": "
|
|
746
|
-
"description": "
|
|
737
|
+
"name": "Cart",
|
|
738
|
+
"description": "Cart integration",
|
|
747
739
|
"source": "@auto-engineer/cart-integration"
|
|
748
740
|
}
|
|
749
741
|
]
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "tsx --no-deprecation src/server.ts",
|
|
8
8
|
"type-check": "tsc --noEmit",
|
|
9
|
-
"test": "vitest run
|
|
9
|
+
"test": "vitest run",
|
|
10
10
|
"dev": "tsx --no-deprecation src/server.ts"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"typescript": "~5.8.3",
|
|
23
|
-
"vitest": "^3.2.3",
|
|
24
23
|
"tsx": "^4.7.1"
|
|
25
24
|
}
|
|
26
25
|
}
|
|
@@ -34,7 +34,6 @@ describe('SeasonalAssistant | CreatesAChatSession', () => {
|
|
|
34
34
|
sessionId: 'session-abc',
|
|
35
35
|
criteria:
|
|
36
36
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
37
|
-
timestamp: new Date('2025-09-04T21:20:20.309Z'),
|
|
38
37
|
},
|
|
39
38
|
})
|
|
40
39
|
|
|
@@ -30,7 +30,6 @@ describe('Seasonal Assistant | enters shopping criteria into assistant', () => {
|
|
|
30
30
|
sessionId: 'shopper-123',
|
|
31
31
|
criteria:
|
|
32
32
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
33
|
-
timestamp: new Date('2025-09-04T21:20:20.309Z'),
|
|
34
33
|
},
|
|
35
34
|
},
|
|
36
35
|
]);
|
|
@@ -2,7 +2,7 @@ import { IllegalStateError } from '@event-driven-io/emmett';
|
|
|
2
2
|
import type { State } from './state';
|
|
3
3
|
import type { SuggestShoppingItems } from './commands';
|
|
4
4
|
import type { ShoppingItemsSuggested } from './events';
|
|
5
|
-
import type { Products } from '@auto-engineer/
|
|
5
|
+
import type { Products } from '@auto-engineer/productcatalog-integration';
|
|
6
6
|
|
|
7
7
|
export const decide = (command: SuggestShoppingItems, state: State, products?: Products): ShoppingItemsSuggested => {
|
|
8
8
|
switch (command.type) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import '@auto-engineer/
|
|
1
|
+
import '@auto-engineer/productcatalog-integration';
|
|
2
2
|
|
|
3
3
|
import { AI } from '@auto-engineer/ai-integration';
|
|
4
4
|
|
|
5
|
-
import { Products } from '@auto-engineer/
|
|
5
|
+
import { Products } from '@auto-engineer/productcatalog-integration';
|
|
6
6
|
|
|
7
7
|
import { CommandHandler, type EventStore, type MessageHandlerResult } from '@event-driven-io/emmett';
|
|
8
8
|
import { evolve } from './evolve';
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type ClientImplementedEvent,
|
|
30
30
|
type ClientImplementationFailedEvent,
|
|
31
31
|
} from '@auto-engineer/frontend-implementer';
|
|
32
|
+
import { type GenerateClientCommand } from '@auto-engineer/frontend-generator-react-graphql';
|
|
32
33
|
|
|
33
34
|
// Plugin configuration
|
|
34
35
|
export default {
|
|
@@ -100,7 +101,10 @@ const completedOperations = fold<string[], Event>('*', (state = [], event) => {
|
|
|
100
101
|
on<SchemaExportedEvent>('SchemaExported', (event) =>
|
|
101
102
|
dispatch<GenerateServerCommand>({
|
|
102
103
|
type: 'GenerateServer',
|
|
103
|
-
data: {
|
|
104
|
+
data: {
|
|
105
|
+
schemaPath: event.data.outputPath,
|
|
106
|
+
destination: event.data.outputPath.replace('/.context/schema.json', '/server'),
|
|
107
|
+
},
|
|
104
108
|
}),
|
|
105
109
|
);
|
|
106
110
|
|
|
@@ -122,16 +126,20 @@ on<ServerGeneratedEvent>('ServerGenerated', (event) =>
|
|
|
122
126
|
// ]),
|
|
123
127
|
// );
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
on<SchemaExportedEvent>('SchemaExported', (event) =>
|
|
130
|
+
dispatch<GenerateClientCommand>({
|
|
131
|
+
type: 'GenerateClient',
|
|
132
|
+
data: {
|
|
133
|
+
starterDir:
|
|
134
|
+
'/Users/sam/WebstormProjects/top/auto-engineer/packages/frontend-generator-react-graphql/shadcn-starter',
|
|
135
|
+
targetDir: '/Users/sam/WebstormProjects/top/auto-engineer/examples/shopping-app/client',
|
|
136
|
+
iaSchemaPath: '/Users/sam/WebstormProjects/top/auto-engineer/examples/shopping-app/.context/auto-ia-scheme.json',
|
|
137
|
+
gqlSchemaPath: '/Users/sam/WebstormProjects/top/auto-engineer/examples/shopping-app/.context/schema.graphql',
|
|
138
|
+
figmaVariablesPath:
|
|
139
|
+
'/Users/sam/WebstormProjects/top/auto-engineer/examples/shopping-app/.context/figma-variables.json',
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
135
143
|
|
|
136
144
|
// on<ClientImplementedEvent>('ClientImplemented', (event) =>
|
|
137
145
|
// dispatch<CheckClientCommand>({ type: 'CheckClient', data: { clientDirectory: './client', skipBrowserChecks: true } }),
|
|
@@ -23,7 +23,6 @@ type ShoppingCriteriaEntered = Event<
|
|
|
23
23
|
{
|
|
24
24
|
sessionId: string;
|
|
25
25
|
criteria: string;
|
|
26
|
-
timestamp: Date;
|
|
27
26
|
}
|
|
28
27
|
>;
|
|
29
28
|
|
|
@@ -32,7 +31,6 @@ type ItemsAddedToCart = Event<
|
|
|
32
31
|
{
|
|
33
32
|
sessionId: string;
|
|
34
33
|
items: { productId: string; quantity: number }[];
|
|
35
|
-
timestamp: Date;
|
|
36
34
|
}
|
|
37
35
|
>;
|
|
38
36
|
|
|
@@ -76,8 +74,6 @@ type AddItemsToCart = Command<
|
|
|
76
74
|
}
|
|
77
75
|
>;
|
|
78
76
|
|
|
79
|
-
// Using generic DSL instead of typed builders
|
|
80
|
-
|
|
81
77
|
flow('Seasonal Assistant', () => {
|
|
82
78
|
commandSlice('enters shopping criteria into assistant')
|
|
83
79
|
.client(() => {
|
|
@@ -111,14 +107,11 @@ flow('Seasonal Assistant', () => {
|
|
|
111
107
|
criteria:
|
|
112
108
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
113
109
|
})
|
|
114
|
-
.then<ShoppingCriteriaEntered>(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
timestamp: new Date(),
|
|
120
|
-
},
|
|
121
|
-
]);
|
|
110
|
+
.then<ShoppingCriteriaEntered>({
|
|
111
|
+
sessionId: 'shopper-123',
|
|
112
|
+
criteria:
|
|
113
|
+
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
114
|
+
});
|
|
122
115
|
});
|
|
123
116
|
});
|
|
124
117
|
});
|
|
@@ -127,21 +120,16 @@ flow('Seasonal Assistant', () => {
|
|
|
127
120
|
specs('When shopping criteria are entered, request wishlist creation', () => {
|
|
128
121
|
rule('Shopping criteria should trigger item suggestion', () => {
|
|
129
122
|
example('Criteria entered triggers wishlist creation')
|
|
130
|
-
.when<ShoppingCriteriaEntered>(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
sessionId: 'session-abc',
|
|
141
|
-
prompt:
|
|
142
|
-
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
143
|
-
},
|
|
144
|
-
]);
|
|
123
|
+
.when<ShoppingCriteriaEntered>({
|
|
124
|
+
sessionId: 'session-abc',
|
|
125
|
+
criteria:
|
|
126
|
+
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
127
|
+
})
|
|
128
|
+
.then<SuggestShoppingItems>({
|
|
129
|
+
sessionId: 'session-abc',
|
|
130
|
+
prompt:
|
|
131
|
+
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
132
|
+
});
|
|
145
133
|
});
|
|
146
134
|
});
|
|
147
135
|
});
|
|
@@ -161,80 +149,76 @@ flow('Seasonal Assistant', () => {
|
|
|
161
149
|
specs('When chat is triggered, AI suggests items based on product catalog', () => {
|
|
162
150
|
rule('AI should suggest relevant items from available products', () => {
|
|
163
151
|
example('Product catalog with matching items generates suggestions')
|
|
164
|
-
.given<Products>(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
},
|
|
201
|
-
])
|
|
152
|
+
.given<Products>({
|
|
153
|
+
products: [
|
|
154
|
+
{
|
|
155
|
+
productId: 'prod-soccer-ball',
|
|
156
|
+
name: 'Super Soccer Ball',
|
|
157
|
+
category: 'Sports',
|
|
158
|
+
price: 10,
|
|
159
|
+
tags: ['soccer', 'sports'],
|
|
160
|
+
imageUrl: 'https://example.com/soccer-ball.jpg',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
productId: 'prod-craft-kit',
|
|
164
|
+
name: 'Deluxe Craft Kit',
|
|
165
|
+
category: 'Arts & Crafts',
|
|
166
|
+
price: 25,
|
|
167
|
+
tags: ['crafts', 'art', 'creative'],
|
|
168
|
+
imageUrl: 'https://example.com/craft-kit.jpg',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
productId: 'prod-laptop-bag',
|
|
172
|
+
name: 'Tech Laptop Backpack',
|
|
173
|
+
category: 'School Supplies',
|
|
174
|
+
price: 45,
|
|
175
|
+
tags: ['computers', 'tech', 'school'],
|
|
176
|
+
imageUrl: 'https://example.com/laptop-bag.jpg',
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
productId: 'prod-mtg-starter',
|
|
180
|
+
name: 'Magic the Gathering Starter Set',
|
|
181
|
+
category: 'Games',
|
|
182
|
+
price: 30,
|
|
183
|
+
tags: ['magic', 'tcg', 'games'],
|
|
184
|
+
imageUrl: 'https://example.com/mtg-starter.jpg',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
})
|
|
202
188
|
.when<SuggestShoppingItems>({
|
|
203
189
|
sessionId: 'session-abc',
|
|
204
190
|
prompt:
|
|
205
191
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
206
192
|
})
|
|
207
|
-
.then<ShoppingItemsSuggested>(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
},
|
|
237
|
-
]);
|
|
193
|
+
.then<ShoppingItemsSuggested>({
|
|
194
|
+
sessionId: 'session-abc',
|
|
195
|
+
suggestedItems: [
|
|
196
|
+
{
|
|
197
|
+
productId: 'prod-soccer-ball',
|
|
198
|
+
name: 'Super Soccer Ball',
|
|
199
|
+
quantity: 1,
|
|
200
|
+
reason: 'Perfect for your daughter who loves soccer',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
productId: 'prod-craft-kit',
|
|
204
|
+
name: 'Deluxe Craft Kit',
|
|
205
|
+
quantity: 1,
|
|
206
|
+
reason: 'Great for creative activities and crafts',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
productId: 'prod-laptop-bag',
|
|
210
|
+
name: 'Tech Laptop Backpack',
|
|
211
|
+
quantity: 1,
|
|
212
|
+
reason: `Essential for your son's school computer needs`,
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
productId: 'prod-mtg-starter',
|
|
216
|
+
name: 'Magic the Gathering Starter Set',
|
|
217
|
+
quantity: 1,
|
|
218
|
+
reason: 'Ideal starter set for Magic the Gathering enthusiasts',
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
});
|
|
238
222
|
});
|
|
239
223
|
});
|
|
240
224
|
});
|
|
@@ -358,7 +342,6 @@ flow('Seasonal Assistant', () => {
|
|
|
358
342
|
{ productId: 'prod-laptop-bag', quantity: 1 },
|
|
359
343
|
{ productId: 'prod-mtg-starter', quantity: 1 },
|
|
360
344
|
],
|
|
361
|
-
timestamp: new Date(),
|
|
362
345
|
});
|
|
363
346
|
});
|
|
364
347
|
});
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"auto": "auto",
|
|
7
|
-
"auto:debug": "DEBUG=flow:*,cli
|
|
6
|
+
"auto": "node ../../packages/cli/dist/bin/auto.js",
|
|
7
|
+
"auto:debug": "DEBUG=flow:*,cli:*,auto*,ai*,-*file-syncer node ../../packages/cli/dist/bin/auto.js",
|
|
8
8
|
"start": "dotenv -e .env -- pnpm --parallel start",
|
|
9
9
|
"build": "tsc",
|
|
10
10
|
"start:ecommerce-site": "cd examples/ecommerce-site && pnpm start",
|
|
@@ -14,7 +14,7 @@ async function main() {
|
|
|
14
14
|
});
|
|
15
15
|
const printedSchema = printSchema(schema);
|
|
16
16
|
|
|
17
|
-
const contextDir = path.resolve('
|
|
17
|
+
const contextDir = path.resolve('../.context');
|
|
18
18
|
const schemaPath = path.join(contextDir, 'schema.graphql');
|
|
19
19
|
await writeFile(schemaPath, printedSchema, 'utf-8');
|
|
20
20
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { State, Integration } from '@auto-engineer/flow';
|
|
2
|
-
import { registerTool
|
|
2
|
+
import { registerTool } from '@auto-engineer/ai-gateway';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
|
|
4
5
|
import { createClient } from './generated/product-catalog/client';
|
|
5
6
|
import type {
|
|
@@ -109,6 +110,7 @@ const _ProductCatalog: Integration<'product-catalog', ProductCatalogQueries> = {
|
|
|
109
110
|
// ---------- Lazy MCP tool registration ----------
|
|
110
111
|
let _toolsRegistered = false;
|
|
111
112
|
|
|
113
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
112
114
|
function registerProductCatalogToolsOnce(): void {
|
|
113
115
|
if (_toolsRegistered) return;
|
|
114
116
|
_toolsRegistered = true;
|
|
@@ -126,12 +128,6 @@ function registerProductCatalogToolsOnce(): void {
|
|
|
126
128
|
},
|
|
127
129
|
async () => {
|
|
128
130
|
const queries = _ProductCatalog.Queries as ProductCatalogQueries;
|
|
129
|
-
if (!queries?.Products) {
|
|
130
|
-
return {
|
|
131
|
-
content: [{ type: 'text' as const, text: 'ProductCatalog.Queries.Products is not available' }],
|
|
132
|
-
isError: true,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
131
|
const result = await queries.Products();
|
|
136
132
|
return { content: [{ type: 'text' as const, text: JSON.stringify(result.data.products, null, 2) }] };
|
|
137
133
|
},
|
|
@@ -151,14 +147,8 @@ function registerProductCatalogToolsOnce(): void {
|
|
|
151
147
|
schemaName: 'GetApiProductsCategoryByCategoryResponse',
|
|
152
148
|
schemaDescription: 'Array of ProductCatalogItem',
|
|
153
149
|
},
|
|
154
|
-
async ({ category }) => {
|
|
150
|
+
async ({ category }: ProductsByCategoryParams) => {
|
|
155
151
|
const queries = _ProductCatalog.Queries as ProductCatalogQueries;
|
|
156
|
-
if (!queries?.ProductsByCategory) {
|
|
157
|
-
return {
|
|
158
|
-
content: [{ type: 'text' as const, text: 'ProductCatalog.Queries.ProductsByCategory is not available' }],
|
|
159
|
-
isError: true,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
152
|
const result = await queries.ProductsByCategory({ category });
|
|
163
153
|
return { content: [{ type: 'text' as const, text: JSON.stringify(result.data.products, null, 2) }] };
|
|
164
154
|
},
|
|
@@ -178,14 +168,8 @@ function registerProductCatalogToolsOnce(): void {
|
|
|
178
168
|
schemaName: 'GetApiProductsSearchResponse',
|
|
179
169
|
schemaDescription: 'Array of ProductCatalogItem',
|
|
180
170
|
},
|
|
181
|
-
async ({ query }) => {
|
|
171
|
+
async ({ query }: ProductSearchParams) => {
|
|
182
172
|
const queries = _ProductCatalog.Queries as ProductCatalogQueries;
|
|
183
|
-
if (!queries?.ProductSearchResults) {
|
|
184
|
-
return {
|
|
185
|
-
content: [{ type: 'text' as const, text: 'ProductCatalog.Queries.ProductSearchResults is not available' }],
|
|
186
|
-
isError: true,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
173
|
const result = await queries.ProductSearchResults({ query });
|
|
190
174
|
return { content: [{ type: 'text' as const, text: JSON.stringify(result.data.products, null, 2) }] };
|
|
191
175
|
},
|
|
@@ -205,14 +189,8 @@ function registerProductCatalogToolsOnce(): void {
|
|
|
205
189
|
schemaName: 'GetApiProductsByIdResponse',
|
|
206
190
|
schemaDescription: 'Single ProductCatalogItem',
|
|
207
191
|
},
|
|
208
|
-
async ({ id }) => {
|
|
192
|
+
async ({ id }: ProductDetailsParams) => {
|
|
209
193
|
const queries = _ProductCatalog.Queries as ProductCatalogQueries;
|
|
210
|
-
if (!queries?.ProductDetails) {
|
|
211
|
-
return {
|
|
212
|
-
content: [{ type: 'text' as const, text: 'ProductCatalog.Queries.ProductDetails is not available' }],
|
|
213
|
-
isError: true,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
194
|
const result = await queries.ProductDetails({ id });
|
|
217
195
|
if (result.data.product === null) {
|
|
218
196
|
return { content: [{ type: 'text' as const, text: `Product with ID "${id}" not found` }], isError: true };
|
|
@@ -221,12 +199,13 @@ function registerProductCatalogToolsOnce(): void {
|
|
|
221
199
|
},
|
|
222
200
|
);
|
|
223
201
|
}
|
|
202
|
+
/* eslint-enable @typescript-eslint/no-unsafe-call */
|
|
224
203
|
|
|
225
204
|
// registers tools on *first usage* of the integration
|
|
226
205
|
export const ProductCatalog: Integration<'product-catalog', ProductCatalogQueries> = new Proxy(_ProductCatalog, {
|
|
227
206
|
get(target, prop, receiver) {
|
|
228
207
|
// First touch of ProductCatalog triggers tool registration
|
|
229
208
|
registerProductCatalogToolsOnce();
|
|
230
|
-
return Reflect.get(target, prop, receiver);
|
|
209
|
+
return Reflect.get(target, prop, receiver) as unknown;
|
|
231
210
|
},
|
|
232
211
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://turbo.build/schema.json",
|
|
3
|
+
"extends": ["//"],
|
|
4
|
+
"tasks": {
|
|
5
|
+
"auto": {
|
|
6
|
+
"dependsOn": ["^build"],
|
|
7
|
+
"inputs": []
|
|
8
|
+
},
|
|
9
|
+
"auto:debug": {
|
|
10
|
+
"dependsOn": ["^build"],
|
|
11
|
+
"inputs": []
|
|
12
|
+
},
|
|
13
|
+
"build": {
|
|
14
|
+
"dependsOn": ["^build"],
|
|
15
|
+
"inputs": [],
|
|
16
|
+
"outputs": []
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|