@noodleseed/agent-kit 0.14.0 → 0.15.0

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.
Files changed (114) hide show
  1. package/manifest.json +545 -5
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/examples/acme-bistro/README.md +51 -0
  5. package/skills/claude-code/examples/acme-bistro/design/UX-Document.md +435 -0
  6. package/skills/claude-code/examples/acme-bistro/design/api-contract.md +161 -0
  7. package/skills/claude-code/examples/acme-bistro/design/wireframe.html +573 -0
  8. package/skills/claude-code/examples/acme-bistro/noodle.json +5 -0
  9. package/skills/claude-code/examples/acme-bistro/package.json +20 -0
  10. package/skills/claude-code/examples/acme-bistro/src/helpers.ts +7 -0
  11. package/skills/claude-code/examples/acme-bistro/src/server.ts +149 -0
  12. package/skills/claude-code/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  13. package/skills/claude-code/examples/acme-bistro/src/views/widget-style.css +228 -0
  14. package/skills/claude-code/examples/acme-bistro/test/server.test.ts +21 -0
  15. package/skills/claude-code/examples/acme-bistro/vitest.config.ts +7 -0
  16. package/skills/claude-code/examples/acme-discovery/README.md +85 -0
  17. package/skills/claude-code/examples/acme-discovery/design/UX-Document.md +441 -0
  18. package/skills/claude-code/examples/acme-discovery/design/wireframe.html +670 -0
  19. package/skills/claude-code/examples/acme-discovery/noodle.json +5 -0
  20. package/skills/claude-code/examples/acme-discovery/package.json +20 -0
  21. package/skills/claude-code/examples/acme-discovery/src/helpers.ts +7 -0
  22. package/skills/claude-code/examples/acme-discovery/src/server.ts +202 -0
  23. package/skills/claude-code/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  24. package/skills/claude-code/examples/acme-discovery/src/views/widget-style.css +207 -0
  25. package/skills/claude-code/examples/acme-discovery/test/server.test.ts +24 -0
  26. package/skills/claude-code/examples/acme-discovery/vitest.config.ts +7 -0
  27. package/skills/claude-code/examples/acme-tasks/README.md +80 -0
  28. package/skills/claude-code/examples/acme-tasks/design/UX-Document.md +277 -0
  29. package/skills/claude-code/examples/acme-tasks/design/wireframe.html +603 -0
  30. package/skills/claude-code/examples/acme-tasks/noodle.json +5 -0
  31. package/skills/claude-code/examples/acme-tasks/package.json +20 -0
  32. package/skills/claude-code/examples/acme-tasks/src/helpers.ts +6 -0
  33. package/skills/claude-code/examples/acme-tasks/src/server.ts +141 -0
  34. package/skills/claude-code/examples/acme-tasks/src/views/task-list.tsx +177 -0
  35. package/skills/claude-code/examples/acme-tasks/src/views/widget-style.css +227 -0
  36. package/skills/claude-code/examples/acme-tasks/test/server.test.ts +22 -0
  37. package/skills/claude-code/examples/acme-tasks/vitest.config.ts +7 -0
  38. package/skills/claude-code/examples/food-ordering/README.md +82 -0
  39. package/skills/claude-code/examples/food-ordering/noodle.json +5 -0
  40. package/skills/claude-code/examples/food-ordering/package.json +22 -0
  41. package/skills/claude-code/examples/food-ordering/src/helpers.ts +34 -0
  42. package/skills/claude-code/examples/food-ordering/src/server.ts +412 -0
  43. package/skills/claude-code/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  44. package/skills/claude-code/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  45. package/skills/claude-code/examples/food-ordering/src/views/widget-style.css +682 -0
  46. package/skills/claude-code/examples/food-ordering/test/server.test.ts +58 -0
  47. package/skills/claude-code/examples/food-ordering/vitest.config.ts +30 -0
  48. package/skills/claude-code/examples/hello/README.md +13 -0
  49. package/skills/claude-code/examples/hello/noodle.json +5 -0
  50. package/skills/claude-code/examples/hello/package.json +16 -0
  51. package/skills/claude-code/examples/hello/src/server.ts +29 -0
  52. package/skills/claude-code/examples/hello/test/server.test.ts +8 -0
  53. package/skills/claude-code/examples/weather/README.md +54 -0
  54. package/skills/claude-code/examples/weather/noodle.json +4 -0
  55. package/skills/claude-code/examples/weather/package.json +16 -0
  56. package/skills/claude-code/examples/weather/src/server.ts +190 -0
  57. package/skills/claude-code/examples/weather/test/server.test.ts +8 -0
  58. package/skills/claude-code/references/examples.md +16 -7
  59. package/skills/codex/SKILL.md +1 -1
  60. package/skills/codex/examples/acme-bistro/README.md +51 -0
  61. package/skills/codex/examples/acme-bistro/design/UX-Document.md +435 -0
  62. package/skills/codex/examples/acme-bistro/design/api-contract.md +161 -0
  63. package/skills/codex/examples/acme-bistro/design/wireframe.html +573 -0
  64. package/skills/codex/examples/acme-bistro/noodle.json +5 -0
  65. package/skills/codex/examples/acme-bistro/package.json +20 -0
  66. package/skills/codex/examples/acme-bistro/src/helpers.ts +7 -0
  67. package/skills/codex/examples/acme-bistro/src/server.ts +149 -0
  68. package/skills/codex/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  69. package/skills/codex/examples/acme-bistro/src/views/widget-style.css +228 -0
  70. package/skills/codex/examples/acme-bistro/test/server.test.ts +21 -0
  71. package/skills/codex/examples/acme-bistro/vitest.config.ts +7 -0
  72. package/skills/codex/examples/acme-discovery/README.md +85 -0
  73. package/skills/codex/examples/acme-discovery/design/UX-Document.md +441 -0
  74. package/skills/codex/examples/acme-discovery/design/wireframe.html +670 -0
  75. package/skills/codex/examples/acme-discovery/noodle.json +5 -0
  76. package/skills/codex/examples/acme-discovery/package.json +20 -0
  77. package/skills/codex/examples/acme-discovery/src/helpers.ts +7 -0
  78. package/skills/codex/examples/acme-discovery/src/server.ts +202 -0
  79. package/skills/codex/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  80. package/skills/codex/examples/acme-discovery/src/views/widget-style.css +207 -0
  81. package/skills/codex/examples/acme-discovery/test/server.test.ts +24 -0
  82. package/skills/codex/examples/acme-discovery/vitest.config.ts +7 -0
  83. package/skills/codex/examples/acme-tasks/README.md +80 -0
  84. package/skills/codex/examples/acme-tasks/design/UX-Document.md +277 -0
  85. package/skills/codex/examples/acme-tasks/design/wireframe.html +603 -0
  86. package/skills/codex/examples/acme-tasks/noodle.json +5 -0
  87. package/skills/codex/examples/acme-tasks/package.json +20 -0
  88. package/skills/codex/examples/acme-tasks/src/helpers.ts +6 -0
  89. package/skills/codex/examples/acme-tasks/src/server.ts +141 -0
  90. package/skills/codex/examples/acme-tasks/src/views/task-list.tsx +177 -0
  91. package/skills/codex/examples/acme-tasks/src/views/widget-style.css +227 -0
  92. package/skills/codex/examples/acme-tasks/test/server.test.ts +22 -0
  93. package/skills/codex/examples/acme-tasks/vitest.config.ts +7 -0
  94. package/skills/codex/examples/food-ordering/README.md +82 -0
  95. package/skills/codex/examples/food-ordering/noodle.json +5 -0
  96. package/skills/codex/examples/food-ordering/package.json +22 -0
  97. package/skills/codex/examples/food-ordering/src/helpers.ts +34 -0
  98. package/skills/codex/examples/food-ordering/src/server.ts +412 -0
  99. package/skills/codex/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  100. package/skills/codex/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  101. package/skills/codex/examples/food-ordering/src/views/widget-style.css +682 -0
  102. package/skills/codex/examples/food-ordering/test/server.test.ts +58 -0
  103. package/skills/codex/examples/food-ordering/vitest.config.ts +30 -0
  104. package/skills/codex/examples/hello/README.md +13 -0
  105. package/skills/codex/examples/hello/noodle.json +5 -0
  106. package/skills/codex/examples/hello/package.json +16 -0
  107. package/skills/codex/examples/hello/src/server.ts +29 -0
  108. package/skills/codex/examples/hello/test/server.test.ts +8 -0
  109. package/skills/codex/examples/weather/README.md +54 -0
  110. package/skills/codex/examples/weather/noodle.json +4 -0
  111. package/skills/codex/examples/weather/package.json +16 -0
  112. package/skills/codex/examples/weather/src/server.ts +190 -0
  113. package/skills/codex/examples/weather/test/server.test.ts +8 -0
  114. package/skills/codex/references/examples.md +16 -7
@@ -0,0 +1,682 @@
1
+ :root {
2
+ color-scheme: light dark;
3
+ font-family:
4
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
5
+ --nw-bg: #ffffff;
6
+ --nw-surface: #f7f7f5;
7
+ --nw-surface-strong: #ffffff;
8
+ --nw-text: #1f2328;
9
+ --nw-muted: #677079;
10
+ --nw-border: #d9dee3;
11
+ --nw-accent: #0f8f5f;
12
+ --nw-accent-strong: #047857;
13
+ --nw-accent-soft: #e8f7ef;
14
+ --nw-info: #1d6feb;
15
+ --nw-info-soft: #eaf2ff;
16
+ --nw-warn: #b7791f;
17
+ --nw-danger: #c2410c;
18
+ --nw-shadow: 0 18px 50px rgb(15 23 42 / 12%);
19
+ --nw-radius: 8px;
20
+ }
21
+
22
+ .dark,
23
+ [data-theme="dark"] {
24
+ --nw-bg: #111820;
25
+ --nw-surface: #16212a;
26
+ --nw-surface-strong: #101820;
27
+ --nw-text: #f4f7f8;
28
+ --nw-muted: #a4b0ba;
29
+ --nw-border: #33414c;
30
+ --nw-accent: #25c385;
31
+ --nw-accent-strong: #19a974;
32
+ --nw-accent-soft: #123a2b;
33
+ --nw-info: #4c9aff;
34
+ --nw-info-soft: #132b4d;
35
+ --nw-warn: #f0b35b;
36
+ --nw-danger: #fb7b54;
37
+ --nw-shadow: 0 18px 50px rgb(0 0 0 / 28%);
38
+ }
39
+
40
+ * {
41
+ box-sizing: border-box;
42
+ }
43
+
44
+ body {
45
+ margin: 0;
46
+ background: var(--nw-bg);
47
+ color: var(--nw-text);
48
+ }
49
+
50
+ button,
51
+ input,
52
+ select {
53
+ font: inherit;
54
+ }
55
+
56
+ .nw-shell {
57
+ min-height: 100vh;
58
+ padding: 14px;
59
+ background: var(--nw-bg);
60
+ color: var(--nw-text);
61
+ }
62
+
63
+ .nw-card {
64
+ width: min(100%, 560px);
65
+ margin: 0 auto;
66
+ border: 1px solid var(--nw-border);
67
+ border-radius: var(--nw-radius);
68
+ background: var(--nw-surface-strong);
69
+ box-shadow: var(--nw-shadow);
70
+ overflow: hidden;
71
+ }
72
+
73
+ .nw-card-wide {
74
+ width: min(100%, 720px);
75
+ }
76
+
77
+ .nsr-card {
78
+ width: min(100%, 560px);
79
+ margin: 0 auto;
80
+ border: 1px solid var(--nw-border);
81
+ border-radius: var(--nw-radius);
82
+ background: var(--nw-surface-strong);
83
+ box-shadow: var(--nw-shadow);
84
+ overflow: hidden;
85
+ }
86
+
87
+ .nsr-card-wide {
88
+ width: min(100%, 720px);
89
+ }
90
+
91
+ .nw-header {
92
+ display: flex;
93
+ align-items: center;
94
+ gap: 10px;
95
+ padding: 14px;
96
+ border-bottom: 1px solid var(--nw-border);
97
+ }
98
+
99
+ .nsr-header {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 10px;
103
+ padding: 14px;
104
+ border-bottom: 1px solid var(--nw-border);
105
+ }
106
+
107
+ .nw-icon {
108
+ display: inline-grid;
109
+ width: 32px;
110
+ height: 32px;
111
+ flex: 0 0 auto;
112
+ place-items: center;
113
+ border-radius: 8px;
114
+ background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));
115
+ color: white;
116
+ }
117
+
118
+ .nsr-icon {
119
+ display: inline-grid;
120
+ width: 32px;
121
+ height: 32px;
122
+ flex: 0 0 auto;
123
+ place-items: center;
124
+ border-radius: 8px;
125
+ background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));
126
+ color: white;
127
+ }
128
+
129
+ .nw-icon svg,
130
+ .nsr-icon svg,
131
+ .nw-button svg,
132
+ .nw-meta svg {
133
+ width: 16px;
134
+ height: 16px;
135
+ stroke: currentColor;
136
+ stroke-width: 2;
137
+ fill: none;
138
+ stroke-linecap: round;
139
+ stroke-linejoin: round;
140
+ }
141
+
142
+ .nw-title-block {
143
+ min-width: 0;
144
+ flex: 1;
145
+ }
146
+
147
+ .nsr-title-block {
148
+ min-width: 0;
149
+ flex: 1;
150
+ }
151
+
152
+ .nw-title {
153
+ margin: 0;
154
+ font-size: 16px;
155
+ line-height: 1.2;
156
+ font-weight: 700;
157
+ letter-spacing: 0;
158
+ }
159
+
160
+ .nsr-title {
161
+ margin: 0;
162
+ font-size: 16px;
163
+ line-height: 1.2;
164
+ font-weight: 700;
165
+ letter-spacing: 0;
166
+ }
167
+
168
+ .nw-subtitle {
169
+ margin: 4px 0 0;
170
+ color: var(--nw-muted);
171
+ font-size: 12px;
172
+ line-height: 1.35;
173
+ }
174
+
175
+ .nsr-subtitle {
176
+ margin: 4px 0 0;
177
+ color: var(--nw-muted);
178
+ font-size: 12px;
179
+ line-height: 1.35;
180
+ }
181
+
182
+ .nw-chip {
183
+ display: inline-flex;
184
+ align-items: center;
185
+ gap: 6px;
186
+ min-height: 24px;
187
+ padding: 3px 9px;
188
+ border: 1px solid var(--nw-border);
189
+ border-radius: 999px;
190
+ background: var(--nw-surface);
191
+ color: var(--nw-text);
192
+ font-size: 12px;
193
+ font-weight: 600;
194
+ white-space: nowrap;
195
+ }
196
+
197
+ .nsr-chip {
198
+ display: inline-flex;
199
+ align-items: center;
200
+ gap: 6px;
201
+ min-height: 24px;
202
+ padding: 3px 9px;
203
+ border: 1px solid var(--nw-border);
204
+ border-radius: 999px;
205
+ background: var(--nw-surface);
206
+ color: var(--nw-text);
207
+ font-size: 12px;
208
+ font-weight: 600;
209
+ white-space: nowrap;
210
+ }
211
+
212
+ .nw-chip::before {
213
+ width: 7px;
214
+ height: 7px;
215
+ border-radius: 99px;
216
+ background: var(--nw-accent);
217
+ content: "";
218
+ }
219
+
220
+ .nsr-chip::before {
221
+ width: 7px;
222
+ height: 7px;
223
+ border-radius: 99px;
224
+ background: var(--nw-accent);
225
+ content: "";
226
+ }
227
+
228
+ .nw-tabs {
229
+ display: grid;
230
+ grid-template-columns: repeat(5, minmax(0, 1fr));
231
+ gap: 1px;
232
+ border-bottom: 1px solid var(--nw-border);
233
+ background: var(--nw-border);
234
+ }
235
+
236
+ .nsr-tabs {
237
+ display: grid;
238
+ grid-template-columns: repeat(5, minmax(0, 1fr));
239
+ gap: 1px;
240
+ border-bottom: 1px solid var(--nw-border);
241
+ background: var(--nw-border);
242
+ }
243
+
244
+ .nw-tab {
245
+ min-width: 0;
246
+ min-height: 34px;
247
+ border: 0;
248
+ background: var(--nw-surface-strong);
249
+ color: var(--nw-muted);
250
+ font-size: 12px;
251
+ font-weight: 700;
252
+ text-transform: capitalize;
253
+ cursor: pointer;
254
+ }
255
+
256
+ .nsr-tab {
257
+ min-width: 0;
258
+ min-height: 34px;
259
+ border: 0;
260
+ background: var(--nw-surface-strong);
261
+ color: var(--nw-muted);
262
+ font-size: 12px;
263
+ font-weight: 700;
264
+ text-transform: capitalize;
265
+ cursor: pointer;
266
+ }
267
+
268
+ .nw-tab[aria-current="step"] {
269
+ color: var(--nw-text);
270
+ background: var(--nw-accent-soft);
271
+ }
272
+
273
+ .nsr-tab[aria-current="step"] {
274
+ color: var(--nw-text);
275
+ background: var(--nw-accent-soft);
276
+ }
277
+
278
+ .nw-body {
279
+ display: grid;
280
+ gap: 14px;
281
+ padding: 14px;
282
+ }
283
+
284
+ .nw-grid {
285
+ display: grid;
286
+ grid-template-columns: minmax(0, 1fr) minmax(180px, 0.75fr);
287
+ gap: 14px;
288
+ }
289
+
290
+ .nw-section-title {
291
+ margin: 0 0 8px;
292
+ font-size: 12px;
293
+ font-weight: 700;
294
+ }
295
+
296
+ .nw-section-head {
297
+ display: grid;
298
+ gap: 2px;
299
+ }
300
+
301
+ .nw-section-detail {
302
+ margin: 0;
303
+ color: var(--nw-muted);
304
+ font-size: 12px;
305
+ }
306
+
307
+ .nw-menu-list,
308
+ .nw-summary-list,
309
+ .nw-feature-list {
310
+ display: grid;
311
+ gap: 8px;
312
+ margin: 0;
313
+ padding: 0;
314
+ list-style: none;
315
+ }
316
+
317
+ .nw-menu-item {
318
+ display: grid;
319
+ grid-template-columns: minmax(0, 1fr) auto;
320
+ gap: 10px;
321
+ width: 100%;
322
+ padding: 10px;
323
+ border: 1px solid var(--nw-border);
324
+ border-radius: var(--nw-radius);
325
+ background: var(--nw-bg);
326
+ color: var(--nw-text);
327
+ text-align: left;
328
+ cursor: pointer;
329
+ }
330
+
331
+ .nw-menu-item[aria-pressed="true"] {
332
+ border-color: var(--nw-accent);
333
+ background: var(--nw-accent-soft);
334
+ }
335
+
336
+ .nw-menu-name,
337
+ .nw-feature-name {
338
+ display: block;
339
+ font-size: 13px;
340
+ font-weight: 700;
341
+ }
342
+
343
+ .nw-menu-desc,
344
+ .nw-feature-desc {
345
+ display: block;
346
+ margin-top: 3px;
347
+ color: var(--nw-muted);
348
+ font-size: 12px;
349
+ line-height: 1.35;
350
+ }
351
+
352
+ .nw-price {
353
+ align-self: center;
354
+ color: var(--nw-text);
355
+ font-size: 13px;
356
+ font-weight: 700;
357
+ }
358
+
359
+ .nw-status {
360
+ align-self: center;
361
+ color: var(--nw-muted);
362
+ font-size: 12px;
363
+ font-weight: 800;
364
+ white-space: nowrap;
365
+ }
366
+
367
+ .nw-status-ok {
368
+ color: var(--nw-accent-strong);
369
+ }
370
+
371
+ .nw-field-grid {
372
+ display: grid;
373
+ grid-template-columns: 1fr 120px;
374
+ gap: 10px;
375
+ }
376
+
377
+ .nw-field {
378
+ display: grid;
379
+ gap: 5px;
380
+ color: var(--nw-muted);
381
+ font-size: 12px;
382
+ font-weight: 650;
383
+ }
384
+
385
+ .nsr-field-label {
386
+ color: var(--nw-muted);
387
+ }
388
+
389
+ .nsr-stepper {
390
+ display: grid;
391
+ grid-template-columns: 34px minmax(42px, 1fr) 34px;
392
+ width: 100%;
393
+ min-height: 34px;
394
+ border: 1px solid var(--nw-border);
395
+ border-radius: 7px;
396
+ overflow: hidden;
397
+ background: var(--nw-bg);
398
+ }
399
+
400
+ .nsr-stepper button {
401
+ border: 0;
402
+ background: var(--nw-surface);
403
+ color: var(--nw-text);
404
+ cursor: pointer;
405
+ }
406
+
407
+ .nsr-stepper button:disabled {
408
+ cursor: not-allowed;
409
+ opacity: 0.5;
410
+ }
411
+
412
+ .nsr-stepper-value {
413
+ display: grid;
414
+ place-items: center;
415
+ color: var(--nw-text);
416
+ font-size: 13px;
417
+ font-weight: 800;
418
+ }
419
+
420
+ .nw-input,
421
+ .nw-select {
422
+ min-width: 0;
423
+ width: 100%;
424
+ min-height: 34px;
425
+ padding: 7px 9px;
426
+ border: 1px solid var(--nw-border);
427
+ border-radius: 7px;
428
+ background: var(--nw-bg);
429
+ color: var(--nw-text);
430
+ outline: none;
431
+ }
432
+
433
+ .nw-input:focus,
434
+ .nw-select:focus,
435
+ .nw-button:focus-visible,
436
+ .nw-menu-item:focus-visible {
437
+ border-color: var(--nw-info);
438
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--nw-info) 24%, transparent);
439
+ }
440
+
441
+ .nw-modifier-grid {
442
+ display: grid;
443
+ grid-template-columns: repeat(3, minmax(0, 1fr));
444
+ gap: 8px;
445
+ }
446
+
447
+ .nw-option {
448
+ display: flex;
449
+ align-items: center;
450
+ gap: 8px;
451
+ padding: 9px;
452
+ border: 1px solid var(--nw-border);
453
+ border-radius: 7px;
454
+ background: var(--nw-bg);
455
+ color: var(--nw-text);
456
+ font-size: 12px;
457
+ font-weight: 650;
458
+ }
459
+
460
+ .nsr-choice {
461
+ display: flex;
462
+ align-items: center;
463
+ gap: 8px;
464
+ padding: 9px;
465
+ border: 1px solid var(--nw-border);
466
+ border-radius: 7px;
467
+ background: var(--nw-bg);
468
+ color: var(--nw-text);
469
+ font-size: 12px;
470
+ font-weight: 650;
471
+ }
472
+
473
+ .nw-summary {
474
+ display: grid;
475
+ gap: 8px;
476
+ padding: 10px;
477
+ border: 1px solid var(--nw-border);
478
+ border-radius: var(--nw-radius);
479
+ background: var(--nw-surface);
480
+ }
481
+
482
+ .nw-summary-compact {
483
+ align-self: end;
484
+ }
485
+
486
+ .nw-summary-row {
487
+ display: flex;
488
+ justify-content: space-between;
489
+ gap: 12px;
490
+ padding-bottom: 8px;
491
+ border-bottom: 1px solid color-mix(in srgb, var(--nw-border) 70%, transparent);
492
+ }
493
+
494
+ .nw-summary-row:last-child {
495
+ padding-bottom: 0;
496
+ border-bottom: 0;
497
+ }
498
+
499
+ .nw-summary-row dt {
500
+ color: var(--nw-muted);
501
+ font-size: 12px;
502
+ }
503
+
504
+ .nw-line-note {
505
+ display: block;
506
+ margin-top: 2px;
507
+ font-size: 11px;
508
+ font-weight: 500;
509
+ }
510
+
511
+ .nw-summary-row dd {
512
+ margin: 0;
513
+ text-align: right;
514
+ font-size: 13px;
515
+ font-weight: 700;
516
+ }
517
+
518
+ .nw-total dd {
519
+ font-size: 18px;
520
+ }
521
+
522
+ .nw-actions {
523
+ display: flex;
524
+ flex-wrap: wrap;
525
+ gap: 8px;
526
+ }
527
+
528
+ .nsr-actions {
529
+ display: flex;
530
+ flex-wrap: wrap;
531
+ gap: 8px;
532
+ }
533
+
534
+ .nw-button {
535
+ display: inline-flex;
536
+ align-items: center;
537
+ justify-content: center;
538
+ gap: 8px;
539
+ min-height: 36px;
540
+ padding: 8px 12px;
541
+ border: 1px solid var(--nw-border);
542
+ border-radius: 7px;
543
+ background: var(--nw-bg);
544
+ color: var(--nw-text);
545
+ font-size: 13px;
546
+ font-weight: 700;
547
+ cursor: pointer;
548
+ }
549
+
550
+ .nw-button-primary {
551
+ border-color: var(--nw-accent-strong);
552
+ background: linear-gradient(145deg, var(--nw-accent), var(--nw-accent-strong));
553
+ color: white;
554
+ }
555
+
556
+ .nw-button-info {
557
+ border-color: var(--nw-info);
558
+ background: var(--nw-info);
559
+ color: white;
560
+ }
561
+
562
+ .nw-button:disabled {
563
+ cursor: wait;
564
+ opacity: 0.65;
565
+ }
566
+
567
+ .nw-note {
568
+ margin: 0;
569
+ padding: 10px;
570
+ border: 1px solid var(--nw-border);
571
+ border-radius: var(--nw-radius);
572
+ background: var(--nw-surface);
573
+ color: var(--nw-muted);
574
+ font-size: 12px;
575
+ line-height: 1.45;
576
+ }
577
+
578
+ .nw-footer {
579
+ display: flex;
580
+ flex-wrap: wrap;
581
+ align-items: center;
582
+ justify-content: space-between;
583
+ gap: 8px;
584
+ padding: 10px 14px;
585
+ border-top: 1px solid var(--nw-border);
586
+ color: var(--nw-muted);
587
+ font-size: 12px;
588
+ }
589
+
590
+ .nsr-footer {
591
+ display: flex;
592
+ flex-wrap: wrap;
593
+ align-items: center;
594
+ justify-content: space-between;
595
+ gap: 8px;
596
+ padding: 10px 14px;
597
+ border-top: 1px solid var(--nw-border);
598
+ color: var(--nw-muted);
599
+ font-size: 12px;
600
+ }
601
+
602
+ .nw-meta {
603
+ display: inline-flex;
604
+ align-items: center;
605
+ gap: 6px;
606
+ }
607
+
608
+ .nw-feature {
609
+ display: grid;
610
+ grid-template-columns: 24px minmax(0, 1fr);
611
+ gap: 10px;
612
+ padding: 10px;
613
+ border: 1px solid var(--nw-border);
614
+ border-radius: var(--nw-radius);
615
+ background: var(--nw-bg);
616
+ }
617
+
618
+ .nw-check {
619
+ display: inline-grid;
620
+ width: 22px;
621
+ height: 22px;
622
+ place-items: center;
623
+ border-radius: 6px;
624
+ background: var(--nw-accent);
625
+ color: white;
626
+ font-size: 13px;
627
+ font-weight: 800;
628
+ }
629
+
630
+ .nw-check svg {
631
+ width: 14px;
632
+ height: 14px;
633
+ stroke: currentColor;
634
+ stroke-width: 3;
635
+ fill: none;
636
+ stroke-linecap: round;
637
+ stroke-linejoin: round;
638
+ }
639
+
640
+ @media (max-width: 560px) {
641
+ .nw-shell {
642
+ padding: 10px;
643
+ }
644
+
645
+ .nw-grid,
646
+ .nw-field-grid,
647
+ .nw-modifier-grid {
648
+ grid-template-columns: 1fr;
649
+ }
650
+
651
+ .nw-tabs {
652
+ grid-template-columns: repeat(3, minmax(0, 1fr));
653
+ }
654
+
655
+ .nsr-tabs {
656
+ grid-template-columns: repeat(3, minmax(0, 1fr));
657
+ }
658
+
659
+ .nw-header {
660
+ align-items: flex-start;
661
+ }
662
+
663
+ .nsr-header {
664
+ align-items: flex-start;
665
+ }
666
+
667
+ .nw-chip {
668
+ max-width: 120px;
669
+ overflow: hidden;
670
+ text-overflow: ellipsis;
671
+ }
672
+
673
+ .nsr-chip {
674
+ max-width: 120px;
675
+ overflow: hidden;
676
+ text-overflow: ellipsis;
677
+ }
678
+
679
+ .nw-button {
680
+ flex: 1 1 140px;
681
+ }
682
+ }
@@ -0,0 +1,58 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import app from '../src/server.js';
3
+
4
+ describe('food-ordering example', () => {
5
+ it('exports a Noodle server definition', () => {
6
+ expect(typeof app.toManifest).toBe('function');
7
+ });
8
+
9
+ it('emits a complete ordering app manifest with cart state and app-only helpers', async () => {
10
+ const manifest = (await app.toManifest()) as {
11
+ server: {
12
+ name: string;
13
+ };
14
+ handoff?: { allowedDomains?: string[] };
15
+ state?: { handles?: Record<string, { kind: string; scope: string }> };
16
+ connectors?: Record<string, { id: string; version: string }>;
17
+ tools: Array<{
18
+ name: string;
19
+ visibility?: string[];
20
+ output?: unknown;
21
+ }>;
22
+ widgets?: Array<{
23
+ name: string;
24
+ tool: string;
25
+ view?: { component?: string; entry?: string };
26
+ }>;
27
+ };
28
+
29
+ expect(manifest.server.name).toBe('food_ordering');
30
+ expect(manifest.state?.handles?.cart).toMatchObject({
31
+ kind: 'cart',
32
+ scope: 'caller',
33
+ });
34
+ expect(manifest.handoff?.allowedDomains).toEqual(['https://orders.example.com']);
35
+ expect(manifest.connectors?.state).toEqual({ id: 'noodle_state', version: '1.0.0' });
36
+
37
+ const tools = new Map(manifest.tools.map((tool) => [tool.name, tool]));
38
+ expect(manifest.widgets?.find((widget) => widget.tool === 'open_ordering')?.view).toMatchObject(
39
+ {
40
+ component: 'ordering-flow',
41
+ entry: './views/ordering-flow.tsx',
42
+ },
43
+ );
44
+ for (const helper of [
45
+ 'search_stores',
46
+ 'load_menu',
47
+ 'load_item',
48
+ 'read_cart',
49
+ 'sync_cart',
50
+ 'prepare_checkout',
51
+ ]) {
52
+ expect(tools.get(helper)?.visibility).toEqual(['app']);
53
+ }
54
+ expect(JSON.stringify(tools.get('open_ordering'))).toContain('featuredItems');
55
+ expect(JSON.stringify(tools.get('sync_cart'))).toContain('revision');
56
+ expect(manifest.widgets?.map((widget) => widget.name)).toContain('capabilities_card');
57
+ });
58
+ });