@assistant-ui/react-generative-ui 0.0.23 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/a2ui.d.ts +1 -4
- package/dist/a2ui.d.ts.map +1 -1
- package/dist/a2ui.js +1 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/index.server.d.ts +1 -2
- package/dist/index.server.d.ts.map +1 -1
- package/dist/index.server.js +1 -10
- package/dist/ir.d.ts +1 -111
- package/dist/ir.d.ts.map +1 -1
- package/dist/ir.js +1 -175
- package/dist/slack.d.ts +1 -4
- package/dist/slack.d.ts.map +1 -1
- package/dist/slack.js +1 -4
- package/dist/teams.d.ts +1 -4
- package/dist/teams.d.ts.map +1 -1
- package/dist/teams.js +1 -4
- package/package.json +5 -5
- package/src/a2ui.ts +1 -22
- package/src/index.server.ts +1 -2
- package/src/index.test.ts +75 -0
- package/src/index.ts +1 -2
- package/src/ir.ts +1 -279
- package/src/slack.ts +1 -39
- package/src/teams.ts +1 -35
- package/dist/JSONGenerativeUI.client.d.ts +0 -28
- package/dist/JSONGenerativeUI.client.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.client.js +0 -101
- package/dist/JSONGenerativeUI.client.js.map +0 -1
- package/dist/JSONGenerativeUI.server.d.ts +0 -21
- package/dist/JSONGenerativeUI.server.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.server.js +0 -32
- package/dist/JSONGenerativeUI.server.js.map +0 -1
- package/dist/JSONGenerativeUI.shared.d.ts +0 -63
- package/dist/JSONGenerativeUI.shared.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.shared.js +0 -31
- package/dist/JSONGenerativeUI.shared.js.map +0 -1
- package/dist/RadioGroupScope.d.ts +0 -6
- package/dist/RadioGroupScope.d.ts.map +0 -1
- package/dist/RadioGroupScope.js +0 -25
- package/dist/RadioGroupScope.js.map +0 -1
- package/dist/a2ui/BindingContext.d.ts +0 -11
- package/dist/a2ui/BindingContext.d.ts.map +0 -1
- package/dist/a2ui/BindingContext.js +0 -12
- package/dist/a2ui/BindingContext.js.map +0 -1
- package/dist/a2ui/PresentRenderer.d.ts +0 -11
- package/dist/a2ui/PresentRenderer.d.ts.map +0 -1
- package/dist/a2ui/PresentRenderer.js +0 -39
- package/dist/a2ui/PresentRenderer.js.map +0 -1
- package/dist/a2ui/convert.d.ts +0 -15
- package/dist/a2ui/convert.d.ts.map +0 -1
- package/dist/a2ui/convert.js +0 -728
- package/dist/a2ui/convert.js.map +0 -1
- package/dist/a2ui/dataModel.d.ts +0 -9
- package/dist/a2ui/dataModel.d.ts.map +0 -1
- package/dist/a2ui/dataModel.js +0 -44
- package/dist/a2ui/dataModel.js.map +0 -1
- package/dist/a2ui/reducer.d.ts +0 -8
- package/dist/a2ui/reducer.d.ts.map +0 -1
- package/dist/a2ui/reducer.js +0 -242
- package/dist/a2ui/reducer.js.map +0 -1
- package/dist/a2ui/snapshot.d.ts +0 -3
- package/dist/a2ui/snapshot.d.ts.map +0 -1
- package/dist/a2ui/snapshot.js +0 -33
- package/dist/a2ui/snapshot.js.map +0 -1
- package/dist/a2ui/types.d.ts +0 -88
- package/dist/a2ui/types.d.ts.map +0 -1
- package/dist/a2ui/types.js +0 -6
- package/dist/a2ui/types.js.map +0 -1
- package/dist/a2ui/valueFunctions.d.ts +0 -16
- package/dist/a2ui/valueFunctions.d.ts.map +0 -1
- package/dist/a2ui/valueFunctions.js +0 -332
- package/dist/a2ui/valueFunctions.js.map +0 -1
- package/dist/actionRegistry.d.ts +0 -29
- package/dist/actionRegistry.d.ts.map +0 -1
- package/dist/actionRegistry.js +0 -41
- package/dist/actionRegistry.js.map +0 -1
- package/dist/answeredValues.d.ts +0 -16
- package/dist/answeredValues.d.ts.map +0 -1
- package/dist/answeredValues.js +0 -37
- package/dist/answeredValues.js.map +0 -1
- package/dist/buildPresentParameters.d.ts +0 -21
- package/dist/buildPresentParameters.d.ts.map +0 -1
- package/dist/buildPresentParameters.js +0 -95
- package/dist/buildPresentParameters.js.map +0 -1
- package/dist/constants.d.ts +0 -15
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -19
- package/dist/constants.js.map +0 -1
- package/dist/convert/boundSpec.d.ts +0 -48
- package/dist/convert/boundSpec.d.ts.map +0 -1
- package/dist/convert/boundSpec.js +0 -108
- package/dist/convert/boundSpec.js.map +0 -1
- package/dist/convert/copyBounded.d.ts +0 -25
- package/dist/convert/copyBounded.d.ts.map +0 -1
- package/dist/convert/copyBounded.js +0 -38
- package/dist/convert/copyBounded.js.map +0 -1
- package/dist/convert/isElement.d.ts +0 -3
- package/dist/convert/isElement.d.ts.map +0 -1
- package/dist/convert/isElement.js +0 -6
- package/dist/convert/isElement.js.map +0 -1
- package/dist/convert/takeRun.d.ts +0 -6
- package/dist/convert/takeRun.d.ts.map +0 -1
- package/dist/convert/takeRun.js +0 -20
- package/dist/convert/takeRun.js.map +0 -1
- package/dist/defineGenerativeComponents.d.ts +0 -29
- package/dist/defineGenerativeComponents.d.ts.map +0 -1
- package/dist/defineGenerativeComponents.js +0 -34
- package/dist/defineGenerativeComponents.js.map +0 -1
- package/dist/fieldReferences.d.ts +0 -9
- package/dist/fieldReferences.d.ts.map +0 -1
- package/dist/fieldReferences.js +0 -53
- package/dist/fieldReferences.js.map +0 -1
- package/dist/generativeUIToJSX.d.ts +0 -18
- package/dist/generativeUIToJSX.d.ts.map +0 -1
- package/dist/generativeUIToJSX.js +0 -76
- package/dist/generativeUIToJSX.js.map +0 -1
- package/dist/index.shared.d.ts +0 -15
- package/dist/index.shared.d.ts.map +0 -1
- package/dist/index.shared.js +0 -9
- package/dist/ir.js.map +0 -1
- package/dist/renderGenerativeUI.d.ts +0 -14
- package/dist/renderGenerativeUI.d.ts.map +0 -1
- package/dist/renderGenerativeUI.js +0 -83
- package/dist/renderGenerativeUI.js.map +0 -1
- package/dist/scopeSchema.d.ts +0 -6
- package/dist/scopeSchema.d.ts.map +0 -1
- package/dist/scopeSchema.js +0 -56
- package/dist/scopeSchema.js.map +0 -1
- package/dist/slack/constants.d.ts +0 -93
- package/dist/slack/constants.d.ts.map +0 -1
- package/dist/slack/constants.js +0 -146
- package/dist/slack/constants.js.map +0 -1
- package/dist/slack/decodeBlockAction.d.ts +0 -10
- package/dist/slack/decodeBlockAction.d.ts.map +0 -1
- package/dist/slack/decodeBlockAction.js +0 -129
- package/dist/slack/decodeBlockAction.js.map +0 -1
- package/dist/slack/fromSlackBlocks.d.ts +0 -27
- package/dist/slack/fromSlackBlocks.d.ts.map +0 -1
- package/dist/slack/fromSlackBlocks.js +0 -483
- package/dist/slack/fromSlackBlocks.js.map +0 -1
- package/dist/slack/toSlackBlocks.d.ts +0 -4
- package/dist/slack/toSlackBlocks.d.ts.map +0 -1
- package/dist/slack/toSlackBlocks.js +0 -901
- package/dist/slack/toSlackBlocks.js.map +0 -1
- package/dist/slack/types.d.ts +0 -204
- package/dist/slack/types.d.ts.map +0 -1
- package/dist/slack/types.js +0 -0
- package/dist/teams/constants.d.ts +0 -34
- package/dist/teams/constants.d.ts.map +0 -1
- package/dist/teams/constants.js +0 -68
- package/dist/teams/constants.js.map +0 -1
- package/dist/teams/decodeSubmitData.d.ts +0 -26
- package/dist/teams/decodeSubmitData.d.ts.map +0 -1
- package/dist/teams/decodeSubmitData.js +0 -70
- package/dist/teams/decodeSubmitData.js.map +0 -1
- package/dist/teams/temporalId.d.ts +0 -5
- package/dist/teams/temporalId.d.ts.map +0 -1
- package/dist/teams/temporalId.js +0 -28
- package/dist/teams/temporalId.js.map +0 -1
- package/dist/teams/toAdaptiveCard.d.ts +0 -45
- package/dist/teams/toAdaptiveCard.d.ts.map +0 -1
- package/dist/teams/toAdaptiveCard.js +0 -642
- package/dist/teams/toAdaptiveCard.js.map +0 -1
- package/dist/teams/toTeamsAttachments.d.ts +0 -10
- package/dist/teams/toTeamsAttachments.d.ts.map +0 -1
- package/dist/teams/toTeamsAttachments.js +0 -99
- package/dist/teams/toTeamsAttachments.js.map +0 -1
- package/dist/teams/types.d.ts +0 -224
- package/dist/teams/types.d.ts.map +0 -1
- package/dist/teams/types.js +0 -0
- package/dist/temporal.d.ts +0 -33
- package/dist/temporal.d.ts.map +0 -1
- package/dist/temporal.js +0 -152
- package/dist/temporal.js.map +0 -1
- package/dist/types.d.ts +0 -99
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -0
- package/dist/vocabulary/alert.d.ts +0 -32
- package/dist/vocabulary/alert.d.ts.map +0 -1
- package/dist/vocabulary/alert.js +0 -160
- package/dist/vocabulary/alert.js.map +0 -1
- package/dist/vocabulary/collectFormValues.d.ts +0 -23
- package/dist/vocabulary/collectFormValues.d.ts.map +0 -1
- package/dist/vocabulary/collectFormValues.js +0 -44
- package/dist/vocabulary/collectFormValues.js.map +0 -1
- package/dist/vocabulary/data.d.ts +0 -66
- package/dist/vocabulary/data.d.ts.map +0 -1
- package/dist/vocabulary/data.js +0 -503
- package/dist/vocabulary/data.js.map +0 -1
- package/dist/vocabulary/dispatch.d.ts +0 -9
- package/dist/vocabulary/dispatch.d.ts.map +0 -1
- package/dist/vocabulary/dispatch.js +0 -50
- package/dist/vocabulary/dispatch.js.map +0 -1
- package/dist/vocabulary/fact.d.ts +0 -19
- package/dist/vocabulary/fact.d.ts.map +0 -1
- package/dist/vocabulary/fact.js +0 -51
- package/dist/vocabulary/fact.js.map +0 -1
- package/dist/vocabulary/form.d.ts +0 -11
- package/dist/vocabulary/form.d.ts.map +0 -1
- package/dist/vocabulary/form.js +0 -23
- package/dist/vocabulary/form.js.map +0 -1
- package/dist/vocabulary/formatValue.d.ts +0 -7
- package/dist/vocabulary/formatValue.d.ts.map +0 -1
- package/dist/vocabulary/formatValue.js +0 -76
- package/dist/vocabulary/formatValue.js.map +0 -1
- package/dist/vocabulary/icon.d.ts +0 -41
- package/dist/vocabulary/icon.d.ts.map +0 -1
- package/dist/vocabulary/icon.js +0 -272
- package/dist/vocabulary/icon.js.map +0 -1
- package/dist/vocabulary/index.d.ts +0 -12
- package/dist/vocabulary/index.d.ts.map +0 -1
- package/dist/vocabulary/index.js +0 -36
- package/dist/vocabulary/index.js.map +0 -1
- package/dist/vocabulary/interactive.d.ts +0 -230
- package/dist/vocabulary/interactive.d.ts.map +0 -1
- package/dist/vocabulary/interactive.js +0 -530
- package/dist/vocabulary/interactive.js.map +0 -1
- package/dist/vocabulary/layout.d.ts +0 -79
- package/dist/vocabulary/layout.d.ts.map +0 -1
- package/dist/vocabulary/layout.js +0 -139
- package/dist/vocabulary/layout.js.map +0 -1
- package/dist/vocabulary/list.d.ts +0 -14
- package/dist/vocabulary/list.d.ts.map +0 -1
- package/dist/vocabulary/list.js +0 -50
- package/dist/vocabulary/list.js.map +0 -1
- package/dist/vocabulary/media.d.ts +0 -25
- package/dist/vocabulary/media.d.ts.map +0 -1
- package/dist/vocabulary/media.js +0 -42
- package/dist/vocabulary/media.js.map +0 -1
- package/dist/vocabulary/text.d.ts +0 -57
- package/dist/vocabulary/text.d.ts.map +0 -1
- package/dist/vocabulary/text.js +0 -49
- package/dist/vocabulary/text.js.map +0 -1
- package/dist/vocabulary/toTextContent.d.ts +0 -2
- package/dist/vocabulary/toTextContent.d.ts.map +0 -1
- package/dist/vocabulary/toTextContent.js +0 -6
- package/dist/vocabulary/toTextContent.js.map +0 -1
- package/src/JSONGenerativeUI.client.tsx +0 -168
- package/src/JSONGenerativeUI.server.tsx +0 -39
- package/src/JSONGenerativeUI.shared.ts +0 -90
- package/src/JSONGenerativeUI.test.tsx +0 -1298
- package/src/RadioGroupScope.server.test.tsx +0 -24
- package/src/RadioGroupScope.tsx +0 -34
- package/src/a2ui/BindingContext.ts +0 -26
- package/src/a2ui/PresentRenderer.tsx +0 -83
- package/src/a2ui/convert.test.ts +0 -2923
- package/src/a2ui/convert.ts +0 -1207
- package/src/a2ui/dataModel.ts +0 -69
- package/src/a2ui/reducer.test.ts +0 -422
- package/src/a2ui/reducer.ts +0 -363
- package/src/a2ui/snapshot.test.ts +0 -52
- package/src/a2ui/snapshot.ts +0 -52
- package/src/a2ui/types.ts +0 -114
- package/src/a2ui/valueFunctions.test.ts +0 -271
- package/src/a2ui/valueFunctions.ts +0 -523
- package/src/actionRegistry.test.ts +0 -90
- package/src/actionRegistry.ts +0 -88
- package/src/answeredValues.test.ts +0 -33
- package/src/answeredValues.tsx +0 -70
- package/src/buildPresentParameters.test.ts +0 -246
- package/src/buildPresentParameters.ts +0 -130
- package/src/constants.ts +0 -17
- package/src/convert/boundSpec.test.ts +0 -192
- package/src/convert/boundSpec.ts +0 -134
- package/src/convert/copyBounded.test.ts +0 -131
- package/src/convert/copyBounded.ts +0 -38
- package/src/convert/isElement.ts +0 -6
- package/src/convert/takeRun.test.ts +0 -64
- package/src/convert/takeRun.ts +0 -19
- package/src/defineGenerativeComponents.ts +0 -38
- package/src/fieldReferences.test.ts +0 -66
- package/src/fieldReferences.ts +0 -83
- package/src/generativeUIToJSX.test.ts +0 -268
- package/src/generativeUIToJSX.ts +0 -152
- package/src/index.server.test.ts +0 -106
- package/src/index.shared.ts +0 -61
- package/src/ir.test.ts +0 -203
- package/src/renderGenerativeUI.test.tsx +0 -373
- package/src/renderGenerativeUI.tsx +0 -165
- package/src/scopeSchema.test.ts +0 -72
- package/src/scopeSchema.ts +0 -71
- package/src/slack/a2uiSlack.test.ts +0 -198
- package/src/slack/constants.ts +0 -194
- package/src/slack/datePicker.test.ts +0 -612
- package/src/slack/decodeBlockAction.test.ts +0 -233
- package/src/slack/decodeBlockAction.ts +0 -232
- package/src/slack/fromSlackBlocks.test.ts +0 -1465
- package/src/slack/fromSlackBlocks.ts +0 -789
- package/src/slack/toSlackBlocks.test.ts +0 -3065
- package/src/slack/toSlackBlocks.ts +0 -1818
- package/src/slack/types.ts +0 -264
- package/src/teams/constants.ts +0 -93
- package/src/teams/decodeSubmitData.test.ts +0 -397
- package/src/teams/decodeSubmitData.ts +0 -110
- package/src/teams/temporal.test.ts +0 -766
- package/src/teams/temporalId.ts +0 -56
- package/src/teams/toAdaptiveCard.test.ts +0 -1897
- package/src/teams/toAdaptiveCard.ts +0 -1057
- package/src/teams/toTeamsAttachments.test.ts +0 -74
- package/src/teams/toTeamsAttachments.ts +0 -133
- package/src/teams/types.ts +0 -266
- package/src/temporal.test.ts +0 -319
- package/src/temporal.ts +0 -259
- package/src/types.ts +0 -119
- package/src/vocabulary/alert.test.tsx +0 -427
- package/src/vocabulary/alert.tsx +0 -217
- package/src/vocabulary/collectFormValues.test.ts +0 -389
- package/src/vocabulary/collectFormValues.ts +0 -116
- package/src/vocabulary/data.test.tsx +0 -858
- package/src/vocabulary/data.tsx +0 -819
- package/src/vocabulary/datepicker.dom.test.tsx +0 -1148
- package/src/vocabulary/dispatch.ts +0 -83
- package/src/vocabulary/fact.test.tsx +0 -94
- package/src/vocabulary/fact.tsx +0 -54
- package/src/vocabulary/form.test.tsx +0 -113
- package/src/vocabulary/form.tsx +0 -39
- package/src/vocabulary/formatValue.test.ts +0 -72
- package/src/vocabulary/formatValue.ts +0 -127
- package/src/vocabulary/icon.test.tsx +0 -64
- package/src/vocabulary/icon.tsx +0 -174
- package/src/vocabulary/index.test.ts +0 -65
- package/src/vocabulary/index.ts +0 -33
- package/src/vocabulary/interactive.dispatch.test.tsx +0 -454
- package/src/vocabulary/interactive.dom.test.tsx +0 -1747
- package/src/vocabulary/interactive.test.tsx +0 -377
- package/src/vocabulary/interactive.tsx +0 -1048
- package/src/vocabulary/layout.test.tsx +0 -323
- package/src/vocabulary/layout.tsx +0 -247
- package/src/vocabulary/list.test.tsx +0 -222
- package/src/vocabulary/list.tsx +0 -50
- package/src/vocabulary/media.test.tsx +0 -85
- package/src/vocabulary/media.tsx +0 -56
- package/src/vocabulary/text.test.tsx +0 -102
- package/src/vocabulary/text.tsx +0 -60
- package/src/vocabulary/toTextContent.ts +0 -2
package/src/a2ui/reducer.ts
DELETED
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
A2UI_SURFACE_ID,
|
|
3
|
-
type A2uiOperationResult,
|
|
4
|
-
type A2uiState,
|
|
5
|
-
type A2uiSurfaceState,
|
|
6
|
-
type A2uiVersion,
|
|
7
|
-
} from "./types";
|
|
8
|
-
|
|
9
|
-
const OPERATION_KEYS = new Set([
|
|
10
|
-
"createSurface",
|
|
11
|
-
"updateComponents",
|
|
12
|
-
"updateDataModel",
|
|
13
|
-
"deleteSurface",
|
|
14
|
-
]);
|
|
15
|
-
// This defensive ceiling is well above the renderer's displayed-item limit.
|
|
16
|
-
export const MAX_AUTO_VIVIFY_ARRAY_INDEX = 10_000;
|
|
17
|
-
const INVALID_POINTER = Symbol("invalidPointer");
|
|
18
|
-
|
|
19
|
-
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
20
|
-
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21
|
-
|
|
22
|
-
const isVersion = (value: unknown): value is A2uiVersion =>
|
|
23
|
-
value === "v0.9" || value === "v0.9.1" || value === "v1.0";
|
|
24
|
-
|
|
25
|
-
const surfaceIdOf = (payload: Record<string, unknown>): string | undefined => {
|
|
26
|
-
const surfaceId = payload["surfaceId"];
|
|
27
|
-
return typeof surfaceId === "string" && surfaceId.length > 0
|
|
28
|
-
? surfaceId
|
|
29
|
-
: undefined;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const catalogIdOf = (payload: Record<string, unknown>): string | undefined => {
|
|
33
|
-
if (typeof payload["catalogId"] === "string") {
|
|
34
|
-
return payload["catalogId"];
|
|
35
|
-
}
|
|
36
|
-
const surfaceProperties = payload["surfaceProperties"];
|
|
37
|
-
return isRecord(surfaceProperties) &&
|
|
38
|
-
typeof surfaceProperties["catalogId"] === "string"
|
|
39
|
-
? surfaceProperties["catalogId"]
|
|
40
|
-
: undefined;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const withSurfaceId = (
|
|
44
|
-
surface: A2uiSurfaceState,
|
|
45
|
-
surfaceId: string,
|
|
46
|
-
): A2uiSurfaceState => {
|
|
47
|
-
Object.defineProperty(surface, A2UI_SURFACE_ID, {
|
|
48
|
-
value: surfaceId,
|
|
49
|
-
enumerable: false,
|
|
50
|
-
});
|
|
51
|
-
return surface;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const getSurfaceId = (surface: A2uiSurfaceState): string | undefined =>
|
|
55
|
-
(surface as A2uiSurfaceState & { [A2UI_SURFACE_ID]?: string })[
|
|
56
|
-
A2UI_SURFACE_ID
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
const cloneSurface = (
|
|
60
|
-
surface: A2uiSurfaceState,
|
|
61
|
-
surfaceId: string,
|
|
62
|
-
): A2uiSurfaceState =>
|
|
63
|
-
withSurfaceId(
|
|
64
|
-
{
|
|
65
|
-
...(surface.catalogId !== undefined
|
|
66
|
-
? { catalogId: surface.catalogId }
|
|
67
|
-
: {}),
|
|
68
|
-
components: new Map(surface.components),
|
|
69
|
-
dataModel: surface.dataModel,
|
|
70
|
-
},
|
|
71
|
-
getSurfaceId(surface) ?? surfaceId,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const upsertComponents = (
|
|
75
|
-
surface: A2uiSurfaceState,
|
|
76
|
-
components: unknown,
|
|
77
|
-
warnings: string[],
|
|
78
|
-
operationIndex: number,
|
|
79
|
-
): void => {
|
|
80
|
-
if (!Array.isArray(components)) {
|
|
81
|
-
warnings.push(
|
|
82
|
-
`Operation at index ${operationIndex} has malformed components.`,
|
|
83
|
-
);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
for (
|
|
88
|
-
let componentIndex = 0;
|
|
89
|
-
componentIndex < components.length;
|
|
90
|
-
componentIndex++
|
|
91
|
-
) {
|
|
92
|
-
const component = components[componentIndex];
|
|
93
|
-
if (
|
|
94
|
-
!isRecord(component) ||
|
|
95
|
-
typeof component["id"] !== "string" ||
|
|
96
|
-
component["id"].length === 0 ||
|
|
97
|
-
typeof component["component"] !== "string" ||
|
|
98
|
-
component["component"].length === 0
|
|
99
|
-
) {
|
|
100
|
-
warnings.push(
|
|
101
|
-
`Component at index ${componentIndex} in operation ${operationIndex} is malformed.`,
|
|
102
|
-
);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
surface.components.set(component["id"], { ...component });
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const decodePointer = (path: string): string[] | undefined => {
|
|
110
|
-
if (path === "" || path === "/") return [];
|
|
111
|
-
if (!path.startsWith("/")) return undefined;
|
|
112
|
-
return path
|
|
113
|
-
.slice(1)
|
|
114
|
-
.split("/")
|
|
115
|
-
.map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const isArrayIndex = (segment: string): boolean =>
|
|
119
|
-
segment === "0" || /^[1-9]\d*$/.test(segment);
|
|
120
|
-
|
|
121
|
-
export const setAtPointer = (
|
|
122
|
-
model: unknown,
|
|
123
|
-
path: string,
|
|
124
|
-
value: unknown,
|
|
125
|
-
nullDeletes: boolean,
|
|
126
|
-
): { readonly ok: boolean; readonly value: unknown } => {
|
|
127
|
-
const segments = decodePointer(path);
|
|
128
|
-
if (!segments) return { ok: false, value: model };
|
|
129
|
-
if (segments.length === 0) return { ok: true, value };
|
|
130
|
-
|
|
131
|
-
const remove = (current: unknown, index: number): unknown => {
|
|
132
|
-
const segment = segments[index]!;
|
|
133
|
-
const isLast = index === segments.length - 1;
|
|
134
|
-
|
|
135
|
-
if (Array.isArray(current)) {
|
|
136
|
-
if (segment !== "-" && !isArrayIndex(segment)) return current;
|
|
137
|
-
const targetIndex = segment === "-" ? current.length : Number(segment);
|
|
138
|
-
if (isLast) {
|
|
139
|
-
if (
|
|
140
|
-
segment === "-" ||
|
|
141
|
-
!Object.prototype.hasOwnProperty.call(current, targetIndex)
|
|
142
|
-
) {
|
|
143
|
-
return current;
|
|
144
|
-
}
|
|
145
|
-
const clone = current.slice();
|
|
146
|
-
// Preserve indices referenced by other JSON Pointers.
|
|
147
|
-
delete clone[targetIndex];
|
|
148
|
-
return clone;
|
|
149
|
-
}
|
|
150
|
-
const child = current[targetIndex];
|
|
151
|
-
if (!Array.isArray(child) && !isRecord(child)) return current;
|
|
152
|
-
const next = remove(child, index + 1);
|
|
153
|
-
if (next === child) return current;
|
|
154
|
-
const clone = current.slice();
|
|
155
|
-
clone[targetIndex] = next;
|
|
156
|
-
return clone;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!isRecord(current)) return current;
|
|
160
|
-
if (!Object.prototype.hasOwnProperty.call(current, segment)) return current;
|
|
161
|
-
if (isLast) {
|
|
162
|
-
const clone = { ...current };
|
|
163
|
-
delete clone[segment];
|
|
164
|
-
return clone;
|
|
165
|
-
}
|
|
166
|
-
const child = current[segment];
|
|
167
|
-
if (!Array.isArray(child) && !isRecord(child)) return current;
|
|
168
|
-
const next = remove(child, index + 1);
|
|
169
|
-
if (next === child) return current;
|
|
170
|
-
return { ...current, [segment]: next };
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
if (nullDeletes && value === null) {
|
|
174
|
-
return { ok: true, value: remove(model, 0) };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const update = (current: unknown, index: number): unknown => {
|
|
178
|
-
const segment = segments[index]!;
|
|
179
|
-
const isLast = index === segments.length - 1;
|
|
180
|
-
|
|
181
|
-
if (Array.isArray(current)) {
|
|
182
|
-
if (segment !== "-" && !isArrayIndex(segment)) return current;
|
|
183
|
-
const targetIndex = segment === "-" ? current.length : Number(segment);
|
|
184
|
-
if (
|
|
185
|
-
segment !== "-" &&
|
|
186
|
-
targetIndex >= current.length &&
|
|
187
|
-
targetIndex > MAX_AUTO_VIVIFY_ARRAY_INDEX
|
|
188
|
-
) {
|
|
189
|
-
return INVALID_POINTER;
|
|
190
|
-
}
|
|
191
|
-
const next = isLast ? value : update(current[targetIndex], index + 1);
|
|
192
|
-
if (next === INVALID_POINTER) return INVALID_POINTER;
|
|
193
|
-
const clone = current.slice();
|
|
194
|
-
clone[targetIndex] = next;
|
|
195
|
-
return clone;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const record: Record<string, unknown> = isRecord(current) ? current : {};
|
|
199
|
-
const child = Object.hasOwn(record, segment) ? record[segment] : undefined;
|
|
200
|
-
const next = isLast
|
|
201
|
-
? value
|
|
202
|
-
: update(
|
|
203
|
-
child ??
|
|
204
|
-
(isArrayIndex(segments[index + 1] ?? "") ||
|
|
205
|
-
segments[index + 1] === "-"
|
|
206
|
-
? []
|
|
207
|
-
: {}),
|
|
208
|
-
index + 1,
|
|
209
|
-
);
|
|
210
|
-
if (next === INVALID_POINTER) return INVALID_POINTER;
|
|
211
|
-
return { ...record, [segment]: next };
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const result = update(model, 0);
|
|
215
|
-
return result === INVALID_POINTER
|
|
216
|
-
? { ok: false, value: model }
|
|
217
|
-
: { ok: true, value: result };
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const dataModelValue = (
|
|
221
|
-
payload: Record<string, unknown>,
|
|
222
|
-
): { readonly found: boolean; readonly value: unknown } => {
|
|
223
|
-
for (const key of ["contents", "value", "data"] as const) {
|
|
224
|
-
if (payload[key] !== undefined) {
|
|
225
|
-
return { found: true, value: payload[key] };
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return { found: false, value: undefined };
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export function applyA2uiOperations(
|
|
232
|
-
state: A2uiState,
|
|
233
|
-
operations: unknown,
|
|
234
|
-
): A2uiOperationResult {
|
|
235
|
-
const nextState = new Map(state);
|
|
236
|
-
const warnings: string[] = [];
|
|
237
|
-
|
|
238
|
-
if (!Array.isArray(operations)) {
|
|
239
|
-
return {
|
|
240
|
-
state: nextState,
|
|
241
|
-
warnings: ["A2UI operations must be an array."],
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
for (let index = 0; index < operations.length; index++) {
|
|
246
|
-
try {
|
|
247
|
-
const entry = operations[index];
|
|
248
|
-
if (!isRecord(entry)) {
|
|
249
|
-
warnings.push(`Operation at index ${index} is malformed.`);
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const version = entry["version"];
|
|
254
|
-
if (!isVersion(version)) {
|
|
255
|
-
warnings.push(
|
|
256
|
-
`Operation at index ${index} has an unsupported version.`,
|
|
257
|
-
);
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const operationKeys = Object.keys(entry).filter(
|
|
262
|
-
(key) => key !== "version",
|
|
263
|
-
);
|
|
264
|
-
if (operationKeys.length !== 1) {
|
|
265
|
-
warnings.push(
|
|
266
|
-
`Operation at index ${index} must contain exactly one operation key.`,
|
|
267
|
-
);
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const operationKey = operationKeys[0]!;
|
|
272
|
-
if (!OPERATION_KEYS.has(operationKey)) {
|
|
273
|
-
warnings.push(
|
|
274
|
-
`Unknown A2UI operation "${operationKey}" at index ${index}.`,
|
|
275
|
-
);
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const payload = entry[operationKey];
|
|
280
|
-
if (!isRecord(payload)) {
|
|
281
|
-
warnings.push(`Operation at index ${index} has a malformed payload.`);
|
|
282
|
-
continue;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const surfaceId = surfaceIdOf(payload);
|
|
286
|
-
if (!surfaceId) {
|
|
287
|
-
warnings.push(`Operation at index ${index} has no valid surfaceId.`);
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (operationKey === "createSurface") {
|
|
292
|
-
const catalogId = catalogIdOf(payload);
|
|
293
|
-
const surface = withSurfaceId(
|
|
294
|
-
{
|
|
295
|
-
...(catalogId !== undefined ? { catalogId } : {}),
|
|
296
|
-
components: new Map(),
|
|
297
|
-
dataModel:
|
|
298
|
-
version === "v1.0" && payload["dataModel"] !== undefined
|
|
299
|
-
? payload["dataModel"]
|
|
300
|
-
: undefined,
|
|
301
|
-
},
|
|
302
|
-
surfaceId,
|
|
303
|
-
);
|
|
304
|
-
if (version === "v1.0" && payload["components"] !== undefined) {
|
|
305
|
-
upsertComponents(surface, payload["components"], warnings, index);
|
|
306
|
-
}
|
|
307
|
-
nextState.set(surfaceId, surface);
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (operationKey === "deleteSurface") {
|
|
312
|
-
nextState.delete(surfaceId);
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const currentSurface = nextState.get(surfaceId);
|
|
317
|
-
if (!currentSurface) {
|
|
318
|
-
warnings.push(
|
|
319
|
-
`Operation at index ${index} references missing surface "${surfaceId}".`,
|
|
320
|
-
);
|
|
321
|
-
continue;
|
|
322
|
-
}
|
|
323
|
-
const surface = cloneSurface(currentSurface, surfaceId);
|
|
324
|
-
|
|
325
|
-
if (operationKey === "updateComponents") {
|
|
326
|
-
upsertComponents(surface, payload["components"], warnings, index);
|
|
327
|
-
nextState.set(surfaceId, surface);
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const update = dataModelValue(payload);
|
|
332
|
-
if (!update.found) {
|
|
333
|
-
warnings.push(`Operation at index ${index} has no data model value.`);
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
const path = payload["path"] ?? "/";
|
|
337
|
-
if (typeof path !== "string") {
|
|
338
|
-
warnings.push(
|
|
339
|
-
`Operation at index ${index} has a malformed data model path.`,
|
|
340
|
-
);
|
|
341
|
-
continue;
|
|
342
|
-
}
|
|
343
|
-
const result = setAtPointer(
|
|
344
|
-
surface.dataModel,
|
|
345
|
-
path,
|
|
346
|
-
update.value,
|
|
347
|
-
version === "v1.0",
|
|
348
|
-
);
|
|
349
|
-
if (!result.ok) {
|
|
350
|
-
warnings.push(
|
|
351
|
-
`Operation at index ${index} has an invalid JSON Pointer path.`,
|
|
352
|
-
);
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
surface.dataModel = result.value;
|
|
356
|
-
nextState.set(surfaceId, surface);
|
|
357
|
-
} catch {
|
|
358
|
-
warnings.push(`Operation at index ${index} is malformed.`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return { state: nextState, warnings };
|
|
363
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { surfaceToOperations } from "./snapshot";
|
|
3
|
-
import { A2UI_SURFACE_ID, type A2uiSurfaceState } from "./types";
|
|
4
|
-
|
|
5
|
-
const surface = (dataModel: unknown): A2uiSurfaceState => ({
|
|
6
|
-
components: new Map([["root", { id: "root", component: "Text" }]]),
|
|
7
|
-
dataModel,
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
describe("surfaceToOperations", () => {
|
|
11
|
-
it("uses an explicit surface id and omits an undefined data model", () => {
|
|
12
|
-
const value = Object.defineProperty(surface(undefined), A2UI_SURFACE_ID, {
|
|
13
|
-
value: "stored",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
expect(surfaceToOperations(value, "provided")).toEqual([
|
|
17
|
-
{
|
|
18
|
-
version: "v0.9",
|
|
19
|
-
createSurface: { surfaceId: "provided" },
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
version: "v0.9",
|
|
23
|
-
updateComponents: {
|
|
24
|
-
surfaceId: "provided",
|
|
25
|
-
components: [{ id: "root", component: "Text" }],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
]);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("uses the reducer surface id when no explicit id is supplied", () => {
|
|
32
|
-
const value = Object.defineProperty(surface(null), A2UI_SURFACE_ID, {
|
|
33
|
-
value: "stored",
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
expect(surfaceToOperations(value)).toMatchObject([
|
|
37
|
-
{ createSurface: { surfaceId: "stored" } },
|
|
38
|
-
{ updateComponents: { surfaceId: "stored" } },
|
|
39
|
-
{ updateDataModel: { surfaceId: "stored", contents: null } },
|
|
40
|
-
]);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("requires either an explicit or reducer surface id", () => {
|
|
44
|
-
expect(() => surfaceToOperations(surface({}))).toThrow(
|
|
45
|
-
"A2UI surfaces must have a surface id to be replayed.",
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
it("rejects an empty surface id", () => {
|
|
49
|
-
const value = { components: new Map(), dataModel: undefined };
|
|
50
|
-
expect(() => surfaceToOperations(value, "")).toThrow();
|
|
51
|
-
});
|
|
52
|
-
});
|
package/src/a2ui/snapshot.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
A2UI_SURFACE_ID,
|
|
3
|
-
type A2uiSurfaceState,
|
|
4
|
-
type A2uiSurfaceSnapshotOperation,
|
|
5
|
-
type ComponentNode,
|
|
6
|
-
} from "./types";
|
|
7
|
-
|
|
8
|
-
const surfaceIdOf = (surface: A2uiSurfaceState): string | undefined =>
|
|
9
|
-
(surface as A2uiSurfaceState & { [A2UI_SURFACE_ID]?: string })[
|
|
10
|
-
A2UI_SURFACE_ID
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
export function surfaceToOperations(
|
|
14
|
-
surface: A2uiSurfaceState,
|
|
15
|
-
surfaceId?: string,
|
|
16
|
-
): readonly A2uiSurfaceSnapshotOperation[] {
|
|
17
|
-
const resolvedSurfaceId = surfaceId ?? surfaceIdOf(surface);
|
|
18
|
-
if (!resolvedSurfaceId) {
|
|
19
|
-
throw new Error("A2UI surfaces must have a surface id to be replayed.");
|
|
20
|
-
}
|
|
21
|
-
const operations: A2uiSurfaceSnapshotOperation[] = [
|
|
22
|
-
{
|
|
23
|
-
version: "v0.9",
|
|
24
|
-
createSurface: {
|
|
25
|
-
surfaceId: resolvedSurfaceId,
|
|
26
|
-
...(surface.catalogId !== undefined
|
|
27
|
-
? { catalogId: surface.catalogId }
|
|
28
|
-
: {}),
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
version: "v0.9",
|
|
33
|
-
updateComponents: {
|
|
34
|
-
surfaceId: resolvedSurfaceId,
|
|
35
|
-
components: [...surface.components.values()].map((component) => ({
|
|
36
|
-
...component,
|
|
37
|
-
})) as ComponentNode[],
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
];
|
|
41
|
-
if (surface.dataModel !== undefined) {
|
|
42
|
-
operations.push({
|
|
43
|
-
version: "v0.9",
|
|
44
|
-
updateDataModel: {
|
|
45
|
-
surfaceId: resolvedSurfaceId,
|
|
46
|
-
path: "/",
|
|
47
|
-
contents: surface.dataModel,
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return operations;
|
|
52
|
-
}
|
package/src/a2ui/types.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
export const A2UI_SURFACE_ID = Symbol("a2uiSurfaceId");
|
|
2
|
-
|
|
3
|
-
export type A2uiVersion = "v0.9" | "v0.9.1" | "v1.0";
|
|
4
|
-
|
|
5
|
-
export interface A2uiTemplateChildren {
|
|
6
|
-
readonly template: {
|
|
7
|
-
readonly componentId: string;
|
|
8
|
-
readonly path: string;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ComponentNode extends Record<string, unknown> {
|
|
13
|
-
readonly id: string;
|
|
14
|
-
readonly component: string;
|
|
15
|
-
readonly children?:
|
|
16
|
-
| readonly string[]
|
|
17
|
-
| { readonly componentId: string; readonly path: string }
|
|
18
|
-
| A2uiTemplateChildren;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface A2uiCreateSurfaceV09Payload {
|
|
22
|
-
readonly surfaceId: string;
|
|
23
|
-
readonly catalogId?: string;
|
|
24
|
-
readonly theme?: unknown;
|
|
25
|
-
readonly attachDataModel?: unknown;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface A2uiCreateSurfaceV10Payload {
|
|
29
|
-
readonly surfaceId: string;
|
|
30
|
-
readonly catalogId?: string;
|
|
31
|
-
readonly surfaceProperties?: unknown;
|
|
32
|
-
readonly sendDataModel?: unknown;
|
|
33
|
-
readonly components?: readonly ComponentNode[];
|
|
34
|
-
readonly dataModel?: unknown;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface A2uiUpdateComponentsPayload {
|
|
38
|
-
readonly surfaceId: string;
|
|
39
|
-
readonly components: readonly ComponentNode[];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface A2uiUpdateDataModelPayload {
|
|
43
|
-
readonly surfaceId: string;
|
|
44
|
-
readonly path?: string;
|
|
45
|
-
readonly contents?: unknown;
|
|
46
|
-
readonly value?: unknown;
|
|
47
|
-
readonly data?: unknown;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface A2uiDeleteSurfacePayload {
|
|
51
|
-
readonly surfaceId: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export type A2uiCreateSurfaceOperation =
|
|
55
|
-
| {
|
|
56
|
-
readonly version: "v0.9";
|
|
57
|
-
readonly createSurface: A2uiCreateSurfaceV09Payload;
|
|
58
|
-
}
|
|
59
|
-
| {
|
|
60
|
-
readonly version: "v0.9.1";
|
|
61
|
-
readonly createSurface: A2uiCreateSurfaceV09Payload;
|
|
62
|
-
}
|
|
63
|
-
| {
|
|
64
|
-
readonly version: "v1.0";
|
|
65
|
-
readonly createSurface: A2uiCreateSurfaceV10Payload;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export interface A2uiUpdateComponentsOperation {
|
|
69
|
-
readonly version: A2uiVersion;
|
|
70
|
-
readonly updateComponents: A2uiUpdateComponentsPayload;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface A2uiUpdateDataModelOperation {
|
|
74
|
-
readonly version: A2uiVersion;
|
|
75
|
-
readonly updateDataModel: A2uiUpdateDataModelPayload;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface A2uiDeleteSurfaceOperation {
|
|
79
|
-
readonly version: A2uiVersion;
|
|
80
|
-
readonly deleteSurface: A2uiDeleteSurfacePayload;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export type A2uiOperation =
|
|
84
|
-
| A2uiCreateSurfaceOperation
|
|
85
|
-
| A2uiUpdateComponentsOperation
|
|
86
|
-
| A2uiUpdateDataModelOperation
|
|
87
|
-
| A2uiDeleteSurfaceOperation;
|
|
88
|
-
|
|
89
|
-
export type A2uiSurfaceSnapshotOperation =
|
|
90
|
-
| {
|
|
91
|
-
readonly version: "v0.9";
|
|
92
|
-
readonly createSurface: A2uiCreateSurfaceV09Payload;
|
|
93
|
-
}
|
|
94
|
-
| {
|
|
95
|
-
readonly version: "v0.9";
|
|
96
|
-
readonly updateComponents: A2uiUpdateComponentsPayload;
|
|
97
|
-
}
|
|
98
|
-
| {
|
|
99
|
-
readonly version: "v0.9";
|
|
100
|
-
readonly updateDataModel: A2uiUpdateDataModelPayload;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
export type A2uiSurfaceState = {
|
|
104
|
-
catalogId?: string;
|
|
105
|
-
components: Map<string, Record<string, unknown>>;
|
|
106
|
-
dataModel: unknown;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export type A2uiState = ReadonlyMap<string, A2uiSurfaceState>;
|
|
110
|
-
|
|
111
|
-
export interface A2uiOperationResult {
|
|
112
|
-
readonly state: A2uiState;
|
|
113
|
-
readonly warnings: string[];
|
|
114
|
-
}
|