nitrostack 1.0.55 → 1.0.57
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/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +14 -9
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/widgets/hooks/index.d.ts +7 -0
- package/dist/widgets/hooks/index.d.ts.map +1 -0
- package/dist/widgets/hooks/index.js +7 -0
- package/dist/widgets/hooks/index.js.map +1 -0
- package/dist/widgets/hooks/use-display-mode.d.ts +11 -0
- package/dist/widgets/hooks/use-display-mode.d.ts.map +1 -0
- package/dist/widgets/hooks/use-display-mode.js +13 -0
- package/dist/widgets/hooks/use-display-mode.js.map +1 -0
- package/dist/widgets/hooks/use-max-height.d.ts +10 -0
- package/dist/widgets/hooks/use-max-height.d.ts.map +1 -0
- package/dist/widgets/hooks/use-max-height.js +13 -0
- package/dist/widgets/hooks/use-max-height.js.map +1 -0
- package/dist/widgets/hooks/use-openai-global.d.ts +12 -0
- package/dist/widgets/hooks/use-openai-global.d.ts.map +1 -0
- package/dist/widgets/hooks/use-openai-global.js +32 -0
- package/dist/widgets/hooks/use-openai-global.js.map +1 -0
- package/dist/widgets/hooks/use-theme.d.ts +10 -0
- package/dist/widgets/hooks/use-theme.d.ts.map +1 -0
- package/dist/widgets/hooks/use-theme.js +12 -0
- package/dist/widgets/hooks/use-theme.js.map +1 -0
- package/dist/widgets/hooks/use-widget-state.d.ts +18 -0
- package/dist/widgets/hooks/use-widget-state.d.ts.map +1 -0
- package/dist/widgets/hooks/use-widget-state.js +27 -0
- package/dist/widgets/hooks/use-widget-state.js.map +1 -0
- package/dist/widgets/hooks/useWidgetSDK.d.ts +47 -0
- package/dist/widgets/hooks/useWidgetSDK.d.ts.map +1 -0
- package/dist/widgets/hooks/useWidgetSDK.js +67 -0
- package/dist/widgets/hooks/useWidgetSDK.js.map +1 -0
- package/dist/widgets/index.d.ts +7 -1
- package/dist/widgets/index.d.ts.map +1 -1
- package/dist/widgets/index.js +11 -1
- package/dist/widgets/index.js.map +1 -1
- package/dist/widgets/runtime/WidgetLayout.d.ts +32 -0
- package/dist/widgets/runtime/WidgetLayout.d.ts.map +1 -0
- package/dist/widgets/runtime/WidgetLayout.js +143 -0
- package/dist/widgets/runtime/WidgetLayout.js.map +1 -0
- package/dist/widgets/runtime/widget-polyfill.d.ts +1 -0
- package/dist/widgets/runtime/widget-polyfill.d.ts.map +1 -0
- package/dist/widgets/runtime/widget-polyfill.js +28 -0
- package/dist/widgets/runtime/widget-polyfill.js.map +1 -0
- package/dist/widgets/sdk.d.ts +109 -0
- package/dist/widgets/sdk.d.ts.map +1 -0
- package/dist/widgets/sdk.js +221 -0
- package/dist/widgets/sdk.js.map +1 -0
- package/dist/widgets/types.d.ts +89 -0
- package/dist/widgets/types.d.ts.map +1 -0
- package/dist/widgets/types.js +8 -0
- package/dist/widgets/types.js.map +1 -0
- package/dist/widgets/utils/media-queries.d.ts +34 -0
- package/dist/widgets/utils/media-queries.d.ts.map +1 -0
- package/dist/widgets/utils/media-queries.js +42 -0
- package/dist/widgets/utils/media-queries.js.map +1 -0
- package/package.json +2 -2
- package/src/studio/app/chat/page.tsx +274 -137
- package/src/studio/app/globals.css +140 -64
- package/src/studio/branding.md +807 -0
- package/src/studio/components/WidgetRenderer.tsx +222 -16
- package/src/studio/lib/llm-service.ts +39 -39
- package/templates/typescript-oauth/{env.example → .env.example} +4 -10
- package/templates/typescript-oauth/README.md +226 -306
- package/templates/typescript-oauth/package-lock.json +4253 -0
- package/templates/typescript-oauth/package.json +10 -5
- package/templates/typescript-oauth/src/app.module.ts +39 -36
- package/templates/typescript-oauth/src/guards/oauth.guard.ts +0 -1
- package/templates/typescript-oauth/src/index.ts +22 -30
- package/templates/typescript-oauth/src/modules/flights/booking.tools.ts +323 -0
- package/templates/typescript-oauth/src/modules/flights/flights.module.ts +14 -0
- package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +231 -0
- package/templates/typescript-oauth/src/modules/flights/flights.resources.ts +215 -0
- package/templates/typescript-oauth/src/modules/flights/flights.tools.ts +457 -0
- package/templates/typescript-oauth/src/services/duffel.service.ts +285 -0
- package/templates/typescript-oauth/src/widgets/app/airport-search/page.tsx +270 -0
- package/templates/typescript-oauth/src/widgets/app/flight-details/page.tsx +261 -0
- package/templates/typescript-oauth/src/widgets/app/flight-search-results/page.tsx +378 -0
- package/templates/typescript-oauth/src/widgets/app/globals.css +167 -0
- package/templates/typescript-oauth/src/widgets/app/layout.tsx +6 -2
- package/templates/typescript-oauth/src/widgets/app/order-cancellation/page.tsx +207 -0
- package/templates/typescript-oauth/src/widgets/app/order-summary/page.tsx +245 -0
- package/templates/typescript-oauth/src/widgets/app/payment-confirmation/page.tsx +152 -0
- package/templates/typescript-oauth/src/widgets/app/seat-selection/page.tsx +486 -0
- package/templates/typescript-oauth/src/widgets/next-env.d.ts +5 -0
- package/templates/typescript-oauth/src/widgets/package-lock.json +155 -126
- package/templates/typescript-oauth/src/widgets/widget-manifest.json +374 -27
- package/templates/typescript-pizzaz/IMPLEMENTATION.md +98 -0
- package/templates/typescript-pizzaz/README.md +233 -0
- package/templates/typescript-pizzaz/package.json +31 -0
- package/templates/typescript-pizzaz/src/app.module.ts +28 -0
- package/templates/typescript-pizzaz/src/index.ts +30 -0
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.data.ts +106 -0
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.module.ts +11 -0
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.service.ts +60 -0
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.tools.ts +197 -0
- package/templates/typescript-pizzaz/src/widgets/app/layout.tsx +18 -0
- package/templates/typescript-pizzaz/src/widgets/app/pizza-list/page.tsx +272 -0
- package/templates/typescript-pizzaz/src/widgets/app/pizza-map/page.tsx +216 -0
- package/templates/typescript-pizzaz/src/widgets/app/pizza-shop/page.tsx +374 -0
- package/templates/typescript-pizzaz/src/widgets/components/CompactShopCard.tsx +144 -0
- package/templates/typescript-pizzaz/src/widgets/components/PizzaCard.tsx +191 -0
- package/templates/typescript-pizzaz/src/widgets/package.json +30 -0
- package/templates/typescript-pizzaz/src/widgets/widget-manifest.json +253 -0
- package/templates/typescript-pizzaz/tsconfig.json +30 -0
- package/templates/typescript-starter/src/modules/calculator/calculator.resources.ts +0 -1
- package/templates/typescript-starter/src/widgets/app/calculator-result/page.tsx +102 -56
- package/templates/typescript-starter/src/widgets/app/layout.tsx +6 -2
- package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +0 -702
- package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +0 -1260
- package/templates/typescript-auth/README.md +0 -402
- package/templates/typescript-auth/env.example +0 -25
- package/templates/typescript-auth/package.json +0 -36
- package/templates/typescript-auth/src/app.module.ts +0 -103
- package/templates/typescript-auth/src/db/database.ts +0 -160
- package/templates/typescript-auth/src/db/seed.ts +0 -374
- package/templates/typescript-auth/src/db/setup.ts +0 -87
- package/templates/typescript-auth/src/events/analytics.service.ts +0 -52
- package/templates/typescript-auth/src/events/notification.service.ts +0 -40
- package/templates/typescript-auth/src/filters/global-exception.filter.ts +0 -28
- package/templates/typescript-auth/src/guards/README.md +0 -75
- package/templates/typescript-auth/src/guards/jwt.guard.ts +0 -105
- package/templates/typescript-auth/src/health/database.health.ts +0 -41
- package/templates/typescript-auth/src/index.ts +0 -29
- package/templates/typescript-auth/src/interceptors/transform.interceptor.ts +0 -24
- package/templates/typescript-auth/src/middleware/logging.middleware.ts +0 -42
- package/templates/typescript-auth/src/modules/addresses/addresses.module.ts +0 -16
- package/templates/typescript-auth/src/modules/addresses/addresses.prompts.ts +0 -114
- package/templates/typescript-auth/src/modules/addresses/addresses.resources.ts +0 -40
- package/templates/typescript-auth/src/modules/addresses/addresses.tools.ts +0 -284
- package/templates/typescript-auth/src/modules/auth/auth.module.ts +0 -16
- package/templates/typescript-auth/src/modules/auth/auth.prompts.ts +0 -147
- package/templates/typescript-auth/src/modules/auth/auth.resources.ts +0 -84
- package/templates/typescript-auth/src/modules/auth/auth.tools.ts +0 -139
- package/templates/typescript-auth/src/modules/cart/cart.module.ts +0 -16
- package/templates/typescript-auth/src/modules/cart/cart.prompts.ts +0 -95
- package/templates/typescript-auth/src/modules/cart/cart.resources.ts +0 -44
- package/templates/typescript-auth/src/modules/cart/cart.tools.ts +0 -277
- package/templates/typescript-auth/src/modules/orders/orders.module.ts +0 -16
- package/templates/typescript-auth/src/modules/orders/orders.prompts.ts +0 -88
- package/templates/typescript-auth/src/modules/orders/orders.resources.ts +0 -48
- package/templates/typescript-auth/src/modules/orders/orders.tools.ts +0 -303
- package/templates/typescript-auth/src/modules/products/products.module.ts +0 -16
- package/templates/typescript-auth/src/modules/products/products.prompts.ts +0 -146
- package/templates/typescript-auth/src/modules/products/products.resources.ts +0 -98
- package/templates/typescript-auth/src/modules/products/products.tools.ts +0 -266
- package/templates/typescript-auth/src/pipes/validation.pipe.ts +0 -42
- package/templates/typescript-auth/src/services/database.service.ts +0 -90
- package/templates/typescript-auth/src/widgets/app/add-to-cart/page.tsx +0 -122
- package/templates/typescript-auth/src/widgets/app/address-added/page.tsx +0 -116
- package/templates/typescript-auth/src/widgets/app/address-deleted/page.tsx +0 -105
- package/templates/typescript-auth/src/widgets/app/address-list/page.tsx +0 -139
- package/templates/typescript-auth/src/widgets/app/address-updated/page.tsx +0 -153
- package/templates/typescript-auth/src/widgets/app/cart-cleared/page.tsx +0 -86
- package/templates/typescript-auth/src/widgets/app/cart-updated/page.tsx +0 -116
- package/templates/typescript-auth/src/widgets/app/categories/page.tsx +0 -134
- package/templates/typescript-auth/src/widgets/app/layout.tsx +0 -21
- package/templates/typescript-auth/src/widgets/app/login-result/page.tsx +0 -129
- package/templates/typescript-auth/src/widgets/app/order-confirmation/page.tsx +0 -231
- package/templates/typescript-auth/src/widgets/app/order-details/page.tsx +0 -225
- package/templates/typescript-auth/src/widgets/app/order-history/page.tsx +0 -218
- package/templates/typescript-auth/src/widgets/app/product-card/page.tsx +0 -121
- package/templates/typescript-auth/src/widgets/app/products-grid/page.tsx +0 -198
- package/templates/typescript-auth/src/widgets/app/shopping-cart/page.tsx +0 -187
- package/templates/typescript-auth/src/widgets/app/whoami/page.tsx +0 -165
- package/templates/typescript-auth/src/widgets/next.config.js +0 -38
- package/templates/typescript-auth/src/widgets/package.json +0 -18
- package/templates/typescript-auth/src/widgets/styles/ecommerce.ts +0 -169
- package/templates/typescript-auth/src/widgets/tsconfig.json +0 -28
- package/templates/typescript-auth/src/widgets/types/tool-data.ts +0 -141
- package/templates/typescript-auth/src/widgets/widget-manifest.json +0 -464
- package/templates/typescript-auth/tsconfig.json +0 -27
- package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +0 -701
- package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +0 -1260
- package/templates/typescript-auth-api-key/README.md +0 -485
- package/templates/typescript-auth-api-key/env.example +0 -17
- package/templates/typescript-auth-api-key/package.json +0 -21
- package/templates/typescript-auth-api-key/src/app.module.ts +0 -38
- package/templates/typescript-auth-api-key/src/guards/apikey.guard.ts +0 -47
- package/templates/typescript-auth-api-key/src/guards/multi-auth.guard.ts +0 -157
- package/templates/typescript-auth-api-key/src/index.ts +0 -47
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.module.ts +0 -12
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.prompts.ts +0 -73
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.resources.ts +0 -60
- package/templates/typescript-auth-api-key/src/modules/calculator/calculator.tools.ts +0 -71
- package/templates/typescript-auth-api-key/src/modules/demo/demo.module.ts +0 -18
- package/templates/typescript-auth-api-key/src/modules/demo/demo.tools.ts +0 -155
- package/templates/typescript-auth-api-key/src/modules/demo/multi-auth.tools.ts +0 -123
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-operations/page.tsx +0 -133
- package/templates/typescript-auth-api-key/src/widgets/app/calculator-result/page.tsx +0 -134
- package/templates/typescript-auth-api-key/src/widgets/app/layout.tsx +0 -14
- package/templates/typescript-auth-api-key/src/widgets/package.json +0 -24
- package/templates/typescript-auth-api-key/src/widgets/widget-manifest.json +0 -48
- package/templates/typescript-auth-api-key/tsconfig.json +0 -23
- package/templates/typescript-oauth/OAUTH_SETUP.md +0 -592
- package/templates/typescript-oauth/src/modules/demo/demo.module.ts +0 -16
- package/templates/typescript-oauth/src/modules/demo/demo.tools.ts +0 -190
- package/templates/typescript-oauth/src/widgets/app/calculator-operations/page.tsx +0 -133
- package/templates/typescript-oauth/src/widgets/app/calculator-result/page.tsx +0 -134
- package/templates/typescript-oauth/src/widgets/out/404.html +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_buildManifest.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/WU9THacVqL52RZbrZOLS1/_ssgManifest.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/117-eb57c7ef86f964a4.js +0 -2
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/_not-found/page-dcb83ba3e4d0aafd.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-operations/page-b8913a740073ea8a.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/calculator-result/page-ddaaab2fce95dea2.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/app/layout-cbd3ebdc4ecc5247.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/fd9d1056-749e5812300142af.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/framework-f66176bb897dc684.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-76df43fcef3db344.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/main-app-f9c40224d04023c5.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_app-72b849fbd24ac258.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/pages/_error-7ba65e1336b92748.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/_next/static/chunks/webpack-100b9e646d9c912e.js +0 -1
- package/templates/typescript-oauth/src/widgets/out/calculator-operations.html +0 -1
- package/templates/typescript-oauth/src/widgets/out/calculator-operations.txt +0 -7
- package/templates/typescript-oauth/src/widgets/out/calculator-result.html +0 -1
- package/templates/typescript-oauth/src/widgets/out/calculator-result.txt +0 -7
- package/templates/typescript-starter/src/widgets/app/calculator-operations/page.tsx +0 -133
- /package/templates/{typescript-auth-api-key → typescript-oauth}/src/health/system.health.ts +0 -0
- /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/next.config.js +0 -0
- /package/templates/{typescript-auth-api-key → typescript-pizzaz}/src/widgets/tsconfig.json +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# 🍕 Pizzaz - Pizza Shop Finder
|
|
2
|
+
|
|
3
|
+
A comprehensive NitroStack template showcasing interactive pizza shop discovery with maps, lists, and detailed views. This template demonstrates the NitroStack Widget SDK for building interactive widgets.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### 🎨 **Widget SDK Features**
|
|
8
|
+
- ✅ `useTheme()` - Automatic dark mode support
|
|
9
|
+
- ✅ `useWidgetState()` - Persistent favorites and view preferences
|
|
10
|
+
- ✅ `useMaxHeight()` - Responsive height-aware layouts
|
|
11
|
+
- ✅ `useDisplayMode()` - Fullscreen mode adaptation
|
|
12
|
+
- ✅ `useWidgetSDK()` - Tool calling, navigation, and external links
|
|
13
|
+
- ✅ `<WidgetLayout>` - Automatic RPC setup
|
|
14
|
+
|
|
15
|
+
### 🗺️ **Three Interactive Widgets**
|
|
16
|
+
1. **Pizza Map** - Interactive Mapbox map with markers and shop selection
|
|
17
|
+
2. **Pizza List** - Grid/list view with sorting, filtering, and favorites
|
|
18
|
+
3. **Pizza Shop** - Detailed shop information with contact actions
|
|
19
|
+
|
|
20
|
+
### 📊 **MCP Tools**
|
|
21
|
+
- `show_pizza_map` - Display shops on an interactive map
|
|
22
|
+
- `show_pizza_list` - Show filterable list of shops
|
|
23
|
+
- `show_pizza_shop` - Display detailed shop information
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### 1. Install Dependencies
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install
|
|
31
|
+
cd src/widgets && npm install && cd ../..
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Configure Mapbox (Optional)
|
|
35
|
+
|
|
36
|
+
The map widget uses Mapbox GL. To use it:
|
|
37
|
+
|
|
38
|
+
1. Get a free API key from [Mapbox](https://www.mapbox.com/)
|
|
39
|
+
2. Create `.env` file:
|
|
40
|
+
```bash
|
|
41
|
+
NEXT_PUBLIC_MAPBOX_TOKEN=your_mapbox_token_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> **Note**: The template works without Mapbox, but the map widget will show an error. You can still use the list and shop widgets.
|
|
45
|
+
|
|
46
|
+
### 3. Run Development Server
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run dev
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The MCP server will start on `http://localhost:3000`
|
|
53
|
+
|
|
54
|
+
### 4. Run Widget Dev Server
|
|
55
|
+
|
|
56
|
+
In a separate terminal:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm run widget dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Widgets will be available on `http://localhost:3001`
|
|
63
|
+
|
|
64
|
+
### 5. Test in NitroStudio
|
|
65
|
+
|
|
66
|
+
1. Open NitroStudio
|
|
67
|
+
2. Connect to your MCP server
|
|
68
|
+
3. Try these prompts:
|
|
69
|
+
- "Show me pizza shops on a map"
|
|
70
|
+
- "List all pizza shops"
|
|
71
|
+
- "Show me details for Tony's New York Pizza"
|
|
72
|
+
|
|
73
|
+
## Project Structure
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
typescript-pizzaz/
|
|
77
|
+
├── src/
|
|
78
|
+
│ ├── index.ts # Main server entry
|
|
79
|
+
│ ├── app.module.ts # App module
|
|
80
|
+
│ └── modules/
|
|
81
|
+
│ └── pizzaz/
|
|
82
|
+
│ ├── pizzaz.data.ts # Pizza shop data
|
|
83
|
+
│ ├── pizzaz.service.ts # Business logic
|
|
84
|
+
│ ├── pizzaz.tools.ts # MCP tools
|
|
85
|
+
│ └── pizzaz.module.ts # Module definition
|
|
86
|
+
│ └── widgets/
|
|
87
|
+
│ ├── app/
|
|
88
|
+
│ │ ├── pizza-map/ # Map widget
|
|
89
|
+
│ │ ├── pizza-list/ # List widget
|
|
90
|
+
│ │ └── pizza-shop/ # Shop detail widget
|
|
91
|
+
│ └── components/
|
|
92
|
+
│ └── PizzaCard.tsx # Reusable card component
|
|
93
|
+
├── package.json
|
|
94
|
+
└── README.md
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Widget Features
|
|
98
|
+
|
|
99
|
+
### Pizza Map Widget
|
|
100
|
+
- **Interactive Mapbox map** with custom markers
|
|
101
|
+
- **Shop sidebar** with quick selection
|
|
102
|
+
- **Fullscreen mode** for better exploration
|
|
103
|
+
- **Persistent favorites** using `useWidgetState()`
|
|
104
|
+
- **Theme-aware** map styles (light/dark)
|
|
105
|
+
|
|
106
|
+
### Pizza List Widget
|
|
107
|
+
- **Grid/List view toggle** with state persistence
|
|
108
|
+
- **Sorting** by rating, name, or price
|
|
109
|
+
- **Favorites tracking** across sessions
|
|
110
|
+
- **Responsive layout** using `useMaxHeight()`
|
|
111
|
+
- **Filter panel** for advanced search
|
|
112
|
+
|
|
113
|
+
### Pizza Shop Widget
|
|
114
|
+
- **Hero image** with overlay information
|
|
115
|
+
- **Contact actions** (call, directions, website)
|
|
116
|
+
- **Specialties showcase**
|
|
117
|
+
- **Related shops** recommendations
|
|
118
|
+
- **External link handling** via `useWidgetSDK()`
|
|
119
|
+
|
|
120
|
+
## Customization
|
|
121
|
+
|
|
122
|
+
### Adding More Shops
|
|
123
|
+
|
|
124
|
+
Edit `src/modules/pizzaz/pizzaz.data.ts`:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
export const PIZZA_SHOPS: PizzaShop[] = [
|
|
128
|
+
{
|
|
129
|
+
id: 'my-pizza-shop',
|
|
130
|
+
name: 'My Pizza Shop',
|
|
131
|
+
description: 'Amazing pizza!',
|
|
132
|
+
address: '123 Main St, City, State 12345',
|
|
133
|
+
coords: [-122.4194, 37.7749], // [lng, lat]
|
|
134
|
+
rating: 4.5,
|
|
135
|
+
reviews: 100,
|
|
136
|
+
priceLevel: 2,
|
|
137
|
+
cuisine: ['Italian', 'Pizza'],
|
|
138
|
+
hours: { open: '11:00 AM', close: '10:00 PM' },
|
|
139
|
+
phone: '(555) 123-4567',
|
|
140
|
+
website: 'https://example.com',
|
|
141
|
+
image: 'https://images.unsplash.com/photo-...',
|
|
142
|
+
specialties: ['Margherita', 'Pepperoni'],
|
|
143
|
+
openNow: true,
|
|
144
|
+
},
|
|
145
|
+
// ... more shops
|
|
146
|
+
];
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Changing Map Style
|
|
150
|
+
|
|
151
|
+
Edit `src/widgets/app/pizza-map/page.tsx`:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
style: isDark
|
|
155
|
+
? 'mapbox://styles/mapbox/dark-v11' // Dark mode style
|
|
156
|
+
: 'mapbox://styles/mapbox/streets-v12' // Light mode style
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Adding New Filters
|
|
160
|
+
|
|
161
|
+
Edit `src/modules/pizzaz/pizzaz.service.ts` to add more filter options.
|
|
162
|
+
|
|
163
|
+
## Deployment
|
|
164
|
+
|
|
165
|
+
### Build for Production
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm run build
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Deploy to OpenAI ChatGPT
|
|
172
|
+
|
|
173
|
+
1. Build widgets:
|
|
174
|
+
```bash
|
|
175
|
+
cd src/widgets && npm run build
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
2. Widget HTML files will be in `src/widgets/out/`
|
|
179
|
+
|
|
180
|
+
3. Upload to your MCP server
|
|
181
|
+
|
|
182
|
+
4. **Zero code changes needed!** Widgets work identically in OpenAI ChatGPT.
|
|
183
|
+
|
|
184
|
+
## SDK Features Demonstrated
|
|
185
|
+
|
|
186
|
+
### Theme Awareness
|
|
187
|
+
```typescript
|
|
188
|
+
const theme = useTheme(); // 'light' | 'dark'
|
|
189
|
+
const bgColor = theme === 'dark' ? '#000' : '#fff';
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### State Persistence
|
|
193
|
+
```typescript
|
|
194
|
+
const [state, setState] = useWidgetState(() => ({
|
|
195
|
+
favorites: [],
|
|
196
|
+
viewMode: 'grid',
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
// State persists across widget reloads
|
|
200
|
+
setState({ ...state, favorites: [...state.favorites, shopId] });
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Responsive Layouts
|
|
204
|
+
```typescript
|
|
205
|
+
const maxHeight = useMaxHeight();
|
|
206
|
+
return <div style={{ maxHeight }}>{content}</div>;
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Display Mode Adaptation
|
|
210
|
+
```typescript
|
|
211
|
+
const displayMode = useDisplayMode(); // 'inline' | 'pip' | 'fullscreen'
|
|
212
|
+
const showSidebar = displayMode === 'fullscreen';
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### External Links
|
|
216
|
+
```typescript
|
|
217
|
+
const { openExternal } = useWidgetSDK();
|
|
218
|
+
openExternal('https://example.com');
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Learn More
|
|
222
|
+
|
|
223
|
+
- [NitroStack Documentation](https://nitrostack.dev)
|
|
224
|
+
- [Widget Development Guide](../../WIDGET_DEVELOPMENT.md)
|
|
225
|
+
- [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/)
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
**Built with ❤️ using NitroStack**
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nitrostack-pizzaz",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Pizza shop finder with interactive map - NitroStack template showcasing Widget SDK features",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "nitrostack dev",
|
|
9
|
+
"build": "nitrostack build",
|
|
10
|
+
"start": "npm run build && nitrostack start",
|
|
11
|
+
"start:prod": "nitrostack start",
|
|
12
|
+
"widget": "npm --prefix src/widgets"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"nitrostack",
|
|
16
|
+
"mcp",
|
|
17
|
+
"pizza",
|
|
18
|
+
"map",
|
|
19
|
+
"widgets"
|
|
20
|
+
],
|
|
21
|
+
"author": "",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"nitrostack": "^1",
|
|
25
|
+
"zod": "^3.22.4",
|
|
26
|
+
"dotenv": "^16.3.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.3.3"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { McpApp, Module, ConfigModule } from 'nitrostack';
|
|
2
|
+
import { PizzazModule } from './modules/pizzaz/pizzaz.module.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Root Application Module
|
|
6
|
+
*
|
|
7
|
+
* Pizza shop finder with interactive maps.
|
|
8
|
+
* Showcases NitroStack Widget SDK features.
|
|
9
|
+
*/
|
|
10
|
+
@McpApp({
|
|
11
|
+
module: AppModule,
|
|
12
|
+
server: {
|
|
13
|
+
name: 'pizzaz-finder',
|
|
14
|
+
version: '1.0.0'
|
|
15
|
+
},
|
|
16
|
+
logging: {
|
|
17
|
+
level: 'info'
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
@Module({
|
|
21
|
+
name: 'pizzaz',
|
|
22
|
+
description: 'Pizza shop finder with interactive maps',
|
|
23
|
+
imports: [
|
|
24
|
+
ConfigModule.forRoot(),
|
|
25
|
+
PizzazModule
|
|
26
|
+
],
|
|
27
|
+
})
|
|
28
|
+
export class AppModule { }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pizzaz MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Pizza shop finder with interactive map widgets.
|
|
5
|
+
* Showcases NitroStack Widget SDK features including:
|
|
6
|
+
* - useTheme() for dark mode
|
|
7
|
+
* - useWidgetState() for persistent favorites
|
|
8
|
+
* - useDisplayMode() for fullscreen support
|
|
9
|
+
* - useMaxHeight() for responsive layouts
|
|
10
|
+
* - useWidgetSDK() for tool calling and navigation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import 'dotenv/config';
|
|
14
|
+
import { McpApplicationFactory } from 'nitrostack';
|
|
15
|
+
import { AppModule } from './app.module.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Bootstrap the application
|
|
19
|
+
*/
|
|
20
|
+
async function bootstrap() {
|
|
21
|
+
// Create and start the MCP server
|
|
22
|
+
const server = await McpApplicationFactory.create(AppModule);
|
|
23
|
+
await server.start();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Start the application
|
|
27
|
+
bootstrap().catch((error) => {
|
|
28
|
+
console.error('❌ Failed to start server:', error);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface PizzaShop {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
address: string;
|
|
6
|
+
coords: [number, number]; // [lng, lat]
|
|
7
|
+
rating: number;
|
|
8
|
+
reviews: number;
|
|
9
|
+
priceLevel: 1 | 2 | 3;
|
|
10
|
+
cuisine: string[];
|
|
11
|
+
hours: {
|
|
12
|
+
open: string;
|
|
13
|
+
close: string;
|
|
14
|
+
};
|
|
15
|
+
phone: string;
|
|
16
|
+
website?: string;
|
|
17
|
+
image: string;
|
|
18
|
+
specialties: string[];
|
|
19
|
+
openNow: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const PIZZA_SHOPS: PizzaShop[] = [
|
|
23
|
+
{
|
|
24
|
+
id: 'tonys-pizza',
|
|
25
|
+
name: "Tony's New York Pizza",
|
|
26
|
+
description: "Authentic New York-style pizza with a crispy thin crust and fresh toppings",
|
|
27
|
+
address: "123 Main St, San Francisco, CA 94102",
|
|
28
|
+
coords: [-122.4194, 37.7749],
|
|
29
|
+
rating: 4.5,
|
|
30
|
+
reviews: 342,
|
|
31
|
+
priceLevel: 2,
|
|
32
|
+
cuisine: ['Italian', 'Pizza', 'New York Style'],
|
|
33
|
+
hours: { open: '11:00 AM', close: '10:00 PM' },
|
|
34
|
+
phone: '(415) 555-0123',
|
|
35
|
+
website: 'https://tonyspizza.example.com',
|
|
36
|
+
image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
|
|
37
|
+
specialties: ['Margherita', 'Pepperoni', 'White Pizza'],
|
|
38
|
+
openNow: true,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'bella-napoli',
|
|
42
|
+
name: 'Bella Napoli',
|
|
43
|
+
description: "Traditional Neapolitan pizza baked in a wood-fired oven",
|
|
44
|
+
address: "456 Market St, San Francisco, CA 94103",
|
|
45
|
+
coords: [-122.4089, 37.7858],
|
|
46
|
+
rating: 4.8,
|
|
47
|
+
reviews: 521,
|
|
48
|
+
priceLevel: 3,
|
|
49
|
+
cuisine: ['Italian', 'Pizza', 'Neapolitan'],
|
|
50
|
+
hours: { open: '12:00 PM', close: '11:00 PM' },
|
|
51
|
+
phone: '(415) 555-0456',
|
|
52
|
+
website: 'https://bellanapoli.example.com',
|
|
53
|
+
image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
|
|
54
|
+
specialties: ['Marinara', 'Quattro Formaggi', 'Diavola'],
|
|
55
|
+
openNow: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'slice-house',
|
|
59
|
+
name: 'The Slice House',
|
|
60
|
+
description: "Casual spot for creative pizza slices and craft beer",
|
|
61
|
+
address: "789 Valencia St, San Francisco, CA 94110",
|
|
62
|
+
coords: [-122.4216, 37.7599],
|
|
63
|
+
rating: 4.3,
|
|
64
|
+
reviews: 289,
|
|
65
|
+
priceLevel: 1,
|
|
66
|
+
cuisine: ['Pizza', 'American', 'Casual'],
|
|
67
|
+
hours: { open: '11:30 AM', close: '9:00 PM' },
|
|
68
|
+
phone: '(415) 555-0789',
|
|
69
|
+
image: 'https://images.unsplash.com/photo-1565299624946-b28f40a0ae38',
|
|
70
|
+
specialties: ['BBQ Chicken', 'Hawaiian', 'Veggie Supreme'],
|
|
71
|
+
openNow: true,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'pizzeria-delfina',
|
|
75
|
+
name: 'Pizzeria Delfina',
|
|
76
|
+
description: "Upscale pizzeria with seasonal ingredients and house-made mozzarella",
|
|
77
|
+
address: "3611 18th St, San Francisco, CA 94110",
|
|
78
|
+
coords: [-122.4252, 37.7615],
|
|
79
|
+
rating: 4.6,
|
|
80
|
+
reviews: 678,
|
|
81
|
+
priceLevel: 3,
|
|
82
|
+
cuisine: ['Italian', 'Pizza', 'Fine Dining'],
|
|
83
|
+
hours: { open: '5:00 PM', close: '10:00 PM' },
|
|
84
|
+
phone: '(415) 555-3611',
|
|
85
|
+
website: 'https://pizzeriadelfina.example.com',
|
|
86
|
+
image: 'https://images.unsplash.com/photo-1571997478779-2adcbbe9ab2f',
|
|
87
|
+
specialties: ['Salsiccia', 'Funghi', 'Prosciutto e Rucola'],
|
|
88
|
+
openNow: false,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'golden-boy',
|
|
92
|
+
name: 'Golden Boy Pizza',
|
|
93
|
+
description: "North Beach institution serving thick Sicilian-style squares",
|
|
94
|
+
address: "542 Green St, San Francisco, CA 94133",
|
|
95
|
+
coords: [-122.4102, 37.7999],
|
|
96
|
+
rating: 4.4,
|
|
97
|
+
reviews: 445,
|
|
98
|
+
priceLevel: 1,
|
|
99
|
+
cuisine: ['Pizza', 'Sicilian', 'Italian'],
|
|
100
|
+
hours: { open: '11:30 AM', close: '11:30 PM' },
|
|
101
|
+
phone: '(415) 555-0542',
|
|
102
|
+
image: 'https://images.unsplash.com/photo-1628840042765-356cda07504e',
|
|
103
|
+
specialties: ['Clam & Garlic', 'Pesto', 'Classic Cheese'],
|
|
104
|
+
openNow: true,
|
|
105
|
+
},
|
|
106
|
+
];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Module } from 'nitrostack';
|
|
2
|
+
import { PizzazService } from './pizzaz.service.js';
|
|
3
|
+
import { PizzazTools } from './pizzaz.tools.js';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
name: 'pizzaz',
|
|
7
|
+
description: 'Pizza shop finder module',
|
|
8
|
+
controllers: [PizzazTools],
|
|
9
|
+
providers: [PizzazService],
|
|
10
|
+
})
|
|
11
|
+
export class PizzazModule { }
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Injectable } from 'nitrostack';
|
|
2
|
+
import { PIZZA_SHOPS, type PizzaShop } from './pizzaz.data.js';
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class PizzazService {
|
|
6
|
+
/**
|
|
7
|
+
* Get all pizza shops
|
|
8
|
+
*/
|
|
9
|
+
getAllShops(): PizzaShop[] {
|
|
10
|
+
return PIZZA_SHOPS;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get a specific pizza shop by ID
|
|
15
|
+
*/
|
|
16
|
+
getShopById(id: string): PizzaShop | undefined {
|
|
17
|
+
return PIZZA_SHOPS.find(shop => shop.id === id);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get pizza shops filtered by criteria
|
|
22
|
+
*/
|
|
23
|
+
getShopsFiltered(filters: {
|
|
24
|
+
openNow?: boolean;
|
|
25
|
+
minRating?: number;
|
|
26
|
+
maxPrice?: number;
|
|
27
|
+
cuisine?: string;
|
|
28
|
+
}): PizzaShop[] {
|
|
29
|
+
let shops = [...PIZZA_SHOPS];
|
|
30
|
+
|
|
31
|
+
if (filters.openNow) {
|
|
32
|
+
shops = shops.filter(shop => shop.openNow);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (filters.minRating !== undefined) {
|
|
36
|
+
shops = shops.filter(shop => shop.rating >= filters.minRating!);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (filters.maxPrice !== undefined) {
|
|
40
|
+
shops = shops.filter(shop => shop.priceLevel <= filters.maxPrice!);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (filters.cuisine) {
|
|
44
|
+
shops = shops.filter(shop =>
|
|
45
|
+
shop.cuisine.some(c => c.toLowerCase().includes(filters.cuisine!.toLowerCase()))
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return shops;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get shops sorted by rating
|
|
54
|
+
*/
|
|
55
|
+
getTopRatedShops(limit: number = 5): PizzaShop[] {
|
|
56
|
+
return [...PIZZA_SHOPS]
|
|
57
|
+
.sort((a, b) => b.rating - a.rating)
|
|
58
|
+
.slice(0, limit);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ToolDecorator as Tool, Widget, ExecutionContext, Injectable, z } from 'nitrostack';
|
|
2
|
+
import { PizzazService } from './pizzaz.service.js';
|
|
3
|
+
|
|
4
|
+
const ShowMapSchema = z.object({
|
|
5
|
+
filter: z.enum(['open_now', 'top_rated', 'all']).optional().describe('Filter to apply'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const ShowListSchema = z.object({
|
|
9
|
+
openNow: z.boolean().optional().describe('Show only shops that are currently open'),
|
|
10
|
+
minRating: z.number().min(1).max(5).optional().describe('Minimum rating (1-5)'),
|
|
11
|
+
maxPrice: z.number().min(1).max(3).optional().describe('Maximum price level (1-3)'),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const ShowShopSchema = z.object({
|
|
15
|
+
shopId: z.string().describe('ID of the pizza shop to display'),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
@Injectable()
|
|
19
|
+
export class PizzazTools {
|
|
20
|
+
constructor(private readonly pizzazService: PizzazService) { }
|
|
21
|
+
|
|
22
|
+
@Tool({
|
|
23
|
+
name: 'show_pizza_map',
|
|
24
|
+
description: 'Display an interactive map of pizza shops in San Francisco',
|
|
25
|
+
inputSchema: ShowMapSchema,
|
|
26
|
+
examples: {
|
|
27
|
+
request: { filter: 'all' },
|
|
28
|
+
response: {
|
|
29
|
+
shops: [
|
|
30
|
+
{
|
|
31
|
+
id: 'tonys-pizza',
|
|
32
|
+
name: "Tony's New York Pizza",
|
|
33
|
+
description: "Authentic New York-style pizza with a crispy thin crust",
|
|
34
|
+
address: "123 Main St, San Francisco, CA 94102",
|
|
35
|
+
coords: [-122.4194, 37.7749],
|
|
36
|
+
rating: 4.5,
|
|
37
|
+
reviews: 342,
|
|
38
|
+
priceLevel: 2,
|
|
39
|
+
cuisine: ['Italian', 'Pizza'],
|
|
40
|
+
hours: { open: '11:00 AM', close: '10:00 PM' },
|
|
41
|
+
phone: '(415) 555-0123',
|
|
42
|
+
website: 'https://tonyspizza.example.com',
|
|
43
|
+
image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
|
|
44
|
+
specialties: ['Margherita', 'Pepperoni'],
|
|
45
|
+
openNow: true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'bella-napoli',
|
|
49
|
+
name: 'Bella Napoli',
|
|
50
|
+
description: "Traditional Neapolitan pizza baked in a wood-fired oven",
|
|
51
|
+
address: "456 Market St, San Francisco, CA 94103",
|
|
52
|
+
coords: [-122.4089, 37.7858],
|
|
53
|
+
rating: 4.8,
|
|
54
|
+
reviews: 521,
|
|
55
|
+
priceLevel: 3,
|
|
56
|
+
cuisine: ['Italian', 'Pizza'],
|
|
57
|
+
hours: { open: '12:00 PM', close: '11:00 PM' },
|
|
58
|
+
phone: '(415) 555-0456',
|
|
59
|
+
image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
|
|
60
|
+
specialties: ['Marinara', 'Quattro Formaggi'],
|
|
61
|
+
openNow: true
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
filter: 'all',
|
|
65
|
+
totalShops: 2
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
@Widget('pizza-map')
|
|
70
|
+
async showPizzaMap(args: z.infer<typeof ShowMapSchema>, ctx: ExecutionContext) {
|
|
71
|
+
let shops;
|
|
72
|
+
|
|
73
|
+
switch (args.filter) {
|
|
74
|
+
case 'open_now':
|
|
75
|
+
shops = this.pizzazService.getShopsFiltered({ openNow: true });
|
|
76
|
+
break;
|
|
77
|
+
case 'top_rated':
|
|
78
|
+
shops = this.pizzazService.getTopRatedShops();
|
|
79
|
+
break;
|
|
80
|
+
default:
|
|
81
|
+
shops = this.pizzazService.getAllShops();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
ctx.logger.info('Showing pizza map', { filter: args.filter, totalShops: shops.length });
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
shops,
|
|
88
|
+
filter: args.filter || 'all',
|
|
89
|
+
totalShops: shops.length,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@Tool({
|
|
94
|
+
name: 'show_pizza_list',
|
|
95
|
+
description: 'Display a list of pizza shops with filtering and sorting options',
|
|
96
|
+
inputSchema: ShowListSchema,
|
|
97
|
+
examples: {
|
|
98
|
+
request: { openNow: true },
|
|
99
|
+
response: {
|
|
100
|
+
shops: [
|
|
101
|
+
{
|
|
102
|
+
id: 'tonys-pizza',
|
|
103
|
+
name: "Tony's New York Pizza",
|
|
104
|
+
description: "Authentic New York-style pizza with a crispy thin crust",
|
|
105
|
+
address: "123 Main St, San Francisco, CA 94102",
|
|
106
|
+
coords: [-122.4194, 37.7749],
|
|
107
|
+
rating: 4.5,
|
|
108
|
+
reviews: 342,
|
|
109
|
+
priceLevel: 2,
|
|
110
|
+
cuisine: ['Italian', 'Pizza'],
|
|
111
|
+
hours: { open: '11:00 AM', close: '10:00 PM' },
|
|
112
|
+
phone: '(415) 555-0123',
|
|
113
|
+
website: 'https://tonyspizza.example.com',
|
|
114
|
+
image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
|
|
115
|
+
specialties: ['Margherita', 'Pepperoni'],
|
|
116
|
+
openNow: true
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
filters: { openNow: true },
|
|
120
|
+
totalShops: 1
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
@Widget('pizza-list')
|
|
125
|
+
async showPizzaList(args: z.infer<typeof ShowListSchema>, ctx: ExecutionContext) {
|
|
126
|
+
const shops = this.pizzazService.getShopsFiltered(args);
|
|
127
|
+
|
|
128
|
+
ctx.logger.info('Showing pizza list', { filters: args, totalShops: shops.length });
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
shops,
|
|
132
|
+
filters: args,
|
|
133
|
+
totalShops: shops.length,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@Tool({
|
|
138
|
+
name: 'show_pizza_shop',
|
|
139
|
+
description: 'Display detailed information about a specific pizza shop',
|
|
140
|
+
inputSchema: ShowShopSchema,
|
|
141
|
+
examples: {
|
|
142
|
+
request: { shopId: 'tonys-pizza' },
|
|
143
|
+
response: {
|
|
144
|
+
shop: {
|
|
145
|
+
id: 'tonys-pizza',
|
|
146
|
+
name: "Tony's New York Pizza",
|
|
147
|
+
description: "Authentic New York-style pizza with a crispy thin crust and fresh toppings",
|
|
148
|
+
address: "123 Main St, San Francisco, CA 94102",
|
|
149
|
+
coords: [-122.4194, 37.7749],
|
|
150
|
+
rating: 4.5,
|
|
151
|
+
reviews: 342,
|
|
152
|
+
priceLevel: 2,
|
|
153
|
+
cuisine: ['Italian', 'Pizza', 'New York Style'],
|
|
154
|
+
hours: { open: '11:00 AM', close: '10:00 PM' },
|
|
155
|
+
phone: '(415) 555-0123',
|
|
156
|
+
website: 'https://tonyspizza.example.com',
|
|
157
|
+
image: 'https://images.unsplash.com/photo-1513104890138-7c749659a591',
|
|
158
|
+
specialties: ['Margherita', 'Pepperoni', 'White Pizza'],
|
|
159
|
+
openNow: true
|
|
160
|
+
},
|
|
161
|
+
relatedShops: [
|
|
162
|
+
{
|
|
163
|
+
id: 'bella-napoli',
|
|
164
|
+
name: 'Bella Napoli',
|
|
165
|
+
description: "Traditional Neapolitan pizza baked in a wood-fired oven",
|
|
166
|
+
address: "456 Market St, San Francisco, CA 94103",
|
|
167
|
+
coords: [-122.4089, 37.7858],
|
|
168
|
+
rating: 4.8,
|
|
169
|
+
reviews: 521,
|
|
170
|
+
priceLevel: 3,
|
|
171
|
+
cuisine: ['Italian', 'Pizza'],
|
|
172
|
+
hours: { open: '12:00 PM', close: '11:00 PM' },
|
|
173
|
+
phone: '(415) 555-0456',
|
|
174
|
+
image: 'https://images.unsplash.com/photo-1574071318508-1cdbab80d002',
|
|
175
|
+
specialties: ['Marinara', 'Quattro Formaggi'],
|
|
176
|
+
openNow: true
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
@Widget('pizza-shop')
|
|
183
|
+
async showPizzaShop(args: z.infer<typeof ShowShopSchema>, ctx: ExecutionContext) {
|
|
184
|
+
const shop = this.pizzazService.getShopById(args.shopId);
|
|
185
|
+
|
|
186
|
+
if (!shop) {
|
|
187
|
+
throw new Error(`Pizza shop not found: ${args.shopId}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ctx.logger.info('Showing pizza shop', { shopId: args.shopId, shopName: shop.name });
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
shop,
|
|
194
|
+
relatedShops: this.pizzazService.getTopRatedShops(3).filter(s => s.id !== shop.id),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|