wizards 0.5.13 → 0.6.1

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 (69) hide show
  1. package/apps/runtime/dist/authoring/guide.js +63 -7
  2. package/apps/runtime/dist/credits/estimate.js +1 -1
  3. package/apps/runtime/dist/engine/requirements.js +1 -1
  4. package/apps/runtime/dist/engine/runner.js +53 -4
  5. package/apps/runtime/dist/engine/steps.js +155 -123
  6. package/apps/runtime/dist/render/downloads.js +16 -3
  7. package/apps/runtime/dist/render/shaped.js +137 -0
  8. package/apps/runtime/dist/routes/runs.js +58 -2
  9. package/apps/runtime/dist/services/brand.js +2 -1
  10. package/apps/runtime/dist/widgets/runtime.js +25 -2
  11. package/apps/runtime/dist/widgets/step.js +2 -0
  12. package/apps/web/dist/assets/AboutDialog-CTuI-l3p.js +1 -0
  13. package/apps/web/dist/assets/{ChangelogDialog-BCS3WIRA.js → ChangelogDialog-jQk_bQpP.js} +1 -1
  14. package/apps/web/dist/assets/ChatView-9TLi0B7K.js +10 -0
  15. package/apps/web/dist/assets/EditorPage-BVrzOfF3.js +3 -0
  16. package/apps/web/dist/assets/{FlowPreview-D2haAZwo.js → FlowPreview-DA0sHtr7.js} +1 -1
  17. package/apps/web/dist/assets/{Harness-CGI6ZMTA.js → Harness-DmYkwU4x.js} +2 -2
  18. package/apps/web/dist/assets/{NewWizardChannels-C4b_phHw.js → NewWizardChannels-BLS9sKhT.js} +1 -1
  19. package/apps/web/dist/assets/NewWizardPage-DWYZYiBF.js +7 -0
  20. package/apps/web/dist/assets/{OnboardingPage-DgySdBgo.js → OnboardingPage-CREvCCdX.js} +1 -1
  21. package/apps/web/dist/assets/ProjectPage-BQkd55xR.js +1 -0
  22. package/apps/web/dist/assets/PublicRunner-sOlOC0zD.js +1 -0
  23. package/apps/web/dist/assets/{ReadOnly-B-4l3bVt.js → ReadOnly-b7TjjRAk.js} +1 -1
  24. package/apps/web/dist/assets/RunDrawer-BPIVaan7.js +4 -0
  25. package/apps/web/dist/assets/{RunnerView-BZ83HUnO.js → RunnerView-CLfZzbKn.js} +1 -1
  26. package/apps/web/dist/assets/SettingsPage-BO6TPmoj.js +1 -0
  27. package/apps/web/dist/assets/SetupPage-DlJHBYWH.js +1 -0
  28. package/apps/web/dist/assets/SharePage-B21QI97K.js +1 -0
  29. package/apps/web/dist/assets/changelog-DeSoCsai.js +1 -0
  30. package/apps/web/dist/assets/{esm-BqbWrbsa.js → esm-DqRvG-PU.js} +1 -1
  31. package/apps/web/dist/assets/index-BhVJwBz7.css +1 -0
  32. package/apps/web/dist/assets/index-CAUeJXCg.js +14 -0
  33. package/apps/web/dist/assets/{lock-BkN0Fai6.js → lock-D_KjsGfU.js} +1 -1
  34. package/apps/web/dist/assets/{phone-Dip_wSUZ.js → phone-YRxkPQk6.js} +1 -1
  35. package/apps/web/dist/assets/{settings-menu-B7eXkvba.js → settings-menu-CQgehwEX.js} +1 -1
  36. package/apps/web/dist/assets/ui-DDUCc_4v.js +137 -0
  37. package/apps/web/dist/assets/{upload-DPQ4pwnl.js → upload-DDo14e2p.js} +1 -1
  38. package/apps/web/dist/index.html +3 -3
  39. package/apps/web/dist/mcp/flow.html +58 -55
  40. package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +5 -2
  41. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +187 -3
  42. package/node_modules/@engenty-wizards/shared/dist/definition.js +89 -18
  43. package/node_modules/@engenty-wizards/shared/dist/json-schema.js +4 -0
  44. package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +11 -0
  45. package/node_modules/@engenty-wizards/shared/dist/projects.js +54 -0
  46. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +22 -0
  47. package/node_modules/@engenty-wizards/shared/dist/run.js +3 -0
  48. package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +41 -1
  49. package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +40 -0
  50. package/node_modules/@engenty-wizards/shared/dist/runners.js +1 -1
  51. package/node_modules/@engenty-wizards/shared/dist/shape.d.ts +102 -0
  52. package/node_modules/@engenty-wizards/shared/dist/shape.js +318 -0
  53. package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +33 -7
  54. package/node_modules/@engenty-wizards/shared/dist/surface.js +263 -20
  55. package/package.json +1 -1
  56. package/apps/web/dist/assets/AboutDialog-CkE7uZNL.js +0 -1
  57. package/apps/web/dist/assets/ChatView-DClGzMte.js +0 -10
  58. package/apps/web/dist/assets/EditorPage-Dg27sIZ7.js +0 -3
  59. package/apps/web/dist/assets/NewWizardPage-DhDXrjKX.js +0 -7
  60. package/apps/web/dist/assets/ProjectPage-dvtJn_3c.js +0 -1
  61. package/apps/web/dist/assets/PublicRunner-lP4sVF1q.js +0 -1
  62. package/apps/web/dist/assets/RunDrawer-B2bsB9Z6.js +0 -4
  63. package/apps/web/dist/assets/SettingsPage-C0_wAa_j.js +0 -1
  64. package/apps/web/dist/assets/SetupPage-kuvBk0G0.js +0 -1
  65. package/apps/web/dist/assets/SharePage-COLVxXMI.js +0 -1
  66. package/apps/web/dist/assets/changelog-CIYdRaa5.js +0 -1
  67. package/apps/web/dist/assets/index-Da9Pvzpj.js +0 -14
  68. package/apps/web/dist/assets/index-DaKjB676.css +0 -1
  69. package/apps/web/dist/assets/ui-B9AOCT0v.js +0 -134
@@ -793,10 +793,13 @@ export interface PluginRunner {
793
793
  token: string;
794
794
  }): PluginRunnerAddress | null | Promise<PluginRunnerAddress | null>;
795
795
  }
796
- /** How a run answers a review: accept it, with edited texts where the review allows, or ask for one of the shown steps again. */
796
+ /**
797
+ * How a run answers a review: accept it, with edits where the review allows (a text, or the
798
+ * data of a json step), or ask for one of the shown steps again.
799
+ */
797
800
  export type PluginReviewAction = {
798
801
  type: "accept";
799
- edits?: Record<string, string>;
802
+ edits?: Record<string, string | Record<string, unknown>>;
800
803
  } | {
801
804
  type: "regenerate";
802
805
  target: string;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { type ObjectShape } from "./shape.js";
2
3
  import { type SurfaceComponent } from "./surface.js";
3
4
  /** The engenty avatars a wizard can wear. Same cast as engenty's ui-core. */
4
5
  export declare const ENGENTY_KINDS: readonly ["round", "drop", "dome", "flame", "oval", "bean", "pebble", "sprout", "tower", "wedge"];
@@ -547,7 +548,40 @@ export declare const agentStepSchema: z.ZodObject<{
547
548
  columns: z.ZodOptional<z.ZodArray<z.ZodString>>;
548
549
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
549
550
  }, z.core.$strip>>>;
550
- surface: z.ZodOptional<z.ZodBoolean>;
551
+ schema: z.ZodOptional<z.ZodType<ObjectShape, unknown, z.core.$ZodTypeInternals<ObjectShape, unknown>>>;
552
+ surface: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodObject<{
553
+ id: z.ZodString;
554
+ component: z.ZodEnum<{
555
+ Actions: "Actions";
556
+ Badge: "Badge";
557
+ BarChart: "BarChart";
558
+ Button: "Button";
559
+ Callout: "Callout";
560
+ Card: "Card";
561
+ Checklist: "Checklist";
562
+ Chips: "Chips";
563
+ Column: "Column";
564
+ DetailGrid: "DetailGrid";
565
+ DonutChart: "DonutChart";
566
+ Fold: "Fold";
567
+ Grid: "Grid";
568
+ Group: "Group";
569
+ Image: "Image";
570
+ LineChart: "LineChart";
571
+ Link: "Link";
572
+ List: "List";
573
+ Metric: "Metric";
574
+ Row: "Row";
575
+ Steps: "Steps";
576
+ Table: "Table";
577
+ Tabs: "Tabs";
578
+ Text: "Text";
579
+ }>;
580
+ children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
581
+ path: z.ZodString;
582
+ componentId: z.ZodString;
583
+ }, z.core.$strip>]>>;
584
+ }, z.core.$loose>>]>>;
551
585
  }, z.core.$strip>>;
552
586
  model: z.ZodOptional<z.ZodEnum<{
553
587
  classifier: "classifier";
@@ -687,6 +721,10 @@ export declare const widgetStepSchema: z.ZodObject<{
687
721
  entry: z.ZodString;
688
722
  data: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
689
723
  sample: z.ZodOptional<z.ZodString>;
724
+ layout: z.ZodOptional<z.ZodEnum<{
725
+ fixed: "fixed";
726
+ page: "page";
727
+ }>>;
690
728
  size: z.ZodOptional<z.ZodObject<{
691
729
  width: z.ZodNumber;
692
730
  height: z.ZodNumber;
@@ -777,16 +815,25 @@ export declare const surfaceCandidateSchema: z.ZodObject<{
777
815
  Badge: "Badge";
778
816
  BarChart: "BarChart";
779
817
  Button: "Button";
818
+ Callout: "Callout";
819
+ Card: "Card";
820
+ Checklist: "Checklist";
821
+ Chips: "Chips";
780
822
  Column: "Column";
781
823
  DetailGrid: "DetailGrid";
782
824
  DonutChart: "DonutChart";
825
+ Fold: "Fold";
783
826
  Grid: "Grid";
827
+ Group: "Group";
784
828
  Image: "Image";
785
829
  LineChart: "LineChart";
830
+ Link: "Link";
786
831
  List: "List";
787
832
  Metric: "Metric";
788
833
  Row: "Row";
834
+ Steps: "Steps";
789
835
  Table: "Table";
836
+ Tabs: "Tabs";
790
837
  Text: "Text";
791
838
  }>;
792
839
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -841,16 +888,25 @@ export declare const surfaceStepSchema: z.ZodObject<{
841
888
  Badge: "Badge";
842
889
  BarChart: "BarChart";
843
890
  Button: "Button";
891
+ Callout: "Callout";
892
+ Card: "Card";
893
+ Checklist: "Checklist";
894
+ Chips: "Chips";
844
895
  Column: "Column";
845
896
  DetailGrid: "DetailGrid";
846
897
  DonutChart: "DonutChart";
898
+ Fold: "Fold";
847
899
  Grid: "Grid";
900
+ Group: "Group";
848
901
  Image: "Image";
849
902
  LineChart: "LineChart";
903
+ Link: "Link";
850
904
  List: "List";
851
905
  Metric: "Metric";
852
906
  Row: "Row";
907
+ Steps: "Steps";
853
908
  Table: "Table";
909
+ Tabs: "Tabs";
854
910
  Text: "Text";
855
911
  }>;
856
912
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -868,16 +924,25 @@ export declare const surfaceStepSchema: z.ZodObject<{
868
924
  Badge: "Badge";
869
925
  BarChart: "BarChart";
870
926
  Button: "Button";
927
+ Callout: "Callout";
928
+ Card: "Card";
929
+ Checklist: "Checklist";
930
+ Chips: "Chips";
871
931
  Column: "Column";
872
932
  DetailGrid: "DetailGrid";
873
933
  DonutChart: "DonutChart";
934
+ Fold: "Fold";
874
935
  Grid: "Grid";
936
+ Group: "Group";
875
937
  Image: "Image";
876
938
  LineChart: "LineChart";
939
+ Link: "Link";
877
940
  List: "List";
878
941
  Metric: "Metric";
879
942
  Row: "Row";
943
+ Steps: "Steps";
880
944
  Table: "Table";
945
+ Tabs: "Tabs";
881
946
  Text: "Text";
882
947
  }>;
883
948
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -1229,7 +1294,40 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1229
1294
  columns: z.ZodOptional<z.ZodArray<z.ZodString>>;
1230
1295
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
1231
1296
  }, z.core.$strip>>>;
1232
- surface: z.ZodOptional<z.ZodBoolean>;
1297
+ schema: z.ZodOptional<z.ZodType<ObjectShape, unknown, z.core.$ZodTypeInternals<ObjectShape, unknown>>>;
1298
+ surface: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodObject<{
1299
+ id: z.ZodString;
1300
+ component: z.ZodEnum<{
1301
+ Actions: "Actions";
1302
+ Badge: "Badge";
1303
+ BarChart: "BarChart";
1304
+ Button: "Button";
1305
+ Callout: "Callout";
1306
+ Card: "Card";
1307
+ Checklist: "Checklist";
1308
+ Chips: "Chips";
1309
+ Column: "Column";
1310
+ DetailGrid: "DetailGrid";
1311
+ DonutChart: "DonutChart";
1312
+ Fold: "Fold";
1313
+ Grid: "Grid";
1314
+ Group: "Group";
1315
+ Image: "Image";
1316
+ LineChart: "LineChart";
1317
+ Link: "Link";
1318
+ List: "List";
1319
+ Metric: "Metric";
1320
+ Row: "Row";
1321
+ Steps: "Steps";
1322
+ Table: "Table";
1323
+ Tabs: "Tabs";
1324
+ Text: "Text";
1325
+ }>;
1326
+ children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
1327
+ path: z.ZodString;
1328
+ componentId: z.ZodString;
1329
+ }, z.core.$strip>]>>;
1330
+ }, z.core.$loose>>]>>;
1233
1331
  }, z.core.$strip>>;
1234
1332
  model: z.ZodOptional<z.ZodEnum<{
1235
1333
  classifier: "classifier";
@@ -1367,6 +1465,10 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1367
1465
  entry: z.ZodString;
1368
1466
  data: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
1369
1467
  sample: z.ZodOptional<z.ZodString>;
1468
+ layout: z.ZodOptional<z.ZodEnum<{
1469
+ fixed: "fixed";
1470
+ page: "page";
1471
+ }>>;
1370
1472
  size: z.ZodOptional<z.ZodObject<{
1371
1473
  width: z.ZodNumber;
1372
1474
  height: z.ZodNumber;
@@ -1417,16 +1519,25 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1417
1519
  Badge: "Badge";
1418
1520
  BarChart: "BarChart";
1419
1521
  Button: "Button";
1522
+ Callout: "Callout";
1523
+ Card: "Card";
1524
+ Checklist: "Checklist";
1525
+ Chips: "Chips";
1420
1526
  Column: "Column";
1421
1527
  DetailGrid: "DetailGrid";
1422
1528
  DonutChart: "DonutChart";
1529
+ Fold: "Fold";
1423
1530
  Grid: "Grid";
1531
+ Group: "Group";
1424
1532
  Image: "Image";
1425
1533
  LineChart: "LineChart";
1534
+ Link: "Link";
1426
1535
  List: "List";
1427
1536
  Metric: "Metric";
1428
1537
  Row: "Row";
1538
+ Steps: "Steps";
1429
1539
  Table: "Table";
1540
+ Tabs: "Tabs";
1430
1541
  Text: "Text";
1431
1542
  }>;
1432
1543
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -1444,16 +1555,25 @@ export declare const stepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1444
1555
  Badge: "Badge";
1445
1556
  BarChart: "BarChart";
1446
1557
  Button: "Button";
1558
+ Callout: "Callout";
1559
+ Card: "Card";
1560
+ Checklist: "Checklist";
1561
+ Chips: "Chips";
1447
1562
  Column: "Column";
1448
1563
  DetailGrid: "DetailGrid";
1449
1564
  DonutChart: "DonutChart";
1565
+ Fold: "Fold";
1450
1566
  Grid: "Grid";
1567
+ Group: "Group";
1451
1568
  Image: "Image";
1452
1569
  LineChart: "LineChart";
1570
+ Link: "Link";
1453
1571
  List: "List";
1454
1572
  Metric: "Metric";
1455
1573
  Row: "Row";
1574
+ Steps: "Steps";
1456
1575
  Table: "Table";
1576
+ Tabs: "Tabs";
1457
1577
  Text: "Text";
1458
1578
  }>;
1459
1579
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -1637,6 +1757,15 @@ export type AgentStep = z.infer<typeof agentStepSchema>;
1637
1757
  * (no text) can take.
1638
1758
  */
1639
1759
  export declare function isDecisionStep(step: AgentStep): boolean;
1760
+ /**
1761
+ * What an agent step's json output holds: its schema, or its fields as one. Undefined when it
1762
+ * names neither (the model then returns one table).
1763
+ */
1764
+ export declare function declaredShape(step: AgentStep): ObjectShape | undefined;
1765
+ /** What an agent step's json output holds: its declared shape, or else one table. */
1766
+ export declare function stepShape(step: AgentStep): ObjectShape;
1767
+ /** The top-level keys of an agent step's output: what `steps.<id>.<key>` may name. */
1768
+ export declare function outputKeys(step: AgentStep): string[];
1640
1769
  export type GenerateStep = z.infer<typeof generateStepSchema>;
1641
1770
  export type WidgetStep = z.infer<typeof widgetStepSchema>;
1642
1771
  export type FilmStep = z.infer<typeof filmStepSchema>;
@@ -2167,7 +2296,40 @@ export declare const wizardSchema: z.ZodObject<{
2167
2296
  columns: z.ZodOptional<z.ZodArray<z.ZodString>>;
2168
2297
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
2169
2298
  }, z.core.$strip>>>;
2170
- surface: z.ZodOptional<z.ZodBoolean>;
2299
+ schema: z.ZodOptional<z.ZodType<ObjectShape, unknown, z.core.$ZodTypeInternals<ObjectShape, unknown>>>;
2300
+ surface: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodArray<z.ZodObject<{
2301
+ id: z.ZodString;
2302
+ component: z.ZodEnum<{
2303
+ Actions: "Actions";
2304
+ Badge: "Badge";
2305
+ BarChart: "BarChart";
2306
+ Button: "Button";
2307
+ Callout: "Callout";
2308
+ Card: "Card";
2309
+ Checklist: "Checklist";
2310
+ Chips: "Chips";
2311
+ Column: "Column";
2312
+ DetailGrid: "DetailGrid";
2313
+ DonutChart: "DonutChart";
2314
+ Fold: "Fold";
2315
+ Grid: "Grid";
2316
+ Group: "Group";
2317
+ Image: "Image";
2318
+ LineChart: "LineChart";
2319
+ Link: "Link";
2320
+ List: "List";
2321
+ Metric: "Metric";
2322
+ Row: "Row";
2323
+ Steps: "Steps";
2324
+ Table: "Table";
2325
+ Tabs: "Tabs";
2326
+ Text: "Text";
2327
+ }>;
2328
+ children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
2329
+ path: z.ZodString;
2330
+ componentId: z.ZodString;
2331
+ }, z.core.$strip>]>>;
2332
+ }, z.core.$loose>>]>>;
2171
2333
  }, z.core.$strip>>;
2172
2334
  model: z.ZodOptional<z.ZodEnum<{
2173
2335
  classifier: "classifier";
@@ -2305,6 +2467,10 @@ export declare const wizardSchema: z.ZodObject<{
2305
2467
  entry: z.ZodString;
2306
2468
  data: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
2307
2469
  sample: z.ZodOptional<z.ZodString>;
2470
+ layout: z.ZodOptional<z.ZodEnum<{
2471
+ fixed: "fixed";
2472
+ page: "page";
2473
+ }>>;
2308
2474
  size: z.ZodOptional<z.ZodObject<{
2309
2475
  width: z.ZodNumber;
2310
2476
  height: z.ZodNumber;
@@ -2355,16 +2521,25 @@ export declare const wizardSchema: z.ZodObject<{
2355
2521
  Badge: "Badge";
2356
2522
  BarChart: "BarChart";
2357
2523
  Button: "Button";
2524
+ Callout: "Callout";
2525
+ Card: "Card";
2526
+ Checklist: "Checklist";
2527
+ Chips: "Chips";
2358
2528
  Column: "Column";
2359
2529
  DetailGrid: "DetailGrid";
2360
2530
  DonutChart: "DonutChart";
2531
+ Fold: "Fold";
2361
2532
  Grid: "Grid";
2533
+ Group: "Group";
2362
2534
  Image: "Image";
2363
2535
  LineChart: "LineChart";
2536
+ Link: "Link";
2364
2537
  List: "List";
2365
2538
  Metric: "Metric";
2366
2539
  Row: "Row";
2540
+ Steps: "Steps";
2367
2541
  Table: "Table";
2542
+ Tabs: "Tabs";
2368
2543
  Text: "Text";
2369
2544
  }>;
2370
2545
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -2382,16 +2557,25 @@ export declare const wizardSchema: z.ZodObject<{
2382
2557
  Badge: "Badge";
2383
2558
  BarChart: "BarChart";
2384
2559
  Button: "Button";
2560
+ Callout: "Callout";
2561
+ Card: "Card";
2562
+ Checklist: "Checklist";
2563
+ Chips: "Chips";
2385
2564
  Column: "Column";
2386
2565
  DetailGrid: "DetailGrid";
2387
2566
  DonutChart: "DonutChart";
2567
+ Fold: "Fold";
2388
2568
  Grid: "Grid";
2569
+ Group: "Group";
2389
2570
  Image: "Image";
2390
2571
  LineChart: "LineChart";
2572
+ Link: "Link";
2391
2573
  List: "List";
2392
2574
  Metric: "Metric";
2393
2575
  Row: "Row";
2576
+ Steps: "Steps";
2394
2577
  Table: "Table";
2578
+ Tabs: "Tabs";
2395
2579
  Text: "Text";
2396
2580
  }>;
2397
2581
  children: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodObject<{
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: FSL-1.1-MIT OR MIT
2
2
  import { z } from "zod";
3
3
  import { tableColumnsSchema } from "./engenty/data-tables/index.js";
4
+ import { outputShapeSchema, shapeOfFields } from "./shape.js";
4
5
  import { CONNECTION_KINDS } from "./store.js";
5
6
  import { surfaceComponentsSchema, validateSurface } from "./surface.js";
6
7
  /** The engenty avatars a wizard can wear. Same cast as engenty's ui-core. */
@@ -505,12 +506,19 @@ export const agentStepSchema = z.object({
505
506
  output: z
506
507
  .object({
507
508
  format: z.enum(["text", "markdown", "json"]),
509
+ /** The short form: one level of keys. A step has `fields` or `schema`, not both. */
508
510
  fields: z.array(outputFieldSchema).optional(),
509
511
  /**
510
- * json only: the step also composes a view of its result from the surface catalog, bound
511
- * to its own fields; reviews and the result show that view instead of a plain table.
512
+ * json only: nested data (lists of entries with lists of their own), in the kinds of
513
+ * `shape.ts`. Objects nest at most four deep, a hundred keys in all.
512
514
  */
513
- surface: z.boolean().optional(),
515
+ schema: outputShapeSchema.optional(),
516
+ /**
517
+ * json only: a view of the result from the surface catalog, bound to the step's own fields;
518
+ * reviews and the result show it instead of a plain table. Components: written once, the
519
+ * same every run, nothing to pay. `true`: a model composes one each run.
520
+ */
521
+ surface: z.union([z.boolean(), surfaceComponentsSchema]).optional(),
514
522
  })
515
523
  .default({ format: "markdown" }),
516
524
  /** The kind of model the step needs; default `high`. The model itself is bound elsewhere. */
@@ -570,6 +578,12 @@ export const widgetStepSchema = z.object({
570
578
  data: z.record(z.string(), z.string()).default({}),
571
579
  /** Workspace path of example data (JSON) for previews before any run. */
572
580
  sample: z.string().optional(),
581
+ /**
582
+ * How the run shows it: `fixed` (default) at `size`, scaled to the page; `page` as a part of
583
+ * the page, as wide as it and as tall as its content — a result people scroll and use, not a
584
+ * picture. PNG/PDF/MP4 still render at `size`.
585
+ */
586
+ layout: z.enum(["fixed", "page"]).optional(),
573
587
  /** The size the widget is designed for; previews scale it, PNG/PDF/MP4 render at it. */
574
588
  size: z
575
589
  .object({
@@ -703,6 +717,7 @@ export const stepSchema = z.discriminatedUnion("type", [
703
717
  export function isDecisionStep(step) {
704
718
  const fields = step.output.fields ?? [];
705
719
  return (!step.call &&
720
+ !step.output.schema &&
706
721
  step.model === "classifier" &&
707
722
  step.output.format === "json" &&
708
723
  fields.length > 0 &&
@@ -712,6 +727,27 @@ export function isDecisionStep(step) {
712
727
  !step.mcp?.length &&
713
728
  !step.connections?.length);
714
729
  }
730
+ /**
731
+ * What an agent step's json output holds: its schema, or its fields as one. Undefined when it
732
+ * names neither (the model then returns one table).
733
+ */
734
+ export function declaredShape(step) {
735
+ if (step.output.schema) {
736
+ return step.output.schema;
737
+ }
738
+ return step.output.fields?.length ? shapeOfFields(step.output.fields) : undefined;
739
+ }
740
+ /** What an agent step's json output holds: its declared shape, or else one table. */
741
+ export function stepShape(step) {
742
+ return (declaredShape(step) ?? {
743
+ kind: "object",
744
+ fields: { data: { kind: "table", description: "The result as a table" } },
745
+ });
746
+ }
747
+ /** The top-level keys of an agent step's output: what `steps.<id>.<key>` may name. */
748
+ export function outputKeys(step) {
749
+ return Object.keys(declaredShape(step)?.fields ?? {});
750
+ }
715
751
  export const listSchema = z.object({
716
752
  id,
717
753
  title: z.string().min(1),
@@ -794,7 +830,10 @@ export function formatsFor(step) {
794
830
  }
795
831
  if (step.type === "agent") {
796
832
  if (step.output.format === "json") {
797
- return ["json", "csv", "xlsx", "md", "zip"];
833
+ // Nested data reads as a document too.
834
+ return step.output.schema
835
+ ? ["json", "csv", "xlsx", "md", "pdf", "zip"]
836
+ : ["json", "csv", "xlsx", "md", "zip"];
798
837
  }
799
838
  return ["md", "txt", "docx", "pdf", "html", "zip"];
800
839
  }
@@ -1017,8 +1056,7 @@ export function validateWizard(def, files) {
1017
1056
  const source = def.steps.find((s) => s.id === from);
1018
1057
  return (source?.type === "agent" &&
1019
1058
  (!probability || isDecisionStep(source)) &&
1020
- ((source.output.fields ?? []).some((f) => f.id === key) ||
1021
- (Boolean(source.each) && key === "rows" && !probability)));
1059
+ (outputKeys(source).includes(key) || (Boolean(source.each) && key === "rows" && !probability)));
1022
1060
  };
1023
1061
  const conditionIssues = (stepId, c) => {
1024
1062
  if ((c.op === "gt" || c.op === "lt") && typeof c.value !== "number") {
@@ -1053,27 +1091,38 @@ export function validateWizard(def, files) {
1053
1091
  if (source?.type === "agent" && source.each && key === "rows") {
1054
1092
  return column ? null : `"optionsFrom": "${from}.rows" is a table; name one of its columns.`;
1055
1093
  }
1056
- const out = source?.type === "agent"
1057
- ? (source.output.fields ?? []).find((f) => f.id === key)
1058
- : undefined;
1094
+ const out = source?.type === "agent" ? declaredShape(source)?.fields[key] : undefined;
1059
1095
  if (!out) {
1060
1096
  return `"optionsFrom" names "${from}.${key}", which is not an output of an earlier agent step.`;
1061
1097
  }
1098
+ // The keys of a table's rows, or of a list's entries; undefined: any (free columns).
1099
+ const columns = out.kind === "table"
1100
+ ? out.columns?.length
1101
+ ? out.columns
1102
+ : undefined
1103
+ : out.kind === "list" && out.of.kind === "object"
1104
+ ? Object.keys(out.of.fields)
1105
+ : null;
1106
+ if (columns === null) {
1107
+ if (column || cards) {
1108
+ return column
1109
+ ? `"optionsFrom": "${from}.${key}" is not a table with the column "${column}".`
1110
+ : `"cards": "${from}.${key}" is not a table.`;
1111
+ }
1112
+ return out.kind === "list"
1113
+ ? null
1114
+ : `"optionsFrom": "${from}.${key}" is not a list (a table takes a column, or "cards").`;
1115
+ }
1062
1116
  if (column) {
1063
- return out.kind === "table" && (!out.columns?.length || out.columns.includes(column))
1117
+ return !columns || columns.includes(column)
1064
1118
  ? null
1065
1119
  : `"optionsFrom": "${from}.${key}" is not a table with the column "${column}".`;
1066
1120
  }
1067
1121
  if (cards) {
1068
- if (out.kind !== "table") {
1069
- return `"cards": "${from}.${key}" is not a table.`;
1070
- }
1071
- const missing = Object.values(cards).find((c) => out.columns?.length && !out.columns.includes(c));
1072
- return missing ? `"cards": table "${from}.${key}" has no column "${missing}".` : null;
1122
+ const missing = Object.values(cards).find((c) => columns && !columns.includes(c));
1123
+ return missing ? `"cards": "${from}.${key}" has no column "${missing}".` : null;
1073
1124
  }
1074
- return out.kind === "list"
1075
- ? null
1076
- : `"optionsFrom": "${from}.${key}" is not a list (a table takes a column, or "cards").`;
1125
+ return `"optionsFrom": "${from}.${key}" is not a list (a table takes a column, or "cards").`;
1077
1126
  }
1078
1127
  return `"optionsFrom" is "steps.<id>.<key>", "steps.<id>.<key>.<column>" or "lists.<id>.<column>".`;
1079
1128
  };
@@ -1182,6 +1231,28 @@ export function validateWizard(def, files) {
1182
1231
  message: 'A step composes a view ("surface") of json output only.',
1183
1232
  });
1184
1233
  }
1234
+ if (step.output.schema) {
1235
+ if (step.output.fields?.length) {
1236
+ issues.push({
1237
+ stepId: step.id,
1238
+ message: 'Output has "fields" or "schema", not both.',
1239
+ });
1240
+ }
1241
+ if (step.output.format !== "json" || step.call) {
1242
+ issues.push({
1243
+ stepId: step.id,
1244
+ message: step.call
1245
+ ? 'A step with "call" keeps the tool\'s answer as it is: no "schema".'
1246
+ : 'A "schema" describes json output: output format "json".',
1247
+ });
1248
+ }
1249
+ }
1250
+ if (Array.isArray(step.output.surface)) {
1251
+ // A step with `each` hands over its entries as `rows`.
1252
+ for (const issue of validateSurface(step.output.surface, step.each ? ["rows"] : declaredShape(step))) {
1253
+ issues.push({ stepId: step.id, message: `View: ${issue.message}` });
1254
+ }
1255
+ }
1185
1256
  if (step.each) {
1186
1257
  const ref = dataRef(step.each);
1187
1258
  const list = ref.match(/^lists\.([a-zA-Z][a-zA-Z0-9_]*)$/)?.[1];
@@ -2,6 +2,8 @@ import { z } from "zod";
2
2
  import { DEFINITION_VERSION, wizardSchema } from "./definition.js";
3
3
  import { manifestSchema, PACKAGE_SCHEMA_URL, WIZARD_SCHEMA_URL } from "./wizard-package.js";
4
4
  const DIALECT = "https://json-schema.org/draft/2020-12/schema";
5
+ /** `$comment` is the one place a validator ignores; an unknown `$license` keyword would trip Ajv's strict mode. */
6
+ const LICENSE_COMMENT = "MIT License. Copyright (c) 2026 Matthias Platzer.";
5
7
  const SCHEMA_PROPERTY = {
6
8
  type: "string",
7
9
  description: "The JSON Schema an editor checks this file against; the app does not read it.",
@@ -38,6 +40,7 @@ export function wizardJsonSchema() {
38
40
  return {
39
41
  $schema: DIALECT,
40
42
  $id: WIZARD_SCHEMA_URL,
43
+ $comment: LICENSE_COMMENT,
41
44
  title: "engenty.wizards wizard definition",
42
45
  description: `A wizard's definition, version ${DEFINITION_VERSION}. Checked by \`wizards validate\`, which also checks what this schema cannot say: ids, references between steps and templates.`,
43
46
  ...withSchemaProperty(generate(wizardSchema)),
@@ -50,6 +53,7 @@ export function packageJsonSchema() {
50
53
  return {
51
54
  $schema: DIALECT,
52
55
  $id: PACKAGE_SCHEMA_URL,
56
+ $comment: LICENSE_COMMENT,
53
57
  title: "engenty.wizards package manifest (wizard.json)",
54
58
  description: "wizard.json in a .wizard package — a zip with this file and the wizard's workspace under files/.",
55
59
  ...manifest,
@@ -1,3 +1,4 @@
1
+ import type { RunTheme } from "./run.js";
1
2
  export declare const FACT_TYPES: readonly ["text", "longtext", "number", "date", "url", "email", "phone", "boolean"];
2
3
  export type FactType = (typeof FACT_TYPES)[number];
3
4
  export interface ProjectFact {
@@ -130,6 +131,16 @@ export interface BrandFont {
130
131
  */
131
132
  uses?: FontUse[];
132
133
  }
134
+ /**
135
+ * How a wizard's pages look, from the brand: the first standard colour is the accent, a standard
136
+ * colour named as the ground ("Hintergrund") the background, the next colourful one the second
137
+ * colour; the typeface for headings and the one for text by their roles. What the brand does not
138
+ * say stays the runner's own.
139
+ */
140
+ export declare function runTheme(brand: {
141
+ colors?: BrandColor[];
142
+ fonts?: Pick<BrandFont, "family" | "role">[];
143
+ }): RunTheme;
133
144
  /** The font's licence as a model reads it: ", licence …, may only be used for …". */
134
145
  export declare function fontLicenseWords(f: Pick<BrandFont, "license" | "uses">): string;
135
146
  /** A text style of the type scale: "Headline XL – Space Grotesk 600, 48 px, line 90 %, −4 %". */
@@ -190,6 +190,60 @@ export const FONT_USE_WORDS = {
190
190
  images: "images and social graphics",
191
191
  video: "video",
192
192
  };
193
+ const BACKGROUND_WORDS = /hintergrund|background|untergrund|grund|paper|papier|fläche|surface/i;
194
+ const TEXT_WORDS = /\btext|schrift|ink|typo/i;
195
+ const DISPLAY_ROLES = /head|überschrift|display|titel|title|headline/i;
196
+ const BODY_ROLES = /body|fließ|copy|lauf|text|ui|interface/i;
197
+ /** The channels of a #rrggbb colour, 0–255; null for anything else. */
198
+ function rgbOf(hex) {
199
+ const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex.trim());
200
+ return m
201
+ ? [Number.parseInt(m[1], 16), Number.parseInt(m[2], 16), Number.parseInt(m[3], 16)]
202
+ : null;
203
+ }
204
+ /** How light a colour looks, 0–1 (relative luminance). */
205
+ function luminance(hex) {
206
+ const rgb = rgbOf(hex);
207
+ if (!rgb) {
208
+ return 1;
209
+ }
210
+ const [r, g, b] = rgb.map((c) => {
211
+ const v = c / 255;
212
+ return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
213
+ });
214
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
215
+ }
216
+ /** A colour with a hue of its own, not a grey, white or black. */
217
+ function colourful(hex) {
218
+ const rgb = rgbOf(hex);
219
+ return rgb ? Math.max(...rgb) - Math.min(...rgb) > 40 : false;
220
+ }
221
+ /**
222
+ * How a wizard's pages look, from the brand: the first standard colour is the accent, a standard
223
+ * colour named as the ground ("Hintergrund") the background, the next colourful one the second
224
+ * colour; the typeface for headings and the one for text by their roles. What the brand does not
225
+ * say stays the runner's own.
226
+ */
227
+ export function runTheme(brand) {
228
+ const standard = (brand.colors ?? []).filter((c) => !c.section && rgbOf(c.value));
229
+ const accent = standard[0]?.value ?? null;
230
+ const background = standard.find((c) => BACKGROUND_WORDS.test(c.name))?.value ?? null;
231
+ const second = standard
232
+ .slice(1)
233
+ .find((c) => c.value !== background && !TEXT_WORDS.test(c.name) && colourful(c.value))
234
+ ?.value ?? null;
235
+ const fonts = brand.fonts ?? [];
236
+ const display = fonts.find((f) => DISPLAY_ROLES.test(f.role)) ?? fonts[0];
237
+ const body = fonts.find((f) => f !== display && BODY_ROLES.test(f.role)) ?? fonts.find((f) => f !== display);
238
+ return {
239
+ accent,
240
+ second,
241
+ background,
242
+ display: display?.family ?? null,
243
+ body: body?.family ?? null,
244
+ dark: background ? luminance(background) < 0.18 : false,
245
+ };
246
+ }
193
247
  /** The font's licence as a model reads it: ", licence …, may only be used for …". */
194
248
  export function fontLicenseWords(f) {
195
249
  return [