@assistant-ui/react-generative-ui 0.0.19 → 0.0.20

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 (137) hide show
  1. package/dist/JSONGenerativeUI.client.d.ts +14 -15
  2. package/dist/JSONGenerativeUI.client.d.ts.map +1 -1
  3. package/dist/JSONGenerativeUI.client.js +28 -8
  4. package/dist/JSONGenerativeUI.client.js.map +1 -1
  5. package/dist/JSONGenerativeUI.server.d.ts +5 -7
  6. package/dist/JSONGenerativeUI.server.d.ts.map +1 -1
  7. package/dist/JSONGenerativeUI.shared.d.ts +35 -36
  8. package/dist/JSONGenerativeUI.shared.d.ts.map +1 -1
  9. package/dist/a2ui/convert.d.ts +7 -7
  10. package/dist/a2ui/convert.d.ts.map +1 -1
  11. package/dist/a2ui/convert.js +115 -16
  12. package/dist/a2ui/convert.js.map +1 -1
  13. package/dist/a2ui/reducer.d.ts +1 -3
  14. package/dist/a2ui/reducer.d.ts.map +1 -1
  15. package/dist/a2ui/reducer.js +8 -0
  16. package/dist/a2ui/reducer.js.map +1 -1
  17. package/dist/a2ui/snapshot.d.ts +3 -0
  18. package/dist/a2ui/snapshot.d.ts.map +1 -0
  19. package/dist/a2ui/snapshot.js +33 -0
  20. package/dist/a2ui/snapshot.js.map +1 -0
  21. package/dist/a2ui/types.d.ts +50 -40
  22. package/dist/a2ui/types.d.ts.map +1 -1
  23. package/dist/a2ui/types.js.map +1 -1
  24. package/dist/a2ui.d.ts +5 -4
  25. package/dist/a2ui.d.ts.map +1 -0
  26. package/dist/a2ui.js +2 -1
  27. package/dist/actionRegistry.d.ts +12 -14
  28. package/dist/actionRegistry.d.ts.map +1 -1
  29. package/dist/actionRegistry.js.map +1 -1
  30. package/dist/buildPresentParameters.d.ts +2 -4
  31. package/dist/buildPresentParameters.d.ts.map +1 -1
  32. package/dist/buildPresentParameters.js +16 -4
  33. package/dist/buildPresentParameters.js.map +1 -1
  34. package/dist/constants.d.ts +0 -2
  35. package/dist/constants.d.ts.map +1 -1
  36. package/dist/convert/boundSpec.d.ts +0 -2
  37. package/dist/convert/boundSpec.d.ts.map +1 -1
  38. package/dist/convert/copyBounded.d.ts +2 -4
  39. package/dist/convert/copyBounded.d.ts.map +1 -1
  40. package/dist/convert/isElement.d.ts +1 -3
  41. package/dist/convert/isElement.d.ts.map +1 -1
  42. package/dist/convert/takeRun.d.ts +3 -5
  43. package/dist/convert/takeRun.d.ts.map +1 -1
  44. package/dist/defineGenerativeComponents.d.ts +1 -3
  45. package/dist/defineGenerativeComponents.d.ts.map +1 -1
  46. package/dist/generativeUIToJSX.d.ts +4 -6
  47. package/dist/generativeUIToJSX.d.ts.map +1 -1
  48. package/dist/index.d.ts +3 -13
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.server.d.ts +3 -13
  51. package/dist/index.server.d.ts.map +1 -0
  52. package/dist/index.shared.d.ts +15 -11
  53. package/dist/index.shared.d.ts.map +1 -0
  54. package/dist/ir.d.ts +17 -19
  55. package/dist/ir.d.ts.map +1 -1
  56. package/dist/renderGenerativeUI.d.ts +2 -4
  57. package/dist/renderGenerativeUI.d.ts.map +1 -1
  58. package/dist/scopeSchema.d.ts +6 -0
  59. package/dist/scopeSchema.d.ts.map +1 -0
  60. package/dist/scopeSchema.js +56 -0
  61. package/dist/scopeSchema.js.map +1 -0
  62. package/dist/slack/constants.d.ts +8 -9
  63. package/dist/slack/constants.d.ts.map +1 -1
  64. package/dist/slack/decodeBlockAction.d.ts +1 -3
  65. package/dist/slack/decodeBlockAction.d.ts.map +1 -1
  66. package/dist/slack/fromSlackBlocks.d.ts +1 -3
  67. package/dist/slack/fromSlackBlocks.d.ts.map +1 -1
  68. package/dist/slack/toSlackBlocks.d.ts +1 -3
  69. package/dist/slack/toSlackBlocks.d.ts.map +1 -1
  70. package/dist/slack/toSlackBlocks.js +1 -1
  71. package/dist/slack/types.d.ts +78 -80
  72. package/dist/slack/types.d.ts.map +1 -1
  73. package/dist/slack.d.ts +5 -5
  74. package/dist/slack.d.ts.map +1 -0
  75. package/dist/teams/constants.d.ts +1 -3
  76. package/dist/teams/constants.d.ts.map +1 -1
  77. package/dist/teams/decodeSubmitData.d.ts +1 -3
  78. package/dist/teams/decodeSubmitData.d.ts.map +1 -1
  79. package/dist/teams/toAdaptiveCard.d.ts +4 -6
  80. package/dist/teams/toAdaptiveCard.d.ts.map +1 -1
  81. package/dist/teams/toTeamsAttachments.d.ts +1 -3
  82. package/dist/teams/toTeamsAttachments.d.ts.map +1 -1
  83. package/dist/teams/types.d.ts +108 -109
  84. package/dist/teams/types.d.ts.map +1 -1
  85. package/dist/teams.d.ts +5 -5
  86. package/dist/teams.d.ts.map +1 -0
  87. package/dist/types.d.ts +36 -37
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/vocabulary/alert.d.ts +21 -23
  90. package/dist/vocabulary/alert.d.ts.map +1 -1
  91. package/dist/vocabulary/collectFormValues.d.ts +8 -10
  92. package/dist/vocabulary/collectFormValues.d.ts.map +1 -1
  93. package/dist/vocabulary/data.d.ts +45 -47
  94. package/dist/vocabulary/data.d.ts.map +1 -1
  95. package/dist/vocabulary/dispatch.d.ts +2 -4
  96. package/dist/vocabulary/dispatch.d.ts.map +1 -1
  97. package/dist/vocabulary/fact.d.ts +8 -10
  98. package/dist/vocabulary/fact.d.ts.map +1 -1
  99. package/dist/vocabulary/form.d.ts +7 -9
  100. package/dist/vocabulary/form.d.ts.map +1 -1
  101. package/dist/vocabulary/icon.d.ts +37 -39
  102. package/dist/vocabulary/icon.d.ts.map +1 -1
  103. package/dist/vocabulary/index.d.ts +1 -3
  104. package/dist/vocabulary/index.d.ts.map +1 -1
  105. package/dist/vocabulary/interactive.d.ts +87 -86
  106. package/dist/vocabulary/interactive.d.ts.map +1 -1
  107. package/dist/vocabulary/interactive.js +4 -4
  108. package/dist/vocabulary/interactive.js.map +1 -1
  109. package/dist/vocabulary/layout.d.ts +75 -77
  110. package/dist/vocabulary/layout.d.ts.map +1 -1
  111. package/dist/vocabulary/list.d.ts +10 -12
  112. package/dist/vocabulary/list.d.ts.map +1 -1
  113. package/dist/vocabulary/media.d.ts +21 -23
  114. package/dist/vocabulary/media.d.ts.map +1 -1
  115. package/dist/vocabulary/text.d.ts +53 -55
  116. package/dist/vocabulary/text.d.ts.map +1 -1
  117. package/dist/vocabulary/toTextContent.d.ts +0 -2
  118. package/dist/vocabulary/toTextContent.d.ts.map +1 -1
  119. package/package.json +4 -4
  120. package/src/JSONGenerativeUI.client.tsx +57 -15
  121. package/src/JSONGenerativeUI.test.tsx +298 -4
  122. package/src/a2ui/convert.test.ts +496 -0
  123. package/src/a2ui/convert.ts +170 -25
  124. package/src/a2ui/reducer.test.ts +18 -0
  125. package/src/a2ui/reducer.ts +16 -0
  126. package/src/a2ui/snapshot.test.ts +52 -0
  127. package/src/a2ui/snapshot.ts +52 -0
  128. package/src/a2ui/types.ts +16 -0
  129. package/src/a2ui.ts +2 -0
  130. package/src/actionRegistry.ts +5 -5
  131. package/src/buildPresentParameters.test.ts +246 -0
  132. package/src/buildPresentParameters.ts +18 -3
  133. package/src/scopeSchema.test.ts +72 -0
  134. package/src/scopeSchema.ts +71 -0
  135. package/src/vocabulary/interactive.dispatch.test.tsx +17 -3
  136. package/src/vocabulary/interactive.test.tsx +19 -0
  137. package/src/vocabulary/interactive.tsx +4 -1
@@ -1,5 +1,4 @@
1
- import { JSONGenerativeUIOptions, PresentTool, PresentToolOptions, PromptUserTool } from "./JSONGenerativeUI.shared.js";
2
- //#region src/JSONGenerativeUI.client.d.ts
1
+ import { type JSONGenerativeUIOptions, type PresentTool, type PresentToolOptions, type PromptUserTool } from "./JSONGenerativeUI.shared.js";
3
2
  /**
4
3
  * Client build of {@link JSONGenerativeUI}, resolved through the package's
5
4
  * `default` export condition (browser and SSR).
@@ -12,18 +11,18 @@ import { JSONGenerativeUIOptions, PresentTool, PresentToolOptions, PromptUserToo
12
11
  * interactive components can fire `$action` through `$dispatch`.
13
12
  */
14
13
  export declare class JSONGenerativeUI {
15
- private readonly library;
16
- private readonly parameters;
17
- private readonly actions;
18
- constructor(options: JSONGenerativeUIOptions);
19
- /**
20
- * The surface a `present` call paints into. It owns the vertical rhythm
21
- * between top-level blocks, which the host's message container does not
22
- * provide, and stays out of the way while it has nothing to show.
23
- */
24
- private readonly render;
25
- present(options?: PresentToolOptions): PresentTool;
26
- promptUser(): PromptUserTool;
14
+ private readonly library;
15
+ private readonly parameters;
16
+ private readonly actions;
17
+ private readonly completedPromptToolCallIds;
18
+ constructor(options: JSONGenerativeUIOptions);
19
+ /**
20
+ * The surface a `present` call paints into. It owns the vertical rhythm
21
+ * between top-level blocks, which the host's message container does not
22
+ * provide, and stays out of the way while it has nothing to show.
23
+ */
24
+ private readonly render;
25
+ present(options?: PresentToolOptions): PresentTool;
26
+ promptUser(): PromptUserTool;
27
27
  }
28
- //#endregion
29
28
  //# sourceMappingURL=JSONGenerativeUI.client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JSONGenerativeUI.client.d.ts","names":[],"sources":["../src/JSONGenerativeUI.client.tsx"],"mappings":";;;;;;;;;;;;;qBAkCa;mBACM;mBACA;mBACA;EAEL,YAAA,SAAS;;;;;;mBAWJ;EAejB,QAAQ,UAAU,qBAAqB;EASvC,cAAc"}
1
+ {"version":3,"file":"JSONGenerativeUI.client.d.ts","sourceRoot":"","sources":["../src/JSONGenerativeUI.client.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,uBAAuB,EAE5B,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,qCAAkC;AAanC;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAqB;gBAEpD,OAAO,EAAE,uBAAuB;IAM5C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAqDrB;IAEF,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW;IASlD,UAAU,IAAI,cAAc;CAO7B"}
@@ -25,6 +25,7 @@ var JSONGenerativeUI = class {
25
25
  library;
26
26
  parameters;
27
27
  actions;
28
+ completedPromptToolCallIds = /* @__PURE__ */ new Set();
28
29
  constructor(options) {
29
30
  this.library = options.library;
30
31
  this.parameters = buildPresentParameters(options.library);
@@ -35,13 +36,32 @@ var JSONGenerativeUI = class {
35
36
  * between top-level blocks, which the host's message container does not
36
37
  * provide, and stays out of the way while it has nothing to show.
37
38
  */
38
- render = ({ args, status }) => /* @__PURE__ */ jsx("div", {
39
- "data-aui": "root",
40
- children: renderGenerativeUI(args, this.library, {
41
- status: uiStatus(status),
42
- ...this.actions ? { dispatch: this.actions.dispatch } : {}
43
- })
44
- });
39
+ render = ({ args, status, addResult, result, toolCallId, unstable_recordInteraction }, completesPrompt = false) => {
40
+ const actions = this.actions;
41
+ const dispatch = actions ? (action) => {
42
+ if (unstable_recordInteraction) try {
43
+ unstable_recordInteraction({
44
+ type: "action",
45
+ payload: action
46
+ }).catch(() => {});
47
+ } catch {}
48
+ const actionResult = actions.dispatch(action);
49
+ if (completesPrompt && actionResult !== void 0 && result === void 0) Promise.resolve(actionResult).then((response) => {
50
+ if (response !== void 0 && !this.completedPromptToolCallIds.has(toolCallId)) {
51
+ this.completedPromptToolCallIds.add(toolCallId);
52
+ addResult(response);
53
+ }
54
+ }).catch(() => {});
55
+ return actionResult;
56
+ } : void 0;
57
+ return /* @__PURE__ */ jsx("div", {
58
+ "data-aui": "root",
59
+ children: renderGenerativeUI(args, this.library, {
60
+ status: uiStatus(status),
61
+ ...dispatch ? { dispatch } : {}
62
+ })
63
+ });
64
+ };
45
65
  present(options) {
46
66
  return {
47
67
  ...presentToolBase(this.parameters, options),
@@ -54,7 +74,7 @@ var JSONGenerativeUI = class {
54
74
  return {
55
75
  ...promptUserToolBase(this.parameters),
56
76
  unstable_backendDefault: { parameters: true },
57
- render: this.render
77
+ render: (props) => this.render(props, true)
58
78
  };
59
79
  }
60
80
  };
@@ -1 +1 @@
1
- {"version":3,"file":"JSONGenerativeUI.client.js","names":[],"sources":["../src/JSONGenerativeUI.client.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { buildPresentParameters } from \"./buildPresentParameters\";\nimport {\n presentToolBase,\n promptUserToolBase,\n type JSONGenerativeUIOptions,\n type PresentParameters,\n type PresentTool,\n type PresentToolOptions,\n type PromptUserTool,\n} from \"./JSONGenerativeUI.shared\";\nimport { type ActionRegistry } from \"./actionRegistry\";\nimport { renderGenerativeUI } from \"./renderGenerativeUI\";\nimport type { GenerativeUILibrary, GenerativeUIStatus } from \"./types\";\n\n/** Maps a tool-call part status to the generative-UI streaming status. Only a\n * `complete` call has fully-arrived args; `running` and `incomplete`\n * (aborted/errored, so args may be partial) both render as `\"streaming\"` so a\n * non-streaming component is never handed partial props. */\nfunction uiStatus(status: { type: string }): GenerativeUIStatus {\n return status.type === \"complete\" ? \"done\" : \"streaming\";\n}\n\n/**\n * Client build of {@link JSONGenerativeUI}, resolved through the package's\n * `default` export condition (browser and SSR).\n *\n * `present` is a frontend tool that renders the model's `{ $type, ...props }`\n * tree against the library and resolves immediately. `prompt_user` is a\n * human-in-the-loop tool: the model pauses and the rendered UI supplies the\n * result. Both draw the tree the same way, so they share one `render`. The\n * `actions` registry (if provided) is threaded into the render context so\n * interactive components can fire `$action` through `$dispatch`.\n */\nexport class JSONGenerativeUI {\n private readonly library: GenerativeUILibrary;\n private readonly parameters: PresentParameters;\n private readonly actions: ActionRegistry | undefined;\n\n constructor(options: JSONGenerativeUIOptions) {\n this.library = options.library;\n this.parameters = buildPresentParameters(options.library);\n this.actions = options.actions;\n }\n\n /**\n * The surface a `present` call paints into. It owns the vertical rhythm\n * between top-level blocks, which the host's message container does not\n * provide, and stays out of the way while it has nothing to show.\n */\n private readonly render = ({\n args,\n status,\n }: {\n args: unknown;\n status: { type: string };\n }): ReactNode => (\n <div data-aui=\"root\">\n {renderGenerativeUI(args, this.library, {\n status: uiStatus(status),\n ...(this.actions ? { dispatch: this.actions.dispatch } : {}),\n })}\n </div>\n );\n\n present(options?: PresentToolOptions): PresentTool {\n return {\n ...presentToolBase(this.parameters, options),\n unstable_backendDefault: { parameters: true },\n execute: async () => ({}),\n render: this.render,\n };\n }\n\n promptUser(): PromptUserTool {\n return {\n ...promptUserToolBase(this.parameters),\n unstable_backendDefault: { parameters: true },\n render: this.render,\n };\n }\n}\n"],"mappings":";;;;;;;;;AAmBA,SAAS,SAAS,QAA8C;CAC9D,OAAO,OAAO,SAAS,aAAa,SAAS;AAC/C;;;;;;;;;;;;AAaA,IAAa,mBAAb,MAA8B;CAC5B;CACA;CACA;CAEA,YAAY,SAAkC;EAC5C,KAAK,UAAU,QAAQ;EACvB,KAAK,aAAa,uBAAuB,QAAQ,OAAO;EACxD,KAAK,UAAU,QAAQ;CACzB;;;;;;CAOA,UAA2B,EACzB,MACA,aAKA,oBAAC,OAAD;EAAK,YAAS;EACX,UAAA,mBAAmB,MAAM,KAAK,SAAS;GACtC,QAAQ,SAAS,MAAM;GACvB,GAAI,KAAK,UAAU,EAAE,UAAU,KAAK,QAAQ,SAAS,IAAI,CAAC;EAC5D,CAAC;CACE,CAAA;CAGP,QAAQ,SAA2C;EACjD,OAAO;GACL,GAAG,gBAAgB,KAAK,YAAY,OAAO;GAC3C,yBAAyB,EAAE,YAAY,KAAK;GAC5C,SAAS,aAAa,CAAC;GACvB,QAAQ,KAAK;EACf;CACF;CAEA,aAA6B;EAC3B,OAAO;GACL,GAAG,mBAAmB,KAAK,UAAU;GACrC,yBAAyB,EAAE,YAAY,KAAK;GAC5C,QAAQ,KAAK;EACf;CACF;AACF"}
1
+ {"version":3,"file":"JSONGenerativeUI.client.js","names":[],"sources":["../src/JSONGenerativeUI.client.tsx"],"sourcesContent":["import type { ToolCallMessagePartProps } from \"@assistant-ui/react\";\nimport type { ReactNode } from \"react\";\nimport { buildPresentParameters } from \"./buildPresentParameters\";\nimport {\n presentToolBase,\n promptUserToolBase,\n type JSONGenerativeUIOptions,\n type PresentParameters,\n type PresentTool,\n type PresentToolOptions,\n type PromptUserTool,\n} from \"./JSONGenerativeUI.shared\";\nimport { type ActionRegistry } from \"./actionRegistry\";\nimport { renderGenerativeUI } from \"./renderGenerativeUI\";\nimport type { GenerativeUILibrary, GenerativeUIStatus } from \"./types\";\n\n/** Maps a tool-call part status to the generative-UI streaming status. Only a\n * `complete` call has fully-arrived args; `running` and `incomplete`\n * (aborted/errored, so args may be partial) both render as `\"streaming\"` so a\n * non-streaming component is never handed partial props. */\nfunction uiStatus(status: { type: string }): GenerativeUIStatus {\n return status.type === \"complete\" ? \"done\" : \"streaming\";\n}\n\n/**\n * Client build of {@link JSONGenerativeUI}, resolved through the package's\n * `default` export condition (browser and SSR).\n *\n * `present` is a frontend tool that renders the model's `{ $type, ...props }`\n * tree against the library and resolves immediately. `prompt_user` is a\n * human-in-the-loop tool: the model pauses and the rendered UI supplies the\n * result. Both draw the tree the same way, so they share one `render`. The\n * `actions` registry (if provided) is threaded into the render context so\n * interactive components can fire `$action` through `$dispatch`.\n */\nexport class JSONGenerativeUI {\n private readonly library: GenerativeUILibrary;\n private readonly parameters: PresentParameters;\n private readonly actions: ActionRegistry | undefined;\n private readonly completedPromptToolCallIds = new Set<string>();\n\n constructor(options: JSONGenerativeUIOptions) {\n this.library = options.library;\n this.parameters = buildPresentParameters(options.library);\n this.actions = options.actions;\n }\n\n /**\n * The surface a `present` call paints into. It owns the vertical rhythm\n * between top-level blocks, which the host's message container does not\n * provide, and stays out of the way while it has nothing to show.\n */\n private readonly render = (\n {\n args,\n status,\n addResult,\n result,\n toolCallId,\n unstable_recordInteraction,\n }: ToolCallMessagePartProps<Record<string, unknown>, any>,\n completesPrompt = false,\n ): ReactNode => {\n const actions = this.actions;\n const dispatch = actions\n ? (action: Parameters<ActionRegistry[\"dispatch\"]>[0]) => {\n if (unstable_recordInteraction) {\n try {\n void unstable_recordInteraction({\n type: \"action\",\n payload: action,\n }).catch(() => {});\n } catch {}\n }\n\n const actionResult = actions.dispatch(action);\n if (\n completesPrompt &&\n actionResult !== undefined &&\n result === undefined\n ) {\n void Promise.resolve(actionResult)\n .then((response) => {\n if (\n response !== undefined &&\n !this.completedPromptToolCallIds.has(toolCallId)\n ) {\n this.completedPromptToolCallIds.add(toolCallId);\n addResult(response);\n }\n })\n .catch(() => {});\n }\n return actionResult;\n }\n : undefined;\n\n return (\n <div data-aui=\"root\">\n {renderGenerativeUI(args, this.library, {\n status: uiStatus(status),\n ...(dispatch ? { dispatch } : {}),\n })}\n </div>\n );\n };\n\n present(options?: PresentToolOptions): PresentTool {\n return {\n ...presentToolBase(this.parameters, options),\n unstable_backendDefault: { parameters: true },\n execute: async () => ({}),\n render: this.render,\n };\n }\n\n promptUser(): PromptUserTool {\n return {\n ...promptUserToolBase(this.parameters),\n unstable_backendDefault: { parameters: true },\n render: (props) => this.render(props, true),\n };\n }\n}\n"],"mappings":";;;;;;;;;AAoBA,SAAS,SAAS,QAA8C;CAC9D,OAAO,OAAO,SAAS,aAAa,SAAS;AAC/C;;;;;;;;;;;;AAaA,IAAa,mBAAb,MAA8B;CAC5B;CACA;CACA;CACA,6CAA8C,IAAI,IAAY;CAE9D,YAAY,SAAkC;EAC5C,KAAK,UAAU,QAAQ;EACvB,KAAK,aAAa,uBAAuB,QAAQ,OAAO;EACxD,KAAK,UAAU,QAAQ;CACzB;;;;;;CAOA,UACE,EACE,MACA,QACA,WACA,QACA,YACA,8BAEF,kBAAkB,UACJ;EACd,MAAM,UAAU,KAAK;EACrB,MAAM,WAAW,WACZ,WAAsD;GACrD,IAAI,4BACF,IAAI;IACF,2BAAgC;KAC9B,MAAM;KACN,SAAS;IACX,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;GACnB,QAAQ,CAAC;GAGX,MAAM,eAAe,QAAQ,SAAS,MAAM;GAC5C,IACE,mBACA,iBAAiB,KAAA,KACjB,WAAW,KAAA,GAEX,QAAa,QAAQ,YAAY,CAAC,CAC/B,MAAM,aAAa;IAClB,IACE,aAAa,KAAA,KACb,CAAC,KAAK,2BAA2B,IAAI,UAAU,GAC/C;KACA,KAAK,2BAA2B,IAAI,UAAU;KAC9C,UAAU,QAAQ;IACpB;GACF,CAAC,CAAC,CACD,YAAY,CAAC,CAAC;GAEnB,OAAO;EACT,IACA,KAAA;EAEJ,OACE,oBAAC,OAAD;GAAK,YAAS;GACX,UAAA,mBAAmB,MAAM,KAAK,SAAS;IACtC,QAAQ,SAAS,MAAM;IACvB,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;GACjC,CAAC;EACE,CAAA;CAET;CAEA,QAAQ,SAA2C;EACjD,OAAO;GACL,GAAG,gBAAgB,KAAK,YAAY,OAAO;GAC3C,yBAAyB,EAAE,YAAY,KAAK;GAC5C,SAAS,aAAa,CAAC;GACvB,QAAQ,KAAK;EACf;CACF;CAEA,aAA6B;EAC3B,OAAO;GACL,GAAG,mBAAmB,KAAK,UAAU;GACrC,yBAAyB,EAAE,YAAY,KAAK;GAC5C,SAAS,UAAU,KAAK,OAAO,OAAO,IAAI;EAC5C;CACF;AACF"}
@@ -1,5 +1,4 @@
1
- import { JSONGenerativeUIOptions, PresentTool, PresentToolOptions, PromptUserTool } from "./JSONGenerativeUI.shared.js";
2
- //#region src/JSONGenerativeUI.server.d.ts
1
+ import { type JSONGenerativeUIOptions, type PresentTool, type PresentToolOptions, type PromptUserTool } from "./JSONGenerativeUI.shared.js";
3
2
  /**
4
3
  * Server build of {@link JSONGenerativeUI}, resolved through the package's
5
4
  * `react-server` export condition.
@@ -14,10 +13,9 @@ import { JSONGenerativeUIOptions, PresentTool, PresentToolOptions, PromptUserToo
14
13
  * tools; on the server it is structurally absent and never read.
15
14
  */
16
15
  export declare class JSONGenerativeUI {
17
- private readonly parameters;
18
- constructor(options: JSONGenerativeUIOptions);
19
- present(options?: PresentToolOptions): PresentTool;
20
- promptUser(): PromptUserTool;
16
+ private readonly parameters;
17
+ constructor(options: JSONGenerativeUIOptions);
18
+ present(options?: PresentToolOptions): PresentTool;
19
+ promptUser(): PromptUserTool;
21
20
  }
22
- //#endregion
23
21
  //# sourceMappingURL=JSONGenerativeUI.server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JSONGenerativeUI.server.d.ts","names":[],"sources":["../src/JSONGenerativeUI.server.tsx"],"mappings":";;;;;;;;;;;;;;;qBAwBa;mBACM;EAEL,YAAA,SAAS;EAIrB,QAAQ,UAAU,qBAAqB;EAIvC,cAAc"}
1
+ {"version":3,"file":"JSONGenerativeUI.server.d.ts","sourceRoot":"","sources":["../src/JSONGenerativeUI.server.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,uBAAuB,EAE5B,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,qCAAkC;AAEnC;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;gBAEnC,OAAO,EAAE,uBAAuB;IAI5C,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW;IAIlD,UAAU,IAAI,cAAc;CAG7B"}
@@ -1,38 +1,37 @@
1
- import { ActionRegistry } from "./actionRegistry.js";
2
- import { GenerativeUILibrary } from "./types.js";
3
- import { ToolDefinition } from "@assistant-ui/react";
4
- import { JSONSchema7 } from "json-schema";
5
- //#region src/JSONGenerativeUI.shared.d.ts
1
+ import type { ToolDefinition } from "@assistant-ui/react";
2
+ import type { JSONSchema7 } from "json-schema";
3
+ import type { ActionRegistry } from "./actionRegistry.js";
4
+ import type { GenerativeUILibrary } from "./types.js";
6
5
  /** Options for {@link JSONGenerativeUI}. */
7
6
  export type JSONGenerativeUIOptions = {
8
- /**
9
- * The components the model is allowed to render, keyed by the `$type` it
10
- * selects them with. Author it with `defineGenerativeComponents({ ... })` so a
11
- * `"use generative"` build can split each `render` from its `properties`.
12
- */
13
- library: GenerativeUILibrary;
14
- /**
15
- * Host-provided map from `$action.type` to its handler. Interactive
16
- * components (`Button`/`Select`/`Input`/`DatePicker`) call `$dispatch($action)`
17
- * on their event, which resolves through this registry. Omit it for a
18
- * read-only render where model-emitted actions degrade to a no-op.
19
- */
20
- actions?: ActionRegistry;
7
+ /**
8
+ * The components the model is allowed to render, keyed by the `$type` it
9
+ * selects them with. Author it with `defineGenerativeComponents({ ... })` so a
10
+ * `"use generative"` build can split each `render` from its `properties`.
11
+ */
12
+ library: GenerativeUILibrary;
13
+ /**
14
+ * Host-provided map from `$action.type` to its handler. Interactive
15
+ * components (`Button`/`Select`/`Input`/`DatePicker`) call `$dispatch($action)`
16
+ * on their event, which resolves through this registry. Omit it for a
17
+ * read-only render where model-emitted actions degrade to a no-op.
18
+ */
19
+ actions?: ActionRegistry;
21
20
  };
22
21
  /** Options for {@link JSONGenerativeUI.present}. */
23
22
  export type PresentToolOptions = {
24
- /**
25
- * Set `"standalone"` to render the component on its own surface (outside the
26
- * chain-of-thought trace), e.g. a full-bleed artifact like a card. Omit it for
27
- * the default inline rendering — there is no `"inline"` value because that is
28
- * already the default.
29
- */
30
- display?: "standalone";
23
+ /**
24
+ * Set `"standalone"` to render the component on its own surface (outside the
25
+ * chain-of-thought trace), e.g. a full-bleed artifact like a card. Omit it for
26
+ * the default inline rendering — there is no `"inline"` value because that is
27
+ * already the default.
28
+ */
29
+ display?: "standalone";
31
30
  };
32
31
  type BackendDefaultMetadata = {
33
- unstable_backendDefault?: {
34
- parameters?: boolean;
35
- };
32
+ unstable_backendDefault?: {
33
+ parameters?: boolean;
34
+ };
36
35
  };
37
36
  /** The `present` tool, as the model sees it (no client `render`/`execute`). */
38
37
  export type PresentTool = ToolDefinition<Record<string, unknown>, Record<string, never>> & BackendDefaultMetadata;
@@ -46,19 +45,19 @@ export type PresentParameters = JSONSchema7;
46
45
  * Takes the already-built `parameters` so it isn't recomputed per tool.
47
46
  */
48
47
  export declare function presentToolBase(parameters: PresentParameters, options?: PresentToolOptions): {
49
- display?: "standalone";
50
- type: "frontend";
51
- description: string;
52
- parameters: JSONSchema7;
48
+ display?: "standalone";
49
+ type: "frontend";
50
+ description: string;
51
+ parameters: JSONSchema7;
53
52
  };
54
53
  /**
55
54
  * The schema-only half of the `prompt_user` tool, shared by both builds. The
56
55
  * server build returns exactly this; the client build adds `render`.
57
56
  */
58
57
  export declare function promptUserToolBase(parameters: PresentParameters): {
59
- type: "human";
60
- description: string;
61
- parameters: JSONSchema7;
58
+ type: "human";
59
+ description: string;
60
+ parameters: JSONSchema7;
62
61
  };
63
- //#endregion
62
+ export {};
64
63
  //# sourceMappingURL=JSONGenerativeUI.shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JSONGenerativeUI.shared.d.ts","names":[],"sources":["../src/JSONGenerativeUI.shared.ts"],"mappings":";;;;;;YAMY;;;;;;EAMV,SAAS;;;;;;;EAOT,UAAU;;;YAIA;;;;;;;EAOV;;KAGG;EACH;IACE;;;;YAKQ,cAAc,eACxB,yBACA,yBAEA;;YAGU,iBAAiB,eAAe,oCAC1C;;YAYU,oBAAoB;;;;;;wBAOhB,gBACd,YAAY,mBACZ,UAAU;;;;;;;;;;wBAcI,mBAAmB,YAAY;;;cAAA"}
1
+ {"version":3,"file":"JSONGenerativeUI.shared.d.ts","sourceRoot":"","sources":["../src/JSONGenerativeUI.shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,4BAAyB;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAgB;AAEnD,4CAA4C;AAC5C,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;OAIG;IACH,OAAO,EAAE,mBAAmB,CAAC;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,uBAAuB,CAAC,EAAE;QACxB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,cAAc,CACtC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CACtB,GACC,sBAAsB,CAAC;AAEzB,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,GAC3E,sBAAsB,CAAC;AAWzB,4FAA4F;AAC5F,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,iBAAiB,EAC7B,OAAO,CAAC,EAAE,kBAAkB;;;;;EAQ7B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB;;;;EAM/D"}
@@ -1,9 +1,9 @@
1
- import { UIElement } from "../ir.js";
2
- import { A2uiSurfaceState } from "./types.js";
3
- //#region src/a2ui/convert.d.ts
4
- export declare function convertSurfaceToUISpec(surface: A2uiSurfaceState): {
5
- spec: UIElement | null;
6
- warnings: string[];
1
+ import { type UIElement } from "../ir.js";
2
+ import { type A2uiSurfaceState } from "./types.js";
3
+ export declare function convertSurfaceToUISpec(surface: A2uiSurfaceState, options?: {
4
+ readonly keepUnknownComponents?: boolean;
5
+ }): {
6
+ spec: UIElement | null;
7
+ warnings: string[];
7
8
  };
8
- //#endregion
9
9
  //# sourceMappingURL=convert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convert.d.ts","names":[],"sources":["../../src/a2ui/convert.ts"],"mappings":";;;wBAscgB,uBAAuB,SAAS;EAC9C,MAAM;EACN"}
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/a2ui/convert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,SAAS,EAAE,iBAAc;AACnD,OAAO,EAEL,KAAK,gBAAgB,EAEtB,mBAAgB;AA8kBjB,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE;IAAE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAAO,GACzD;IACD,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CA+BA"}
@@ -1,3 +1,4 @@
1
+ import { ICON_NAMES } from "../ir.js";
1
2
  import { A2UI_SURFACE_ID } from "./types.js";
2
3
  //#region src/a2ui/convert.ts
3
4
  const DEPTH_CAP = 32;
@@ -6,13 +7,23 @@ const NODE_BUDGET = 5e3;
6
7
  const SUPPORTED_COMPONENTS = /* @__PURE__ */ new Set([
7
8
  "Text",
8
9
  "Image",
10
+ "Icon",
9
11
  "Row",
10
12
  "Column",
13
+ "List",
11
14
  "Card",
12
15
  "Divider",
13
16
  "Button",
14
17
  "TextField",
15
- "CheckBox"
18
+ "CheckBox",
19
+ "ChoicePicker",
20
+ "DateTimeInput"
21
+ ]);
22
+ const ICON_NAME_SET = new Set(ICON_NAMES);
23
+ const ICON_SIZE_SET = /* @__PURE__ */ new Set([
24
+ "sm",
25
+ "md",
26
+ "lg"
16
27
  ]);
17
28
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
18
29
  const isPlainObject = (value) => {
@@ -114,6 +125,15 @@ const mappedAction = (node, props, dataSource, context) => {
114
125
  ...resolvedContext !== void 0 ? { context: resolvedContext } : {}
115
126
  };
116
127
  };
128
+ const choiceOptions = (value) => {
129
+ if (!Array.isArray(value)) return [];
130
+ const options = [];
131
+ for (const option of value) if (isRecord(option) && typeof option["label"] === "string" && typeof option["value"] === "string") options.push({
132
+ label: option["label"],
133
+ value: option["value"]
134
+ });
135
+ return options;
136
+ };
117
137
  const mappedProps = (node, props, dataSource, context) => {
118
138
  const component = node["component"];
119
139
  if (component === "Text") {
@@ -134,7 +154,11 @@ const mappedProps = (node, props, dataSource, context) => {
134
154
  }
135
155
  if (component === "Image") {
136
156
  const src = stringProp(props, ["src", "url"]);
137
- const alt = stringProp(props, ["alt", "altText"]);
157
+ const alt = stringProp(props, [
158
+ "alt",
159
+ "altText",
160
+ "description"
161
+ ]);
138
162
  const size = props["size"];
139
163
  const round = props["round"];
140
164
  return {
@@ -145,6 +169,16 @@ const mappedProps = (node, props, dataSource, context) => {
145
169
  ...typeof round === "boolean" ? { round } : {}
146
170
  };
147
171
  }
172
+ if (component === "Icon") {
173
+ const name = stringProp(props, ["name"]);
174
+ if (!name || !ICON_NAME_SET.has(name)) return void 0;
175
+ const size = props["size"];
176
+ return {
177
+ $type: "Icon",
178
+ name,
179
+ ...typeof size === "string" && ICON_SIZE_SET.has(size) ? { size } : {}
180
+ };
181
+ }
148
182
  if (component === "Row") {
149
183
  const gap = props["gap"];
150
184
  const align = firstDefined(props, ["align", "alignment"]);
@@ -165,6 +199,15 @@ const mappedProps = (node, props, dataSource, context) => {
165
199
  ...typeof align === "string" ? { align } : {}
166
200
  };
167
201
  }
202
+ if (component === "List") {
203
+ const direction = props["direction"];
204
+ const align = props["align"];
205
+ if (direction === "horizontal") return {
206
+ $type: "Row",
207
+ ...typeof align === "string" ? { align } : {}
208
+ };
209
+ return { $type: "ListView" };
210
+ }
168
211
  if (component === "Card") {
169
212
  const title = props["title"];
170
213
  const padding = props["padding"];
@@ -222,14 +265,49 @@ const mappedProps = (node, props, dataSource, context) => {
222
265
  ...typeof defaultChecked === "boolean" ? { defaultChecked } : {}
223
266
  };
224
267
  }
268
+ if (component === "ChoicePicker") {
269
+ const options = choiceOptions(props["options"]);
270
+ const value = props["value"];
271
+ const defaultValue = typeof value === "string" ? value : Array.isArray(value) && typeof value[0] === "string" ? value[0] : void 0;
272
+ if (props["variant"] === "radio" || props["variant"] === "single" || props["variant"] === "singleSelection" || props["displayStyle"] === "radio" || props["variant"] === "mutuallyExclusive" && props["displayStyle"] !== "chips") return {
273
+ $type: "RadioGroup",
274
+ options,
275
+ ...label !== void 0 ? { label } : {},
276
+ ...name !== void 0 ? { name } : {},
277
+ ...defaultValue !== void 0 ? { defaultValue } : {}
278
+ };
279
+ const placeholder = stringProp(props, ["placeholder"]);
280
+ return {
281
+ $type: "Select",
282
+ options,
283
+ ...placeholder !== void 0 ? { placeholder } : {},
284
+ ...label !== void 0 ? { label } : {},
285
+ ...name !== void 0 ? { name } : {}
286
+ };
287
+ }
288
+ if (component === "DateTimeInput") {
289
+ const value = stringProp(props, ["value"]);
290
+ const min = stringProp(props, ["min"]);
291
+ const max = stringProp(props, ["max"]);
292
+ return {
293
+ $type: "DatePicker",
294
+ ...value !== void 0 ? { value } : {},
295
+ ...min !== void 0 ? { min } : {},
296
+ ...max !== void 0 ? { max } : {},
297
+ ...label !== void 0 ? { label } : {},
298
+ ...name !== void 0 ? { name } : {}
299
+ };
300
+ }
225
301
  };
226
- const convertTemplate = (node, templateChildren, dataSource, context, depth, visited) => {
302
+ const convertTemplate = (node, templateChildren, dataSource, context, depth, visited, retained, mappedContainer) => {
227
303
  if (!reserveNode(context)) return null;
304
+ const horizontalList = node["component"] === "List" && materialize(node["direction"], dataSource) === "horizontal";
305
+ const container = mappedContainer ?? retained ?? { $type: horizontalList ? "Row" : "ListView" };
228
306
  const list = resolvePointer(dataSource, templateChildren.template.path);
229
307
  if (!Array.isArray(list)) {
230
308
  context.warnings.push(`Template on component "${String(node["id"] ?? "")}" did not resolve to a list.`);
231
309
  return {
232
- $type: "ListView",
310
+ ...container,
233
311
  children: []
234
312
  };
235
313
  }
@@ -240,15 +318,17 @@ const convertTemplate = (node, templateChildren, dataSource, context, depth, vis
240
318
  }
241
319
  const children = [];
242
320
  for (let index = 0; index < itemCount; index++) {
243
- if (!reserveNode(context)) break;
321
+ if (!retained && !horizontalList && !reserveNode(context)) break;
244
322
  const child = convertComponent(templateChildren.template.componentId, list[index], context, depth + 1, visited);
245
- children.push({
323
+ if (retained || horizontalList) {
324
+ if (child) children.push(child);
325
+ } else children.push({
246
326
  $type: "ListViewItem",
247
327
  ...child ? { children: child } : {}
248
328
  });
249
329
  }
250
330
  return {
251
- $type: "ListView",
331
+ ...container,
252
332
  children
253
333
  };
254
334
  };
@@ -272,13 +352,16 @@ function convertComponent(componentId, dataSource, context, depth, visited) {
272
352
  const component = node["component"];
273
353
  visited.add(componentId);
274
354
  try {
275
- const templateChildren = node["children"];
276
- if (isTemplateChildren(templateChildren)) return convertTemplate(node, templateChildren, dataSource, context, depth, visited);
277
- if (typeof component !== "string" || !SUPPORTED_COMPONENTS.has(component)) {
355
+ if (typeof component !== "string") {
278
356
  context.warnings.push(`Unknown A2UI component "${String(component ?? "")}" was skipped.`);
279
357
  return null;
280
358
  }
281
- if (!reserveNode(context)) return null;
359
+ const templateChildren = node["children"];
360
+ const hasTemplate = isTemplateChildren(templateChildren);
361
+ if (!SUPPORTED_COMPONENTS.has(component) && !context.keepUnknownComponents && !hasTemplate) {
362
+ context.warnings.push(`Unknown A2UI component "${component}" was skipped.`);
363
+ return null;
364
+ }
282
365
  const props = {};
283
366
  for (const [key, value] of Object.entries(node)) {
284
367
  if (key === "id" || key === "component" || key === "children") continue;
@@ -286,17 +369,32 @@ function convertComponent(componentId, dataSource, context, depth, visited) {
286
369
  if (resolved !== void 0) setOwnProperty(props, key, resolved);
287
370
  }
288
371
  const mapped = mappedProps(node, props, dataSource, context);
289
- if (!mapped) return null;
372
+ if (!mapped && SUPPORTED_COMPONENTS.has(component)) {
373
+ context.warnings.push(`A2UI component "${component}" could not be mapped and was skipped.`);
374
+ return null;
375
+ }
376
+ const retained = !mapped && context.keepUnknownComponents ? {
377
+ $type: component,
378
+ ...Object.fromEntries(Object.entries(props).filter(([key]) => !key.startsWith("$")))
379
+ } : void 0;
380
+ if (hasTemplate) return convertTemplate(node, templateChildren, dataSource, context, depth, visited, retained, component === "List" ? mapped : void 0);
381
+ if (!reserveNode(context)) return null;
382
+ const converted = mapped ?? retained;
383
+ if (!converted) return null;
290
384
  const children = childrenOf(node, dataSource, context, depth, visited);
385
+ const listChildren = component === "List" && mapped?.$type === "ListView" ? children.map((child) => ({
386
+ $type: "ListViewItem",
387
+ children: child
388
+ })) : children;
291
389
  return {
292
- ...mapped,
293
- ...children.length > 0 ? { children } : {}
390
+ ...converted,
391
+ ...listChildren.length > 0 ? { children: listChildren } : {}
294
392
  };
295
393
  } finally {
296
394
  visited.delete(componentId);
297
395
  }
298
396
  }
299
- function convertSurfaceToUISpec(surface) {
397
+ function convertSurfaceToUISpec(surface, options = {}) {
300
398
  const warnings = [];
301
399
  if (!surface.components.has("root")) return {
302
400
  spec: null,
@@ -309,7 +407,8 @@ function convertSurfaceToUISpec(surface) {
309
407
  emittedNodes: 0,
310
408
  depthWarned: false,
311
409
  budgetWarned: false,
312
- templateCapWarned: false
410
+ templateCapWarned: false,
411
+ keepUnknownComponents: options.keepUnknownComponents === true
313
412
  };
314
413
  try {
315
414
  return {