@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.
- package/dist/JSONGenerativeUI.client.d.ts +14 -15
- package/dist/JSONGenerativeUI.client.d.ts.map +1 -1
- package/dist/JSONGenerativeUI.client.js +28 -8
- package/dist/JSONGenerativeUI.client.js.map +1 -1
- package/dist/JSONGenerativeUI.server.d.ts +5 -7
- package/dist/JSONGenerativeUI.server.d.ts.map +1 -1
- package/dist/JSONGenerativeUI.shared.d.ts +35 -36
- package/dist/JSONGenerativeUI.shared.d.ts.map +1 -1
- package/dist/a2ui/convert.d.ts +7 -7
- package/dist/a2ui/convert.d.ts.map +1 -1
- package/dist/a2ui/convert.js +115 -16
- package/dist/a2ui/convert.js.map +1 -1
- package/dist/a2ui/reducer.d.ts +1 -3
- package/dist/a2ui/reducer.d.ts.map +1 -1
- package/dist/a2ui/reducer.js +8 -0
- package/dist/a2ui/reducer.js.map +1 -1
- package/dist/a2ui/snapshot.d.ts +3 -0
- package/dist/a2ui/snapshot.d.ts.map +1 -0
- package/dist/a2ui/snapshot.js +33 -0
- package/dist/a2ui/snapshot.js.map +1 -0
- package/dist/a2ui/types.d.ts +50 -40
- package/dist/a2ui/types.d.ts.map +1 -1
- package/dist/a2ui/types.js.map +1 -1
- package/dist/a2ui.d.ts +5 -4
- package/dist/a2ui.d.ts.map +1 -0
- package/dist/a2ui.js +2 -1
- package/dist/actionRegistry.d.ts +12 -14
- package/dist/actionRegistry.d.ts.map +1 -1
- package/dist/actionRegistry.js.map +1 -1
- package/dist/buildPresentParameters.d.ts +2 -4
- package/dist/buildPresentParameters.d.ts.map +1 -1
- package/dist/buildPresentParameters.js +16 -4
- package/dist/buildPresentParameters.js.map +1 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/convert/boundSpec.d.ts +0 -2
- package/dist/convert/boundSpec.d.ts.map +1 -1
- package/dist/convert/copyBounded.d.ts +2 -4
- package/dist/convert/copyBounded.d.ts.map +1 -1
- package/dist/convert/isElement.d.ts +1 -3
- package/dist/convert/isElement.d.ts.map +1 -1
- package/dist/convert/takeRun.d.ts +3 -5
- package/dist/convert/takeRun.d.ts.map +1 -1
- package/dist/defineGenerativeComponents.d.ts +1 -3
- package/dist/defineGenerativeComponents.d.ts.map +1 -1
- package/dist/generativeUIToJSX.d.ts +4 -6
- package/dist/generativeUIToJSX.d.ts.map +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.d.ts.map +1 -0
- package/dist/index.server.d.ts +3 -13
- package/dist/index.server.d.ts.map +1 -0
- package/dist/index.shared.d.ts +15 -11
- package/dist/index.shared.d.ts.map +1 -0
- package/dist/ir.d.ts +17 -19
- package/dist/ir.d.ts.map +1 -1
- package/dist/renderGenerativeUI.d.ts +2 -4
- package/dist/renderGenerativeUI.d.ts.map +1 -1
- package/dist/scopeSchema.d.ts +6 -0
- package/dist/scopeSchema.d.ts.map +1 -0
- package/dist/scopeSchema.js +56 -0
- package/dist/scopeSchema.js.map +1 -0
- package/dist/slack/constants.d.ts +8 -9
- package/dist/slack/constants.d.ts.map +1 -1
- package/dist/slack/decodeBlockAction.d.ts +1 -3
- package/dist/slack/decodeBlockAction.d.ts.map +1 -1
- package/dist/slack/fromSlackBlocks.d.ts +1 -3
- package/dist/slack/fromSlackBlocks.d.ts.map +1 -1
- package/dist/slack/toSlackBlocks.d.ts +1 -3
- package/dist/slack/toSlackBlocks.d.ts.map +1 -1
- package/dist/slack/toSlackBlocks.js +1 -1
- package/dist/slack/types.d.ts +78 -80
- package/dist/slack/types.d.ts.map +1 -1
- package/dist/slack.d.ts +5 -5
- package/dist/slack.d.ts.map +1 -0
- package/dist/teams/constants.d.ts +1 -3
- package/dist/teams/constants.d.ts.map +1 -1
- package/dist/teams/decodeSubmitData.d.ts +1 -3
- package/dist/teams/decodeSubmitData.d.ts.map +1 -1
- package/dist/teams/toAdaptiveCard.d.ts +4 -6
- package/dist/teams/toAdaptiveCard.d.ts.map +1 -1
- package/dist/teams/toTeamsAttachments.d.ts +1 -3
- package/dist/teams/toTeamsAttachments.d.ts.map +1 -1
- package/dist/teams/types.d.ts +108 -109
- package/dist/teams/types.d.ts.map +1 -1
- package/dist/teams.d.ts +5 -5
- package/dist/teams.d.ts.map +1 -0
- package/dist/types.d.ts +36 -37
- package/dist/types.d.ts.map +1 -1
- package/dist/vocabulary/alert.d.ts +21 -23
- package/dist/vocabulary/alert.d.ts.map +1 -1
- package/dist/vocabulary/collectFormValues.d.ts +8 -10
- package/dist/vocabulary/collectFormValues.d.ts.map +1 -1
- package/dist/vocabulary/data.d.ts +45 -47
- package/dist/vocabulary/data.d.ts.map +1 -1
- package/dist/vocabulary/dispatch.d.ts +2 -4
- package/dist/vocabulary/dispatch.d.ts.map +1 -1
- package/dist/vocabulary/fact.d.ts +8 -10
- package/dist/vocabulary/fact.d.ts.map +1 -1
- package/dist/vocabulary/form.d.ts +7 -9
- package/dist/vocabulary/form.d.ts.map +1 -1
- package/dist/vocabulary/icon.d.ts +37 -39
- package/dist/vocabulary/icon.d.ts.map +1 -1
- package/dist/vocabulary/index.d.ts +1 -3
- package/dist/vocabulary/index.d.ts.map +1 -1
- package/dist/vocabulary/interactive.d.ts +87 -86
- package/dist/vocabulary/interactive.d.ts.map +1 -1
- package/dist/vocabulary/interactive.js +4 -4
- package/dist/vocabulary/interactive.js.map +1 -1
- package/dist/vocabulary/layout.d.ts +75 -77
- package/dist/vocabulary/layout.d.ts.map +1 -1
- package/dist/vocabulary/list.d.ts +10 -12
- package/dist/vocabulary/list.d.ts.map +1 -1
- package/dist/vocabulary/media.d.ts +21 -23
- package/dist/vocabulary/media.d.ts.map +1 -1
- package/dist/vocabulary/text.d.ts +53 -55
- package/dist/vocabulary/text.d.ts.map +1 -1
- package/dist/vocabulary/toTextContent.d.ts +0 -2
- package/dist/vocabulary/toTextContent.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/JSONGenerativeUI.client.tsx +57 -15
- package/src/JSONGenerativeUI.test.tsx +298 -4
- package/src/a2ui/convert.test.ts +496 -0
- package/src/a2ui/convert.ts +170 -25
- package/src/a2ui/reducer.test.ts +18 -0
- package/src/a2ui/reducer.ts +16 -0
- package/src/a2ui/snapshot.test.ts +52 -0
- package/src/a2ui/snapshot.ts +52 -0
- package/src/a2ui/types.ts +16 -0
- package/src/a2ui.ts +2 -0
- package/src/actionRegistry.ts +5 -5
- package/src/buildPresentParameters.test.ts +246 -0
- package/src/buildPresentParameters.ts +18 -3
- package/src/scopeSchema.test.ts +72 -0
- package/src/scopeSchema.ts +71 -0
- package/src/vocabulary/interactive.dispatch.test.tsx +17 -3
- package/src/vocabulary/interactive.test.tsx +19 -0
- 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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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","
|
|
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 }
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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","
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
type: "human";
|
|
59
|
+
description: string;
|
|
60
|
+
parameters: JSONSchema7;
|
|
62
61
|
};
|
|
63
|
-
|
|
62
|
+
export {};
|
|
64
63
|
//# sourceMappingURL=JSONGenerativeUI.shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSONGenerativeUI.shared.d.ts","
|
|
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"}
|
package/dist/a2ui/convert.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { UIElement } from "../ir.js";
|
|
2
|
-
import { A2uiSurfaceState } from "./types.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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","
|
|
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"}
|
package/dist/a2ui/convert.js
CHANGED
|
@@ -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, [
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
...
|
|
293
|
-
...
|
|
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 {
|