@dudousxd/nestjs-agent-core 0.40.0 → 0.42.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 +7 -0
- package/dist/ag-ui/index.cjs +46 -10
- package/dist/ag-ui/index.cjs.map +1 -1
- package/dist/ag-ui/index.d.cts +9 -3
- package/dist/ag-ui/index.d.ts +9 -3
- package/dist/ag-ui/index.js +46 -10
- package/dist/ag-ui/index.js.map +1 -1
- package/dist/{catalog-CrzetM3_.d.cts → catalog-BKS3Yxo6.d.cts} +2 -0
- package/dist/{catalog-CrzetM3_.d.ts → catalog-BKS3Yxo6.d.ts} +2 -0
- package/dist/genui/builtins.cjs.map +1 -1
- package/dist/genui/builtins.d.cts +1 -1
- package/dist/genui/builtins.d.ts +1 -1
- package/dist/genui/builtins.js.map +1 -1
- package/dist/genui/index.cjs +660 -68
- package/dist/genui/index.cjs.map +1 -1
- package/dist/genui/index.d.cts +5 -5
- package/dist/genui/index.d.ts +5 -5
- package/dist/genui/index.js +654 -68
- package/dist/genui/index.js.map +1 -1
- package/dist/guardrails/index.cjs +3 -1
- package/dist/guardrails/index.cjs.map +1 -1
- package/dist/guardrails/index.d.cts +5 -4
- package/dist/guardrails/index.d.ts +5 -4
- package/dist/guardrails/index.js +3 -1
- package/dist/guardrails/index.js.map +1 -1
- package/dist/index.cjs +1164 -421
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -13
- package/dist/index.d.ts +124 -13
- package/dist/index.js +1156 -421
- package/dist/index.js.map +1 -1
- package/dist/{processors-BR3nICcp.d.ts → processors-BKILjME5.d.ts} +1 -1
- package/dist/{processors-B7nfbU6E.d.cts → processors-DpHBqRuE.d.cts} +1 -1
- package/dist/{stream-events-M0jc7lSW.d.cts → stream-events-C-pj3bVY.d.cts} +92 -4
- package/dist/{stream-events-DAmes2Of.d.ts → stream-events-D92SgfRk.d.ts} +92 -4
- package/package.json +1 -1
package/dist/genui/index.js
CHANGED
|
@@ -177,21 +177,21 @@ function check(schema, value, path, root, issues, depth) {
|
|
|
177
177
|
});
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
|
-
const
|
|
181
|
-
if (typeof
|
|
182
|
-
const target = resolveRef(root,
|
|
180
|
+
const s2 = schema;
|
|
181
|
+
if (typeof s2.$ref === "string") {
|
|
182
|
+
const target = resolveRef(root, s2.$ref);
|
|
183
183
|
if (target === void 0) {
|
|
184
184
|
issues.push({
|
|
185
185
|
path,
|
|
186
|
-
message: `references unknown schema ${
|
|
186
|
+
message: `references unknown schema ${s2.$ref}`
|
|
187
187
|
});
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
190
|
check(target, value, path, root, issues, depth + 1);
|
|
191
191
|
}
|
|
192
|
-
if (
|
|
193
|
-
const types = Array.isArray(
|
|
194
|
-
|
|
192
|
+
if (s2.type !== void 0) {
|
|
193
|
+
const types = Array.isArray(s2.type) ? s2.type : [
|
|
194
|
+
s2.type
|
|
195
195
|
];
|
|
196
196
|
if (!types.some((type) => matchesType(type, value))) {
|
|
197
197
|
issues.push({
|
|
@@ -201,76 +201,76 @@ function check(schema, value, path, root, issues, depth) {
|
|
|
201
201
|
return;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
|
-
if (Array.isArray(
|
|
204
|
+
if (Array.isArray(s2.enum) && !s2.enum.some((option) => deepEqual(option, value))) {
|
|
205
205
|
issues.push({
|
|
206
206
|
path,
|
|
207
|
-
message: `must be one of ${
|
|
207
|
+
message: `must be one of ${s2.enum.map((option) => JSON.stringify(option)).join(", ")}`
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
-
if ("const" in
|
|
210
|
+
if ("const" in s2 && !deepEqual(s2.const, value)) {
|
|
211
211
|
issues.push({
|
|
212
212
|
path,
|
|
213
|
-
message: `must be ${JSON.stringify(
|
|
213
|
+
message: `must be ${JSON.stringify(s2.const)}`
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
if (typeof value === "string") {
|
|
217
|
-
if (typeof
|
|
217
|
+
if (typeof s2.minLength === "number" && value.length < s2.minLength) {
|
|
218
218
|
issues.push({
|
|
219
219
|
path,
|
|
220
|
-
message: `must be at least ${
|
|
220
|
+
message: `must be at least ${s2.minLength} characters`
|
|
221
221
|
});
|
|
222
222
|
}
|
|
223
|
-
if (typeof
|
|
223
|
+
if (typeof s2.maxLength === "number" && value.length > s2.maxLength) {
|
|
224
224
|
issues.push({
|
|
225
225
|
path,
|
|
226
|
-
message: `must be at most ${
|
|
226
|
+
message: `must be at most ${s2.maxLength} characters`
|
|
227
227
|
});
|
|
228
228
|
}
|
|
229
|
-
if (typeof
|
|
229
|
+
if (typeof s2.pattern === "string") {
|
|
230
230
|
let pattern;
|
|
231
231
|
try {
|
|
232
|
-
pattern = new RegExp(
|
|
232
|
+
pattern = new RegExp(s2.pattern, "u");
|
|
233
233
|
} catch {
|
|
234
234
|
pattern = void 0;
|
|
235
235
|
}
|
|
236
236
|
if (pattern !== void 0 && !pattern.test(value)) {
|
|
237
237
|
issues.push({
|
|
238
238
|
path,
|
|
239
|
-
message: `must match ${
|
|
239
|
+
message: `must match ${s2.pattern}`
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
if (typeof value === "number") {
|
|
245
|
-
if (typeof
|
|
245
|
+
if (typeof s2.minimum === "number" && value < s2.minimum) {
|
|
246
246
|
issues.push({
|
|
247
247
|
path,
|
|
248
|
-
message: `must be >= ${
|
|
248
|
+
message: `must be >= ${s2.minimum}`
|
|
249
249
|
});
|
|
250
250
|
}
|
|
251
|
-
if (typeof
|
|
251
|
+
if (typeof s2.maximum === "number" && value > s2.maximum) {
|
|
252
252
|
issues.push({
|
|
253
253
|
path,
|
|
254
|
-
message: `must be <= ${
|
|
254
|
+
message: `must be <= ${s2.maximum}`
|
|
255
255
|
});
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
if (Array.isArray(value)) {
|
|
259
|
-
if (typeof
|
|
259
|
+
if (typeof s2.minItems === "number" && value.length < s2.minItems) {
|
|
260
260
|
issues.push({
|
|
261
261
|
path,
|
|
262
|
-
message: `must have at least ${
|
|
262
|
+
message: `must have at least ${s2.minItems} items`
|
|
263
263
|
});
|
|
264
264
|
}
|
|
265
|
-
if (typeof
|
|
265
|
+
if (typeof s2.maxItems === "number" && value.length > s2.maxItems) {
|
|
266
266
|
issues.push({
|
|
267
267
|
path,
|
|
268
|
-
message: `must have at most ${
|
|
268
|
+
message: `must have at most ${s2.maxItems} items`
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
|
-
if (
|
|
271
|
+
if (s2.items !== void 0 && !Array.isArray(s2.items)) {
|
|
272
272
|
value.forEach((item, index) => {
|
|
273
|
-
check(
|
|
273
|
+
check(s2.items, item, [
|
|
274
274
|
...path,
|
|
275
275
|
index
|
|
276
276
|
], root, issues, depth + 1);
|
|
@@ -279,9 +279,9 @@ function check(schema, value, path, root, issues, depth) {
|
|
|
279
279
|
}
|
|
280
280
|
if (matchesType("object", value)) {
|
|
281
281
|
const record2 = value;
|
|
282
|
-
const properties = typeof
|
|
283
|
-
if (Array.isArray(
|
|
284
|
-
for (const key of
|
|
282
|
+
const properties = typeof s2.properties === "object" && s2.properties !== null ? s2.properties : {};
|
|
283
|
+
if (Array.isArray(s2.required)) {
|
|
284
|
+
for (const key of s2.required) {
|
|
285
285
|
if (record2[key] === void 0) {
|
|
286
286
|
issues.push({
|
|
287
287
|
path: [
|
|
@@ -301,7 +301,7 @@ function check(schema, value, path, root, issues, depth) {
|
|
|
301
301
|
key
|
|
302
302
|
], root, issues, depth + 1);
|
|
303
303
|
}
|
|
304
|
-
} else if (
|
|
304
|
+
} else if (s2.additionalProperties === false) {
|
|
305
305
|
issues.push({
|
|
306
306
|
path: [
|
|
307
307
|
...path,
|
|
@@ -309,34 +309,34 @@ function check(schema, value, path, root, issues, depth) {
|
|
|
309
309
|
],
|
|
310
310
|
message: "is not a known property"
|
|
311
311
|
});
|
|
312
|
-
} else if (typeof
|
|
313
|
-
check(
|
|
312
|
+
} else if (typeof s2.additionalProperties === "object" && s2.additionalProperties !== null) {
|
|
313
|
+
check(s2.additionalProperties, entry, [
|
|
314
314
|
...path,
|
|
315
315
|
key
|
|
316
316
|
], root, issues, depth + 1);
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
if (Array.isArray(
|
|
321
|
-
for (const sub of
|
|
320
|
+
if (Array.isArray(s2.allOf)) {
|
|
321
|
+
for (const sub of s2.allOf) check(sub, value, path, root, issues, depth + 1);
|
|
322
322
|
}
|
|
323
|
-
if (Array.isArray(
|
|
324
|
-
const options = Array.isArray(
|
|
323
|
+
if (Array.isArray(s2.anyOf) || Array.isArray(s2.oneOf)) {
|
|
324
|
+
const options = Array.isArray(s2.anyOf) ? s2.anyOf : s2.oneOf;
|
|
325
325
|
const passing = options.filter((sub) => {
|
|
326
326
|
const nested = [];
|
|
327
327
|
check(sub, value, path, root, nested, depth + 1);
|
|
328
328
|
return nested.length === 0;
|
|
329
329
|
}).length;
|
|
330
|
-
if (Array.isArray(
|
|
330
|
+
if (Array.isArray(s2.anyOf) ? passing === 0 : passing !== 1) {
|
|
331
331
|
issues.push({
|
|
332
332
|
path,
|
|
333
|
-
message: Array.isArray(
|
|
333
|
+
message: Array.isArray(s2.anyOf) ? "does not match any allowed shape" : "must match exactly one allowed shape"
|
|
334
334
|
});
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
if (
|
|
337
|
+
if (s2.not !== void 0) {
|
|
338
338
|
const nested = [];
|
|
339
|
-
check(
|
|
339
|
+
check(s2.not, value, path, root, nested, depth + 1);
|
|
340
340
|
if (nested.length === 0) {
|
|
341
341
|
issues.push({
|
|
342
342
|
path,
|
|
@@ -393,7 +393,7 @@ function buildCatalog(byName, validator) {
|
|
|
393
393
|
]
|
|
394
394
|
};
|
|
395
395
|
}
|
|
396
|
-
const result = await validateProps(definition.props, props, validator);
|
|
396
|
+
const result = await validateProps(definition.outputProps ?? definition.props, props, validator);
|
|
397
397
|
return result;
|
|
398
398
|
},
|
|
399
399
|
validateSync(component, props) {
|
|
@@ -409,11 +409,11 @@ function buildCatalog(byName, validator) {
|
|
|
409
409
|
]
|
|
410
410
|
};
|
|
411
411
|
}
|
|
412
|
-
return validatePropsSync(definition.props, props, validator);
|
|
412
|
+
return validatePropsSync(definition.outputProps ?? definition.props, props, validator);
|
|
413
413
|
},
|
|
414
414
|
jsonSchemaFor(component) {
|
|
415
415
|
const definition = byName.get(component);
|
|
416
|
-
return definition === void 0 ? void 0 : toJsonSchema(definition.props);
|
|
416
|
+
return definition === void 0 ? void 0 : toJsonSchema(definition.outputProps ?? definition.props);
|
|
417
417
|
},
|
|
418
418
|
extend(more) {
|
|
419
419
|
const next = new Map(byName);
|
|
@@ -437,7 +437,7 @@ __name(toolNameFor, "toolNameFor");
|
|
|
437
437
|
|
|
438
438
|
// src/genui/tree.ts
|
|
439
439
|
var GENUI_TREE_COMPONENT = "genui:tree";
|
|
440
|
-
async function validateTree(catalog, tree, limits = {}) {
|
|
440
|
+
async function validateTree(catalog, tree, limits = {}, phase = "output") {
|
|
441
441
|
const maxDepth = limits.maxDepth ?? 12;
|
|
442
442
|
const maxNodes = limits.maxNodes ?? 200;
|
|
443
443
|
const issues = [];
|
|
@@ -489,7 +489,7 @@ async function validateTree(catalog, tree, limits = {}) {
|
|
|
489
489
|
});
|
|
490
490
|
return void 0;
|
|
491
491
|
}
|
|
492
|
-
const validated = await catalog.validate(element.type, element.props ?? {});
|
|
492
|
+
const validated = phase === "input" ? await validateProps(definition.props, element.props ?? {}, catalog.validator) : await catalog.validate(element.type, element.props ?? {});
|
|
493
493
|
let props = {};
|
|
494
494
|
if (!validated.ok) {
|
|
495
495
|
for (const issue of validated.issues) {
|
|
@@ -711,7 +711,7 @@ function catalogToModelText(catalog, options = {}) {
|
|
|
711
711
|
lines.push("Components you can show (one tool each):");
|
|
712
712
|
}
|
|
713
713
|
for (const component of catalog.modelComponents()) {
|
|
714
|
-
const schema =
|
|
714
|
+
const schema = toJsonSchema(component.props);
|
|
715
715
|
const head = mode === "per-component" ? `- ${component.name} (tool \`${toolNameFor(component.name, options.namePrefix)}\`)` : `- ${component.name}`;
|
|
716
716
|
lines.push(`${head}: ${component.description}`);
|
|
717
717
|
if (schema !== void 0) {
|
|
@@ -726,38 +726,38 @@ function catalogToModelText(catalog, options = {}) {
|
|
|
726
726
|
__name(catalogToModelText, "catalogToModelText");
|
|
727
727
|
function summarizeSchema(schema, root, depth) {
|
|
728
728
|
if (typeof schema !== "object" || schema === null) return "unknown";
|
|
729
|
-
const
|
|
729
|
+
const s2 = schema;
|
|
730
730
|
if (depth > 5) return "\u2026";
|
|
731
|
-
if (typeof
|
|
732
|
-
return
|
|
731
|
+
if (typeof s2.$ref === "string") {
|
|
732
|
+
return s2.$ref === "#" ? "Self" : s2.$ref.split("/").pop() ?? "unknown";
|
|
733
733
|
}
|
|
734
|
-
if (Array.isArray(
|
|
735
|
-
return
|
|
734
|
+
if (Array.isArray(s2.enum)) {
|
|
735
|
+
return s2.enum.map((option) => JSON.stringify(option)).join(" | ");
|
|
736
736
|
}
|
|
737
|
-
if ("const" in
|
|
738
|
-
const variants =
|
|
737
|
+
if ("const" in s2) return JSON.stringify(s2.const);
|
|
738
|
+
const variants = s2.anyOf ?? s2.oneOf;
|
|
739
739
|
if (Array.isArray(variants)) {
|
|
740
740
|
return variants.map((variant) => summarizeSchema(variant, root, depth + 1)).join(" | ");
|
|
741
741
|
}
|
|
742
|
-
const types = Array.isArray(
|
|
743
|
-
|
|
742
|
+
const types = Array.isArray(s2.type) ? s2.type : s2.type !== void 0 ? [
|
|
743
|
+
s2.type
|
|
744
744
|
] : [];
|
|
745
745
|
if (types.length > 1) {
|
|
746
746
|
return types.map((type2) => summarizeSchema({
|
|
747
|
-
...
|
|
747
|
+
...s2,
|
|
748
748
|
type: type2
|
|
749
749
|
}, root, depth + 1)).join(" | ");
|
|
750
750
|
}
|
|
751
751
|
const type = types[0];
|
|
752
752
|
if (type === "array") {
|
|
753
|
-
const item =
|
|
753
|
+
const item = s2.items === void 0 ? "unknown" : summarizeSchema(s2.items, root, depth + 1);
|
|
754
754
|
return /[|\s]/.test(item) && !item.startsWith("{") ? `(${item})[]` : `${item}[]`;
|
|
755
755
|
}
|
|
756
|
-
if (type === "object" || type === void 0 &&
|
|
757
|
-
const properties =
|
|
756
|
+
if (type === "object" || type === void 0 && s2.properties !== void 0) {
|
|
757
|
+
const properties = s2.properties ?? {};
|
|
758
758
|
const keys = Object.keys(properties);
|
|
759
759
|
if (keys.length === 0) return "object";
|
|
760
|
-
const required = new Set(Array.isArray(
|
|
760
|
+
const required = new Set(Array.isArray(s2.required) ? s2.required : []);
|
|
761
761
|
const fields = keys.map((key) => {
|
|
762
762
|
const field = properties[key];
|
|
763
763
|
const note = typeof field?.description === "string" && depth === 0 ? ` /* ${field.description} */` : "";
|
|
@@ -925,7 +925,7 @@ function componentTool(catalog, component, options) {
|
|
|
925
925
|
if (definition === void 0) {
|
|
926
926
|
throw new Error(`component "${component.name}" is not available here`);
|
|
927
927
|
}
|
|
928
|
-
const validated = await validateProps(definition.props, input, resolved.validator);
|
|
928
|
+
const validated = await validateProps(dynamic ? definition.props : definition.outputProps ?? definition.props, input, resolved.validator);
|
|
929
929
|
if (!validated.ok) {
|
|
930
930
|
throw new Error(`invalid ${component.name} props: ${formatIssues(validated.issues)}`);
|
|
931
931
|
}
|
|
@@ -981,7 +981,7 @@ function treeTool(catalog, options) {
|
|
|
981
981
|
const handler = {
|
|
982
982
|
async execute(input, ctx) {
|
|
983
983
|
const resolved = await catalogFor(catalog, options, scopeOf(ctx));
|
|
984
|
-
const result = await validateTree(resolved, input, options.treeLimits);
|
|
984
|
+
const result = await validateTree(resolved, input, options.treeLimits, dynamic ? "input" : "output");
|
|
985
985
|
if (!result.ok) {
|
|
986
986
|
throw new Error(`invalid UI tree: ${formatIssues(result.issues)}`);
|
|
987
987
|
}
|
|
@@ -1005,7 +1005,7 @@ function treeTool(catalog, options) {
|
|
|
1005
1005
|
kind: "read",
|
|
1006
1006
|
description: describeFor(catalog),
|
|
1007
1007
|
inputSchema: dynamic ? permissiveSchema(treeJsonSchema(catalog)) : asyncJsonStandardSchema(treeJsonSchema(catalog), async (value) => {
|
|
1008
|
-
const result = await validateTree(catalog, value, options.treeLimits);
|
|
1008
|
+
const result = await validateTree(catalog, value, options.treeLimits, "input");
|
|
1009
1009
|
return result.ok ? {
|
|
1010
1010
|
value: result.value
|
|
1011
1011
|
} : {
|
|
@@ -1040,7 +1040,7 @@ function showToolJsonSchema(catalog) {
|
|
|
1040
1040
|
};
|
|
1041
1041
|
}
|
|
1042
1042
|
__name(showToolJsonSchema, "showToolJsonSchema");
|
|
1043
|
-
async function validateShow(catalog, input) {
|
|
1043
|
+
async function validateShow(catalog, input, phase = "input") {
|
|
1044
1044
|
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
1045
1045
|
return {
|
|
1046
1046
|
ok: false,
|
|
@@ -1081,7 +1081,7 @@ async function validateShow(catalog, input) {
|
|
|
1081
1081
|
]
|
|
1082
1082
|
};
|
|
1083
1083
|
}
|
|
1084
|
-
const validated = await validateProps(definition.props, props ?? {}, catalog.validator);
|
|
1084
|
+
const validated = await validateProps(phase === "input" ? definition.props : definition.outputProps ?? definition.props, props ?? {}, catalog.validator);
|
|
1085
1085
|
if (!validated.ok) {
|
|
1086
1086
|
return {
|
|
1087
1087
|
ok: false,
|
|
@@ -1121,7 +1121,7 @@ function showTool(catalog, options) {
|
|
|
1121
1121
|
const handler = {
|
|
1122
1122
|
async execute(input, ctx) {
|
|
1123
1123
|
const resolved = await catalogFor(catalog, options, scopeOf(ctx));
|
|
1124
|
-
const result = await validateShow(resolved, input);
|
|
1124
|
+
const result = await validateShow(resolved, input, dynamic ? "input" : "output");
|
|
1125
1125
|
if (!result.ok) {
|
|
1126
1126
|
throw new Error(`invalid ${name} call: ${formatIssues(result.issues)}`);
|
|
1127
1127
|
}
|
|
@@ -1220,6 +1220,586 @@ function asyncJsonStandardSchema(schema, validate) {
|
|
|
1220
1220
|
};
|
|
1221
1221
|
}
|
|
1222
1222
|
__name(asyncJsonStandardSchema, "asyncJsonStandardSchema");
|
|
1223
|
+
|
|
1224
|
+
// src/genui/builtins.ts
|
|
1225
|
+
var str = /* @__PURE__ */ __name((description, extra = {}) => ({
|
|
1226
|
+
type: "string",
|
|
1227
|
+
...description !== void 0 ? {
|
|
1228
|
+
description
|
|
1229
|
+
} : {},
|
|
1230
|
+
...extra
|
|
1231
|
+
}), "str");
|
|
1232
|
+
var obj = /* @__PURE__ */ __name((properties, required = []) => ({
|
|
1233
|
+
type: "object",
|
|
1234
|
+
properties,
|
|
1235
|
+
required,
|
|
1236
|
+
additionalProperties: false
|
|
1237
|
+
}), "obj");
|
|
1238
|
+
var arr = /* @__PURE__ */ __name((items, extra = {}) => ({
|
|
1239
|
+
type: "array",
|
|
1240
|
+
items,
|
|
1241
|
+
...extra
|
|
1242
|
+
}), "arr");
|
|
1243
|
+
var cell = {
|
|
1244
|
+
type: [
|
|
1245
|
+
"string",
|
|
1246
|
+
"number",
|
|
1247
|
+
"boolean",
|
|
1248
|
+
"null"
|
|
1249
|
+
]
|
|
1250
|
+
};
|
|
1251
|
+
var row = {
|
|
1252
|
+
type: "object",
|
|
1253
|
+
additionalProperties: cell
|
|
1254
|
+
};
|
|
1255
|
+
var s = /* @__PURE__ */ __name((value) => value === null || value === void 0 ? "" : String(value), "s");
|
|
1256
|
+
var heading = /* @__PURE__ */ __name((props) => props.title ? `*${s(props.title)}*
|
|
1257
|
+
` : "", "heading");
|
|
1258
|
+
function textTable(columns, rows, max = 15) {
|
|
1259
|
+
const shown = rows.slice(0, max);
|
|
1260
|
+
const widths = columns.map((column) => Math.min(28, Math.max(column.label.length, ...shown.map((r) => s(r[column.key]).length))));
|
|
1261
|
+
const format = /* @__PURE__ */ __name((values) => values.map((value, index) => value.slice(0, widths[index]).padEnd(widths[index] ?? 0)).join(" "), "format");
|
|
1262
|
+
const lines = [
|
|
1263
|
+
format(columns.map((column) => column.label)),
|
|
1264
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
1265
|
+
...shown.map((r) => format(columns.map((column) => s(r[column.key]))))
|
|
1266
|
+
];
|
|
1267
|
+
if (rows.length > max) lines.push(`\u2026 ${rows.length - max} more rows`);
|
|
1268
|
+
return `\`\`\`
|
|
1269
|
+
${lines.join("\n")}
|
|
1270
|
+
\`\`\``;
|
|
1271
|
+
}
|
|
1272
|
+
__name(textTable, "textTable");
|
|
1273
|
+
function lineDiff(before, after) {
|
|
1274
|
+
const a = before.split("\n");
|
|
1275
|
+
const b = after.split("\n");
|
|
1276
|
+
if (a.length * b.length > 25e4) {
|
|
1277
|
+
return [
|
|
1278
|
+
...a.map((text) => ({
|
|
1279
|
+
op: "del",
|
|
1280
|
+
text
|
|
1281
|
+
})),
|
|
1282
|
+
...b.map((text) => ({
|
|
1283
|
+
op: "add",
|
|
1284
|
+
text
|
|
1285
|
+
}))
|
|
1286
|
+
];
|
|
1287
|
+
}
|
|
1288
|
+
const dp = Array.from({
|
|
1289
|
+
length: a.length + 1
|
|
1290
|
+
}, () => new Array(b.length + 1).fill(0));
|
|
1291
|
+
const at = /* @__PURE__ */ __name((i2, j2) => dp[i2]?.[j2] ?? 0, "at");
|
|
1292
|
+
for (let i2 = a.length - 1; i2 >= 0; i2--) {
|
|
1293
|
+
for (let j2 = b.length - 1; j2 >= 0; j2--) {
|
|
1294
|
+
dp[i2][j2] = a[i2] === b[j2] ? at(i2 + 1, j2 + 1) + 1 : Math.max(at(i2 + 1, j2), at(i2, j2 + 1));
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
const out = [];
|
|
1298
|
+
let i = 0;
|
|
1299
|
+
let j = 0;
|
|
1300
|
+
while (i < a.length && j < b.length) {
|
|
1301
|
+
if (a[i] === b[j]) {
|
|
1302
|
+
out.push({
|
|
1303
|
+
op: "same",
|
|
1304
|
+
text: a[i]
|
|
1305
|
+
});
|
|
1306
|
+
i++;
|
|
1307
|
+
j++;
|
|
1308
|
+
} else if (at(i + 1, j) >= at(i, j + 1)) {
|
|
1309
|
+
out.push({
|
|
1310
|
+
op: "del",
|
|
1311
|
+
text: a[i++]
|
|
1312
|
+
});
|
|
1313
|
+
} else {
|
|
1314
|
+
out.push({
|
|
1315
|
+
op: "add",
|
|
1316
|
+
text: b[j++]
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
while (i < a.length) out.push({
|
|
1321
|
+
op: "del",
|
|
1322
|
+
text: a[i++]
|
|
1323
|
+
});
|
|
1324
|
+
while (j < b.length) out.push({
|
|
1325
|
+
op: "add",
|
|
1326
|
+
text: b[j++]
|
|
1327
|
+
});
|
|
1328
|
+
return out;
|
|
1329
|
+
}
|
|
1330
|
+
__name(lineDiff, "lineDiff");
|
|
1331
|
+
function bar(value, max, width = 20) {
|
|
1332
|
+
const n = max > 0 ? Math.round(Math.abs(value) / max * width) : 0;
|
|
1333
|
+
return "\u2588".repeat(n) || "\u258F";
|
|
1334
|
+
}
|
|
1335
|
+
__name(bar, "bar");
|
|
1336
|
+
var DataTable = defineComponent({
|
|
1337
|
+
name: "DataTable",
|
|
1338
|
+
title: "Data table",
|
|
1339
|
+
description: "Tabular data (records with the same fields) as a sortable table. Prefer it over markdown tables for more than 3 rows.",
|
|
1340
|
+
props: obj({
|
|
1341
|
+
title: str("Short caption"),
|
|
1342
|
+
columns: arr(obj({
|
|
1343
|
+
key: str("Field name in each row"),
|
|
1344
|
+
label: str("Column header"),
|
|
1345
|
+
align: str(void 0, {
|
|
1346
|
+
enum: [
|
|
1347
|
+
"left",
|
|
1348
|
+
"right",
|
|
1349
|
+
"center"
|
|
1350
|
+
]
|
|
1351
|
+
}),
|
|
1352
|
+
format: str("How to format values", {
|
|
1353
|
+
enum: [
|
|
1354
|
+
"text",
|
|
1355
|
+
"number",
|
|
1356
|
+
"currency",
|
|
1357
|
+
"percent",
|
|
1358
|
+
"date",
|
|
1359
|
+
"link"
|
|
1360
|
+
]
|
|
1361
|
+
})
|
|
1362
|
+
}, [
|
|
1363
|
+
"key",
|
|
1364
|
+
"label"
|
|
1365
|
+
]), {
|
|
1366
|
+
minItems: 1,
|
|
1367
|
+
maxItems: 12
|
|
1368
|
+
}),
|
|
1369
|
+
rows: arr(row, {
|
|
1370
|
+
maxItems: 500
|
|
1371
|
+
})
|
|
1372
|
+
}, [
|
|
1373
|
+
"columns",
|
|
1374
|
+
"rows"
|
|
1375
|
+
]),
|
|
1376
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${textTable(props.columns ?? [], props.rows ?? [])}`, "fallbackText")
|
|
1377
|
+
});
|
|
1378
|
+
var Chart = defineComponent({
|
|
1379
|
+
name: "Chart",
|
|
1380
|
+
title: "Chart",
|
|
1381
|
+
description: "`bar` to compare categories, `line` for a trend over time. `data` is a list of points; `xKey` names the category/time field and each series names a numeric field.",
|
|
1382
|
+
props: obj({
|
|
1383
|
+
type: str("Chart type", {
|
|
1384
|
+
enum: [
|
|
1385
|
+
"bar",
|
|
1386
|
+
"line"
|
|
1387
|
+
]
|
|
1388
|
+
}),
|
|
1389
|
+
title: str(),
|
|
1390
|
+
xKey: str("Field of each point used for the x axis"),
|
|
1391
|
+
series: arr(obj({
|
|
1392
|
+
key: str("Numeric field"),
|
|
1393
|
+
label: str()
|
|
1394
|
+
}, [
|
|
1395
|
+
"key"
|
|
1396
|
+
]), {
|
|
1397
|
+
minItems: 1,
|
|
1398
|
+
maxItems: 6
|
|
1399
|
+
}),
|
|
1400
|
+
data: arr(row, {
|
|
1401
|
+
minItems: 1,
|
|
1402
|
+
maxItems: 200
|
|
1403
|
+
}),
|
|
1404
|
+
unit: str("Unit shown after values, e.g. `KB` or `%`")
|
|
1405
|
+
}, [
|
|
1406
|
+
"type",
|
|
1407
|
+
"xKey",
|
|
1408
|
+
"series",
|
|
1409
|
+
"data"
|
|
1410
|
+
]),
|
|
1411
|
+
fallbackText: /* @__PURE__ */ __name((props) => {
|
|
1412
|
+
const series = props.series ?? [];
|
|
1413
|
+
const data = props.data ?? [];
|
|
1414
|
+
const first = series[0]?.key ?? "";
|
|
1415
|
+
const max = Math.max(0, ...data.map((point) => Math.abs(Number(point[first]) || 0)));
|
|
1416
|
+
const unit = props.unit ? ` ${s(props.unit)}` : "";
|
|
1417
|
+
const lines = data.slice(0, 20).map((point) => `${s(point[props.xKey]).slice(0, 18).padEnd(18)} ${bar(Number(point[first]) || 0, max)} ${s(point[first])}${unit}`);
|
|
1418
|
+
return `${heading(props)}\`\`\`
|
|
1419
|
+
${lines.join("\n")}
|
|
1420
|
+
\`\`\``;
|
|
1421
|
+
}, "fallbackText")
|
|
1422
|
+
});
|
|
1423
|
+
var KpiCards = defineComponent({
|
|
1424
|
+
name: "KpiCards",
|
|
1425
|
+
title: "KPI cards",
|
|
1426
|
+
description: "A few key numbers (metrics, totals, counts) as cards.",
|
|
1427
|
+
props: obj({
|
|
1428
|
+
title: str(),
|
|
1429
|
+
items: arr(obj({
|
|
1430
|
+
label: str(),
|
|
1431
|
+
value: {
|
|
1432
|
+
type: [
|
|
1433
|
+
"string",
|
|
1434
|
+
"number"
|
|
1435
|
+
]
|
|
1436
|
+
},
|
|
1437
|
+
delta: str("Change, e.g. `+12%`"),
|
|
1438
|
+
trend: str(void 0, {
|
|
1439
|
+
enum: [
|
|
1440
|
+
"up",
|
|
1441
|
+
"down",
|
|
1442
|
+
"flat"
|
|
1443
|
+
]
|
|
1444
|
+
}),
|
|
1445
|
+
hint: str()
|
|
1446
|
+
}, [
|
|
1447
|
+
"label",
|
|
1448
|
+
"value"
|
|
1449
|
+
]), {
|
|
1450
|
+
minItems: 1,
|
|
1451
|
+
maxItems: 8
|
|
1452
|
+
})
|
|
1453
|
+
}, [
|
|
1454
|
+
"items"
|
|
1455
|
+
]),
|
|
1456
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `\u2022 *${s(item.label)}:* ${s(item.value)}${item.delta ? ` (${s(item.delta)})` : ""}`).join("\n")}`, "fallbackText")
|
|
1457
|
+
});
|
|
1458
|
+
var SourceCards = defineComponent({
|
|
1459
|
+
name: "SourceCards",
|
|
1460
|
+
title: "Sources",
|
|
1461
|
+
description: "The documents, pages or links an answer is based on, as cards.",
|
|
1462
|
+
props: obj({
|
|
1463
|
+
title: str(),
|
|
1464
|
+
items: arr(obj({
|
|
1465
|
+
title: str(),
|
|
1466
|
+
url: str(),
|
|
1467
|
+
snippet: str(),
|
|
1468
|
+
source: str("e.g. Wiki, GitHub")
|
|
1469
|
+
}, [
|
|
1470
|
+
"title"
|
|
1471
|
+
]), {
|
|
1472
|
+
minItems: 1,
|
|
1473
|
+
maxItems: 12
|
|
1474
|
+
})
|
|
1475
|
+
}, [
|
|
1476
|
+
"items"
|
|
1477
|
+
]),
|
|
1478
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `\u2022 ${item.url ? `<${s(item.url)}|${s(item.title)}>` : s(item.title)}${item.source ? ` \u2014 ${s(item.source)}` : ""}`).join("\n")}`, "fallbackText")
|
|
1479
|
+
});
|
|
1480
|
+
var Checklist = defineComponent({
|
|
1481
|
+
name: "Checklist",
|
|
1482
|
+
title: "Checklist",
|
|
1483
|
+
description: "Steps or a to-do list with done/not-done state.",
|
|
1484
|
+
props: obj({
|
|
1485
|
+
title: str(),
|
|
1486
|
+
items: arr(obj({
|
|
1487
|
+
label: str(),
|
|
1488
|
+
done: {
|
|
1489
|
+
type: "boolean"
|
|
1490
|
+
},
|
|
1491
|
+
note: str()
|
|
1492
|
+
}, [
|
|
1493
|
+
"label"
|
|
1494
|
+
]), {
|
|
1495
|
+
minItems: 1,
|
|
1496
|
+
maxItems: 50
|
|
1497
|
+
})
|
|
1498
|
+
}, [
|
|
1499
|
+
"items"
|
|
1500
|
+
]),
|
|
1501
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.items ?? []).map((item) => `${item.done ? "\u2611" : "\u2610"} ${s(item.label)}${item.note ? ` \u2014 _${s(item.note)}_` : ""}`).join("\n")}`, "fallbackText")
|
|
1502
|
+
});
|
|
1503
|
+
var Timeline = defineComponent({
|
|
1504
|
+
name: "Timeline",
|
|
1505
|
+
title: "Timeline",
|
|
1506
|
+
description: "Events in chronological order (the history of a project, an incident, a deal).",
|
|
1507
|
+
props: obj({
|
|
1508
|
+
title: str(),
|
|
1509
|
+
events: arr(obj({
|
|
1510
|
+
date: str(),
|
|
1511
|
+
title: str(),
|
|
1512
|
+
description: str()
|
|
1513
|
+
}, [
|
|
1514
|
+
"title"
|
|
1515
|
+
]), {
|
|
1516
|
+
minItems: 1,
|
|
1517
|
+
maxItems: 50
|
|
1518
|
+
})
|
|
1519
|
+
}, [
|
|
1520
|
+
"events"
|
|
1521
|
+
]),
|
|
1522
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}${(props.events ?? []).map((event) => `\u2022 ${event.date ? `*${s(event.date)}* ` : ""}${s(event.title)}${event.description ? ` \u2014 ${s(event.description)}` : ""}`).join("\n")}`, "fallbackText")
|
|
1523
|
+
});
|
|
1524
|
+
var CodeBlock = defineComponent({
|
|
1525
|
+
name: "CodeBlock",
|
|
1526
|
+
title: "Code",
|
|
1527
|
+
description: "A code snippet or file excerpt with syntax highlighting.",
|
|
1528
|
+
props: obj({
|
|
1529
|
+
title: str(),
|
|
1530
|
+
language: str(),
|
|
1531
|
+
code: str()
|
|
1532
|
+
}, [
|
|
1533
|
+
"code"
|
|
1534
|
+
]),
|
|
1535
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}\`\`\`
|
|
1536
|
+
${s(props.code)}
|
|
1537
|
+
\`\`\``, "fallbackText")
|
|
1538
|
+
});
|
|
1539
|
+
var Diff = defineComponent({
|
|
1540
|
+
name: "Diff",
|
|
1541
|
+
title: "Diff",
|
|
1542
|
+
description: "A before/after change to a text or code file, as a line diff.",
|
|
1543
|
+
props: obj({
|
|
1544
|
+
title: str(),
|
|
1545
|
+
language: str(),
|
|
1546
|
+
before: str(),
|
|
1547
|
+
after: str()
|
|
1548
|
+
}, [
|
|
1549
|
+
"before",
|
|
1550
|
+
"after"
|
|
1551
|
+
]),
|
|
1552
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${heading(props)}\`\`\`
|
|
1553
|
+
${lineDiff(s(props.before), s(props.after)).map((line) => `${line.op === "add" ? "+" : line.op === "del" ? "-" : " "} ${line.text}`).join("\n")}
|
|
1554
|
+
\`\`\``, "fallbackText")
|
|
1555
|
+
});
|
|
1556
|
+
var Callout = defineComponent({
|
|
1557
|
+
name: "Callout",
|
|
1558
|
+
title: "Callout",
|
|
1559
|
+
description: "A short note, warning or success message, emphasized.",
|
|
1560
|
+
props: obj({
|
|
1561
|
+
tone: str(void 0, {
|
|
1562
|
+
enum: [
|
|
1563
|
+
"info",
|
|
1564
|
+
"success",
|
|
1565
|
+
"warning",
|
|
1566
|
+
"danger"
|
|
1567
|
+
]
|
|
1568
|
+
}),
|
|
1569
|
+
title: str(),
|
|
1570
|
+
text: str()
|
|
1571
|
+
}, [
|
|
1572
|
+
"text"
|
|
1573
|
+
]),
|
|
1574
|
+
fallbackText: /* @__PURE__ */ __name((props) => `${props.tone === "warning" || props.tone === "danger" ? ":warning: " : ":information_source: "}${heading(props)}${s(props.text)}`, "fallbackText")
|
|
1575
|
+
});
|
|
1576
|
+
var Stack = defineComponent({
|
|
1577
|
+
name: "Stack",
|
|
1578
|
+
title: "Stack",
|
|
1579
|
+
description: "Lays its children out vertically (or horizontally with direction=row).",
|
|
1580
|
+
props: obj({
|
|
1581
|
+
direction: str(void 0, {
|
|
1582
|
+
enum: [
|
|
1583
|
+
"column",
|
|
1584
|
+
"row"
|
|
1585
|
+
]
|
|
1586
|
+
}),
|
|
1587
|
+
gap: {
|
|
1588
|
+
type: "number"
|
|
1589
|
+
}
|
|
1590
|
+
}),
|
|
1591
|
+
children: true,
|
|
1592
|
+
fallbackText: /* @__PURE__ */ __name(() => "", "fallbackText")
|
|
1593
|
+
});
|
|
1594
|
+
var Card = defineComponent({
|
|
1595
|
+
name: "Card",
|
|
1596
|
+
title: "Card",
|
|
1597
|
+
description: "A box with an optional title around its children.",
|
|
1598
|
+
props: obj({
|
|
1599
|
+
title: str(),
|
|
1600
|
+
subtitle: str()
|
|
1601
|
+
}),
|
|
1602
|
+
children: true,
|
|
1603
|
+
fallbackText: /* @__PURE__ */ __name((props) => props.title ? `*${s(props.title)}*${props.subtitle ? ` \u2014 ${s(props.subtitle)}` : ""}` : "", "fallbackText")
|
|
1604
|
+
});
|
|
1605
|
+
var Heading = defineComponent({
|
|
1606
|
+
name: "Heading",
|
|
1607
|
+
title: "Heading",
|
|
1608
|
+
description: "A heading.",
|
|
1609
|
+
props: obj({
|
|
1610
|
+
text: str()
|
|
1611
|
+
}, [
|
|
1612
|
+
"text"
|
|
1613
|
+
]),
|
|
1614
|
+
fallbackText: /* @__PURE__ */ __name((props) => `*${s(props.text)}*`, "fallbackText")
|
|
1615
|
+
});
|
|
1616
|
+
var Text = defineComponent({
|
|
1617
|
+
name: "Text",
|
|
1618
|
+
title: "Text",
|
|
1619
|
+
description: "A paragraph of plain text (no markdown).",
|
|
1620
|
+
props: obj({
|
|
1621
|
+
text: str(),
|
|
1622
|
+
muted: {
|
|
1623
|
+
type: "boolean"
|
|
1624
|
+
}
|
|
1625
|
+
}, [
|
|
1626
|
+
"text"
|
|
1627
|
+
]),
|
|
1628
|
+
fallbackText: /* @__PURE__ */ __name((props) => s(props.text), "fallbackText")
|
|
1629
|
+
});
|
|
1630
|
+
var Badge = defineComponent({
|
|
1631
|
+
name: "Badge",
|
|
1632
|
+
title: "Badge",
|
|
1633
|
+
description: "A small label.",
|
|
1634
|
+
props: obj({
|
|
1635
|
+
text: str(),
|
|
1636
|
+
tone: str(void 0, {
|
|
1637
|
+
enum: [
|
|
1638
|
+
"neutral",
|
|
1639
|
+
"brand",
|
|
1640
|
+
"success",
|
|
1641
|
+
"warning",
|
|
1642
|
+
"danger"
|
|
1643
|
+
]
|
|
1644
|
+
})
|
|
1645
|
+
}, [
|
|
1646
|
+
"text"
|
|
1647
|
+
]),
|
|
1648
|
+
fallbackText: /* @__PURE__ */ __name((props) => `[${s(props.text)}]`, "fallbackText")
|
|
1649
|
+
});
|
|
1650
|
+
var Link = defineComponent({
|
|
1651
|
+
name: "Link",
|
|
1652
|
+
title: "Link",
|
|
1653
|
+
description: "A link to an http(s) URL.",
|
|
1654
|
+
props: obj({
|
|
1655
|
+
text: str(),
|
|
1656
|
+
url: str(void 0, {
|
|
1657
|
+
pattern: "^https?://"
|
|
1658
|
+
})
|
|
1659
|
+
}, [
|
|
1660
|
+
"text",
|
|
1661
|
+
"url"
|
|
1662
|
+
]),
|
|
1663
|
+
fallbackText: /* @__PURE__ */ __name((props) => `<${s(props.url)}|${s(props.text || props.url)}>`, "fallbackText")
|
|
1664
|
+
});
|
|
1665
|
+
var Image = defineComponent({
|
|
1666
|
+
name: "Image",
|
|
1667
|
+
title: "Image",
|
|
1668
|
+
description: "An image from an https URL.",
|
|
1669
|
+
props: obj({
|
|
1670
|
+
url: str(void 0, {
|
|
1671
|
+
pattern: "^https://"
|
|
1672
|
+
}),
|
|
1673
|
+
alt: str()
|
|
1674
|
+
}, [
|
|
1675
|
+
"url"
|
|
1676
|
+
]),
|
|
1677
|
+
fallbackText: /* @__PURE__ */ __name((props) => s(props.url), "fallbackText")
|
|
1678
|
+
});
|
|
1679
|
+
|
|
1680
|
+
// src/genui/registry.ts
|
|
1681
|
+
function snapshotComponentPresentation(value) {
|
|
1682
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1683
|
+
const check2 = /* @__PURE__ */ __name((entry) => {
|
|
1684
|
+
if (entry === null || typeof entry === "string" || typeof entry === "boolean") return;
|
|
1685
|
+
if (typeof entry === "number" && Number.isFinite(entry)) return;
|
|
1686
|
+
if (typeof entry !== "object" || entry === null) throw new TypeError("genui: presentation must contain only JSON values");
|
|
1687
|
+
if (seen.has(entry)) throw new TypeError("genui: presentation must contain acyclic JSON values");
|
|
1688
|
+
if (!Array.isArray(entry) && Object.getPrototypeOf(entry) !== Object.prototype && Object.getPrototypeOf(entry) !== null) throw new TypeError("genui: presentation must contain plain JSON objects");
|
|
1689
|
+
seen.add(entry);
|
|
1690
|
+
for (const item of Object.values(entry)) check2(item);
|
|
1691
|
+
seen.delete(entry);
|
|
1692
|
+
}, "check");
|
|
1693
|
+
check2(value);
|
|
1694
|
+
return JSON.parse(JSON.stringify(value));
|
|
1695
|
+
}
|
|
1696
|
+
__name(snapshotComponentPresentation, "snapshotComponentPresentation");
|
|
1697
|
+
function createComponent(definition, options = {}) {
|
|
1698
|
+
defineComponent(definition);
|
|
1699
|
+
const catalog = defineCatalog([
|
|
1700
|
+
definition
|
|
1701
|
+
], options);
|
|
1702
|
+
const factory = /* @__PURE__ */ __name(async (props) => {
|
|
1703
|
+
const result = await validateProps(definition.props, props, catalog.validator);
|
|
1704
|
+
if (!result.ok) throw new Error(`genui: invalid ${definition.name} props: ${formatIssues(result.issues)}`);
|
|
1705
|
+
const normalized = snapshotComponentPresentation(result.value);
|
|
1706
|
+
if (typeof normalized !== "object" || normalized === null || Array.isArray(normalized)) throw new TypeError("genui: component props must be a JSON object");
|
|
1707
|
+
const portable = await catalog.validate(definition.name, normalized);
|
|
1708
|
+
if (!portable.ok || canonicalJson(snapshotComponentPresentation(portable.value)) !== canonicalJson(normalized)) {
|
|
1709
|
+
throw new Error(`genui: ${definition.name} requires outputProps accepting stable normalized JSON props`);
|
|
1710
|
+
}
|
|
1711
|
+
return {
|
|
1712
|
+
component: definition.name,
|
|
1713
|
+
props: normalized,
|
|
1714
|
+
version: definition.version ?? 1,
|
|
1715
|
+
fallbackText: componentToText(catalog, definition.name, normalized)
|
|
1716
|
+
};
|
|
1717
|
+
}, "factory");
|
|
1718
|
+
return Object.assign(factory, {
|
|
1719
|
+
definition
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
__name(createComponent, "createComponent");
|
|
1723
|
+
function createComponentRegistry(options = {}) {
|
|
1724
|
+
let catalog = defineCatalog([], options);
|
|
1725
|
+
const channels = /* @__PURE__ */ new Map();
|
|
1726
|
+
const registry = {
|
|
1727
|
+
get catalog() {
|
|
1728
|
+
return catalog;
|
|
1729
|
+
},
|
|
1730
|
+
get manifest() {
|
|
1731
|
+
return catalog.components.map((definition) => {
|
|
1732
|
+
const props = catalog.jsonSchemaFor(definition.name);
|
|
1733
|
+
return {
|
|
1734
|
+
name: definition.name,
|
|
1735
|
+
title: definition.title,
|
|
1736
|
+
description: definition.description,
|
|
1737
|
+
version: definition.version ?? 1,
|
|
1738
|
+
...props === void 0 ? {} : {
|
|
1739
|
+
props: snapshotComponentPresentation(props)
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
});
|
|
1743
|
+
},
|
|
1744
|
+
register(definition, renderers) {
|
|
1745
|
+
if (catalog.has(definition.name)) throw new Error(`genui: component "${definition.name}" is already registered`);
|
|
1746
|
+
catalog = catalog.extend([
|
|
1747
|
+
definition
|
|
1748
|
+
]);
|
|
1749
|
+
channels.set(definition.name, {
|
|
1750
|
+
...renderers
|
|
1751
|
+
});
|
|
1752
|
+
return this;
|
|
1753
|
+
},
|
|
1754
|
+
async prepare(presentation) {
|
|
1755
|
+
const definition = catalog.get(presentation.component);
|
|
1756
|
+
if (definition === void 0) throw new Error(`genui: unknown component "${presentation.component}"`);
|
|
1757
|
+
if (presentation.version !== (definition.version ?? 1)) throw new Error(`genui: component "${presentation.component}" version mismatch`);
|
|
1758
|
+
const validated = await catalog.validate(presentation.component, presentation.props);
|
|
1759
|
+
if (!validated.ok) throw new Error(`genui: invalid ${presentation.component} props: ${formatIssues(validated.issues)}`);
|
|
1760
|
+
const props = snapshotComponentPresentation(validated.value);
|
|
1761
|
+
if (typeof props !== "object" || props === null || Array.isArray(props)) throw new TypeError("genui: component props must be a JSON object");
|
|
1762
|
+
return {
|
|
1763
|
+
component: definition.name,
|
|
1764
|
+
props,
|
|
1765
|
+
version: definition.version ?? 1,
|
|
1766
|
+
fallbackText: componentToText(catalog, definition.name, props)
|
|
1767
|
+
};
|
|
1768
|
+
},
|
|
1769
|
+
async render(presentation, channel, context) {
|
|
1770
|
+
const prepared = await this.prepare(presentation);
|
|
1771
|
+
const mapping = channels.get(prepared.component);
|
|
1772
|
+
const renderer = mapping === void 0 ? void 0 : Object.hasOwn(mapping, channel) ? mapping[channel] : Object.hasOwn(mapping, "text") ? mapping.text : void 0;
|
|
1773
|
+
return renderer === void 0 ? prepared.fallbackText : renderer(prepared.props, context);
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
return registry;
|
|
1777
|
+
}
|
|
1778
|
+
__name(createComponentRegistry, "createComponentRegistry");
|
|
1779
|
+
var table = createComponent(DataTable);
|
|
1780
|
+
var chart = createComponent(Chart);
|
|
1781
|
+
function validatePresentationBatch(presentations) {
|
|
1782
|
+
const batch = Array.isArray(presentations) ? presentations : [
|
|
1783
|
+
presentations
|
|
1784
|
+
];
|
|
1785
|
+
return batch.map((item) => {
|
|
1786
|
+
const presentation = snapshotComponentPresentation(item);
|
|
1787
|
+
if (typeof presentation !== "object" || presentation === null || typeof presentation.component !== "string" || !/^[A-Za-z][A-Za-z0-9]{0,63}$/.test(presentation.component) || !Number.isSafeInteger(presentation.version) || presentation.version <= 0 || typeof presentation.fallbackText !== "string" || typeof presentation.props !== "object" || presentation.props === null || Array.isArray(presentation.props)) {
|
|
1788
|
+
throw new TypeError("genui: invalid component presentation");
|
|
1789
|
+
}
|
|
1790
|
+
return presentation;
|
|
1791
|
+
});
|
|
1792
|
+
}
|
|
1793
|
+
__name(validatePresentationBatch, "validatePresentationBatch");
|
|
1794
|
+
function canonicalJson(value) {
|
|
1795
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
1796
|
+
if (typeof value === "object" && value !== null) {
|
|
1797
|
+
const record2 = value;
|
|
1798
|
+
return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record2[key])}`).join(",")}}`;
|
|
1799
|
+
}
|
|
1800
|
+
return JSON.stringify(value);
|
|
1801
|
+
}
|
|
1802
|
+
__name(canonicalJson, "canonicalJson");
|
|
1223
1803
|
export {
|
|
1224
1804
|
COMPONENT_NAME,
|
|
1225
1805
|
GENUI_SHOW_TOOL,
|
|
@@ -1227,7 +1807,10 @@ export {
|
|
|
1227
1807
|
ajvValidator,
|
|
1228
1808
|
builtinJsonSchemaValidator,
|
|
1229
1809
|
catalogToModelText,
|
|
1810
|
+
chart,
|
|
1230
1811
|
componentToText,
|
|
1812
|
+
createComponent,
|
|
1813
|
+
createComponentRegistry,
|
|
1231
1814
|
defineCatalog,
|
|
1232
1815
|
defineComponent,
|
|
1233
1816
|
fillTemplate,
|
|
@@ -1239,13 +1822,16 @@ export {
|
|
|
1239
1822
|
negotiateCatalog,
|
|
1240
1823
|
prepareUiEmission,
|
|
1241
1824
|
showToolJsonSchema,
|
|
1825
|
+
snapshotComponentPresentation,
|
|
1242
1826
|
summarizeSchema,
|
|
1827
|
+
table,
|
|
1243
1828
|
toJsonSchema,
|
|
1244
1829
|
toSnakeCase,
|
|
1245
1830
|
toolNameFor,
|
|
1246
1831
|
treeJsonSchema,
|
|
1247
1832
|
treeToFlatSpec,
|
|
1248
1833
|
treeToText,
|
|
1834
|
+
validatePresentationBatch,
|
|
1249
1835
|
validateProps,
|
|
1250
1836
|
validatePropsSync,
|
|
1251
1837
|
validateTree,
|