@zhama/a2ui-core 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.
@@ -0,0 +1,308 @@
1
+ // src/validators/message-validator.ts
2
+ var STANDARD_COMPONENT_TYPES = [
3
+ "Text",
4
+ "Image",
5
+ "Icon",
6
+ "Video",
7
+ "AudioPlayer",
8
+ "Row",
9
+ "Column",
10
+ "List",
11
+ "Card",
12
+ "Tabs",
13
+ "Divider",
14
+ "Modal",
15
+ "Button",
16
+ "CheckBox",
17
+ "TextField",
18
+ "DateTimeInput",
19
+ "ChoicePicker",
20
+ "Slider"
21
+ ];
22
+ function validateV09Message(message, options = {}) {
23
+ const errors = [];
24
+ const warnings = [];
25
+ if ("createSurface" in message) {
26
+ const { createSurface } = message;
27
+ if (!createSurface.surfaceId) {
28
+ errors.push({
29
+ code: "MISSING_SURFACE_ID",
30
+ message: "createSurface.surfaceId is required",
31
+ path: "createSurface.surfaceId"
32
+ });
33
+ }
34
+ if (!createSurface.catalogId) {
35
+ errors.push({
36
+ code: "MISSING_CATALOG_ID",
37
+ message: "createSurface.catalogId is required",
38
+ path: "createSurface.catalogId"
39
+ });
40
+ }
41
+ } else if ("updateComponents" in message) {
42
+ const { updateComponents } = message;
43
+ if (!updateComponents.surfaceId) {
44
+ errors.push({
45
+ code: "MISSING_SURFACE_ID",
46
+ message: "updateComponents.surfaceId is required",
47
+ path: "updateComponents.surfaceId"
48
+ });
49
+ }
50
+ if (!updateComponents.components || !Array.isArray(updateComponents.components)) {
51
+ errors.push({
52
+ code: "INVALID_COMPONENTS",
53
+ message: "updateComponents.components must be an array",
54
+ path: "updateComponents.components"
55
+ });
56
+ } else {
57
+ validateComponentsV09(updateComponents.components, errors, warnings, options);
58
+ }
59
+ } else if ("updateDataModel" in message) {
60
+ const { updateDataModel } = message;
61
+ if (!updateDataModel.surfaceId) {
62
+ errors.push({
63
+ code: "MISSING_SURFACE_ID",
64
+ message: "updateDataModel.surfaceId is required",
65
+ path: "updateDataModel.surfaceId"
66
+ });
67
+ }
68
+ } else if ("deleteSurface" in message) {
69
+ const { deleteSurface } = message;
70
+ if (!deleteSurface.surfaceId) {
71
+ errors.push({
72
+ code: "MISSING_SURFACE_ID",
73
+ message: "deleteSurface.surfaceId is required",
74
+ path: "deleteSurface.surfaceId"
75
+ });
76
+ }
77
+ } else {
78
+ errors.push({
79
+ code: "INVALID_MESSAGE_TYPE",
80
+ message: "Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface"
81
+ });
82
+ }
83
+ return {
84
+ valid: errors.length === 0,
85
+ errors,
86
+ warnings
87
+ };
88
+ }
89
+ function validateV08Message(message, options = {}) {
90
+ const errors = [];
91
+ const warnings = [];
92
+ if ("beginRendering" in message) {
93
+ const { beginRendering } = message;
94
+ if (!beginRendering.surfaceId) {
95
+ errors.push({
96
+ code: "MISSING_SURFACE_ID",
97
+ message: "beginRendering.surfaceId is required",
98
+ path: "beginRendering.surfaceId"
99
+ });
100
+ }
101
+ if (!beginRendering.root) {
102
+ errors.push({
103
+ code: "MISSING_ROOT",
104
+ message: "beginRendering.root is required",
105
+ path: "beginRendering.root"
106
+ });
107
+ }
108
+ } else if ("surfaceUpdate" in message) {
109
+ const { surfaceUpdate } = message;
110
+ if (!surfaceUpdate.surfaceId) {
111
+ errors.push({
112
+ code: "MISSING_SURFACE_ID",
113
+ message: "surfaceUpdate.surfaceId is required",
114
+ path: "surfaceUpdate.surfaceId"
115
+ });
116
+ }
117
+ if (!surfaceUpdate.components || !Array.isArray(surfaceUpdate.components)) {
118
+ errors.push({
119
+ code: "INVALID_COMPONENTS",
120
+ message: "surfaceUpdate.components must be an array",
121
+ path: "surfaceUpdate.components"
122
+ });
123
+ } else {
124
+ validateComponentsV08(surfaceUpdate.components, errors, warnings, options);
125
+ }
126
+ } else if ("dataModelUpdate" in message) {
127
+ const { dataModelUpdate } = message;
128
+ if (!dataModelUpdate.surfaceId) {
129
+ errors.push({
130
+ code: "MISSING_SURFACE_ID",
131
+ message: "dataModelUpdate.surfaceId is required",
132
+ path: "dataModelUpdate.surfaceId"
133
+ });
134
+ }
135
+ if (!dataModelUpdate.contents || !Array.isArray(dataModelUpdate.contents)) {
136
+ errors.push({
137
+ code: "INVALID_CONTENTS",
138
+ message: "dataModelUpdate.contents must be an array",
139
+ path: "dataModelUpdate.contents"
140
+ });
141
+ }
142
+ } else if ("deleteSurface" in message) {
143
+ const { deleteSurface } = message;
144
+ if (!deleteSurface.surfaceId) {
145
+ errors.push({
146
+ code: "MISSING_SURFACE_ID",
147
+ message: "deleteSurface.surfaceId is required",
148
+ path: "deleteSurface.surfaceId"
149
+ });
150
+ }
151
+ } else {
152
+ errors.push({
153
+ code: "INVALID_MESSAGE_TYPE",
154
+ message: "Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface"
155
+ });
156
+ }
157
+ return {
158
+ valid: errors.length === 0,
159
+ errors,
160
+ warnings
161
+ };
162
+ }
163
+ function validateMessage(message, options = {}) {
164
+ if ("createSurface" in message || "updateComponents" in message || "updateDataModel" in message) {
165
+ return validateV09Message(message, options);
166
+ }
167
+ if ("beginRendering" in message || "surfaceUpdate" in message || "dataModelUpdate" in message) {
168
+ return validateV08Message(message, options);
169
+ }
170
+ if ("deleteSurface" in message) {
171
+ if (!message.deleteSurface.surfaceId) {
172
+ return {
173
+ valid: false,
174
+ errors: [{
175
+ code: "MISSING_SURFACE_ID",
176
+ message: "deleteSurface.surfaceId is required",
177
+ path: "deleteSurface.surfaceId"
178
+ }],
179
+ warnings: []
180
+ };
181
+ }
182
+ return { valid: true, errors: [], warnings: [] };
183
+ }
184
+ return {
185
+ valid: false,
186
+ errors: [{
187
+ code: "UNKNOWN_MESSAGE_TYPE",
188
+ message: "Unknown message type"
189
+ }],
190
+ warnings: []
191
+ };
192
+ }
193
+ function validateMessages(messages, options = {}) {
194
+ const errors = [];
195
+ const warnings = [];
196
+ for (let i = 0; i < messages.length; i++) {
197
+ const result = validateMessage(messages[i], options);
198
+ for (const error of result.errors) {
199
+ errors.push({
200
+ ...error,
201
+ path: `messages[${i}].${error.path || ""}`
202
+ });
203
+ }
204
+ for (const warning of result.warnings) {
205
+ warnings.push({
206
+ ...warning,
207
+ path: `messages[${i}].${warning.path || ""}`
208
+ });
209
+ }
210
+ }
211
+ return {
212
+ valid: errors.length === 0,
213
+ errors,
214
+ warnings
215
+ };
216
+ }
217
+ function validateComponentsV09(components, errors, warnings, options) {
218
+ const componentIds = /* @__PURE__ */ new Set();
219
+ let hasRoot = false;
220
+ for (let i = 0; i < components.length; i++) {
221
+ const comp = components[i];
222
+ const path = `updateComponents.components[${i}]`;
223
+ if (!comp.id) {
224
+ errors.push({
225
+ code: "MISSING_COMPONENT_ID",
226
+ message: "Component id is required",
227
+ path: `${path}.id`
228
+ });
229
+ } else {
230
+ if (componentIds.has(comp.id)) {
231
+ errors.push({
232
+ code: "DUPLICATE_COMPONENT_ID",
233
+ message: `Duplicate component id: ${comp.id}`,
234
+ path: `${path}.id`
235
+ });
236
+ }
237
+ componentIds.add(comp.id);
238
+ if (comp.id === "root") {
239
+ hasRoot = true;
240
+ }
241
+ }
242
+ if (!comp.component) {
243
+ errors.push({
244
+ code: "MISSING_COMPONENT_TYPE",
245
+ message: "Component type is required",
246
+ path: `${path}.component`
247
+ });
248
+ } else if (options.strict && options.allowedComponents) {
249
+ if (!options.allowedComponents.includes(comp.component)) {
250
+ warnings.push({
251
+ code: "UNKNOWN_COMPONENT_TYPE",
252
+ message: `Unknown component type: ${comp.component}`,
253
+ path: `${path}.component`
254
+ });
255
+ }
256
+ }
257
+ }
258
+ if (!hasRoot && options.strict) {
259
+ warnings.push({
260
+ code: "MISSING_ROOT_COMPONENT",
261
+ message: 'No component with id "root" found',
262
+ path: "updateComponents.components"
263
+ });
264
+ }
265
+ }
266
+ function validateComponentsV08(components, errors, warnings, options) {
267
+ const componentIds = /* @__PURE__ */ new Set();
268
+ for (let i = 0; i < components.length; i++) {
269
+ const comp = components[i];
270
+ const path = `surfaceUpdate.components[${i}]`;
271
+ if (!comp.id) {
272
+ errors.push({
273
+ code: "MISSING_COMPONENT_ID",
274
+ message: "Component id is required",
275
+ path: `${path}.id`
276
+ });
277
+ } else {
278
+ if (componentIds.has(comp.id)) {
279
+ errors.push({
280
+ code: "DUPLICATE_COMPONENT_ID",
281
+ message: `Duplicate component id: ${comp.id}`,
282
+ path: `${path}.id`
283
+ });
284
+ }
285
+ componentIds.add(comp.id);
286
+ }
287
+ if (!comp.component || typeof comp.component !== "object") {
288
+ errors.push({
289
+ code: "MISSING_COMPONENT",
290
+ message: "Component definition is required",
291
+ path: `${path}.component`
292
+ });
293
+ } else {
294
+ const componentType = Object.keys(comp.component)[0];
295
+ if (options.strict && !STANDARD_COMPONENT_TYPES.includes(componentType)) {
296
+ warnings.push({
297
+ code: "UNKNOWN_COMPONENT_TYPE",
298
+ message: `Unknown component type: ${componentType}`,
299
+ path: `${path}.component`
300
+ });
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ export { validateMessage, validateMessages, validateV08Message, validateV09Message };
307
+ //# sourceMappingURL=index.js.map
308
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/validators/message-validator.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Message Validator\n *\n * 提供 A2UI 消息验证功能\n */\n\nimport type {\n ServerToClientMessage,\n ServerToClientMessageV08,\n ServerToClientMessageV09,\n ComponentInstance,\n ComponentInstanceV08,\n} from '../types';\n\n/**\n * 验证结果\n */\nexport interface ValidationResult {\n /** 是否有效 */\n valid: boolean;\n /** 错误信息列表 */\n errors: ValidationError[];\n /** 警告信息列表 */\n warnings: ValidationWarning[];\n}\n\n/**\n * 验证错误\n */\nexport interface ValidationError {\n /** 错误代码 */\n code: string;\n /** 错误消息 */\n message: string;\n /** 错误路径(如 'components[0].id') */\n path?: string;\n}\n\n/**\n * 验证警告\n */\nexport interface ValidationWarning {\n /** 警告代码 */\n code: string;\n /** 警告消息 */\n message: string;\n /** 警告路径 */\n path?: string;\n}\n\n/**\n * 验证选项\n */\nexport interface ValidationOptions {\n /** 是否严格模式(报告更多问题) */\n strict?: boolean;\n /** 允许的组件类型(为空表示允许所有) */\n allowedComponents?: string[];\n}\n\n/**\n * 标准组件类型列表\n */\nconst STANDARD_COMPONENT_TYPES = [\n 'Text',\n 'Image',\n 'Icon',\n 'Video',\n 'AudioPlayer',\n 'Row',\n 'Column',\n 'List',\n 'Card',\n 'Tabs',\n 'Divider',\n 'Modal',\n 'Button',\n 'CheckBox',\n 'TextField',\n 'DateTimeInput',\n 'ChoicePicker',\n 'Slider',\n];\n\n/**\n * 验证 v0.9 消息\n */\nexport function validateV09Message(\n message: ServerToClientMessageV09,\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n if ('createSurface' in message) {\n const { createSurface } = message;\n if (!createSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'createSurface.surfaceId is required',\n path: 'createSurface.surfaceId',\n });\n }\n if (!createSurface.catalogId) {\n errors.push({\n code: 'MISSING_CATALOG_ID',\n message: 'createSurface.catalogId is required',\n path: 'createSurface.catalogId',\n });\n }\n } else if ('updateComponents' in message) {\n const { updateComponents } = message;\n if (!updateComponents.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'updateComponents.surfaceId is required',\n path: 'updateComponents.surfaceId',\n });\n }\n if (!updateComponents.components || !Array.isArray(updateComponents.components)) {\n errors.push({\n code: 'INVALID_COMPONENTS',\n message: 'updateComponents.components must be an array',\n path: 'updateComponents.components',\n });\n } else {\n // 验证组件\n validateComponentsV09(updateComponents.components, errors, warnings, options);\n }\n } else if ('updateDataModel' in message) {\n const { updateDataModel } = message;\n if (!updateDataModel.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'updateDataModel.surfaceId is required',\n path: 'updateDataModel.surfaceId',\n });\n }\n } else if ('deleteSurface' in message) {\n const { deleteSurface } = message;\n if (!deleteSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n });\n }\n } else {\n errors.push({\n code: 'INVALID_MESSAGE_TYPE',\n message: 'Message must contain one of: createSurface, updateComponents, updateDataModel, deleteSurface',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * 验证 v0.8 消息\n */\nexport function validateV08Message(\n message: ServerToClientMessageV08,\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n if ('beginRendering' in message) {\n const { beginRendering } = message;\n if (!beginRendering.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'beginRendering.surfaceId is required',\n path: 'beginRendering.surfaceId',\n });\n }\n if (!beginRendering.root) {\n errors.push({\n code: 'MISSING_ROOT',\n message: 'beginRendering.root is required',\n path: 'beginRendering.root',\n });\n }\n } else if ('surfaceUpdate' in message) {\n const { surfaceUpdate } = message;\n if (!surfaceUpdate.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'surfaceUpdate.surfaceId is required',\n path: 'surfaceUpdate.surfaceId',\n });\n }\n if (!surfaceUpdate.components || !Array.isArray(surfaceUpdate.components)) {\n errors.push({\n code: 'INVALID_COMPONENTS',\n message: 'surfaceUpdate.components must be an array',\n path: 'surfaceUpdate.components',\n });\n } else {\n validateComponentsV08(surfaceUpdate.components, errors, warnings, options);\n }\n } else if ('dataModelUpdate' in message) {\n const { dataModelUpdate } = message;\n if (!dataModelUpdate.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'dataModelUpdate.surfaceId is required',\n path: 'dataModelUpdate.surfaceId',\n });\n }\n if (!dataModelUpdate.contents || !Array.isArray(dataModelUpdate.contents)) {\n errors.push({\n code: 'INVALID_CONTENTS',\n message: 'dataModelUpdate.contents must be an array',\n path: 'dataModelUpdate.contents',\n });\n }\n } else if ('deleteSurface' in message) {\n const { deleteSurface } = message;\n if (!deleteSurface.surfaceId) {\n errors.push({\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n });\n }\n } else {\n errors.push({\n code: 'INVALID_MESSAGE_TYPE',\n message: 'Message must contain one of: beginRendering, surfaceUpdate, dataModelUpdate, deleteSurface',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * 验证消息(自动检测版本)\n */\nexport function validateMessage(\n message: ServerToClientMessage,\n options: ValidationOptions = {}\n): ValidationResult {\n // 检测消息版本\n if ('createSurface' in message || 'updateComponents' in message || 'updateDataModel' in message) {\n return validateV09Message(message as ServerToClientMessageV09, options);\n }\n \n if ('beginRendering' in message || 'surfaceUpdate' in message || 'dataModelUpdate' in message) {\n return validateV08Message(message as ServerToClientMessageV08, options);\n }\n\n if ('deleteSurface' in message) {\n // deleteSurface 在两个版本中格式相同\n if (!message.deleteSurface.surfaceId) {\n return {\n valid: false,\n errors: [{\n code: 'MISSING_SURFACE_ID',\n message: 'deleteSurface.surfaceId is required',\n path: 'deleteSurface.surfaceId',\n }],\n warnings: [],\n };\n }\n return { valid: true, errors: [], warnings: [] };\n }\n\n return {\n valid: false,\n errors: [{\n code: 'UNKNOWN_MESSAGE_TYPE',\n message: 'Unknown message type',\n }],\n warnings: [],\n };\n}\n\n/**\n * 验证消息数组\n */\nexport function validateMessages(\n messages: ServerToClientMessage[],\n options: ValidationOptions = {}\n): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const result = validateMessage(messages[i], options);\n for (const error of result.errors) {\n errors.push({\n ...error,\n path: `messages[${i}].${error.path || ''}`,\n });\n }\n for (const warning of result.warnings) {\n warnings.push({\n ...warning,\n path: `messages[${i}].${warning.path || ''}`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n// ============================================================================\n// 内部辅助函数\n// ============================================================================\n\nfunction validateComponentsV09(\n components: ComponentInstance[],\n errors: ValidationError[],\n warnings: ValidationWarning[],\n options: ValidationOptions\n): void {\n const componentIds = new Set<string>();\n let hasRoot = false;\n\n for (let i = 0; i < components.length; i++) {\n const comp = components[i];\n const path = `updateComponents.components[${i}]`;\n\n // 验证 ID\n if (!comp.id) {\n errors.push({\n code: 'MISSING_COMPONENT_ID',\n message: 'Component id is required',\n path: `${path}.id`,\n });\n } else {\n if (componentIds.has(comp.id)) {\n errors.push({\n code: 'DUPLICATE_COMPONENT_ID',\n message: `Duplicate component id: ${comp.id}`,\n path: `${path}.id`,\n });\n }\n componentIds.add(comp.id);\n\n if (comp.id === 'root') {\n hasRoot = true;\n }\n }\n\n // 验证组件类型\n if (!comp.component) {\n errors.push({\n code: 'MISSING_COMPONENT_TYPE',\n message: 'Component type is required',\n path: `${path}.component`,\n });\n } else if (options.strict && options.allowedComponents) {\n if (!options.allowedComponents.includes(comp.component)) {\n warnings.push({\n code: 'UNKNOWN_COMPONENT_TYPE',\n message: `Unknown component type: ${comp.component}`,\n path: `${path}.component`,\n });\n }\n }\n }\n\n // 检查是否有 root 组件\n if (!hasRoot && options.strict) {\n warnings.push({\n code: 'MISSING_ROOT_COMPONENT',\n message: 'No component with id \"root\" found',\n path: 'updateComponents.components',\n });\n }\n}\n\nfunction validateComponentsV08(\n components: ComponentInstanceV08[],\n errors: ValidationError[],\n warnings: ValidationWarning[],\n options: ValidationOptions\n): void {\n const componentIds = new Set<string>();\n\n for (let i = 0; i < components.length; i++) {\n const comp = components[i];\n const path = `surfaceUpdate.components[${i}]`;\n\n // 验证 ID\n if (!comp.id) {\n errors.push({\n code: 'MISSING_COMPONENT_ID',\n message: 'Component id is required',\n path: `${path}.id`,\n });\n } else {\n if (componentIds.has(comp.id)) {\n errors.push({\n code: 'DUPLICATE_COMPONENT_ID',\n message: `Duplicate component id: ${comp.id}`,\n path: `${path}.id`,\n });\n }\n componentIds.add(comp.id);\n }\n\n // 验证组件类型\n if (!comp.component || typeof comp.component !== 'object') {\n errors.push({\n code: 'MISSING_COMPONENT',\n message: 'Component definition is required',\n path: `${path}.component`,\n });\n } else {\n const componentType = Object.keys(comp.component)[0];\n if (options.strict && !STANDARD_COMPONENT_TYPES.includes(componentType)) {\n warnings.push({\n code: 'UNKNOWN_COMPONENT_TYPE',\n message: `Unknown component type: ${componentType}`,\n path: `${path}.component`,\n });\n }\n }\n }\n}\n\n"]}
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@zhama/a2ui-core",
3
+ "version": "0.1.0",
4
+ "description": "A2UI Protocol Core Library - Framework-agnostic TypeScript types and builders for A2UI protocol",
5
+ "author": "Zhama",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "require": {
18
+ "types": "./dist/index.d.cts",
19
+ "default": "./dist/index.cjs"
20
+ }
21
+ },
22
+ "./types": {
23
+ "import": {
24
+ "types": "./dist/types/index.d.ts",
25
+ "default": "./dist/types/index.js"
26
+ },
27
+ "require": {
28
+ "types": "./dist/types/index.d.cts",
29
+ "default": "./dist/types/index.cjs"
30
+ }
31
+ },
32
+ "./builders": {
33
+ "import": {
34
+ "types": "./dist/builders/index.d.ts",
35
+ "default": "./dist/builders/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/builders/index.d.cts",
39
+ "default": "./dist/builders/index.cjs"
40
+ }
41
+ },
42
+ "./validators": {
43
+ "import": {
44
+ "types": "./dist/validators/index.d.ts",
45
+ "default": "./dist/validators/index.js"
46
+ },
47
+ "require": {
48
+ "types": "./dist/validators/index.d.cts",
49
+ "default": "./dist/validators/index.cjs"
50
+ }
51
+ }
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "README.md"
56
+ ],
57
+ "scripts": {
58
+ "build": "tsup",
59
+ "dev": "tsup --watch",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "lint": "eslint src",
63
+ "typecheck": "tsc --noEmit",
64
+ "prepublishOnly": "npm run build"
65
+ },
66
+ "devDependencies": {
67
+ "@types/node": "^20.10.0",
68
+ "eslint": "^9.0.0",
69
+ "tsup": "^8.0.0",
70
+ "typescript": "^5.3.0",
71
+ "vitest": "^1.0.0"
72
+ },
73
+ "keywords": [
74
+ "a2ui",
75
+ "agent-to-ui",
76
+ "protocol",
77
+ "typescript",
78
+ "ui-protocol",
79
+ "streaming-ui"
80
+ ],
81
+ "repository": {
82
+ "type": "git",
83
+ "url": "https://github.com/zhama/a2ui-core"
84
+ },
85
+ "engines": {
86
+ "node": ">=18.0.0"
87
+ }
88
+ }
89
+